Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 28 additions & 0 deletions .github/workflows/witnesses.yml
Original file line number Diff line number Diff line change
Expand Up @@ -412,6 +412,34 @@ jobs:
ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
"$ROOT/target/release/gunbc" run --source-root "$ROOT/dag" --source-root "$ROOT/src/v2" --entry dag/gunbc/instruments/generated_artifact_gate.dag --function main
if: "!cancelled() && steps.build_witness_fold.outcome == 'success'"
- name: "Stage0 mirrors match what this seed emits, both generations (merge_group only): required CI build lane"
id: stage0_regen
run: |+
GUNBC_FLOOR_LOG='gunbc-floor-cmd.log'
'set' '+e'
'set' '-o' 'pipefail'
('sh' '-e' '-c' 'ROOT=$(git rev-parse --show-toplevel 2>/dev/null || pwd)
cd "$ROOT"
'\''target/release/claim_executor'\'' '\''--required-ci'\'' '\''--source-root'\'' '\''dag'\'' '\''--source-root'\'' '\''src/v2'\'' '\''--required-lane'\'' '\''build'\''
') 2>&1 | 'tee' "$GUNBC_FLOOR_LOG"
GUNBC_FLOOR_EXIT="$?"
GUNBC_FLOOR_RECEIPT='gunbc-floor-outcome.txt'
GUNBC_FLOOR_CLASS='structural'
GUNBC_FLOOR_SIGNATURE=''
if '[' "$GUNBC_FLOOR_EXIT" '-eq' '126' ']'; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='CommandInvokedCannotExecute'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' "$GUNBC_FLOOR_EXIT" '-eq' '127' ']'; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='CommandNotFound'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' "$GUNBC_FLOOR_EXIT" '-eq' '0' ']'; then GUNBC_FLOOR_CLASS='none'; GUNBC_FLOOR_SIGNATURE=''; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'MemoryStallRefusedPageThrash' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='MemoryStallRefusedPageThrash'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'The runner has received a shutdown signal' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='RunnerLost'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'sccache: error: failed to execute compile' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='SccacheFailedToExecuteCompile'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' '(exit status: 254)' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='SccacheRustcWrapperExit254'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'sccache: encountered fatal error' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='SccacheFatalError'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'failed to spawn' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='ProcessSpawnFailure'; fi
if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' && '[' '-f' "$GUNBC_FLOOR_LOG" ']' && 'grep' '-q' 'Resource temporarily unavailable' "$GUNBC_FLOOR_LOG"; then GUNBC_FLOOR_CLASS='infra'; GUNBC_FLOOR_SIGNATURE='ResourceTemporarilyUnavailable'; fi
if (! '[' '-f' "$GUNBC_FLOOR_RECEIPT" ']') || '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']' || ('[' "$GUNBC_FLOOR_CLASS" '=' 'infra' ']' && (! ('[' '-f' "$GUNBC_FLOOR_RECEIPT" ']' && 'grep' '-q' 'class=structural' "$GUNBC_FLOOR_RECEIPT"))) || ('[' "$GUNBC_FLOOR_CLASS" '=' 'none' ']' && (! ('[' '-f' "$GUNBC_FLOOR_RECEIPT" ']' && 'grep' '-q' 'class=structural' "$GUNBC_FLOOR_RECEIPT")) && (! ('[' '-f' "$GUNBC_FLOOR_RECEIPT" ']' && 'grep' '-q' 'class=infra' "$GUNBC_FLOOR_RECEIPT"))); then 'printf' 'class=%s\nsignature=%s\nexit=%s\n' "$GUNBC_FLOOR_CLASS" "$GUNBC_FLOOR_SIGNATURE" "$GUNBC_FLOOR_EXIT" > "$GUNBC_FLOOR_RECEIPT"; if '[' "$GUNBC_FLOOR_CLASS" '=' 'infra' ']'; then 'echo' '::error title=environment::floor_class='"$GUNBC_FLOOR_CLASS"' signature='"$GUNBC_FLOOR_SIGNATURE"' exit='"$GUNBC_FLOOR_EXIT"'; this is not a verdict about the diff. Attempt receipt: '"$GUNBC_FLOOR_RECEIPT"; fi; if '[' "$GUNBC_FLOOR_CLASS" '=' 'structural' ']'; then 'echo' '::error title=subject::floor_class='"$GUNBC_FLOOR_CLASS"' exit='"$GUNBC_FLOOR_EXIT"'; read the step log for the subject defect'; fi; fi
'exit' "$GUNBC_FLOOR_EXIT"

