Skip to content

Make the five docs/adr ADRs conform to the adr genre and route them to the structured-madr gate - #208

Merged
zircote merged 3 commits into
mainfrom
fix/203-adr-genre-conformance
Aug 4, 2026
Merged

zircote merged 3 commits into
mainfrom
fix/203-adr-genre-conformance

Conversation

@zircote

@zircote zircote commented Aug 4, 2026

Copy link
Copy Markdown
Contributor

Closes #203

What

The repo's own five ADRs (docs/adr/00010005) carried type: semantic and no status:, so the ADR carve-out never fired on them: audit-deterministic.mjs recorded all five as mutability: mutable and the documented routing of type: adr documents to the structured-madr oracle never applied — the exact defect class the immutable-ADR policy exists to prevent, on the plugin's own decision records.

This takes the genre-conformance branch of the issue's scope decision (per accepted ADR-0001, whose own Decision states "Every ADR carries type: adr and conceptType: semantic in its frontmatter"):

  • docs/adr/00010005: frontmatter rewritten to the adr genre's structured-MADR form — type: adr, conceptType: semantic, lifecycle status: accepted, category, created/updated dates, author, project — keeping the MIF L3 fields the smadr schema carries (temporal, provenance, citations, relationships, summary) and moving non-schema keys (aliases, ontology, the old extensions block) to x- extension keys. Bodies are untouched; the section skeletons already conformed.
  • scripts/lib/corpus.mjs: content-based ADR carve-out. listL3Docs() now excludes type: adr documents (same shared predicate as the guard and the audit runner, via mif-genre-signal.mjs); a new listAdrDocs() returns them. Fail-closed checks (missing tree, empty tree) still run on the pre-filter list, and the carve-out is content-based, so a non-adr doc dropped into docs/adr stays in the mif-validate corpus.
  • .github/workflows/ci.yml: the adr-smadr job now validates docs/adr with the structured-madr Action in both smadr (strict) and mif (level 3) modes, so the five ADRs stay gated after leaving the mif-validate path; the stale "project ADRs are L3 MIF, not structured-MADR" comment is corrected.
  • tests/corpus.test.mjs: regression tests pinning that every docs/adr document is the type: adr carve-out with a lifecycle status (fails on the pre-fix tree), that listL3Docs() excludes exactly the ADRs (listAdrDocs() returns them), and that a non-adr doc under an L3 tree stays gated.

Verification

  • Issue repro now yields genre: adr | mutability: immutable | oracle: structured-madr | status: accepted for all five files in corpus-map.json.
  • structured-madr Action validators run locally against docs/adr: smadr strict mode 5/5 passed, 0 warnings; mif mode level 3 5/5 passed.
  • Full local gate sequence green: validate-plugin, hydrate-schema, mif-validate over the whole gated corpus at L1/L2/L3, check-exemplars, planner-check, check-doc-links, provenance-corpus-check idempotency, test:hook (272 pass, includes the new regression tests), lint:md, actionlint, and the site/ Astro build (75 pages).

…hem to the structured-madr gate

