Skip to content

Bind the first roadmap node's execution contract; dispatch stops refusing everywhere - #7404

Closed
briansrls wants to merge 6 commits into
mainfrom
dispatch-contract-and-output
Closed

briansrls wants to merge 6 commits into
mainfrom
dispatch-contract-and-output

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

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, and dispatch_environment_admit matches 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_execution mirrors sign, sitting directly beside it and already threading execution: rn.execution through 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 keeps ExecutionContractUnspecified — 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-invocation binds to corpus_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:

job needs this PR
prove the Verify path runs a green validation ✅
prove it discriminates a currently-red validation ❌ — next binding

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 variant
  • witness_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 = 9
  • witness_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 once

Also corrected

roadmap_execution_contract_frontier_note read "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.md is unchanged: execution contracts are dispatch mechanics, not roadmap content, and the projection correctly doesn't render them.

Validation

  • whole-tree gunbc compile --target dag — 0 blocking errors
  • 46 witnesses green, zero failures across roadmap_authority (incl. the three new and the pre-existing re-entry RED controls), generated_artifact_drift, roadmap_execution_contract, roadmap_dispatch_environment

Next

The output pane, which I mis-sized earlier and want to flag: the raw JSONL is retained per attempt, but codex_provider_event_projection_filter deliberately strips message content before it reaches the observer — an agent_message survives 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_text already 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

@cursor

cursor Bot commented Jul 29, 2026

Copy link
Copy Markdown

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.

briansrls and others added 3 commits July 29, 2026 16:17
…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
briansrls force-pushed the dispatch-contract-and-output branch from 81ffa00 to bc316c1 Compare July 29, 2026 16:43
…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.
@briansrls

Copy link
Copy Markdown
Contributor Author

Superseded by #7440, which consolidates this with the other roadmap-belt PRs. Four branches racing a moving main produced a ROADMAP.md conflict on every advance; one branch regenerating the artifact ends that. All content from this PR is carried forward and re-verified on the consolidated branch (199 witnesses green).

@briansrls briansrls closed this Jul 29, 2026
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant