Skip to content

Debt ratchet red on every PR since #820 — run-debtfile.sh --write emits a file check-debtfile-structure.sh rejects #955

Description

@hyperpolymath

Summary

governance / Debt ratchet has failed on every PR to this repo since 0afcfd4c (#820), independent of the PR's content. Observed on six consecutive merged PRs. The failure is not in check-debt-ratchet.sh — that gate passes. It is in scripts/check-debtfile-structure.sh:79-80, which rejects count > ceiling.

Root cause — the writer emits a file its own validator refuses

scripts/run-debtfile.sh documents at lines 35-36:

--write   update `count` in place, and lower `ceiling` to match when debt
          has been paid down (the auto-ratchet). Never raises a ceiling.

and appends the new count at lines 111-113 regardless of whether the entry breached:

if [ "$out" != "$count" ]; then
  NEW_COUNT_IDS+=("$name"); NEW_COUNT_VALS+=("$out")
fi

So when debt grows, --write raises count, deliberately refuses to raise ceiling, and exits 1 — leaving behind exactly the internally inconsistent file that check-debtfile-structure.sh:79 rejects. This is a design contradiction between the two scripts, not an editing slip.

It has happened twice. e083dfe7 (#724) produced gate=33/31, deno=5/4 and was cured by an actual paydown at 5db75ff7. 0afcfd4c (#820) produced the current state and was never followed by a paydown.

History — every revision that touched the Debtfile

rev gate-scripts todo-fixme deno-residue commit
43ab303c 31/31 276/276 — a Debtfile and a debt runner (#591)
5fcf81f2 31/31 276/276 4/4 track Deno removal as a probed integer (#601)
e083dfe7 33/31 76/76 5/4 re-measure Debtfile probes (#724) — first breach
5db75ff7 31/31 76/76 4/4 re-measure after the paydown — cured
092dedad 30/30 76/76 1/1 retire Deno from check-ts-allowlist (#730)
0afcfd4c 31/30 77/76 2/1 re-measure Debtfile probes (#820) — the live breach
08f77c14 31/30 77/76 2/1 validate-sha-pins could not fail (#882) — values carried forward untouched

#882 merely carried the values forward. #947 and #948 never touched the file.

Observed verdicts

gh pr view <N> --json statusCheckRollup, filtered to the Debt check:

PR #898   governance / Debt ratchet=FAILURE
PR #899   governance / Debt ratchet=FAILURE
PR #931   governance / Debt ratchet=FAILURE
PR #946   governance / Debt ratchet=FAILURE
PR #947   governance / Debt ratchet=FAILURE
PR #948   governance / Debt ratchet=FAILURE

(#882–#893 return no Debt check from the API; that may be check retention rather than absence, so no claim is made about them.)

Current state vs live probes

entry count ceiling live probe verdict
gate-scripts-without-tests 31 30 40 real drift, +9 beyond the record
todo-fixme-markers 77 76 80 real drift, +3 (severity low)
deno-residue 2 1 3 probe defect — true non-comment value is 0

deno-residue is a false positive of a class the spec already names

docs/DEBTFILE-SPEC.adoc:269-275 documents it: "Writing a ## Banned languages heading into a register is not a banned language. Every textual probe therefore excludes the register and its spec." The deno-residue probe excludes only file globs, so prose about the ban scores as the ban.

All five matching lines across all three files are comments describing Deno's removal:

.github/workflows/ci-pipeline.yml:377          # This job used to install a pinned Deno binary and run `deno lint` /
.github/workflows/ci-pipeline.yml:378          # `deno fmt --check`, announcing the ban with a `::warning::`. A
.github/workflows/governance-reusable.yml:375  # existed only to be fed to `deno run`, which forced a
.github/workflows/governance-reusable.yml:376  # `denoland/setup-deno` install onto a REQUIRED context in every
scripts/check-ts-allowlist.deno.js:15          // standalone `deno test`, by packages/affine-deno/mod.js.

Non-comment count: 0. This repo has zero live Deno invocations. Attribution: the two hits in ci-pipeline.yml and governance-reusable.yml were introduced by #899 (git log -S), which moved the live probe 2→3. #899 did not cause the breach — it was already 2/1 before #899 landed — but it did widen the gap.

Proposed cure — three parts, two need an owner decision

  1. deno-residue — correct the probe to exclude comment lines; count 0, ceiling 0. This is a ratchet down, so no Debt-exception: trailer is required. ⚠ But the entry's own description already concedes the probe counts a comment and accepted ceiling 1, so this is a design change to a curated register, not a bug fix. Owner call.
  2. gate-scripts-without-tests 30→40 and todo-fixme-markers 76→80 — genuine ceiling raises, each requiring a column-0 Debt-exception: trailer. This is exactly the debt-acceptance decision the ratchet exists to force to a human. Owner call.
  3. run-debtfile.sh — resolve the writer/validator contradiction. Either --write refuses to write a count above its ceiling (and says so), or the structure check tolerates it. Leaving both is what produced chore(debt): re-measure Debtfile probes #724 and chore(debt): re-measure Debtfile probes #820.

⚠ A2ML doctrine. A values-only reconciliation of Debtfile.a2ml is maintenance and is in bounds. A probe redesign is closer to new gate work on a dead format; the elegant long-term arm is moving the register to .deed. Flagged, not actioned here.

Acceptance criteria

  • bash scripts/check-debtfile-structure.sh exits 0 on main.
  • bash scripts/run-debtfile.sh exits 0 on main (no breach, no expired acceptance).
  • governance / Debt ratchet is green on a fresh PR that changes nothing relevant.
  • run-debtfile.sh --write against a grown probe either refuses to write, or writes a file that check-debtfile-structure.sh accepts — verified by a test in scripts/tests/run-debtfile-test.sh that grows a probe and asserts the two scripts agree.
  • Each ceiling raise that lands carries a column-0 Debt-exception: trailer naming the entry.

Does this block the ci-pipeline rollout?

No. governance-reusable.yml:1484 guards the structure check with if [ -f .machine_readable/Debtfile.a2ml ], and check-debt-ratchet.sh:83-85 exits 0 when neither side has a Debtfile. Caller repos without one are unaffected.

Related: #787 (decision surface).

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    tech-debtKnown shortcut, drift, or hygiene owed - includes cleanup

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions