Make the five docs/adr ADRs conform to the adr genre and route them to the structured-madr gate - #208
Conversation
…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.
|
In review. |
There was a problem hiding this comment.
Pull request overview
This PR makes the repository’s own ADR documents (docs/adr/0001–0005) 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/0001–0005to Structured MADR / adr-genre shape (type: adr,status: accepted, etc.), preserving existing bodies. - Updated
scripts/lib/corpus.mjsto carve out ADR docs content-based (viatype: adr), addinglistAdrDocs()and filtering ADRs out oflistL3Docs(). - Added regression tests and expanded CI (
adr-smadrjob) to validate project ADRs in bothsmadr(strict) andmif(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.
…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.
There was a problem hiding this comment.
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.
There was a problem hiding this comment.
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
listAllGatedDocsis "the same one definition ci.yml, release.yml and engine-parity.mjs consume", butengine-parity.mjsactually importslistGatedDocs()(mif-validate corpus only) rather thanlistAllGatedDocs(). 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-casesdocs/adrand 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 eitherlistL3Docs()(non-ADR docs) orlistAdrDocs()(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');
Closes #203
What
The repo's own five ADRs (
docs/adr/0001–0005) carriedtype: semanticand nostatus:, so the ADR carve-out never fired on them:audit-deterministic.mjsrecorded all five asmutability: mutableand the documented routing oftype: adrdocuments 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: adrandconceptType: semanticin its frontmatter"):docs/adr/0001–0005: frontmatter rewritten to the adr genre's structured-MADR form —type: adr,conceptType: semantic, lifecyclestatus: accepted,category,created/updateddates,author,project— keeping the MIF L3 fields the smadr schema carries (temporal,provenance,citations,relationships,summary) and moving non-schema keys (aliases,ontology, the oldextensionsblock) tox-extension keys. Bodies are untouched; the section skeletons already conformed.scripts/lib/corpus.mjs: content-based ADR carve-out.listL3Docs()now excludestype: adrdocuments (same shared predicate as the guard and the audit runner, viamif-genre-signal.mjs); a newlistAdrDocs()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 intodocs/adrstays in the mif-validate corpus..github/workflows/ci.yml: theadr-smadrjob now validatesdocs/adrwith the structured-madr Action in bothsmadr(strict) andmif(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 everydocs/adrdocument is thetype: adrcarve-out with a lifecycle status (fails on the pre-fix tree), thatlistL3Docs()excludes exactly the ADRs (listAdrDocs()returns them), and that a non-adr doc under an L3 tree stays gated.Verification
genre: adr | mutability: immutable | oracle: structured-madr | status: acceptedfor all five files incorpus-map.json.docs/adr: smadr strict mode 5/5 passed, 0 warnings; mif mode level 3 5/5 passed.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 thesite/Astro build (75 pages).