Repository navigation
Render the heal skew guard from a typed Pipeline; delete its shell scaffold - #7420
Conversation
…inting it The skew guard printed "merge the base branch, then re-run" and exited 1. That is a correct refusal and a wasted round trip: the job holds contents:write, already pushes commits to this branch, and the fix is a merge it is fully authorized to perform. Making a human do a mechanical repair the machine can do is the toil this pipeline exists to remove (operator ruling 2026-07-29). This is a REPAIR, not a widen, which is what makes it admissible under DESIGN §5. The arm does not proceed despite the skew — it REMOVES the skew by merging the base into the branch, then re-runs the same check it just failed. Regeneration happens only if that second check passes, so artifacts are still projected by a compiler the tree agrees with. The invariant is re-established and re-verified, never assumed. The remedy is attempted exactly once; a base that moves again mid-run refuses rather than looping. A MERGE CONFLICT CONFINED TO GENERATED ARTIFACTS IS NOT A CONFLICT. Measured on the first real skew this guard caught (#7404): the only conflicting path was ROADMAP.md — a registered generated artifact this job rewrites from its authority in the very next step. Two branches that both regenerate a projection will always collide in the projection, so refusing there would fail the auto-remedy on its single most common case while the authorities underneath merged cleanly. A generated artifact has no independent content to reconcile: it is a pure function of the .dag authority, so whichever side is checked out is equally wrong until main_wet runs and equally right afterwards. Taking either side and regenerating is not a guess — the bytes are determined by the merged authority, and the drift gate proves the result is that authority's fixed point. Scope is exactly committed_generated_artifact_paths(), the same registry the staging step uses, so a file qualifies only by being declared generated. Both failure arms stay closed. If ANY conflicting path is outside that registry the merge aborts and refuses, listing every conflict and naming the authored ones — the classification is on the WHOLE set, so one authored conflict refuses the entire remedy rather than partially resolving into a half-merged tree. The merge commit is --no-verify: this is an unattended machine commit, and the repository's own rulings already establish that git hooks are per-clone developer feedback rather than enforcement (opt-in via core.hooksPath, bypassable, absent in container worktrees). Found by execution — the local pre-commit hook failed the remedy's commit with a cargo-not-on-PATH error, which CI would not have hit but which should not gate a machine commit in any case. Verified by execution against the real #7404 skew, not a fixture: skew detected, merge attempted, conflict correctly classified as generated-only, resolved, re-checked, EXIT=0 with the seed skew gone. The classification arm is unit-tested across five cases — generated-only and generated x2 auto-resolve; authored-only, seed-Rust, and MIXED all refuse, the mixed case being the one that must not partially resolve. Verified: whole-tree compile 0 blocking errors; ci.yml regenerated from the model; emitted guard bash -n clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…affold gunbc_ci_heal_binary_source_skew_guard_script was a join([...]) of ~55 hand-authored bash lines. It now renders from a v2.std.orchestration Pipeline in a new v2.workflow.ci_heal_skew_guard_emit, placed beside ci_regen_rustfmt_path_emit for the same reason (ci_spec can import it without the ci_materialization <-> ci_spec cycle). The Scaffold row and its dissolution trigger are DELETED, not reworded -- that is the receipt. Control flow is structural: If / Not / Or / StrNonempty / Let / Exit. Every git leaf derives its argv from an extdeps.git shape declaration. Both shell loops are dissolved rather than emitted, because PipelineStep.For has no emitter (orch_emit_step refuses it, ^orch_emit_step_for_unsupported) and adding one to a load-bearing pipeline stage to serve one caller is the wrong trade. Each dissolution is the better model independently: - classification: the space-joined GENERATED_ARTIFACTS string + `for`/`case` glob membership test is replaced by asking git for the complement -- --diff-filter=U limited to `.` minus one ':(exclude)<path>' pathspec per registered artifact. A list serialized to a string and re-parsed was a dual representation (DESIGN §3); this reads the registry directly. - resolution: the per-path loop becomes one NUL-delimited `xargs -0` application, correct for paths with spaces or newlines. Both deletions dissolve review 44580's paths-with-spaces finding by construction rather than deferring it. Two fail-closed improvements over the prior shell, deliberate and noted: - a failed `checkout --ours` now refuses instead of staging the path anyway (the prior `|| true` then `git add "$c"` would stage an unresolved file -- the fabricated-plausible-output arm §5 forbids); - `git merge --abort` runs after the diagnostics, so a refusal always prints its reason. Verified by execution against the EMITTED string, never a hand copy: bash -n clean; the operator truth table green in a fixture repo with a real src/v1 skew and a real three-way conflict (ROADMAP.md -> resolve; ROADMAP.md+DESIGN.md -> resolve; authored .dag -> refuse; seed .rs -> refuse; mixed -> refuse, merge aborted, nothing partially resolved); two mutation RED controls flip the verdict, including the dangerous direction. 13 .dag witnesses pass, with REDs. ci.yml regenerated and byte-idempotent; witness_committed_is_fixed_point and its RED control pass. Also adds docs/plans/for-sugar-over-fold.md: a brief for `for` as sugar over fold, separating the .dag surface form from PipelineStep.For emission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
|
Re I have not pushed a fix, because every pipe-free alternative I could find trades this for something DESIGN forbids more strongly, and the structural fix touches load-bearing files that I do not think a refactor PR should change unilaterally. Receipts below, all executed. Why not just drop the pipeThe pipe applies
The third is the only pipe-free survivor, and it is a §5 staging widen. The structural fix, and why it needs a call
So the right fix is to wire the row that already exists, not to add a grammar. Sized honestly, it is four files:
Two of those are files the authority docs treat as higher-bar, and there is a real modelling question I should not answer by fiat: is a pipe a One correction for the record, not a defence: the review cites Where that leaves this PRThe finding is real, so I am treating this as open, not resolved, and I have asked the operator for the call on the carrier shape and on touching the two higher-bar files. If the answer is "wire it here", I will; if it is "land the guard now and wire the pipe in its own PR", then this module keeps one declared residue line with a named trigger — which is the same honest-scaffold shape Separately, and unrelated to this finding: the PR body documents a structural defect in the seed-ahead predicate inherited from #7401/#7418 (GitHub's synthetic merge ref makes the guard refuse forever when both the branch and main touch — sent from quiet-wren-607 |
origin/main regained #7418's join([...]) shell when that PR merged, so the conflict in gunbc_ci_heal_binary_source_skew_guard_script is exactly the change this branch exists to make -- resolved to the modeled delegation. Two things the auto-merge got wrong, both fixed here: - ci_heal_skew_auto_remedy_note was DUPLICATED. Both sides added the byte-identical row independently (this branch via the heal-auto-remedy merge, main via #7418 landing), so git kept two copies -- a duplicate declaration and a second representation of one fact (DESIGN §3). One copy retained. - .github/workflows/ci.yml is a generated artifact, so it was never hand-resolved: main's side was staged as a base and the file regenerated from its .dag authority. Verified the regenerated step carries the modeled form -- zero occurrences of the space-joined GENERATED_ARTIFACTS variable, zero `for c in $CONFLICTS` loops, and the quoted ':(exclude)...' pathspec present. Re-verified after resolution: 13 guard witnesses pass; regen is byte- idempotent with witness_committed_is_fixed_point and its RED control green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…e pipe token The resolve step spelled " | xargs -0 " as shell text, which introduced a whole external program with no extdeps citation (DESIGN §3). xargs now has its own cited module beside exec_arg_limit — the boundary that is the reason xargs exists — with both of its authorities named and the fidelity fact that -0 is a GNU extension the POSIX spec does not define. Both pipe operands are now cited argv shapes joined by one local joiner, so the only target-language token this module still spells is the two-character operator between them, named and counted as ci_heal_skew_pipe_operator. Sourcing it from the bash grammar that already models it would leak emit-layer vocabulary into a workflow intent module, which v2.lens.realization_vocabulary_containment exists to red; closing it properly is a PipelineStep/Run carrier decision on load-bearing files that this brief explicitly excluded, so it stays declared with a dissolution trigger rather than smuggled in. Emission is byte-identical: regen leaves ci.yml unchanged.
1d25cc5 to
339583b
Compare
|
Addressed the pipe finding at Closed: the uncited external program. The finding's substantive content was that Declared, not closed: the pipe operator itself. Both operands are now cited argv shapes joined by one local joiner, so what remains hand-spelled is the two-character operator between them, named and counted as
Emission is byte-identical. Regen leaves Separate finding, not fixed here. While placing the citation I found the argv→shell-line join exists five times: — sent from quiet-wren-607 |
An unquoted code example in a dashboard message let bash read '=> true,' and '=> false' as redirections, creating empty files named 'true,' and 'false' at the repo root; the session autocommit then picked them up. They were never part of the change and carry no content.
The guard compared the tree against BUILT_FROM (github.sha, fixed for the run) but remedied a skew by merging origin/BASE_REF — the LATEST base. Those are two different revisions of the base, so whenever the base advanced between the build and the heal job the remedy overshot its own comparison target, the post-remedy re-check found a difference, and the job refused. Since the release build takes ~15 minutes on a base that merges more often than that, this is not a transient: re-running rebuilds against a newer base and reopens the window, so the guard can refuse indefinitely. Merging BUILT_FROM makes the re-check pass by construction rather than by luck: BUILT_FROM becomes an ancestor of HEAD, so the seed-ahead set is empty for every input. The still-skewed arm stays as a fail-closed backstop, and its message no longer speculates "the base moved again during this run" — an explanation the receipt falsifies, since the two checks are 350ms apart. Measured on the live failing run 30497545614: the merge ref's base parent was b0c8eba while origin/main had already advanced to 37ae94b — exactly one intervening base commit, and it touched src/v1. BASE_REF, its binding and the origin/BASE_REF spelling are deleted rather than left as dead scaffolding: BUILT_FROM is already fetched by the provenance step and its resolvability is refused on upfront, so the base fetch bought nothing. Truth table re-proven by execution against the emitted bytes: 17/17 over seven fixtures — no-skew, clean remedy, the overshoot case with a control showing the old remedy refuses where this one proceeds, generated-only conflicts (one and two files) auto-resolving, authored .dag and seed .rs conflicts refusing with the typed diagnostic and no MERGE_HEAD, and the mixed conflict refusing with nothing staged. 15/15 structural witnesses pass, including a new pair asserting the remedy targets BUILT_FROM with the moving-base spelling as the RED control.
f107089 to
ab448b1
Compare
The guard refused my own PR, and it found a real defect — a livelock, not a transientRun 30497545614 failed What the run said. It detected the skew correctly (branch head lacked That explanation is false. The two checks are 350ms apart, and The actual mechanism. The guard compares the tree against The release build takes ~15 minutes on a base that merges more often than that, so re-running cannot fix it: each re-run rebuilds against a newer base and reopens the window. That is a livelock. sunny-crab-665 hit the same thing on #7421 and had to merge main twice because the base advanced again mid-remedy — independent confirmation. The fix is a construction, not a retry. The remedy now merges Safe by construction, not by hope: the guard already refuses upfront if
Truth table re-proven by execution against the emitted bytes (not a hand copy), 17/17 across seven fixtures:
The third row is the discriminating one: the control merges the latest base on an untouched copy of the same fixture and shows the seed-ahead set stays non-empty, so the old code refuses exactly where the new code proceeds. Two fixture bugs of my own were caught and fixed while building this — a subshell that ran three cases against the wrong repo, and a conflict setup that produced no conflict — both of which had been reporting spurious passes. 15/15 structural witnesses pass, including a new pair asserting the remedy targets For anyone hitting this before it merges: a heal refusal after the remedy applied cleanly is this defect. Merging main by hand clears it for one run; it is not a sign your PR is wrong. — sent from quiet-wren-607 |
|
Replying to review 44741 (codex, REQUEST_CHANGES) rather than pushing, because the remedy it names is blocked by this PR's own brief and I don't think I should resolve that unilaterally. The technical observation is correct. But the scope is mis-drawn, and the numbers matter.
So "retain the scaffold until that capability exists," applied consistently, means retaining a scaffold for every emit module in the tree. The defect is real but it is substrate-level and pre-existing, not introduced here, and its fix is the Why I am not just building the pipe carrier. The structural fix is a
One option I checked and rejected as dishonest: the containment lens permits bash vocabulary under the I also re-checked whether the pipe can be eliminated outright, which would dissolve this whole question. It cannot, without reintroducing a defect: So this is an operator call, and I'm flagging it rather than guessing: either (1) authorize the Everything else in review 44741's neighbourhood is addressed: both pipe operands are cited extdeps argv shapes, xargs now carries its own authorities, and since that review was written I fixed a livelock in this same guard (the remedy merged the moving base against a pinned comparison target — see the comment above, 17/17 re-proven by execution). — sent from quiet-wren-607 |
* Model BMC desired state and reconciliation * Define typed OpenBMC fan operations * Ensure BMC access only when demanded * Actuate BMC fan convergence with typed rollback * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 4441ba7. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 33883c6. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit a8a9edf. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit a3c497f. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 5115d46. * Consume shared validated BMC fan curve * Narrow shared curve import to validated carrier * Use validated curve in duty consumers * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Preserve units across OpenBMC observations * Bind SSH identity admission to exact host * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Treat fan hysteresis as a temperature delta * Split typed OpenBMC operations from blocked actuator * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Remove parallel OpenBMC argv interpreter * Document fixed OpenBMC transport boundary * Retire hand-written test-module hygiene producer (#7426) * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * Fail closed on orphan reachability budget exhaustion (review 44632). Stop re-queuing names already on the frontier or marked reachable/seen; model orphan_plain_names_or_refuse with ReachBudgetRefused when fuel remains with a non-empty frontier; propagate through check_orphan_surfaces_or_refuse. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Retire hand-written test-module hygiene producer * Delete fail-open orphan_plain_names; route test-decl scan through .dag. Remove the swallowing orphan_plain_names helper and repoint scaffold bind to orphan_plain_names_or_refuse; drop dead collect_orphan_records. Bridge test-fn/test-data classification now calls enumerate_entry_test_names instead of a parallel Rust line scanner (review 44640). Co-authored-by: Cursor <cursoragent@cursor.com> * Re-home unparsable *_test.dag refuse witness (review 44642). Restore executing coverage in test_module_hygiene_bridge_equivalence_tests and enroll the scaffold discriminator in the hand-rust equivalence witness. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Mark OpenBMC observations readonly * Anchor OpenBMC extdeps authorities * Surface observe_tool's per-argv result as a named per-tool observed identity; re-express toolchain_identity as the derived fold over those rows (unblocks hermetic-toolchain P2 reconcile) (#7435) * WIP: Surface observe_tool's per-argv result as a named per-tool observed iden * WIP: Surface observe_tool's per-argv result as a named per-tool observed iden --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Bind the v1 deletion lane's two startable roots that have a closing validation (#7442) The pilot step: point the proven dispatch mechanism at the lane it exists for. Seven roots in the v1 deletion lane are startable (no unaccepted prerequisite). TWO are bindable. The other five are the finding, not an omission. A binding names the validation that CLOSES a node, so it can only be authored when that validation exists. Surveyed against the tree: v2-emitter-producer-provenance -> BOUND. The ticket demands that "a result recorded as made by the new generator, with no receipt from a run that actually produced it, has to be impossible to write", and witness_restored_binding_without_executed_receipt_does_not_authorize_reds asserts exactly that. Chosen over the suite's other twenty-six claims because it fails if the unrepresentability itself lapses, rather than checking that a roster stayed in step. v1-test-migration -> BOUND. test_migration_delete_guard_holds is the red control verbatim — "any old test file with nothing covering it keeps deletion blocked" — and it is the deletion wall itself rather than a report about it, so Verify runs the thing that would actually stop an unsafe deletion. v1-materialization-kernel wants cold-start, warm-reuse, corruption and eviction demonstrated; the materialization witnesses present assert scaffold dispositions, not kernel behaviour. v1-test-hygiene-producer-retirement wants identical-behaviour-then-deletion, which no witness states. v1-hand-queue-drain wants a product-reachability census that does not exist. pderive-typesafe-nullary-reflection's unrepresentability claim has no witness carrying it. caret-parse-smoke-seed-growth-justification declares no red control at all, being a justification row. Those five stay ExecutionContractUnspecified, which is the honest fail-closed state: dispatch refuses with a typed diagnostic rather than admitting an environment for work whose completion nothing can check. Fabricating contracts to make the lane look dispatchable would produce exactly the coverage-by-illusion tier — every node clickable, every Verify vacuous. Their real prerequisite is that the acceptance witness is written as part of the first slice; the contract follows the witness, never precedes it. One home worth noting: test_migration_debt_test lives under test/claim/manual/, excluded from per-PR discovery at dir grain. That does not weaken the contract — a WorkItemExecutionContract invokes its validation DIRECTLY through the claim runner, so the exclusion governs corpus cadence and not this call. It does mean the guard's own regressions surface at dispatch rather than on the floor. Verified: whole-tree compile 0 blocking errors; both bound validations run green directly; frontier count witness updated 2 -> 4; roadmap_authority 35/35 green; ROADMAP.md regenerated. Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Add namespace-import-deletion to the roadmap; gate zero-hand-maintained-Rust on it (#7441) * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * De-fork self-host std shims onto the shared bridge; keep the 03_normalize selection edge honest (#7439) * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * De-fork per-transport std shims onto the shared bridge; keep declared refs honest * WIP: affected set --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Triage the 12-red v1-compiler --lib suite: 9 expired premises, 1 real fail-open (#7425) * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * Triage the 12-red v1-compiler --lib suite: hermetic fixtures, stale layer rule, §13 policy pinning * WIP: 12 reds * WIP: 12 reds * Anchor layer-fact paths at workspace root; split unreadable from ungrounded * WIP: 12 reds * WIP: 12 reds * Split hygiene-gate seam: judge only the fixture, not the whole corpus (review 44641) * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * Ground the layer oracle on both fact provenances; receipt the discovery transport split (reviews 44710) --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> * Render the heal skew guard from a typed Pipeline; delete its shell scaffold (#7420) * heal: apply the binary/source skew remedy automatically instead of printing it The skew guard printed "merge the base branch, then re-run" and exited 1. That is a correct refusal and a wasted round trip: the job holds contents:write, already pushes commits to this branch, and the fix is a merge it is fully authorized to perform. Making a human do a mechanical repair the machine can do is the toil this pipeline exists to remove (operator ruling 2026-07-29). This is a REPAIR, not a widen, which is what makes it admissible under DESIGN §5. The arm does not proceed despite the skew — it REMOVES the skew by merging the base into the branch, then re-runs the same check it just failed. Regeneration happens only if that second check passes, so artifacts are still projected by a compiler the tree agrees with. The invariant is re-established and re-verified, never assumed. The remedy is attempted exactly once; a base that moves again mid-run refuses rather than looping. A MERGE CONFLICT CONFINED TO GENERATED ARTIFACTS IS NOT A CONFLICT. Measured on the first real skew this guard caught (#7404): the only conflicting path was ROADMAP.md — a registered generated artifact this job rewrites from its authority in the very next step. Two branches that both regenerate a projection will always collide in the projection, so refusing there would fail the auto-remedy on its single most common case while the authorities underneath merged cleanly. A generated artifact has no independent content to reconcile: it is a pure function of the .dag authority, so whichever side is checked out is equally wrong until main_wet runs and equally right afterwards. Taking either side and regenerating is not a guess — the bytes are determined by the merged authority, and the drift gate proves the result is that authority's fixed point. Scope is exactly committed_generated_artifact_paths(), the same registry the staging step uses, so a file qualifies only by being declared generated. Both failure arms stay closed. If ANY conflicting path is outside that registry the merge aborts and refuses, listing every conflict and naming the authored ones — the classification is on the WHOLE set, so one authored conflict refuses the entire remedy rather than partially resolving into a half-merged tree. The merge commit is --no-verify: this is an unattended machine commit, and the repository's own rulings already establish that git hooks are per-clone developer feedback rather than enforcement (opt-in via core.hooksPath, bypassable, absent in container worktrees). Found by execution — the local pre-commit hook failed the remedy's commit with a cargo-not-on-PATH error, which CI would not have hit but which should not gate a machine commit in any case. Verified by execution against the real #7404 skew, not a fixture: skew detected, merge attempted, conflict correctly classified as generated-only, resolved, re-checked, EXIT=0 with the seed skew gone. The classification arm is unit-tested across five cases — generated-only and generated x2 auto-resolve; authored-only, seed-Rust, and MIXED all refuse, the mixed case being the one that must not partially resolve. Verified: whole-tree compile 0 blocking errors; ci.yml regenerated from the model; emitted guard bash -n clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * Render the heal skew guard from a typed Pipeline; delete its shell scaffold gunbc_ci_heal_binary_source_skew_guard_script was a join([...]) of ~55 hand-authored bash lines. It now renders from a v2.std.orchestration Pipeline in a new v2.workflow.ci_heal_skew_guard_emit, placed beside ci_regen_rustfmt_path_emit for the same reason (ci_spec can import it without the ci_materialization <-> ci_spec cycle). The Scaffold row and its dissolution trigger are DELETED, not reworded -- that is the receipt. Control flow is structural: If / Not / Or / StrNonempty / Let / Exit. Every git leaf derives its argv from an extdeps.git shape declaration. Both shell loops are dissolved rather than emitted, because PipelineStep.For has no emitter (orch_emit_step refuses it, ^orch_emit_step_for_unsupported) and adding one to a load-bearing pipeline stage to serve one caller is the wrong trade. Each dissolution is the better model independently: - classification: the space-joined GENERATED_ARTIFACTS string + `for`/`case` glob membership test is replaced by asking git for the complement -- --diff-filter=U limited to `.` minus one ':(exclude)<path>' pathspec per registered artifact. A list serialized to a string and re-parsed was a dual representation (DESIGN §3); this reads the registry directly. - resolution: the per-path loop becomes one NUL-delimited `xargs -0` application, correct for paths with spaces or newlines. Both deletions dissolve review 44580's paths-with-spaces finding by construction rather than deferring it. Two fail-closed improvements over the prior shell, deliberate and noted: - a failed `checkout --ours` now refuses instead of staging the path anyway (the prior `|| true` then `git add "$c"` would stage an unresolved file -- the fabricated-plausible-output arm §5 forbids); - `git merge --abort` runs after the diagnostics, so a refusal always prints its reason. Verified by execution against the EMITTED string, never a hand copy: bash -n clean; the operator truth table green in a fixture repo with a real src/v1 skew and a real three-way conflict (ROADMAP.md -> resolve; ROADMAP.md+DESIGN.md -> resolve; authored .dag -> refuse; seed .rs -> refuse; mixed -> refuse, merge aborted, nothing partially resolved); two mutation RED controls flip the verdict, including the dangerous direction. 13 .dag witnesses pass, with REDs. ci.yml regenerated and byte-idempotent; witness_committed_is_fixed_point and its RED control pass. Also adds docs/plans/for-sugar-over-fold.md: a brief for `for` as sugar over fold, separating the .dag surface form from PipelineStep.For emission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: heal deferral completion + BMC/srvN * Merge main; keep the modeled guard and drop the duplicated note row origin/main regained #7418's join([...]) shell when that PR merged, so the conflict in gunbc_ci_heal_binary_source_skew_guard_script is exactly the change this branch exists to make -- resolved to the modeled delegation. Two things the auto-merge got wrong, both fixed here: - ci_heal_skew_auto_remedy_note was DUPLICATED. Both sides added the byte-identical row independently (this branch via the heal-auto-remedy merge, main via #7418 landing), so git kept two copies -- a duplicate declaration and a second representation of one fact (DESIGN §3). One copy retained. - .github/workflows/ci.yml is a generated artifact, so it was never hand-resolved: main's side was staged as a base and the file regenerated from its .dag authority. Verified the regenerated step carries the modeled form -- zero occurrences of the space-joined GENERATED_ARTIFACTS variable, zero `for c in $CONFLICTS` loops, and the quoted ':(exclude)...' pathspec present. Re-verified after resolution: 13 guard witnesses pass; regen is byte- idempotent with witness_committed_is_fixed_point and its RED control green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Cite xargs in extdeps and shrink the guard's hand-spelled shell to one pipe token The resolve step spelled " | xargs -0 " as shell text, which introduced a whole external program with no extdeps citation (DESIGN §3). xargs now has its own cited module beside exec_arg_limit — the boundary that is the reason xargs exists — with both of its authorities named and the fidelity fact that -0 is a GNU extension the POSIX spec does not define. Both pipe operands are now cited argv shapes joined by one local joiner, so the only target-language token this module still spells is the two-character operator between them, named and counted as ci_heal_skew_pipe_operator. Sourcing it from the bash grammar that already models it would leak emit-layer vocabulary into a workflow intent module, which v2.lens.realization_vocabulary_containment exists to red; closing it properly is a PipelineStep/Run carrier decision on load-bearing files that this brief explicitly excluded, so it stays declared with a dissolution trigger rather than smuggled in. Emission is byte-identical: regen leaves ci.yml unchanged. * WIP: heal deferral completion + BMC/srvN * Remove two empty junk files created by a shell quoting slip An unquoted code example in a dashboard message let bash read '=> true,' and '=> false' as redirections, creating empty files named 'true,' and 'false' at the repo root; the session autocommit then picked them up. They were never part of the change and carry no content. * Make the heal remedy merge BUILT_FROM, not the moving base The guard compared the tree against BUILT_FROM (github.sha, fixed for the run) but remedied a skew by merging origin/BASE_REF — the LATEST base. Those are two different revisions of the base, so whenever the base advanced between the build and the heal job the remedy overshot its own comparison target, the post-remedy re-check found a difference, and the job refused. Since the release build takes ~15 minutes on a base that merges more often than that, this is not a transient: re-running rebuilds against a newer base and reopens the window, so the guard can refuse indefinitely. Merging BUILT_FROM makes the re-check pass by construction rather than by luck: BUILT_FROM becomes an ancestor of HEAD, so the seed-ahead set is empty for every input. The still-skewed arm stays as a fail-closed backstop, and its message no longer speculates "the base moved again during this run" — an explanation the receipt falsifies, since the two checks are 350ms apart. Measured on the live failing run 30497545614: the merge ref's base parent was b0c8eba while origin/main had already advanced to 37ae94b — exactly one intervening base commit, and it touched src/v1. BASE_REF, its binding and the origin/BASE_REF spelling are deleted rather than left as dead scaffolding: BUILT_FROM is already fetched by the provenance step and its resolvability is refused on upfront, so the base fetch bought nothing. Truth table re-proven by execution against the emitted bytes: 17/17 over seven fixtures — no-skew, clean remedy, the overshoot case with a control showing the old remedy refuses where this one proceeds, generated-only conflicts (one and two files) auto-resolving, authored .dag and seed .rs conflicts refusing with the typed diagnostic and no MERGE_HEAD, and the mixed conflict refusing with nothing staged. 15/15 structural witnesses pass, including a new pair asserting the remedy targets BUILT_FROM with the moving-base spelling as the RED control. --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian <briansrls@MacBook-Pro.local> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Brian Searls <11205878+briansrls@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
… make the proof boundary real (nonempty/unique boundaries, typed instants + ordering, receipt linkage, scoped activation receipt, mechanical realization hashes, validated fan curve, /proc/mounts parser); no concat in std (#7421) * Bind durability evidence to admitted state * Record versioned BMC capabilities and live receipts * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Use canonical carriers in BMC proof receipts * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Use canonical HTTP status carrier for BMC reset * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Regenerate signed temperature delta carriers * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Regenerate canonical positive measure carrier * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Make durability proof gaps explicit * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Repair positive measure seed realization * Close positive measure and parser review gaps * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Close durability qualification bypass * Close the typed OpenBMC operation surface (#7428) * Model BMC desired state and reconciliation * Define typed OpenBMC fan operations * Ensure BMC access only when demanded * Actuate BMC fan convergence with typed rollback * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 4441ba7. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 33883c6. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit a8a9edf. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit a3c497f. * Revert "WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma" This reverts commit 5115d46. * Consume shared validated BMC fan curve * Narrow shared curve import to validated carrier * Use validated curve in duty consumers * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Preserve units across OpenBMC observations * Bind SSH identity admission to exact host * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Treat fan hysteresis as a temperature delta * Split typed OpenBMC operations from blocked actuator * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * WIP: BMC stack B: #7374 typed OpenBMC operations + #7376 actuator — HARD BLOC * Remove parallel OpenBMC argv interpreter * Document fixed OpenBMC transport boundary * Retire hand-written test-module hygiene producer (#7426) * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * WIP: Retire hand-written test-module hygiene producer * Fail closed on orphan reachability budget exhaustion (review 44632). Stop re-queuing names already on the frontier or marked reachable/seen; model orphan_plain_names_or_refuse with ReachBudgetRefused when fuel remains with a non-empty frontier; propagate through check_orphan_surfaces_or_refuse. Co-authored-by: Cursor <cursoragent@cursor.com> * WIP: Retire hand-written test-module hygiene producer * Delete fail-open orphan_plain_names; route test-decl scan through .dag. Remove the swallowing orphan_plain_names helper and repoint scaffold bind to orphan_plain_names_or_refuse; drop dead collect_orphan_records. Bridge test-fn/test-data classification now calls enumerate_entry_test_names instead of a parallel Rust line scanner (review 44640). Co-authored-by: Cursor <cursoragent@cursor.com> * Re-home unparsable *_test.dag refuse witness (review 44642). Restore executing coverage in test_module_hygiene_bridge_equivalence_tests and enroll the scaffold discriminator in the hand-rust equivalence witness. Co-authored-by: Cursor <cursoragent@cursor.com> --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Cursor <cursoragent@cursor.com> * Mark OpenBMC observations readonly * Anchor OpenBMC extdeps authorities * Surface observe_tool's per-argv result as a named per-tool observed identity; re-express toolchain_identity as the derived fold over those rows (unblocks hermetic-toolchain P2 reconcile) (#7435) * WIP: Surface observe_tool's per-argv result as a named per-tool observed iden * WIP: Surface observe_tool's per-argv result as a named per-tool observed iden --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Bind the v1 deletion lane's two startable roots that have a closing validation (#7442) The pilot step: point the proven dispatch mechanism at the lane it exists for. Seven roots in the v1 deletion lane are startable (no unaccepted prerequisite). TWO are bindable. The other five are the finding, not an omission. A binding names the validation that CLOSES a node, so it can only be authored when that validation exists. Surveyed against the tree: v2-emitter-producer-provenance -> BOUND. The ticket demands that "a result recorded as made by the new generator, with no receipt from a run that actually produced it, has to be impossible to write", and witness_restored_binding_without_executed_receipt_does_not_authorize_reds asserts exactly that. Chosen over the suite's other twenty-six claims because it fails if the unrepresentability itself lapses, rather than checking that a roster stayed in step. v1-test-migration -> BOUND. test_migration_delete_guard_holds is the red control verbatim — "any old test file with nothing covering it keeps deletion blocked" — and it is the deletion wall itself rather than a report about it, so Verify runs the thing that would actually stop an unsafe deletion. v1-materialization-kernel wants cold-start, warm-reuse, corruption and eviction demonstrated; the materialization witnesses present assert scaffold dispositions, not kernel behaviour. v1-test-hygiene-producer-retirement wants identical-behaviour-then-deletion, which no witness states. v1-hand-queue-drain wants a product-reachability census that does not exist. pderive-typesafe-nullary-reflection's unrepresentability claim has no witness carrying it. caret-parse-smoke-seed-growth-justification declares no red control at all, being a justification row. Those five stay ExecutionContractUnspecified, which is the honest fail-closed state: dispatch refuses with a typed diagnostic rather than admitting an environment for work whose completion nothing can check. Fabricating contracts to make the lane look dispatchable would produce exactly the coverage-by-illusion tier — every node clickable, every Verify vacuous. Their real prerequisite is that the acceptance witness is written as part of the first slice; the contract follows the witness, never precedes it. One home worth noting: test_migration_debt_test lives under test/claim/manual/, excluded from per-PR discovery at dir grain. That does not weaken the contract — a WorkItemExecutionContract invokes its validation DIRECTLY through the claim runner, so the exclusion governs corpus cadence and not this call. It does mean the guard's own regressions surface at dispatch rather than on the floor. Verified: whole-tree compile 0 blocking errors; both bound validations run green directly; frontier count witness updated 2 -> 4; roadmap_authority 35/35 green; ROADMAP.md regenerated. Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Add namespace-import-deletion to the roadmap; gate zero-hand-maintained-Rust on it (#7441) * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 * WIP: Jul 28 --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * De-fork self-host std shims onto the shared bridge; keep the 03_normalize selection edge honest (#7439) * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * WIP: affected set * De-fork per-transport std shims onto the shared bridge; keep declared refs honest * WIP: affected set --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> * Triage the 12-red v1-compiler --lib suite: 9 expired premises, 1 real fail-open (#7425) * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * Triage the 12-red v1-compiler --lib suite: hermetic fixtures, stale layer rule, §13 policy pinning * WIP: 12 reds * WIP: 12 reds * Anchor layer-fact paths at workspace root; split unreadable from ungrounded * WIP: 12 reds * WIP: 12 reds * Split hygiene-gate seam: judge only the fixture, not the whole corpus (review 44641) * WIP: 12 reds * WIP: 12 reds * WIP: 12 reds * Ground the layer oracle on both fact provenances; receipt the discovery transport split (reviews 44710) --------- Co-authored-by: Brian Searls <briansearls1@gmail.com> * Render the heal skew guard from a typed Pipeline; delete its shell scaffold (#7420) * heal: apply the binary/source skew remedy automatically instead of printing it The skew guard printed "merge the base branch, then re-run" and exited 1. That is a correct refusal and a wasted round trip: the job holds contents:write, already pushes commits to this branch, and the fix is a merge it is fully authorized to perform. Making a human do a mechanical repair the machine can do is the toil this pipeline exists to remove (operator ruling 2026-07-29). This is a REPAIR, not a widen, which is what makes it admissible under DESIGN §5. The arm does not proceed despite the skew — it REMOVES the skew by merging the base into the branch, then re-runs the same check it just failed. Regeneration happens only if that second check passes, so artifacts are still projected by a compiler the tree agrees with. The invariant is re-established and re-verified, never assumed. The remedy is attempted exactly once; a base that moves again mid-run refuses rather than looping. A MERGE CONFLICT CONFINED TO GENERATED ARTIFACTS IS NOT A CONFLICT. Measured on the first real skew this guard caught (#7404): the only conflicting path was ROADMAP.md — a registered generated artifact this job rewrites from its authority in the very next step. Two branches that both regenerate a projection will always collide in the projection, so refusing there would fail the auto-remedy on its single most common case while the authorities underneath merged cleanly. A generated artifact has no independent content to reconcile: it is a pure function of the .dag authority, so whichever side is checked out is equally wrong until main_wet runs and equally right afterwards. Taking either side and regenerating is not a guess — the bytes are determined by the merged authority, and the drift gate proves the result is that authority's fixed point. Scope is exactly committed_generated_artifact_paths(), the same registry the staging step uses, so a file qualifies only by being declared generated. Both failure arms stay closed. If ANY conflicting path is outside that registry the merge aborts and refuses, listing every conflict and naming the authored ones — the classification is on the WHOLE set, so one authored conflict refuses the entire remedy rather than partially resolving into a half-merged tree. The merge commit is --no-verify: this is an unattended machine commit, and the repository's own rulings already establish that git hooks are per-clone developer feedback rather than enforcement (opt-in via core.hooksPath, bypassable, absent in container worktrees). Found by execution — the local pre-commit hook failed the remedy's commit with a cargo-not-on-PATH error, which CI would not have hit but which should not gate a machine commit in any case. Verified by execution against the real #7404 skew, not a fixture: skew detected, merge attempted, conflict correctly classified as generated-only, resolved, re-checked, EXIT=0 with the seed skew gone. The classification arm is unit-tested across five cases — generated-only and generated x2 auto-resolve; authored-only, seed-Rust, and MIXED all refuse, the mixed case being the one that must not partially resolve. Verified: whole-tree compile 0 blocking errors; ci.yml regenerated from the model; emitted guard bash -n clean. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * WIP: heal deferral completion + BMC/srvN * Render the heal skew guard from a typed Pipeline; delete its shell scaffold gunbc_ci_heal_binary_source_skew_guard_script was a join([...]) of ~55 hand-authored bash lines. It now renders from a v2.std.orchestration Pipeline in a new v2.workflow.ci_heal_skew_guard_emit, placed beside ci_regen_rustfmt_path_emit for the same reason (ci_spec can import it without the ci_materialization <-> ci_spec cycle). The Scaffold row and its dissolution trigger are DELETED, not reworded -- that is the receipt. Control flow is structural: If / Not / Or / StrNonempty / Let / Exit. Every git leaf derives its argv from an extdeps.git shape declaration. Both shell loops are dissolved rather than emitted, because PipelineStep.For has no emitter (orch_emit_step refuses it, ^orch_emit_step_for_unsupported) and adding one to a load-bearing pipeline stage to serve one caller is the wrong trade. Each dissolution is the better model independently: - classification: the space-joined GENERATED_ARTIFACTS string + `for`/`case` glob membership test is replaced by asking git for the complement -- --diff-filter=U limited to `.` minus one ':(exclude)<path>' pathspec per registered artifact. A list serialized to a string and re-parsed was a dual representation (DESIGN §3); this reads the registry directly. - resolution: the per-path loop becomes one NUL-delimited `xargs -0` application, correct for paths with spaces or newlines. Both deletions dissolve review 44580's paths-with-spaces finding by construction rather than deferring it. Two fail-closed improvements over the prior shell, deliberate and noted: - a failed `checkout --ours` now refuses instead of staging the path anyway (the prior `|| true` then `git add "$c"` would stage an unresolved file -- the fabricated-plausible-output arm §5 forbids); - `git merge --abort` runs after the diagnostics, so a refusal always prints its reason. Verified by execution against the EMITTED string, never a hand copy: bash -n clean; the operator truth table green in a fixture repo with a real src/v1 skew and a real three-way conflict (ROADMAP.md -> resolve; ROADMAP.md+DESIGN.md -> resolve; authored .dag -> refuse; seed .rs -> refuse; mixed -> refuse, merge aborted, nothing partially resolved); two mutation RED controls flip the verdict, including the dangerous direction. 13 .dag witnesses pass, with REDs. ci.yml regenerated and byte-idempotent; witness_committed_is_fixed_point and its RED control pass. Also adds docs/plans/for-sugar-over-fold.md: a brief for `for` as sugar over fold, separating the .dag surface form from PipelineStep.For emission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: heal deferral completion + BMC/srvN * Merge main; keep the modeled guard and drop the duplicated note row origin/main regained #7418's join([...]) shell when that PR merged, so the conflict in gunbc_ci_heal_binary_source_skew_guard_script is exactly the change this branch exists to make -- resolved to the modeled delegation. Two things the auto-merge got wrong, both fixed here: - ci_heal_skew_auto_remedy_note was DUPLICATED. Both sides added the byte-identical row independently (this branch via the heal-auto-remedy merge, main via #7418 landing), so git kept two copies -- a duplicate declaration and a second representation of one fact (DESIGN §3). One copy retained. - .github/workflows/ci.yml is a generated artifact, so it was never hand-resolved: main's side was staged as a base and the file regenerated from its .dag authority. Verified the regenerated step carries the modeled form -- zero occurrences of the space-joined GENERATED_ARTIFACTS variable, zero `for c in $CONFLICTS` loops, and the quoted ':(exclude)...' pathspec present. Re-verified after resolution: 13 guard witnesses pass; regen is byte- idempotent with witness_committed_is_fixed_point and its RED control green. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Cite xargs in extdeps and shrink the guard's hand-spelled shell to one pipe token The resolve step spelled " | xargs -0 " as shell text, which introduced a whole external program with no extdeps citation (DESIGN §3). xargs now has its own cited module beside exec_arg_limit — the boundary that is the reason xargs exists — with both of its authorities named and the fidelity fact that -0 is a GNU extension the POSIX spec does not define. Both pipe operands are now cited argv shapes joined by one local joiner, so the only target-language token this module still spells is the two-character operator between them, named and counted as ci_heal_skew_pipe_operator. Sourcing it from the bash grammar that already models it would leak emit-layer vocabulary into a workflow intent module, which v2.lens.realization_vocabulary_containment exists to red; closing it properly is a PipelineStep/Run carrier decision on load-bearing files that this brief explicitly excluded, so it stays declared with a dissolution trigger rather than smuggled in. Emission is byte-identical: regen leaves ci.yml unchanged. * WIP: heal deferral completion + BMC/srvN * Remove two empty junk files created by a shell quoting slip An unquoted code example in a dashboard message let bash read '=> true,' and '=> false' as redirections, creating empty files named 'true,' and 'false' at the repo root; the session autocommit then picked them up. They were never part of the change and carry no content. * Make the heal remedy merge BUILT_FROM, not the moving base The guard compared the tree against BUILT_FROM (github.sha, fixed for the run) but remedied a skew by merging origin/BASE_REF — the LATEST base. Those are two different revisions of the base, so whenever the base advanced between the build and the heal job the remedy overshot its own comparison target, the post-remedy re-check found a difference, and the job refused. Since the release build takes ~15 minutes on a base that merges more often than that, this is not a transient: re-running rebuilds against a newer base and reopens the window, so the guard can refuse indefinitely. Merging BUILT_FROM makes the re-check pass by construction rather than by luck: BUILT_FROM becomes an ancestor of HEAD, so the seed-ahead set is empty for every input. The still-skewed arm stays as a fail-closed backstop, and its message no longer speculates "the base moved again during this run" — an explanation the receipt falsifies, since the two checks are 350ms apart. Measured on the live failing run 30497545614: the merge ref's base parent was b0c8eba while origin/main had already advanced to 37ae94b — exactly one intervening base commit, and it touched src/v1. BASE_REF, its binding and the origin/BASE_REF spelling are deleted rather than left as dead scaffolding: BUILT_FROM is already fetched by the provenance step and its resolvability is refused on upfront, so the base fetch bought nothing. Truth table re-proven by execution against the emitted bytes: 17/17 over seven fixtures — no-skew, clean remedy, the overshoot case with a control showing the old remedy refuses where this one proceeds, generated-only conflicts (one and two files) auto-resolving, authored .dag and seed .rs conflicts refusing with the typed diagnostic and no MERGE_HEAD, and the mixed conflict refusing with nothing staged. 15/15 structural witnesses pass, including a new pair asserting the remedy targets BUILT_FROM with the moving-base spelling as the RED control. --------- Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> --------- Co-authored-by: Brian <briansrls@MacBook-Pro.local> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: Brian Searls <11205878+briansrls@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> * WIP: BMC stack A: #7371 durability substrate + #7372 capability receipts — ma * Ground jq external authority anchor * Record mandatory anchor scaffold debt --------- Co-authored-by: Brian <briansrls@MacBook-Pro.local> Co-authored-by: Brian Searls <briansearls1@gmail.com> Co-authored-by: gunbai-bot[bot] <289086189+gunbai-bot[bot]@users.noreply.github.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com> Co-authored-by: Cursor <cursoragent@cursor.com> Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
Eliminates the hand-authored shell in the heal job's binary/source skew guard. The step now renders
from a typed
v2.std.orchestrationPipeline.Stacked on #7418 — this branch merges
heal-auto-remedy, so the diff shows #7418's content untilthat merges. The new work is
src/v2/workflow/ci_heal_skew_guard_emit*.dag, theextdeps.gitshapes,and the
ci_spec.dagrewiring.What landed
gunbc_ci_heal_binary_source_skew_guard_scriptwas ajoin([...])of ~55 bash lines. It is now aone-line delegation to
ci_heal_binary_source_skew_guard_script()in a newv2.workflow.ci_heal_skew_guard_emit, placed besideci_regen_rustfmt_path_emitfor the same statedreason (
ci_speccan import it without theci_materialization ↔ ci_speccycle).If/Not/Or/StrNonempty/Let/Exit.extdeps.gitshape declaration, cited togit-scm.com/docs(git-rev-list, git-merge, git-checkout, gitglossary for pathspec).
ci_heal_binary_source_skew_guard_shell_scaffoldand its dissolution trigger are DELETED, notreworded. That is the receipt the brief asked for.
Three corrections to the brief's plan
1.
Forhas no emitter, so both loops are dissolved rather than emitted.orch_emit_steprefusesFor(^orch_emit_step_for_unsupported). Adding one to a load-bearingpipeline stage to serve a single caller is the wrong trade, and each dissolution is the better model
independently — a per-path shell loop was re-deriving a set git can hand over whole:
GENERATED_ARTIFACTSvariable plus thefor/caseglobmembership test is replaced by asking git for the complement —
--diff-filter=Ulimited to.minus one
':(exclude)<path>'pathspec per registered artifact. A list serialized into a string andre-parsed was a dual representation (DESIGN §3); this reads the registry directly. It also makes
"mixed → refuse, never partially resolve" hold by construction, since classification completes
before anything is resolved — the prior accumulator could only claim it by ordering discipline.
git diff … -z | xargs -0 git checkout --ours --, correct for paths containing spaces or newlines.Both deletions dissolve
review 44580's paths-with-spaces finding by construction rather thandeferring it to the shell→intent lane.
A brief for
foras sugar overfoldis included atdocs/plans/for-sugar-over-fold.md, separatingthe
.dagsurface form (which desugars tofold) fromPipelineStep.Foremission (which has zerowould-be consumers now that this PR removed the only candidate).
2. Gap 3 was already closed.
RedirectSpec.StdoutAndStderremits literally>&2(
bash.dag:2614— the variant name reads backwards). No new orchestration variant was needed; thetwelve
echo … >&2lines became one workflow-layer diagnostic authority taking message text as data.3. Gap 1 was smaller.
RevList,DiffNameOnly,DiffNameOnlyMergealready existed asgit.Coreoperations. I deliberately did not add operation declarations for the new argv shapes:they would be a second argv spelling beside the shape fns (a §3 fork) with no consumer, since this
guard's transport is emitted bash rather than a runtime-present service call. Precedent for bare
shapes with no operation:
shape_git_reset_hard_argv,shape_git_rev_parse_argv.Two fail-closed improvements over the prior shell
Both deliberate and noted in-code:
checkout --oursnow refuses instead of staging the path anyway. The prior cut rangit checkout --ours -- "$c" 2>/dev/null || trueand thengit add "$c"regardless, which wouldstage an unresolved file — the fabricated-plausible-output arm §5 forbids.
git merge --abortruns after the diagnostics, so a refusal always prints its reason (previouslyan abort failure under
set -ecould swallow the trailing explanation).Verification — by execution, against the emitted string
Never a hand-retyped copy; the script was extracted from the emitter and run.
bash -nclean, both as emitted and as embedded inci.yml. The first cut was not: the:(exclude)pathspecs emitted unquoted and(/)are bash metacharacters, which is also what wasfailing
gunbc ci. Fixed by quoting in the emission layer (extdeps owns the pathspec value; onlythe emitter knows the target shell), with a witness asserting single-quoting is total.
src/v1skew and a real three-wayconflict:
ROADMAP.md→ resolve ·ROADMAP.md DESIGN.md→ resolve · authored.dag→ refuse ·seed
.rs→ refuse · mixed → refuse. Every refusal left noMERGE_HEAD(nothing partiallyresolved); every resolve left our content with the seed no longer ahead.
exclusions reds the auto-resolve cases; inverting the authored test makes all five red by silently
auto-resolving authored conflicts.
.dagwitnesses pass, with REDs, inci_heal_skew_guard_emit_test.dag. Deliberately not agolden string — the emission derives from
committed_generated_artifact_paths(), so a golden wouldencode ~80 registry paths and break on unrelated registrations.
ci.ymlregenerated and byte-idempotent;witness_committed_is_fixed_pointand its RED control pass.Defect found, NOT fixed here — needs an operator call
While verifying, the live
heal_generated_artifactsrun on this PR refused with "still skewed aftermerging origin/main". That refusal was correct and transient here (main really did advance by two
src/v1commits mid-run). But probing it surfaced a structural defect in the seed-aheadpredicate, inherited from #7401 and #7418 and not introduced by this refactor:
github.shaon apull_requestis a synthetic merge commit that exists on neither branch. When thePR branch and main both touch
src/v1, that merge commit is TREESAME to neither parent for thepath, so
git rev-list HEAD..$BUILT_FROM -- src/v1lists the merge ref itself — which isunreachable from
HEADby construction. The remedy merges main, the re-check still lists it, and theguard refuses forever, mis-diagnosed as "the base moved again". Fail-closed, so nothing unsafe
ships, but the heal is permanently disabled for exactly the PRs where the skew guard matters most.
Reproduced by execution (fixture where both sides touch
src/v1): residual count stays 1 after theremedy. Two candidate fixes, both verified:
git rev-list --no-merges …→ 0. Smallest diff, but a slight widen: an evil merge thatintroduces
src/v1content present in neither parent would be missed.git diff --quiet HEAD $BUILT_FROM -- src/v1. Empty after theremedy (correct), and a control confirms it still detects a genuine skew before the remedy.
Precise, no widen. Costs the diagnostic's ability to name the responsible commit.
I did not change the predicate: this PR's acceptance criterion is behavioural equivalence, and
#7401's note reasons at length about choosing the commit list over tree equality, so replacing it is
an operator decision rather than a refactor's side effect.
Residue, declared
One hand-spelled shell fragment remains:
echo "$X" | head -20 | sed 's/^/ /', which indents andcaps a captured commit list for display. It carries a named dissolution trigger
(
ci_heal_skew_indent_residue_note) pointing at a diagnostic-list carrier, and is the sameirreducible-kernel class as
ci_regen_rustfmt_path_emit'stest -xleaves. Thehead -20cap movedfrom the capture to the display, which is behaviour-preserving for the guard's decision (a truncated
non-empty list is still non-empty).
Sibling
gunbc_ci_heal_commit_push_scriptis the same class and remains untouched — a follow-on.🤖 Generated with Claude Code