From 14c7f832fc659a41584ee1a1401d1c440a2b2408 Mon Sep 17 00:00:00 2001 From: Simon Keimer Date: Sat, 19 Sep 2026 14:47:57 +0200 Subject: [PATCH] docs(1403): CAP-33 does not own the engine's OTA arm, and should not MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. 09048b84 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: 09048b84'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 Claude-Session: https://claude.ai/code/session_0188ATCj6DZ9aRVQ2vSirua6 --- docs/dev/project/traceability.md | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/docs/dev/project/traceability.md b/docs/dev/project/traceability.md index a2f4dc7f..6c2b9114 100644 --- a/docs/dev/project/traceability.md +++ b/docs/dev/project/traceability.md @@ -15,6 +15,31 @@ and the actually-observed results per change. --- +## 2026-09-19 — CAP-33 does not own the engine's OTA arm, and should not; #1403 + +**Decision (maintainer, 2026-09-19): no map change.** `Refactors:` is **structural** — #1402 +established it from `check-trailer.sh`'s own header — so it names the 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 the correction did not change the answer.** I warned that +widening CAP-33 to `engine.rs` would add 1 335 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`**, and `req-mutation.sh --all-enforced` never touches them. The real cost is a **seventh +owner on `engine.rs`**, which weakens the relevance rule precisely where commits concentrate. + +**`09048b84` 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 worth knowing about, found here.** `09048b84`'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 +(#1401) one irrelevant id fails the whole body. That is the lint working, not a defect: each +constituent trailer is judged against the *union* diff, so a correct one still passes and only a +genuinely wrong one fails — which is what happened. Worth knowing because a PR body left as +GitHub's default squash text inherits every commit's trailer, so a single bad one in a ten-commit +branch will fail the PR. ## 2026-09-19 — REQ-PTT-04 was born scope-bound; bound its CLI half; #1405 **Change.** One `// VERIFIES: REQ-PTT-04` in `openpulse-cli`. Reachability **281/363 (0.77) ->