diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index b38c4032ddf..5f3baa5a74b 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -151,6 +151,11 @@ jobs: # 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). diff --git a/Makefile b/Makefile index 95be064456f..a406543fbad 100644 --- a/Makefile +++ b/Makefile @@ -10,7 +10,7 @@ .DEFAULT_GOAL := help -.PHONY: help preflight-fix ensure-codegen build-release-bins lint-upsert codegen build clean testgen testgen-check bootstrap-check verify verify-fix fmt-fix lint-fix test-all test test-xs test-s test-m test-l test-xl test-small test-medium test-large test-extra-large test-integration test-external check clippy fmt fmt-check test-fix check-fix clippy-fix bootstrap bootstrap-dry build-all build-all-dry design design-dry gist gist-dry gist-diff gist-diff-dry gist-recent gist-recent-dry infra infra-dry readme readme-dry workflow workflow-dry ci release-doc-authority-check release-doc-authority-test manager-brief-authority-check manager-brief-authority-test +.PHONY: help preflight-fix ensure-codegen build-release-bins lint-upsert codegen build clean testgen testgen-check bootstrap-check verify verify-fix fmt-fix lint-fix test-all test test-xs test-s test-m test-l test-xl test-small test-medium test-large test-extra-large test-integration test-external check clippy fmt fmt-check test-fix check-fix clippy-fix bootstrap bootstrap-dry build-all build-all-dry design design-dry gist gist-dry gist-diff gist-diff-dry gist-recent gist-recent-dry infra infra-dry readme readme-dry workflow workflow-dry ci release-doc-authority-check release-doc-authority-test manager-brief-authority-check manager-brief-authority-test test-timeout-ratchet-test # Preflight: auto-fix rustc warnings before running generators preflight-fix: @@ -85,6 +85,12 @@ manager-brief-authority-check: manager-brief-authority-test: @bash scripts/test-check-manager-brief-authority.sh +# Self-test for the per-test timeout ratchet consumer. Without this, +# future JSONL manifest parsing changes could silently neuter fail-closed +# behavior for slow-test policy. +test-timeout-ratchet-test: + @bash scripts/test-check-test-timeout.sh + # Ensure generated artifacts are up to date verify-fix: lint-upsert @RUSTFLAGS="-D warnings" cargo run -p gunbc-codegen --bin gunbc-bootstrap diff --git a/ROADMAP.md b/ROADMAP.md index 5b600daffd2..2fd9cad2391 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` 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). **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`. - **`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/scripts/test-check-test-timeout.sh b/scripts/test-check-test-timeout.sh new file mode 100755 index 00000000000..50ce8abd33a --- /dev/null +++ b/scripts/test-check-test-timeout.sh @@ -0,0 +1,142 @@ +#!/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. + +set -euo pipefail + +ROOT="$(cd "$(dirname "$0")/.." && pwd)" +cd "$ROOT" + +CONSUMER="$ROOT/scripts/check-test-timeout.sh" +TMPDIR="$(mktemp -d)" +cleanup() { + rm -rf "$TMPDIR" +} +trap cleanup EXIT + +MANIFEST="$TMPDIR/test-node-wall-clock-ratchet.jsonl" +LOG="$TMPDIR/libtest.log" + +cat > "$MANIFEST" <<'EOF' +{"test":"slow_warned_test","policy":"warn"} +{"test":"not_warn_policy","policy":"fail"} +EOF + +write_log() { + cat > "$LOG" <<'EOF' +test fast_test ... ok <0.001s> +test slow_warned_test ... ok <2.500s> +EOF +} + +test_warn_manifest_allows_known_slow_test() { + write_log + local output + if ! output=$(TEST_TIMEOUT_MANIFEST="$MANIFEST" bash "$CONSUMER" "$LOG" 2000 2>&1); then + echo "FAIL [known-warn]: consumer rejected a manifest warn-policy test" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi + if [[ "$output" != *"warn-policy tests exceeded budget"* ]]; then + echo "FAIL [known-warn]: consumer passed but did not report warn-policy backlog" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi +} + +test_unknown_slow_test_fails_closed() { + write_log + cat >> "$LOG" <<'EOF' +test slow_unknown_test ... ok <2.100s> +EOF + + local output exit_code + if output=$(TEST_TIMEOUT_MANIFEST="$MANIFEST" bash "$CONSUMER" "$LOG" 2000 2>&1); then + exit_code=0 + else + exit_code=$? + fi + + if [ "$exit_code" -eq 0 ]; then + echo "FAIL [unknown-slow]: consumer passed with an over-budget test absent from JSONL" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi + if [[ "$output" != *"slow_unknown_test"* ]] || [[ "$output" != *"not warn-listed in manifest"* ]]; then + echo "FAIL [unknown-slow]: consumer failed but did not name the missing slow test" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi +} + +test_non_warn_manifest_policy_fails_closed() { + write_log + cat >> "$LOG" <<'EOF' +test not_warn_policy ... ok <2.100s> +EOF + + local output exit_code + if output=$(TEST_TIMEOUT_MANIFEST="$MANIFEST" bash "$CONSUMER" "$LOG" 2000 2>&1); then + exit_code=0 + else + exit_code=$? + fi + + if [ "$exit_code" -eq 0 ]; then + echo "FAIL [non-warn-policy]: consumer treated a non-warn manifest row as warn-listed" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi + if [[ "$output" != *"not_warn_policy"* ]] || [[ "$output" != *"not warn-listed in manifest"* ]]; then + echo "FAIL [non-warn-policy]: consumer failed but did not name the non-warn slow test" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi +} + +test_zero_parsed_lines_fails_closed() { + printf 'not libtest output\n' > "$LOG" + + local output exit_code + if output=$(TEST_TIMEOUT_MANIFEST="$MANIFEST" bash "$CONSUMER" "$LOG" 2000 2>&1); then + exit_code=0 + else + exit_code=$? + fi + + if [ "$exit_code" -eq 0 ]; then + echo "FAIL [zero-parsed]: consumer passed on a log with no libtest timing lines" + return 1 + fi + if [[ "$output" != *"zero test-result lines parsed"* ]]; then + echo "FAIL [zero-parsed]: consumer failed but did not report parser drift guard" + printf '%s\n' "$output" | sed 's/^/ | /' + return 1 + fi +} + +failures=0 + +for test_fn in \ + test_warn_manifest_allows_known_slow_test \ + test_unknown_slow_test_fails_closed \ + test_non_warn_manifest_policy_fails_closed \ + test_zero_parsed_lines_fails_closed; do + echo "Test: $test_fn..." + if "$test_fn"; then + echo " PASS" + else + failures=$((failures + 1)) + fi +done + +if [ "$failures" -ne 0 ]; then + echo "FAIL: $failures check-test-timeout self-test(s) failed" + exit 1 +fi + +echo "PASS: check-test-timeout JSONL manifest behavior verified"