Skip to content

codegen-corpus: compile sample moves with the run, so one commit is red and green (#851 W15) #885

Open

Description

@gHashTag

codegen-corpus goes red for a reason the commit does not decide

Part of #851, weak point W15: a gate that fails or passes for a reason other than its claim.

What was measured

The red is always the same. I read the logs of the nine Codegen Validation failures from 09-24 to 10-04, on every ref: 5 on main and 4 on PR branches. All nine print the same two lines:

  DOES NOT COMPILE: specs/tri/phi_utils_multi.tri (ast-check passed it)
0 spec(s) regressed, 1 of 24 sampled outputs do not compile.
run created (UTC) event ref SHA
36011281829 09-24 14:13 pull_request trinet-fleet-truth 4e13a68
36027587352 09-24 16:28 push main 9eae0b4
36029076209 09-24 16:41 push main 9947512
37016445887 10-02 13:56 push main 4d2a864
37063193586 10-02 20:51 pull_request deps/docusaurus-3.10.2 d104319
37065544442 10-02 21:13 pull_request ci/gates-floor-10 9a62c10
37088537159 10-03 02:05 push main e6eac09
37102745385 10-03 06:20 pull_request ci/run-syntax-self-hosted 57c3c56
37225448222 10-04 18:42 push main 57de4a1

One commit, both verdicts. On e6eac0900, push run 37088537159 is red and schedule run 37090643092 is green. Main 57de4a1f5 is red on push (37225448222), while PR runs on the same spec tree are green.

The output really does not compile. Its compile errors, from the probe run below:

  • compute_phi_power(n: u32) PhiResult has a stub body that falls off the end;
  • the generated test calls encode_to_trits(allocator, "test"), but the function takes one parameter.

That is a generator defect and is tracked separately. The question here is why it is only sometimes sampled.

Why the sample moves

tools/codegen_corpus.zig compiles 24 outputs: every stride-th entry of this run's clean list, with stride = clean.len / 24.

  • Green runs report 788 clean, so stride = 32. The picks are indices 0, 32, …, 736.
  • phi_utils_multi is baseline line 448, which is index 447. The slot at 448 is one past it.
  • If one spec that sorts before it counts as clean when the baseline does not hold it, phi_utils_multi moves to index 448 and is sampled.
  • 0 spec(s) regressed means every baseline entry was still clean, so the red runs had at least 788 clean.
  • Inference, not measured: the red runs had 789–791 clean, with exactly one extra entry before phi_utils_multi. The tool never prints its clean count on the failure path, so the red runs did not record it.

A false clean that this can come from (measured locally):

  • vibee_gen prints Behaviors: N before it generates.
  • When it cannot create or write the file, or when it produced 0 bytes, it leaves no file and exits 0 (writeGenerated(...) catch return).
  • zig ast-check on a missing file prints error: unable to open file '…' for ast-check: FileNotFound and exits 1. On a directory it prints error: unable to load file … ReadFailed, also exit 1.
  • Neither message contains : error: , which is the only thing astCheckOk looks for. The exit code is ignored, so the spec counts as clean.
  • Measured later (probe 37242067946): a second hole. 18 baseline specs abort with SIGABRT after creating the output file and leave it empty, and zig ast-check passes an empty file with exit 0. The abort is vibee_gen aborts (SIGABRT) on 18 Verilog specs and intermittently on 2 Zig specs #887.

What does not explain it:

  • Probe run 37241431527 generated all 1137 specs 5 times on one runner, which took 104.9 s.
    • 0 specs differ in exit code, behaviour count or output sha256.
    • Clean equals the baseline (788), with 0 extra and 0 lost.
    • Five repeats have little power against a rare flip, so this is not evidence that the generator is deterministic across runners.
  • Same image ubuntu-24.04 20260927.320.1 on both runs of e6eac09. The red run was in westus2, the green one in westus.
  • No randomness or clock use in the generator path: I grepped vibee_gen.zig, zig_codegen.zig, vibee_parser.zig and lang_generators.zig.
  • vibee_gen is built for the native CPU (standardTargetOptions). A CPU-dependent outcome is possible and not tested.

Side defect found on the way

The output name flattened / to _, so specs/storm/main.tri and specs/storm_main.tri both wrote .zig-cache/codegen-corpus/specs_storm_main.tri.zig. Neither spec is in the baseline, so this is not the cause, but the compile sample could have tested one spec's output under the other's name.

Fix (PR to follow)

  • The sample is drawn from the committed baseline: slot k is baseline entry k * stride. A run cannot move it.
  • A spec counts as clean only if the generator exits 0, leaves a non-empty regular file, and zig ast-check exits 0 with no : error: .
  • The output file is deleted before each generation. Its path mirrors the spec path.
  • The clean count, regressed, new-clean and no-output specs are printed on both paths, by name. The next disagreement will then name its spec.
  • The runner's CPU model is printed.

Done when

  • PR merged and its own Codegen Validation run is green.

  • CI A/B on throwaway branches (main 37243529377, fixed 37243526975; all three rows below came out as expected). Each arm runs main's tool and the fixed tool on the same tree:

    • plain;
    • one extra clean spec added before phi_utils_multi;
    • one non-baseline spec before it forced to leave no file;
    • one baseline spec forced to leave no file.

    Expected:

    arm main's tool fixed tool
    extra clean spec red on phi_utils_multi green, naming the new clean spec
    non-baseline spec leaves no file red on phi_utils_multi green, naming the spec with no output
    baseline spec leaves no file green over the missing output red, naming the regression
  • A separate issue for the phi_utils_multi generator defects. They are listed in vibee_gen aborts (SIGABRT) on 18 Verilog specs and intermittently on 2 Zig specs #887 under "Also found", which is not yet an issue of their own.

Not measured

Also seen, not this issue

src/firebird/vsa_simd.zig:448, test "benchmark dot product speedup", asserts a wall-clock ratio > 0.5; its siblings use > 0.1. It made the 09-29 scheduled run red (36515512024). src/firebird/ is outside the direct-edit zones, so the threshold is the owner's call.

🤖 Generated with Claude Code

Activity

  1. gHashTag commented on Oct 4, 2026

    @gHashTag
    OwnerAuthor

    Results: the A/B, the probe, and two corrections

    A/B (exp/corpus-ab-main and exp/corpus-ab-fix, same helper and workflow, different tool; four arms on one runner each):

    arm main's tool, 37243529377 #886's tool, 37243526975
    1 plain tree green, 788 green, 769
    2 one extra clean spec (specs/tri/a_s42_extra.tri) before phi_utils_multi red: DOES NOT COMPILE: specs/tri/phi_utils_multi.tri green, NEW CLEAN names it
    3 non-baseline specs/algo/avgpool2d.tri blocked from writing red, the same line green
    4 baseline specs/algo/adam.tri (index 1, never sampled) blocked green: the loss is hidden red: REGRESSED: specs/algo/adam.tri

    Main's arms replicate the earlier run 37242996093. The shifted-sample mechanism in this issue is reproduced. So is its mirror image: a baseline spec that stops writing goes unnoticed by main's tool.

    Probe 37242067946 (exp/codegen-flake-ab): 60 passes over all 1033 specs with behaviours, removing the destination before each generation.

    • 19 baseline entries never wrote a usable file. All 19 end in SIGABRT.
      • 18 are language: varlog and leave a 0-byte file every time.
      • specs/tri/long_context_system.vibee leaves no file in 59 of 60 passes.
    • zig ast-check passes an empty file with exit 0. So main's tool counted the 18 clean through the empty file, not a missing one.
    • fix(codegen): sample the corpus compile check from the baseline #886 drops the 19 (02b9958de, baseline 788 → 769). phi_utils_multi moves to index 432, which is still not sampled.
    • A likely natural trigger (inference): specs/tri/hdc_stream_classifier.vibee is not in the baseline and sorts before phi_utils_multi. It aborts with no file in 3 of 60 passes. Main's tool counts that as clean, which is arm 3 above happening on its own.
    • The abort is filed as vibee_gen aborts (SIGABRT) on 18 Verilog specs and intermittently on 2 Zig specs #887. It covers the Verilog path's use of a buffer that has already been freed, read from source, and the Zig-path aborts, which are unexplained.

    Correction 1: red-run count, in #886. #886's description said main was red 9 times. The table above is right, but its 9 runs span every ref: 5 on main and 4 on PR branches. Counted from the API (codegen.yml, branch=main, 09-24 to 10-04), branch main alone was red 6 times:

    • the 5 phi_utils_multi runs in the table;
    • 1 on the vsa_simd benchmark, 36515512024, which is listed under "Also seen".

    #886's description now says so.

    Correction 2: the cause of the false clean. 02b9958de's message said the 19 got into the baseline because ast-check ran on a missing output. That holds for one spec only; for the other 18 the file existed and was empty. d959eb722's message states the correction. The gate's own NO OUTPUT line still said no file for all 19. b937408ce makes it say empty file where that is what happened.

    #886's own CI. All three runs below report 769 of 1033 … clean, baseline 769, 0 regressed, 0 new clean, 19 NO OUTPUT, and a clean compile sample.

    • 02b9958de (37243448031): every NO OUTPUT reason was a symbol-less stack frame.
    • d959eb722 (37243963781): the 18 Verilog specs name the panic, programmer bug caused syscall error: FAULT. They are still labelled no file, and long_context_system still shows a frame.
    • b937408ce (37244594555): the 18 read signal 6, empty file, … panic: programmer bug caused syscall error: FAULT. long_context_system reads signal 6, no file, Segmentation fault at address 0x7fee7103b2a2. Its abort is a segfault, not a panic; where it happens is not known (vibee_gen aborts (SIGABRT) on 18 Verilog specs and intermittently on 2 Zig specs #887).

    hdc_stream_classifier did not abort in any of #886's 4 codegen runs, so the natural trigger above stays an inference.

    🤖 Generated with Claude Code

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

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions