Development record
a record's resolution frontmatter is user-reachable and nothing checks it against the record body it sits on. The resolution field is emitted verbatim by 'abcd capture list --resolved --json', which commands/capture.md dispatches, so it is a shipped surface rather than an internal note — but the rendered site pages carry the record BODY, so a resolution that contradicts its own body is invisible on the site and visible on the CLI. Demonstrated in the v0.6.6 cut: iss-2608250743421381's body was corrected to say identity-check is deliberately NOT added to the ahoy hint, while its resolution field still said the hint advertises it and describes 'adding the identity-check it registers'. The docs-currency gate caught it by running the command rather than by reading the file, after the body had already been fixed. Same class as iss-2608242043243131 (the preflight gate list restated by hand in five places with no test deriving it) in a different field: a claim with more than one representation and no check that the representations agree. Candidate detector: a record-lint rule asserting the resolution field does not contradict the body, or more tractably that a record edited in a commit has its resolution field edited in the same commit whenever the body's claims change.
a record's resolution frontmatter is user-reachable and nothing checks it against the record body it sits on. The resolution field is emitted verbatim by 'abcd capture list --resolved --json', which commands/capture.md dispatches, so it is a shipped surface rather than an internal note — but the rendered site pages carry the record BODY, so a resolution that contradicts its own body is invisible on the site and visible on the CLI. Demonstrated in the v0.6.6 cut: iss-2608250743421381's body was corrected to say identity-check is deliberately NOT added to the ahoy hint, while its resolution field still said the hint advertises it and describes 'adding the identity-check it registers'. The docs-currency gate caught it by running the command rather than by reading the file, after the body had already been fixed. Same class as iss-2608242043243131 (the preflight gate list restated by hand in five places with no test deriving it) in a different field: a claim with more than one representation and no check that the representations agree. Candidate detector: a record-lint rule asserting the resolution field does not contradict the body, or more tractably that a record edited in a commit has its resolution field edited in the same commit whenever the body's claims change.
Deferral 2026-09-29
Deferred past v0.11.1: Ruled M14 on 2026-09-23: the co-edit rule first (a body change on a resolved record requires a resolution change in the same commit), the contradiction detector second, both inside the one sibling intent ruling M13 names with iss-2608241612007530 and iss-2608261635558358. That intent is not filed, filing it needs the product thinker's adoption, and its interview owes one question: does the co-edit rule refuse or advise?
Remedy grounds (2026-09-29)
- The ruling of 2026-09-23, dcn-2609230000000006, orders the co-edit rule first, and it is mechanical where a contradiction detector needs judgement.
- The issue-resolution script already walks the range's record moves, so the rule sits beside RS006 rather than in a new gate.
- Rejected: a semantic contradiction check first, which the ruling sequences second.
Frontmatter
| id | iss-2608250844259345 |
|---|---|
| type | issue |
| lifecycle | open |
| severity | major |
.abcd/work/issues/open/iss-2608250844259345-a-record-s-resolution-frontmatter-is.md
open on GitHub ↗ · commit history ↗
mentions5
- dcn-26092300000000062026-09-23 — The resolution field of a resolved issue gets two detectors, in order (product thinker, ruling on iss-2608250844259345): first a co-edit rule, under which a body change on a resolved record requires a resolution change in the same commit; later, as a second layer, a detector for a resolution that contradicts its body. Both belong to one intent, planned next cycle, for the three unwatched edges of issue resolution, with the inverse open-record detector (iss-2608241612007530) and audit verdicts that never reach resolved issues (iss-2608261635558358).
- iss-2608241612007530the issue-resolution gate is triggered by the trailer, so a fix that lands without one is invisible to it. RS001 fires only on a commit carrying a Resolves trailer, and RS002/RS003 only on stamps that already exist, so a merged fix whose commit names no issue passes all three rules and leaves its record in open/ — the exact backlog iss-2608241347321757 was built to stop, reached from the other direction. Measured 2026-08-24: 1315 commits name an iss- id somewhere in the message and 3 carry the trailer. iss-202 is the standing instance: its fix merged on 2026-08-24 in a commit ending with a bare 'iss-202' line rather than the trailer form, and its record sits in open/ with the fix shipped. The missing detector is the inverse direction — a change touching code an open record describes, declaring no resolution.
- iss-2608242043243131the preflight gate list is prose no test derives from the recipe, so it drifts every time the recipe changes. Makefile's preflight target names its prerequisites once; docs/how-to/install.md, CONTRIBUTING.md and the Makefile's own comment each restate that list by hand. The restatements have now drifted twice in two releases: v0.6.4 corrected three surfaces that said three gates after lint-issues made it four (2852c095 updated AGENTS.md alone), and v0.6.5 re-introduced the same defect by adding site-render as a fifth prerequisite and leaving those surfaces saying four. Both times only the host-run docs-currency reviewer noticed, and both times it refused a release cut over it. The class is a derived-value restatement with no deriving test: the same shape as the marketplace slug, which TestInstallGuideDocumentsTheInstallAndUpdatePath solved by reading go.mod and asserting the documented string contains it. The detector is the same move here — parse preflight's prerequisites out of the Makefile and assert each enumerating surface names exactly that set. Acceptance corpus: the two instances above, both of which the test must flag when replayed against their pre-fix trees.
- iss-2608250743421381two slash-command argument-hints advertise sub-verbs the binary refuses, in the one string a user reads before invoking. commands/ahoy.md:4 offers '[status | install | uninstall | doctor | dry-run]': 'abcd ahoy status' exits 2 with unknown command — bare 'abcd ahoy' is the status render — and the real sub-verb identity-check is absent from the hint. commands/launch.md:4 offers '[dry-run | ship | scaffold]': dry-run is a FLAG, so 'abcd launch dry-run' exits 2 while 'abcd launch --dry-run' exits 0; the binary registers only scaffold and ship. Both files' own bodies get it right, so the drift is confined to the frontmatter hint, which is exactly the part no prose reader checks and the part the harness surfaces first. The brief does NOT get it right: 04-surfaces/01-ahoy.md's dispatch sentence carries the same phantom status token, which is brief-tier and tracked under iss-2608231346137587. A first attempt at this fix ALSO added identity-check to the ahoy hint, which is wrong in the other direction: that verb is deliberately CLI-only, the command page carries a scoping note saying it stays a bare-CLI entrypoint rather than a plugin sub-verb, and the page carries a flow section for every other hinted token and none for it. The plugin dispatch set is install, uninstall, doctor and dry-run. This is a shipped surface, not record drift: commands/ is carried in the release bundle, so the adr-28 disposition that covers brief-tier findings does not apply. Found by the iss-35 crosscheck's plugin-command-surface probe at the v0.6.6 gate; the docs-currency pass had not flagged it across three runs, because its scope reads command prose rather than frontmatter.
- iss-2608261635558358Audit verdicts do not propagate to the resolved issues that rode the audited spec. An issue fixed inside a spec resolves at the fixing change (Resolves trailer, watched-fail test, RS001-RS003 provenance), which is correct and deliberate — but when the intent's audit later returns NOT_MET or MET_WITH_CONCERNS on a criterion, nothing walks back from the verdict to the resolved issues whose resolved_by points into that spec: they stay resolved while the audit says the delivery fell short. The design-consistent remedy is audit back-propagation, not a pending-verification state (a candidate queue is the forgotten post-merge step the close-with-the-act rule exists to avoid): the auditor's verdict names the resolved issues riding the failed criterion and files the recurrence treatment for each — a new issue citing the old disposition, per recurrence-is-signal — so a hollow fix is surfaced by the audit rather than waiting for the defect to bite. Kin: iss-2608241612007530 (a trailerless fix is invisible to the gate) and iss-2608250844259345 (resolution frontmatter unchecked against the body) — the three together are the closure loop's three unwatched edges.