Fil-C on Nix

Filnix wiki

campaign-failure-review.md

Campaign failure review, October 6, 2026

The latest recording is the 300-root release campaign frozen at 01e875b67b93089452f3e20e00b7a9341180ed01. It stopped after 279 attempts: 265 successful, 13 failed, one incomplete (GTK2), and 21 unattempted. The restarted service serves observations and does not retry builds.

Observer memory

The kernel recorded a cgroup OOM at 10:59:55 CEST on October 6 and killed the observer, whose anonymous RSS was about 4 GiB. The native Nix worker was small. The unit's allowance is 4 GiB, but an unconfigured DuckDB on SWA selects a 99.9 GiB budget and 32 threads from host resources. Dashboard queries repeatedly joined the full 13,166,583-event journal for per-root metadata. The journal also kept ART indexes for offsets and (run,seq); a two-million-event measurement found about 33 MiB of index memory versus 2 MiB of base-table buffers. Indexes are an additional growth cost, not evidence that indexes alone caused the OOM.

The runner now configures DuckDB before opening with a 1 GiB budget and two threads. New schema-2 recordings omit the redundant raw event/log indexes; transactional writer ordering remains enforced. Small entity-table constraints remain. A temporary per-run overview cache is rebuilt once at startup and updated in append transactions. Polling no longer joins the raw journal. Existing schema-1 recordings remain readable without migration.

The budget leaves headroom for allocations outside DuckDB's budget; it is not a process RSS ceiling. Graph materialization remains per selected run, and very large individual records still need byte-budgeted paging. See the runner README.

Infrastructure checks and fixes

The native dataset and nine integration tests pass. The committed memory fixture uses two million events, 300 roots, and output/progress observations. A separate 13,200,302-event fixture with approximately one million log lines passed for schema 2 and indexed schema 1; viewer peaks were 442,789,888 and 444,661,760 bytes (about 424 MiB). This checks reopening and HTTP queries at campaign scale; it does not claim an end-to-end replay of every original build or payload.

Package failures

Ten failed roots originate in release-toolchain pthread cancellation: eight from PipeWire and two from LTTng-UST. The three staging patches and their limits are reviewed in the cancellation overview. Both current x86-64 staging cancellation checks were freshly rebuilt and passed. The release pin and its runtime semantics remain unchanged.

BusyBox's SHA acceleration assembly lacks SaRCAsm signatures. Its package now selects portable C SHA1/SHA256 via actual package arguments; the old use step set attributes without changing the configure arguments. The fixed derivation builds, and the installed SHA1/SHA256 applets produce the expected hashes.

Redis's built-in vectorset and loadable modules export the same entrypoint. Fil-C function-descriptor interposition made module loading call the wrong entrypoint. -Bsymbolic fixes the focused ACL module suite (16 tests); the package patch places it in the test-module Makefile because the Tcl runner rebuilds modules outside stdenv's build flags. No ACL tests are skipped. The full configured Redis suite passed all 141 test groups, followed by the installed version check.

The remaining Nix utility-test failure happens before tests start, while a global constructor copies ../alignment.cc through libc++'s builtin memmove. GDB confirmed an eight-byte access starting seven bytes into the literal, with an incorrect eight-byte alignment requirement. Simple string and GoogleTest reproductions, and the isolated original alignment test source at O2/O3, pass; the failing whole-program optimization is not reduced yet. No memory checks were weakened and no utility tests were disabled. Compiler/runtime changes need the review and regressions required by AGENTS.md.

Delivery

After explicit deployment approval, /opt/filnix-v2 was switched to the checked runner (ddnrfa7dljp92w0xcq8mml43q1dgsbnz-filnix-campaign-next-0.1.0) and the service restarted. The closed database and frozen manifest were backed up at /var/lib/filnix-v2/archives/before-memory-fix-20261006T135923Z; the old application remains GC-rooted for rollback.

The public dashboard and /api/resources confirm the 1 GiB/two-thread settings. Repeated overview/detail reads of the actual recording kept process peak RSS around 1.1 GiB and cgroup peak around 1.4 GiB, below the unchanged 4 GiB allowance. The watermark remains 13,166,583 and all root counts are unchanged; the cohort now reports recording-interrupted. Publication paths are unchanged. The service log confirms serving only without automatic retries. This updates the viewer, not the unfinished campaign: a later campaign needs a freshly frozen manifest and an empty recording.