if: "!cancelled() && github.event_name == 'merge_group' && steps.build_witness_fold.outcome == 'success'"
- name: Declare which ledger rows this repair covers
id: repair_declaration
run: |-
Expand Down
2 changes: 1 addition & 1 deletion DESIGN.md
Original file line number Diff line number Diff line change
Expand Up @@ -262,4 +262,4 @@ One row per class, each carrying its recognition rule and its receipts, as a fil
- **`gunbc test <label>` is the dedicated CLI for invoking a v2 measurement, and a new one is a row rather than a flag** (operator ruling, 2026-09-16). The seam is `gunbc.target_binding` `TargetProducer` bound to a `gunbc.instrument_targets` label, and the host note says the extension shape outright: *adding one is a row in `instrument_registry` and an arm here; it is not a new route*. What that buys is not tidiness: the label carries its own refusal vocabulary, so an unknown or pattern label REFUSES with exit 2 rather than reporting a pass, and the three terminations stay distinct β€” 0 held, 1 an observation that did not hold, 2 no observation β€” which is the conflation Β§5 forbids, closed by construction for every instrument at once. The subject is the instrument's own fact and never a CLI option, so an invocation cannot quietly measure a different corpus while reporting the same target's standing. **What this rules out is the alternative that keeps suggesting itself:** a flag on `claim_executor`, whose ~20 flags are hand-parsed in a 2783-line `main` over 44,451 lines of `cli_run.rs` with NO `.dag` authority at all β€” v2 work that lands there is unmodeled by construction, and `--self-host` was withdrawn in the same change that added `//gunbc/instruments:self-host` rather than left standing beside it, because two routes to one fact is the Β§3 fork. `gunbc`'s own surface is modeled (`gunbc.cli_dispatch_surface` β†’ `gunbc_cli_dispatch_generated.rs`); `claim_executor`'s is not, and the gap is the point.
- **Two CLIs, and which one a session wants is decided by which compiler is running.** `gunbc` is the SEED's CLI β€” `std.compiler_entry` `RetainedHostCliKernel`, a clap surface dispatching into hand-authored host Rust (`v1_compiler.cli_run`) β€” so its verbs are unreachable from a self-emitted binary BY CONSTRUCTION, not by omission: an emitted crate does not contain that module. The v2-exclusive door is `v2.cli.compile_cli`, `.dag` in `src/v2/cli/`, declaring the fourth driver `std.compiler_entry` `NativeCliDriver`. It parses argv, decides the verb, decides every refusal, decides what to emit and decides the process exit (`std.process` `ProcessExit`); its rendered main performs only the four operations no `.dag` fold can β€” read argv, walk and read the source roots the PLAN named, write stdout, set the status β€” and hands each back as a VALUE. **That boundary is measured, not chosen for taste:** a resource method on an ordinary `fn` is a located compiler refusal (`Filesystem.Read` off a plain function refuses with *receiver type 'Primitive(Filesystem)' establishes no method surface*), because a resource METHOD is admitted only where the function declares that resource through its `uses` clause β€” an effect requirement, never a function kind: `workflow` was never a semantic kind, only the emitter predicate `v1.compiler.emit_rust` `is_workflow_item`, and gunbc#11528 DELETED it. What keeps the source-root walk in the rendered main is therefore not that boundary but TWO EMISSION GAPS: the free primitive `filesystem_read` PANICS on a missing file instead of returning the typed outcome Β§5 requires of a door whose job is to refuse precisely, and the emitted surface carries no directory listing, which a walk needs before it can be a fold at all. An emitted binary DOES read files β€” `filesystem_read` is typed by `v1.compiler.infer_method` `builtin_function_registry`, bridged by `extdeps.languages.rust.emit` `rt_function_registry` and realized by `v1.compiler.runtime_rust` `rt_filesystem` as `std::fs::read_to_string`. Both gaps close in EMISSION and neither closes by growing the interpreter, so neither makes this boundary permanent. The shim shape is deliberately the capability `gunbc.source_root_eval_driver_seed_growth` names as the trigger retiring ITS row β€” *the rendered main becomes one call into that fold* β€” so the new door adds no seed debt. **Why a second entry module rather than a mode on the first:** one emitted crate has one entry point and the emitter admits exactly one `compiler_pipeline_entry` declaration per closure (`compiler_pipeline_entry_is_ambiguous` refuses two by name), and the CLI's closure reaches no part of `v2.compiler.compile`, so exactly-one holds by construction rather than by a flag choosing between them. The two generations are two instrument rows: `gunbc test //gunbc/instruments:self-host` is the seed emitting and building `v2.compiler.compile`, and `gunbc test //gunbc/instruments:v2-native-cli` is the seed emitting and building the CLI closure β€” two labels because they are two compilations, so a regression in either is reported under a name that says which. Neither is the second generation; that is the BUILT CLI emitting a closure, and it needs this door to exist first.
- explicit actuator (CI / tooling): `gunbc run --source-root dag --source-root src/v2 --entry dag/gunbc/repo/repo_local_git_config.dag --function converge`
- **CI** is one emission, `gunbc.witness_floor_workflow` β†’ `.github/workflows/witnesses.yml`, invoking our own binary once per LANE: `claim_executor --required-ci --source-root dag --source-root src/v2 --required-lane build` and the same with `--required-lane witnesses`, in two parallel jobs, plus an aggregating job that carries the required context and reads BOTH lane results β€” that last is what makes a lane block rather than merely be waited on, so read `gunbc.witness_floor_workflow` `required_lanes_roster` for the current membership rather than this sentence. **The job roster is closed to growth: adding a job needs operator sign-off, because a job is a standing claim on a paid runner on every pull request and on every queued landing** β€” the 2026-09-04 ruling cut three of seven on that basis (`rust-unit-tests`, `fabric-evidence`, `emit-copy-qualification-battery`), and the reasoning an author owes before proposing a lane is stated at `witness_floor_lane_jobs`. The push-on-main trigger was CUT on 2026-09-15 under the same reasoning applied to an event rather than a job: with the merge queue enabled, the required run on the queue's composed revision proves the sha that lands, so the push run re-ran a proof that already existed β€” one required run per landing, not two. Which phases a lane owns is decided in the binary, never in the YAML β€” the partition is an exhaustive match, so a phase belonging to no job fails to compile. **Read the roster from the run's own announcement, not from here:** every required run prints one `phase <name>` line per phase it owns and one `ROUTED to lane <other>` line per phase it does not. Several capabilities that used to gate are currently declared rung drops β€” see Β§4b.
- **CI** is one emission, `gunbc.witness_floor_workflow` β†’ `.github/workflows/witnesses.yml`, invoking our own binary once per LANE: `claim_executor --required-ci --source-root dag --source-root src/v2 --required-lane witnesses` in the `floor` job on every pull request and merge_group, and the same with `--required-lane build` (the stage0 mirrors: generated-artifact and regen-fixed-point) as a later step of that job on merge_group ONLY (operator decision 2026-09-23, `gunbc.compiler_gate_workflow` `compiler_gate_stage0_regen_step`), plus an aggregating job that carries the required context and reads every lane result β€” that last is what makes a lane block rather than merely be waited on, so read the emitting authority for the current membership rather than this sentence. **The job roster is closed to growth: adding a job needs operator sign-off, because a job is a standing claim on a paid runner on every pull request and on every queued landing** β€” the 2026-09-04 ruling cut three of seven on that basis (`rust-unit-tests`, `fabric-evidence`, `emit-copy-qualification-battery`), and the reasoning an author owes before proposing a lane is stated at `witness_floor_lane_jobs`. The push-on-main trigger was CUT on 2026-09-15 under the same reasoning applied to an event rather than a job: with the merge queue enabled, the required run on the queue's composed revision proves the sha that lands, so the push run re-ran a proof that already existed β€” one required run per landing, not two. Which phases a lane owns is decided in the binary, never in the YAML β€” the partition is an exhaustive match, so a phase belonging to no job fails to compile. **Read the roster from the run's own announcement, not from here:** every required run prints one `phase <name>` line per phase it owns and one `ROUTED to lane <other>` line per phase it does not. Several capabilities that used to gate are currently declared rung drops β€” see Β§4b.
Loading