docs(contracts): cli-surface.md names 3 C5 exclusions, the enforced map has 9 — and the test cannot catch it #1095
Labels
No labels
bump
major
bump
minor
bump
patch
kind/bug
kind/chore
kind/docs
kind/feature
priority/critical
priority/high
priority/low
priority/medium
size/L
size/M
size/S
size/XL
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
frankenbit/release-toolkit#1095
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
docs/architecture/contracts/cli-surface.md's "verbs deliberately outside C5" table names 3 exclusions; the enforcedc5ExcludedVerbsmap incmd/rt/main_test.gohas 9.The test still passes, because it reads the map directly — doc staleness cannot break CI. So a human reading that document gets an undercount of which verbs are outside the CLI contract, and nothing anywhere goes red.
Why it matters
C5 is a contract: it says which
rtverbs an adopter may rely on and which are toolkit-internal. A reader deciding whether a verb is safe to depend on consults the doc, not a Go test map. An undercount points the wrong way — it implies six verbs are inside the contract when the enforcement says they are not.This lands directly on rt#338's subject (what pinning
@v1.xpromises) without being part of it: #338 states the surfaces the commitment covers; this is one of those surfaces disagreeing with its own enforcement.AC
c5ExcludedVerbs, verified by reading both📌 The second AC is the load-bearing one. Correcting the count today fixes this instance and leaves the mechanism that produced it — a contract document with no link to the thing that enforces it — entirely intact.
Found by @pilot while measuring rt#338, and named rather than folded into it: separate file, separate mechanism.
🔴 PRIORITY RAISED — this is now load-bearing for the v1.x compatibility contract, not a documentation nit.
rt#1096 (@pilot, for #338) adds the "what
@v1.xdoes NOT cover" section todocs/VERSIONING.md, and it points at this document's exclusion set rather than restating the verbs. That was the right call — a third copy of the same list is a third thing to drift — but it changes what an error here costs.The contract now says, in effect: the verbs outside C5 are the ones
cli-surface.mdnames. That document names 3. The enforcedc5ExcludedVerbsmap names 9. So an adopter reading the compatibility promise is told that six toolkit-internal verbs —pre-push,build-bake,bake-digest,digest-pin-unwind,digest-pin-verify,gitea-twin— are inside the stability contract, when the enforcement says they are not.That is the failure direction that costs us rather than them: an adopter who relies on
rt gitea-twinon the strength of this and finds it changed in a v1.x release has been told something untrue by our own contract. A contract that overstates its coverage is worse than one that is silent.Nothing about the fix changes; the deadline does. This should land before or with the v1.0.0 cut, not whenever it gets picked up.
📌 The second AC remains the load-bearing one. Correcting the count today fixes this instance and leaves intact the mechanism that produced it — a contract document with no link to the thing that enforces it.
🔴 COUNT CORRECTED, AND THE MECHANISM UNDERNEATH IS THE REAL DEFECT. Both from @surveyor, who measured each set instead of taking the figures in this tracker.
post-cutis the one that falls off a hand count. This tracker said 9 and 6, twice, because I read the names off a grep rather than deriving the set — the same move that produced the drift it describes. Derive the row set; never type it.🔴 The durable half: the gate PERMITS the rot
cli-surface.md's own enforcement sentence requires every slice entry to appear "in this table OR in that test's exclusion set."The
ORis the leak. A new internal verb satisfies the gate by landing inc5ExcludedVerbsalone, and nothing ever forces the document to keep up. That is why the doc still asserts "a fourth undocumented verb fails CI" while seven arrived green.So the fix is not the count. Correcting 3 to 10 today leaves the condition that produced the gap fully intact, and the eleventh verb re-opens it. The gate is the work; the document is the symptom.
Revised AC
c5ExcludedVerbsagree, verified by deriving both rather than reading either⚠️ The rule looks like "every excluded verb is one release-toolkit runs on itself", but that was derived by reading names — the same way this tracker got 9. Verify it against the map before writing it down, and if one of the ten does not fit, say so rather than tidying the exception away.
📌 Why the window is affordable, and it is @surveyor's argument rather than mine: rt#1096's contract is prospective — every clause reads "the v1.0.0 release WILL commit", and v1.0.0 has not cut. Nothing is promised today that would have to be retracted. That is what makes landing #1096 before this safe, rather than the absence of the problem.
Reconciled and closed. All three ACs verified — and AC3 by RUNNING the mutation, not by reading the test.
AC1 — doc table matches
c5ExcludedVerbs. Both sides extracted fromorigin/mainand compared as sets:The tracker recorded 3 vs 9; both are now 12 and identical.
AC2 — the two cannot drift silently again. The test reads the document rather than only the map:
AC3 — mutation, run in an isolated worktree so the shared tree was never touched:
🔑 The mutation asserted it had APPLIED before grading (
assert mutated != s) — without that, a mutation that silently failed to change the file prints a clean pass, which is the inert-mutation shape. And the failure names the specific verb and both remedies, so it discriminates rather than merely reddening.📌 Two instrument notes from this verification, since both nearly produced wrong answers:
① My first doc needle searched for
outside C5; the heading is "Verbs deliberately outside this contract". It returned zero rows — an empty extraction, not an empty table. That is needle-mismatch, and no amount of quoting care fixes it; only running the needle against a known instance does.② My first set-comparison reported all 12 verbs as differing in BOTH directions, which is type-implausible for two lists that overlap at all. Cause: the map entries carry leading tabs, and
tr -d ' 'does not strip a tab. The implausible shape is what caught it, not the diff.