Library audit: fixes and refutations¶
Another model audited the
48-librarybranch statically and reported 1 critical, 5 major, 56 minor and 47 nit findings, 109 in all. Eight triage agents re-derived each finding from the code, 88 held as reported, 6 held in part, and 15 were refuted with the reason below. Eight fix agents applied the 94, five reviewers read the resulting diff adversarially, and one more agent corrected the 17 details they raised. The critical finding was real and shipped in 0.2.0:gpu_antsignored its Evaporation parameter, and the tutorial's GPU foraging port taught the same call. Ten user-visible fixes join a new### Fixedsection of the 0.3.0 changelog, andHENAD_REQUIRE_GPU=1 ./check.shpasses with 26 more tests than before.
State before¶
The release bump of record #44 sat uncommitted on 48-library, on top of 7faf864, with the shared accumulator's retry in kit.rs.
The audit (dev-docs/deepseek-v4-1-48audit/, gitignored) reviewed that working tree statically, with no build, test or GPU run.
Its register lists each finding by an R-NNN id and an area id, and its verifiers had re-derived every critical, major and minor finding.
What was done¶
Triage¶
Each finding was re-derived against the working tree, with git history, targeted cargo runs and gh api where those settled it.
A finding counts as introduced on the branch only when git show 773a7a5 shows the code differed at v0.2.0, and a style nit on a comment that predates the rules was refuted, since AGENTS.md leaves those alone.
No finding needed a decision from the maintainer.
The six critical and major findings¶
- R-001, Evaporation on the GPU. The merge pass of
gpu_antsand of the tutorial'sgpu_foragingread the field's parameter from the whole composed list, where index 0 isnum_agents, soextract_f32fell back to 0.999. Both now take the field's half ofsplit_params, as the CPU engine does, and the page teaching it says so. A device-free test reads the merge uniform at 0.95, and the tutorial parity test builds both sides at a non-default value, where both copies had matched each other's mistake at the defaults. - R-002, Windows paths in generated code. The binding assertion's message is written through
Debugwith forward slashes, so a nested shader no longer puts\sor\dinto a Rust literal. - R-003, the stamp tests'
init. It fell back to itself on a git before 2.45 and recursed until the test binary aborted. It now falls back to a plaingit init, andcommitted_crategoes through it (R-011), so the packed-refs test gets the ref format it asserts on. - R-004,
gpu_boids' declared memory.GpuAgentState::demandsized the index tables to the world's cells, about 278 times the hash grid at the defaults. It now reads theHashGridthe engine builds, and a registry test checks visual ranges 50 and 1. - R-005, the
packagejob. It namescontents: readandpull-requests: read, whichdorny/paths-filterneeds under the repository's read-only default token. - R-006, a PSE axis of no cells.
ResultSetrefuses a folder whose manifest records a searchSearchSpec::checkrefuses, through a newResultSetError::Search. Patching the subtraction alone would have left the Search view indexing an empty grid.
The minor findings and nits¶
The rest are smaller and grouped here by kind.
- Robustness. The reduce leaf sizes its partial sums to the folded dispatch (R-015, through a
leaf_blockshelper the test pins). A plan caps its configs over all its blocks (R-056).acquire_headlesschecks the baseline beforeraiseclamps it (R-025, throughdevice_limits). A search resume refuses rows past its budget (R-027). Save results refuses a link of a results file's name (R-055). The template'sseed_bufferstolerates a short list (R-042). The sweep draft ignores an undeclared action index in place of dropping a row (R-034). Build is disabled with no model selected (R-035). - Provenance and resume. A resume credits the runs of a session that ended before replacing the manifest (R-023), a merge records its own build as
engine(R-024), and a changed model reads asSchemaChanged(R-028). - henad-build. A
#define_import_pathin a block comment no longer hides an entry (R-007),@binding (N)with a space fails the build like any other odd form (R-009), and a path whoseShaderEntryvariant is no identifier is refused (R-062). - Debug.
agent_lanes!gives its three types manualDebugimpls (R-014, R-101), andNodesandNodeCtximplement it for any model (R-064), which a test-only model withoutDebugpins. - Tests.
gpu_antsjoinsinterleaved_gpu_runs_match_sequential_ones(R-030), the paused-sweep test runs two lanes (R-029), the GPU handle test compares every file (R-061), the parity comparison fails on NaN (R-016), and the limit tests fail without an adapter underHENAD_REQUIRE_GPU(R-060). Device-free tests now compare each grid port's seeded buffer with its CPUinitcell by cell (R-017). - Testing kit. A
ThreadCountskipped at an overridden size says so (R-020,SkipReason::OneJobAtOverride), and the grid job search bisects downward (R-022). - Facade. Eleven more types reachable from listed items, and the
design_csvmodule, havehenad::paths (R-037, R-038). The complete example clears its temporary folder first, so a second run succeeds (R-039). - Repository.
check_packaging.shholds the template's requirements to the workspace's major and minor (R-051) and reads every include form (R-058). The template checks the Mesa tarball's SHA-256 (R-057). Four CI steps setpipefail(R-050). The docs project moves to 0.3.0 (R-052), and the release procedure now names it. - Docs and comments. The rest correct a claim against the code: the docs' GPU seeding sentences (R-017), the settings folder per platform (R-043), the Life page's final
step_cell(R-040),rayonas a dependency of the pool pattern (R-044), theok_ormessages (R-045), boids' query buffer (R-046), several CLI reference examples, and the doc lines over 120 columns or with British spelling in a literal. - Records. Record #44 lists the retry in
kit.rsandAGENTS.mdand no longer says no workspace code changed (R-048). Record #41's grep sentence names the two hits it missed (R-049).
Refuted¶
- R-008: the shader walk follows a directory symlink, as rustc and Cargo do. Skipping it would drop a linked shader directory without a word.
- R-010: a package hashes
Cargo.toml.origby design, which keeps a package's hash equal to the checkout's, and editing a registry download's generated manifest is no supported workflow. - R-026: a run's series is flushed before its row, so a cut-off write cannot leave a row without its series. Only hand damage can, and a check would need its own row count per run kind.
- R-059: the per-pass view
Vecholds one entry per chunk, is documented in place, and any replacement needsunsafeor nested zips. No measurement suggests a win. - R-068: the comment describes the check
every_example_model_joins_the_setmakes. - R-072:
SweepPreparationis crate-private, and every caller routes a search spec away first. - R-077: the two
DefaultSetupcomparisons pin engine contracts carried over from a registry test. - R-081, R-082: both CLI messages changed on purpose, and the CHANGELOG and the CLI reference record them.
- R-085: the proposed count would use the loop's own filter, and the golden
--listtest already catches a lost model. - R-091: a one-row "One at a time" draft writes the same spec as "Every combination", and reading it back as the latter is correct.
- R-094: the About row follows the documented format, and the host's Sources row already gives the hash.
- R-100: the releasing page's
v0.3.0against0.2.0is an example of a mismatched pair, and still a correct one. - R-106: the line moved verbatim from v0.2.0's
main.rs. - R-109: the Build check clones a handful of values once per UI frame.
Of the partial ones, R-018 and R-054 became doc notes, since a resume using the host's execution settings is the existing rule and a browser cannot wait on a paused sweep. R-045, R-057, R-058 and R-102 fixed the part that held.
Review of the fixes¶
Five reviewers read the audit-only diff, the worktree against HEAD with record #44's patch applied.
They found no wrong fix and 17 details: doc claims broader than the code (the source hash, the pool entry rule, NativeOnly, the wasm pause, the credited runs), three tests that would pass without their fix (R-015, R-025, R-064), one Display text, a comment, two markdown lines, one template call rustfmt splits, and one changelog threshold.
All 17 were applied.
Edited tree¶
.
├── AGENTS.md ~ henad-build's deps and binding rule, GPU seeding, the kit's skips
├── CHANGELOG.md ~ [0.3.0] ### Fixed, ResultSetError::Search, the settings-folder line
├── pyproject.toml, uv.lock ~ henad-docs at 0.3.0
├── zensical.toml ~ nav entry #45
├── .github/workflows/ci.yml, release.yml ~ the package job's permissions, pipefail
├── scripts/check_packaging.sh ~ the template's requirements, every include form
├── crates/
│ ├── henad-build/src/ ~ the escaped message, block comments, binding forms, variant names
│ │ └── tests/ ~ generate, paths, binding_lines and the stamp init
│ ├── henad-core/src/ ~ build_info! through __macro_support, Nodes Debug, the plan cap
│ ├── henad-compute/src/ ~ demand's index grid, leaf_blocks, lane Debug, limit and parity tests
│ ├── henad-models/src/ ~ Evaporation, the seed tests, the index demand test
│ ├── henad-explore/src/ ~ resume, merge, result set, device, testing kit, docs
│ │ └── tests/ ~ gpu_ants tracks, the paused sweep, every file, the new refusals
│ ├── henad-cli/ ~ doc and test-doc corrections
│ ├── henad-app/ ~ Build with no model, save links, draft actions, labels, About
│ └── henad/ ~ eleven facade paths, the example's message and fresh folder
├── examples/tutorial/ ~ gpu_foraging's Evaporation, the parity test at 0.95
├── templates/model-project/ ~ seed_buffers, the Mesa digest, README, models() doc
└── docs/
├── authoring/, guide/, reference/ ~ the corrected claims
└── developing/
├── contributing.md, releasing.md ~ the jobs check.sh leaves out, the docs project version
└── agent-record/
├── 20261002-41-library-tutorial.md ~ the grep sentence
├── 20261002-44-library-release.md ~ kit.rs and AGENTS.md in its tree
└── 20261003-45-library-audit-fixes.md +
State after¶
Everything is uncommitted on 48-library, in the main checkout, mixed with record #44's release bump.
A patch of the bump as it stood before this session, m11b-before-audit.patch beside the audit, lets the two be split for separate commits.
HENAD_REQUIRE_GPU=1 ./check.shpassed after the fixes with 1092 tests, none failed, and after the review corrections with 1093.uv run --locked zensical buildpasses with no issues, this record and its nav entry included.- No separate target directory was left behind.
Proposed commit: fix: audit findings on the library branch.
Issues found & future directions¶
- Windows is the only proof of R-002. On Unix the new test passes with or without the fix, and the
windows-2025leg of CI is the first build of a nested shader there. - R-005 is unproven in CI. The
packagejob has never run, and the 403 the audit predicts was not reproduced. - R-025's test reaches the helper alone. An edit that bypasses
device_limitsinacquire_headlesswould go unnoticed without a device. - The audit's questions for the author are all answered by the fixes or refutations above, the resume's execution settings (R-018) and the wasm pause (R-054) among them as documented behaviour.
- Next. The maintainer's release steps of record #44.