docs(1402): correct nine merged trailers — most are the wrong trailer type - #1410
Merged
Merged
Conversation
… TYPE The nine commits are merged, so the ledger is the only place their record can still be corrected — the remedy #1371 applied to its four. No code, no schema, no rule change. HOW THEY WERE FOUND, AND HOW THEY WERE NOT. #1402 was filed on a count: 29 of 51 `Implements:`-only production commits name a requirement whose capabilities own none of the touched files. Adjudicating those 29 by PURPOSE rather than by file overlap gives 9 real mislabels and 20 false positives (69%). The relevance rule that works for `Refactors:` would be wrong more often than right here, and check-trailer.sh's own header says why: `Implements:` is "product behaviour SERVING a requirement" (teleological) while `Refactors:` is a "STRUCTURAL change to a capability". A structural test applied to a purpose claim is a category error. The nine were found by reading, not by the rule, and no rule is proposed. THE UNIFYING FACT is that most carry the wrong trailer TYPE, not merely the wrong id — the teleological trailer used for structural changes: 5x repeater commits Implements: REQ-FUN-11 -> Refactors: CAP-47 185ce8d Implements: REQ-OBS-02 -> Refactors: CAP-47 d8527a3 Implements: REQ-SEC-13 -> Refactors: CAP-32 6f06b0f Implements: REQ-SEC-13 -> Refactors: CAP-55 561f064 Implements: REQ-DISC-01 -> Implements: REQ-DISC-07 AND THE CORRECT TRAILER WOULD HAVE BEEN CHECKABLE. Verified against the live rule: `Refactors: CAP-47` on 59784df, 42369e6 and fcbb859 returns an empty irrelevant-set, i.e. PASS. The right answer is not a new requirement or a looser rule — it is the trailer type that carries a claim the machine can test. Five of the nine are one copy-paste run, the same shape as #1371's four CAP-59 commits: the defect #1371 was filed about, recurring in the half of the trailers no rule inspects. Verification-objective: the permanent record of what a merged change served must be correctable after the fact, since a squash message cannot be, and the ledger is the only artifact that can carry that correction. Review: none — recording the adjudication posted on #1402 (2026-09-19). Each of the nine was read individually; the twenty defensible ones are listed there and deliberately left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6
dc0sk
added a commit
that referenced
this pull request
Sep 19, 2026
Maintainer decision 2026-09-19: no map change. `Refactors:` is STRUCTURAL — capability whose code was changed. engine.rs is CAP-38's. A commit changing the engine's OTA arm says `Refactors: CAP-38`; CAP-33's involvement is teleological and belongs in `Implements: REQ-FUN-06`. CAP-33 keeps ota_rate.rs + profile.rs: the policy, not its driver. THE COST I CITED IN #1403 WAS WRONG, and correcting it did not change the answer. I warned that widening CAP-33 to engine.rs would add 1335 mutants. It would add ZERO to the enforced set: CAP-33 satisfies only REQ-FUN-06 and CAP-38 only REQ-NFR-10/PHY-02/PHY-06/PERF-01, all baseline, which `req-mutation.sh --all-enforced` never touches. The real cost is a seventh owner on engine.rs, weakening the relevance rule where commits concentrate most. 09048b8 therefore joins #1410's corrections: its `Refactors: CAP-33` should have been `Refactors: CAP-38`. It is merged, so this entry is the record. A SQUASH ARTEFACT FOUND HERE: 09048b8's message carries THREE `Refactors:` lines (CAP-33, CAP-38, CAP-33), because a squash concatenates its constituent commits' messages and check-trailer.sh collects every matching line. Under the ANY predicate one irrelevant id fails the whole body. That is the lint working — each id is judged against the union diff, so a correct one still passes — but it means a PR body left as GitHub's default squash text inherits every commit's trailer, and one bad id in a ten-commit branch fails the PR. Verification-objective: the record of which capability a merged change altered must name the capability whose code it actually altered, so the requirement->implementation join is not attributed to a capability the change never touched. Review: none — recording a maintainer decision taken on #1403 (2026-09-19) after the cost figure in the issue was measured and found wrong. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6
dc0sk
added a commit
that referenced
this pull request
Sep 19, 2026
…1416) Maintainer decision 2026-09-19: no map change. `Refactors:` is STRUCTURAL — capability whose code was changed. engine.rs is CAP-38's. A commit changing the engine's OTA arm says `Refactors: CAP-38`; CAP-33's involvement is teleological and belongs in `Implements: REQ-FUN-06`. CAP-33 keeps ota_rate.rs + profile.rs: the policy, not its driver. THE COST I CITED IN #1403 WAS WRONG, and correcting it did not change the answer. I warned that widening CAP-33 to engine.rs would add 1335 mutants. It would add ZERO to the enforced set: CAP-33 satisfies only REQ-FUN-06 and CAP-38 only REQ-NFR-10/PHY-02/PHY-06/PERF-01, all baseline, which `req-mutation.sh --all-enforced` never touches. The real cost is a seventh owner on engine.rs, weakening the relevance rule where commits concentrate most. 09048b8 therefore joins #1410's corrections: its `Refactors: CAP-33` should have been `Refactors: CAP-38`. It is merged, so this entry is the record. A SQUASH ARTEFACT FOUND HERE: 09048b8's message carries THREE `Refactors:` lines (CAP-33, CAP-38, CAP-33), because a squash concatenates its constituent commits' messages and check-trailer.sh collects every matching line. Under the ANY predicate one irrelevant id fails the whole body. That is the lint working — each id is judged against the union diff, so a correct one still passes — but it means a PR body left as GitHub's default squash text inherits every commit's trailer, and one bad id in a ten-commit branch fails the PR. Verification-objective: the record of which capability a merged change altered must name the capability whose code it actually altered, so the requirement->implementation join is not attributed to a capability the change never touched. Review: none — recording a maintainer decision taken on #1403 (2026-09-19) after the cost figure in the issue was measured and found wrong. Claude-Session: https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6 Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The nine commits are merged, so the ledger is the only place their record can still be corrected — the remedy #1371 applied to its four. No code, no schema, no rule change.
How they were found, and how they were not
#1402 was filed on a count: 29 of 51
Implements:-only production commits name a requirement whose capabilities own none of the touched files. Adjudicating those 29 by purpose rather than by file overlap gives 9 real mislabels and 20 false positives (69 %).The relevance rule that works for
Refactors:would therefore be wrong more often than right here, andcheck-trailer.sh's own header says why:(indented above: the trailer lint greps
^Implements:without excluding fenced code blocks, so an unindented copy of the syntax in a PR body is parsed as a real trailer — which is how this PR first failed its own gate.)A structural test applied to a purpose claim is a category error. The nine were found by reading, not by the rule, and no rule is proposed.
The nine — and the unifying fact
Most carry the wrong trailer type, not merely the wrong id: the teleological trailer used for structural changes.
59784df142369e604d268836ceaa3d4ffcbb8594Implements: REQ-FUN-11("signed transfer manifests")Refactors: CAP-47(Relay forwarding and digipeater)185ce8d1Implements: REQ-OBS-02("rotating file logging")Refactors: CAP-47d8527a3fImplements: REQ-SEC-13("signing domains")Refactors: CAP-32(ownscore/ack.rs)6f06b0f6Implements: REQ-SEC-13Refactors: CAP-55(daemon/control server)561f064aImplements: REQ-DISC-01("Native JS8 waveform")Implements: REQ-DISC-07— genuinely teleological, simply the wrong id; #1400's CAP-79 split made it visibleThe correct trailer would also have been checkable
Verified against the live rule:
Refactors: CAP-47on59784df1,42369e60andfcbb8594returns an empty irrelevant-set — PASS. So the right answer is neither a new requirement nor a looser rule; it is the trailer type that carries a claim the machine can test.Five of the nine are one copy-paste run (the repeater cluster) — the same shape as #1371's four CAP-59 commits, recurring in the half of the trailers no rule inspects.
Left alone deliberately
The 20 defensible commits are listed on #1402 and not touched. Eight of them map "every emission keys the transmitter" onto REQ-PTT-01 ("PTT assert/release within 50 ms"), which is a missing-requirement gap rather than a mislabel — filed separately.
Verification
ledger order ok · doc frontmatter ok · trace check ok · doc stamps ok. Docs only.
Verification-objective: the permanent record of what a merged change served must be correctable after the fact, since a squash message cannot be, and the ledger is the only artifact that can carry that correction.
Review: none — recording the adjudication posted on #1402 (2026-09-19). Each of the nine was read individually.
🤖 Generated with Claude Code
https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6