Repository navigation
Conversation
|
Bugbot is not enabled for your account, so this pull request was not reviewed. Enable Bugbot in the Cursor dashboard to get automatic reviews on future PRs. |
…sing everywhere Every roadmap node was ExecutionContractUnspecified, so dispatch_environment_admit matched that arm and refused before doing anything else. Clicking Dispatch on any of the ~46 tickets produced a typed refusal and nothing more, which meant no part of the workflow below Env — worktree, agent, and every receipt that depends on them — had ever executed end to end in production. The frontier reached zero when the 2026-07-27 authority refresh deleted the node that carried the prior binding; no claim noticed, because none existed. The binding is a COMBINATOR, not a constructor parameter. `sign` is the precedent sitting beside it and already threads `execution: rn.execution` through untouched; threading an execution argument instead would edit seven constructors and every one of their call sites to express a fact that today holds for exactly one node. A node without the wrapper keeps ExecutionContractUnspecified, which stays the fail-closed refusal the frontier note declares rather than a default anyone chose. shell-typed-invocation is bound to the transport-clean corpus witness (corpus_dag_compile_clean_transport_clean_holds), which is this ticket's own red control expressed as an operation: "a new unclassified production construction site reds the census". It reads the live tree, so it is a statement about the repository rather than a fixture. That validation is ALREADY GREEN, deliberately. A first binding has two jobs that pull apart — prove the Verify path runs at all, and prove it discriminates — and conflating them is how a green pipeline gets mistaken for a working one. This row takes the first job only: an Agent turn that changes nothing still produces a real admitted environment, a real derived command, and a real validation receipt, which is a statement about the PLUMBING and not about the provider. It proves nothing about discrimination and must not be read as evidence that Verify can fail; the discriminating red belongs on a second node whose validation is currently red and goes green when the work lands, and that is the next binding, not this one. The frontier note is corrected in the same motion. It read "Every node below is ExecutionContractUnspecified", which was true when written and false the moment one was bound. It now states the count is one, and that a count is not a completion. Three witnesses pin both halves of the frontier: the bound node yields a real contract rather than the fail-closed variant; the platform/task capability JOIN actually happens at admission (8 fixed dispatch mechanics + the one capability this validation derives = 9); and the frontier is exactly one node — which fails if a binding is silently lost AND if a second is added without updating the roster, so the documented count cannot drift from the authority. ROADMAP.md is unchanged: execution contracts are dispatch mechanics, not roadmap content, and the projection correctly does not render them. Verified: whole-tree compile 0 blocking errors; 46 witnesses green across roadmap_authority (incl. the three new ones and the pre-existing re-entry RED controls), generated_artifact_drift, roadmap_execution_contract, and roadmap_dispatch_environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…n actually fail The first binding named an already-green validation, on purpose, to prove the Verify path executes at all — admission, argv derivation, receipt production. It cannot prove the path DISCRIMINATES, because nothing it runs is capable of returning anything but green. A frontier with only that binding is the coverage-by-illusion tier: machinery present, nothing gating on it. observation-raw-print-retirement now binds a validation that FAILS today. gunbc.observation_emit_census classifies every seed emit site as exactly one of MigratedToObservation or CountedFrontierSite, and observation_emit_frontier_count is the population of the second arm — 8 today (floor-drain, gate-warm-cost, receipt, file, resolve-split, assembly-split, witness-row-cost, witness-row-cost-drift). The witness asserts 0, which is that node's handback stated verbatim: "the classified zero-residue progress census". So the red is the ticket's own acceptance condition rather than a planted fixture, the count IS the completion condition rather than a proxy for it, and red -> green is the work being finished. The two bindings now pin both directions, and neither claim is obtainable from the other. Finding a genuine red took some looking, and the search is worth recording: the transport-script wall is clean corpus-wide (every enrolled path AND every unenrolled Exec.Run site I measured returns zero violations), so there was no red available there; the existing known-red quarantine rows are self-host behavioral receipts that red on cargo/shim closure refusal, which is infrastructure rather than anything a dispatched agent could turn green. The emit census is the one place where a small, agent-doable ticket has a countable completion condition that is currently false. The acceptance witness is enrolled QuarantineProbeExpectRed in gunbc.ci_layer_roots — the cadence std.witness_admission defines for exactly this, "known-red quarantined rows run on a probe cadence expecting red (greening is a counted un-quarantine event)" — so a deliberately-red acceptance test does not red the corpus. Its dissolution is forced rather than optional: when the frontier reaches zero the roster row becomes a still-red expectation against a green witness, so it must be deleted in the same change that lands the last migration, promoting the witness to ordinary DiscoverySelection as a standing regression ratchet. It lives in its own file rather than inside observation_emit_census_witness_test because that suite asserts the count the census HAS (== 8, which must red if the roster drifts) while this asserts the count the work OWES (== 0). Both are true and they disagree by construction; merging them would drag the roster's own hygiene check into quarantine and stop it reding when it should. The frontier note now reads TWO and says why the pair is one claim rather than two bindings. witness_execution_contract_frontier_is_exactly_one_node becomes _two_nodes, joined by witness_bound_pair_covers_both_verify_directions. Verified: whole-tree compile 0 blocking errors; the discriminating validation FAILS and the plumbing validation PASSES when each is run directly, which is the receipt that matters; 63 witnesses green with zero failures across roadmap_authority, generated_artifact_drift, observation_emit_census and witness_admission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
…ion reported
The dashboard could not show what an agent actually said. The raw JSONL is
retained per attempt, but codex_provider_event_projection_filter — the jq stage
that bounds each line before the substrate reads it — emitted only
{"type":…,"item":{"type":…}} for item events, so an agent_message survived as an
activity CLASSIFICATION and its text was gone before anything could render it.
That was deliberate: the boundary exists because one item.completed carrying
~154KB of aggregated command output killed the old 64KB reader. So surfacing the
report is a change AT that boundary, not a rendering change, and the reviewable
decision is the bound.
THE FIELD NAME IS CAPTURED, NOT GUESSED. Nothing in the repository recorded the
agent_message item's text member, the shipped CLI is a stripped native binary,
and the locator extdeps.llm.cli already cites documents the mode rather than the
per-item event schema. Modeling it from memory is the guess DESIGN §3 forbids for
an extdeps surface, and #7368's own design note sets the same bar for provider
grammars: admitted only "after an actual provider receipt demonstrates its
grammar". So a receipt was produced — codex exec --json against @openai/codex
0.145.0, landed under dag/test/fixture/codex_provider_events with its version and
capture conditions. Its third line is the authority:
{"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"ok"}}
The report gets its OWN budget rather than reusing the detail budget beside it.
They are the same type and genuinely different facts: a detail is a diagnostic,
short by nature, read to find out what broke; a report is what the provider says
it DID, and it is the text an operator reads to judge whether the work is any
good. One shared number would mean tuning either bound silently retunes the
other. 8192 is set against the incident this projection exists to prevent — an
order of magnitude under the 65536 line budget so a report can never be the
payload that reproduces it, and deliberately above the 4096 detail budget because
a 4KB error is pathological while a 6KB work summary is ordinary.
TRUNCATION IS REPORTED, NEVER SILENT. Everywhere else these bounds guard a
machine-read classification, where a cut string simply fails to match and
refuses. Here the bounded value is prose an operator reads and acts on, so a
report severed mid-sentence and shown as if complete is a wrong answer delivered
confidently — the operator would judge the work on a fragment with nothing on
screen saying so. The envelope therefore carries a message object pairing the
bounded text with a truncated flag computed from the ORIGINAL length before
slicing, so the flag describes the provider's output rather than the slice.
The anchored item.type walk is untouched by construction: the report is emitted
as a member AFTER item.type, so item.type remains item's first member and the
walk's landing position is unchanged — a report whose own text quotes an
item-type fragment still cannot reclassify the pane. The note that described the
envelope shape is corrected to say so rather than understating it.
Verified by execution, which for a jq program means running the MODELED filter
string rather than a hand copy: extracted from the substrate and run through real
jq against the real captured receipt, it yields
{"text":"ok","truncated":false}; against an 8193-character control it yields
exactly 8192 retained characters and truncated:true.
Four witnesses pin the contract the shell cannot prove downstream: the bound is
the message budget (a copy-paste of the detail budget would still emit valid jq
and still look fine until the day a long message arrived), the two budgets are
distinct, truncation is computed against the original length, and both item
envelope shapes keep item.type first.
Verified: whole-tree compile 0 blocking errors; provider-events 18/18; 50 more
green across roadmap_workflow_progress, generated_artifact_drift and
roadmap_authority; zero failures.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
briansrls
force-pushed
the
dispatch-contract-and-output
branch
from
July 29, 2026 16:43
81ffa00 to
bc316c1
Compare
…tity Two roadmap-authority changes, both about replanning not destroying work. FOCUS CLOSURE. Owner membership alone was the wrong visibility rule. The v1 deletion lane's critical path runs through pderive-source-slot-binding, whose prerequisite namespace-canonical-binding lives in a lane the focus hid — so the page rendered the fourth link of the spine as ready with its blocker invisible. Nothing was red; the page lied by omission. Worse for a dispatched agent than for a person: a worker reads a ready-looking node, starts, and stalls on work the roadmap never mentioned. Visibility is now lane membership UNION the transitive prerequisite closure, reusing std.graph.graph_reverse_reachable_members over the roadmap's own edge relation rather than minting a second walk — the edge is already a dependency edge, reverse reachability from a lane node is exactly its ancestors, and the graph is acyclic by witness so the walk terminates by construction. The closure found FIVE blockers, not the three visible by eye: namespace-canonical-binding has its own prerequisites, so the lane was blocked on a namespace sub-chain of three. Manual inspection would have discovered those one stall at a time. Pulled-in rows are named as prerequisites rather than counted as lane work, so the lane's real size stays honest at 17. The focus label is now "the v1 deletion lane" per the operator's naming. DURABLE IDENTITY. A roadmap node's id is its authored slug (RoadmapNodeId = NonEmptyStr), so a rename is structurally a delete plus a create: edges stop resolving, receipts name a node that no longer exists, and any attempt or session joined to it is orphaned. That is not hypothetical — the 2026-07-27 authority refresh deleted the node carrying the only execution contract and no claim noticed. std.occurrence_identity already states the right law: identity may not derive from filename, span, authored name, structural equality, or content hash. The LAW is reused; the TYPE deliberately is not. OccurrenceId is an ordinal from a per-graph allocator starting at zero, so inserting a node at the front renumbers every node after it and two branches mint the same integer — positional identity wearing an allocator's clothes. Correct for occurrences inside one parse, wrong for an entity that must survive edits, reordering, regeneration and independent branches. What occurrence identity does not claim is PERSISTENCE SCOPE, and that is the only thing missing. 51 collision-resistant identities are minted and persisted, one per declared node, at AUTHORING time — nothing mints during render, compile or regen, because a value re-derivable by evaluation would reintroduce the property the module exists to remove. The slug stays readable and stops being identity. Stage I0 is deliberately additive: no rendering, dependency, receipt or dispatch path changes. The v1-deletion recut can be authored against durable identities immediately without waiting on a consumer migration, and without its new nodes being rewritten a second time afterwards. TWO GATES DECLARED AS OWED, NOT ASSUMED. Permanence is a historical property and every witness here reads the current tree, so an identity silently REPLACED between base and head satisfies all of them — the snapshot corpus is structurally incapable of catching the exact edit this module forbids. The owed row lists the admitted and refused transitions for a base-versus-head registry comparison. Separately, decomposition needs an explicit parent completion policy: containment keeps pointers valid but cannot say whether a parent completes on direct acceptance, on all children, or both, and inferring it would silently close a parent whose children are unfinished. Verified: whole-tree compile 0 blocking errors; ROADMAP.md regenerated; 109 witnesses green with zero failures across roadmap_identity (7, incl. the discriminating identity_is_persisted_not_positional), roadmap_focus (8, incl. no_visible_node_has_a_hidden_prerequisite), roadmap_authority, generated_artifact_drift, roadmap_page, doc_reachability (both homes), roadmap_emit and roadmap_document. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
CI caught orphaned enrollment, which is the Phase 0(b) admission invariant working exactly as intended: WITNESS ADMISSION REFUSAL cause=UnexecutedDeferredWitness count=1 — enrolled witness row(s) excluded from discovery name zero executing consumers The deliberately-red acceptance witness was classified QuarantineProbeExpectRed in witness_exclusion_frontier, which removes it from per-PR discovery. That is half the job. The exclusion says where it does NOT run; it does not say where it DOES. Without a matching row on known_red_probe_entries — the roster that actually executes known-red witnesses on their probe cadence expecting red — the witness ran nowhere, which is precisely the "enrolled, zero executions" coverage-by-illusion the invariant refuses. Adding the probe row completes the pair. The exclusion note now states the pairing rule and cites this failure, so the next author reads why both rows are required rather than discovering it from a floor red. Verified: whole-tree compile 0 blocking errors; ci.yml/ROADMAP.md regenerated.
Contributor
Author
|
Superseded by #7440, which consolidates this with the other roadmap-belt PRs. Four branches racing a moving |
briansrls
added a commit
that referenced
this pull request
Jul 29, 2026
…entity, bounded agent report, heal auto-remedy (#7440) * Bind the first roadmap node's execution contract; dispatch stops refusing everywhere Every roadmap node was ExecutionContractUnspecified, so dispatch_environment_admit matched that arm and refused before doing anything else. Clicking Dispatch on any of the ~46 tickets produced a typed refusal and nothing more, which meant no part of the workflow below Env — worktree, agent, and every receipt that depends on them — had ever executed end to end in production. The frontier reached zero when the 2026-07-27 authority refresh deleted the node that carried the prior binding; no claim noticed, because none existed. The binding is a COMBINATOR, not a constructor parameter. `sign` is the precedent sitting beside it and already threads `execution: rn.execution` through untouched; threading an execution argument instead would edit seven constructors and every one of their call sites to express a fact that today holds for exactly one node. A node without the wrapper keeps ExecutionContractUnspecified, which stays the fail-closed refusal the frontier note declares rather than a default anyone chose. shell-typed-invocation is bound to the transport-clean corpus witness (corpus_dag_compile_clean_transport_clean_holds), which is this ticket's own red control expressed as an operation: "a new unclassified production construction site reds the census". It reads the live tree, so it is a statement about the repository rather than a fixture. That validation is ALREADY GREEN, deliberately. A first binding has two jobs that pull apart — prove the Verify path runs at all, and prove it discriminates — and conflating them is how a green pipeline gets mistaken for a working one. This row takes the first job only: an Agent turn that changes nothing still produces a real admitted environment, a real derived command, and a real validation receipt, which is a statement about the PLUMBING and not about the provider. It proves nothing about discrimination and must not be read as evidence that Verify can fail; the discriminating red belongs on a second node whose validation is currently red and goes green when the work lands, and that is the next binding, not this one. The frontier note is corrected in the same motion. It read "Every node below is ExecutionContractUnspecified", which was true when written and false the moment one was bound. It now states the count is one, and that a count is not a completion. Three witnesses pin both halves of the frontier: the bound node yields a real contract rather than the fail-closed variant; the platform/task capability JOIN actually happens at admission (8 fixed dispatch mechanics + the one capability this validation derives = 9); and the frontier is exactly one node — which fails if a binding is silently lost AND if a second is added without updating the roster, so the documented count cannot drift from the authority. ROADMAP.md is unchanged: execution contracts are dispatch mechanics, not roadmap content, and the projection correctly does not render them. Verified: whole-tree compile 0 blocking errors; 46 witnesses green across roadmap_authority (incl. the three new ones and the pre-existing re-entry RED controls), generated_artifact_drift, roadmap_execution_contract, and roadmap_dispatch_environment. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Bind the discriminating second node: give Verify a validation that can actually fail The first binding named an already-green validation, on purpose, to prove the Verify path executes at all — admission, argv derivation, receipt production. It cannot prove the path DISCRIMINATES, because nothing it runs is capable of returning anything but green. A frontier with only that binding is the coverage-by-illusion tier: machinery present, nothing gating on it. observation-raw-print-retirement now binds a validation that FAILS today. gunbc.observation_emit_census classifies every seed emit site as exactly one of MigratedToObservation or CountedFrontierSite, and observation_emit_frontier_count is the population of the second arm — 8 today (floor-drain, gate-warm-cost, receipt, file, resolve-split, assembly-split, witness-row-cost, witness-row-cost-drift). The witness asserts 0, which is that node's handback stated verbatim: "the classified zero-residue progress census". So the red is the ticket's own acceptance condition rather than a planted fixture, the count IS the completion condition rather than a proxy for it, and red -> green is the work being finished. The two bindings now pin both directions, and neither claim is obtainable from the other. Finding a genuine red took some looking, and the search is worth recording: the transport-script wall is clean corpus-wide (every enrolled path AND every unenrolled Exec.Run site I measured returns zero violations), so there was no red available there; the existing known-red quarantine rows are self-host behavioral receipts that red on cargo/shim closure refusal, which is infrastructure rather than anything a dispatched agent could turn green. The emit census is the one place where a small, agent-doable ticket has a countable completion condition that is currently false. The acceptance witness is enrolled QuarantineProbeExpectRed in gunbc.ci_layer_roots — the cadence std.witness_admission defines for exactly this, "known-red quarantined rows run on a probe cadence expecting red (greening is a counted un-quarantine event)" — so a deliberately-red acceptance test does not red the corpus. Its dissolution is forced rather than optional: when the frontier reaches zero the roster row becomes a still-red expectation against a green witness, so it must be deleted in the same change that lands the last migration, promoting the witness to ordinary DiscoverySelection as a standing regression ratchet. It lives in its own file rather than inside observation_emit_census_witness_test because that suite asserts the count the census HAS (== 8, which must red if the roster drifts) while this asserts the count the work OWES (== 0). Both are true and they disagree by construction; merging them would drag the roster's own hygiene check into quarantine and stop it reding when it should. The frontier note now reads TWO and says why the pair is one claim rather than two bindings. witness_execution_contract_frontier_is_exactly_one_node becomes _two_nodes, joined by witness_bound_pair_covers_both_verify_directions. Verified: whole-tree compile 0 blocking errors; the discriminating validation FAILS and the plumbing validation PASSES when each is run directly, which is the receipt that matters; 63 witnesses green with zero failures across roadmap_authority, generated_artifact_drift, observation_emit_census and witness_admission. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Carry the agent's report through the bounded projection, with truncation reported The dashboard could not show what an agent actually said. The raw JSONL is retained per attempt, but codex_provider_event_projection_filter — the jq stage that bounds each line before the substrate reads it — emitted only {"type":…,"item":{"type":…}} for item events, so an agent_message survived as an activity CLASSIFICATION and its text was gone before anything could render it. That was deliberate: the boundary exists because one item.completed carrying ~154KB of aggregated command output killed the old 64KB reader. So surfacing the report is a change AT that boundary, not a rendering change, and the reviewable decision is the bound. THE FIELD NAME IS CAPTURED, NOT GUESSED. Nothing in the repository recorded the agent_message item's text member, the shipped CLI is a stripped native binary, and the locator extdeps.llm.cli already cites documents the mode rather than the per-item event schema. Modeling it from memory is the guess DESIGN §3 forbids for an extdeps surface, and #7368's own design note sets the same bar for provider grammars: admitted only "after an actual provider receipt demonstrates its grammar". So a receipt was produced — codex exec --json against @openai/codex 0.145.0, landed under dag/test/fixture/codex_provider_events with its version and capture conditions. Its third line is the authority: {"type":"item.completed","item":{"id":"item_0","type":"agent_message","text":"ok"}} The report gets its OWN budget rather than reusing the detail budget beside it. They are the same type and genuinely different facts: a detail is a diagnostic, short by nature, read to find out what broke; a report is what the provider says it DID, and it is the text an operator reads to judge whether the work is any good. One shared number would mean tuning either bound silently retunes the other. 8192 is set against the incident this projection exists to prevent — an order of magnitude under the 65536 line budget so a report can never be the payload that reproduces it, and deliberately above the 4096 detail budget because a 4KB error is pathological while a 6KB work summary is ordinary. TRUNCATION IS REPORTED, NEVER SILENT. Everywhere else these bounds guard a machine-read classification, where a cut string simply fails to match and refuses. Here the bounded value is prose an operator reads and acts on, so a report severed mid-sentence and shown as if complete is a wrong answer delivered confidently — the operator would judge the work on a fragment with nothing on screen saying so. The envelope therefore carries a message object pairing the bounded text with a truncated flag computed from the ORIGINAL length before slicing, so the flag describes the provider's output rather than the slice. The anchored item.type walk is untouched by construction: the report is emitted as a member AFTER item.type, so item.type remains item's first member and the walk's landing position is unchanged — a report whose own text quotes an item-type fragment still cannot reclassify the pane. The note that described the envelope shape is corrected to say so rather than understating it. Verified by execution, which for a jq program means running the MODELED filter string rather than a hand copy: extracted from the substrate and run through real jq against the real captured receipt, it yields {"text":"ok","truncated":false}; against an 8193-character control it yields exactly 8192 retained characters and truncated:true. Four witnesses pin the contract the shell cannot prove downstream: the bound is the message budget (a copy-paste of the detail budget would still emit valid jq and still look fine until the day a long message arrived), the two budgets are distinct, truncation is computed against the original length, and both item envelope shapes keep item.type first. Verified: whole-tree compile 0 blocking errors; provider-events 18/18; 50 more green across roadmap_workflow_progress, generated_artifact_drift and roadmap_authority; zero failures. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Close the focus over prerequisites; give roadmap nodes a durable identity Two roadmap-authority changes, both about replanning not destroying work. FOCUS CLOSURE. Owner membership alone was the wrong visibility rule. The v1 deletion lane's critical path runs through pderive-source-slot-binding, whose prerequisite namespace-canonical-binding lives in a lane the focus hid — so the page rendered the fourth link of the spine as ready with its blocker invisible. Nothing was red; the page lied by omission. Worse for a dispatched agent than for a person: a worker reads a ready-looking node, starts, and stalls on work the roadmap never mentioned. Visibility is now lane membership UNION the transitive prerequisite closure, reusing std.graph.graph_reverse_reachable_members over the roadmap's own edge relation rather than minting a second walk — the edge is already a dependency edge, reverse reachability from a lane node is exactly its ancestors, and the graph is acyclic by witness so the walk terminates by construction. The closure found FIVE blockers, not the three visible by eye: namespace-canonical-binding has its own prerequisites, so the lane was blocked on a namespace sub-chain of three. Manual inspection would have discovered those one stall at a time. Pulled-in rows are named as prerequisites rather than counted as lane work, so the lane's real size stays honest at 17. The focus label is now "the v1 deletion lane" per the operator's naming. DURABLE IDENTITY. A roadmap node's id is its authored slug (RoadmapNodeId = NonEmptyStr), so a rename is structurally a delete plus a create: edges stop resolving, receipts name a node that no longer exists, and any attempt or session joined to it is orphaned. That is not hypothetical — the 2026-07-27 authority refresh deleted the node carrying the only execution contract and no claim noticed. std.occurrence_identity already states the right law: identity may not derive from filename, span, authored name, structural equality, or content hash. The LAW is reused; the TYPE deliberately is not. OccurrenceId is an ordinal from a per-graph allocator starting at zero, so inserting a node at the front renumbers every node after it and two branches mint the same integer — positional identity wearing an allocator's clothes. Correct for occurrences inside one parse, wrong for an entity that must survive edits, reordering, regeneration and independent branches. What occurrence identity does not claim is PERSISTENCE SCOPE, and that is the only thing missing. 51 collision-resistant identities are minted and persisted, one per declared node, at AUTHORING time — nothing mints during render, compile or regen, because a value re-derivable by evaluation would reintroduce the property the module exists to remove. The slug stays readable and stops being identity. Stage I0 is deliberately additive: no rendering, dependency, receipt or dispatch path changes. The v1-deletion recut can be authored against durable identities immediately without waiting on a consumer migration, and without its new nodes being rewritten a second time afterwards. TWO GATES DECLARED AS OWED, NOT ASSUMED. Permanence is a historical property and every witness here reads the current tree, so an identity silently REPLACED between base and head satisfies all of them — the snapshot corpus is structurally incapable of catching the exact edit this module forbids. The owed row lists the admitted and refused transitions for a base-versus-head registry comparison. Separately, decomposition needs an explicit parent completion policy: containment keeps pointers valid but cannot say whether a parent completes on direct acceptance, on all children, or both, and inferring it would silently close a parent whose children are unfinished. Verified: whole-tree compile 0 blocking errors; ROADMAP.md regenerated; 109 witnesses green with zero failures across roadmap_identity (7, incl. the discriminating identity_is_persisted_not_positional), roadmap_focus (8, incl. no_visible_node_has_a_hidden_prerequisite), roadmap_authority, generated_artifact_drift, roadmap_page, doc_reachability (both homes), roadmap_emit and roadmap_document. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * 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> * Close the roadmap focus over prerequisites Owner membership alone was the wrong visibility rule. The v1 deletion lane's critical path runs through pderive-source-slot-binding, whose prerequisite namespace-canonical-binding lives in a lane the focus hid — so the page rendered the fourth link of the spine as READY with its blocker invisible. Nothing was red; the page lied by omission. That is worse for a dispatched agent than for a person: a worker reads a ready-looking node, starts, and stalls on work the roadmap never mentioned. Visibility is now lane membership UNION the transitive prerequisite closure, reusing std.graph.graph_reverse_reachable_members over the roadmap's own edge relation rather than minting a second walk — the edge is already a dependency edge, reverse reachability from a lane node is exactly its ancestors, and the graph is acyclic by witness so the walk terminates by construction. The closure found FIVE blockers where three were visible by eye: namespace-canonical-binding has its own prerequisites, so the lane was blocked on a namespace sub-chain of three. Manual inspection would have found those one stall at a time, each costing a wasted attempt. Pulled-in rows are named as prerequisites in the notice rather than counted as lane work, so the lane's real size stays honest. THE DISCRIMINATOR IS SYNTHETIC, deliberately (review). An earlier cut asserted count(pulled) > 0 against the live roadmap_focus_selection, which contradicts the carrier's own promise that changing or clearing the focus is a one-row view edit: it fails the moment the focus is NoFocus, or a lane that legitimately has no cross-owner prerequisite — reporting a defect where none exists and making the focus row un-editable in practice. The fixture owns its two lanes and its transitive cross-lane chain, so it holds under any live focus, and it exercises TRANSITIVITY (b3 pulls b2 pulls b1) which is the part manual inspection misses. A companion asserts the no-external-prerequisite case pulls nothing, so the empty result is a tested outcome rather than an untested branch. The notice claim is also strengthened per review: the test named "pulled in and named as such" now actually checks the notice contains every pulled id, which it previously did not. The live-tree invariant is stated conditionally beside the fixture: whatever the current focus is, no visible node may have a hidden prerequisite. That holds under every focus including NoFocus, so it constrains the projection without pinning the selection. Split out of #7417 on review: the identity half needs identity on RoadmapNode, an active/tombstoned lifecycle, and a base-versus-head permanence gate, and is being rebuilt separately. This half is independent of that work. Verified: whole-tree compile 0 blocking errors; ROADMAP.md regenerated from the authority; 104 witnesses green with zero failures across roadmap_focus (12), roadmap_authority, generated_artifact_drift, roadmap_page, doc_reachability (both homes), roadmap_emit and roadmap_document. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Give roadmap nodes a durable identity as a required field A roadmap node's id was its authored slug, so a rename was structurally a delete plus a create: edges stop resolving, acceptance receipts name a node that no longer exists, and any attempt or session joined to it is orphaned. Not hypothetical — the 2026-07-27 authority refresh deleted the node carrying the only execution contract and no claim noticed. std.occurrence_identity already states the right law: identity may not derive from filename, span, authored name, structural equality or content hash. The LAW is reused; the TYPE deliberately is not. OccurrenceId is an ordinal from a per-graph allocator starting at zero, so inserting a node at the front renumbers everything after it and two branches mint the same integer — positional identity wearing an allocator's clothes. Right for occurrences inside one parse, wrong for an entity that must survive edits, reordering, regeneration and independent branches. What occurrence identity does not claim is PERSISTENCE SCOPE, and that is the only thing missing. IDENTITY IS A REQUIRED FIELD, NOT A SIDE REGISTRY. The first cut carried a hand-written (identity, slug) list beside the authority. It compiled cleanly and was wrong twice over: two authorities that must be kept in step (DESIGN 3), and a node still authorable WITHOUT an identity, detectable only by a later witness — validation standing where construction was available (DESIGN 5). As a field it is unwritable instead, and the index is DERIVED from declared_roadmap_nodes() so the two cannot disagree. The change measured its own necessity: adding the field produced 50 hard failures — 28 struct literals the compiler rejected outright, then 22 constructor call sites failing with `undefined variable: identity`. Every one was a site where a node could previously come into existence without durable identity, and the side registry would have compiled past all fifty. 62 collision-resistant identities are minted and persisted at AUTHORING time. Nothing mints during render, compile or regen; a value re-derivable by evaluation would reintroduce the property this exists to remove. TOMBSTONES, because a base-versus-head diff alone cannot enforce non-reuse. Without persisted retirement: PR A removes node X, a diff observes the removal once, after merge X is simply absent from base, PR B reuses X's identity, and the next comparison sees present-in-head/absent-in-base — indistinguishable from a legitimately new identity. The reuse passes every check. So retirement is a STATE: TombstonedIdentity keeps the identity forever, carries the slug it last wore so historical links resolve, and names its successor. The roster is empty today and the witnesses are arithmetic (registry == active + tombstoned) rather than pinning zero, so the first real retirement will not red them. RESOLUTION IS EXACTLY-ONE. filter-map-first answers a duplicate registry with a plausible first row — the fabricated-plausible-output arm DESIGN 5 forbids, and it fails exactly when the registry is corrupt and a confident wrong answer is worst. IdentityResolved | IdentityUnknown | IdentityAmbiguous{matches} keeps the three remedies distinct. The discriminating witness is identity_survives_a_slug_rename. Every other claim here — uniqueness, totality, resolution — is equally true of a broken registry where identity IS the slug; only this one fails if the separation collapses. STILL OWED: the permanence gate. Every claim reads the current tree, so an identity silently REPLACED between base and head satisfies all of them. The carrier lists the admitted and refused transitions concretely; the tombstone above is what makes that gate implementable at all. ROADMAP.md is unchanged: identity is machinery, the slug remains display. Verified: whole-tree compile EXIT=0, 0 blocking errors; ROADMAP.md regenerated; 241 witnesses green across 15 roadmap suites. Seven wet witnesses fail identically on plain main (hermetic mode refusing to fabricate a host Check) and are unrelated — confirmed by running them on origin/main before attributing. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> * Enroll the known-red acceptance witness on its executing probe roster CI caught orphaned enrollment, which is the Phase 0(b) admission invariant working exactly as intended: WITNESS ADMISSION REFUSAL cause=UnexecutedDeferredWitness count=1 — enrolled witness row(s) excluded from discovery name zero executing consumers The deliberately-red acceptance witness was classified QuarantineProbeExpectRed in witness_exclusion_frontier, which removes it from per-PR discovery. That is half the job. The exclusion says where it does NOT run; it does not say where it DOES. Without a matching row on known_red_probe_entries — the roster that actually executes known-red witnesses on their probe cadence expecting red — the witness ran nowhere, which is precisely the "enrolled, zero executions" coverage-by-illusion the invariant refuses. Adding the probe row completes the pair. The exclusion note now states the pairing rule and cites this failure, so the next author reads why both rows are required rather than discovering it from a floor red. Verified: whole-tree compile 0 blocking errors; ci.yml/ROADMAP.md regenerated. * Restore identity pass-through in with_execution The fixture-identity script matched the RoadmapNode literal inside with_execution and replaced its `identity: rn.identity` pass-through with a hardcoded literal. Since with_execution wraps both bound nodes, both collapsed onto one identity. identities_are_unique_across_the_registry failed on the first attempt to violate it — which is the claim's whole purpose: it is the one that notices when identity stops being per-node. Caught before the change could ship rather than after. Both combinators (sign, with_execution) now thread rn.identity. Verified: 4/4 identity witnesses green including identity_survives_a_slug_rename. --------- Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com> Co-authored-by: gunbc-ci-auto-heal <gunbc-ci-auto-heal@users.noreply.github.com>
briansrls
pushed a commit
that referenced
this pull request
Jul 30, 2026
…affold (#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>
briansrls
added a commit
that referenced
this pull request
Jul 30, 2026
* 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>
briansrls
added a commit
that referenced
this pull request
Jul 30, 2026
… 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>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Dispatch refused on every roadmap node. This binds one, so the workflow below Env can execute end to end for the first time.
The state this fixes
Every node was
ExecutionContractUnspecified, anddispatch_environment_admitmatches that arm first and refuses. Clicking Dispatch on any of the ~46 tickets produced a typed refusal and nothing else — so worktree, agent, and every receipt depending on them had never run in production.The frontier hit zero when the 2026-07-27 authority refresh deleted the node carrying the prior binding. No claim noticed, because none existed — which is why this PR adds them.
Why a combinator
with_executionmirrorssign, sitting directly beside it and already threadingexecution: rn.executionthrough untouched. Threading an execution argument through the constructors instead would edit seven of them and every one of their call sites to express a fact that today holds for exactly one node. A node without the wrapper keepsExecutionContractUnspecified— still the fail-closed refusal the frontier note declares, not a default anyone chose.Why this node, and why an already-green validation
shell-typed-invocationbinds tocorpus_dag_compile_clean_transport_clean_holds— this ticket's own red control expressed as an operation ("a new unclassified production construction site reds the census"), reading the live tree rather than a fixture.That validation passes today, deliberately. A first binding has two jobs that pull apart:
Conflating them is how a green pipeline gets mistaken for a working one. This row takes the first job only: an Agent turn that changes nothing still produces a real admitted environment, a real derived command, and a real validation receipt. That is a statement about the plumbing, not the provider — and it must not be read as evidence that Verify can fail.
Witnesses
Three claims pin both halves of the frontier:
witness_shell_typed_invocation_carries_a_real_contract— the bound node yields a real contract, not the fail-closed variantwitness_bound_contract_joins_platform_and_task_capabilities— the platform/task join actually happens at admission: 8 fixed dispatch mechanics + the one capability this validation derives = 9witness_execution_contract_frontier_is_exactly_one_node— the RED-shaped one. It fails if a binding is silently lost and if a second is added without updating the roster, so the documented count cannot drift from the authority the way it already did onceAlso corrected
roadmap_execution_contract_frontier_noteread "Every node below is ExecutionContractUnspecified" — true when written, false the moment one was bound. It now states the count is one, and that a count is not a completion.ROADMAP.mdis unchanged: execution contracts are dispatch mechanics, not roadmap content, and the projection correctly doesn't render them.Validation
gunbc compile --target dag— 0 blocking errorsroadmap_authority(incl. the three new and the pre-existing re-entry RED controls),generated_artifact_drift,roadmap_execution_contract,roadmap_dispatch_environmentNext
The output pane, which I mis-sized earlier and want to flag: the raw JSONL is retained per attempt, but
codex_provider_event_projection_filterdeliberately strips message content before it reaches the observer — anagent_messagesurvives only as an activity classification. Surfacing the agent's output means extending that bounded projection to carry a bounded text field, which is a design change at the safety boundary #7368 built after a 154 KB event killed the old reader.bounded_textalready exists there for error fields, so the mechanism is right; the reviewable question is the budget. That's its own PR.🤖 Generated with Claude Code