The repo's own ADRs (docs/adr/0001-0005) carried type: semantic and no
status:, so the ADR carve-out never fired: audit-v2 recorded them as
mutable and the structured-madr oracle routing never applied (#203).

- Rewrite the five ADR frontmatters to the genre's structured-MADR form
  (type: adr, conceptType: semantic, lifecycle status, category,
  created/updated dates, author, project), keeping the MIF L3 fields the
  smadr schema carries (temporal, provenance, citations, relationships,
  summary) and moving non-schema keys to x- extensions. Bodies untouched.
- corpus.mjs: content-based ADR carve-out — listL3Docs excludes
  type: adr docs (predicate shared via mif-genre-signal.mjs), new
  listAdrDocs returns them; fail-closed checks still run pre-filter.
- ci.yml: adr-smadr job now validates docs/adr in both smadr (strict)
  and mif (level 3) modes; stale corpus comment corrected.
- tests: regression tests pinning that every docs/adr doc is the
  carve-out with a lifecycle status, that listL3Docs excludes exactly
  the ADRs, and that a non-adr doc under docs/adr stays gated.
@zircote

zircote commented Aug 4, 2026

Copy link
Copy Markdown
Contributor Author

In review.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR makes the repository’s own ADR documents (docs/adr/00010005) conform to the adr genre (Structured MADR frontmatter with type: adr and lifecycle status) and updates the corpus/CI routing so ADRs are validated by the structured-madr Action instead of flowing through the mif-validate corpus.

Changes:

  • Rewrote frontmatter for docs/adr/00010005 to Structured MADR / adr-genre shape (type: adr, status: accepted, etc.), preserving existing bodies.
  • Updated scripts/lib/corpus.mjs to carve out ADR docs content-based (via type: adr), adding listAdrDocs() and filtering ADRs out of listL3Docs().
  • Added regression tests and expanded CI (adr-smadr job) to validate project ADRs in both smadr (strict) and mif (level 3) modes; updated changelog entry.

Reviewed changes

Copilot reviewed 9 out of 9 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
tests/corpus.test.mjs Adds regression coverage for the ADR carve-out and status requirements; introduces listAdrDocs() assertions.
scripts/lib/corpus.mjs Implements content-based ADR carve-out; introduces listAdrDocs() and filters ADRs out of listL3Docs().
docs/adr/0001-align-adr-genre-to-structured-madr.md Updates ADR frontmatter to Structured MADR / adr-genre shape.
docs/adr/0002-host-ontologies-in-a-separate-repo.md Updates ADR frontmatter to Structured MADR / adr-genre shape.
docs/adr/0003-attested-delivery-release-pattern.md Updates ADR frontmatter to Structured MADR / adr-genre shape.
docs/adr/0004-node-engine-authoritative-with-parity-gate.md Updates ADR frontmatter to Structured MADR / adr-genre shape.
docs/adr/0005-provenance-consent-in-settings-hierarchy.md Updates ADR frontmatter to Structured MADR / adr-genre shape.
.github/workflows/ci.yml Routes project ADR validation to the structured-madr Action in both strict and MIF modes.
CHANGELOG.md Records the fix and the routing/gating changes under Unreleased.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread tests/corpus.test.mjs Outdated
Comment thread scripts/lib/corpus.mjs
…validated

Review follow-ups to the docs/adr genre-conformance change in this PR.

Carving the five ADRs out of listL3Docs() removed them from
listGatedDocs(), which is exactly the corpus engine-parity.mjs walks. Its
expected-disagreements ledger still named docs/adr/0001-0003, so every one
of them became an ORPHANED-EXPECTATION and the harness exits 1 ("RESULT:
PARITY FAILED"). The engine-parity workflow is nightly and deliberately
never runs on pull requests, so PR CI could not surface this: the break
would have shown up at 05:17 UTC, detached from the change that caused it.

- expected-disagreements.json: drop the three docs/adr entries. The
  description-key drift they tracked is still covered by the committed
  tests/fixtures/engine-parity/drift-description.md reproduction under the
  same mif-rs#38 upstream, so nothing stops being tracked. The ledger
  comment now also states the orphan failure mode and the corpus invariant
  every entry must satisfy.
- tests/corpus.test.mjs: pin that invariant in a PR-gated test — every
  ledger entry must resolve into listGatedDocs() + the parity fixtures.
  Fails on the pre-fix ledger (3 orphans), passes after. This moves the
  whole rot class out of nightly-only visibility. Also folds the duplicate
  node:fs import into the existing one.

Separately, three documents asserted the repo's ADRs carry MIF
type: semantic, which this PR makes false:

- skills/mif-corpus/SKILL.md instructed agents to identify the ingest skip
  set "never by a `type: adr` frontmatter value" — precisely backwards
  after this change, in a shipped skill.
- docs/reference/skills/mif-corpus.md and docs/reference/corpus-layer.md
  repeated the same type: semantic claim.

All three now say type: adr with conceptType: semantic, and name type as a
valid skip-set discriminator alongside the description: key and the path.
The conceptType columns in genre-and-cli-catalog.md and skills/adr.md were
already correct and are untouched.

Gates: test:hook 273 pass, validate-plugin 47 skills / 0 errors, lint:md
0 issues, check-doc-links 74 files clean, mif-validate L3 on both edited
reference docs.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 13 out of 13 changed files in this pull request and generated no new comments.

Suppressed comments (1)

tests/corpus.test.mjs:123

  • The status extraction regex is stricter than YAML/structured-MADR requires: if an ADR uses a quoted scalar (e.g. status: "accepted"), this test will fail even though the frontmatter is valid. Normalizing optional surrounding quotes avoids false negatives while still enforcing the allowed lifecycle enum.
    const status = split.fmText.match(/(^|\n)status[ \t]*:[ \t]*(\S+)/)?.[2];
    assert.ok(
      status && SMADR_STATUSES.has(status),
      `${f} must declare a structured-MADR lifecycle status, got ${status ?? '(none)'}`,
    );

…GatedDocs

The #203 carve-out removed type: adr docs from listGatedDocs(), which
silently shrank provenance-corpus-check.mjs's default corpus even though
the ADRs (and the adr template) are still gated by the adr-smadr job.
Add listAllGatedDocs() -- the mif-validate corpus plus the adr-smadr-owned
docs -- switch provenance coverage to it, clarify listGatedDocs()'s
doc-comment, and pin the union with a regression test.
Copilot AI review requested due to automatic review settings August 4, 2026 16:03

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 14 changed files in this pull request and generated no new comments.

Suppressed comments (2)

scripts/provenance-corpus-check.mjs:11

  • The header comment says listAllGatedDocs is "the same one definition ci.yml, release.yml and engine-parity.mjs consume", but engine-parity.mjs actually imports listGatedDocs() (mif-validate corpus only) rather than listAllGatedDocs(). This wording can mislead readers about what parity covers vs what provenance covers.
// Default corpus: every doc the suite gates (scripts/lib/corpus.mjs's
// listAllGatedDocs — the mif-validate corpus PLUS the adr-smadr-owned ADRs
// and adr template, so the #203 carve-out can't shrink provenance coverage),
// built on the same one definition ci.yml, release.yml and engine-parity.mjs
// consume. --dir switches to every .md under one tree instead.

tests/corpus.test.mjs:35

  • The test name says listL3Docs covers every configured L3 tree, but the body now special-cases docs/adr and skips asserting coverage there. Since ADR routing is now part of the corpus contract, this test would be clearer (and more future-proof) if it asserted that each L3 dir is covered by either listL3Docs() (non-ADR docs) or listAdrDocs() (ADR carve-out), instead of hardcoding a skip.
test('listL3Docs covers every configured L3 tree', () => {
  const files = listL3Docs();
  assert.ok(files.length > 0, 'expected at least one L3 doc');

@zircote
zircote merged commit 63433e2 into main Aug 4, 2026
13 checks passed
@zircote
zircote deleted the fix/203-adr-genre-conformance branch August 4, 2026 16:27
@github-project-automation github-project-automation Bot moved this from In Review to Done in Modeled Information Format Aug 4, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

Status: Done

Development

Successfully merging this pull request may close these issues.

docs/adr/0001-0005 violate the plugin's own adr genre skill (no type: adr, no status:), so audit-v2's immutable-ADR policy never engages on them

2 participants