diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 5f3baa5a74b..1c6e9b0152e 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -505,14 +505,18 @@ jobs: 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 in - # `scripts/test-node-wall-clock-ratchet.jsonl` (interim JSONL bridge: same - # libtest tokens as modeled `TestNodeCostDimension` / gate #101; gate #102 - # pass still requires reading policy from substrate, not this file) log as - # warnings when over budget; any other test above the threshold fails this - # step. See + # 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`). # diff --git a/ROADMAP.md b/ROADMAP.md index c4313d711c9..a42ae16562b 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -435,7 +435,7 @@ Tracked debt not dispatched with the 2026-04-21 lane wave (Lane 1e P3.0, SG-2c-4 - **Lane E-I — port `SubValueRelation` + inductive fields + cost algebra (M)**: port Tier 1 (structural) + Tier 2 (lattice) + Tier 3 (`CostBound` + master theorem). Requires E-T, E-C. Pre-flight: verify v3 lowers `CostBound`'s self-referential-through-`List` shape. Acceptance: carrier types ported with round-trip tests; no lens row moves on E-I alone because consumer-visible facts still wait for E-P producer/consumer wiring. - **Lane E-P — per-call descent-evidence provenance (M)**: producer coverage gate #76 receipt is landed as `v3_compiler::dag::per_call_descent_evidence` for the current ratcheted lowered callable surface (live `TransformTarget::Callable` edges; per-argument evidence vector; arithmetic, structural sub-value, preserved-value, and fail-closed unknown/absent cases; `TransformNode` stays unwidened). v2 stores this class of fact on `ExprCall.descent_evidence` (`src/v2/00_core.dag:199`); v3 derives it off-substrate for now. Requires E-T, E-C, E-I. Remaining acceptance for the broader lane: cost lens consumption and same-source v2/v3 cementing beyond the already-wired complexity recurrence consumer. - **Lane E-M — `MethodSemantics` port-or-subsume (S–M)**: **closed via M-b structural subsumption.** Transitive facts (`CollectionSizeEffect` / `CostShape` / `AlgebraFieldTemplate`) remain algebra-declaration facts; v3 method-like calls dispatch through `TransformTarget::{Callable, FieldProject, Operator}` and typed declaration/effect metadata. No `src/v3/std/method_semantics.dag`, no Rust mirror, and no `ExprMethodCall` attachment point. -- **CI ratchet architecture — PARTIAL (T-Receipts W1 second bundle)**: surfaced during the 2026-04-21 reflective analysis (`53b3110..ae8825a` range). Commits `37cd6128`, `4898983e`, `f84ed355` hardened the ratchet against CI-log instability, but `2d8396df` widened the original exemption list. **Landed partial:** classification audit [docs/debt/ci-ratchet-exemption-audit-2026-04-24.md](docs/debt/ci-ratchet-exemption-audit-2026-04-24.md) (2026-04-24 baseline) plus follow-up routing audit [docs/debt/ci-ratchet-exemption-audit-2026-05-02.md](docs/debt/ci-ratchet-exemption-audit-2026-05-02.md) (bounded scope — not a completed Phase 1 per-test timing pass). **Manifest bridge landed:** `scripts/slow-test-exemptions.txt` and `TEST_TIMEOUT_MAX_EXEMPTIONS` are retired; `scripts/check-test-timeout.sh` now reads structured warn policy from `scripts/test-node-wall-clock-ratchet.jsonl` and fails closed for over-budget libtest tokens not warn-listed in the manifest, with `scripts/test-check-test-timeout.sh` wired through CI/Makefile to pin the consumer contract pending #102 projection from modeled `TestNodeCostDimension` timing facts. **D1 residual sweep 2026-05-13:** [docs/debt/slow-test-residual-sweep-2026-05-13.md](docs/debt/slow-test-residual-sweep-2026-05-13.md) verified manifest names against current libtest list and retired one now-under-budget warn row. **Still open:** fresh CI-shaped per-test timing audits, stale warn-row deletion when entries measure under 2s, and per-node duration budgets once fresh timings exist. Dispatch brief: `docs/briefs/ci-ratchet-architecture-audit.md`. +- **CI ratchet architecture — PARTIAL (T-Receipts W1 second bundle)**: surfaced during the 2026-04-21 reflective analysis (`53b3110..ae8825a` range). Commits `37cd6128`, `4898983e`, `f84ed355` hardened the ratchet against CI-log instability, but `2d8396df` widened the original exemption list. **Landed partial:** classification audit [docs/debt/ci-ratchet-exemption-audit-2026-04-24.md](docs/debt/ci-ratchet-exemption-audit-2026-04-24.md) (2026-04-24 baseline) plus follow-up routing audit [docs/debt/ci-ratchet-exemption-audit-2026-05-02.md](docs/debt/ci-ratchet-exemption-audit-2026-05-02.md) (bounded scope — not a completed Phase 1 per-test timing pass). **Warn-policy bridge landed (interim — not #102 closure):** `scripts/slow-test-exemptions.txt` and `TEST_TIMEOUT_MAX_EXEMPTIONS` are retired; checked-in `scripts/test-node-wall-clock-ratchet.jsonl` is deleted in favor of substrate `dsl/gunbc/test_node_wall_clock_ratchet.dag`, with `gunbc-ci wall-clock-warn-manifest` projecting JSONL for `scripts/check-test-timeout.sh`, which fails closed for over-budget libtest tokens not on the warn list (**interim bridge — not #102 closure**; #102 pass target remains `TestNodeCostDimension` timing facts as policy authority). `scripts/test-check-test-timeout.sh` is wired through CI/Makefile to pin the consumer contract. **D1 residual sweep 2026-05-13:** [docs/debt/slow-test-residual-sweep-2026-05-13.md](docs/debt/slow-test-residual-sweep-2026-05-13.md) verified manifest names against current libtest list and retired one now-under-budget warn row. **Still open:** fresh CI-shaped per-test timing audits, stale warn-row deletion when entries measure under 2s, and per-node duration budgets once fresh timings exist. Dispatch brief: `docs/briefs/ci-ratchet-architecture-audit.md`. - **`IntegrationRsScan` / `integration_rs_active_line_contains` in `src/v3/compiler/tests/integration/common/mod.rs` — PARTIAL (T-Receipts; char/byte-char literal widening **PR #1856**).** Historical context (#686 / #705): the scanner was narrow enough that authors on its scan path avoided `b'\\'` / `b'"'` in favor of numeric byte constants. **Landed in #1856:** explicit `ByteCharLiteral` / `CharLiteral` states with escape-aware skipping plus lifetime vs `'…'` disambiguation and focused unit tests — byte-char and character literals no longer false-green Band-C `#[path` / `mod` needles. (Earlier ROADMAP text cited **PR #1791** for partial CI / row hygiene only; **#1856** is the live implementation receipt for the widening in `common/mod.rs`.) **Residual:** raw strings (`r#"…"#`) and byte strings (`b"…"`, `br#"…"#`) are still intentionally loud via the existing opener probe (panic in `Code`). Dissolution for that remainder: widen `IntegrationRsScan` for those forms **or** replace this scan with a structural reader. Owner: unassigned; P2 Boundary Discipline / T-Receipts bundle. - **Stale-receipt sweep in `docs/briefs/` — PARTIAL (T-Receipts W1).** The cited `DeclarationLookup` cleanup brief now carries a historical-receipt banner stating the lane is closed by SG-4b-1-fix and that `DeclarationLookup` / `find_declaration` are gone from `src/v3/lenses/variant_payload.dag`; its stale INVARIANTS refs were also updated to stable anchors. Remaining broad `docs/briefs/` sweep stays open for later post-wave stale claims. **Include:** `docs/design-pure-bootstrap.md`'s hand-maintained count ("78 hand-maintained .rs files") was stale vs. the SG-0 census — **CLOSED in this R1 PR**: all five occurrences (lines 7, 49, 82, 105, 242 of the design doc) now point at the live census, reframed as deltas against the illustrative 78-file baseline, or scoped to the non-test + TESTING residual framing. No frozen absolute count remains. - **Compiler–`std/` consolidation program — specific migrations**: end-state defined in [docs/thesis/compiler-std-consolidation.md](docs/thesis/compiler-std-consolidation.md). Each of the migrations below is a standalone lane; together they collapse the compiler-specific type surface toward the positive definition (pipeline + regen + lens-specific return-type carriers + accessor). **Ratchet:** count of `type` declarations in `src/v3/compiler/*.dag` AND `src/v3/lenses/*.dag` that are NOT in the positive-def set AND NOT exempted → 0. Positive-def: pipeline/regen types + lens-API return carriers (`Origin`, `UnusedParameter`, `ComplexitySummary`, `VariantPayloadShapeLookup` 3-variant, `TemplateArgumentBinding` semantic carrier, `LinearBranchesLookup` terminal lens-private control-flow carrier, etc.). Exempted: `parse_tables.dag` (7 types, pending SG-2c-proper per-row classification). In-ratchet: **workaround/scaffold-shaped lens coproducts with named dissolution triggers (`TemplateArgumentsMatch`, `TemplateArgumentCursor`, `NormalizedInstantiationArgs`, `NonCommutingPairLookup`)** — Lookup-pattern carriers on lens surfaces import `v3.std.lookup::Lookup` (`complexity`, `cost`, `infer_helpers`); `NonCommutingPairLookup` dissolves when typed pairwise non-commute evidence lands on `WorkflowParallelismReport`. Primary count: 4. See thesis doc table for per-file disposition. diff --git a/TESTING.md b/TESTING.md index c1cb7da176e..b6fb1e13bba 100644 --- a/TESTING.md +++ b/TESTING.md @@ -156,21 +156,22 @@ drifting into heavy-integration territory. See The v3 CI job tees libtest `--report-time` output and `scripts/check-test-timeout.sh` enforces `TEST_TIMEOUT_MS` (default -2000 ms). **Warn-only backlog** is the checked-in manifest -**`scripts/test-node-wall-clock-ratchet.jsonl`**: one JSON object per -line, `{"test":"","policy":"warn"}`. That file is an +2000 ms). **Warn-only backlog** is modeled in +**`dsl/gunbc/test_node_wall_clock_ratchet.dag`** and projected to JSONL +via **`gunbc-ci wall-clock-warn-manifest`** for `jq` — one JSON object per +line, `{"test":"","policy":"warn"}`. That path is an **interim shell bridge** (P5 scaffold): same libtest name tokens the substrate will eventually attach `TestNodeCostDimension` facts to (R3 -gate **#101**, `src/v3/std/verification.dag`), but **today the script -reads the JSONL directly** — it is not yet a projection from modeled -test-node timing facts. Retiring `scripts/slow-test-exemptions.txt` +gate **#101**, `src/v3/std/verification.dag`), but **policy is still a +parallel warn-name roster**, not yet derived from modeled test-node +timing facts — so it does **not** satisfy gate **#102** +`slow_test_exemptions_dissolved` as “no side manifest / timing-fact +authority” under `INVARIANTS.md` P5. Retiring `scripts/slow-test-exemptions.txt` drops the free-form table plus the `TEST_TIMEOUT_MAX_EXEMPTIONS` -row-count ratchet and tightens fail-closed behavior; it does **not** by -itself satisfy gate **#102** `slow_test_exemptions_dissolved` as “no -side manifest” under `INVARIANTS.md` P5. Unknown tests over budget **fail +row-count ratchet and tightens fail-closed behavior. Unknown tests over budget **fail closed**. Any `#[test]` that must **warn** instead of **fail** when over -budget needs a manifest row in the **same PR** as the policy intent. -Override: **`TEST_TIMEOUT_MANIFEST`**. +budget needs a row in the `.dag` warn table in the **same PR** as the policy intent. +Override: **`TEST_TIMEOUT_MANIFEST`** (JSONL fixture path for self-tests / local override only). ## Mocks and dependency injection diff --git a/docs/r3-program-plan.md b/docs/r3-program-plan.md index 1057aa60a56..b74025c4cec 100644 --- a/docs/r3-program-plan.md +++ b/docs/r3-program-plan.md @@ -327,7 +327,7 @@ This principle is NOT a separate lane; it's a per-lane gate-shape requirement ap | 99 | `workflow_runtime_open_enum_landed` | substrate-shape | T-Workflow-As-Data | **CONSUMER_LANDED + PASSING** — `WorkflowRuntime = YamlStatic \| BinaryShim` declared at `dsl/gunbc/ci_emission.dag:27`; substrate consumer: `workflow_runtime_initial_enum_matches_t_wad_gate_99` at `src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs` compiles the isolated `WorkflowRuntime` declaration slice and asserts the initial variant labels exactly match `YamlStatic` and `BinaryShim`. Per (c-refined) shape ratified at PR #2749 §7 + Director msg_237bde05 / msg_f9fd669e. `PythonShim` and `InlineGunbc` are DESIGN-ONLY future targets — NOT in the initial enum; each lands via separate substrate-prereq PR paired with a runtime consumer. | | 100 | `project_github_actions_landed` | substrate-shape | T-Workflow-As-Data | **DECLARED + TEXT-RATCHETED** — `fn project_github_actions(dag: CIWorkflowDag, runtime: WorkflowRuntime) -> Workflow` declared at `dsl/gunbc/ci_emission.dag:87`; pinned binding `data gunbc_ci_yml_workflow: Workflow = project_github_actions(ci_workflow_dag, YamlStatic)` at `dsl/gunbc/ci_emission.dag:95`. Consumes `extdeps.github.actions.Workflow` as codomain + `CIWorkflowDag` (PR #2736 carrier) as input domain per (c-refined) substrate-shape per PR #2749 §7. Current receipt: `gunbc_ci_emission_substrate_contract_is_present` at `src/v3/compiler/tests/integration/t_ci_workflow_as_data_demo_test.rs` pins the projection signature and `YamlStatic` binding as source text only; it is not a full-file v3 type-check of `project_github_actions`. The separate YAML-authority byte-drift guard ratchets `.github/workflows/ci.yml` against `gen_gunbc_ci_workflow_dag` output and is not an emit-back consumer of `project_github_actions`. The full `.dag`-authoritative emit-back/type-check receipt + per-arm body completion remain Slice 4-5 follow-on under #98 `ci_yml_hand_authority_dissolved`. | | 101 | `test_cost_dimension_landed` | substrate-shape | T-Workflow-As-Data + Debt-Paydown (Cluster M sub-component) | **CONSUMER_LANDED + PASSING** — `type TestNodeCostDimension` declared at `src/v3/std/verification.dag:578` and `dsl/std/verification.dag:75` (v3 authority reuses T-WAD timing substrate via `TimingBudget` + `TimingMeasurement` over Nanoseconds; legacy dsl projection uses branded non-negative Milliseconds and is marked to retire/rewire under #102) per PR #2761 (eager-crane-176, squash-merged 2026-05-12T18:07:31Z). P5 hand-Rust consumer receipt: `test_cost_dimension_landed_on_test_node` at `src/v3/compiler/tests/integration/test_runner_test.rs:287` compiles a `TestNodeCostDimension` row, asserts the nested timing-budget shape, and routes the referenced `TestClaim` through `TestRunner`. **Distinct from existing compiler-internal cost gates** (#37 `cost_lens_reads_target_realization` / #39 `no_coercion_cost_dimension` / #40 `symbolic_cost_expr_equals_executable` / #70 `cost_lens_demonstration` / #80 `cost_lens_behaviorally_complete` are about `SymbolicCost` as the compiler's cost lens reading target programs); this gate is about `Cost`-as-`Dimension` applied to **test nodes** so the slow-test ratchet **can** attach wall-clock facts to modeled test nodes instead of treating exemptions as an unstructured compiler-local table (substrate-shape sibling of state-check #102). | -| 102 | `slow_test_exemptions_dissolved` | state-check | T-Workflow-As-Data + Debt-Paydown | DECLARED (NEW 2026-05-12 per PR #2744 §1) | **Pass target:** slow-test ratchet policy is read from modeled test-node timing / `TestNodeCostDimension` substrate facts (no checked-in warn-manifest side input). **Interim (not closure):** `scripts/slow-test-exemptions.txt` is deleted and warn rows live in structured `scripts/test-node-wall-clock-ratchet.jsonl` while CI still reads that file directly — bridge work toward #101/#102, not a claim that #102 is GREEN. Pair with kernel-modeling split per `feedback_state_space_vs_behavioral_invariants` + Director msg_f9fd669e. | +| 102 | `slow_test_exemptions_dissolved` | state-check | T-Workflow-As-Data + Debt-Paydown | DECLARED (NEW 2026-05-12 per PR #2744 §1) | **Pass target:** slow-test ratchet policy is read from modeled test-node timing / `TestNodeCostDimension` substrate facts (no checked-in warn-manifest side input). **Interim (not closure / not GREEN for #102):** `scripts/slow-test-exemptions.txt` is deleted; warn-token rows live in `dsl/gunbc/test_node_wall_clock_ratchet.dag` and are projected via `gunbc-ci wall-clock-warn-manifest` for `check-test-timeout.sh` — dissolves the hand-checked JSONL scaffold but is still a **parallel name roster**, not timing-fact authority. Pair with kernel-modeling split per `feedback_state_space_vs_behavioral_invariants` + Director msg_f9fd669e. | | 103 | `ci_uses_affected_set_selection` | state-check | T-Workflow-As-Data + T-Verification | DECLARED (NEW 2026-05-12 per PR #2744 §1) | `BinaryShim` emitter consumes affected-set lens output from PR #2713 (merged); Layer 2 path-regex `if:` gates removed from any remaining workflow files (cross-tier co-owned with clever-tern-670 Slice 7 work). | | 104 | `lens_read_witness_shape_dissolved` | state-check | T-Lens-Behavioral-Parity | **DECLARED** (NEW 2026-05-12 per Director ratification msg_915aa2c1 + operator directive 2026-05-11 at `docs/audit/r3-deferral-anti-pattern-audit-2026-05-11.md` §0: "Miss should go away entirely; if something in substrate defines a Miss it should fail and be investigated asap") | All `Lookup` lens read-channel constructions dissolved; lens `read: (Dag, Behavior) → Witness` honors locked-discipline shape (`Witness::Inhabits | Violates { reason, at }`) without parallel `Lookup::Miss` deferral surface. **Scope at HEAD** (Part A predicate executed at PR #2807 HEAD per codex BLOCKING #4276876807 on PR #2804 — supersedes Director-grep msg_cefcbe05 which omitted 2 files): `src/v3/lenses/cost.dag` 25 sites + `src/v3/lenses/complexity.dag` 25 sites + `src/v3/lenses/infer_helpers.dag` 3 sites + `src/v3/std/algebra.dag` 3 sites + `src/v3/std/substrate.dag` 3 sites + `src/v3/std/lookup.dag` 11 sites = **70 total** across 6 files; parallelism + effect_enumeration + timing_lens .dag layers already clean (0 sites). `ArrowBody::Pending` is related-but-distinct sibling per audit §3.6 — out of scope. **Bundled-migration shape** (Director ratification msg_915aa2c1 + atomic per §P5): TWO parallel migrations bundled, NOT one. (1) **Substrate-level (primary)**: collapse `Lookup::Miss` → `Witness::Violates { reason, at }` across the 70 sites; Phase 1 cost.dag + complexity.dag bundle (50 sites; canonical pattern — `complexity_of` + `symbolic_cost_of` lens read-channel + helpers), Phase 2 monomorphized accessor sweep (substrate.dag 3 + algebra.dag 3 + infer_helpers.dag 3 = 9 sites; `miss_*_lookup` / `hit_*_lookup` constructor pairs at `substrate.dag:691,695` + `algebra.dag:225,229` + `Lookup` return-type at `infer_helpers.dag:141` + doc references at `algebra.dag:219` + `infer_helpers.dag:77,88`), Phase 3 lookup.dag terminal carrier deletion (11 sites + carrier itself). (2) **Testgen-level (companion)**: per-lens TestClaim asserting universal coverage `∀ bind ∈ bootstrap. lens_read(bind) ∈ Inhabits(_)`; fail-closed on `Violates`. Violates set becomes structural test fixture (named-reason enumeration of legitimate exclusions). Without (2), (1) leaves regression window; without (1), (2) has nothing to test. **Two-part predicate** (per Director ratification): Part A (terminal, primary) = `git grep -nE "Lookup<" src/v3/lenses/ src/v3/std/ ; expected = 0` (terminal state after Phase 3 lookup.dag deletion); Part B (regression guard) = `git grep -nE "::Miss\b" src/v3/compiler/src/lens_*_generated.rs ; expected = 0`. Both must pass = green. **Status progression**: DECLARED → CONSUMER_LANDED requires BOTH (a) Substrate Mgr brief authored covering ≥3 lens carriers AND (b) at least one universal-coverage TestClaim landed → PASSING requires Part A + Part B predicates both zero. **Canvas-framing** (operator-surfaced 2026-05-12 23:09Z; relayed to Substrate Mgr in brief): Q-MissOrError (why Miss instead of Error → answer: Miss carries neither reason nor at, forces caller to ignore or fabricate; correct shape is `Witness::Violates { reason: , at: }`); Q-WhyTestgenMissed (3 structural gaps: (a) TestClaim rows scenario-driven not universal-property-driven, (b) parity tests pin frozen v2-oracle snapshots not v3-coverage sweeps, (c) lens-discipline ratchet didn't exist — fix substrate, testgen has property to enforce). **Authority chain**: operator 2026-05-11 + audit §0/§3.1/§3.4 + design-lens-framework.md:51,326,382-384 + design-emission-model.md:958,1206 + R4.D §4 (WISHLIST.md:147 from PR #2800) + R4.D faithfulness framework. **Origin**: Director's 2026-05-12 complexity-lens dump (msg_32a3775e) surfaced concrete evidence of 15 Miss returns at algebra.dag bind layer; operator surfaced the audit-doc precedent; Director provided concrete grep counts (msg_cefcbe05; subsequently superseded — see scope correction below); PM proposed §1.8 row (msg_054e2a43); Director ratified (b) with refinements (msg_915aa2c1). **Scope correction at PR #2807** (codex BLOCKING #4276876807): Director's relayed 64-count omitted 2 files (`algebra.dag` 3 + `infer_helpers.dag` 3 = 6 missing sites). PM verified Part A predicate at `7a7c19d3` HEAD = 70 matches; algebra.dag inclusion is structurally required since `algebra.dag:225 miss_symbolic_cost_lookup()` is the canonical `Lookup::Miss` constructor at the bind layer that emits the 15 Miss returns Director's dump surfaced — excluding it would have left the row's own terminal predicate red post-migration. Scope-statement + Phase 2 reframed accordingly. | | 105 | `symbolic_cost_textbook_coverage_landed` | substrate-shape | T-CostLens-Composition | **CANVAS_RATIFIED** (NEW 2026-05-13 per operator directive at gunbc#846 2026-05-13 ("anything you would find in an algorithms textbook ... our current list looks very slim" + "we need to land this all in R3 please") + Director ratification msg_ad5e934d — Path A RATIFIED, Tier 1 IN-R3 with Tier 2 deferred to R4 with structural-extension caveat; Substrate Mgr canvas Director-RATIFIED 2026-05-13 via PR #2828 squash `fe1dd99c` 12:06:20Z covering all 5 sub-canvas questions Q1-Q5 + extended Q6/Q7 dispositions: Q1-α `Field.compare` for Rational dominance (no parallel Int-tuple); Q2-Y `LinearCost ≡ PolyCost(degree=1)` Practice-4 collapse (same-variant); Q6 Option B `PolynomialCost.degree: Rational where nonzero` carrier refinement (Practice-2; cross-variant redundancy `PolyCost(d=0) ≡ ConstantCost` — Director msg_b80bcaa8 same-variant→P4 / cross-variant→P2 disambiguation rule); Q7 SymbolicCost preserves full expression (Big-O is derived projection); 12 anti-patterns enumerated in canvas §10 + worker brief §11; sign-orthogonal degree admission unblocks operator inverse-exponent request 2026-05-13 ("cubed -> quarter -> quintet roots ... also inverse applies"; n^-x exponential expressible via PolyCost(_, Rational(-x)))) | `SymbolicCost` carrier extended to cover algorithms-textbook common asymptotic bounds — `UnknownCost("reason")` remains algebra-top floor per `docs/design-symbolic-cost-algebra.md:20-33`, but reviewer STOP-SIGNAL fires if a Tier-1-coverable bound is collapsed to Unknown post-extension. **Tier 1 ratified carrier extension** (Path A — rational-degree polynomial promotion with `where nonzero` refinement + LinearCost dissolution + 3 new named variants; final variant count per worker brief execution per `src/v3/std/algebra.dag:190-197`, NOT pre-computed here to avoid drift against ratified Q2-Y collapse): (1) **PROMOTE + REFINE (Q6 Option B)** `PolynomialCost { var: SizeVariable, degree: DegreeAtLeastTwo }` → `PolynomialCost { var: SizeVariable, degree: Rational where nonzero }` per `dsl/std/rational.dag:26` `Field>` + new `nonzero` predicate in KNOWN_PREDICATES — subsumes roots (degree 1/2 = √n, 1/3 = ∛n, 2/3, etc.) + non-integer poly (degree 2.373 Coppersmith-Winograd matrix mult, 2.807 Strassen) + existing integer poly + signed degrees (Rational(-x) for n^-x inverse exponents) — degree=0 is type-rejected (would collide with `ConstantCost` per cross-variant Practice-2 carrier refinement); (1b) **DISSOLVE (Q2-Y same-variant Practice-4)** `LinearCost` collapses into `PolynomialCost(degree=1)` — LinearCost ceases to exist as a distinct variant per Director ratification msg_7d51b699; (2) **ADD** `PolyLogCost { var: SizeVariable, exponent: Int }` for log² n, log^k n (repeated binary search, AKS primality log^7.5 n); (3) **ADD** `ExponentialCost { base: Int, var: SizeVariable }` for 2^n, c^n with integer c ≥ 2 (NP brute-force, subset enumeration); (4) **ADD** `FactorialCost { var: SizeVariable }` for n! (permutation enumeration, TSP brute-force). **Tier 2 R4-deferred** with named-consumer-trigger requirement: `LogLogCost` (vEB trees) / `InverseAckermannCost` (α(n) union-find) / `IteratedLogCost` (log* n) / `HyperExponentialCost` (n^n super-exp) — each requires consumer-evidence justification before R4-promotion per Director rationale "YAGNI per `feedback_state_space_vs_behavioral_invariants`; α(n) carries 80% utility today as ConstantCost-with-named-reason; nested-log structure may be expressible via PolyLogCost composition." **Structural-extension caveat** (Director msg_ad5e934d): if Substrate Mgr canvas surfaces a compositional mechanism for Tier 2 that satisfies `feedback_groundedness_gates_lenses` + composes with Sum/Product algebra + carries consumer-evidence justification, accept that mechanism IN-R3 instead of named variants. **5 sub-canvas substrate-shape questions** (Director-routed via PM relay to warm-wolf-698 — required for carrier ratification): (Q1) **Rational dominance lattice**: `Field>` supports addition + equality but NOT order; polynomial dominance requires order on Rational degrees (1/2 < 1 < 2/3 < 1 < 2 < 2.373) — extend Rational with OrderedField witness, OR carry parallel Int-tuple representation, OR canvas third approach; (Q2) **Linear-vs-Polynomial split reconciliation**: current `DegreeAtLeastTwo` excludes degree=1; options X (keep Linear separate; Polynomial{degree: Rational where degree ≠ 1}) vs Y (collapse Linear into Polynomial(degree=1); Polynomial{degree: Rational where degree > 0}); (Q3) **Sum/Product algebra interaction rules** for new variants: PolyCost · LogCost = PolyLogCost?; PolyCost · ExpCost = ExpCost; ExpCost · ExpCost = ExpCost (base composition rule); FactorialCost · anything = FactorialCost; normalization n^(1/2) · n^(1/2) → n^1; (Q4) **STOP-SIGNAL update**: existing `algebra.dag:69-72` "wanting an 8th variant pause and escalate" — post-extension cap re-resets at 11 variants (Tier 1 only) or 15 (Tier 1+Tier 2); reviewer-tier STOP fires if Tier-1-coverable bound collapsed to UnknownCost; (Q5) **Canvas-shape authoring** before worker dispatch per `feedback_substrate_shape_belongs_in_mgr_canvas`. **Two-part predicate** (per Director ratification + canvas extension; predicates target the actual `SymbolicCost` coproduct body shape at `src/v3/std/algebra.dag:190` — variant arms are pipe-prefixed lines inside the `type SymbolicCost inhabits Semiring` block, NOT top-level `type` declarations; greps use POSIX ERE `[[:space:]]` rather than `\s` for portability across git's ERE engine; HTML entity `|` is used in the patterns below to display literal `|` characters in this markdown table cell without breaking column structure — when copying into a shell, `|` becomes the literal `|` character + the `\` before it remains, yielding the actual regex escape `\|`): Part A (carrier landed) = five grep checks against `src/v3/std/algebra.dag` SymbolicCost body — (i.a) `git grep -nE '^[[:space:]]*\| PolyLogCost' src/v3/std/algebra.dag` returns 1 line (variant arm present); (i.b) `git grep -nE '^[[:space:]]*\| ExponentialCost' src/v3/std/algebra.dag` returns 1 line; (i.c) `git grep -nE '^[[:space:]]*\| FactorialCost' src/v3/std/algebra.dag` returns 1 line; (ii) `git grep -nE '^[[:space:]]*\| PolynomialCost \{ var: SizeVariable, degree: Rational where nonzero \}' src/v3/std/algebra.dag` matches exactly one line (refinement-explicit; NOT `DegreeAtLeastTwo`, NOT `Rational` alone); (iii) `git grep -nE '^[[:space:]]*\| LinearCost' src/v3/std/algebra.dag` returns empty (LinearCost variant arm absent — dissolved per Q2-Y collapse). Receipt-on-failure: if any of (i.a) / (i.b) / (i.c) returns 0 lines, or (ii) returns 0 lines, or (iii) returns ≥1 line, Part A fails closed. Part B (algebra rules landed) = dominance lattice via `Field.compare` (Q1-α, no parallel Int-tuple) + Sum/Product interaction tests pass + LinearCost → PolyCost(d=1) normalization receipt + `PolyCost(_, Rational(0))` type-rejection negative test (Q6 Option B bootstrap ratchet) all via `cargo test -p v3-compiler symbolic_cost_textbook_coverage`. Both must pass = green. **Status progression**: DECLARED → CANVAS_RATIFIED requires Director ratification of Substrate Mgr canvas covering Q1-Q5 (extended with Q6-Q7 mid-cycle per Director scope-extension msg_2c1bfb0e + msg_b80bcaa8) → CONSUMER_LANDED requires Tier 1 carrier landed via worker brief (carrier promotion-with-nonzero-refinement + LinearCost dissolution + 3 new variants + dominance lattice via `Field.compare` + Sum/Product interaction rules + LinearCost→PolyCost(d=1) normalization + `PolyCost(_, Rational(0))` type-rejection bootstrap ratchet test mirroring `timing_lens_substrate_carrier_test.rs`) → PASSING requires Part A + Part B predicates both green. **Authority chain**: operator directive 2026-05-13 + Director ratification msg_ad5e934d + design-symbolic-cost-algebra.md §283-292 ("Add as needed" framing upgraded to "Add as needed for R3 close") + Path A rationale 4-axes (algebraic closure / non-Int poly subsumption / Practice-4 dissolution per `feedback_coproduct_dissolution` / lower carrier surface) + Tier 1 vs Tier 2 split per Director YAGNI + consumer-evidence-trigger rationale. **Anti-patterns reviewers should flag** (Director-enumerated 5): (1) Any Tier 2 variant named without consumer-evidence (premature variants); (2) Any Path B revival (RootCost as separate variant — Practice-4 RED per Director); (3) Linear-Polynomial split decision authored without canvas (substrate-shape question goes through Mgr); (4) Dominance lattice fudging via string-tagged Rational (use real ordered-witness); (5) UnknownCost used for textbook-Tier-1-coverable bounds post-promotion (STOP-SIGNAL violation). **Effort estimate** (PM 3-4 weeks): substrate carrier change 1wk + dominance lattice rules 1wk + Sum/Product algebra interactions 1wk + testgen + demo per variant + parity validation. R3 close timeline extends accordingly per operator-accepted scope. **Origin**: PM §1.2 cost-modeling interrogation probe authored 2026-05-13 (PR #2822) surfaced "current 7-variant SymbolicCost collapses exotic bounds to UnknownCost"; operator interrogated "what is the extent of cost modeling? can we model any arbitrary cost mode i.e. arbitrary roots, arbitrary functions"; PM enumerated 3 ambition levels (minimal rational-degree / medium named-variants / maximal Hardy-field); operator selected "anything you would find in an algorithms textbook" with R3-blocking framing; Director ratified Path A + Tier 1 IN-R3 + 5-sub-canvas-question routing to Substrate Mgr. | diff --git a/docs/r3-remaining-work-dependency-graph.md b/docs/r3-remaining-work-dependency-graph.md index 3f0cb3d918a..e5dde982f09 100644 --- a/docs/r3-remaining-work-dependency-graph.md +++ b/docs/r3-remaining-work-dependency-graph.md @@ -102,7 +102,7 @@ Each entry documents a finding initially enumerated as in-scope here but RETRACT - #99 `workflow_runtime_open_enum_landed` — **CONSUMER_LANDED + PASSING** (PR #2774 merged 2026-05-12; `WorkflowRuntime` declared at `dsl/gunbc/ci_emission.dag:27`; drift-guard consumer green). §1.8 row ratified 2026-05-13. - #100 `project_github_actions_landed` — **CONSUMER_LANDED + PASSING** (PR #2774; `project_github_actions` declared at `dsl/gunbc/ci_emission.dag:87` with pinned binding `gunbc_ci_yml_workflow` at :95). §1.8 row ratified 2026-05-13. - #101 `test_cost_dimension_landed` — **CONSUMER_LANDED + PASSING** (PR #2761; `TestNodeCostDimension` at `src/v3/std/verification.dag:578` + `dsl/std/verification.dag:75`; P5 receipt `test_cost_dimension_landed_on_test_node`). §1.8 row ratified 2026-05-13. -- #102 `slow_test_exemptions_dissolved` — CLOSED (PR #2764 merged) +- #102 `slow_test_exemptions_dissolved` — **DECLARED** (pass target: `TestNodeCostDimension` timing facts; interim warn-token bridge in flight — not GREEN) - #98 `ci_yml_hand_authority_dissolved` — IN-FLIGHT/OPEN - #103 `ci_uses_affected_set_selection` — OPEN (Slice 7; cool-crab-565 canvas at PR #2766) diff --git a/docs/r3-structure.md b/docs/r3-structure.md index f0a85cb0498..92f6c4a4ee5 100644 --- a/docs/r3-structure.md +++ b/docs/r3-structure.md @@ -176,7 +176,7 @@ L6 (`l6_structural_form_coverage`) was moved out of this lane during the engine- - `workflow_runtime_open_enum_landed` — (NEW 2026-05-12) `WorkflowRuntime` sum-type with 2 initial arms (`YamlStatic | BinaryShim | ...`) declared in gunbc namespace as open enum; per (c-refined) shape ratified at PR #2749 §7 + Director msg_237bde05 / msg_f9fd669e. `PythonShim` and `InlineGunbc` are DESIGN-ONLY future targets — NOT in initial enum; each lands via separate substrate-prereq PR paired with a runtime consumer. - `project_github_actions_landed` — (NEW 2026-05-12) `project_github_actions: (CIWorkflowDag, WorkflowRuntime) -> Workflow` projection function declared in gunbc namespace; consumes `extdeps.github.actions.Workflow` as codomain type + `CIWorkflowDag` (PR #2736 carrier introduction) as input domain; per (c-refined) substrate-shape per PR #2749 §7; WI-2 lands DECLARATION + signature only (per-arm bodies are Slice 4-5 work owned by Substrate Mgr) - `test_cost_dimension_landed` — (NEW 2026-05-12; cross-lane co-owned with Debt-Paydown Cluster M sub-component) `Cost` dimension declared on test nodes. **Distinct from existing compiler-internal cost gates** (#37 / #39 / #40 / #70 / #80 are about `SymbolicCost` as the compiler's cost lens reading target programs); this gate is about `Cost`-as-`Dimension` applied to **test nodes** so wall-clock ratchet facts **can** attach to modeled test nodes (substrate-shape sibling of state-check #102 below). - - `slow_test_exemptions_dissolved` — (NEW 2026-05-12; cross-lane co-owned with Debt-Paydown) **Pass target:** ratchet policy comes from modeled test-node timing / `TestNodeCostDimension` facts — no hand-maintained warn-manifest side file. **Interim:** `scripts/slow-test-exemptions.txt` deleted; structured JSONL (`scripts/test-node-wall-clock-ratchet.jsonl`) still read by `check-test-timeout.sh` until the runner wires through substrate facts (P5 bridge, not #102 closure). State-check sibling of `test_cost_dimension_landed` per kernel-modeling discipline split (`feedback_state_space_vs_behavioral_invariants` + Director msg_f9fd669e). + - `slow_test_exemptions_dissolved` — (NEW 2026-05-12; cross-lane co-owned with Debt-Paydown) **Pass target:** ratchet policy comes from modeled test-node timing / `TestNodeCostDimension` facts — no hand-maintained warn-manifest side file. **Interim (not #102 closure):** `scripts/slow-test-exemptions.txt` deleted; checked-in `scripts/test-node-wall-clock-ratchet.jsonl` retired in favor of `dsl/gunbc/test_node_wall_clock_ratchet.dag` + `gunbc-ci wall-clock-warn-manifest` projection for `check-test-timeout.sh` until the runner consumes timing facts as authority (P5 bridge). State-check sibling of `test_cost_dimension_landed` per kernel-modeling discipline split (`feedback_state_space_vs_behavioral_invariants` + Director msg_f9fd669e). - `ci_uses_affected_set_selection` — (NEW 2026-05-12; cross-lane co-owned with T-Verification) `BinaryShim` emitter consumes affected-set lens output from PR #2713 (merged); Layer 2 path-regex `if:` gates removed from any remaining workflow files (cross-tier co-owned with clever-tern-670 Slice 7 work) - **T-Lens-Self-Application** (NEW 2026-05-04; demonstrates recursive-flex thesis claim). - `lens_self_application_demonstrated` — gunbc lenses (cost / complexity / parallelism / timing) applied to gunbc's own build/CI workflow (modeled as `.dag` data per T-Workflow-As-Data); produces `DimensionReport` for each lens; demonstrates that the same lens framework users get also validates the workflow that produces gunbc itself diff --git a/dsl/gunbc/ci_github_actions_workflow.dag b/dsl/gunbc/ci_github_actions_workflow.dag index bac74c80f59..335ab96f32d 100644 --- a/dsl/gunbc/ci_github_actions_workflow.dag +++ b/dsl/gunbc/ci_github_actions_workflow.dag @@ -179,6 +179,16 @@ data gunbc_ci_github_actions_workflow: Workflow = { if_condition: none, continue_on_error: false, timeout_minutes: none + }, RunStep { + name: Some { value: "Test-timeout ratchet self-test (consumer not ceremonial)" }, + id: none, + run: "bash scripts/test-check-test-timeout.sh", + shell: Bash, + env: none, + working_directory: none, + if_condition: none, + continue_on_error: false, + timeout_minutes: none }, RunStep { name: Some { value: "Rust toolchain single-authority check (P2)" }, id: none, @@ -406,6 +416,16 @@ data gunbc_ci_github_actions_workflow: Workflow = { if_condition: none, continue_on_error: false, timeout_minutes: none + }, RunStep { + name: Some { value: "v3 gunbc-ci binary (wall-clock warn manifest + BinaryShim stub)" }, + id: none, + run: "cargo build -p v3-compiler --bin gunbc-ci", + shell: Bash, + env: none, + working_directory: none, + if_condition: Some { value: "always()" }, + continue_on_error: false, + timeout_minutes: none }, RunStep { name: Some { value: "v3 tests (per-test 2s ratchet)" }, id: none, diff --git a/dsl/gunbc/test_node_wall_clock_ratchet.dag b/dsl/gunbc/test_node_wall_clock_ratchet.dag new file mode 100644 index 00000000000..3e5040eb8dc --- /dev/null +++ b/dsl/gunbc/test_node_wall_clock_ratchet.dag @@ -0,0 +1,108 @@ +// gunbc/test_node_wall_clock_ratchet.dag — **Interim** Phase-0 per-test wall-clock +// warn policy (libtest name tokens) for shell/JQ consumption. Canonical R3 gate **#102** +// (`slow_test_exemptions_dissolved`) pass target: derive policy from modeled +// `TestNodeCostDimension` / timing facts — this table is a bridge until that wiring lands. +// +// CI `scripts/check-test-timeout.sh` projects this modeled `List` into the +// JSONL lines consumed by `jq` (same `{"test":...,"policy":"warn"}` shape as +// the retired hand-only manifest). Single edit surface: add/remove rows here. +// +// Related: `TestNodeCostDimension` + `TestNodeRef` in `src/v3/std/verification.dag` +// (gate #101 substrate); this table names the same libtest tokens until every +// slow test is either sped up or modeled with explicit budget/measured facts. + +module gunbc.test_node_wall_clock_ratchet + +import std.list { List } + +type WallClockWarnLibtestToken { + test: String +} + +data wall_clock_warn_libtest_tokens: List = [ + { test: "db8_rust_emit_avoids_time_paths_and_float_hooks_on_program_matrix" }, + { test: "emit_matrix_module_go_is_deterministic" }, + { test: "emit_matrix_module_python_is_deterministic" }, + { test: "emit_matrix_module_rust_is_deterministic" }, + { test: "emit_matrix_program_go_is_deterministic" }, + { test: "emit_matrix_program_python_is_deterministic" }, + { test: "emit_matrix_program_rust_is_deterministic" }, + { test: "four_fixture_disk_sources_emit_deterministically" }, + { test: "m1_5_testgen_test::testgen_lens_emits_claims_as_structural_testclaim_values" }, + { test: "m1_5_testgen_test::testgen_generated_claims_execute_against_compile_boundary" }, + { test: "m1_5_testgen_test::representative_generated_claims_cover_predicate_families" }, + { test: "m1_5_testgen_test::representative_generated_claims_execute_against_compile_boundary" }, + { test: "four_fixture_regression_test::four_fixture_suite_shares_one_reachability_shape" }, + { test: "common::cached_compile::tests::cached_compile_any_returns_clean_dag_when_key_warmed_by_strict" }, + { test: "int_literal_cardinality_test::int_refinement_overflow_is_proven_parametric_for_representable_widths" }, + { test: "lane2_stage_2d_symbolic_cost_test::branch_reports_constant_when_both_arms_constant" }, + { test: "lane2_stage_2d_symbolic_cost_test::cost_dag_compiles_cleanly" }, + { test: "lane2_stage_2d_symbolic_cost_test::cost_generated_module_matches_checked_in_snapshot" }, + { test: "lane2_stage_2d_symbolic_cost_test::recursive_fn_body_contributes_to_loop_cost" }, + { test: "lane2_stage_2d_symbolic_cost_test::recursive_fn_reports_linear_via_loop_lowering" }, + { test: "lane2_stage_2d_symbolic_cost_test::transform_single_op_reports_constant" }, + { test: "lane2_stage_2d_symbolic_cost_test::value_reports_constant" }, + { test: "m0_acceptance::compile_boundary_is_fail_closed" }, + { test: "m0_acceptance::post_sweep_port_state_matches_diagnostic_table" }, + { test: "m1_substrate_test::referenced_port_walk_real_helper_stack_compiles" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_emitted_module_compares_reflected_port_ids_in_list_contains" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_emitted_module_invokes_reflected_dag_function" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_emitted_module_matches_reflected_behavior_payloads" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_emitted_module_returns_reflected_source_span_list" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_emitted_module_returns_user_record_list_from_reflected_binds" }, + { test: "m1_3_emit_rust_test::rustc_roundtrip_generic_list_fold_prints_one" }, + { test: "m2_lens_cost_migration_test::complexity_dag_compiles_cleanly" }, + { test: "m2_lens_cost_migration_test::complexity_dag_runs_end_to_end_via_rustc_harness" }, + { test: "m2_lens_cost_migration_test::complexity_generated_module_matches_checked_in_snapshot" }, + { test: "m2_lens_idempotency_migration_test::idempotency_emitted_analyze_matches_oracle" }, + { test: "m2_lens_provenance_migration_test::lens_provenance_dag_runs_end_to_end_via_rustc_harness" }, + { test: "m2_lens_unused_parameters_migration_test::unused_parameters_dag_runs_end_to_end_via_rustc_harness" }, + { test: "m2_lens_unused_parameters_migration_test::unused_parameters_dag_self_analysis_reports_zero_findings" }, + { test: "t_pb_b_1_dag_runner_test::r1c_e_emit_gates_suite_passes_through_runner" }, + { test: "r3_verification_l4_l7_l5_skeleton_test::r3_verification_l4_emit_eval_false_branch_passes_w1_emit_vs_eval" }, + { test: "r3_verification_l4_l7_l5_skeleton_test::r3_verification_l4_l7_direct_suite_lists_four_l4_certification_seed_claims" }, + { test: "r3_verification_l4_l7_l5_skeleton_test::r3_verification_l7_algebraic_law_matrix_has_current_runner_receipts" }, + { test: "complexity_lens_behavioral_completion::literal_bind_cements_constant_complexity_summary" }, + { test: "complexity_lens_behavioral_completion::recursive_countdown_cements_linear_work_and_span" }, + { test: "cost_lens_symbolic_consumer_test::literal_bind_pins_symbolic_cost_of_constant_on_fixture" }, + { test: "cost_lens_symbolic_consumer_test::recursive_countdown_pins_symbolic_cost_linear_and_sizevar_on_fixture" }, + { test: "cost_lens_symbolic_consumer_test::e_p_sub_value_relation_per_call_landed_cost_lens_routes_through_per_call_pattern_query" }, + { test: "e6_g1a_option3_static_lens_test::e6_g1a_option3_static_lens_mini_report_executes_without_reflection_imports" }, + { test: "lens_behavioral_parity_demonstration_test::r3_gate_73_demonstrates_complexity_certainty_is_proven" }, + { test: "sg2_parse_authority_test::parse_surface_dag_compiles_cleanly_for_regen_parse" }, + { test: "sg2c1_parse_tables_authority_test::parse_tables_generated_module_matches_checked_in_snapshot" }, + { test: "sg6_hand_authored_census_test::sg6_regen_lens_cli_smoke_regenerates_named_entry_without_drift" }, + { test: "t_demo_fixture_test::t_demo_canonical_suites_are_runner_visible" }, + { test: "t_ci_workflow_as_data_demo_test::lens_self_application_demonstrated_bootstrap_ci_modeled_exclusivity" }, + { test: "t_ci_workflow_as_data_demo_test::ci_workflow_as_data_demo_timing_dimension_report_on_bootstrap_shell" }, + { test: "t_ci_workflow_as_data_demo_test::lens_self_application_demonstrated_timing_dimension_report_on_ci_modeled_workflow" }, + { test: "t_pb_b_1_dag_runner_test::r3_gate_87_cementing_regen_lens_suites_pass_through_runner" }, + { test: "tc1_substrate_lens_eta_equivalence_strict_fire_test::tc1_strict_fire_suite_has_canonical_executable_claim_with_valid_binary_shape" }, + { test: "thesis_validation_test::kf_1_structural_list_operation_ordering_holds" }, + { test: "dimension::analyze_complexity_tests::analyze_complexity_fail_arm_has_no_composed_field" }, + { test: "dimension::analyze_complexity_tests::analyze_complexity_fails_closed_with_typed_diagnostic_on_missing_cost" }, + { test: "dimension::analyze_complexity_tests::analyze_complexity_matches_analyze_symbolic_cost_dimension_for_known_workflow" }, + { test: "dimension::analyze_complexity_tests::analyze_complexity_returns_ok_for_bounded_int_add_workflow" }, + { test: "dimension::analyze_complexity_tests::analyze_complexity_violation_entries_are_typed_diagnostic_enums" }, + { test: "dimension::fail_closed_tests::missing_symbolic_cost_surfaces_as_dimension_fail_with_violates_witnesses" }, + { test: "dimension::fail_closed_tests::transform_workflow_root_still_backward_reaches_operand_ports" }, + { test: "e7_analyze_complexity_integration::analyze_complexity_composed_matches_lens_at_workflow_root" }, + { test: "e7_analyze_complexity_integration::analyze_complexity_public_api_delegates_to_symbolic_cost_dimension" }, + { test: "e7_analyze_complexity_integration::analyze_complexity_public_api_honors_supplied_workflow_root" }, + { test: "e7_analyze_complexity_integration::analyze_complexity_public_api_preserves_typed_witness_envelope_on_ok" }, + { test: "lane2_stage_2f_dimension_test::analyze_symbolic_cost_composed_matches_lens_at_workflow_root" }, + { test: "lens_behavioral_parity_demonstration_test::r3_gate_73_demonstrates_symbolic_cost_is_keyed_by_countdown_parameter" }, + { test: "lens_cost_target_realization_test::cost_lens_composes_symbolic_cost_with_rust_type_realization_row" }, + { test: "lens_cost_target_realization_test::cost_lens_demonstration_composes_representative_rust_program_cost" }, + { test: "m1_5_verification_test::symbolic_cost_expr_equals_smoke_suite_passes" }, + { test: "r3_free_consequences_second_batch_test::cross_target_optimization_constant_fold_consistent_has_symbolic_cost_witness" }, + { test: "r3_free_consequences_second_batch_test::cross_target_optimization_cost_structurally_derived_receipt" }, + { test: "r3_free_consequences_second_batch_test::r3_free_consequences_second_batch_reaches_expected_consumer_shapes" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_builder_fails_closed_when_merge_step_has_no_log_cost_witness" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_basis_cost_hits_symbolic_cost_lens_table" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_declaration_pins_subject_span_and_per_write_log_budget" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_log_replicas_in_symbolic_cost_lens_table" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_per_op_budget_is_not_sound_ceiling_for_composed_workflow" }, + { test: "t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_unknown_ceiling_covers_composed_workflow" } + +] diff --git a/dsl/std/verification.dag b/dsl/std/verification.dag index 0271f038030..4ac4a8901fb 100644 --- a/dsl/std/verification.dag +++ b/dsl/std/verification.dag @@ -46,10 +46,11 @@ type TestClaim { // modeled test node. This deliberately does not reuse compiler-internal // `SymbolicCost`: the slow-test ratchet needs observed/budgeted wall-clock // cost for the test node itself. **Target:** #102 derives ratchet policy from -// those substrate facts. **Today:** CI still reads the checked-in JSONL warn -// manifest `scripts/test-node-wall-clock-ratchet.jsonl` (structured bridge, -// same libtest tokens) until the runner projects budgets from `.dag` data — not -// yet “dissolved” off a side file under P5. +// those substrate facts. **Interim (not #102 closure):** warn-token rows live in +// `dsl/gunbc/test_node_wall_clock_ratchet.dag` and are projected for shell/JQ until +// the runner routes policy off `TestNodeCostDimension` facts instead of a parallel +// warn-name list. **Follow-on:** attach explicit `TimingBudget` / `TimingMeasurement` +// rows per test where paydown replaces warn-only policy. // // Legacy dsl projection note: this tree does not carry T-WAD's v3 // `TimingBudget` / `TimingMeasurement` / `Nanoseconds` substrate yet. diff --git a/scripts/check-test-timeout.sh b/scripts/check-test-timeout.sh index 717db35f8e2..6997f069ce7 100755 --- a/scripts/check-test-timeout.sh +++ b/scripts/check-test-timeout.sh @@ -5,19 +5,15 @@ # Reads libtest `--report-time` output (lines like # `test foo::bar ... ok <1.234s>`) from a pre-captured log file and fails # if any single `#[test]` exceeded the budget (default 2000 ms, aligns -# with `feedback_test_timeout_2s`). Tests listed in the checked-in JSONL -# warn manifest log a warning when over budget instead of failing — still a -# hand-maintained side file (P5 bridge), but structured JSONL replacing the -# retired free-form `slow-test-exemptions.txt` table + row-count ratchet. +# with `feedback_test_timeout_2s`). Warn-only policy rows are projected from +# substrate (`dsl/gunbc/test_node_wall_clock_ratchet.dag`) via `gunbc-ci +# wall-clock-warn-manifest` (**interim toward #102** — canonical #102 is timing-fact +# authority via `TestNodeCostDimension`) into JSONL consumed here — same +# `{"test":"","policy":"warn"}` transport `jq` already understands. # -# **Naming alignment (gate #101; gate #102 in flight).** Rows use the same -# libtest name tokens as `--report-time` — the tokens that -# `TestNodeCostDimension` will attach to in `src/v3/std/verification.dag`. -# **Enforcement here still -# reads this file** until #102 wires the ratchet to modeled timing facts. Each -# line is JSON `{"test":"","policy":"warn"}` carrying warn-only policy -# for that node (shell transport today; substrate projection is the retirement -# path). +# **Naming alignment (gates #101 / #102).** Row tokens match libtest +# `--report-time` names — the same strings `TestNodeCostDimension` attaches +# to in `src/v3/std/verification.dag`. # # **Why parse an external log, not re-run `cargo test`.** The v3 CI job # already runs `cargo test -p v3-compiler` once (budget 1200s) and the @@ -52,34 +48,59 @@ # TEST_TIMEOUT_MS Override budget (default 2000). # TEST_TIMEOUT_PACKAGE Cargo package for the local fallback # (default v3-compiler). -# TEST_TIMEOUT_MANIFEST Path to JSONL warn manifest (default -# scripts/test-node-wall-clock-ratchet.jsonl). +# TEST_TIMEOUT_MANIFEST Optional path to JSONL warn manifest (self-tests / +# emergencies). When unset, rows come from `gunbc-ci +# wall-clock-warn-manifest` (requires built binary). +# GUNBC_CI_BIN Override path to `gunbc-ci` (default: search +# target/debug|release under repo root). +# GITHUB_WORKSPACE Passed through to `gunbc-ci` (default: repo root). # -# **Fail-closed policy (interim ratchet).** A test whose wall time exceeds -# `TEST_TIMEOUT_MS` and whose libtest name is **not** warn-listed in the -# manifest is a ratchet **failure**. There is no `TEST_TIMEOUT_MAX_EXEMPTIONS` -# floor: the JSONL is the sole warn backlog for this step — add a -# `{"policy":"warn"}` row in the **same PR** as any intentional expansion of -# warn-only coverage. Omitting a slow test fails closed (unknown over-budget -# names error this step). Closing R3 gate #102 still requires moving policy -# input off this hand manifest onto modeled test-node timing facts. +# **Fail-closed policy.** A test whose wall time exceeds `TEST_TIMEOUT_MS` and +# whose libtest name is **not** warn-listed fails this step. Add a row to +# `dsl/gunbc/test_node_wall_clock_ratchet.dag` in the **same PR** as any +# intentional warn-only expansion. set -euo pipefail log_file_arg=${1:-} budget_ms=${2:-${TEST_TIMEOUT_MS:-2000}} pkg=${TEST_TIMEOUT_PACKAGE:-v3-compiler} -manifest=${TEST_TIMEOUT_MANIFEST:-scripts/test-node-wall-clock-ratchet.jsonl} script_dir=$(cd "$(dirname "$0")" && pwd) repo_root=$(cd "$script_dir/.." && pwd) cd "$repo_root" cleanup_log="" -trap '[ -n "$cleanup_log" ] && rm -f "$cleanup_log"' EXIT +cleanup_manifest="" +trap '[ -n "$cleanup_log" ] && rm -f "$cleanup_log"; [ -n "$cleanup_manifest" ] && rm -f "$cleanup_manifest"' EXIT + +if [ -n "${TEST_TIMEOUT_MANIFEST:-}" ]; then + manifest=${TEST_TIMEOUT_MANIFEST} +else + gunbc_ci_bin=${GUNBC_CI_BIN:-} + if [ -z "$gunbc_ci_bin" ]; then + for c in "$repo_root/target/debug/gunbc-ci" "$repo_root/target/release/gunbc-ci"; do + if [ -x "$c" ]; then + gunbc_ci_bin=$c + break + fi + done + fi + if [ -z "$gunbc_ci_bin" ]; then + echo "::error::gunbc-ci binary not found (build with: cargo build -p v3-compiler --bin gunbc-ci, or set GUNBC_CI_BIN / TEST_TIMEOUT_MANIFEST)." + exit 2 + fi + manifest=$(mktemp -t wall-clock-warn.XXXXXX.jsonl) + cleanup_manifest=$manifest + export GITHUB_WORKSPACE=${GITHUB_WORKSPACE:-$repo_root} + if ! "$gunbc_ci_bin" wall-clock-warn-manifest >"$manifest"; then + echo "::error::gunbc-ci wall-clock-warn-manifest failed" + exit 2 + fi +fi if ! command -v jq >/dev/null 2>&1; then - echo "::error::jq is required to parse ${manifest} (install jq)." + echo "::error::jq is required to parse warn manifest (install jq)." exit 2 fi @@ -179,7 +200,7 @@ fi echo "Parsed ${parsed_count} test-result lines from timing log." warn_list=$(mktemp) -trap '[ -n "$cleanup_log" ] && rm -f "$cleanup_log"; rm -f "$warn_list"' EXIT +trap '[ -n "$cleanup_log" ] && rm -f "$cleanup_log"; [ -n "$cleanup_manifest" ] && rm -f "$cleanup_manifest"; rm -f "$warn_list"' EXIT jq -r 'select(.policy == "warn") | .test' "$manifest" | sort -u >"$warn_list" unexpected="" @@ -197,8 +218,13 @@ if [ -n "$violations" ]; then done <<< "$violations" fi +warn_source="warn-policy manifest" +if [ -z "${TEST_TIMEOUT_MANIFEST:-}" ]; then + warn_source="warn-policy manifest (projected from dsl/gunbc/test_node_wall_clock_ratchet.dag)" +fi + if [ -n "$warned" ]; then - echo "::warning::${budget_ms}ms ratchet: warn-policy tests exceeded budget (paydown backlog in $manifest):" + echo "::warning::${budget_ms}ms ratchet: warn-policy tests exceeded budget ($warn_source):" printf '%s' "$warned" | awk -F'\t' 'NF==2 {printf " %s — %sms\n", $1, $2}' fi @@ -209,7 +235,7 @@ if [ -n "$unexpected" ]; then echo "Options:" echo " 1. Speed up the test (share bootstrap via OnceLock, shrink fixtures," echo " collapse fine-grained cases)." - echo " 2. Add a {\"test\":\"\",\"policy\":\"warn\"} line to $manifest with a ROADMAP/task reference in commit message." + echo ' 2. Add a WallClockWarnLibtestToken row to dsl/gunbc/test_node_wall_clock_ratchet.dag (same PR as the policy intent).' echo " 3. Mark #[ignore]-by-default if the coverage is redundant." exit 1 fi diff --git a/scripts/ci-merge/sg0-pr-body-append.3032.txt b/scripts/ci-merge/sg0-pr-body-append.3032.txt new file mode 100644 index 00000000000..1361cc939eb --- /dev/null +++ b/scripts/ci-merge/sg0-pr-body-append.3032.txt @@ -0,0 +1,4 @@ +SG-0 hand-path delta: +2 + +SG-0 pairing: (c) dispatch-tracked T-WAD Full R3-close program (operator/Director ratification) covers this census net-add for Slice 6 / gate #102 program; P5(b) receipt — deleted scaffold `scripts/test-node-wall-clock-ratchet.jsonl` (interim warn-token bridge → `dsl/gunbc/test_node_wall_clock_ratchet.dag` + `gunbc-ci`; **not** #102 closure — pass target remains `TestNodeCostDimension` timing facts). +gunbc#828 diff --git a/scripts/test-check-test-timeout.sh b/scripts/test-check-test-timeout.sh index 50ce8abd33a..eda8dc2a7bb 100755 --- a/scripts/test-check-test-timeout.sh +++ b/scripts/test-check-test-timeout.sh @@ -1,10 +1,9 @@ #!/usr/bin/env bash # Self-test for scripts/check-test-timeout.sh. # -# Pins the T-WAD Slice 6 bridge behavior: slow-test policy comes from the -# structured JSONL manifest, and over-budget tests not warn-listed in the -# manifest fail closed. The retired slow-test-exemptions.txt count floor must not be -# required for the consumer to run. +# Drives warn vs fail cases via TEST_TIMEOUT_MANIFEST (temp JSONL fixture only). +# Production uses dsl/gunbc/test_node_wall_clock_ratchet.dag projected by +# gunbc-ci wall-clock-warn-manifest (interim #102-path bridge, not #102 closure). set -euo pipefail @@ -139,4 +138,4 @@ if [ "$failures" -ne 0 ]; then exit 1 fi -echo "PASS: check-test-timeout JSONL manifest behavior verified" +echo "PASS: check-test-timeout warn-manifest behavior verified" diff --git a/scripts/test-node-wall-clock-ratchet.jsonl b/scripts/test-node-wall-clock-ratchet.jsonl deleted file mode 100644 index f3a02bbc793..00000000000 --- a/scripts/test-node-wall-clock-ratchet.jsonl +++ /dev/null @@ -1,84 +0,0 @@ -{"test":"db8_rust_emit_avoids_time_paths_and_float_hooks_on_program_matrix","policy":"warn"} -{"test":"emit_matrix_module_go_is_deterministic","policy":"warn"} -{"test":"emit_matrix_module_python_is_deterministic","policy":"warn"} -{"test":"emit_matrix_module_rust_is_deterministic","policy":"warn"} -{"test":"emit_matrix_program_go_is_deterministic","policy":"warn"} -{"test":"emit_matrix_program_python_is_deterministic","policy":"warn"} -{"test":"emit_matrix_program_rust_is_deterministic","policy":"warn"} -{"test":"four_fixture_disk_sources_emit_deterministically","policy":"warn"} -{"test":"m1_5_testgen_test::testgen_lens_emits_claims_as_structural_testclaim_values","policy":"warn"} -{"test":"m1_5_testgen_test::testgen_generated_claims_execute_against_compile_boundary","policy":"warn"} -{"test":"m1_5_testgen_test::representative_generated_claims_cover_predicate_families","policy":"warn"} -{"test":"m1_5_testgen_test::representative_generated_claims_execute_against_compile_boundary","policy":"warn"} -{"test":"four_fixture_regression_test::four_fixture_suite_shares_one_reachability_shape","policy":"warn"} -{"test":"common::cached_compile::tests::cached_compile_any_returns_clean_dag_when_key_warmed_by_strict","policy":"warn"} -{"test":"int_literal_cardinality_test::int_refinement_overflow_is_proven_parametric_for_representable_widths","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::branch_reports_constant_when_both_arms_constant","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::cost_dag_compiles_cleanly","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::cost_generated_module_matches_checked_in_snapshot","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::recursive_fn_body_contributes_to_loop_cost","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::recursive_fn_reports_linear_via_loop_lowering","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::transform_single_op_reports_constant","policy":"warn"} -{"test":"lane2_stage_2d_symbolic_cost_test::value_reports_constant","policy":"warn"} -{"test":"m0_acceptance::compile_boundary_is_fail_closed","policy":"warn"} -{"test":"m0_acceptance::post_sweep_port_state_matches_diagnostic_table","policy":"warn"} -{"test":"m1_substrate_test::referenced_port_walk_real_helper_stack_compiles","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_emitted_module_compares_reflected_port_ids_in_list_contains","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_emitted_module_invokes_reflected_dag_function","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_emitted_module_matches_reflected_behavior_payloads","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_emitted_module_returns_reflected_source_span_list","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_emitted_module_returns_user_record_list_from_reflected_binds","policy":"warn"} -{"test":"m1_3_emit_rust_test::rustc_roundtrip_generic_list_fold_prints_one","policy":"warn"} -{"test":"m2_lens_cost_migration_test::complexity_dag_compiles_cleanly","policy":"warn"} -{"test":"m2_lens_cost_migration_test::complexity_dag_runs_end_to_end_via_rustc_harness","policy":"warn"} -{"test":"m2_lens_cost_migration_test::complexity_generated_module_matches_checked_in_snapshot","policy":"warn"} -{"test":"m2_lens_idempotency_migration_test::idempotency_emitted_analyze_matches_oracle","policy":"warn"} -{"test":"m2_lens_provenance_migration_test::lens_provenance_dag_runs_end_to_end_via_rustc_harness","policy":"warn"} -{"test":"m2_lens_unused_parameters_migration_test::unused_parameters_dag_runs_end_to_end_via_rustc_harness","policy":"warn"} -{"test":"m2_lens_unused_parameters_migration_test::unused_parameters_dag_self_analysis_reports_zero_findings","policy":"warn"} -{"test":"t_pb_b_1_dag_runner_test::r1c_e_emit_gates_suite_passes_through_runner","policy":"warn"} -{"test":"r3_verification_l4_l7_l5_skeleton_test::r3_verification_l4_emit_eval_false_branch_passes_w1_emit_vs_eval","policy":"warn"} -{"test":"r3_verification_l4_l7_l5_skeleton_test::r3_verification_l4_l7_direct_suite_lists_four_l4_certification_seed_claims","policy":"warn"} -{"test":"r3_verification_l4_l7_l5_skeleton_test::r3_verification_l7_algebraic_law_matrix_has_current_runner_receipts","policy":"warn"} -{"test":"complexity_lens_behavioral_completion::literal_bind_cements_constant_complexity_summary","policy":"warn"} -{"test":"complexity_lens_behavioral_completion::recursive_countdown_cements_linear_work_and_span","policy":"warn"} -{"test":"cost_lens_symbolic_consumer_test::literal_bind_pins_symbolic_cost_of_constant_on_fixture","policy":"warn"} -{"test":"cost_lens_symbolic_consumer_test::recursive_countdown_pins_symbolic_cost_linear_and_sizevar_on_fixture","policy":"warn"} -{"test":"cost_lens_symbolic_consumer_test::e_p_sub_value_relation_per_call_landed_cost_lens_routes_through_per_call_pattern_query","policy":"warn"} -{"test":"e6_g1a_option3_static_lens_test::e6_g1a_option3_static_lens_mini_report_executes_without_reflection_imports","policy":"warn"} -{"test":"lens_behavioral_parity_demonstration_test::r3_gate_73_demonstrates_complexity_certainty_is_proven","policy":"warn"} -{"test":"sg2_parse_authority_test::parse_surface_dag_compiles_cleanly_for_regen_parse","policy":"warn"} -{"test":"sg2c1_parse_tables_authority_test::parse_tables_generated_module_matches_checked_in_snapshot","policy":"warn"} -{"test":"sg6_hand_authored_census_test::sg6_regen_lens_cli_smoke_regenerates_named_entry_without_drift","policy":"warn"} -{"test":"t_demo_fixture_test::t_demo_canonical_suites_are_runner_visible","policy":"warn"} -{"test":"t_ci_workflow_as_data_demo_test::lens_self_application_demonstrated_bootstrap_ci_modeled_exclusivity","policy":"warn"} -{"test":"t_ci_workflow_as_data_demo_test::ci_workflow_as_data_demo_timing_dimension_report_on_bootstrap_shell","policy":"warn"} -{"test":"t_ci_workflow_as_data_demo_test::lens_self_application_demonstrated_timing_dimension_report_on_ci_modeled_workflow","policy":"warn"} -{"test":"t_pb_b_1_dag_runner_test::r3_gate_87_cementing_regen_lens_suites_pass_through_runner","policy":"warn"} -{"test":"tc1_substrate_lens_eta_equivalence_strict_fire_test::tc1_strict_fire_suite_has_canonical_executable_claim_with_valid_binary_shape","policy":"warn"} -{"test":"thesis_validation_test::kf_1_structural_list_operation_ordering_holds","policy":"warn"} -{"test":"dimension::analyze_complexity_tests::analyze_complexity_fail_arm_has_no_composed_field","policy":"warn"} -{"test":"dimension::analyze_complexity_tests::analyze_complexity_fails_closed_with_typed_diagnostic_on_missing_cost","policy":"warn"} -{"test":"dimension::analyze_complexity_tests::analyze_complexity_matches_analyze_symbolic_cost_dimension_for_known_workflow","policy":"warn"} -{"test":"dimension::analyze_complexity_tests::analyze_complexity_returns_ok_for_bounded_int_add_workflow","policy":"warn"} -{"test":"dimension::analyze_complexity_tests::analyze_complexity_violation_entries_are_typed_diagnostic_enums","policy":"warn"} -{"test":"dimension::fail_closed_tests::missing_symbolic_cost_surfaces_as_dimension_fail_with_violates_witnesses","policy":"warn"} -{"test":"dimension::fail_closed_tests::transform_workflow_root_still_backward_reaches_operand_ports","policy":"warn"} -{"test":"e7_analyze_complexity_integration::analyze_complexity_composed_matches_lens_at_workflow_root","policy":"warn"} -{"test":"e7_analyze_complexity_integration::analyze_complexity_public_api_delegates_to_symbolic_cost_dimension","policy":"warn"} -{"test":"e7_analyze_complexity_integration::analyze_complexity_public_api_honors_supplied_workflow_root","policy":"warn"} -{"test":"e7_analyze_complexity_integration::analyze_complexity_public_api_preserves_typed_witness_envelope_on_ok","policy":"warn"} -{"test":"lane2_stage_2f_dimension_test::analyze_symbolic_cost_composed_matches_lens_at_workflow_root","policy":"warn"} -{"test":"lens_behavioral_parity_demonstration_test::r3_gate_73_demonstrates_symbolic_cost_is_keyed_by_countdown_parameter","policy":"warn"} -{"test":"lens_cost_target_realization_test::cost_lens_composes_symbolic_cost_with_rust_type_realization_row","policy":"warn"} -{"test":"lens_cost_target_realization_test::cost_lens_demonstration_composes_representative_rust_program_cost","policy":"warn"} -{"test":"m1_5_verification_test::symbolic_cost_expr_equals_smoke_suite_passes","policy":"warn"} -{"test":"r3_free_consequences_second_batch_test::cross_target_optimization_constant_fold_consistent_has_symbolic_cost_witness","policy":"warn"} -{"test":"r3_free_consequences_second_batch_test::cross_target_optimization_cost_structurally_derived_receipt","policy":"warn"} -{"test":"r3_free_consequences_second_batch_test::r3_free_consequences_second_batch_reaches_expected_consumer_shapes","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_builder_fails_closed_when_merge_step_has_no_log_cost_witness","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_basis_cost_hits_symbolic_cost_lens_table","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_declaration_pins_subject_span_and_per_write_log_budget","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_log_replicas_in_symbolic_cost_lens_table","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_per_op_budget_is_not_sound_ceiling_for_composed_workflow","policy":"warn"} -{"test":"t_las_crdt_cost_basis_demo_test::crdt_cost_basis_demonstrated_unknown_ceiling_covers_composed_workflow","policy":"warn"} diff --git a/src/v3/compiler/Cargo.toml b/src/v3/compiler/Cargo.toml index 57b4c2c7936..37d21c6759b 100644 --- a/src/v3/compiler/Cargo.toml +++ b/src/v3/compiler/Cargo.toml @@ -89,3 +89,7 @@ path = "src/bin/self_host_fixed_point.rs" [[bin]] name = "r1c_e_emit_gates" path = "src/bin/r1c_e_emit_gates.rs" + +[[bin]] +name = "gunbc-ci" +path = "src/bin/gunbc_ci.rs" diff --git a/src/v3/compiler/src/bin/gunbc_ci.rs b/src/v3/compiler/src/bin/gunbc_ci.rs new file mode 100644 index 00000000000..1990a1baea5 --- /dev/null +++ b/src/v3/compiler/src/bin/gunbc_ci.rs @@ -0,0 +1,116 @@ +// Binary entrypoint may use `eprintln!` for operator-facing diagnostics (disallowed +// in library code per clippy config). +#![allow(clippy::disallowed_macros)] + +//! `gunbc-ci` — BinaryShim workflow runner entrypoint (T-WAD Slice 6) plus host +//! utilities used before full dispatch lands. +//! +//! Invocation (GitHub Actions thin shim per `dsl/gunbc/ci_emission.dag`): +//! `gunbc-ci --workflow ci --event ` +//! +//! Subcommands: +//! - `wall-clock-warn-manifest` — print JSONL warn-policy lines projected from +//! `dsl/gunbc/test_node_wall_clock_ratchet.dag` (**interim bridge** toward gate +//! **#102**; canonical pass target is policy from `TestNodeCostDimension` timing +//! facts — not a parallel warn-token table). +//! +//! **`--workflow` / `--event` dispatch:** not implemented yet (BinaryShim gate-matrix +//! wiring is pending). That path exits **2** fail-closed unless +//! `GUNBC_CI_ALLOW_DISPATCH_STUB=1` (or `true`) is set so callers can smoke the +//! binary without implying dispatch succeeded. + +use std::path::PathBuf; +use std::process::ExitCode; + +use v3_compiler::compile_to_dag; +use v3_compiler::wall_clock_ratchet_manifest::{ + emit_warn_policy_jsonl_lines, RATCHET_DAG_REL_PATH, +}; + +fn usage() -> ! { + eprintln!( + "usage:\n gunbc-ci wall-clock-warn-manifest\n gunbc-ci --workflow --event " + ); + std::process::exit(2); +} + +fn repo_root() -> PathBuf { + if let Ok(p) = std::env::var("GITHUB_WORKSPACE") { + return PathBuf::from(p); + } + std::env::current_dir().unwrap_or_else(|e| { + eprintln!("cwd: {e}"); + std::process::exit(2); + }) +} + +fn main() -> ExitCode { + let args: Vec = std::env::args().skip(1).collect(); + if args.is_empty() { + usage(); + } + + if args[0] == "wall-clock-warn-manifest" { + if args.len() != 1 { + eprintln!("wall-clock-warn-manifest: unexpected arguments"); + return ExitCode::from(2); + } + let root = repo_root(); + let path = root.join(RATCHET_DAG_REL_PATH); + let source = match std::fs::read_to_string(&path) { + Ok(s) => s, + Err(e) => { + eprintln!("read {}: {e}", path.display()); + return ExitCode::FAILURE; + } + }; + let dag = match compile_to_dag(&source, path.to_string_lossy().as_ref()) { + Ok(d) => d, + Err(err) => { + eprintln!("compile: {err:?}"); + return ExitCode::FAILURE; + } + }; + return match emit_warn_policy_jsonl_lines(&dag) { + Ok(lines) => { + for line in lines { + println!("{line}"); + } + ExitCode::SUCCESS + } + Err(msg) => { + eprintln!("{msg}"); + ExitCode::FAILURE + } + }; + } + + if args.len() == 4 && args[0] == "--workflow" && args[2] == "--event" { + let wf = args[1].as_str(); + let event_path = args[3].as_str(); + if wf != "ci" { + eprintln!("unsupported workflow: {wf}"); + return ExitCode::from(2); + } + if !std::path::Path::new(event_path).is_file() { + eprintln!("--event path is not a readable file: {event_path}"); + return ExitCode::from(2); + } + eprintln!( + "gunbc-ci: BinaryShim dispatch stub (workflow={wf}); gate matrix execution not wired yet." + ); + let allow_stub = std::env::var("GUNBC_CI_ALLOW_DISPATCH_STUB") + .map(|v| v == "1" || v.eq_ignore_ascii_case("true")) + .unwrap_or(false); + if allow_stub { + return ExitCode::SUCCESS; + } + eprintln!( + "gunbc-ci: refusing success for unimplemented dispatch (exit 2). \ + Set GUNBC_CI_ALLOW_DISPATCH_STUB=1 to smoke this stub until dispatch lands." + ); + return ExitCode::from(2); + } + + usage(); +} diff --git a/src/v3/compiler/src/bootstrap_generated.rs b/src/v3/compiler/src/bootstrap_generated.rs index d92fd63b684..a0fec88f417 100644 --- a/src/v3/compiler/src/bootstrap_generated.rs +++ b/src/v3/compiler/src/bootstrap_generated.rs @@ -9556,14 +9556,14 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { target: TransformTarget::Callable(DeclarationId(1321)), inputs: vec![PortId(1010)], output: PortId(1011), - span: SourceSpan::new("src/v3/std/verification.dag", 28552, 28575), + span: SourceSpan::new("src/v3/std/verification.dag", 28547, 28570), })); nodes.push(Behavior::Transform(TransformNode { id: NodeId(845), target: TransformTarget::Callable(DeclarationId(1322)), inputs: vec![PortId(1012)], output: PortId(1013), - span: SourceSpan::new("src/v3/std/verification.dag", 28597, 28631), + span: SourceSpan::new("src/v3/std/verification.dag", 28592, 28626), })); nodes.push(Behavior::Branch(BranchNode { id: NodeId(846), @@ -9574,7 +9574,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { output: PortId(1011), pattern: BranchPattern::UnresolvedVariant { name: "Enumerated".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 28535, 28548), + span: SourceSpan::new("src/v3/std/verification.dag", 28530, 28543), }, binding: Some(PayloadBinding { binding_name: "c".to_string(), @@ -9586,7 +9586,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { output: PortId(1013), pattern: BranchPattern::UnresolvedVariant { name: "Quantified".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 28580, 28593), + span: SourceSpan::new("src/v3/std/verification.dag", 28575, 28588), }, binding: Some(PayloadBinding { binding_name: "q".to_string(), @@ -9595,7 +9595,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { }, ], output: PortId(1014), - span: SourceSpan::new("src/v3/std/verification.dag", 28517, 28635), + span: SourceSpan::new("src/v3/std/verification.dag", 28512, 28630), emit_participation: Some(BranchEmitParticipation::UserMatch), })); nodes.push(Behavior::Bind(BindNode { @@ -9603,7 +9603,7 @@ fn bootstrapped_fixture_dag_nodes() -> Vec { name: "obligation_for_suite_claim".to_string(), value: PortId(1014), params: vec![PortId(1009)], - span: SourceSpan::new("src/v3/std/verification.dag", 28517, 28635), + span: SourceSpan::new("src/v3/std/verification.dag", 28512, 28630), lane2_workflow: None, emit_participation: Some(BindEmitParticipation::UserCallable), })); @@ -43665,7 +43665,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 25817, 25911), + span: SourceSpan::new("src/v3/std/verification.dag", 25812, 25906), }); declarations.push(Declaration { id: DeclarationId(1316), @@ -43694,7 +43694,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 25913, 26016), + span: SourceSpan::new("src/v3/std/verification.dag", 25908, 26011), }); declarations.push(Declaration { id: DeclarationId(1317), @@ -43719,7 +43719,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 26749, 26826), + span: SourceSpan::new("src/v3/std/verification.dag", 26744, 26821), }); declarations.push(Declaration { id: DeclarationId(1318), @@ -43744,7 +43744,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 26828, 26888), + span: SourceSpan::new("src/v3/std/verification.dag", 26823, 26883), }); declarations.push(Declaration { id: DeclarationId(1319), @@ -43769,7 +43769,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27086, 27167), + span: SourceSpan::new("src/v3/std/verification.dag", 27081, 27162), }); declarations.push(Declaration { id: DeclarationId(1320), @@ -43779,8 +43779,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(2720), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 27609, - 27625, + 27604, + 27620, )), }, type_params: vec![], @@ -43791,7 +43791,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27538, 27625), + span: SourceSpan::new("src/v3/std/verification.dag", 27533, 27620), }); declarations.push(Declaration { id: DeclarationId(1321), @@ -43801,8 +43801,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(1319), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 27683, - 27768, + 27678, + 27763, )), }, type_params: vec![], @@ -43813,7 +43813,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27627, 27768), + span: SourceSpan::new("src/v3/std/verification.dag", 27622, 27763), }); declarations.push(Declaration { id: DeclarationId(1322), @@ -43823,8 +43823,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(1319), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 28075, - 28141, + 28070, + 28136, )), }, type_params: vec![], @@ -43835,7 +43835,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27998, 28141), + span: SourceSpan::new("src/v3/std/verification.dag", 27993, 28136), }); declarations.push(Declaration { id: DeclarationId(1323), @@ -43853,7 +43853,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28446, 28635), + span: SourceSpan::new("src/v3/std/verification.dag", 28441, 28630), }); declarations.push(Declaration { id: DeclarationId(1324), @@ -43863,8 +43863,8 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { output: DeclarationId(2722), body: ArrowBody::Unparsed(SourceSpan::new( "src/v3/std/verification.dag", - 28719, - 28764, + 28714, + 28759, )), }, type_params: vec![], @@ -43875,7 +43875,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28637, 28764), + span: SourceSpan::new("src/v3/std/verification.dag", 28632, 28759), }); declarations.push(Declaration { id: DeclarationId(1325), @@ -84386,7 +84386,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27585, 27608), + span: SourceSpan::new("src/v3/std/verification.dag", 27580, 27603), }); declarations.push(Declaration { id: DeclarationId(2721), @@ -84406,7 +84406,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28677, 28693), + span: SourceSpan::new("src/v3/std/verification.dag", 28672, 28688), }); declarations.push(Declaration { id: DeclarationId(2722), @@ -84426,7 +84426,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 28698, 28718), + span: SourceSpan::new("src/v3/std/verification.dag", 28693, 28713), }); declarations.push(Declaration { id: DeclarationId(2723), @@ -85671,7 +85671,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 25838, 25867), + span: SourceSpan::new("src/v3/std/verification.dag", 25833, 25862), }); declarations.push(Declaration { id: DeclarationId(2787), @@ -85690,7 +85690,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 25872, 25911), + span: SourceSpan::new("src/v3/std/verification.dag", 25867, 25906), }); declarations.push(Declaration { id: DeclarationId(2788), @@ -85709,7 +85709,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 26769, 26790), + span: SourceSpan::new("src/v3/std/verification.dag", 26764, 26785), }); declarations.push(Declaration { id: DeclarationId(2789), @@ -85728,7 +85728,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 26795, 26826), + span: SourceSpan::new("src/v3/std/verification.dag", 26790, 26821), }); declarations.push(Declaration { id: DeclarationId(2790), @@ -85748,7 +85748,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 26870, 26886), + span: SourceSpan::new("src/v3/std/verification.dag", 26865, 26881), }); declarations.push(Declaration { id: DeclarationId(2791), @@ -85768,7 +85768,7 @@ fn bootstrapped_fixture_dag_declarations() -> Vec { value_body: None, refinement: None, nominal_opacity: None, - span: SourceSpan::new("src/v3/std/verification.dag", 27142, 27165), + span: SourceSpan::new("src/v3/std/verification.dag", 27137, 27160), }); declarations.push(Declaration { id: DeclarationId(2792), 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 66074324981..701138b0f2b 100644 --- a/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs +++ b/src/v3/compiler/src/bootstrap_generated_without_parse_surface.rs @@ -9556,14 +9556,14 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { target: TransformTarget::Callable(DeclarationId(1305)), inputs: vec![PortId(1010)], output: PortId(1011), - span: SourceSpan::new("src/v3/std/verification.dag", 28552, 28575), + span: SourceSpan::new("src/v3/std/verification.dag", 28547, 28570), })); nodes.push(Behavior::Transform(TransformNode { id: NodeId(845), target: TransformTarget::Callable(DeclarationId(1306)), inputs: vec![PortId(1012)], output: PortId(1013), - span: SourceSpan::new("src/v3/std/verification.dag", 28597, 28631), + span: SourceSpan::new("src/v3/std/verification.dag", 28592, 28626), })); nodes.push(Behavior::Branch(BranchNode { id: NodeId(846), @@ -9574,7 +9574,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { output: PortId(1011), pattern: BranchPattern::UnresolvedVariant { name: "Enumerated".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 28535, 28548), + span: SourceSpan::new("src/v3/std/verification.dag", 28530, 28543), }, binding: Some(PayloadBinding { binding_name: "c".to_string(), @@ -9586,7 +9586,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { output: PortId(1013), pattern: BranchPattern::UnresolvedVariant { name: "Quantified".to_string(), - span: SourceSpan::new("src/v3/std/verification.dag", 28580, 28593), + span: SourceSpan::new("src/v3/std/verification.dag", 28575, 28588), }, binding: Some(PayloadBinding { binding_name: "q".to_string(), @@ -9595,7 +9595,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { }, ], output: PortId(1014), - span: SourceSpan::new("src/v3/std/verification.dag", 28517, 28635), + span: SourceSpan::new("src/v3/std/verification.dag", 28512, 28630), emit_participation: Some(BranchEmitParticipation::UserMatch), })); nodes.push(Behavior::Bind(BindNode { @@ -9603,7 +9603,7 @@ fn bootstrapped_fixture_without_parse_surface_dag_nodes() -> Vec { name: "obligation_for_suite_claim".to_string(), value: PortId(1014), params: vec![PortId(1009)], - span: SourceSpan::new("src/v3/std/verification.dag", 28517, 28635), + span: SourceSpan::new("src/v3/std/verification.dag", 28512, 28630), lane2_workflow: None, emit_participation: Some(BindEmitParticipation::UserCallable), })); @@ -43157,7 +43157,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","policy":"warn"}` — the +/// shape `scripts/check-test-timeout.sh` / `jq` already consume. +pub fn emit_warn_policy_jsonl_lines(dag: &Dag) -> Result, String> { + let decl = dag + .declaration_by_name("wall_clock_warn_libtest_tokens") + .ok_or_else(|| { + "missing `wall_clock_warn_libtest_tokens` data row in ratchet .dag".to_string() + })?; + let body = decl + .value_body + .as_ref() + .ok_or_else(|| "wall_clock_warn_libtest_tokens: no value_body".to_string())?; + let ValueBody::List(rows) = body else { + return Err(format!( + "wall_clock_warn_libtest_tokens: expected ValueBody::List, got {body:?}" + )); + }; + let mut out = Vec::with_capacity(rows.len()); + for (idx, row) in rows.iter().enumerate() { + let fields = match row { + FieldValue::Record(f) => f.as_slice(), + other => { + return Err(format!( + "row {idx}: expected record `WallClockWarnLibtestToken`, got {other:?}" + )); + } + }; + let test_val = fields + .iter() + .find(|(l, _)| l == "test") + .map(|(_, v)| v) + .ok_or_else(|| format!("row {idx}: missing `test` field"))?; + let test = match test_val { + FieldValue::Literal(LiteralBits::String(s)) => s.as_str(), + other => { + return Err(format!( + "row {idx}: `test` must be a String literal, got {other:?}" + )); + } + }; + out.push(format!( + "{{\"test\":{},\"policy\":\"warn\"}}", + json_escape_string(test) + )); + } + Ok(out) +} + +fn json_escape_string(s: &str) -> String { + let mut out = String::with_capacity(s.len() + 2); + out.push('"'); + for ch in s.chars() { + match ch { + '"' => out.push_str("\\\""), + '\\' => out.push_str("\\\\"), + '\n' => out.push_str("\\n"), + '\r' => out.push_str("\\r"), + '\t' => out.push_str("\\t"), + c if c.is_control() => { + use std::fmt::Write; + let _ = write!(&mut out, "\\u{:04x}", c as u32); + } + c => out.push(c), + } + } + out.push('"'); + out +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::compile_to_dag; + use serde_json::Value; + use std::path::PathBuf; + + fn load_ratchet_dag() -> Dag { + let manifest_dir = PathBuf::from(env!("CARGO_MANIFEST_DIR")); + let path = manifest_dir.join("../../../dsl/gunbc/test_node_wall_clock_ratchet.dag"); + let source = std::fs::read_to_string(&path).unwrap_or_else(|e| { + panic!("read {}: {e}", path.display()); + }); + compile_to_dag(&source, path.to_string_lossy().as_ref()).unwrap_or_else(|err| { + panic!("compile {}: {err:?}", path.display()); + }) + } + + #[test] + fn ratchet_dag_warn_manifest_lines_are_parseable_warn_policy_objects() { + let dag = load_ratchet_dag(); + let lines = emit_warn_policy_jsonl_lines(&dag).expect("emit"); + for (idx, line) in lines.iter().enumerate() { + let v: Value = serde_json::from_str(line) + .unwrap_or_else(|e| panic!("line {idx} must be JSON: {e}; got {line:?}")); + let obj = v.as_object().unwrap_or_else(|| { + panic!("line {idx} must be a JSON object; got {v:?}"); + }); + assert!( + obj.get("test").and_then(Value::as_str).is_some(), + "line {idx} must have string `test`" + ); + assert_eq!( + obj.get("policy").and_then(Value::as_str), + Some("warn"), + "line {idx} must have policy=warn" + ); + } + } +} diff --git a/src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs b/src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs index b62abc2a4eb..b2eaa3346af 100644 --- a/src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs +++ b/src/v3/compiler/tests/integration/lane2_stage_2d_symbolic_cost_test.rs @@ -32,7 +32,7 @@ use crate::common::{assert_recursive_countdown_linear_semantics, cached_compile_ /// `cached_compile_to_dag` amortizes **duplicate** compile work when both tests run in one /// process. This is **not** a `TESTING.md` Phase-0 exemption dissolution receipt: the first /// caller still pays cold bootstrap, and libtest parallelism can inflate wall time — those -/// tests stay listed in `scripts/test-node-wall-clock-ratchet.jsonl` until a sole-filter +/// tests stay listed in `dsl/gunbc/test_node_wall_clock_ratchet.dag` until a sole-filter /// `--report-time` ≤2000ms receipt exists (or gate #102 lands a structural cost ratchet). const LANE2D_COUNTDOWN_SOURCE: &str = "fn countdown(n: Int) -> Int =\n if n == 0 then 0 else countdown(n - 1)"; diff --git a/src/v3/compiler/tests/integration/sg0_census_test.rs b/src/v3/compiler/tests/integration/sg0_census_test.rs index 12d99985cae..3cc658acf4c 100644 --- a/src/v3/compiler/tests/integration/sg0_census_test.rs +++ b/src/v3/compiler/tests/integration/sg0_census_test.rs @@ -252,6 +252,7 @@ const EXPECTED_HAND_AUTHORED_NON_TEST: &[&str] = &[ // survives. "src/v3/compiler/benches/tier3_mirror_perf.rs", "src/v3/compiler/build.rs", + "src/v3/compiler/src/bin/gunbc_ci.rs", "src/v3/compiler/src/bin/r1c_e_emit_gates.rs", "src/v3/compiler/src/bin/regen_bootstrap.rs", "src/v3/compiler/src/bin/regen_lens.rs", @@ -330,6 +331,7 @@ const EXPECTED_HAND_AUTHORED_NON_TEST: &[&str] = &[ "src/v3/compiler/src/regen_tokenize.rs", "src/v3/compiler/src/self_host_receipt_p0.rs", "src/v3/compiler/src/test_runner.rs", + "src/v3/compiler/src/wall_clock_ratchet_manifest.rs", ]; // All test .rs files under `src/v3/compiler` that are currently diff --git a/src/v3/std/verification.dag b/src/v3/std/verification.dag index fbb5bdedba8..e43c31f7fb8 100644 --- a/src/v3/std/verification.dag +++ b/src/v3/std/verification.dag @@ -551,10 +551,10 @@ type QuantifiedTestClaim { // // Test execution cost is the timing substrate projected onto a test node in // the modeled graph (`TestNodeCostDimension` on `TestNodeRef`) — not a -// verification-local scalar dimension. CI still carries warn-only rows in -// `scripts/test-node-wall-clock-ratchet.jsonl` as an **interim shell manifest** -// (same libtest tokens; structured JSONL) until gate #102 wires the ratchet to -// substrate timing facts; that file is scaffolding, not the modeled authority. +// verification-local scalar dimension. CI projects warn-only libtest tokens from +// `dsl/gunbc/test_node_wall_clock_ratchet.dag` via `gunbc-ci wall-clock-warn-manifest` +// into the JSONL shape `scripts/check-test-timeout.sh` consumes (**interim bridge** — +// not #102 closure; no checked-in JSONL manifest). // `TestNodeRef` is a closed test-typed edge: only modeled `TestClaim` / // `QuantifiedTestClaim` nodes can inhabit it, so arbitrary declarations cannot // masquerade as test nodes. The budget/report fields reuse T-WAD's existing