Skip to content

shell -> dag - #8703

Closed
briansrls wants to merge 1 commit into
mainfrom
prelude-capability-binding
Closed

briansrls wants to merge 1 commit into
mainfrom
prelude-capability-binding

Conversation

@briansrls

Copy link
Copy Markdown
Contributor

Auto-opened by session-dashboard for session eager-crane-282.
Pushing to prelude-capability-binding advances this PR.

Worker attestation

Before flipping this PR to ready for review, confirm each item:

  • Title describes the change (not the session id or branch).
  • PR body summarises what and why (replace the TODO below).
  • Tests run: name the command (e.g. npm test, cargo test) and the result.
  • If this closes a work item, the body contains a Closes #N directive.
  • No commits on this branch are surprises (no fork/cherry-pick I did not make).
  • No secrets / credentials / large binaries staged.

Summary

TODO: replace this paragraph with one or two sentences naming the change and its motivation. Reviewers read this first.

Test plan

  • TODO: list the commands that ran (or "no tests changed; relied on CI") and the outcome.

…ider cannot be emitted

deploy.yml ran `cargo build --release -p v1-compiler --bin gunbc` as step two
with no toolchain provider anywhere in the file -- the only `uses:` in all 42
lines was the checkout -- and died on `cargo: command not found` 30 out of 30
runs without ever reaching its terminal step. Nothing in this repository could
refuse it, because by the time a job is List<Step> a step that NEEDS a toolchain
and one that PROVIDES it are indistinguishable.

Receipt for that claim: git show a4677f3:.github/workflows/deploy.yml
(deleted in 5814d0d). Counted with positive
controls on the same scan of the same input -- cargo=1, uses:=1, name:=6 all
nonzero, so setup-rust-toolchain=0 is a real zero rather than a broken pattern.

WHAT THIS ADDS. gunbc.workflow_capability_closure models a step's relationship
to the capabilities its job needs -- Provides / Consumes / Neutral over the
EXISTING ExecutionCapability vocabulary (CargoCapability et al), not a second
one -- and folds the steps IN ORDER, so a capability counts as available only
once a preceding step has provided it.

It sits ABOVE extdeps.github.actions and does not touch it. RunStep { run: String }
is a faithful model of the GitHub wire format; the defect is product modules
constructing that wire representation directly for operations whose semantics are
known. Editing Step would re-coin the upstream spec (§3).

STRUCTURAL, NOT TEXTUAL, and the reason is measured: the same consumption is
spelled `cargo build` in one workflow and `"$CARGO_BIN" build` in another. My own
regex over the second form returned a confident ZERO on a file that invokes cargo
twice, because a closing quote sits between the name and the space.

THE BINDING, which is what makes this a change rather than a demonstration.
witness_floor_bound_steps is ONE list carrying both the Step and its role;
witness_floor_steps and witness_floor_step_annotations are both projections of
it, so they cannot drift. A hand-maintained roles list beside the steps list
would be the §3 fork this closure exists to close, reintroduced as its own fix.

expected_witness_floor_yml now REFUSES: a job whose consumer has no preceding
provider yields a refusal marker instead of yaml. A check only tests call is
specification-without-execution -- green forever while the emitter produces the
broken workflow beside it.

EVIDENCE, every witness falsified by a different plausible wrong implementation:

  witness                          base  M1     M2       M3c
                                         vacuous blanket  order-insensitive
  no-provider job refuses          true  false  true     true
  provider-first job admitted      true  true   false    true
  provider-after-consumer refuses  true  false  true     false

M3c is the one that proves ordering is the content of the claim: a check asking
only "does this job contain a toolchain anywhere" passes a job broken exactly the
way deploy.yml was.

Binding proven in both directions (M4, toolchain retagged neutral):
  mutated:  refusal_marker=1  yaml_name_line=0   <- refusal REPLACES, not decorates
  restored: refusal_marker=0  yaml_name_line=1

Emission is byte-identical to the committed .github/workflows/witnesses.yml
(1428 bytes both sides), so the step-construction refactor is behaviour-preserving
and no regeneration is required.

RUNG, HONESTLY. Mechanically preventable for the one job that is bound. Every
other workflow can still be assembled as bare Steps and bypass closure entirely
-- fleet-converge.yml is not bound by this cut. Next-rung trigger: binding the
remaining emitters, at which point an unannotated job becomes the unwritable
state rather than merely the unchecked one.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@gunbai-bot

gunbai-bot Bot commented Aug 21, 2026

Copy link
Copy Markdown
Contributor

Closing this rather than rebasing it, because rebasing would be repairing a branch whose content has already landed by another route.

prelude-capability-binding was cut long enough ago that its diff against current main is 1015 insertions against 7863 deletions across 93 files — fleet_desired_admission, fleet_main_revision, guarantee_rung_drop, measurement_provenance, node_hash_protocol, the claim_executor phases, the trait-derive emit path, and more. Those deletions are not this branch's work; they are main's subsequent work that this branch simply predates. Resolving that conflict-by-conflict is not a rebase, it is hand-reconstructing main inside a stale branch — the exact stale-branch-plus-squash shape that already caused one silent revert I had to repair in #8737. I am not doing it a second time deliberately.

The work this PR existed to deliver — binding the CI prelude steps to a declared capability role instead of an unchecked inline literal list — is delivered by #8734 (fleet-converge-capability-binding), against current main, with 8 green witnesses and fleet-converge.yml byte-identical at 18736. ci_prelude_steps_with_checkout is there, alongside ci_prelude_bound_steps_with_checkout, ci_prelude_annotations, and the extracted ci_setup_rust_step / ci_pin_rustup_default_step / ci_cache_cargo_step rows.

Nothing is dropped by closing this. If review later wants the two rows that appear only here (ci_native_cache_root_step, ci_release_bins_pack_step as extracted step functions), they are a small follow-up authored against main, not a reason to keep a branch that would revert 7863 lines.

@gunbai-bot gunbai-bot Bot closed this Aug 21, 2026
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