fix(ci): stop two gates passing while verifying nothing, and add a debt register - #306
Conversation
Retiring the bundled cartridges/ tree left two gates looping over a glob that now matches zero files. Both then exited 0 and reported success. - tests/truthfulness_check.sh walked cartridges/*/cartridge.json. It now resolves the catalogue the way the runtime does — BOJ_CARTRIDGES_PATH, else the tracked E2E fixture catalogue — and fails hard on zero manifests. A truthfulness gate that cannot fail is itself an untruth. Verified: 23 cartridges checked, was 0. - scripts/typecheck-proofs.sh advertised 'core + all cartridge ABIs' and claimed PASS=105 in PROOF-NEEDS.md; with the tree gone it checked one package. The dead loop is removed (the registry type-checks its own abi/ dirs in its own gate) and the vacuous-pass guard is ported from boj-server-cartridges' twin of this script, which already had it. Neither repo had both halves: this one lacked the vacuous-pass guard, the registry lacks the weekly schedule backstop. That gap is recorded in the new DEBT register. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
DEBT.md indexes known debt across seven domains (licence, proof, CI/CD, code, test, documentation, supply chain). Every item carries the command that produced its evidence, so any row can be re-checked or falsified in one step; unverified claims are labelled DIAGNOSIS (unconfirmed) rather than asserted. It links the existing registers (PROOF-NEEDS, TEST-NEEDS, proof-debt, tech-debt) instead of duplicating them. The register's headline finding is that the cartridges/ retirement is one incomplete migration wearing ten disguises — two permanently-off workflows, scripts looping over nothing, count claims in fourteen documents, and 1,346 files of build residue. Also corrects PROOF-NEEDS.md, which claimed 'exactly 5' sanctioned axioms and PASS=105. There are 4 (charEqSym was discharged 2026-06-24; check-trusted-base.sh has said EXPECTED_AXIOMS=4 ever since, and docs/proof-debt.md agrees), and the gate now covers 1 package because the 104 cartridge ABIs moved to the registry. Two documents that described themselves as in sync disagreed with each other and with the code. 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 with suggestions 1 resolved / 2 findingsFixes false-green CI gates and introduces a technical debt register. Consider updating the stale docstring in typecheck-proofs.sh and confirming the truthfulness check targets the real catalogue rather than fixtures.
💡 Quality: Stale docstring still claims it type-checks every cartridge ABI📄 scripts/typecheck-proofs.sh:5-13 The file header (lines 8-13) still states the script type-checks "every cartridge ABI (its .ipkg if present, else each .idr individually)" and that the old recipe "covered just 5 of ~50 cartridge ABIs", but this PR removed that loop so only the core ✅ 1 resolved✅ Edge Case: Truthfulness gate now only checks 23 fixtures, not real catalogue
🤖 Prompt for agentsOptionsDisplay: 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 |
There was a problem hiding this comment.
Configure merge blocking · Maintainers can dismiss this review.
…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>
…t exist Sharpens C-3. The finding was 'unpinned actions'; the truth is worse — all 26 gates are hyperpolymath/cicd-suite/actions/*@main and hyperpolymath/cicd-suite returns 404, anonymously and to a token that can see all 35 private repos in the account. The workflow has never run in either repo. This matters for the remediation: it cannot be SHA-pinned, because there is nothing to pin to. Committing it as-is would add a workflow that fails on every run in both repos. It needs an owner decision — delete, or create cicd-suite first — not a mechanical pinning sweep. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
My previous revision said the audit workflow points at a repository that does not exist. True of GitHub, but misleading about the cause and the cure. A local checkout at developer/hyper-repos/cicd-suite holds all 26 referenced actions, each with an action.yml, matching the workflow's references exactly — but it has 0 commits and no remote. The workflow is correct; the repository was simply never published. That makes the item actionable rather than mysterious, and fixes the remediation order: publish cicd-suite, then SHA-pin against a real commit, then commit the workflow. Pinning first is impossible; committing first adds a workflow that fails on every run. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
C-3: the 404 is fixed — hyperpolymath/cicd-suite is published at 11b5ab51 and all 26 referenced actions resolve. The workflow stays untracked deliberately, because running its hard gates against this repo today fails both: required-files-check on 3 missing files, and code-hygiene-check on 112 files — including the four sanctioned, documented, CI-counted believe_me axioms that ARE this repo's declared trusted base. Satisfying required-files-check means adding presence-only filler, which is exactly how the ARCHITECTURE.md / MAINTAINERS boilerplate on fix/zig-ptr-cast-shim came to exist. C-7 (new): 13 of the 26 actions cannot fail at all, and the suite contradicts itself — one gate hard-fails you for lacking GOVERNANCE.md while another warns it should be .adoc. rollout_estate.sh has already placed the consuming workflow in 199 repos, untracked in 198. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
cicd-suite#1 repairs code-hygiene-check (whole-tree case-insensitive grep: 112 matching files here, now 2 true positives) and required-files-check (presence-only checking that rewarded template filler), and ends the contradiction where one gate hard-failed a repo for lacking GOVERNANCE.md while another warned it should be .adoc. C-7 drops HIGH to MEDIUM: what remains is the advisory/enforcing split, 13 of 26 actions that cannot fail. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
… over an empty set (#308) 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 test` printed *"All FFI tests passed!"* over zero items. `aspect_tests.sh` Aspect 4 printed *"All cartridges accounted for (0 complete, 0 stub, 0 ffi_only)"*. Both now fail on an empty set. ## Changes | Item | What | |---|---| | **`Justfile`** | 8 sites in 6 recipes now read `CARTS="${BOJ_CARTRIDGES_PATH:-tests/fixtures/cartridges}"`, the convention `tests/e2e_full.sh` already set. `test`/`test-verbose` **fail** on an empty set; `build`/`heal`/`tour` say so out loud. `clean` targets the fixture only — deliberately **not** the operator's fetched cache. 108 recipes still parse. | | **`scripts/refresh-bundled-cartridges.sh`** | Deleted — it existed solely to sync the retired tree, and `rm -rf`'d inside it. No references anywhere. | | **`scripts/boj-selinux-contexts.sh`** | Was labelling `<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.js`** | Its fallback was the deleted tree, so with no env var it silently regenerated an **empty menu**. Now falls back to the fixture and `exit(1)`s on an empty root. | | **`aspect_tests.sh`, `integration.sh`, `federation_multinode.sh`** | Repointed. `integration.sh` step 5's bare `cd` under `set -e` was killing the run outright. | | **`SECURITY.md`** | The vulnerability template sent reporters to `cartridges/browser-mcp/` and `cartridges/cloudflare/` — the latter was never even a real directory name. | | **Gitlinks** | Two `.claude/worktrees` entries 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`/`ready` where `aspect_tests.sh` expects `stub`/`ffi_only`, so a naive repoint produced 23 spurious failures. Rather than loosen the check, all 23 manifests were verified to confirm `catalogued` ≡ manifest-only and `ready` ≡ ffi-without-abi — the two rules that already existed — and the synonyms documented. Likewise `integration.sh` **skips** 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 | check | result | |---|---| | `just --list` | 108 recipes parse | | `bash tests/aspect_tests.sh` | exit 0 — 43 passed, 0 failed; Aspect 4 names the root and 23 items | | same, with an **empty** `BOJ_CARTRIDGES_PATH` | **exit 1** — "completeness verified nothing" | | workflows YAML | 25 parse | | `node --check` + `deno check` | clean | | `shellcheck -S error`, all touched scripts | clean | ## Build residue — reported, not touched **1,346 files / 226 `.so` / 4.3 GB** survive under `cartridges/` on disk, invisible to `git status` (gitignored). Investigated rather than assumed: - **Nothing has touched it in three weeks** — newest mtime `2026-07-17`, retirement commit `2026-08-04`. Zero `cartridge.json`, zero `.zig` sources: it is purely build output. - **The `local-coord-mcp.service` unit does not exist** on this machine, user or system. - **No live process maps any `.so` under `cartridges/`** (`/proc/*/maps` is 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:80` does `COPY cartridges/ /tmp/carts-meta/` from the host build context and never runs `fetch-cartridges.sh`** — `COPY` on a missing source is a hard failure, so that image cannot build. Note the main `container/Containerfile` is **fine**: it fetches into the builder stage first, so its `COPY --from=zig-builder /build/cartridges/` is populated. One file, not both. Also stale and untouched: `stapeln.toml:44` (same empty-loop class, plus `|| true` so 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](https://claude.com/claude-code) --------- Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Two findings from a full-estate audit, plus the register that will keep them visible.
Two gates were passing while checking zero things
Retiring the bundled
cartridges/tree (#300) left two gates looping over a glob that now matches nothing. Both then exited 0 and reported success.tests/truthfulness_check.shwalkedcartridges/*/cartridge.json. Its entire purpose is to guarantee the catalogue never advertises availability it cannot back — and it was reportingtruthfulness: OKhaving inspected 0 cartridges. It now resolves the catalogue the way the runtime does (BOJ_CARTRIDGES_PATH, else the tracked fixture catalogue) and fails hard on an empty subject. Verified: 23 cartridges checked, was 0.scripts/typecheck-proofs.shadvertised "core + all cartridge ABIs" in its job name andPASS=105in the docs; with the tree gone it checked one package. The dead loop is removed (the registry type-checks its ownabi/dirs) and the vacuous-pass guard is ported from boj-server-cartridges' twin of this script, which already had it.Neither repo had both halves of the protection: this one lacked the vacuous-pass guard, the registry lacks the weekly
schedule:backstop that this repo'sproofs.ymlhas precisely because a proof break living in main is otherwise never re-detected. Each contained the other's fix.PROOF-NEEDS.md was wrong about the axiom count
It claimed "exactly 5" sanctioned class-(J) axioms. There are 4 —
charEqSymwas discharged 2026-06-24,check-trusted-base.shhas enforcedEXPECTED_AXIOMS=4ever since, anddocs/proof-debt.mdalready said 4. Two documents describing themselves as in sync disagreed with each other and with the enforcing code. Also corrects thePASS=105claim toPASS=1with a note explaining where the other 104 went.DEBT.md
A root-level register indexing debt across seven domains — licence, proof, CI/CD, code, test, documentation, supply chain. Each row carries the command that produced its evidence, so it can be re-checked or falsified in one step. Unverified claims are labelled DIAGNOSIS (unconfirmed) instead of asserted. It links
PROOF-NEEDS.md/TEST-NEEDS.md/docs/proof-debt.md/docs/tech-debt-2026-05-26.mdrather than duplicating them.Its headline: the retirement is one incomplete migration wearing ten disguises. Two permanently-off workflows (
abi-drift,lsp-dap-bsp— five required contexts that are green-by-skip), scripts looping over nothing, cartridge counts disagreeing three ways across the estate (125 vs 139 vs an actual 142), and 1,346 files of build residue thatgit statuscannot see. A separate PR finishes those tails.Positive controls are recorded too, so the file isn't only bad news — the dual-licence posture is REUSE-correct, the axiom budget is genuinely tight and well-isolated, and TODO density is effectively zero.
🤖 Generated with Claude Code