Repository navigation
fix(ci): judge the headless test graph instead of piping it through tee (Refs #989) - #1207
Merged
Merged
Conversation
…ee (Refs #989, #616) S12 of #988, first part. ci.yml ran `zig build test -Dci=true 2>&1 | tee` under bash without pipefail, so the step's exit code was tee's: on main five test roots do not compile -- src/trinity.zig, the library's own test root, among them -- and every run was reported green while its summary said "124/135 steps succeeded; 5 failed". specs/reproduce/headless.t27 declares the headless profile as measured at afc9d38 (Zig 0.15.2; CI run 36875247882 and a Linux aarch64 container with empty caches): the commands, the four dependency pins, the 46 installs, the 67 compiled test roots, the floors of the test graph, and the five blocked roots with their errors and the capability cards they hold back. tools/reproduce.py runs the build and the test step from a clean clone with fresh zig caches, reads each exit code from the process, and judges the result against the spec; --self-check plants fifteen defects. The CI test step now runs the same judge, and .github/workflows/reproduce.yml runs the whole profile on a runner with no cache. Судим граф тестов headless-профиля вместо того, чтобы прогонять его через tee. S12 эпика #988, первая часть. ci.yml запускал `zig build test -Dci=true 2>&1 | tee` в bash без pipefail, и код шага был кодом tee: на main пять корней тестов не компилируются -- среди них src/trinity.zig, собственный тест библиотеки, -- а каждый прогон считался зелёным, хотя сводка говорила «124/135 steps succeeded; 5 failed». specs/reproduce/headless.t27 описывает headless-профиль, измеренный на afc9d38 (Zig 0.15.2; CI run 36875247882 и контейнер Linux aarch64 с пустыми кэшами): команды, четыре пина зависимостей, 46 установок, 67 корней тестов, нижние границы графа и пять заблокированных корней с ошибками и карточками возможностей. tools/reproduce.py собирает и тестирует из чистого клона со свежими кэшами zig, читает код выхода каждой команды из процесса и сверяет результат со спекой; --self-check подкладывает пятнадцать дефектов. Шаг тестов в CI теперь идёт через тот же судья, а .github/workflows/reproduce.yml прогоняет весь профиль на раннере без кэша. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
dmitrii-f-t27
added a commit
that referenced
this pull request
Oct 1, 2026
S12 of #988, second part. #1207 named five test roots that did not compile and whose tests had not run for months; this change fixes all five and the test graph runs whole. A clean clone with empty caches on CI's x86_64 runner: build 94/94 with 46/46 installs, test 135/135 steps, 2768/2768 tests passed. On Linux aarch64: 2760 passed and 8 skipped (the x86-64 JIT tests of src/jit.zig). - build.zig: both dependency module names (zig-hdc-vsa / hdc_vsa) and golden_float on the test modules of src/trinity.zig and src/e2e_test.zig; libc on the queen_api and c_api test modules; the C headers at src/libs/c, where they moved on 2026-03-19, so zig build libvsa and libqueen build again. - src/c_api.zig, src/vm.zig, src/science.zig, src/vsa_jit.zig: ported to the HybridBigInt of the pinned zig-golden-float (the unpacked cache is an array; dotProduct, bundle2 and bundle3 take no allocator); c_api's duplicated `if` removed and gen_encoding reached through the vsa.zig facade; e2e_test.zig no longer imports the deleted packed_trit.zig. - The first x86_64 run of these roots found a real bug: src/jit.zig returned the generated code as a pointer with Zig's own calling convention, while the code reads rdi and rsi; the x86-64 backend that builds Debug does not pass them there, so bind and bundle read the wrong memory. JitBinaryFn now has callconv(.c), as src/jit_arm64.zig already declares. - The second run failed the wall-clock thresholds of the e2e benchmarks: Zig 0.15's own x86_64 Debug backend compiles zig-golden-float's by-value 71 KB HybridBigInt code 185 to 1680 times slower than LLVM on aarch64 (cosine 19.4 ms against 11.6 us). The e2e test compile now uses LLVM; no threshold raised, no test skipped. - specs/reproduce/headless.t27 names no blocked root, raises the floors (66 run steps with tests, 2760 tests passed) and caps skipped tests at 8. tools/reproduce.py reads run steps once from the tree after the summary (zig prints a failed step twice), names failed tests, prints and uploads the whole output of a failed command, judges skipped tests, and its self-check plants a defect for every rule and parses verbatim zig 0.15 output. Пять заблокированных корней тестов снова компилируются. S12 эпика #988, вторая часть. #1207 назвал пять корней тестов, которые не компилировались и чьи тесты месяцами не запускались; это изменение чинит все пять, и граф тестов идёт целиком. Чистый клон с пустыми кэшами на x86_64-раннере CI: сборка 94/94 и 46/46 установок, тесты 135/135 шагов, 2768/2768 прошли. На Linux aarch64: 2760 прошли и 8 пропущены (x86-64 JIT-тесты src/jit.zig). - build.zig: оба имени модуля зависимости (zig-hdc-vsa / hdc_vsa) и golden_float у тестовых модулей src/trinity.zig и src/e2e_test.zig; libc у тестовых модулей queen_api и c_api; C-заголовки в src/libs/c, куда они переехали 2026-03-19, поэтому zig build libvsa и libqueen снова собираются. - src/c_api.zig, src/vm.zig, src/science.zig, src/vsa_jit.zig: переведены на HybridBigInt закреплённого zig-golden-float (распакованный кэш -- массив; dotProduct, bundle2 и bundle3 без аллокатора); в c_api убран дубль `if`, а gen_encoding берётся через фасад vsa.zig; e2e_test.zig больше не импортирует удалённый packed_trit.zig. - Первый прогон этих корней на x86_64 нашёл настоящий баг: src/jit.zig отдавал сгенерированный код указателем с собственным соглашением вызова Zig, а код читает rdi и rsi; x86-64 бэкенд Debug передаёт их не туда, и bind с bundle читали чужую память. Теперь у JitBinaryFn callconv(.c), как в src/jit_arm64.zig. - Второй прогон уронил пороги времени e2e-бенчмарков: собственный x86_64 Debug-бэкенд Zig 0.15 компилирует код zig-golden-float с HybridBigInt по 71 КБ по значению в 185-1680 раз медленнее, чем LLVM на aarch64 (cosine 19,4 мс против 11,6 мкс). Компиляция e2e-тестов теперь через LLVM; пороги не подняты, тесты не пропущены. - specs/reproduce/headless.t27 больше не называет заблокированных корней, поднимает нижние границы (66 шагов с тестами, 2760 пройденных) и ограничивает пропуски восемью. tools/reproduce.py читает шаги один раз из дерева после сводки (zig печатает упавший шаг дважды), называет упавшие тесты, печатает и загружает весь вывод упавшей команды, судит пропуски, а его self-check подкладывает дефект под каждое правило и разбирает дословный вывод zig 0.15. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
S12 of #988, first part (Refs #989; Refs #616 -- this supersedes the tee fix of #987 by judging the result instead of only propagating it).
What was wrong
ci.ymlran the tests aszig build test -Dci=true 2>&1 | tee test-output.txtunder bash withoutpipefail, so the step's exit code was tee's. Onmain(afc9d38) the test graph does not compile five of its roots, and every CI run reported that as a success. The summary line says it plainly and nothing read it:Measured twice with Zig 0.15.2: the Build & Test job of CI run 36875247882 (Linux x86_64) and a Linux aarch64 container with empty caches. The five roots, and what the compiler says:
src/trinity.zig-- the library's own test rootsrc/hybrid.zig:4,src/vsa.zig:7: no module namedzig-hdc-vsa(the test module provides it ashdc_vsa);src/science.zig:53,143,161,179,204: expected optional type, found[59049]i8trinity/lib.trinitysrc/vm.zigsrc/vm.zig:1150: expected optional type, found[59049]i8;src/vsa_jit.zig:117: member function expected 1 argument, found 2trinity/lib.trinitysrc/queen_api.ziglink_libc, as the main test module doestrinity/queen.libsrc/c_api.zigsrc/c_api.zig:270: expected statement, found a document commenttrinity/abi.c-apisrc/e2e_test.zigpacked_trit.zig, removed in 42490a2 (#517)trinity/examples.zigOne more run step compiles and runs no test at all (
external/zig-hslm/src/root.zighas no test declaration).What this adds
specs/reproduce/headless.t27-- the headless profile as measured: Zig 0.15.2, the two commands, the four dependency pins ofbuild.zig.zon, the 46 files the build installs (45 executables andlibtrinity.a), the 67 test roots the test step compiles, the floors the graph may not drop below (135 steps, 61 run steps with tests, 2510 tests passed, at most 1 empty run step), and the five blocked roots, each with its error and the card it holds back.tools/reproduce.py-- the documented clean-clone command,python3 tools/reproduce.py headless. It pointsZIG_GLOBAL_CACHE_DIRandZIG_LOCAL_CACHE_DIRat a new empty directory, runs the build and the test step, reads each exit code from the process, and judges: exactly the blocked roots may fail (a sixth fails the gate, and so does a blocked root that compiles again -- take it off the list); a failed test, a leak, a failure the output does not name, a missing install, a changed dependency pin, fewer tests, fewer run steps or a declared root that left the graph fail it. Every install is hashed into the record it writes.--self-checkplants fifteen defects (the swallowed exit code of CI: main has no build.zig matching its own source tree (2217 files vs a build script from March) #616 among them) and shows each caught. Standard library only.ci.yml: the Test step is nowpython3 tools/reproduce.py test --reuse-cache-- the same judge over the same test graph, the leak check kept. CI stays green onmainonly because the five failures are named, with reasons, in a file a reviewer can read; a new one turns it red..github/workflows/reproduce.yml: the headless profile from a clean clone on a runner with no cache (setup-ziguse-cache: false, empty zig caches), the negative control first, the record uploaded asreproduce-headless. On pushes tomain, on pull requests that touch the build, weekly, and by hand.Python follows the existing CI scripts (#997);
.claude/rules/no-shell-scripts.mdstill says "zero Python", which the repository no longer follows.What it does not do yet (rest of #989)
link_libc, a comment, a removed import, a module name, an optional that became an array); each makes one capability's tests run for the first time in months, and the gate will ask for its line to be removed.{ "version": 1, "head_sha": "14c595aae4b13fb5f60d729578d46046c2fce8d3", "summary": "CI judges the headless test graph against a declared profile instead of piping it through tee, so the five test roots that do not compile on main are named, with reasons, and a sixth fails the job.", "changes": [ "Added specs/reproduce/headless.t27: the headless profile measured at afc9d384 with Zig 0.15.2, its commands, dependency pins, 46 installs, 67 compiled test roots, graph floors and five blocked roots with errors and capability cards.", "Added tools/reproduce.py: the clean-clone command that builds and tests with fresh zig caches, reads every exit code from the process and judges the result against the spec, with a self-check of fifteen planted defects.", "Replaced the tee-piped CI test step with the same judge, keeping the leak check, and added a reproduce workflow that runs the whole profile on a runner with no cache and uploads the record." ], "tests": [ { "command": "python3 tools/reproduce.py --self-check", "status": "passed", "result": "All fifteen planted defects are reported under their own codes, including the swallowed exit code of #616, and a conforming record stays silent.", "evidence": "tools/reproduce.py self_check; run locally on macOS Python 3 before the commit" }, { "command": "python3 tools/reproduce.py headless --zig zig-0.15.2 in ubuntu:24.04 aarch64 with empty caches", "status": "passed", "result": "Build 94/94 steps with 46/46 installs; test 124/135 steps with exactly the five blocked roots failing, 61 run steps with tests, one empty, 2510 tests passed; no violation.", "evidence": "Run on tree e5bb811d4eaf (this commit) in ubuntu:24.04 aarch64 with empty caches, 2 min 43 s; record zig-out/reproduce/headless.json lists no violation" }, { "command": "Build and Test job of CI run 36875247882 on main afc9d384, read from its log", "status": "passed", "result": "The log prints the same summary, 124/135 steps succeeded with five failed compiles, while the job reported success through tee.", "evidence": "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/gHashTag/trinity/actions/runs/36875247882" } ], "limitations": [ "The five blocked roots are named, not fixed; each fix is a separate small change that makes one capability's tests run again and removes its line from the spec.", "Only the headless profile is reproduced; web, native, FPGA, training and network profiles keep their present status.", "The pinned t27 lock, the capability evidence index, the end-to-end task and the catalog publication of #989 come in later parts." ], "tags": [ "Engineering", "Verification", "CI" ], "blog": { "title": "A green build that hid five test roots that never compiled", "summary": "Trinity's test step piped its output through tee without pipefail, so failed compiles of five test roots, the core library among them, reported success on every push until a judge read the exit code.", "outline": [ "How a pipe without pipefail turns a failed test step green, and what the build summary said all along.", "Declaring the headless profile as data: commands, pins, installs, test roots, floors and the blocked roots with their reasons.", "What is still open: fixing the five roots one by one, the pinned contract lock, the evidence index and the end-to-end task." ] } }🤖 Generated with Claude Code