Skip to content

Debug CLI rejects bundled std/pattern package with SPX-G171 #962

Open

Description

@devdotbo

Summary

semaprax check and semaprax test exit 1 with SPX-G171 on the bundled std/pattern package, so the package cannot be checked or tested from the CLI. The pre-charge forecast (57,309,377 bytes) fits the 67,108,864-byte cap; live graph construction then exceeds it.

The Rust gate standard_library::pattern_executes_on_all_three_backends fails with the same diagnostic. std/pattern is the only one of the 52 std packages that fails test.

Environment

  • Repository: github.com/wavect/semaprax, main at 2d215d3377f86e0d77b1057cb7486dc4b9295ba1, clean working tree.
  • Binary: target/debug/semaprax from cargo build --locked -p semaprax --bin semaprax, sha256 3eb5ebbf7f5cefa5a3be9b5c66032ffb0dbbda162f48cb015975721d636b8b2f. semaprax --version prints semaprax 0.9.0 (commit unknown).
  • Host: macOS arm64 (Darwin 27.2.0).
  • Toolchain: rustc 1.98.1 (48a229cea 2026-09-01); cargo 1.98.1 (797e8a9bc 2026-08-05).

Fixture

The input is std/pattern as committed at the commit above, unmodified: manifest std/pattern/semaprax.toml (entry std.pattern.examples, test module std.pattern.tests) with sources src/examples.spx (3,585 bytes), src/pattern.spx (81,944 bytes) and src/tests.spx (23,503 bytes).

Steps and observed output

Run from the repository root. semaprax below denotes target/debug/semaprax.

Control:

$ semaprax check examples/calculator.spx; echo rc=$?
verified examples/calculator.spx (sha256:4a908247b72078dc847285cb38e9f20dd1d600206a4115ec23cc1aff87eea29b)
rc=0
  1. check on the package. stdout is empty; this is stderr:
$ semaprax check std/pattern/semaprax.toml; echo rc=$?
error[SPX-G171]: Workspace Semantic Graph `builder_bytes` exceeds 67108864
  help: live graph construction, not the static admission pre-charge, exceeded the budget: the pre-charge forecast 57309377 bytes for 3 module(s) and fit within 67108864, with `src/pattern.spx` the largest at 44192945 bytes. Reducing reachable source is the only lever; the forecast itself was not the refusing bound. resolved-core phase first sticky ledger refusal: requested 256 bytes with 185 remaining and 0 reserved floor. Authenticated internal stage: loan CFG expression discovery. These are cumulative reservation bytes, not a retained-memory forecast or process RSS; the exact inner operation is unknown.
rc=1
  1. semaprax test std/pattern/semaprax.toml; echo rc=$? prints rc=1, empty stdout, and stderr byte-identical to step 1 (cmp exit 0). semaprax check std/pattern --json and semaprax test --manifest-path std/pattern/semaprax.toml --json also exit 1, with the same help text in a JSON diagnostic on stdout.

  2. test over every std package:

$ pass=0; fail=0; for d in std/*/; do m="${d}semaprax.toml"; [ -f "$m" ] || continue; out=$(semaprax test "$m" 2>&1); rc=$?; if [ $rc -eq 0 ]; then pass=$((pass+1)); else fail=$((fail+1)); echo "FAIL $d rc=$rc: $(echo "$out" | grep -m1 -E 'error')"; fi; done; echo "pass=$pass fail=$fail"
FAIL std/pattern/ rc=1: error[SPX-G171]: Workspace Semantic Graph `builder_bytes` exceeds 67108864
pass=51 fail=1
  1. The two std backend gates:
$ cargo test --locked -p semaprax --test project -- --exact standard_library::pattern_executes_on_all_three_backends standard_library::tracing_backend_audit::tracing_executes_on_all_three_backends; echo rc=$?
running 2 tests
test standard_library::pattern_executes_on_all_three_backends ... FAILED
test standard_library::tracing_backend_audit::tracing_executes_on_all_three_backends ... ok
test result: FAILED. 1 passed; 1 failed; 0 ignored; 0 measured; 657 filtered out; finished in 6.30s
rc=101

The pattern gate panics at tests/project/standard_library/backend_conformance.rs:287:14 with the same SPX-G171 diagnostic shown in step 1.

Earlier commit: this was first observed at f247b8e, where std/tracing failed the same way and the sweep reported pass=50 fail=2. The std/pattern and std/tracing sources are byte-identical between the two commits (git diff --stat f247b8e5b HEAD -- std/pattern std/tracing is empty). Tracing passes with the newer binary; no fixing commit was isolated. std/pattern still fails, now with a larger forecast (57,309,377 instead of 56,399,230) and at a different stage (loan CFG expression discovery instead of canonical loan directory append).

Expected behaviour

semaprax check std/pattern/semaprax.toml and semaprax test std/pattern/semaprax.toml exit 0, and standard_library::pattern_executes_on_all_three_backends passes.

Where in the code

  • The cap is MAX_BUILDER_BYTES (64 * 1024 * 1024) at src/workspace_graph.rs:96. It is the default of the thread-local ACTIVE_BUILDER_LIMIT at src/workspace_graph.rs:137 and the limit build_owned passes at src/workspace_graph.rs:1039.
  • Both CLI paths go through project::with_authenticated_project: project check at src/cli_driver.rs:177, and default project test through execute_held (dispatched at src/cli_driver.rs:773, called at src/cli/project_runtime.rs:20).
  • The gate (tests/project/standard_library.rs:468) builds the unmodified manifest first (fixture list at tests/project/standard_library/pattern_conformance.rs:50) and panics on the .unwrap() of that build at tests/project/standard_library/backend_conformance.rs:287.
  • The STD-08 list in .github/workflows/ci.yml:647-661 names standard_library::tracing_backend_audit::tracing_executes_on_all_three_backends (line 658) but not standard_library::pattern_executes_on_all_three_backends.

Further cases

The failure persists when the large test module is replaced with a trivial module. Copy std/pattern to a scratch directory, keep the manifest and the other two sources unchanged, and replace src/tests.spx with:

module std.pattern.tests;

@id("std.pattern.tests.main")
fn main() -> i64
{
    0
}

From inside the copy, semaprax check . and semaprax test . both exit 1 with empty stdout and identical stderr. It is the step 1 diagnostic with three values changed: forecast 45,581,726 bytes, first refusal of 472 bytes with 379 remaining, stage HIR final validation.

The in-tree fit test builds the same three sources directly and also fails:

$ cargo test --locked -p semaprax --lib -- --exact workspace_graph::tests::builder_limits::pattern_source_workspace_fits_unchanged_builder_budget; echo rc=$?
running 1 test
test workspace_graph::tests::builder_limits::pattern_source_workspace_fits_unchanged_builder_budget ... FAILED
test result: FAILED. 0 passed; 1 failed; 0 ignored; 0 measured; 10785 filtered out; finished in 0.64s
rc=101

It panics at src/workspace_graph/tests/builder_limits.rs:886:48 with SPX-G171: same forecast (57,309,377), first refusal of 32 bytes with 8 remaining, stage HIR canonical cleanup plans; its trace reports consumed: 67108856. The --exact selector needs the full module path; a shorter name runs 0 tests.

Across the three runs, the forecast fits each time and the refusal stage varies between runs. The stage shows where the budget ran out, not which earlier operation charged the most.

Suggested fix

No compiler change is proposed, because the first sticky refusal does not identify the operation that used most of the budget. Separately, adding standard_library::pattern_executes_on_all_three_backends to the STD-08 list would add a dedicated selection in that job. The complete workspace CI shards already select the pattern gate and the fit test; their hosted outcomes were not checked.

Related

Not verified

  • A release build, and any host other than macOS arm64.
  • The commit at which std/pattern started to fail, and the commit that fixed std/tracing (no bisect was run).
  • Hosted results of the workspace CI shards that select the fit test and the pattern gate.

Written by an AI agent loop, lightly reviewed by a human. All commands were re-run at the commit above.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions