Repository navigation
fix(build): compile the five blocked test roots again (Refs #989) - #1210
Merged
Merged
Conversation
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, so the test graph runs whole: 135/135 steps, 2760 tests passed and 8 skipped on Linux aarch64 (the four x86-64 JIT tests of src/jit.zig, in two roots), up from 124/135 and 2510. - src/trinity.zig and src/e2e_test.zig: their test modules offered the dependency under one name while the files they reach import it under the other (zig-hdc-vsa / hdc_vsa), and e2e had no golden_float; e2e_test.zig imported packed_trit.zig, deleted in 42490a2 (#517). - src/vm.zig, src/science.zig, src/vsa_jit.zig, src/c_api.zig: written for an older HybridBigInt, whose unpacked cache was an optional and whose dotProduct, bundle2 and bundle3 took an allocator; zig-golden-float's holds an array and takes none. - src/c_api.zig: a duplicated `if` that kept the file from parsing, and an import of src/vsa/gen_encoding.zig, which moved to zig-hdc (now reached through the vsa.zig facade); the queen_api and c_api test modules link libc, as their libraries do. - build.zig: the C headers moved to src/libs/ on 2026-03-19 (bc75049), so `zig build libvsa` and `zig build libqueen` failed installing the header; both build now, and the two C examples compile against the header with -Wall -Werror and run. 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 judges skipped tests, and its self-check no longer depends on the list being non-empty: it plants a blocked root of its own, and fails if a rule of the judge was never seen to fire. Пять заблокированных корней тестов снова компилируются. S12 эпика #988, вторая часть. #1207 назвал пять корней тестов, которые не компилировались и чьи тесты месяцами не запускались; это изменение чинит все пять, и граф тестов идёт целиком: 135/135 шагов, 2760 тестов прошли и 8 пропущены на Linux aarch64 (четыре x86-64 JIT-теста src/jit.zig в двух корнях), было 124/135 и 2510. - src/trinity.zig и src/e2e_test.zig: тестовые модули отдавали зависимость под одним именем, а файлы, до которых они доходят, импортируют её под другим (zig-hdc-vsa / hdc_vsa), у e2e не было golden_float; e2e_test.zig импортировал packed_trit.zig, удалённый в 42490a2 (#517). - src/vm.zig, src/science.zig, src/vsa_jit.zig, src/c_api.zig: написаны под старый HybridBigInt, где распакованный кэш был optional, а dotProduct, bundle2 и bundle3 принимали аллокатор; у zig-golden-float кэш -- массив, и аллокатор не нужен. - src/c_api.zig: продублированный `if`, из-за которого файл не парсился, и импорт src/vsa/gen_encoding.zig, переехавшего в zig-hdc (теперь через фасад vsa.zig); тестовые модули queen_api и c_api линкуют libc, как и их библиотеки. - build.zig: C-заголовки переехали в src/libs/ 2026-03-19 (bc75049), поэтому `zig build libvsa` и `zig build libqueen` падали на установке заголовка; теперь обе собираются, а два C-примера компилируются с заголовком при -Wall -Werror и запускаются. specs/reproduce/headless.t27 больше не называет заблокированных корней, поднимает нижние границы (66 шагов с тестами, 2760 пройденных тестов) и ограничивает пропущенные тесты восемью. tools/reproduce.py судит пропущенные тесты, а его self-check больше не зависит от того, что список не пуст: он подкладывает свой заблокированный корень и падает, если какое-то правило судьи ни разу не сработало. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…n (Refs #989) The first x86_64 run of the roots that compile again failed eight tests, and the judge reported them badly. Both fixed here. src/jit.zig: `finalize` returned `*const fn (*anyopaque, *anyopaque) void`, Zig's own calling convention, while the code it emits reads its two pointers from rdi and rsi. Nothing promises the default convention passes them there, and the x86-64 backend that builds Debug does not: "bind correctness" and "bundle correctness" read the wrong memory ("expected 1, found -1"). The dot product test, which casts to callconv(.c) itself, passed. The pointer type is now JitBinaryFn with callconv(.c), as src/jit_arm64.zig already declares; all six tests of the file pass when built for x86_64-linux and run on x86_64. tools/reproduce.py: zig prints each failed run step twice, above its error report and in the tree after the summary, so the judge counted four failed steps for two and missed that a step whose tests failed ran tests, which added a false PARTIAL_GRAPH. Run steps are now read from the tree after the summary only; failed tests are named in the record and in TEST_FAILED; and a command that fails has its whole output printed, as a wrapper that keeps a tool's output must. The output of each command is written beside the record and uploaded with it. The self-check carries verbatim zig 0.15 output for these cases; the previous parser fails it. Вызываем сгенерированный x86-64 код с соглашением вызова C. Первый прогон на x86_64 корней, которые снова компилируются, уронил восемь тестов, а судья плохо о них сообщил. Здесь исправлено и то, и другое. src/jit.zig: `finalize` возвращал `*const fn (*anyopaque, *anyopaque) void`, то есть собственное соглашение вызова Zig, а сгенерированный код читает два указателя из rdi и rsi. Соглашение по умолчанию не обещает передавать их туда, и x86-64 бэкенд, которым собирается Debug, не передаёт: «bind correctness» и «bundle correctness» читали чужую память («expected 1, found -1»). Тест скалярного произведения, который сам приводит указатель к callconv(.c), проходил. Теперь тип указателя -- JitBinaryFn с callconv(.c), как уже объявлено в src/jit_arm64.zig; все шесть тестов файла проходят в сборке для x86_64-linux при запуске на x86_64. tools/reproduce.py: zig печатает каждый упавший шаг дважды -- над отчётом об ошибке и в дереве после сводки, поэтому судья насчитал четыре упавших шага вместо двух и не засчитал шаг с упавшими тестами как запускавший тесты, отсюда ложный PARTIAL_GRAPH. Теперь шаги читаются только из дерева после сводки, упавшие тесты названы в записи и в TEST_FAILED, а у упавшей команды печатается весь вывод, как и положено обёртке, которая его забирает. Вывод каждой команды пишется рядом с записью и загружается вместе с ней. Self-check содержит дословный вывод zig 0.15 для этих случаев; прежний парсер его не проходит. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…t (Refs #989) With the JIT fixed, the second x86_64 run failed four tests of src/e2e_test.zig, now named by the judge: three benchmarks that assert under 1 ms per 1024-trit operation, and the VERDICT that scores them. On CI: cosine 19.4 ms, permute 3.1 ms, pack/unpack 2.4 ms per operation; natively on aarch64 the same Debug code takes 11.6, 16.8 and 10.2 microseconds. Zig 0.15 builds Debug for x86_64 with its own backend and for aarch64 with LLVM. The VSA kernels of zig-golden-float make and return a 71 KB HybridBigInt by value (zero(), permute()), and the self-hosted backend compiles that into code 185 to 1680 times slower, so on x86_64 the thresholds measured the backend. The e2e test compile now sets use_llvm: under x86_64 emulation the root passes 99/99 (cosine 11.4 us, permute 12.2 us, pack/unpack 21.8 us, VERDICT 100/100), and on aarch64 nothing changes. No threshold is raised and no test is skipped; the other roots keep the default backend. tools/reproduce.py: TEST_FAILED names the failed tests only. The text after "failed:" is the first line the test wrote, which for a benchmark is its own output (a cosine failure "said" bind(1024): 47710 ns/op), so the record keeps it as first_line and the printed output carries the whole report. Собираем корень e2e и бенчмарков через LLVM на любой платформе. С исправленным JIT второй прогон на x86_64 уронил четыре теста src/e2e_test.zig, теперь названные судьёй: три бенчмарка, требующие меньше 1 мс на операцию над 1024 тритами, и VERDICT, который их оценивает. На CI: cosine 19,4 мс, permute 3,1 мс, pack/unpack 2,4 мс на операцию; на aarch64 тот же Debug-код занимает 11,6, 16,8 и 10,2 микросекунды. Zig 0.15 собирает Debug для x86_64 собственным бэкендом, а для aarch64 -- через LLVM. VSA-ядра zig-golden-float создают и возвращают по значению HybridBigInt размером 71 КБ (zero(), permute()), и собственный бэкенд компилирует это в код в 185-1680 раз медленнее, так что на x86_64 пороги измеряли бэкенд. Теперь компиляция e2e-тестов задаёт use_llvm: под эмуляцией x86_64 корень проходит 99/99 (cosine 11,4 мкс, permute 12,2 мкс, pack/unpack 21,8 мкс, VERDICT 100/100), на aarch64 ничего не меняется. Пороги не подняты, тесты не пропущены; остальные корни собираются бэкендом по умолчанию. tools/reproduce.py: TEST_FAILED называет только упавшие тесты. Текст после "failed:" -- первая строка, которую написал тест, а у бенчмарка это его же вывод (падение cosine «сообщало» bind(1024): 47710 ns/op), поэтому запись хранит её как first_line, а полный отчёт есть в напечатанном выводе. 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, second part (Refs #989). #1207 put a judge in front of the test step and named the five test roots that did not compile as blocked. This change fixes all five and takes them off the list, so the test graph runs whole for the first time in months.
Before and after (Zig 0.15.2, Linux aarch64, empty caches)
zig build test -Dci=truezig build libvsa,zig build libqueen-Wall -Werrorand runThe eight skipped tests are the four tests in
src/jit.zigthat execute x86-64 machine code. They are compiled into bothsrc/trinity.zigandsrc/e2e_test.zig, and they skip themselves on any other architecture.The first x86_64 run
The first push failed on CI's x86_64 runners with
132/135 steps succeeded; 2 failed; 2760/2768 tests passed; 8 failed. That is the gate doing its job, and it found two things.src/jit.zig.finalizereturned*const fn (*anyopaque, *anyopaque) void, which uses Zig's own calling convention, while the code it emits reads its arguments fromrdiandrsi. The x86-64 backend that builds Debug does not pass them there. So "bind correctness" and "bundle correctness" read the wrong memory ("expected 1, found -1"). The dot product test, which casts tocallconv(.c)itself, passed. The type is nowJitBinaryFnwithcallconv(.c), assrc/jit_arm64.zigalready declares, and all six tests of the file pass when built for x86_64-linux and run on x86_64 (an amd64 container).PARTIAL_GRAPH. It also never printed zig's output, so the log could not say which tests failed. Now run steps are read from the tree after the summary, failed tests are named in the record and inTEST_FAILED, a failed command has its whole output printed, and each command's output is uploaded beside the record. The self-check carries verbatim zig 0.15 output for these cases; the previous parser fails it.The second x86_64 run, with the JIT fixed, failed four tests of
src/e2e_test.zig, and the judge now named them: three benchmarks that assert under 1 ms per 1024-trit operation, and the VERDICT that scores them.Zig 0.15 builds Debug for x86_64 with its own backend and for aarch64 with LLVM. The VSA kernels of zig-golden-float create and return a 71 KB
HybridBigIntby value (zero(),permute()), and the self-hosted backend compiles that into code 185 to 1680 times slower, so on x86_64 the thresholds were measuring the backend. The e2e test compile now setsuse_llvm. Under x86_64 emulation the root then passes 99/99 (cosine 11.4 µs, permute 12.2 µs, pack/unpack 21.8 µs, VERDICT 100/100), and aarch64 is unchanged. No threshold was raised and no test is skipped (.claude/rules/testing.md), and the other roots keep the default backend. Whether the VSA kernels should stop passing 71 KB values around is a question for zig-golden-float, not for this PR.The five roots
src/trinity.zig, the library's own test roothdc_vsa, whilesrc/hybrid.zigandsrc/vsa.zig, which it re-exports, importzig-hdc-vsa;src/science.zigreadsunpacked_cacheas an optionaltrinity_modalready does; the cache is indexed directly (every reader already callsensureUnpacked()first)src/vm.zigvm.zig:1150reads the optional cache;vsa_jit.zig:117passes an allocator todotProductensureUnpacked(), then index. The old test silently skipped its check whenever the cache was null; now it always checks. No allocator.src/queen_api.ziglink_libcon its test modulesrc/c_api.zigif (value > 0) {that kept the file from parsing. Behind it:src/vsa/gen_encoding.zig, which moved to zig-hdc; the optional cache; allocator arguments todotProduct,bundle2andbundle3; no libcvsa.encodingthrough the facade, the array API,link_libcon its test module (both of its libraries already calllinkLibC())src/e2e_test.zigpacked_trit.zig, deleted in 42490a2 (#517); reachessrc/trinity.zigwithouthdc_vsaorgolden_floatEvery API change follows
HybridBigIntas the pinned zig-golden-float defines it (e7ce3288,src/ternary/hybrid.zig):unpacked_cache: [MAX_TRITS]Trit,dotProduct(a, b) i32,bundle2(a, b),bundle3(a, b, c). This is one change rather than five because the fixes share two causes, a module name and that API, and three of the roots needed both.build.zigalso pointed both C headers atlibs/c/..., but they moved tosrc/libs/c/...on 2026-03-19 (bc75049). As a resultzig build libvsaandzig build libqueencompiled their libraries and then failed. Both build now.The gate
specs/reproduce/headless.t27:BLOCKED_ROOTSis empty. The floors rise to 66 run steps with tests and 2760 tests passed, and a newTESTS_SKIPPED_MAX = 8caps skips. The header keeps the history of the five.tools/reproduce.py: a newSKIPPEDrule. The self-check no longer relies on the real list being non-empty. It plants a blocked root of its own, so the ledger stays tested in both directions: a named root that compiles fails the gate, and a named root that still fails is accepted. It now plants a defect for every rule of the judge (21 planted defects, up from 15) and fails if any rule was never seen to fire. As negative controls, a copy without theSKIPPEDrule and a copy with a rule that has no plant were each reportedBAD.Found, not changed here
src/jit_arm64.zig, and 4 of the 5 insrc/jit_x86_64.zig,returnearly off their own architecture and count as passed there;error.SkipZigTestwould report them as skipped. This is recorded in the spec. Converting them changes the skip count per architecture, so it is left for its own change.trinity_vsa_encode_texthashes the text into one integer (HybridBigInt.fromI64,src/c_api.zig), which is not a semantic encoding: the C example's "similar" pair scores 0.05.Still open in #989
The pinned, byte-checked t27 lock and the capability -> spec -> artifact -> evidence index; the end-to-end task over CLI/MCP, tri-api policy, persistence and the Queen lifecycle; the catalog refresh and publication.
{ "version": 1, "head_sha": "85de91bba047b8ecc58ca13bded27cd3c466e900", "summary": "The five test roots that did not compile on main compile and pass again, so the headless test graph runs whole (135/135 steps, 2760 tests passed, 8 skipped on aarch64) and the spec names no blocked root.", "changes": [ "Fixed the five blocked roots: both dependency module names 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 duplicated if in src/c_api.zig, and the removed packed_trit.zig import.", "Ported src/science.zig, src/vm.zig, src/vsa_jit.zig and src/c_api.zig to the HybridBigInt of the pinned zig-golden-float: the unpacked cache is an array, and dotProduct, bundle2 and bundle3 take no allocator; c_api reaches gen_encoding through the vsa.zig facade.", "Pointed build.zig at the C headers in src/libs/c, where they moved on 2026-03-19, so zig build libvsa and zig build libqueen build again.", "Gave the x86-64 JIT of src/jit.zig the C calling convention its generated code assumes (JitBinaryFn), which the first x86_64 run of the unblocked roots showed was missing.", "Built the e2e and benchmark root with LLVM (use_llvm), because 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 and its wall-clock thresholds measured the backend.", "Emptied BLOCKED_ROOTS in specs/reproduce/headless.t27, raised its floors, added TESTS_SKIPPED_MAX, and fixed tools/reproduce.py: run steps read once from the summary tree, failed tests named, a failed command's output printed and uploaded, a SKIPPED rule, and a self-check that plants a defect for every rule and parses verbatim zig output." ], "tests": [ { "command": "python3 tools/reproduce.py --self-check", "status": "passed", "result": "21 planted defects are each reported under their own code, a conforming record and a blocked root that still fails stay silent, and all 20 rules of the judge were seen to fire; copies without the SKIPPED rule or with an unplanted rule fail.", "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 135/135 steps, 2760/2768 tests passed and 8 skipped, 66 run steps with tests and one empty, 67 compiled roots, no compile failure, both commands exit 0; no violation.", "evidence": "Linux aarch64 container, head 85de91bba047b8ecc58ca13bded27cd3c466e900, fresh zig caches, 3 min 9 s; the record and both command logs written by the tool" }, { "command": "zig test src/jit.zig -target x86_64-linux-gnu, run in an amd64 container", "status": "passed", "result": "All six tests pass with callconv(.c); before the fix, bind correctness and bundle correctness failed exactly as on CI.", "evidence": "Run locally before the commit, Zig 0.15.2" }, { "command": "zig build e2e -Dci=true with use_llvm, x86_64 zig 0.15.2 in an amd64 container", "status": "passed", "result": "99/99 tests including the four x86-64 JIT tests; cosine 11.4 us, permute 12.2 us, pack/unpack 21.8 us per operation; VERDICT 100/100.", "evidence": "Run locally under emulation before the commit; without use_llvm the same root failed the three benchmarks and the verdict, as on CI" }, { "command": "zig build libvsa and libqueen, then zig cc -Wall -Werror on examples/basic.c and semantic_search.c against the installed header and static library", "status": "passed", "result": "Both libraries build with their headers, both examples compile without warnings and run to completion.", "evidence": "Linux aarch64 container with Zig 0.15.2, run locally before the commit" } ], "limitations": [ "The x86_64 numbers are from emulation and from the failing CI run; this PR's own x86_64 job is the first native run with LLVM for the e2e root.", "Most tests in src/jit_arm64.zig and src/jit_x86_64.zig return early off their architecture and count as passed there; they are recorded, not converted to skips.", "The C libraries and their examples are not part of the headless profile, so a regression there is not yet gated." ], "tags": [ "Engineering", "Verification", "CI" ], "blog": { "title": "Five test roots back in the graph, and what kept them out for months", "summary": "Once CI read the exit code of the test step, the five test roots it had hidden were fixed: two module names, libc, a duplicated if, a deleted import, and an old API.", "outline": [ "What the judge named: five roots, among them the library's own test root, and the compiler's message for each.", "Two causes behind most of them: a dependency offered under the wrong name, and code written for an older HybridBigInt.", "What the whole graph shows once it runs: 2760 tests, eight JIT tests that only x86_64 runs, and passes that test nothing." ] } }🤖 Generated with Claude Code