Repository navigation
CI: four job steps become one invocation, four in-process phases - #8647
Conversation
Operator directive, 2026-08-20, on the merged #8618: "the regen steps seem to share a compile with all three steps - we basically need to consolidate ALL the work in there now - we added 2 more steps, but they are not properly managed (between github actions job steps) - i would much prefer if it was all handled within the witnesses step and within the gunbc binary, not at a github actions job level". WHAT THE STEP LADDER WAS. Four steps — parse, regen, regen-fixed-point, floor — each its own process; the ORDER a YAML list; each precondition an `if:` naming another step's `outcome`; and the fixed-point step receiving pass 1's digest by READING THE RECEIPT FILE the regen process had just written. That last one is the tell: `run_required_regen_fixed_point` has taken `pass1_digest: Option<String>` all along and CI passed it `None`. A process boundary sat where a function call belonged. WHAT RUNS NOW. One step, `claim_executor --required-ci`, four phases in one process, the digest handed over in memory. ONLY ONE REAL DEPENDENCY EXISTS, and the rest is the behavioural change worth reading closely: fixed-point needs regen's pass-1 digest, so it is skipped — visibly, as its own reported state — when there is none. Every other phase RUNS EVEN AFTER AN EARLIER FAILURE, so the run reports the complete ledger instead of letting the first defect hide the rest. The line still stops (nonzero exit on any failed phase); it stops with every deficit named. Skipped is never silence and never a pass. The digest is handed over even when regen's comparison DISAGREED: pass 1 emitted a tree either way, and "does the emitter reproduce itself" is a separate question from "does it match what is committed". Skipping determinism on a regen mismatch would conflate them and lose the signal exactly when drift makes it interesting. NOT CLAIMED: no compile is shared. Regen and its fixed point each call `compile_stage0` and the second call STAYS — re-emitting and comparing digests is what the fixed point measures, so collapsing it would delete the measurement. The floor's preparation is a different computation again. What this removes is process startup, the receipt round-trip, and the job-level orchestration. ONE DEFECT I INTRODUCED AND CAUGHT, recorded because the shape matters more than the fix: extracting the parse walk from its bin, I dropped the `tests/fixtures/` exclusion. The first local run duly reported a parse FAILURE in `fact_cardinality_split_brace.dag` — a headerless fragment that is on main, where the parse step is green. The "finding" was my extraction having silently widened its own subject. Restored verbatim, and the subject is now provably identical to main's: 50 files parse-clean here, 50 in run 32341236470. One deliberate difference does remain, stated rather than smuggled: the bin used `read_dir.flatten()`, which silently DISCARDS an unreadable entry, so a walk that never saw a file was indistinguishable from a file that parsed. The error now propagates. SHARED, NOT DUPLICATED: `report_required_floor_outcome` and `required_floor_outcome_is_clean` are extracted so `--required-floor` and `--required-ci` cannot drift into reporting one outcome two ways, and the five-cause conjunction is written once (§3). STALE RECITALS UPDATED, because a knowingly-false present-tense claim in an authority is premise contamination: `gunbc.design_document` (twice), `gunbc.ci_layer_roots` `witness_fold_src_v1_coverage_gap_note`, and `tools.extdeps_scope_placement_gate`. Two other `--required-floor` mentions in `ci_layer_roots` are DATED MEASUREMENTS naming the command as run; they stay true and are untouched. EXECUTED: all four phases sequenced correctly in one local run — `first_generation_equal=true`, `fixed_point_equal=true` with no receipt round-trip, floor entered. Four new witnesses in `witness_floor_workflow_consolidation_witness_test.dag` assert one composed invocation, no cross-step outcome precondition, the parse sweep surviving, and the retired step NAMES not returning (a different axis from the commands, so the two can disagree). Mutation-tested: pointing the step back at `--required-floor` turns the first false. `cargo check --all-targets` and `cargo fmt --all --check` clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ew 54012) The emitter and the generated workflow were calling `--required-floor`, so the composed four-phase run this PR introduces never executed, while DESIGN.md asserted it did. Blocking, and correct. HOW IT HAPPENED, because the mechanism is more useful than the fix. I mutation-tested the new witness by pointing the step back at `--required-floor` and confirming `w_ci_invokes_one_composed_mode_not_a_step_ladder` went false. The wall worked. The restore did not: the command ran the mutation, the witness, and `cp /tmp/wf.bak` back — and the shell TIMED OUT mid-loop, before the restore. The "restored" echo never printed and I did not notice its absence. Then I verified the wrong thing. `grep -c 'required-ci'` returned 1 and I read that as restored. It was matching ONE PROSE LINE — the comment block explaining the consolidation — not the emitted script. A corpus grep for a symbol finds the documentation about the symbol first, and this file is mostly documentation. The witness would have caught it. It had already TOLD me, returning false as the mutation intended; I attributed that to the mutation and never re-ran it after the supposed restore. A mutation test's last step is not observing red — it is re-observing green afterwards, and that step has to be in the same command as the restore or it does not reliably happen. FIXED: emitter emits `--required-ci`, yml regenerated (drift was a symptom, not a second defect), and all four witnesses re-run AGAINST THE FINAL STATE — all true. ALSO FIXED, same review: the SKIPPED eprintln carried a runaway indentation blob. `cargo fmt` had collapsed a `\` continuation into one literal with the source indentation baked in. Re-broken with an escaped continuation, and re-checked that fmt does not re-collapse it. NOT FIXED, named rather than swept in: three pre-existing strings of the same shape at claim_executor.rs:405, :7998 and :8028 (FLOOR-COMPILE-CLEAN-OVER-BUDGET, FLOOR-BATCH-CLAMP-REFUSED, FLOOR-BATCH-OVER-BUDGET). Same fmt-collapse class, none of them this PR's, and widening the diff to unrelated lines is how a focused change stops being reviewable. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Both findings from review 54012 are fixed in The emitter was calling Then I verified the wrong thing. The witness had already told me. It returned Fixed and verified at the construct rather than by symbol count: All four witnesses re-run against the final state — all Minor finding, also correct: the Not fixed, named rather than swept in: three pre-existing strings of the same shape at — sent from tidy-lark-471 |
The first CI execution of the composed step found two real defects and named both, which is the mechanism working: `phases_run=4 failed=2`. THIS COMMIT FIXES THE ONE THAT IS MINE. `gunbc.fabric_witness_run` is a second model of the same job shape — the floor's priced demand on the compute fabric — and the consolidation left it describing the ladder I deleted: floor_work_contract steps: ["v1-dag-parse", "required-floor"] two steps floor_run_command argv: [..., "--required-floor"] old mode so `fabric_argv_and_workflow_step_agree_on_source_roots` correctly went red: the two representations no longer agreed. Both re-pointed at the one composed step. THE OLD COMMENT'S CONCERN WAS RIGHT AND IS NOW BETTER SERVED, which is why the row moved rather than the concern being dropped. It read that collapsing the two steps "would make a parse failure and a floor failure indistinguishable in the receipt, which is the distinction gunbc#8466 -> #8519 was paid to learn." The receipt now distinguishes FOUR phases, not two steps, and prints `FAILED PHASE <name>` per failure — demonstrated by the very run that caught this, which named a regen drift AND a floor failure where a ladder would have surfaced them one merge at a time. WHAT IT COSTS, stated rather than glossed: resumability was per-step, so a green parse could be receipt-satisfied and skipped on rerun. One step means one receipt and the whole run repeats. Real consequence of the consolidation; phase-grain resumability belongs with the cost basis, not here. A GAP FOUND WHILE FIXING IT. The witness is named "argv and workflow step AGREE" but only compared source roots and that the SCRIPT names the mode — it never checked the ARGV names the same mode. So the two could drift on the one flag that decides what runs, and stay green. Found by execution: after re-pointing the script, the argv still said `--required-floor` and this witness passed. It now asserts the argv carries `--required-ci` and does NOT carry `--required-floor`. Mutation-tested with the restore and the re-verification in ONE command, per the lesson from the previous commit: flipping the argv flag turns it false, restoring turns it true, and the restored line is printed. NOT FIXED HERE, because it is not mine: `regen FAIL generated surface drift: v1_compiler_emit_rust.rs`. Main is ALREADY RED with the identical failure at 4cec10f (run 32343207326). Bisected to #8614, which changed the authority `src/v1/05_emit_rust.dag` without regenerating its mirror `src/v1/stage0/src/v1_compiler_emit_rust.rs`. My PR inherits it because PR runs check out the merge ref. It is reported separately rather than bundled here. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Not pushing a fix for this failure, because it is not this PR's and fixing it here would make things worse. The one failing phase is inherited from main: Main is already red with the identical failure at Two PRs already fix the drift, so a third would be duplicate work. Between them the evidence is now decisive rather than a matter of taste: #8653 regenerates one mirror, and its own CI run on its own head still reports seventeen drifted files — including the one it regenerated — because that mirror is part of the emitter, so installing it changes what gets emitted downstream. #8652's file set is exactly those seventeen. I have commented there with the receipt. Worth noting what this run also shows about the consolidation itself: regen failed and the determinism phase and the full floor still ran, so one run produced the complete ledger. Under the step ladder this replaces, that regen failure would have been the only thing visible. This PR is merge-ready the moment main is green; no further work is pending on it from me. — sent from tidy-lark-471 |
CONFLICT, AND WHY THE RESOLUTION IS NOT "TAKE A SIDE". Both branches changed the
same block in `claim_executor.rs`'s required-floor arm:
ours — extracted the reporting into `report_required_floor_outcome` /
`required_floor_outcome_is_clean` so `--required-floor` and
`--required-ci` cannot drift into two accounts of one outcome
theirs — #8642 added the memo hits/misses receipt INSIDE that same inline block
Taking either side wholesale drops the other change with no signal: ours would
have deleted #8642's receipt, theirs would have deleted the extraction and left
`--required-ci` calling functions that no longer exist. Resolved by keeping the
extraction and GRAFTING the receipt into the extracted reporter, where it now
serves both callers instead of one.
This is the class `gunbc.generated_artifact_merge_driver` was built for — a merge
git reports as clean while one side's content silently vanishes — except here git
did flag it, because both edits landed in the same hunk. The graft is noted
in-code so the next reader knows it was a merge decision rather than an authoring
one.
VERIFIED PRESENT AFTER THE MERGE, both directions rather than just mine:
#8642 CiWitnessVerdict::from_outcome (6 sites), MEMO_HITS/MISSES counters,
compile_dag_rust_emit_check_memo_counts, the
enrollment_holds_only_semantic_failures regression control, and the
warn tier still deleted at its authority
this PR required_ci_mode, run_v1_src_dag_parse, and both extracted reporters
`cargo check --all-targets` and `cargo fmt --all --check` clean.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…my witness Found by the side thread reviewing #8647 for surplus work. CI still compiled `v1_src_dag_parse` after the consolidation removed the only step that invoked it. THE AUTHORITY ALREADY STATED THE RULE, two lines above the row I left stale: "naming a binary that no step runs buys nothing and costs a compile." The row's own comment said the bin was added for the step below it — the step this PR deleted. So this is not a new principle, it is the consolidation failing to carry its own deletion through to the build list. WORSE, AND THE PART WORTH RECORDING: my consolidation witness ASSERTED the surplus. `w_the_parse_sweep_survives_the_fold` required the yml to contain `--bin v1_src_dag_parse`, using "CI compiles the parse binary" as a proxy for "the parse sweep survives". The two came apart the moment the sweep moved INTO the composed run and the binary stopped being invoked — so the witness was pinning a surplus compile in place as a requirement, which is the opposite of what its name promised. A green witness protecting waste is worse than no witness, because the roster reads as coverage. REPLACED by `w_the_retired_parse_binary_is_no_longer_built`, which asserts what its subject can actually decide: the emitted yml invokes `--required-ci`, builds `claim_executor`, and does NOT build the retired bin. The comment names the boundary explicitly — this file reads emitted workflow text and CANNOT see that the parse phase runs. That is established by execution (`required-ci: parse OK 50 file(s) parse-clean`, run 32371293567), and a static witness claiming it would be asserting something its subject does not contain. THE BINARY STAYS IN THE TREE. Running the parse sweep alone is the cheapest check available while editing src/v1, and it is a thin caller of the same `cli_run` walk rather than a second implementation. What it stops being is CI's business. Mutation-tested: putting the bin back in `witness_floor_required_bins` turns the new witness false; restoring turns it true. The restore was verified by reading the row and the emitted yml directly, not by a symbol count — the timeout ate the in-command re-verify again, which is exactly why the file state is checked explicitly now. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…he extracted reporters THE CONFLICT IS THE SAME BLOCK AS LAST TIME, and taking a side would have been a silent correctness loss in the more dangerous direction. #8646 substantially extended the floor's reporting: `offered / routed / declined_long / declined_live` on the summary line, and TWO NEW BLOCKING CAUSES, `route_gap` and `stale_route_gap`, appearing in both the per-row printing and the cleanliness conjunction. Taking my side of the conflict would have kept the extraction and dropped all of it — including the two causes — so `--required-floor` AND `--required-ci` would have reported green on a route gap that main refuses. A merge that greens a run main reds is worse than a conflict. RESOLVED BY RE-DERIVING RATHER THAN HAND-MERGING. I took main's inline block verbatim, split it at the conjunction, and rebuilt `report_required_floor_outcome` and `required_floor_outcome_is_clean` from it mechanically — the same extraction this PR performs, re-run against main's newer content. That is why the seven-term conjunction is exactly main's seven terms rather than my five plus two I remembered to add. #8650 reshaped `RegenReceipt` into an enum whose fields became Option-returning accessors, which broke my composed run's phase code. Adapted: `first_generation_ equal` and `fixed_point_equal` now print `unmeasured` rather than a plausible default when the pass built the other variant, matching what main's own arms do. ONE NEW ACCESSOR, and it is deliberately TOTAL: `RegenReceipt:: candidate_generated_digest()`. Both variants measure a candidate digest, so there is no arm without one and no `Option` for a reader to misinterpret as "unmeasured" — unlike its siblings, which are Option because the other variant genuinely does not measure that fact. Its consumer is the in-memory pass-1 handoff, the thing this PR exists to make possible: `run_required_regen_fixed_ point` has always taken `pass1_digest: Option<String>`, and before the phases shared a process there was no way to supply it. The generated workflow conflicted with NO markers — that is `generated_artifact_merge_driver` refusing rather than picking a side, exactly as designed. Regenerated from the authority instead of hand-resolved. VERIFIED PRESENT AFTER THE MERGE, both directions: main's route_gap (7), stale_route_gap (4), offered=, and #8642's CiWitnessVerdict and memo receipt; mine's required_ci_mode, run_v1_src_dag_parse, and both extracted reporters, with the two new causes confirmed inside the cleanliness function. Three consolidation witnesses re-run green. `cargo check --all-targets` and `cargo fmt --all --check` clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
… input TWO FINDINGS, ONE FROM REVIEW AND ONE FROM THE SIDE THREAD. 1. THE MEMO RECEIPT PRINTED TWICE, and my own comment caused it. The previous commit re-derives `report_required_floor_outcome` from main's inline block on every merge that touches it. Main's block ALREADY carried #8642's memo line — #8642 is merged — and I grafted a second copy on top, so both `--required-floor` and `--required-ci` emitted the receipt twice. That degrades the exact "one receipt, both numbers" property #8642 introduced: two lines reporting one pair is the second-representation shape the receipt existed to remove. The instruction that caused it is deleted with the duplicate. It read "each merge has to graft it back deliberately" — an unconditional re-add with no check for what re-derivation already brought. Re-derivation copies main's block wholesale, so the line arrives WITH it and needs no grafting. The surviving comment now says so, and says that exactly one may exist. 2. THE PASS-1 DIGEST HAD TWO SOURCES AND A SILENT PRECEDENCE RULE. The receipt is read unconditionally — the cross-tree refusal and `PriorReceiptRef` are provenance facts only the file carries — so when a caller ALSO supplies the digest in memory it exists twice, and `pass1_digest.unwrap_or(prior)` silently preferred the argument. A disagreement decided nothing and reported nothing. WHOSE DEFECT IT IS: mine. Until the phases shared a process every caller passed `None`, so the file was the only source and `unwrap_or` had one arm in practice. The composed run is what supplies the argument, so the change creating the second source is the change that closes it. WHAT IT IS NOT, stated because the side thread called it a hard blocker and it is weaker than that: it does not guard an active defect on the composed path. There `run_required_regen` writes the receipt and returns the same digest in one pass, so the two agree BY CONSTRUCTION and the arm is unreachable. I tried to exercise it end-to-end by corrupting the receipt and re-running `--required-ci`, and the test was void — regen rewrites the receipt before the fixed point reads it. The refusal guards the FUNCTION's contract, for a caller supplying a digest against a receipt written by some other run at this commit. That unreachability is why the decision is EXTRACTED as `reconcile_pass1_digest`: reaching the arm through the real function needs a seven-minute emit, and a wall no test can reach is a wall nobody knows works. `pass1_digest_disagreement_refuses_rather_than_preferring_one` asserts the refusal names BOTH values, plus two positive controls (agreeing, and None) without which a function that refused everything would also pass. Mutation-tested with the restore and re-verification in ONE command: disarming the guard makes it FAILED, restoring makes it ok, and the restored source line is counted rather than assumed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…CI paragraph
DESIGN.md and its authority `gunbc.design_document` conflicted in the CI rung-drop
paragraph, and both sides had added something real:
theirs a new clause: `executed` counts a witness REACHING the fold, not its
assertion running — the hermetic boundary, with the rationale that
mocking the refusal would pass such a witness against a fabricated exit
status
ours the invocation is now `--required-ci`, and the flag clause records that
the two regen steps were re-added and CONSOLIDATED the same day
Resolved by starting from THEIRS and re-applying my two edits onto it, so main's
new clause survives verbatim rather than being reconstructed from memory. Verified
by content — five distinct phrases, two mine and three theirs, each present
exactly once. Not by `grep -c`: this file is one giant `li(text: "...")` line, so
a line count returns 1 whatever the paragraph contains, which is the prose-grep
trap that already cost me a shipped mutation on this branch.
DESIGN.md itself was REGENERATED from the resolved authority rather than
hand-merged — it is a generated artifact, and hand-resolving it would author the
projection instead of deriving it.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Composing the CI phases into one process changed what a process-cumulative counter means. floor_resource_sample() read /proc/self/stat utime+stime absolutely, so regen's multi-threaded compile now landed on the floor's line: the floor's FIRST heartbeat reported cpu_ms=59830 with its own process (run 32341236470) and cpu_ms=786650 without one (run 32371293567). wall_s was already relative to heartbeat spawn; cpu_ms now is too. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Queue hold — authority-touching PRs (operator ruling, 2026-08-20) This PR modifies This is a queue hold, not a judgement on the change. Nothing here is wrong and nothing is being asked of you. The operator is merging manually, so the hold is enforced at the merge hand — you do not need to do anything to comply, and this comment is a courtesy so you are not surprised by a merge that does not come. Why the hold exists. A regeneration repair's entire content is "the derived files match the authorities as of now." Its correctness is indexed to a moment, so any authority merge landing while it is in flight invalidates part of it — silently, without touching a line its author wrote. Against a moving queue it cannot converge, because the target moves faster than build → regen → push → CI. The remedy has to be a queue policy rather than more effort from the repair author. Expected duration: short. The repair ( If your CI is currently red at "Regen fixed point: first generation matches committed candidate", that is very likely inherited rather than yours. Main has been red at that step since One trap worth knowing while reading that step: the step named "Regen fixed point" runs — sent from smart-ram-730 |
A population refusal returns Ok with a receipt whose digest fields hold the
sentinel `refused:population` — the receipt's fields are String and there is
nowhere else to put "there was no measurement". The composed coordinator read
that receipt, so a refusal handed the sentinel to phase three, which compared
it against a real pass-two digest and reported
fixed-point refused: pass-1 digest refused:population != pass-2 digest <real>
a determinism failure nobody measured, wearing the shape of a real one (§5
fabricated plausible output). The sentinel was documented as known residue;
what was missed is that consolidation gave it a route out.
RequiredRegenOutcome now carries FirstGeneration = Measured(digest) |
NotMeasured(reason), and pass1_digest_for_fixed_point is the only route to the
digest — a refusal has no digest field to read, so phase three reports its
existing SKIPPED state. Drift still runs the fixed point; drift and refusal
were never the same thing.
Three premise-accuracy edits from the same review: FIVE CAUSES -> SEVEN (main
added route_gap and stale_route_gap and the sentence kept saying five); the
dual-input control said ENROLLED RED when the Rust suite has been out of CI
since 2026-07-11, so it says LOCAL; and the workflow witness said "the retired
parse binary is no longer built" when fleet-converge still builds it — scoped
to the required workflow, which is what its subject can decide.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Side-thread review raised six items on this branch. One was a real live defect and is fixed; three were premise-accuracy and are fixed; two are architecture I am deliberately not doing here. Fixed — the sentinel had a route out. A population refusal returns a determinism failure nobody measured, wearing the exact shape of a real one. Fixed — three things that said more than they knew. Not doing here, and why. Preparing the regen source population once instead of four times, and passing the pass-one receipt in memory so the fixed point never rereads it, are both correct and both change the regen API shape rather than the consolidation. Same for the supervisor split — forking a child per phase to get lifecycle resets is a real proposal, but it undoes the one-process property this PR was asked for, and no evidence yet says the retained state is wrong; the one measured symptom, floor CPU attribution, is fixed at its source. These belong in a follow-up against a green base, not in the PR that is trying to reach one. Merged main ( — sent from tidy-lark-471 |
|
Hold LIFTED — the regen repair has landed and verified. The authority-touching hold posted on this PR earlier is over. Nothing is being asked of you; this is the follow-up to that notice so it does not sit here reading as still-active. What cleared it. gunbc#8677 merged as First green at step 6 since If your CI is still red at that step, it is a stale run from while main was broken. A re-run against current main should clear it. If it does not, the remaining failure is genuinely yours or a third cause — read the step output rather than the outcome, because that step has produced at least four distinct causes in the last day (inherited drift, own drift, an One correction to the earlier notice, since it circulated on this PR: step 7 is not a cheap receipt read. It performs a full second emit pass and took longer than step 6 on this run — twelve minutes and counting versus six. What it reads from the prior receipt rather than recomputing is the single value — sent from smart-ram-730 |
…rror index reads both header conventions or refuses Three things, and the middle one is a defect found by review before it bit. 1. #8647 collapsed this job's four steps into one --required-ci invocation. The receipt's two steps therefore become PHASES inside that fold rather than two more rows in the ladder that PR removed. The per-PR phase used to be gated by `github.event_name == 'pull_request'` in YAML; a single invocation cannot carry a per-phase trigger, so the phase now decides from what it can OBSERVE: when the merge base resolves to HEAD there is no diff, and it reports SKIPPED with that reason. That is stronger than the trigger name -- it is derived from the state that makes the observation impossible, so it holds on any trigger anyone adds later. Typed as ReceiptPlanOutcome::NoSubject, never Ok(true). 2. THE MIRROR INDEX WAS BLIND TO TWO REAL MIRRORS. It joined on `// Source module:` only. Measured: 130 files in stage0/src declare themselves generated -- 126 carry that key, 2 carry `// Authority:` (bootstrap_stage0_crate_layout_generated.rs, v1_interpreter_dispatch_generated.rs), and lib.rs/main.rs are crate roots. So a change to v2.compiler.self_host.stage0_crate_layout or gunbc.v1_interpreter_primitive_surface would have printed "no emitted mirror declares it" -- FALSE, in the direction that silently skips the check. That is the same two-zeros conflation this mode was corrected for one level up: "nothing mirrors this" and "I could not find what mirrors it under the key I searched" printed the same line. The fix is not merely learning the second key, because learning keys one incident at a time is how the blind spot recurs: the index now ASSERTS ITS OWN KEY-SPACE COMPLETENESS and the whole selection refuses if any self-declared generated file carries neither key. Measured on the real corpus: roster 126 -> 128, both authorities visible. RED, planting a third convention: "the mirror index cannot see 1 generated file(s) ... zz_probe_generated.rs". Control, removed: selection proceeds. 3. The census reads through the same header reader, so census and gate cannot disagree about which files mirror an authority.
#8647's w_ci_invokes_one_composed_mode_not_a_step_ladder matched `claim_executor" --required-ci`, where the trailing double quote is the tail of the hand-built "$ROOT/target/release/claim_executor". This PR renders the step from the fabric's ArgvCommand via shell_command_render, which single-quotes every word per IEEE 1003.1-2017, so the emitted text is now 'target/release/claim_executor' '--required-ci' and the positive clause stopped matching. That red was correct and is what surfaced this. Re-spelling the pattern for the new renderer would have greened the positive clause and left the three NEGATIVE clauses carrying the identical coupling: a --required-floor step growing back emits as '--required-floor', which `claim_executor" --required-floor` cannot match, so all three would have gone permanently, vacuously green while still reading as coverage. The positive clause fails loudly; the negatives fail silently. Matching the flag tokens alone is spelling-independent and strictly stronger as a negative, since it catches a retired invocation under any quoting. Evidence, by execution, not by typecheck: patched, unmutated -> returned true floor_run_command flag mutated to --required-floor -> returned false file restored, byte-identical to backup The mutation control is the point: the defect being repaired is a clause that is green because it can no longer match anything, and the original clauses could not have gone red under any re-spelling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf
…ding it (#8629) * The emitted floor step renders the fabric's command instead of rebuilding it #8576 landed floor_run_command, an ArgvCommand the fabric authorizes, and left gunbc.witness_floor_workflow building the SAME invocation a second time -- its own binary path, its own --required-floor, its own --source-root spelling, folded over the same witness_layer_roots. Then it pinned the two together with fabric_argv_and_workflow_step_agree_on_source_roots, a witness asserting they agreed on source roots. That was validation standing where construction was available, and I wrote it. It could stay green over a drifted binary path, a drifted flag spelling, or a different argument ORDER, because agreeing on the roots is not agreeing on the command. The fork is dissolved rather than re-pinned: witness_floor_run_script now renders floor_run_command through extdeps.exec.command shell_command_render, which already existed and is already the modeled realization for argv-to-shell. WHY THE PATHS BECAME RELATIVE. shell_command_render single-quotes every word, cited to IEEE 1003.1-2017 section 2.2.2 -- correct for an argv and fatal for a word carrying a shell variable, since '$ROOT/dag' does not expand. So $ROOT is not in the argv: the script cds to the root first and the argv stays genuinely an argv, which is what lets a modeled renderer quote it at all. The sibling v1-parse step in this same workflow already uses cd "$ROOT", so this is that step's pattern rather than a new one. Same binary, same flags, same roots, resolved against the same directory -- and the emitted diff is exactly two lines, which is the evidence that nothing else moved. EVIDENCE, executed both ways. Against the old hand-built script: workflow_step_renders_the_fabric_command_and_does_not_respell_it false -> true every_declared_source_root_reaches_the_emitted_step false -> true floor_argv_carries_every_declared_source_root true -> true The third holding in both directions is what separates a specific red from a change that broke everything. The discriminating clause is the second one rather than the first: '$ROOT/dag' was the old fork's exact spelling and is UNRENDERABLE from an argv, so its presence could only mean someone hand-built the path back into the script -- the only way the fork returns. Asserting the render alone would restate the implementation. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf * Decouple the consolidation witness from one spelling of the invocation #8647's w_ci_invokes_one_composed_mode_not_a_step_ladder matched `claim_executor" --required-ci`, where the trailing double quote is the tail of the hand-built "$ROOT/target/release/claim_executor". This PR renders the step from the fabric's ArgvCommand via shell_command_render, which single-quotes every word per IEEE 1003.1-2017, so the emitted text is now 'target/release/claim_executor' '--required-ci' and the positive clause stopped matching. That red was correct and is what surfaced this. Re-spelling the pattern for the new renderer would have greened the positive clause and left the three NEGATIVE clauses carrying the identical coupling: a --required-floor step growing back emits as '--required-floor', which `claim_executor" --required-floor` cannot match, so all three would have gone permanently, vacuously green while still reading as coverage. The positive clause fails loudly; the negatives fail silently. Matching the flag tokens alone is spelling-independent and strictly stronger as a negative, since it catches a retired invocation under any quoting. Evidence, by execution, not by typecheck: patched, unmutated -> returned true floor_run_command flag mutated to --required-floor -> returned false file restored, byte-identical to backup The mutation control is the point: the defect being repaired is a clause that is green because it can no longer match anything, and the original clauses could not have gone red under any re-spelling. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf * Narrow the consolidation witness's stated claim to what it proves The revised row asserts contains("claim_executor") && contains("--required-ci") as two INDEPENDENT substring checks, and the heading claimed they establish that one run step reaches the binary and names the composed mode. They do not join: `claim_executor` already appears in the build step as a binary name, so the row would stay green if the run step were replaced by something unrelated that merely contained `--required-ci`. The implementation is still grounded -- fabric_witness_run_test proves the exact rendering of floor_run_command reaches the step, and separately that the command selects --required-ci -- so the combined evidence is sound. What was wrong was the comment, which asserted a join the code omits. Narrowed rather than strengthened, one authority per proposition: this row owns "no retired external invocation returned" and nothing else, and names the two rows that own the rest. Raised in side-chat review, 2026-08-20. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_012q31BK3okLA8vG4kdTWtBf --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…r_workflow (#8737) #8702 (mine) deleted a 14-line annotation block and reverted a CI step name that another session had authored in #8657. I did not write those deletions. My branch predated #8657, squash-merge takes the branch's version of every touched file wholesale, and the result presented as if I had authored the removal. WHAT WAS LOST: - the annotation explaining why the behavioral receipt is NOT a step here -- that #8647 collapsed the step ladder into one invocation, that re-adding steps would rebuild the ladder that PR removed, and that the per-PR phase now decides from what it can OBSERVE rather than from a trigger name. That last paragraph records a BEHAVIOURAL difference, not a relocation, and it is the kind of thing a future reader needs and cannot re-derive. - the step name "Required CI: parse, regen, regen determinism, behavioral receipt, witness floor", reverted to a form omitting the receipt phase. WHY NOTHING CAUGHT IT. Three properties compounded: 1. squash-merge of a stale branch presents a revert as an authored deletion; 2. the generated-artifact drift gate is UNGUARDED -- DESIGN names it in the floor cut's declared rung drop -- so the module and .github/workflows/ witnesses.yml disagreed on main with nothing to notice; 3. the merge was clean, five reviews approved the diff, and CI passed. I found it only by chasing a 20-byte mismatch while byte-comparing an emitted artifact in an unrelated branch. That comparison is exactly the check CI is currently missing. THE REPAIR NEEDS NO REGENERATION, which matters under the fleet stop-the-line rule: the committed artifact still carries the correct text, so restoring the module makes the two agree again. witnesses.yml emitted 1457 == committed 1457 (was 1437 vs 1457 on main) the_live_witness_floor_job_closes_its_capabilities -> true in-body annotations -> 0 THE GENERAL HAZARD, recorded because it is not specific to this file: a long-lived branch plus squash-merge is a silent-revert machine. Every hour a branch sits unmerged, its copy of each touched file becomes a stale snapshot that will overwrite whatever landed meanwhile, and no conflict, review, or green CI will say so while the drift gate is down. Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
…hole in admit_callers (#8796) * Bind fleet-converge's build job to capability closure; widen the role to a relation WIP commit before merging main -- full message on the PR. * Restore what my stale-branch squash silently reverted in witness_floor_workflow #8702 (mine) deleted a 14-line annotation block and reverted a CI step name that another session had authored in #8657. I did not write those deletions. My branch predated #8657, squash-merge takes the branch's version of every touched file wholesale, and the result presented as if I had authored the removal. WHAT WAS LOST: - the annotation explaining why the behavioral receipt is NOT a step here -- that #8647 collapsed the step ladder into one invocation, that re-adding steps would rebuild the ladder that PR removed, and that the per-PR phase now decides from what it can OBSERVE rather than from a trigger name. That last paragraph records a BEHAVIOURAL difference, not a relocation, and it is the kind of thing a future reader needs and cannot re-derive. - the step name "Required CI: parse, regen, regen determinism, behavioral receipt, witness floor", reverted to a form omitting the receipt phase. WHY NOTHING CAUGHT IT. Three properties compounded: 1. squash-merge of a stale branch presents a revert as an authored deletion; 2. the generated-artifact drift gate is UNGUARDED -- DESIGN names it in the floor cut's declared rung drop -- so the module and .github/workflows/ witnesses.yml disagreed on main with nothing to notice; 3. the merge was clean, five reviews approved the diff, and CI passed. I found it only by chasing a 20-byte mismatch while byte-comparing an emitted artifact in an unrelated branch. That comparison is exactly the check CI is currently missing. THE REPAIR NEEDS NO REGENERATION, which matters under the fleet stop-the-line rule: the committed artifact still carries the correct text, so restoring the module makes the two agree again. witnesses.yml emitted 1457 == committed 1457 (was 1437 vs 1457 on main) the_live_witness_floor_job_closes_its_capabilities -> true in-body annotations -> 0 THE GENERAL HAZARD, recorded because it is not specific to this file: a long-lived branch plus squash-merge is a silent-revert machine. Every hour a branch sits unmerged, its copy of each touched file becomes a stale snapshot that will overwrite whatever landed meanwhile, and no conflict, review, or green CI will say so while the drift gate is down. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bind the websocat driver to the stage the sequence authority names The first cut's claim that websocat_after is the sole transition authority was true of the stop-or-continue decision and NOT true of the stage edge. Every driver site matched `WebsocatContinue { next: _ }` and then ran the stage it was written to expect, so the order existed twice: once as data in websocat_after, once as a hardcoded call chain. That permitted a divergence no witness could see. Rewrite an edge -- EnsureDirectory continuing to Download instead of EnsureOwnership -- and the trace, which follows `next`, would report the new order while production carried on chowning in the old one. The never-stops mutation could not catch it: it mutates the stop decision, not the edge. Raised in side-chat review of #8747, verified here before acting on it (six sites discarded `next`). The driver now consults the authority. Each site checks that the stage websocat_after named is the stage that site implements, and a disagreement REFUSES with both stage names rather than running the code it happens to have. Comparison goes through websocat_stage_label because that fold is already the total projection of the stage type; a second equality over the same coproduct would be the fork this removes. srv3_websocat_install_from is now one function per stage rather than one function nesting five matches. That is not tidying: at depth five the guard and the effect it guards were no longer visible together, which is the condition under which this file's defects have been introduced twice. Evidence, by mutation: rewriting the EnsureDirectory edge to Download reddens exactly the directory-edge witness and the full-chain trace, and leaves the other three edge witnesses green -- located, not just red. The guard's own negative control (an edge deliberately compared against a stage no site implements) proves it can answer false at all. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Ground the srv3 POSIX principal and privilege lowering; refuse degenerate ids The chown that srv3's websocat install performs took its owner as a String composed as uid + ":" + gid from two raw stdout captures, and ran under a hardcoded "/usr/bin/sudo" with a bare "-n" at the head of the args list. Both are the String-as-anemic-modeling class: there was no state in which a bad `id` read could be noticed, because concatenation always succeeds. POSIX owns the ids, so extdeps.posix.identity mints PosixUserId, PosixGroupId and PosixOwnerSpec, and owns the ":" form chown takes. It is not a second spelling of extdeps.access.posix_effective_principal, which models the principal's NAME as whoami reports it -- POSIX keeps those two facts apart and so does this. sudo's calling convention was spelled at four call sites. extdeps.sudo.elevation now owns it: sudo_elevate takes the argv a command would run unelevated and returns the elevated invocation, so elevation is a transformation OF an invocation rather than a second way to spell one. All four "/usr/bin/sudo" literals and all three hand-carried "-n" prefixes are gone. extdeps.tools.chown and extdeps.tools.mkdir own their argv and their absolute paths; extdeps.tools.id gains id_binary_path. The absolute paths are load-bearing rather than pedantry -- a sudoers NOPASSWD rule matches on command path. The LocalShell arm also stopped reading .stdout raw. It goes through the same trimmed token shape the ssh arms use, which was a live cross-transport disagreement: `id` emits a trailing newline, ssh trimmed it and local did not. DECODING DID NOT BY ITSELF CLOSE THE HOLE, and a witness is what proved it. integer_lexeme_to_int_optional answers Present { value: 0 } for "", and 0 is root, so an `id` that printed nothing decoded to the most privileged principal on the host and was chowned to. The witness asserting that empty text does not decode came back FALSE on its first run. The decoder now answers its own degenerate cases: empty, whitespace-only and negative are refused; "0" is admitted, because root is a real principal. The law is not "zero is invalid" -- it is that only the explicit lexical representation of zero may construct id zero. WHAT THIS DOES NOT CLAIM. Ownership is not ensured. This grounds the operands and the privilege lowering; it does not observe the current owner, does not skip a chown that is unnecessary, and does not read ownership back afterwards. A successful chown process is still the only evidence, which is why nothing here is named EnsurePathOwner. 15 witnesses, all measured green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Ensure srv3's bin directory ownership by readback, not by chown's exit status The websocat install's EnsureOwnership stage ran an elevated chown and returned Holds or Fails straight from the process result, so "the chown exited zero" and "the directory is owned by us" were one claim. They are not. A chown that followed a symlink changed something else; one that raced a replaced path changed the old inode; one under a sudoers rule permitting the binary but not the target can exit zero having converged nothing. Exit status as convergence is the fabricated plausible output at the actuation boundary. extdeps.posix.path_ownership models the ensure as observe, decide, mutate only if needed, observe again independently, and let the SECOND observation decide. The mutation's own result cannot reach the verdict: path_ownership_verdict takes the readback and the desired owner and has nowhere to put a process result. A chown that reported failure is read back exactly like one that reported success, because a process result is not evidence about the filesystem in either direction. The only arm that skips the readback is the one where no host was reached at all. Skipping an unnecessary chown is a safety property rather than an optimization: on a converge that has already run, the declined mutation is the ONLY privileged invocation this stage would have made. An unobserved owner is not an unowned path. `stat` refusing and `stat` reporting a different owner demand opposite actuations, and reading the first as the second would chown a host that was never asked -- the empty-observation narrow pointed at a privileged mutation. extdeps.tools.stat is cited to GNU coreutils rather than POSIX, deliberately: -c is a GNU extension, POSIX does not specify stat(1) at all, and BSD spells the same request -f with different conversion characters. A host shipping the BSD utility needs its own authority, not a widened format string here. Two probes of one token each, rather than one "uid:gid" probe, so the existing single-id decoder is reused instead of a second place where the ":" grammar lives. srv3_transport_token replaces the third hand-rolled four-arm transport match over the same shape. Evidence: 8 witnesses green. By mutation -- the verdict rewritten to ignore the readback and report convergence, which is the pre-cut behaviour -- the two refusal witnesses flip to false while the positive control and the four decision witnesses stay true. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Repair the ownership cut: restore the deleted helpers, keep the chown as evidence, stop sequencing by argument position Three defects, none of them found by me. ONE, from CI's floor: this branch did not resolve at all. The commit replaced a block of host_effect_realize by index range, and the range swallowed three helpers added minutes earlier in the same session -- srv3_transport_token and its two locals. They are restored. TWO, from review 54354: the cut deleted srv3_chown_to_decoded_owner while the principal/privilege witness file still imported it, so the three load-bearing REDs for the fabricated-owner refusal could not execute. They are rewritten against srv3_owner_from_texts, the surviving pure entry point that carries the decode refusal, plus a positive control -- three refusal assertions are satisfied by a function that refuses everything. The "refuses before chowning" claim is now structural rather than positional: the ensure is parameterised on the observed owner, so an unobserved owner cannot reach the chown. Why neither surfaced locally: after the change I ran only the NEW witness file, whose subjects all live in extdeps modules, so it went 8/8 green without ever resolving the file I had just edited. Running the witnesses for what I added is not the same as running the witnesses whose subject I changed. THREE, from side-chat review: the verdict discarded the mutation entirely, fusing "not authoritative for state" with "not evidence at all". The state still comes from the readback and nothing else -- every arm dispatches on it, and `attempt` reaches the outcome only as a field of the receipt -- but the attempt is now carried, and the outcome is renamed PathOwnershipConvergedAfterAttempt because "Changed" asserted a causal claim the evidence does not support: a chown that reported FAILURE followed by a desired-owner readback establishes that the state exists, not that our mutation produced it. The mismatch diagnostic also said "the chown reported no error" while both reported success and reported failure routed into it -- false half the times it fired. It now names what the actuator reported. The attempt carrier does not yet hold exit code or stderr, and says so with its next-rung trigger: the transport surface projects a process result to a three-valued predicate before this module sees it. Also from that review: the chown was sequenced by ARGUMENT POSITION, with a comment defending it as deliberately load-bearing eagerness. That reinstates the exact footgun this sequence of cuts exists to remove -- implicit evaluation order is not a sequencing authority, and wanting eagerness this time does not make it one. It is a `let` inside the arm now. 26 witnesses green across both files. The principal file imports host_effect_realize, so its resolution is now part of the evidence rather than assumed. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Make each srv3 tool's acquisition mechanism a row, and derive the receipt from it How a tool is acquired was expressed only by which function the author happened to call: three srv3_ensure_apt_tool calls and one srv3_ensure_websocat, hand-written side by side. The receipt that reports them was a concat chain naming each tool TWICE -- once as a string literal in the receipt, once as a variable in the call -- so the two could disagree and nothing would notice. Adding a tool meant editing three places and remembering a fourth. Srv3ToolAcquisition names the mechanism, Srv3ToolRow pairs it with the tool, and srv3_ensure_tool is the only place a mechanism is chosen -- a total match, so a new mechanism is a variant the compiler refuses to leave unanswered. The ensure folds the rows and the receipt is derived from the same observations, so a tool cannot be ensured and omitted from the receipt, or renamed in one and not the other. require_version_probe moved INSIDE the apt variant rather than sitting beside the acquisition as a peer field. The release path has no version probe to require, so as a peer it was a value one variant silently ignored -- a state the type admitted and the code dropped. Evidence: 4 witnesses green, and each is discriminating. Switching websocat's row from the release mechanism to apt reddens the mechanism witness alone; stripping the tool name out of the receipt entry reddens both receipt witnesses and leaves the mechanism one green. The empty case is stated rather than left to be discovered. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Seal srv3's execution surface so no other module can name it A caller outside gunbc.host_effect_realize could reach srv3_transport_witness_bin_success and srv3_elevated_witness_bin_success directly -- "run this argv on this transport" and "run this argv as root on this transport". Both are now admit_callers-sealed to the functions that legitimately reach them, so a foreign caller can name a semantic operation (ensure this tool, ensure this owner) and cannot name the machinery that executes it. THE SEAL'S REACH IS MEASURED, AND IT IS NARROWER THAN THE NAME SUGGESTS. Two probes on one build: - a caller in ANOTHER module REFUSES at resolve, naming the permitted set: "constructor call admission refused: ... refuses call from 'test.claim.srv3_seal_probe.a_foreign_module_may_not_run_a_privileged_argv' -- permitted callers: [...]" - a caller in THIS module, absent from the admitted list, calling the elevated form with ["/bin/rm", "-rf", "/"], typechecked and resolved with NO DIAGNOSTIC AT ALL. So the rung is mechanically preventable at the module boundary and nothing within it. Reporting only the refusal would be the rung inflation DESIGN section 4b calls worse than sitting low, so both halves are recorded beside the seal with the next-rung trigger: admission checked per caller rather than per module. The admitted lists were derived by walking the module rather than by reading the call sites. My first hand-read attributed two calls to the wrong enclosing function and invented a fifth caller that does not exist -- and because in-module admission is unchecked, nothing would have caught either. A list the compiler does not verify is the second reason that trigger matters. Both probes were removed after measurement: an admission refusal is a resolve-time error, so it cannot be enrolled as a passing witness without breaking the corpus it proves. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Assemble elevated argv with one append instead of a snoc per element Raised as a non-blocking observation on review 54393, and fixed rather than noted: DESIGN section 6's bare-minimum-cost rule says a proven cost shape -- "a copied accumulator, a quadratic fold" is the wording -- is always fixed regardless of the realized n, because "n is small here" is not a time-stable fact. sudo_elevate folded the command argv, appending to a growing accumulator once per element. It is the single place every privileged invocation in the repository is assembled, so its n is whatever a future caller's argv turns out to be, which is exactly the case the rule is about. srv3_argv_with_bin carried the same shape and is fixed with it rather than left as the next instance of a defect just removed. The reviewer's second observation -- that websocat_edge_admits compares stages through websocat_stage_label rather than a structural equality -- is deliberate and stays. A second total projection over the same coproduct would be the fork that function exists to remove. Five witnesses over both argv builders and the acquisition rows re-measured green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Dissolve the last argv literal in the srv3 chain: chmod gets its authority Review 54403 called the surviving "/bin/chmod" literal minor residue and outside this cut's scope. It is the last one in the chain, and leaving one of six is what makes the class get re-derived later -- the operator's standing instruction on this program is that a string in this position is anemic modeling and that the debt is mine to own, so the scope argument cuts the other way here. extdeps.tools.chmod cites POSIX and carries the absolute path for the same reason extdeps.tools.chown and extdeps.tools.mkdir do: a sudoers NOPASSWD rule names a command by path, and chmod sits at /bin rather than /usr/bin on the hosts this actuator targets -- a fact about those hosts, recorded rather than assumed at a call site. The mode is SYMBOLIC and the module says why: `+x` ADDS the execute bit to whatever permissions the file carries, while an octal mode REPLACES the whole set. They are not interchangeable spellings of "make it executable" -- one preserves the other bits and one silently decides them -- and an ensure means the additive one. srv3_transport_argv_success is the argv-shaped sibling of the witness-bin surface. Every extdeps tool row returns a complete argv while that surface takes a binary and its tail separately, so callers were either splitting the argv apart by hand or, more often, not building one at all and passing a literal binary beside a literal args list. It is sealed to its caller like the rest of the execution surface, and it refuses an empty argv rather than running whatever a split of nothing produces. Five witnesses green, including the new chmod row and the two websocat stages that reach it. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Close the same-module hole in admit_callers constructor_call_admission_diags skipped the permitted-list comparison entirely when caller and callee shared a module, so the semantics the compiler implemented were 'a permitted caller OR any declaration in the defining module' -- an implicit wildcard that never appeared in the authored declaration and that no reader of a sealed fn could see. Measured before the repair: a probe added to gunbc.host_effect_realize, absent from the admitted list, calling the elevated execution leaf with ["/bin/rm", "-rf", "/"], typechecked and resolved with no diagnostic at all, while the same call from another module refused. Measured after: same-module unlisted callers now refuse with the existing ConstructorCallAdmissionRefused diagnostic naming the permitted set. The repair deletes the branch and nothing else. The exact caller-coordinate comparison, the diagnostic, and the caller-identity-unavailable arm were all already present and already correct -- the compiler had every fact it needed and declined to use it. The stage0 mirror is the regen candidate, produced by claim_executor --required-regen and installed from it, not hand-carried. required-regen reported drift on exactly one file, v1_compiler_infer.rs, which is the mirror of this change. Operator-admitted (2026-08-21, direct chat: 'regarding the compiler defect, you may fix it'). The permitted lists this surfaces across the corpus follow in the same change. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Admit the sibling constructor route the closed hole exposed Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Ground the build-step chmod invocation on the cited chmod authority Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Answers the operator's directive on the merged #8618:
What the step ladder was
Four steps — parse, regen, regen-fixed-point, floor — each its own process; the order a YAML list; each precondition an
if:naming another step'soutcome; and the fixed-point step receiving pass 1's digest by reading the receipt file the regen process had just written.That last one is the tell.
run_required_regen_fixed_pointhas takenpass1_digest: Option<String>all along, and CI passed itNone— a process boundary sitting where a function call belonged.What runs now
One step. Four phases in one process. The digest handed over in memory.
The behavioural change, stated plainly
Only one real dependency exists. Fixed-point needs regen's pass-1 digest, so it is skipped — visibly, as its own reported state — when there is none. Every other phase runs even after an earlier failure, so the run reports the complete ledger instead of letting the first defect hide the rest. The line still stops (nonzero exit on any failed phase); it stops with every deficit named. Skipped is never silence and never a pass.
The digest is handed over even when regen's comparison disagreed: pass 1 emitted a tree either way, and does the emitter reproduce itself is a separate question from does it match what is committed. Skipping determinism on a regen mismatch would conflate them and lose that signal exactly when drift makes it interesting.
Not claimed
No compile is shared. Regen and its fixed point each call
compile_stage0, and the second call stays — re-emitting and comparing digests is precisely what the fixed point measures, so collapsing it would delete the measurement. The floor's preparation is a different computation again. What this removes is process startup, the receipt round-trip, and the job-level orchestration.One defect I introduced and caught
Recorded because the shape matters more than the fix. Extracting the parse walk from its bin, I dropped the
tests/fixtures/exclusion. The first local run duly reported a parse FAILURE infact_cardinality_split_brace.dag— a headerless fragment that is on main, where the parse step is green. The "finding" was my extraction having silently widened its own subject.Restored verbatim, and the subject is now provably identical to main's: 50 files parse-clean here, 50 in run 32341236470.
One deliberate difference does remain, stated rather than smuggled: the bin used
read_dir.flatten(), which silently discards an unreadable entry — so a walk that never saw a file was indistinguishable from a file that parsed. The error now propagates.Shared, not duplicated
report_required_floor_outcomeandrequired_floor_outcome_is_cleanare extracted so--required-floorand--required-cicannot drift into reporting one outcome two ways, and the five-cause conjunction is written once (§3).Stale recitals updated
A knowingly-false present-tense claim in an authority is premise contamination, so:
gunbc.design_document(twice),gunbc.ci_layer_rootswitness_fold_src_v1_coverage_gap_note, andtools.extdeps_scope_placement_gate. Two other--required-floormentions inci_layer_rootsare dated measurements naming the command as run — they stay true and are untouched.Executed
first_generation_equal=true,fixed_point_equal=truewith no receipt round-trip, floor entered.--required-floorturns the first witnessfalse.cargo check --all-targets,cargo fmt --all --checkclean.Also closed
#8633 (
v1-parse-gate), which had a merge conflict, is closed as fully superseded — its bin was byte-identical to main's, its one finding was already on main, and against main it would have deleted #8618's regen steps and resurrected exclusion rows #8506 deliberately removed.— sent from tidy-lark-471