From 63be61b4f98097fb988ebb9cf269ac201c684ef6 Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 14:47:34 -0400 Subject: [PATCH 1/2] WIP: R3 gate #98: ci_yml_hand_authority_dissolved (T-Workflow-As-Data) --- .github/workflows/ci.yml | 937 +++++++----------- dsl/gunbc/ci.dag | 11 +- dsl/gunbc/ci_emission.dag | 4 +- .../t_ci_workflow_as_data_demo_test.rs | 43 +- src/v3/std/verification.dag | 8 + tools/gen_gunbc_ci_workflow_dag/src/lib.rs | 23 + tools/gen_gunbc_ci_workflow_dag/src/main.rs | 47 +- 7 files changed, 455 insertions(+), 618 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 89ac195843d..8fa1afd9d37 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -1,641 +1,372 @@ name: ci - on: push: branches: - - main + - main pull_request: branches: - - main - # Default types are opened/synchronize/reopened. Add `ready_for_review` - # so CI fires when a draft is promoted without a new push. - types: [opened, synchronize, reopened, ready_for_review] - + - main + types: + - opened + - synchronize + - reopened + - ready_for_review permissions: contents: read - # Manager-brief authority check uses `gh pr view --json state` to - # verify "LANDED via #N" claims map to MERGED PRs. Default - # GITHUB_TOKEN scopes don't include pull-request read; without this - # the check fails with "Resource not accessible by integration". pull-requests: read - -# Cancel duplicate in-flight runs for the same PR **tip** only. -# -# PR-number-only groups caused `cancel-in-progress` to target every in-flight -# job for that PR: a stuck `v3` run on an older `head.sha` could abort a newer -# SHA's workflow mid-step (spurious red on the latest push; gunbc#2681). -# Appending `head.sha` scopes cancellation to same-commit reruns (double -# `synchronize`, label churn). Different SHAs no longer cancel each other. -# -# Keyed on PR number (not `head_ref`) so two fork PRs sharing a branch name do -# not share a group. On `push` to `main`, `pull_request` is absent — fall back -# to `github.sha` so each push stays distinct; `run_id` remains for uniqueness -# where needed. concurrency: group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.run_id }}-${{ github.event_name == 'pull_request' && github.event.pull_request.head.sha || github.sha }} cancel-in-progress: true - -# Rust: each `setup-rust-toolchain` step omits `toolchain:` so the action reads -# `rust-toolchain.toml` at the repo root after `actions/checkout`. No job uses a -# non-default `working-directory` for Rust setup; if one did, make `rust-toolchain.toml` -# visible from that directory (e.g. copy it in) — do **not** add a workflow `toolchain:` -# input: `scripts/check-rust-toolchain-single-authority.sh` rejects `toolchain:` in the -# same Actions step as `actions-rust-lang/setup-rust-toolchain` in any -# `.github/workflows/*.{yml,yaml}`, and the action -# ignores the repo file when `toolchain` is set explicitly (upstream semantics). env: CARGO_TERM_COLOR: always RUSTFLAGS: -D warnings - jobs: fmt: - # Skip draft PRs. `github.event.pull_request.draft` is undefined on push - # events, so `!= true` keeps main-branch pushes running. if: github.event.pull_request.draft != true runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }} timeout-minutes: 5 steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Setup Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 - with: - components: rustfmt - cache: false - rustflags: "" - - - name: cargo fmt --all --check - run: cargo fmt --all --check - - # Policy + bootstrap snapshot verify (T-V2 G-2-prereq-ci): shell policy checks - # plus `regen_bootstrap --verify` so stale `bootstrap_generated*.rs` cannot merge - # when only this job is green (#1543). Legacy CI previously built and ran the - # DAG-language compiler from the retired legacy tree in this job; that release transport is - # removed to cut wall time. Full compiler + test surface stays in the `v3` - # job. Local reproduction of the old pipeline: `dsl/gunbc/tools/ci_runner.dag` - # `run_ci_pipeline`. - # Dissolution trigger: remove the verify step below once the committed bootstrap - # snapshot surface dissolves (default-build regen or chosen artifact path). Track - # #1559; rationale: docs/audit/bootstrap-snapshot-drift-dissolution-assessment.md. + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Setup Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 + with: + components: rustfmt + cache: false + rustflags: '' + - name: cargo fmt --all --check + run: cargo fmt --all --check ci: if: github.event.pull_request.draft != true runs-on: ${{ vars.CI_RUNNER || 'ubuntu-latest' }} timeout-minutes: 25 steps: - - name: Checkout - uses: actions/checkout@v4 - with: - # Full clone so `git diff origin/main...HEAD` sees every commit on the PR - # branch (shallow `fetch-depth: 1` misses earlier commits and can false-negative - # the SG-0 net-shrink discipline gate). - fetch-depth: 0 - - - name: Fetch main for PR discipline diffs - if: github.event_name == 'pull_request' - run: git fetch origin main:refs/remotes/origin/main - - - name: SG-0 net-shrink PR-body discipline (self-test) - run: bash scripts/check-pr-sg0-net-shrink-discipline.sh --self-test - - - name: SG-0 net-shrink PR-body discipline - if: github.event_name == 'pull_request' - env: - PR_BODY: ${{ github.event.pull_request.body }} - run: | - body="${PR_BODY}" - append_file="scripts/ci-merge/sg0-pr-body-append.${{ github.event.pull_request.number }}.txt" - if [ -f "${append_file}" ]; then - # Prepend so `check-pr-sg0-net-shrink-discipline.sh` (grep head-1 on - # `SG-0 hand-path delta:`) reads the machine-authored append **first**. PR - # descriptions often keep template scaffolding or mistaken `+0` paste lines - # above the fold — appending only left those as the first match and tripped - # declared-vs-computed mismatch (false fail). - body="$(cat "${append_file}")"$'\n\n'"${body}" - fi - PR_BODY="${body}" bash scripts/check-pr-sg0-net-shrink-discipline.sh - - - name: R4-carve dissolution discipline (self-test) - run: bash scripts/check-r4-carve-dissolution-discipline.sh --self-test - - - name: R4-carve dissolution discipline - run: bash scripts/check-r4-carve-dissolution-discipline.sh - - - name: Fabrication sentinel ratchet (P0-C) - run: bash scripts/check-fabrication-sentinels.sh - - - name: Release-doc authority check (P2 single-authority discipline) - # Forbidden-string consumer for release-control docs. Authority: - # docs/r2-structure.md §"Release-doc authority discipline". - run: bash scripts/check-release-doc-authority.sh - - - name: Release-doc authority self-test (consumer not ceremonial) - # Prevents future RETRACTION_PATTERNS broadening from silently - # neutering the consumer. - run: bash scripts/test-check-release-doc-authority.sh - - - name: Manager-brief authority check (P2 single-authority discipline) - # Verifies 7 R2 manager briefs cite live authorities and use - # consistent projections. Q1 (file existence) + Q2 (anchor - # existence) + Q4 (LANDED via #N reachability) + Q5 (cross-brief - # lane-count consistency). Authority: gpt-5-5-pro meta-review - # on PR #1126. - run: bash scripts/check-manager-brief-authority.sh - env: - GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} - - - name: Manager-brief authority self-test (consumer not ceremonial) - # Prevents future MANAGER_BRIEFS or pattern-set changes from - # silently neutering the consumer. - run: bash scripts/test-check-manager-brief-authority.sh - - - name: Test-timeout ratchet self-test (consumer not ceremonial) - # Prevents future JSONL manifest parsing changes from silently - # neutering fail-closed slow-test policy. - run: bash scripts/test-check-test-timeout.sh - - - name: Rust toolchain single-authority check (P2) - # Pinned channel must not be duplicated in dsl/extdeps/rustup.dag; - # authority is rust-toolchain.toml only (PR #1794). - run: bash scripts/check-rust-toolchain-single-authority.sh - - - name: Setup Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 - with: - components: rustfmt - cache: false - rustflags: "" - - - name: Cache Cargo (ci bootstrap gate) - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: cargo-ci-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/src/**', 'src/v3/compiler/tests/**') }} - restore-keys: | - cargo-ci-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- - cargo-ci-${{ runner.os }}- - - - name: v3 bootstrap snapshot freshness gate (--verify) - run: cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap -- --verify - - # Gate #103 / T-WAD Slice 7 — **explicit** CI callsites (not only via the full `v3` suite): - # - Canvas §5 dissolution evidence (b): static ratchet on `.github/workflows/*`. - # - Worker brief `docs/briefs/r3-wave1-s6-slice7-affected-set-impl-worker.md` §1 **Layer 1**: - # gate-id `CiWorkflowDiff` plumbing + `select_affected_gates_for_binary_shim` integration tests. - # **Layer 2** (PR #2713 `Set` / dimension receipts → emitted BinaryShim runner) waits on - # Slice 5 per canvas §6–§7; this job does not pretend that runner exists yet. - - name: "Gate #103 — path-regex inventory ratchet (canvas §5)" - run: bash scripts/check-workflow-path-regex-inventory.sh - - # Also runs `workflow_no_path_regex_policy_ci_yml` (Rust belt-and-suspenders vs the shell - # ratchet above; same forbidden-substrings manifest). - - name: "Gate #103 — Layer 1 selection + workflow YAML policy (integration)" - run: | - set -euo pipefail - cargo test -p v3-compiler --test integration ci_uses_affected_set_selection -- --quiet - cargo test -p v3-compiler --test integration workflow_no_path_regex_policy_ci_yml -- --quiet - - # Merge-blocking heavy compute always runs on non-draft PRs and on pushes to - # main. Docs-only skip was removed as **Layer 2 Phase C** hygiene under gate - # `ci_uses_affected_set_selection` (program row 103): YAML path-regex selection is - # not authoritative (`docs/briefs/r3-wave1-s6-slice7-affected-set-impl-worker.md` §1 - # two-layer model + `docs/design-t-wad-slice-7-binary-shim-affected-set-selection-canvas.md` §5). - # **Layer 2** in-runner narrowing (`select_affected_gates_for_binary_shim` fed from PR #2713 - # receipts inside the Slice 5 runner) is tracked on the canvas checklist §7; the `ci` job - # above runs the Layer 1 adapter tests + §5 ratchet explicitly. + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 0 + - name: Fetch main for PR discipline diffs + if: github.event_name == 'pull_request' + run: git fetch origin main:refs/remotes/origin/main + - name: SG-0 net-shrink PR-body discipline (self-test) + run: bash scripts/check-pr-sg0-net-shrink-discipline.sh --self-test + - name: SG-0 net-shrink PR-body discipline + if: github.event_name == 'pull_request' + env: + PR_BODY: ${{ github.event.pull_request.body }} + run: | + body="${PR_BODY}" + append_file="scripts/ci-merge/sg0-pr-body-append.${{ github.event.pull_request.number }}.txt" + if [ -f "${append_file}" ]; then + # Prepend so `check-pr-sg0-net-shrink-discipline.sh` (grep head-1 on + # `SG-0 hand-path delta:`) reads the machine-authored append **first**. PR + # descriptions often keep template scaffolding or mistaken `+0` paste lines + # above the fold — appending only left those as the first match and tripped + # declared-vs-computed mismatch (false fail). + body="$(cat "${append_file}")"$'\n\n'"${body}" + fi + PR_BODY="${body}" bash scripts/check-pr-sg0-net-shrink-discipline.sh + - name: R4-carve dissolution discipline (self-test) + run: bash scripts/check-r4-carve-dissolution-discipline.sh --self-test + - name: R4-carve dissolution discipline + run: bash scripts/check-r4-carve-dissolution-discipline.sh + - name: Fabrication sentinel ratchet (P0-C) + run: bash scripts/check-fabrication-sentinels.sh + - name: Release-doc authority check (P2 single-authority discipline) + run: bash scripts/check-release-doc-authority.sh + - name: Release-doc authority self-test (consumer not ceremonial) + run: bash scripts/test-check-release-doc-authority.sh + - name: Manager-brief authority check (P2 single-authority discipline) + run: bash scripts/check-manager-brief-authority.sh + env: + GH_TOKEN: ${{ secrets.GITHUB_TOKEN }} + - name: Manager-brief authority self-test (consumer not ceremonial) + run: bash scripts/test-check-manager-brief-authority.sh + - name: Test-timeout ratchet self-test (consumer not ceremonial) + run: bash scripts/test-check-test-timeout.sh + - name: Rust toolchain single-authority check (P2) + run: bash scripts/check-rust-toolchain-single-authority.sh + - name: Setup Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 + with: + components: rustfmt + cache: false + rustflags: '' + - name: Cache Cargo (ci bootstrap gate) + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: cargo-ci-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/src/**', 'src/v3/compiler/tests/**') }} + restore-keys: | + cargo-ci-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- + cargo-ci-${{ runner.os }}- + - name: v3 bootstrap snapshot freshness gate (--verify) + run: cargo run -p v3-compiler --features bootstrap-regen-fresh --bin regen_bootstrap -- --verify + - name: 'Gate #103 — path-regex inventory ratchet (canvas §5)' + run: bash scripts/check-workflow-path-regex-inventory.sh + - name: 'Gate #103 — Layer 1 selection + workflow YAML policy (integration)' + run: | + set -euo pipefail + cargo test -p v3-compiler --test integration ci_uses_affected_set_selection -- --quiet + cargo test -p v3-compiler --test integration workflow_no_path_regex_policy_ci_yml -- --quiet v3: if: github.event.pull_request.draft != true - # Heavy compute (cargo release builds, full v3 test suite at the - # 4000s transitional budget + clippy + lens gates). 2-core ubuntu-latest blows - # the 60min cap reliably; `ubicloud-standard-8` (8 vCPU, ~$0.0256/hr) finishes - # the workload well under cap. The `vars.CI_RUNNER` indirection is intentionally - # absent for this job because the core-count requirement is structural — no - # orchestrator should route this onto a 2-core runner regardless of cost-routing. runs-on: ubicloud-standard-8 - # Full suite is transitionally capped at 4000s (~67m), plus lane2d gate, prebuild, - # two clippy passes, regen-fresh compile check, and L-7/L-8 shell gates. A 60m job cap - # cancels mid-suite on cold/cache-miss runners (observed: Actions "maximum execution time - # of 1h0m0s"). Keep headroom above the in-step 4000s budget + downstream steps. - # Revert toward 60–90m when OnceLock/module-cache brings warmed full-suite wall back down. timeout-minutes: 120 steps: - - name: Checkout - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: Setup Rust - uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 - with: - # Integration snapshot tests (`regen_parse` path, lane2d cost lens, …) shell out to `rustfmt`. - components: rustfmt, clippy - cache: false - rustflags: "" - - - name: Setup Zig C toolchain - uses: goto-bus-stop/setup-zig@v2 - with: - # Pin a stable linker toolchain instead of the action default - # nightly/master download path; the self-hosted runner has lost - # contact repeatedly while resolving the moving Zig setup target. - version: 0.13.0 - cache: false - - - name: Configure user-space C linker - run: | - mkdir -p "${RUNNER_TEMP}/gunbc-bin" - cat > "${RUNNER_TEMP}/gunbc-bin/zig-cc" <<'EOF' - #!/usr/bin/env bash - exec zig cc "$@" - EOF - chmod +x "${RUNNER_TEMP}/gunbc-bin/zig-cc" - echo "CC=${RUNNER_TEMP}/gunbc-bin/zig-cc" >> "${GITHUB_ENV}" - echo "RUSTFLAGS=-D warnings -C linker=${RUNNER_TEMP}/gunbc-bin/zig-cc" >> "${GITHUB_ENV}" - - - name: Setup Python - uses: actions/setup-python@v6 - with: - python-version: "3.x" - - - name: Setup Go - uses: actions/setup-go@v6 - with: - go-version: "stable" - - - name: Cache Cargo (v3) - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: cargo-v3-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/src/**', 'src/v3/compiler/tests/**') }} - restore-keys: | - cargo-v3-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- - cargo-v3-${{ runner.os }}- - - # **PB-Runtime helper-binary prereq (PR #1049 / #1063 / #856).** The Linux - # `ExecuteCommand` host path invokes `gunbc_execute_command_bootstrap` as the - # `unshare(1)` target — it sets `FD_CLOEXEC` on fd 3 immediately before `execvp(3)`, - # closing the sentinel channel atomically on successful exec (the structural P2(c) - # guarantee). `cargo test -p v3-compiler` does not pull this bin-only crate into its - # build graph (bin-only crates can't be `[dependencies]` on stable), so we build it - # explicitly here. `test_runner.rs::locate_unshare_bootstrap_helper` walks from - # `current_exe()` to find the resulting `target/debug/gunbc_execute_command_bootstrap`. - - name: Build ExecuteCommand unshare helper - run: cargo build -p execute-command-bootstrap - - # Layer 1 (coarse CI): wall-clock gates on `cargo test -p v3-compiler`. - # - # Full-suite wall-clock ratchet below is transitionally 4000s (raised from 3300s after - # observed ~3681s cold gunbc-ci full-suite wall on PR #2696). Earlier history: 3300s from - # ~2873s cold ubicloud-standard-8 runs (gate #78 era); 2400s before that. Revert toward lower - # caps once integration amortization / OnceLock warming restores headroom. Mainline timing on ubuntu-24.04 - # reached ~951–953s after #548 (earlier green ~719s); warm local runs are often - # ~520–560s for `cargo test -p v3-compiler`. Cold runners, cache misses, m1_5_testgen, - # and the DB-8 determinism matrix can push higher — observed ~1082s motivated cap >1050s. - # Ratchet is coarse (catch suite-wide slowdown), not a tight perf SLA. - # Regressions show up when integration tests redo full `compile_to_dag` per - # `#[test]` (see `lane2_stage_2e_parallelism_test`: shared `OnceLock` + clone). - # - # Wall-clock gate on lane2 Stage 2d symbolic-cost tests only (ζ / #537). - # Post-#546 these live in the consolidated `integration` test binary; the - # `lane2_stage_2d_symbolic_cost_test::` filter keeps the ratchet narrow. - # The timer wraps the full `cargo test` process. Prebuild the integration - # harness (`--no-run`) so this gate measures lane2d work — not a cold link - # of the whole `integration` binary (observed ~322s over a 300s budget on - # ubuntu-latest; PR #1794). **Cold** runs (cache miss) can still spend minutes; - # keep headroom beyond a tight 120s; per-test discipline lives in - # `tests/common/budgeted.rs` (DEFAULT_BUDGET_MS). - # Tracked headroom: ratchet this ceiling back toward 300s once cold lane2d - # CI runs regularly complete under 300s after fixture compile amortization. - - name: Prebuild v3 integration test binary (lane2d wall-clock denominator) - run: | - set -euo pipefail - heartbeat() { - while sleep 60; do - echo "v3 prebuild heartbeat: $(date -u +%FT%TZ)" - done - } - heartbeat & - heartbeat_pid=$! - trap 'kill "$heartbeat_pid" 2>/dev/null || true' EXIT - cargo test -p v3-compiler --test integration --no-run - - # **HOT-FIX 2026-05-12 — Stage 2d test execution SKIPPED** per operator - # directive at gunbc#846 ('cut all demos and integration tests for now, - # get v3 to 10 minutes'). The lane2d integration tests are part of the - # full integration harness and execution is paused until OnceLock/ - # cached_compile amortization (rebuild session) lands. Compile coverage - # remains via the `--no-run` prebuild step above (catches Rust-level - # breakages); only execution is skipped. - # - # **Restore criteria** (rebuild session per #2722 §5): when each lane2d - # symbolic-cost test re-enables under shared bootstrap + OnceLock - # amortization with per-test wall ≤ 2s, restore this step (or transition - # to per-cluster path-conditional gating per Layer 2 brief #2719). - - name: v3 tests (Stage 2d integration module, HOT-FIX SKIPPED) - run: | - echo "::notice::v3 lane2d Stage 2d test execution SKIPPED per operator hot-fix directive at gunbc#846 (cold-v3 → ~10min target)." - echo "::notice::Restore criteria: per-test wall ≤ 2s under OnceLock/cached_compile amortization (rebuild session per #2722 §5)." + - name: Checkout + uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: Setup Rust + uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 + with: + components: rustfmt, clippy + cache: false + rustflags: '' + - name: Setup Zig C toolchain + uses: goto-bus-stop/setup-zig@v2 + with: + version: 0.13.0 + cache: false + - name: Configure user-space C linker + run: | + mkdir -p "${RUNNER_TEMP}/gunbc-bin" + cat > "${RUNNER_TEMP}/gunbc-bin/zig-cc" <<'EOF' + #!/usr/bin/env bash + exec zig cc "$@" + EOF + chmod +x "${RUNNER_TEMP}/gunbc-bin/zig-cc" + echo "CC=${RUNNER_TEMP}/gunbc-bin/zig-cc" >> "${GITHUB_ENV}" + echo "RUSTFLAGS=-D warnings -C linker=${RUNNER_TEMP}/gunbc-bin/zig-cc" >> "${GITHUB_ENV}" + - name: Setup Python + uses: actions/setup-python@v6 + with: + python-version: 3.x + - name: Setup Go + uses: actions/setup-go@v6 + with: + go-version: stable + - name: Cache Cargo (v3) + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: cargo-v3-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/src/**', 'src/v3/compiler/tests/**') }} + restore-keys: | + cargo-v3-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- + cargo-v3-${{ runner.os }}- + - name: Build ExecuteCommand unshare helper + run: cargo build -p execute-command-bootstrap + - name: Prebuild v3 integration test binary (lane2d wall-clock denominator) + run: | + set -euo pipefail + heartbeat() { + while sleep 60; do + echo "v3 prebuild heartbeat: $(date -u +%FT%TZ)" + done + } + heartbeat & + heartbeat_pid=$! + trap 'kill "$heartbeat_pid" 2>/dev/null || true' EXIT + cargo test -p v3-compiler --test integration --no-run + - name: v3 tests (Stage 2d integration module, HOT-FIX SKIPPED) + run: | + echo "::notice::v3 lane2d Stage 2d test execution SKIPPED per operator hot-fix directive at gunbc#846 (cold-v3 → ~10min target)." + echo "::notice::Restore criteria: per-test wall ≤ 2s under OnceLock/cached_compile amortization (rebuild session per #2722 §5)." + exit 0 + - name: v3 full-suite split guard (integration test targets) + run: scripts/check-v3-full-suite-split-test-targets.sh + - name: v3 tests (full suite lib+bins, timings part 1/4) + env: + CARGO_TERM_COLOR: never + RUST_MIN_STACK: 16777216 + run: | + set -euo pipefail + echo "V3_SUITE_START_TS=$(date +%s)" >> "${GITHUB_ENV}" + : > /tmp/v3-test-timings.log + RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --lib --bins -- -Z unstable-options --report-time 2>&1 | tee /tmp/v3-test-timings.log + status=${PIPESTATUS[0]} + if [ "$status" -ne 0 ]; then + echo "::error::cargo test (lib+bins) failed (exit=$status)" + exit "$status" + fi + - name: v3 tests (full suite determinism harness, timings part 2/4) + env: + CARGO_TERM_COLOR: never + RUST_MIN_STACK: 16777216 + run: | + set -euo pipefail + RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --test determinism_test -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log + status=${PIPESTATUS[0]} + if [ "$status" -ne 0 ]; then + echo "::error::cargo test (determinism_test) failed (exit=$status)" + exit "$status" + fi + - name: v3 tests (full suite doc tests, timings part 3/4) + env: + CARGO_TERM_COLOR: never + RUST_MIN_STACK: 16777216 + run: | + set -euo pipefail + RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --doc -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log + status=${PIPESTATUS[0]} + if [ "$status" -ne 0 ]; then + echo "::error::cargo test (--doc) failed (exit=$status)" + exit "$status" + fi + - name: v3 tests (full suite integration harness, HOT-FIX zero-test-filter) + env: + CARGO_TERM_COLOR: never + RUST_MIN_STACK: 16777216 + run: | + set -euo pipefail + echo "::notice::v3 integration test execution SKIPPED via zero-test-filter per operator hot-fix at gunbc#846." + echo "::notice::Guard pattern preserved; integration binary runs zero tests (nonexistent filter)." + if [ -z "${V3_SUITE_START_TS:-}" ]; then + echo "::error::missing V3_SUITE_START_TS (full suite part 1 must run first)" + exit 1 + fi + # Zero-test-filter: `__HOT_FIX_NONEXISTENT_FILTER__` matches no tests; + # binary runs through libtest setup + reports 0 tests run. Satisfies + # check-v3-full-suite-split-test-targets.sh pattern requirement. + RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --test integration __HOT_FIX_NONEXISTENT_FILTER__ -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log + status=${PIPESTATUS[0]} + elapsed=$(( $(date +%s) - V3_SUITE_START_TS )) + echo "v3 full-suite wall time (integration-skipped): ${elapsed}s" + if [ "$status" -ne 0 ]; then + echo "::error::cargo test (integration, zero-filter) failed (exit=$status) — should never happen with nonexistent filter; investigate." + exit "$status" + fi + echo "::notice::Restore criteria: rebuild session per #2722 §5 OnceLock/cached_compile amortization → per-test wall ≤ 2s ratchet → re-enable per cluster filter (replace __HOT_FIX_NONEXISTENT_FILTER__ with cluster-specific filter)." + - name: v3 gunbc-ci binary (wall-clock warn manifest + BinaryShim stub) + if: always() + run: cargo build -p v3-compiler --bin gunbc-ci + - name: v3 tests (per-test 2s ratchet) + if: always() + run: | + if [ ! -s /tmp/v3-test-timings.log ]; then + echo "::notice::no timing log captured or log is empty (full-suite steps did not reach cargo test, or tee wrote nothing) — skipping per-test ratchet" exit 0 - - # **Dissolution trigger:** reshape m1_5_testgen to spot-check instead of exhaustive - # compile-every-claim, OR mark the two slow tests `#[ignore]`-by-default + nightly job. - # - # Timing capture — the trailing `-- -Z unstable-options --report-time` enables - # libtest's per-test timing output (`` trailer) so the Phase 0 per-test - # ratchet step below can parse violations without running the suite a second - # time. `--report-time` is still unstable on 1.93 (rust-lang/rust#64888); the - # `RUSTC_BOOTSTRAP=1` prefix is the documented narrow unlock for libtest flags - # and does not enable unstable language features. - # - # **Split across YAML steps (gunbc#2681):** a single long `cargo test | tee` - # step on self-hosted runners sometimes completed with `failure` while the - # Actions log contained no `cargo test` output (mid-step runner loss / flush - # behavior). Running `lib`+`bins`, `determinism_test`, `doc`, and `integration` as - # separate steps preserves streamed logs per phase and the same combined - # `/tmp/v3-test-timings.log` for `scripts/check-test-timeout.sh`. - # - # **Target-discovery guard:** every `tests/*.rs` integration binary must appear in - # a split step with `--report-time` (codex review on #2681); otherwise clippy - # `--all-targets` could compile a new harness without the full suite ever running it. - # **Bridge debt:** script is a tracked hand-CI shim until Workflow-as-Data owns this - # gate (see header in `scripts/check-v3-full-suite-split-test-targets.sh`; openai-pro - # APPROVE_WITH_COMMENTS on #2681). - - name: v3 full-suite split guard (integration test targets) - run: scripts/check-v3-full-suite-split-test-targets.sh - - - name: v3 tests (full suite lib+bins, timings part 1/4) - env: - CARGO_TERM_COLOR: never - RUST_MIN_STACK: 16777216 - run: | - set -euo pipefail - echo "V3_SUITE_START_TS=$(date +%s)" >> "${GITHUB_ENV}" - : > /tmp/v3-test-timings.log - RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --lib --bins -- -Z unstable-options --report-time 2>&1 | tee /tmp/v3-test-timings.log - status=${PIPESTATUS[0]} - if [ "$status" -ne 0 ]; then - echo "::error::cargo test (lib+bins) failed (exit=$status)" - exit "$status" - fi - - - name: v3 tests (full suite determinism harness, timings part 2/4) - env: - CARGO_TERM_COLOR: never - RUST_MIN_STACK: 16777216 - run: | - set -euo pipefail - RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --test determinism_test -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log - status=${PIPESTATUS[0]} - if [ "$status" -ne 0 ]; then - echo "::error::cargo test (determinism_test) failed (exit=$status)" - exit "$status" - fi - - - name: v3 tests (full suite doc tests, timings part 3/4) - env: - CARGO_TERM_COLOR: never - RUST_MIN_STACK: 16777216 - run: | - set -euo pipefail - RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --doc -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log - status=${PIPESTATUS[0]} - if [ "$status" -ne 0 ]; then - echo "::error::cargo test (--doc) failed (exit=$status)" - exit "$status" - fi - - # **HOT-FIX 2026-05-12 — full integration harness execution SKIPPED via - # nonexistent-filter pattern** per operator directive at gunbc#846 ('cut - # all demos and integration tests for now, get v3 to 10 minutes'). - # - # **Why nonexistent-filter pattern instead of skip-step**: the - # `scripts/check-v3-full-suite-split-test-targets.sh` guard requires every - # v3-compiler `[[test]]` target to appear in ci.yml with a `cargo test -p - # v3-compiler --test ... --report-time` invocation (so per-test - # ratchet has timing data). Outright skipping the step broke this guard - # (cursor BLOCKING on #2724). Solution: keep the invocation but filter - # to a nonexistent test name so the integration binary runs with zero - # tests selected — guard satisfied + fast (no test execution) + timing - # log gets empty integration section + per-test ratchet still parses it - # cleanly. - # - # **Restore criteria**: rebuild session per #2722 §5 (OnceLock/cached_compile - # amortization). When each cluster re-enables, replace the nonexistent- - # filter with the cluster-specific filter (e.g., `lane2_stage_2d_symbolic_cost_test::`). - # When all integration tests re-enable, drop the filter entirely and - # restore the original full-execution invocation. - - name: v3 tests (full suite integration harness, HOT-FIX zero-test-filter) - env: - CARGO_TERM_COLOR: never - RUST_MIN_STACK: 16777216 - run: | - set -euo pipefail - echo "::notice::v3 integration test execution SKIPPED via zero-test-filter per operator hot-fix at gunbc#846." - echo "::notice::Guard pattern preserved; integration binary runs zero tests (nonexistent filter)." - if [ -z "${V3_SUITE_START_TS:-}" ]; then - echo "::error::missing V3_SUITE_START_TS (full suite part 1 must run first)" - exit 1 - fi - # Zero-test-filter: `__HOT_FIX_NONEXISTENT_FILTER__` matches no tests; - # binary runs through libtest setup + reports 0 tests run. Satisfies - # check-v3-full-suite-split-test-targets.sh pattern requirement. - RUSTC_BOOTSTRAP=1 cargo test -p v3-compiler --test integration __HOT_FIX_NONEXISTENT_FILTER__ -- -Z unstable-options --report-time 2>&1 | tee -a /tmp/v3-test-timings.log - status=${PIPESTATUS[0]} - elapsed=$(( $(date +%s) - V3_SUITE_START_TS )) - echo "v3 full-suite wall time (integration-skipped): ${elapsed}s" - if [ "$status" -ne 0 ]; then - echo "::error::cargo test (integration, zero-filter) failed (exit=$status) — should never happen with nonexistent filter; investigate." - exit "$status" - fi - echo "::notice::Restore criteria: rebuild session per #2722 §5 OnceLock/cached_compile amortization → per-test wall ≤ 2s ratchet → re-enable per cluster filter (replace __HOT_FIX_NONEXISTENT_FILTER__ with cluster-specific filter)." - - # Build `gunbc-ci` (BinaryShim entrypoint + interim #102-path warn-manifest projector). - - name: v3 gunbc-ci binary (wall-clock warn manifest + BinaryShim stub) - if: always() - run: cargo build -p v3-compiler --bin gunbc-ci - - # Per-test 2s wall-clock ratchet — binding Phase 0 gate. - # Parses the timing log captured by the full-suite steps above; does not - # re-run `cargo test`. Warn-policy rows are projected from - # `dsl/gunbc/test_node_wall_clock_ratchet.dag` via `gunbc-ci wall-clock-warn-manifest` - # (**interim bridge** — not #102 closure; same libtest tokens as `TestNodeCostDimension` - # / gate #101 until policy routes off timing facts). Over-budget warn-listed tests log as warnings; any other test - # above the threshold fails this step. See - # `src/v3/compiler/tests/HANDOFF_PHASE0.md` (TESTING.md § test layers, - # `feedback_test_timeout_2s`). - # - # **`if: always()`** — the ratchet report is still useful on red runs - # (full-suite failure, 4000s transitional-budget overflow). The log is captured via - # `tee` before the enforcement check, so partial timing data survives - # failure and the ratchet can still emit actionable slow-test output. - - name: v3 tests (per-test 2s ratchet) - if: always() - run: | - if [ ! -s /tmp/v3-test-timings.log ]; then - echo "::notice::no timing log captured or log is empty (full-suite steps did not reach cargo test, or tee wrote nothing) — skipping per-test ratchet" - exit 0 - fi - scripts/check-test-timeout.sh /tmp/v3-test-timings.log - - # Default graph (no regen feature): locks in `cfg_attr(dead_code)` hygiene and - # ensures production targets stay clean without relying on the feature build alone. - - name: v3 Compiler Clippy (default features) - run: cargo clippy -p v3-compiler --all-targets -- -D warnings - - - name: v3 Compiler Clippy (bootstrap-regen-fresh) - run: cargo clippy -p v3-compiler --all-targets --features bootstrap-regen-fresh -- -D warnings - - # Type-check lib + default integration harness with the regen feature on - # (clippy already checks targets; this ensures `cargo test` linkage too). - - name: v3 test targets compile with bootstrap-regen-fresh - run: cargo test -p v3-compiler --no-run --features bootstrap-regen-fresh - - # `regen_bootstrap --verify` runs in the required `ci` job (pre-merge - # fail-closed gate; #1543). Skip duplicate here. Dissolution trigger for - # both places: #1559 (see docs/audit/bootstrap-snapshot-drift-dissolution-assessment.md). - - - name: L-7 Substrate accessor reconstruction gate - run: | - # L-7 (INVARIANTS.md): lenses consume substrate query - # functions (`port`, `node`, `resolve_producer`) instead of - # reconstructing local `find_port` / `find_behavior` / ... - # Scan `.dag` lens files for forbidden helper declarations. - matches=$(grep -nE "fn (find_port|find_behavior|resolve_producer|lookup_node|lookup_port)" src/v3/lenses/*.dag 2>/dev/null || true) - if [ -n "$matches" ]; then - echo "::error::L-7 violation: lens reconstructs a substrate lookup locally" - echo "$matches" - exit 1 - fi - - - name: L-8 Lens surface gate - run: | - # L-8 (INVARIANTS.md): migrated .dag lenses must not collapse - # their typed failure carriers into primitives at the public - # Rust surface. The forbidden shape is any `pub fn ... -> T` - # for T in {usize, bool, i64} inside a hand-written wrapper - # alongside a generated lens module — e.g., the deleted - # `pub fn cost_of(&self, port: PortId) -> usize` wrapper that - # shadowed the generated `CostLookup` carrier. - # - # Scope: every `src/v3/compiler/src/lens_*.rs` file (hand-written - # and `*_generated.rs` — catching a collapsed wrapper in generated - # code would mean the emitter regressed). - wrappers=$(ls src/v3/compiler/src/lens_*.rs 2>/dev/null || true) - if [ -z "$wrappers" ]; then - echo "L-8: no lens wrapper files to scan" - exit 0 - fi - matches=$(grep -nE "pub fn .*-> (usize|bool|i64)" $wrappers 2>/dev/null || true) - if [ -n "$matches" ]; then - echo "::error::L-8 violation: lens wrapper collapses typed carrier to a primitive" - echo "$matches" - exit 1 - fi - - - name: Compiler-std consolidation ratchet - run: scripts/check-compiler-std-ratchet.sh - - - name: Banked-dissolutions ratchet - run: scripts/check-banked-dissolutions.sh - - # DB-8 — fixed-point ratchet infrastructure (Lane 3 Stage 3c prep). Staged until - # Lane 1 Stage 1e closes: do not block merges on this job yet. - # - # R3 T-FixedPoint / `docs/r3-program-plan.md` §1.8 gate #16: `self_host_fixed_point` - # is the DB-8 mechanical verifier on the path to the strong fixed-point horizon; - # R1 `pb_self_compile_fixed_point` pass/fail still comes from `verification.dag` + - # `test_runner` — this job's continue-on-error posture does not redefine that gate. + fi + scripts/check-test-timeout.sh /tmp/v3-test-timings.log + - name: v3 Compiler Clippy (default features) + run: cargo clippy -p v3-compiler --all-targets -- -D warnings + - name: v3 Compiler Clippy (bootstrap-regen-fresh) + run: cargo clippy -p v3-compiler --all-targets --features bootstrap-regen-fresh -- -D warnings + - name: v3 test targets compile with bootstrap-regen-fresh + run: cargo test -p v3-compiler --no-run --features bootstrap-regen-fresh + - name: L-7 Substrate accessor reconstruction gate + run: | + # L-7 (INVARIANTS.md): lenses consume substrate query + # functions (`port`, `node`, `resolve_producer`) instead of + # reconstructing local `find_port` / `find_behavior` / ... + # Scan `.dag` lens files for forbidden helper declarations. + matches=$(grep -nE "fn (find_port|find_behavior|resolve_producer|lookup_node|lookup_port)" src/v3/lenses/*.dag 2>/dev/null || true) + if [ -n "$matches" ]; then + echo "::error::L-7 violation: lens reconstructs a substrate lookup locally" + echo "$matches" + exit 1 + fi + - name: L-8 Lens surface gate + run: | + # L-8 (INVARIANTS.md): migrated .dag lenses must not collapse + # their typed failure carriers into primitives at the public + # Rust surface. The forbidden shape is any `pub fn ... -> T` + # for T in {usize, bool, i64} inside a hand-written wrapper + # alongside a generated lens module — e.g., the deleted + # `pub fn cost_of(&self, port: PortId) -> usize` wrapper that + # shadowed the generated `CostLookup` carrier. + # + # Scope: every `src/v3/compiler/src/lens_*.rs` file (hand-written + # and `*_generated.rs` — catching a collapsed wrapper in generated + # code would mean the emitter regressed). + wrappers=$(ls src/v3/compiler/src/lens_*.rs 2>/dev/null || true) + if [ -z "$wrappers" ]; then + echo "L-8: no lens wrapper files to scan" + exit 0 + fi + matches=$(grep -nE "pub fn .*-> (usize|bool|i64)" $wrappers 2>/dev/null || true) + if [ -n "$matches" ]; then + echo "::error::L-8 violation: lens wrapper collapses typed carrier to a primitive" + echo "$matches" + exit 1 + fi + - name: Compiler-std consolidation ratchet + run: scripts/check-compiler-std-ratchet.sh + - name: Banked-dissolutions ratchet + run: scripts/check-banked-dissolutions.sh self_host_ratchet: - # Always schedule on non-draft PRs (and on pushes, where `pull_request` is absent) - # so branch-protection required checks get a definitive result after `v3`. - # The heavy DB-8 matrix still runs only on `push` to `main`; PRs hit the stub below. - # First step validates `v3` outcome (fail-closed on failure/cancel). if: ${{ always() && github.event.pull_request.draft != true }} - # Same sizing rationale as `v3` above: DB-8 release builds + determinism_test (5× matrix) + - # `self_host_fixed_point` run on `ubicloud-standard-8` (#1814); small/default runners saw - # mid-compile shutdown on #1794. **60m** wall so cold-cache / full release `cargo` is unlikely - # to cancel mid-job; ratchet remains non-blocking. (Runner label is orthogonal to P2: - # `rust-toolchain.toml` + no workflow `toolchain:` input.) runs-on: ubicloud-standard-8 timeout-minutes: 60 - needs: [v3] + needs: + - v3 continue-on-error: true steps: - - name: Validate gate evidence (fail-closed under v3 failure) - run: | - echo "Gate evidence: v3.result=${{ needs.v3.result }}" - if [ "${{ needs.v3.result }}" = "failure" ] || [ "${{ needs.v3.result }}" = "cancelled" ]; then - echo "::error::v3 job did not succeed (result=${{ needs.v3.result }}); ratchet cannot claim green." - exit 1 - fi - if [ "${{ needs.v3.result }}" != "success" ]; then - echo "::error::v3 job has unexpected result (result=${{ needs.v3.result }}); expected success after Layer-2 path-regex removal." - exit 1 - fi - echo "Gate evidence validated; ratchet may proceed." - - - name: Checkout - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/checkout@v4 - with: - fetch-depth: 1 - - - name: DB-8 stub (PR / non-main — full matrix is main-push only) - if: github.event_name != 'push' || github.ref != 'refs/heads/main' - run: | - echo "::notice::self_host_ratchet DB-8 release matrix runs only on pushes to main (Lane 1e staged)." - exit 0 - - - name: Setup Rust - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 - with: - cache: false - rustflags: "" - - - name: Cache Cargo (self_host_ratchet) - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - uses: actions/cache@v4 - with: - path: | - ~/.cargo/registry/index/ - ~/.cargo/registry/cache/ - ~/.cargo/git/db/ - target/ - key: cargo-self-host-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/**') }} - restore-keys: | - cargo-self-host-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- - cargo-self-host-${{ runner.os }}- - - # Named DB-8 ratchet (also executed inside the `v3` full suite); release - # build here matches `self_host_fixed_point` and gives a dedicated log section. - # Step-level continue-on-error: one ratchet can fail without aborting the other - # (job-level continue-on-error keeps the workflow green until Lane 1e graduates). - - name: DB-8 determinism_test (5× emit matrix) - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - continue-on-error: true - run: cargo test -p v3-compiler --release --test determinism_test - - - name: DB-8 self_host_fixed_point (staged) - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - continue-on-error: true - run: cargo run -p v3-compiler --release --bin self_host_fixed_point - - - name: DB-8 emit.rs HashMap iteration policy (informational) - if: github.event_name == 'push' && github.ref == 'refs/heads/main' - run: | - if grep -nE "(HashMap|HashSet)::" src/v3/compiler/src/emit.rs; then - echo "::notice::DB-8: emit.rs still uses HashMap/HashSet:: iteration — target is BTree* / sorted keys (determinism_test + ROADMAP Lane 3 Stage 3c prep)" - else - echo "emit.rs: no HashMap::/HashSet:: — consider graduating this check to required when Lane 1e clears debt" - fi + - name: Validate gate evidence (fail-closed under v3 failure) + run: | + echo "Gate evidence: v3.result=${{ needs.v3.result }}" + if [ "${{ needs.v3.result }}" = "failure" ] || [ "${{ needs.v3.result }}" = "cancelled" ]; then + echo "::error::v3 job did not succeed (result=${{ needs.v3.result }}); ratchet cannot claim green." + exit 1 + fi + if [ "${{ needs.v3.result }}" != "success" ]; then + echo "::error::v3 job has unexpected result (result=${{ needs.v3.result }}); expected success after Layer-2 path-regex removal." + exit 1 + fi + echo "Gate evidence validated; ratchet may proceed." + - name: Checkout + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: actions/checkout@v4 + with: + fetch-depth: 1 + - name: DB-8 stub (PR / non-main — full matrix is main-push only) + if: github.event_name != 'push' || github.ref != 'refs/heads/main' + run: | + echo "::notice::self_host_ratchet DB-8 release matrix runs only on pushes to main (Lane 1e staged)." + exit 0 + - name: Setup Rust + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: actions-rust-lang/setup-rust-toolchain@v1.16.0 + with: + cache: false + rustflags: '' + - name: Cache Cargo (self_host_ratchet) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + uses: actions/cache@v4 + with: + path: | + ~/.cargo/registry/index/ + ~/.cargo/registry/cache/ + ~/.cargo/git/db/ + target/ + key: cargo-self-host-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}-${{ hashFiles('src/v3/compiler/**') }} + restore-keys: | + cargo-self-host-${{ runner.os }}-${{ hashFiles('**/Cargo.lock') }}- + cargo-self-host-${{ runner.os }}- + - name: DB-8 determinism_test (5× emit matrix) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + continue-on-error: true + run: cargo test -p v3-compiler --release --test determinism_test + - name: DB-8 self_host_fixed_point (staged) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + continue-on-error: true + run: cargo run -p v3-compiler --release --bin self_host_fixed_point + - name: DB-8 emit.rs HashMap iteration policy (informational) + if: github.event_name == 'push' && github.ref == 'refs/heads/main' + run: | + if grep -nE "(HashMap|HashSet)::" src/v3/compiler/src/emit.rs; then + echo "::notice::DB-8: emit.rs still uses HashMap/HashSet:: iteration — target is BTree* / sorted keys (determinism_test + ROADMAP Lane 3 Stage 3c prep)" + else + echo "emit.rs: no HashMap::/HashSet:: — consider graduating this check to required when Lane 1e clears debt" + fi diff --git a/dsl/gunbc/ci.dag b/dsl/gunbc/ci.dag index b15e5b01855..3c1003a9e8f 100644 --- a/dsl/gunbc/ci.dag +++ b/dsl/gunbc/ci.dag @@ -111,10 +111,13 @@ type CIGateEdge { } // `github_actions_workflow` does not author `pipeline` / `edges` (sole gate-topology -// authority remains those fields). It pins the typed Actions `Workflow` carrier -// regenerated from `.github/workflows/ci.yml` into `dsl/gunbc/ci_github_actions_workflow.dag` -// (byte drift test: `gunbc_ci_github_actions_workflow_dag_matches_yaml_generator_output`). -// That is one mechanical encoding of the repo CI YAML, not a second editorial source for +// authority remains those fields). It pins the typed Actions `Workflow` carrier regenerated from +// `.github/workflows/ci.yml` into `dsl/gunbc/ci_github_actions_workflow.dag` +// (**R3 gate #98**, `ci_yml_hand_authority_dissolved`): +// `.github/workflows/ci.yml` matches deterministic `serde_yaml` serialization after +// `tools/gen_gunbc_ci_workflow_dag` validates the modeled `Workflow` subset (integration test: +// `ci_yml_hand_authority_dissolved`). Gate #59 YAML→`.dag` byte drift stays orthogonal. +// That mechanical encoding is not a second editorial source for // which compiler gates exist; gate-vs-Actions alignment is process + follow-on projection // (WI-2), not dual authority over the same axis (INVARIANTS P2 / modeling Practices 3+5). type CIWorkflowDag { diff --git a/dsl/gunbc/ci_emission.dag b/dsl/gunbc/ci_emission.dag index 587a92ed1c9..87e3e33e861 100644 --- a/dsl/gunbc/ci_emission.dag +++ b/dsl/gunbc/ci_emission.dag @@ -1,7 +1,9 @@ // gunbc/ci_emission.dag — T-WAD WI-2 / Slice 4: `WorkflowRuntime` + `project_github_actions`. // // Canonical GitHub Actions `Workflow` bytes live in `gunbc.ci.github_actions_workflow` -// (`dsl/gunbc/ci_github_actions_workflow.dag`, regenerated from `.github/workflows/ci.yml`). +// (`dsl/gunbc/ci_github_actions_workflow.dag`, regenerated from canonical `.github/workflows/ci.yml`). +// **R3 gate #98:** `ci.yml` is machine-serialized YAML (see `gen_gunbc_ci_workflow_dag` +// `--write-canonical-github-actions-yaml`); no hand-authored comments in the committed artifact. // `CIWorkflowDag.github_actions_workflow` pins that carrier as part of the same authority // row as the gate graph (`dsl/gunbc/ci.dag`). // diff --git a/src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs b/src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs index 425250caa27..36a2ac2ab34 100644 --- a/src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs +++ b/src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs @@ -817,7 +817,8 @@ fn gunbc_ci_github_actions_workflow_authority_compiles() { assert!(dag.diagnostics().is_empty(), "{:?}", dag.diagnostics()); } -/// Mechanical source gate: `.github/workflows/ci.yml` is the YAML authority; the committed +/// Mechanical source gate: the committed `.github/workflows/ci.yml` is **canonical serialized +/// YAML** (R3 gate #98, `ci_yml_hand_authority_dissolved`); the committed /// `dsl/gunbc/ci_github_actions_workflow.dag` row must match the generator library output /// byte-for-byte (same implementation as the `gen_gunbc_ci_workflow_dag` binary). /// @@ -863,6 +864,46 @@ fn gunbc_ci_github_actions_workflow_dag_matches_yaml_generator_output() { ); } +/// **R3 gate #98** (`ci_yml_hand_authority_dissolved`): the committed YamlStatic Actions artifact is +/// **exactly** the canonical `serde_yaml` serialization of its own parse after fail-closed +/// structural projection validation (`tools/gen_gunbc_ci_workflow_dag`), matching §1.8 "byte-identical +/// emission" for `project_github_actions(ci_workflow_dag, YamlStatic)` (same `Workflow` semantics the +/// generator embeds into `gunbc.ci.github_actions_workflow`). +/// +/// Migrate drift with: +/// ```text +/// CTRL_BUILD_WRAP_CARGO=0 cargo run -q -p gen_gunbc_ci_workflow_dag \\ +/// -- --write-canonical-github-actions-yaml .github/workflows/ci.yml +/// CTRL_BUILD_WRAP_CARGO=0 cargo run -q -p gen_gunbc_ci_workflow_dag \\ +/// -- .github/workflows/ci.yml > dsl/gunbc/ci_github_actions_workflow.dag +/// ``` +#[test] +fn ci_yml_hand_authority_dissolved() { + use std::path::Path; + + let repo_root = Path::new(env!("CARGO_MANIFEST_DIR")).join("../../.."); + let repo_root = repo_root + .canonicalize() + .unwrap_or_else(|e| panic!("canonicalize repo root {}: {e}", repo_root.display())); + let ci_yml = repo_root.join(".github/workflows/ci.yml"); + assert!(ci_yml.is_file(), "missing {}", ci_yml.display(),); + + let raw = std::fs::read_to_string(&ci_yml) + .unwrap_or_else(|e| panic!("read {}: {e}", ci_yml.display())); + let v = gen_gunbc_ci_workflow_dag::parse_and_validate_github_actions_workflow_yaml(&raw) + .unwrap_or_else(|e| panic!("validate GitHub Actions workflow YAML: {e}")); + let mut canon = gen_gunbc_ci_workflow_dag::canonical_github_actions_yaml_string(&v) + .unwrap_or_else(|e| panic!("canonicalize workflow YAML emission: {e}")); + if !canon.ends_with('\n') { + canon.push('\n'); + } + assert_eq!( + raw, canon, + "`{}` drifted from canonical emission (gate #98). Run the migration commands documented on this test.", + ci_yml.display() + ); +} + /// **R3 gate #59** — recursive-flex / YamlStatic emit-back lemma: `project_github_actions`'s /// YamlStatic arm is `dag.github_actions_workflow`, which is exactly the carrier wired on /// `ci_workflow_dag` (structural equality in the linked `gunbc.ci` compile). Full diff --git a/src/v3/std/verification.dag b/src/v3/std/verification.dag index 68c7cb424c0..2504acb4459 100644 --- a/src/v3/std/verification.dag +++ b/src/v3/std/verification.dag @@ -582,6 +582,14 @@ type QuantifiedTestClaim { requires: List } +// R3 T-Workflow-As-Data gate #98 (`ci_yml_hand_authority_dissolved`). +// +// Committed `.github/workflows/ci.yml` is the **`YamlStatic` artifact**: byte-identical to +// deterministic `serde_yaml` serialization after `tools/gen_gunbc_ci_workflow_dag`'s fail-closed +// structural parsing onto the modeled `Workflow` carrier (`emit_workflow` subset), aligning with +// `project_github_actions(ci_workflow_dag, YamlStatic)` semantics wired on `CIWorkflowDag`. Receipt: +// Rust test `ci_yml_hand_authority_dissolved` in `t_ci_workflow_as_data_demo_test.rs`. +// // R3 T-Workflow-As-Data gate #101 (`test_cost_dimension_landed`). // // Test execution cost is the timing substrate projected onto a test node in diff --git a/tools/gen_gunbc_ci_workflow_dag/src/lib.rs b/tools/gen_gunbc_ci_workflow_dag/src/lib.rs index edf78c9b5a3..3771908834f 100644 --- a/tools/gen_gunbc_ci_workflow_dag/src/lib.rs +++ b/tools/gen_gunbc_ci_workflow_dag/src/lib.rs @@ -535,3 +535,26 @@ fn emit_action_ref(uses: &str) -> Result> { dag_string(ref_part) )) } + +/// Parse `ci.yml`-shaped YAML, fail closed on constructs the generator cannot project into +/// [`extdeps.github.actions.Workflow`], then return the serde value. +/// +/// Used by emission round-trip checks (`ci_yml_hand_authority_dissolved`) so the repo cannot +/// carry hand-authored YAML that drifts outside the substrate-supported subset without breaking +/// the structural generator first. +pub fn parse_and_validate_github_actions_workflow_yaml( + raw_yaml: &str, +) -> Result> { + let v: Value = serde_yaml::from_str(raw_yaml)?; + emit_workflow(&v)?; + Ok(v) +} + +/// Deterministic emitter for hand-authority dissolution: **semantics encoded in serde_yaml's +/// `Value` serialization** (comments and non-semantic layout are intentionally discarded — +/// `.github/workflows/ci.yml` is the emitted artifact matching `project_github_actions(..., YamlStatic)`). +pub fn canonical_github_actions_yaml_string( + workflow_value: &Value, +) -> Result> { + Ok(serde_yaml::to_string(workflow_value)?) +} diff --git a/tools/gen_gunbc_ci_workflow_dag/src/main.rs b/tools/gen_gunbc_ci_workflow_dag/src/main.rs index c05f60e654e..ca6066d73d0 100644 --- a/tools/gen_gunbc_ci_workflow_dag/src/main.rs +++ b/tools/gen_gunbc_ci_workflow_dag/src/main.rs @@ -1,19 +1,48 @@ -//! Regenerate `dsl/gunbc/ci_github_actions_workflow.dag` from `.github/workflows/ci.yml`. +//! Regenerate `dsl/gunbc/ci_github_actions_workflow.dag` from `.github/workflows/ci.yml`, or +//! rewrite the YAML file to canonical `serde_yaml` bytes (hand-authority dissolution / gate #98). //! -//! Run from repo root (local cargo, bypass ctrl-build shims): +//! Emit `.dag`: //! CTRL_BUILD_WRAP_CARGO=0 cargo run -q -p gen_gunbc_ci_workflow_dag -- .github/workflows/ci.yml \\ //! > dsl/gunbc/ci_github_actions_workflow.dag +//! +//! Canonicalize committed workflow YAML (then re-emit `.dag` as above): +//! CTRL_BUILD_WRAP_CARGO=0 cargo run -q -p gen_gunbc_ci_workflow_dag \\ +//! -- --write-canonical-github-actions-yaml .github/workflows/ci.yml use std::env; use std::fs; use std::io::{self, Write}; +use std::path::Path; -fn main() -> Result<(), Box> { - let path = env::args() - .nth(1) - .ok_or("usage: gen_gunbc_ci_workflow_dag ")?; - let raw = fs::read_to_string(&path)?; - let out = gen_gunbc_ci_workflow_dag::emit_ci_github_actions_workflow_module(&path, &raw)?; - io::stdout().write_all(out.as_bytes())?; +fn usage() -> &'static str { + "usage:\n gen_gunbc_ci_workflow_dag (emit `.dag` module to stdout)\n gen_gunbc_ci_workflow_dag --write-canonical-github-actions-yaml (migrate YAML to deterministic serialization)" +} + +fn write_canonical_github_actions_yaml(path: &Path) -> Result<(), Box> { + let raw = fs::read_to_string(path)?; + let v = gen_gunbc_ci_workflow_dag::parse_and_validate_github_actions_workflow_yaml(&raw)?; + let mut canon = gen_gunbc_ci_workflow_dag::canonical_github_actions_yaml_string(&v)?; + if !canon.ends_with('\n') { + canon.push('\n'); + } + fs::write(path, canon)?; Ok(()) } + +fn main() -> Result<(), Box> { + let mut args = env::args().skip(1); + match (args.next().as_deref(), args.next()) { + (Some("--write-canonical-github-actions-yaml"), Some(path)) => { + write_canonical_github_actions_yaml(Path::new(&path)) + } + (Some(flag), _) if flag.starts_with('-') && flag != "-" => Err(usage().into()), + (Some(path), None) => { + let raw = fs::read_to_string(path)?; + let out = + gen_gunbc_ci_workflow_dag::emit_ci_github_actions_workflow_module(path, &raw)?; + io::stdout().write_all(out.as_bytes())?; + Ok(()) + } + _ => Err(usage().into()), + } +} From fd1bad6250d3f04d3c0c3a45ae7a35d54f3edadc Mon Sep 17 00:00:00 2001 From: Brian Searls Date: Thu, 14 May 2026 18:55:46 +0000 Subject: [PATCH 2/2] fix: regenerate bootstrap snapshots after verification.dag gate #98 commentary regen_bootstrap --verify requires committed bootstrap_generated*.rs to match a fresh compile from std .dag sources. Gate #98 documentation comments shifted SourceSpan byte ranges in verification.dag; refresh snapshots for CI. Co-authored-by: Cursor --- src/v3/compiler/src/bootstrap_generated.rs | 66 +++++++++---------- ...otstrap_generated_without_parse_surface.rs | 66 +++++++++---------- 2 files changed, 66 insertions(+), 66 deletions(-) diff --git a/src/v3/compiler/src/bootstrap_generated.rs b/src/v3/compiler/src/bootstrap_generated.rs index 685c1be0111..3f41b440cab 100644 --- a/src/v3/compiler/src/bootstrap_generated.rs +++ b/src/v3/compiler/src/bootstrap_generated.rs @@ -10183,14 +10183,14 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { target: TransformTarget::Callable(DeclarationId(1331)), inputs: vec![PortId(1058)], output: PortId(1059), - span: SourceSpan::new("src/v3/std/verification.dag", 30917, 30940), + span: SourceSpan::new("src/v3/std/verification.dag", 31472, 31495), })); nodes.push(Behavior::Transform(TransformNode { id: NodeId(894), target: TransformTarget::Callable(DeclarationId(1332)), inputs: vec![PortId(1060)], output: PortId(1061), - span: SourceSpan::new("src/v3/std/verification.dag", 30962, 30996), + span: SourceSpan::new("src/v3/std/verification.dag", 31517, 31551), })); nodes.push(Behavior::Branch(BranchNode { id: NodeId(895), @@ -10201,7 +10201,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { output: PortId(1059), pattern: BranchPattern::UnresolvedVariant { name: "Enumerated".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 30900, 30913), + span: SourceSpan::new("src/v3/std/verification.dag", 31455, 31468), }, binding: Some(PayloadBinding { binding_name: "c".to_string(), @@ -10213,7 +10213,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { output: PortId(1061), pattern: BranchPattern::UnresolvedVariant { name: "Quantified".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 30945, 30958), + span: SourceSpan::new("src/v3/std/verification.dag", 31500, 31513), }, binding: Some(PayloadBinding { binding_name: "q".to_string(), @@ -10222,7 +10222,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { }, ], output: PortId(1062), - span: SourceSpan::new("src/v3/std/verification.dag", 30882, 31000), + span: SourceSpan::new("src/v3/std/verification.dag", 31437, 31555), emit_participation: Some(BranchEmitParticipation::UserMatch), })); nodes.push(Behavior::Bind(BindNode { @@ -10230,7 +10230,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { name: "obligation_for_suite_claim".to_string(), value: PortId(1062), params: vec![PortId(1057)], - span: SourceSpan::new("src/v3/std/verification.dag", 30882, 31000), + span: SourceSpan::new("src/v3/std/verification.dag", 31437, 31555), lane2_workflow: None, emit_participation: Some(BindEmitParticipation::UserCallable), })); @@ -44420,7 +44420,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28182, 28276), + span: SourceSpan::new("src/v3/std/verification.dag", 28737, 28831), }); declarations.push(Declaration { id: DeclarationId(1326), @@ -44449,7 +44449,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28278, 28381), + span: SourceSpan::new("src/v3/std/verification.dag", 28833, 28936), }); declarations.push(Declaration { id: DeclarationId(1327), @@ -44474,7 +44474,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29114, 29191), + span: SourceSpan::new("src/v3/std/verification.dag", 29669, 29746), }); declarations.push(Declaration { id: DeclarationId(1328), @@ -44499,7 +44499,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29193, 29253), + span: SourceSpan::new("src/v3/std/verification.dag", 29748, 29808), }); declarations.push(Declaration { id: DeclarationId(1329), @@ -44524,7 +44524,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29451, 29532), + span: SourceSpan::new("src/v3/std/verification.dag", 30006, 30087), }); declarations.push(Declaration { id: DeclarationId(1330), @@ -44534,8 +44534,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(2729), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 29974, - 29990, + 30529, + 30545, )), }, type_params: vec![], @@ -44546,7 +44546,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29903, 29990), + span: SourceSpan::new("src/v3/std/verification.dag", 30458, 30545), }); declarations.push(Declaration { id: DeclarationId(1331), @@ -44556,8 +44556,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(1329), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 30048, - 30133, + 30603, + 30688, )), }, type_params: vec![], @@ -44568,7 +44568,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29992, 30133), + span: SourceSpan::new("src/v3/std/verification.dag", 30547, 30688), }); declarations.push(Declaration { id: DeclarationId(1332), @@ -44578,8 +44578,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(1329), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 30440, - 30506, + 30995, + 31061, )), }, type_params: vec![], @@ -44590,7 +44590,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 30363, 30506), + span: SourceSpan::new("src/v3/std/verification.dag", 30918, 31061), }); declarations.push(Declaration { id: DeclarationId(1333), @@ -44608,7 +44608,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 30811, 31000), + span: SourceSpan::new("src/v3/std/verification.dag", 31366, 31555), }); declarations.push(Declaration { id: DeclarationId(1334), @@ -44618,8 +44618,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(2731), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 31084, - 31129, + 31639, + 31684, )), }, type_params: vec![], @@ -44630,7 +44630,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 31002, 31129), + span: SourceSpan::new("src/v3/std/verification.dag", 31557, 31684), }); declarations.push(Declaration { id: DeclarationId(1335), @@ -85270,7 +85270,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29950, 29973), + span: SourceSpan::new("src/v3/std/verification.dag", 30505, 30528), }); declarations.push(Declaration { id: DeclarationId(2730), @@ -85290,7 +85290,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 31042, 31058), + span: SourceSpan::new("src/v3/std/verification.dag", 31597, 31613), }); declarations.push(Declaration { id: DeclarationId(2731), @@ -85310,7 +85310,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 31063, 31083), + span: SourceSpan::new("src/v3/std/verification.dag", 31618, 31638), }); declarations.push(Declaration { id: DeclarationId(2732), @@ -86603,7 +86603,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28203, 28232), + span: SourceSpan::new("src/v3/std/verification.dag", 28758, 28787), }); declarations.push(Declaration { id: DeclarationId(2798), @@ -86622,7 +86622,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28237, 28276), + span: SourceSpan::new("src/v3/std/verification.dag", 28792, 28831), }); declarations.push(Declaration { id: DeclarationId(2799), @@ -86641,7 +86641,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29134, 29155), + span: SourceSpan::new("src/v3/std/verification.dag", 29689, 29710), }); declarations.push(Declaration { id: DeclarationId(2800), @@ -86660,7 +86660,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29160, 29191), + span: SourceSpan::new("src/v3/std/verification.dag", 29715, 29746), }); declarations.push(Declaration { id: DeclarationId(2801), @@ -86680,7 +86680,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29235, 29251), + span: SourceSpan::new("src/v3/std/verification.dag", 29790, 29806), }); declarations.push(Declaration { id: DeclarationId(2802), @@ -86700,7 +86700,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 29507, 29530), + span: SourceSpan::new("src/v3/std/verification.dag", 30062, 30085), }); declarations.push(Declaration { id: DeclarationId(2803), diff --git a/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs b/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs index f9f7546219a..074491c565f 100644 --- a/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs +++ b/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs @@ -10183,14 +10183,14 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { target: TransformTarget::Callable(DeclarationId(1315)), inputs: vec![PortId(1058)], output: PortId(1059), - span: SourceSpan::new("src/v3/std/verification.dag", 30917, 30940), + span: SourceSpan::new("src/v3/std/verification.dag", 31472, 31495), })); nodes.push(Behavior::Transform(TransformNode { id: NodeId(894), target: TransformTarget::Callable(DeclarationId(1316)), inputs: vec![PortId(1060)], output: PortId(1061), - span: SourceSpan::new("src/v3/std/verification.dag", 30962, 30996), + span: SourceSpan::new("src/v3/std/verification.dag", 31517, 31551), })); nodes.push(Behavior::Branch(BranchNode { id: NodeId(895), @@ -10201,7 +10201,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { output: PortId(1059), pattern: BranchPattern::UnresolvedVariant { name: "Enumerated".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 30900, 30913), + span: SourceSpan::new("src/v3/std/verification.dag", 31455, 31468), }, binding: Some(PayloadBinding { binding_name: "c".to_string(), @@ -10213,7 +10213,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { output: PortId(1061), pattern: BranchPattern::UnresolvedVariant { name: "Quantified".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 30945, 30958), + span: SourceSpan::new("src/v3/std/verification.dag", 31500, 31513), }, binding: Some(PayloadBinding { binding_name: "q".to_string(), @@ -10222,7 +10222,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { }, ], output: PortId(1062), - span: SourceSpan::new("src/v3/std/verification.dag", 30882, 31000), + span: SourceSpan::new("src/v3/std/verification.dag", 31437, 31555), emit_participation: Some(BranchEmitParticipation::UserMatch), })); nodes.push(Behavior::Bind(BindNode { @@ -10230,7 +10230,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { name: "obligation_for_suite_claim".to_string(), value: PortId(1062), params: vec![PortId(1057)], - span: SourceSpan::new("src/v3/std/verification.dag", 30882, 31000), + span: SourceSpan::new("src/v3/std/verification.dag", 31437, 31555), lane2_workflow: None, emit_participation: Some(BindEmitParticipation::UserCallable), })); @@ -43912,7 +43912,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_declarations() -> Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec Vec