fix: finish the cartridges/ retirement — stop six more things passing over an empty set - #308
Conversation
…eted tree The bundled cartridges/ tree was retired in #300, but eight recipes still globbed it. Every one of them matched nothing: * `build`, `test`, `test-verbose`, `heal` looped `cartridges/*/ffi` — zero iterations, and `test` then printed "All FFI tests passed!" over an empty set. A green `just test` proving nothing is exactly the failure mode the retirement cleanup is meant to remove. * `clean` rm -rf'd `cartridges/*/ffi/{.zig-cache,zig-out}` and `cartridges/*/abi/build` — no such paths in tree. * `tour` computed `CART_COUNT=$(ls -d cartridges/*-mcp | wc -l)`, so it reported "Current cartridge count: 0" beside a line saying cartridges now live in the registry. All loops now read a catalog root, defaulting to the tracked fixture catalogue exactly as tests/e2e_full.sh does, and overridable with BOJ_CARTRIDGES_PATH for a cache populated by scripts/fetch-cartridges.sh. Each loop counts what it visited: `test`/`test-verbose` FAIL on an empty set rather than pass, `build`/`heal`/`tour` say so out loud. `clean` targets the in-tree fixture artefacts only — it must not delete an operator's fetched cache. Also drops the stale "17 cartridges" count from `help-me`. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…ule at the cache refresh-bundled-cartridges.sh existed solely to overwrite the in-tree cartridges/ bundle from the canonical registry — it bailed with "run from repo root (cartridges/ not found here)" and, had that check passed, would have `rm -rf`'d directories that no longer exist. Its subject was deleted in #300; the script is deleted with it. Nothing in the tree referenced it (grepped: only its own header). boj-selinux-contexts.sh wrote an fcontext rule for <repo>/cartridges/.*/ffi/zig-out/lib/.*\.so and ran `restorecon -Rv <repo>/cartridges/`, neither of which resolves any more. Cartridge .so files now live in the host-local cache that scripts/fetch-cartridges.sh populates, so the rule is written against that root (BOJ_CARTRIDGES_PATH, default $HOME/.boj/cartridges) and is skipped with an explicit message when no cache is present — rather than labelling a path that cannot exist. The core ffi/zig rule is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…leted tree generate-offline-menu.js fell back to join(__dirname, "../../cartridges") when BOJ_CARTRIDGES_PATH was unset. That path was removed in #300, so on a fresh clone the generator scanned nothing; where stale build residue still sits under cartridges/ on a developer's disk it scanned *that* instead, and either way the operator would be told to hand-edit offline-menu.js from a result that describes no real catalogue. The fallback is now the tracked fixture catalogue, matching tests/e2e_full.sh, and an empty or unreadable catalog root is a hard error with a pointer to scripts/fetch-cartridges.sh — regenerating a menu from zero cartridges must not look like success. offline-menu.js: corrected the header (it is generated from a catalog root, not from cartridges/; the regenerate command is a Deno invocation) and the `summary.total` note, which claimed 127 cartridges were "on disk" under a directory that no longer exists. The number is left as the snapshot it is, now labelled as such. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… passing over empty sets All three scripts still walked the cartridges/ tree deleted in #300. tests/aspect_tests.sh Aspect 1's cartridge-FFI loop globbed $PROJECT_DIR/cartridges/*/ffi, matched nothing, and said nothing. Aspect 4 was worse: `shopt -s nullglob` plus an empty glob gave zero iterations, so incomplete stayed 0 and it printed "PASS: All cartridges accounted for (0 complete, 0 stub, 0 ffi_only)" — a green check over an audit of nothing. Both loops now read a catalog root (BOJ_CARTRIDGES_PATH, default the tracked fixture catalogue). Aspect 1 reports how many FFI dirs it audited and WARNs when there are none; Aspect 4 FAILs outright on an empty root — "completeness verified nothing" — and otherwise names the root and the count in its pass line. Aspect 4 also learns the catalogue's status vocabulary: `catalogued` is the fixture/registry spelling of `stub` (manifest-only) and `ready` of `ffi_only`. Verified against all 23 fixture manifests: the 22 `catalogued` entries carry neither abi/ nor ffi/, and `ready` feedback-mcp carries ffi/ without abi/ — exactly the two existing rules. Without this they would all fall through to the strict `complete` branch and fail for having a shape they are supposed to have. tests/integration.sh Steps 4, 5 and 7 hard-coded cartridges/<name>/{adapter,ffi,abi}. Step 5's bare `cd "cartridges/$cart/ffi"` under `set -e` killed the run outright. All three now read the catalog root and distinguish three cases per cartridge: absent (SKIP, named), manifest-only catalogue entry (SKIP, named — nothing to audit, and reporting a missing adapter there would be a phantom defect), or implemented-but-missing-a-layer (FAIL, as before). Each step also says when it checked nothing at all. Fixes SC2144 while there: `[ -f dir/*_ffi.zig ]` is not a glob test — it errors on two matches and tests a literal pattern on none. tests/federation_multinode.sh LD_LIBRARY_PATH named cartridges/container-mcp/ffi/zig-out/lib, a path that cannot exist, so the entry was inert. Replaced with the catalog-root sweep tests/e2e_full.sh already uses, which adds only lib dirs that are really there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
The "Affected Component" example in the report template named cartridges/browser-mcp/ and cartridges/cloudflare/ — neither of which is in this repo since #300, and cartridges/cloudflare/ was never even a cartridge directory name. A reporter following the template would file against a path the maintainer cannot open. Replaced with real in-tree components, plus an explicit pointer to hyperpolymath/boj-server-cartridges for cartridge-side findings. The rest of SECURITY.md's cartridge references are about the cartridge system as a concept (isolation, loading, sandbox escape) and remain accurate; left alone. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
.claude/worktrees/gov-red and .claude/worktrees/zig-mutex were tracked with mode 160000 (gitlink) while the repo has no .gitmodules. Git had no URL to clone them from, so every fresh clone produced two empty directories that `git status` reported as permanently modified, and no tooling could ever resolve them. They are per-developer Claude Code scratch checkouts and were never meant to be shared. `git rm --cached` removes them from the index only — the directories on disk are untouched — and .gitignore now covers .claude/worktrees/ so the next scratch worktree cannot be committed by accident. Verified: `git ls-files -s` now reports no mode-160000 entries anywhere, and `git check-ignore -v` confirms both paths are covered. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
…et loops Found while finishing the retirement tails (#308): - D-8 (HIGH): container/Containerfile.fly cannot build. It COPYs cartridges/ from the host build context and never runs fetch-cartridges.sh, and COPY on a missing source is a hard failure. The main Containerfile is NOT affected — it fetches into the builder stage first — so this is one file, not both. - D-9 (MEDIUM): stapeln.toml, coord-tui/install.sh, guix.scm and an Elixir test still traverse the deleted tree. stapeln.toml is the same empty-loop class plus `|| true`, so it can never fail. - D-7 (LOW): dead entries left in .hypatia-ignore and .gitleaksignore make the allowlists look larger than the real exposure. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
|
Note Automatic reviews are paused because your trial's included automatic processing has been used for this period. Upgrade now, or comment "Gitar review" to run a review anytime. Code Review ✅ Approved 1 resolved / 1 findingsFinishes the cartridges directory retirement by repointing recipes, tests, and scripts to the active catalog root and preventing empty-set silent successes. Consider harmonizing the global SKIP counter increments between Step 4 and Step 7 in the test scripts.
✅ 1 resolved✅ Quality: SKIP tally inconsistent between Step 4 and Step 7
OptionsDisplay: compact → Showing less information. Comment with these commands to change the behavior for this request:
Important Your trial ends in 3 days — upgrade now to keep code review, CI analysis, auto-apply, custom automations, and more. Was this helpful? React with 👍 / 👎 | Gitar |
✅ All code review findings resolved.
The audit behind #306 found the
cartridges/retirement was roughly 70% done. This finishes the consumers.The recurring defect is the same one #306 fixed in two gates, found six more times: a loop over a glob that now matches nothing, reporting success.
just testprinted "All FFI tests passed!" over zero items.aspect_tests.shAspect 4 printed "All cartridges accounted for (0 complete, 0 stub, 0 ffi_only)". Both now fail on an empty set.Changes
JustfileCARTS="${BOJ_CARTRIDGES_PATH:-tests/fixtures/cartridges}", the conventiontests/e2e_full.shalready set.test/test-verbosefail on an empty set;build/heal/toursay so out loud.cleantargets the fixture only — deliberately not the operator's fetched cache. 108 recipes still parse.scripts/refresh-bundled-cartridges.shrm -rf'd inside it. No references anywhere.scripts/boj-selinux-contexts.sh<repo>/cartridges/. Repointed at the cache root, and skips with a message when no cache exists rather than labelling an impossible path.generate-offline-menu.jsexit(1)s on an empty root.aspect_tests.sh,integration.sh,federation_multinode.shintegration.shstep 5's barecdunderset -ewas killing the run outright.SECURITY.mdcartridges/browser-mcp/andcartridges/cloudflare/— the latter was never even a real directory name..claude/worktreesentries were committed as mode-160000 with no.gitmodules, so a fresh clone got two empty dirs and both showed permanently modified.git rm --cached+.gitignore. Directories on disk untouched.One judgement call worth surfacing: the fixture manifests use
catalogued/readywhereaspect_tests.shexpectsstub/ffi_only, so a naive repoint produced 23 spurious failures. Rather than loosen the check, all 23 manifests were verified to confirmcatalogued≡ manifest-only andready≡ ffi-without-abi — the two rules that already existed — and the synonyms documented. Likewiseintegration.shskips manifest-only cartridges rather than failing them: reporting "missing adapter" against a catalogue that is manifest-only by design would be a fabricated defect in the other direction.Verification
just --listbash tests/aspect_tests.shBOJ_CARTRIDGES_PATHnode --check+deno checkshellcheck -S error, all touched scriptsBuild residue — reported, not touched
1,346 files / 226
.so/ 4.3 GB survive undercartridges/on disk, invisible togit status(gitignored). Investigated rather than assumed:2026-07-17, retirement commit2026-08-04. Zerocartridge.json, zero.zigsources: it is purely build output.local-coord-mcp.serviceunit does not exist on this machine, user or system..soundercartridges/(/proc/*/mapsis clean).Deletion looks safe, but it is disk state outside git — your call, so nothing was removed.
Found en route, deliberately out of scope
container/Containerfile.fly:80doesCOPY cartridges/ /tmp/carts-meta/from the host build context and never runsfetch-cartridges.sh—COPYon a missing source is a hard failure, so that image cannot build. Note the maincontainer/Containerfileis fine: it fetches into the builder stage first, so itsCOPY --from=zig-builder /build/cartridges/is populated. One file, not both.Also stale and untouched:
stapeln.toml:44(same empty-loop class, plus|| trueso it can never fail),coord-tui/install.sh:28,guix.scm:34,elixir/test/js_worker_pool_test.exs:6(two tests currently pass by short-circuiting when Deno is absent), and dead entries in.hypatia-ignore/.gitleaksignore/.dockerignore. These are logged rather than swept so each gets a reviewable change.🤖 Generated with Claude Code