Skip to content

fix(ci): stop two gates passing while verifying nothing, and add a debt register - #306

Merged
hyperpolymath merged 8 commits into
mainfrom
fix/false-green-gates
Aug 7, 2026
Merged

fix(ci): stop two gates passing while verifying nothing, and add a debt register#306
hyperpolymath merged 8 commits into
mainfrom
fix/false-green-gates

Conversation

@hyperpolymath

Copy link
Copy Markdown
Owner

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.sh walked cartridges/*/cartridge.json. Its entire purpose is to guarantee the catalogue never advertises availability it cannot back — and it was reporting truthfulness: OK having 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.sh advertised "core + all cartridge ABIs" in its job name and PASS=105 in the docs; with the tree gone it checked one package. The dead loop is removed (the registry type-checks its own abi/ 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's proofs.yml has 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 4charEqSym was discharged 2026-06-24, check-trusted-base.sh has enforced EXPECTED_AXIOMS=4 ever since, and docs/proof-debt.md already said 4. Two documents describing themselves as in sync disagreed with each other and with the enforcing code. Also corrects the PASS=105 claim to PASS=1 with 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.md rather 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 that git status cannot 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

hyperpolymath and others added 2 commits August 7, 2026 12:34
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>
@gitar-bot

gitar-bot Bot commented Aug 7, 2026

Copy link
Copy Markdown

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.
Learn more

Code Review 👍 Approved with suggestions 1 resolved / 2 findings

Fixes 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.

Auto-approved and auto-merge armed: No blocking issues found.
Please see Auto-approve Docs for details on setting custom approval criteria. — merges when pipeline and required approvals pass.

💡 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 src/abi/boj.ipkg package is now checked. Given the PR's thesis is that docs must match reality, update the top-of-file comment to reflect that cartridge ABIs are now type-checked in the boj-server-cartridges repo, matching the accurate inline comment added at lines 44-48.

✅ 1 resolved
Edge Case: Truthfulness gate now only checks 23 fixtures, not real catalogue

📄 tests/truthfulness_check.sh:48 📄 tests/truthfulness_check.sh:51
truthfulness.yml runs bash tests/truthfulness_check.sh --probe without setting BOJ_CARTRIDGES_PATH, so CATALOGUE_ROOT always falls back to tests/fixtures/cartridges (23 tracked fixtures) rather than the real ~142-cartridge published catalogue. The gate can no longer detect truthfulness drift in the actual catalogue it exists to police — it validates static in-repo test data. This is a genuine improvement over the previous 0-manifest vacuous pass, but narrower than the pre-retirement coverage; consider having the CI job fetch the real cache and export BOJ_CARTRIDGES_PATH (as release.yml already does) so the gate exercises the published catalogue.

🤖 Prompt for agents
Code Review: Fixes 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.

1. 💡 Quality: Stale docstring still claims it type-checks every cartridge ABI
   Files: 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 `src/abi/boj.ipkg` package is now checked. Given the PR's thesis is that docs must match reality, update the top-of-file comment to reflect that cartridge ABIs are now type-checked in the boj-server-cartridges repo, matching the accurate inline comment added at lines 44-48.

Options

Display: compact → Showing less information.

Comment with these commands to change the behavior for this request:

Compact
gitar display:verbose         

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

Comment thread tests/truthfulness_check.sh

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ This PR is blocked due to unresolved code review findings.

Configure merge blocking · Maintainers can dismiss this review.

@gitar-bot
gitar-bot Bot enabled auto-merge (squash) August 7, 2026 11:40
gitar-bot[bot]
gitar-bot Bot previously approved these changes Aug 7, 2026

@gitar-bot gitar-bot Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Gitar has auto-approved this PR and enabled auto-merge (configure)

…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>
hyperpolymath and others added 2 commits August 7, 2026 13:11
…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>
hyperpolymath and others added 2 commits August 7, 2026 14:22
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>
@hyperpolymath
hyperpolymath disabled auto-merge August 7, 2026 14:47
@hyperpolymath
hyperpolymath merged commit 29b517e into main Aug 7, 2026
@hyperpolymath
hyperpolymath deleted the fix/false-green-gates branch August 7, 2026 14:47
hyperpolymath added a commit that referenced this pull request Aug 7, 2026
… 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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

gitar-approved Added by Gitar

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant