release_gate_e2e.rs:102-122 still says musl is continue-on-error and that nothing runs the step-13 migration gate — both false since #84 #187
Labels
No labels
code-review
correctness
dos
performance
security
severity/high
severity/low
severity/medium
tech-debt
Kind/Breaking
Kind/Bug
Kind/Documentation
Kind/Enhancement
Kind/Feature
Kind/Security
Kind/Testing
Priority
Critical
Priority
High
Priority
Low
Priority
Medium
Reviewed
Confirmed
Reviewed
Duplicate
Reviewed
Invalid
Reviewed
Won't Fix
Status
Abandoned
Status
Blocked
Status
Need More Info
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
h-dv/code-index#187
Loading…
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?
Found by dogfooding during the 2026-09-06 triage session, while compiling the #80 blocker checklist. The file that is #80's release gate carries a stale description of two of the gate's own thirteen steps.
Measured
crates/daemon/tests/release_gate_e2e.rs:102-122— the header table describing steps 12 and 13:continue-on-errorbuild-musljob with nocontinue-on-error, already runningcrates/plugin-host/examples/release_smoke.rsbefore packaging, so an archive that fails is not shipped. Corrected in7b3fc7c, whose message says the earlier brief was stale.crates/package/tests/ruby_claim_parity.rs:420/:510(axis A),crates/plugins/tests/ruby_builtin_expectations.rs:936(axis B),crates/indexer/tests/ruby_package_parity.rs:450(axis C), pluscrates/indexer/tests/ruby_package_cost.rs:577andcrates/daemon/tests/ruby_package_e2e.rs. Axis C is wired at.forgejo/workflows/ci.yml:864, 878, 935, 948.Why this one is worse than ordinary comment rot
This file is the release gate.
the_release_gate(release_gate_e2e.rs:920) is the sequenced implementation of #80's steps 1–11, and its header is where anyone scoping the release reads what the remaining steps cost.Both stale sentences point the same way — toward more remaining work than exists. That is the exact error that has now cost this project three times:
Here the stale text is not in an issue but in the gate, which is the one artefact a reader would trust over an issue.
The rest of the file is exemplary by contrast:
:66-86states its own two real limitations honestly (step 9's crash uses acfg!(debug_assertions)seam so the phase-accurate crash is not reproducible against a released binary; step 11 grades the operator path only, because a package whose grammar never returns cannot pass C1). Those are the kind of statement this header exists for — which is why the two false ones stand out.Repro
Read
crates/daemon/tests/release_gate_e2e.rs:102-122, then read.forgejo/workflows/release.yml'sbuild-musljob and.forgejo/workflows/ci.yml:864. The file and the workflows disagree.Why existing gates miss it
Nothing grades this header against the workflows it describes. There is an in-house pattern that does exactly this kind of thing —
crates/indexer/tests/ci_disk_preflight.rsderives its exemption set from the workflows by scanning them (checks_out()at:197, withexempt.len() <= 1), andci_cadence.rsasserts workflow shape — so the capability exists; it has simply never been pointed at this file.What must NOT be done
continue-on-error, whether a step exists) should be derived from the workflow files, the wayci_disk_preflightalready derives its job census.Related
packages.rs:4478-4480vsrecord.rs:18;disclosure_derivation_registry.rs:63-86vs its own body). Three in one day, three files, same form: in-tree prose asserting a state the tree has moved past — and in all three the prose overstated the remaining work.🤖 Filed by the triage lane, 2026-09-06, found while compiling the #80 checklist.
packages.rs:4478-4480says the wire has no bit foris_extension, contradictingrecord.rs:18and a comment fifteen lines above it in the same expression #185disclosure_derivation_registry.rscalls #137 an open blind spot in its header while its own body says the gap is closed and inside the gate #186CONFIRMED and FIXED, and this one got the gate. Plus the answer to the generic-detection question, which is a refusal with numbers.
Lane worktree:
/tmp/cosi-lane-docdrift, detached at master552e3a2. Staged by path, not pushed.Verified before touching anything — both claims are false
Step 12 / musl.
build-muslis a separate job atrelease.yml:1196. It carries no job-levelcontinue-on-error; the onlycontinue-on-error: trueinside it is at:1715, on theUpload artifactstep, and the comment immediately below it (:1725) says the asymmetry is deliberate and that the smoke step deliberately has none. The file's own header at:1167-1177reads "THE OPTIONAL LEG IS A JOB, NOT Acontinue-on-errorFLAG" and describes the oldcontinue-on-error: ${{ matrix.optional }}in the past tense. So the workflow already knew; onlyrelease_gate_e2e.rsdid not.Step 13. All five files exist, and ci.yml's "Corpus suites" step invokes
ruby_package_parityandruby_package_costby--testflag.The fix —
release_gate_e2e.rs:97-140(was:97-122)Corrected, not deleted, and deliberately not swung to optimism. The step-12 table keeps every row and the "So step 12 STILL owes" paragraph now carries exactly the residual this issue named: aarch64-linux-gnu cross-built and executed nowhere; the shipped Windows archive is windows-gnu while the native per-push test proves the MSVC debug binary; macOS not a target (#59); the eleven-step sequence on Linux-gnu only. Step 13 reads "IMPLEMENTED AND CI-WIRED BY #84. That issue is still OPEN — see it for what remains, and do not read this row as a green tick" — no green tick, per the issue's second "must not". #80's checklist should be updated to match.
THE GATE —
the_platform_and_migration_table_is_derived_from_the_workflowsAppended to
release_gate_e2e.rs(:2414-2689). It re-derives both claims from.forgejo/workflows/*and the tree on every run. It modifies no workflow file — it only reads them — which keeps this lane off the surface another lane is editing.Derived, not written: the
jobs:mapping is split on the two-space job-head indent (so a job-levelcontinue-on-error:at four spaces is distinguishable from a step-level one at eight, and from the dozens that appear in these files as comment prose — that distinction is the whole game inrelease.yml); the musl job is found by its- target:line; its steps are split and therelease_smokeone checked; the--testarguments in ci.yml are parsed as tokens.Scoped honestly in its own doc: "This grades TWO enumerated claims, not 'the prose is fresh'."
MUTATIONS — ten, all RUN, real RED
continue-on-erroronbuild-muslcontinue-on-erroron the muslrelease_smokestep--testflag scan (predicate)ruby_claim_parity.rsworkflow_jobs' indent rule (predicate)M5 is the finding. My first cut asserted
ci.contains("--test ruby_package_parity"). Renaming the test toruby_package_parity_DISABLEDleaves that substring intact, and the mutation passed green — I had written the twelfthcontainswhile writing the gate that exists because of the other eleven. Fixed by parsing the--testflag's argument into a token set; M5 then reddens and prints the 23 tests ci.yml actually names. M6 exists because of M5: it mutates the parser and proves the floor catches a broken scan rather than reporting an empty set as compliance.M1 was re-run after
cargo fmtreformatted the file, since a mutation that was never executed against the shipped bytes is not evidence.THE REAL QUESTION: can a gate detect this class? — NO, and here are the numbers
Three refusals, each measured rather than argued.
1. Vocabulary — "prose asserting a wire/API shape". Over 152,986 comment lines in
crates/:no bit for1 hit (the #185 sentence),the wire has no0,has no tag0. The phrases wide enough to catch a paraphrase returnthere is no320,does not exist99,no such83 — overwhelmingly runtime conditions. The true family is one line and the generalisable families are pure noise.2. Issue state — "names an issue as open when the issue is closed". 4,766 in-tree mentions of 137 real issue numbers; 2,829 (59%) already name CLOSED issues, legitimately, as provenance. Narrowing to "closed issue + openness word on the same line" yields 113 hits that are ~all false positives, because
pending,open,stillandnothingare this codebase's ordinary domain vocabulary. And decisively: the predicate fires on 0 of the 3 instances. #185's sentence names no issue. #186 names #137, which is OPEN — the header was wrong about which work remained, not about a state. #187's sentence names none, and #84, which falsifies it, is also OPEN.3. Internal contradiction — "the same file states both sides". True of #185 and #186, and it is what makes them findable by a reader. It is not machine-checkable: "the wire has no bit for it" and "Its ABI half is closed too" are contradictory only under a semantic model of both sentences. There is no computable relation there — only the trivial fact that both strings are in one file.
This tree already contains the correct analysis, with its own measurements.
crates/abi/tests/doc_citation_gate.rs's header: of six doc defects one session found, "The first four are NAME RESOLUTION, and a scanner settles them mechanically. The last two are not, and this gate does not pretend to reach them" — and the last two are exactly this class (a test whose stated rule was the negation of its own assertions; aMUTATION (RUN)line that was false). It also records the calibration: dropping its shape rule from five words to one takes 300 citations to 1,851 candidates with 102 non-resolving, "a gate reporting them would be suppressed within a week." A gate with a high false-positive rate gets suppressed, which is worse than no gate.What IS generic, and is the actual deliverable
The line that holds is referent vs proposition. A backticked name is checkable — that is
doc_citation_gate, and it works. A claim about a state is not, unless the claims are enumerated, and enumeration does not scale past a handful.So the mechanism is not detection. It is: doc drift is the symptom; the disease is a fact whose only home is prose. Every instance here is a fact that had nowhere else to live:
pool_capability_registry'sNeverDynamicrow) and the comment was competing with it. Fixed by making the comment cite the row instead of restating it.doc_citation_gate— rename the test and the sentence reddens.The rule that falls out, and the reason all three drifted in the same direction: negative existence claims are the ones that rot. The tree only grows artefacts, so "there is no X" is falsified by ordinary progress while nobody ever revisits the comment — which is exactly why all three overstated the remaining work, and why the release gate's own body did too. A positive claim usually rots into a compile error or a broken intra-doc link and gets caught.
The cheap, non-vacuous discipline that follows is not a scanner: a negative existence claim should name its referent in backticks, which converts an ungradeable proposition into a citation the existing gate already grades.
release_gate_e2e.rs:84's "There is noplugin upgrade" is the good form and is already graded. "The wire has no bit for it" and "Nothing in this repository runs it today" are the bad form — anaphoric, referent unnamed, ungradeable by construction. I am not proposing a gate to enforce that; detecting "is this a negative existence claim" is refusal (1) again. It is a review heuristic, and it is worth writing down precisely because it costs nothing.Gates
No protected record touched; no baseline blessed.
Merge points.
release_gate_e2e.rsis shared: module doc:99-140, and a new block appended at:2414-2689(nothing between them is touched, so a conflict should be confined to the header hunk)..forgejo/workflows/*are read but not modified.🤖 Doc-drift lane, 2026-09-06, master
552e3a2Closing — fixed and, unlike its siblings, given a gate
Verified at source on
87a3fc8(pushed), independently of the lane's report::99-140now states both claims in the past tense with the correction beside them: "step 12 said musl wascontinue-on-errorafter7b3fc7chad already made it a separate REQUIRED job, and step 13 said nothing in this repository ran the…"x86_64-unknown-linux-musl | RUN in build-musl, a REQUIRED job, BEFORE packaging.the_platform_and_migration_table_is_derived_from_the_workflowsat:2512derives the claims from the workflow files instead of restating them.Why this one got a gate and #185/#186 did not
The lane's reasoning is worth keeping: doc drift is the symptom of a fact whose only home is prose. #185 and #186 were fixed by citation because their facts already had graded homes (
pool_capability_registry'sNeverDynamicrow; the file's own body). #187's facts had none, so it got a gate.And the structural note that explains why all three drifted in the same direction: negative existence claims are the ones that rot, because the tree only ever grows artefacts. "Nothing runs step 13" was true when written and could only become false.
The mutation that matters here
M5 SURVIVED FIRST. The gate written for this issue shipped
contains("--test ruby_package_parity"), and renaming the target to..._DISABLEDpassed green — the twelfthcontains, written inside the gate that exists because of the other eleven (#178, #180). It now parses the flag into tokens, with M6 added to mutate that parser. Reported rather than quietly fixed, because the recurrence is the finding.Closing.