You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
The Debt-exception: and Ratchet-exception: commit trailers are the only sanctioned escape hatch for the debt and exemption ratchets. On this repository they have never once survived into main's history. Both ratchets fail when re-run against main today.
The mechanism works perfectly pre-merge and is erased by the merge.
Measured
#954 raised two debt ceilings and declared both correctly. The PR-branch commits carried:
Debt-exception: gate-scripts-without-tests — re-baselining fossilized 31/30 to measured 40/40 (#953); falls as tests land.
Debt-exception: todo-fixme-markers — re-baselining fossilized 77/76 to measured 80/80 (#953); advisory markers only.
governance / Debt ratchet passed on the PR — correctly, because check-debt-ratchet.sh:133 scans git log --format=%B "${BASE_REF}..HEAD" and the trailers were there.
The squash merge then collapsed those two commits into 9c256b67, whose message carries neither trailer at column 0:
The only surviving trace is indented, backticked prose inside the PR description, which the gate's grep -iE '^Debt-exception' cannot match by design.
Both ratchets now fail against main's own history:
$ bash scripts/check-debt-ratchet.sh be6c9580 # be6c9580 = #954's actual CI base
rc=1 "A debt ceiling rose, or an entry was deleted, without saying so."
$ bash scripts/check-exemption-ratchet.sh be6c9580
rc=1 same shape
It has never worked, not once
Across every commit that has ever touched .machine_readable/Debtfile.a2ml:
Root cause — a repository setting, not a script bug
$ gh api repos/hyperpolymath/standards --jq '{squash_merge_commit_title, squash_merge_commit_message}'
{"squash_merge_commit_title":"PR_TITLE","squash_merge_commit_message":"PR_BODY"}
PR_BODY means the squash commit's message is the pull request description, not the concatenated branch commit messages. So a trailer written into a commit is discarded at merge by design. Only text in the PR body survives — and only at column 0 would the gate ever match it.
This is not specific to standards. Both comparison repos share the setting:
repo
title / message
hyperpolymath/standards
PR_TITLE / PR_BODY
hyperpolymath/rsr-template-repo
PR_TITLE / PR_BODY
metadatastician/stapeln
PR_TITLE / PR_BODY
Any repo adopting these ratchets inherits the same hole.
Why it matters
The audit trail the mechanism exists to create does not exist. Every ceiling raise in this repo's history looks unjustified. The reasons were written; they were thrown away.
The gate is self-defeating on re-run. Any process that re-checks a merged range — a release audit, a bisect, a consumer pinning an older base — sees an undeclared raise it cannot explain.
The escape hatch cannot be audited for abuse. You cannot grep main for "who raised a ceiling and why", which is the one question the trailer was invented to answer.
Proposed cures — three options, owner's call
Change the setting to COMMIT_MESSAGES. Branch commit messages are concatenated into the squash commit, so trailers survive verbatim. Cost: the curated PR body no longer becomes the commit message, and squash commits get noisier.
Make the gate check the PR body as well as the commit range.github.event.pull_request.body is available to the workflow. This makes the gate consistent with what actually persists under PR_BODY, and can be paired with (2).
My recommendation is (1) plus (3): (1) makes the record durable regardless of author behaviour, and (3) makes the gate measure the thing that actually survives. (2) alone is the weakest arm — it has already been tried implicitly and failed.
Acceptance criteria
A ceiling raise merged to main leaves a column-0 Debt-exception: line greppable in git log on main.
bash scripts/check-debt-ratchet.sh <base of the merge> exits 0 when re-run against main after such a merge.
Same for check-exemption-ratchet.sh and Ratchet-exception:.
A regression test merges (or simulates) a squash and asserts the trailer survives — this defect is invisible to any test that only exercises a PR branch.
The chosen cure is applied to rsr-template-repo and the template, so adopting repos do not inherit the hole.
Related: #955 (the debt breach that surfaced this), #787 (decision surface).
Summary
The
Debt-exception:andRatchet-exception:commit trailers are the only sanctioned escape hatch for the debt and exemption ratchets. On this repository they have never once survived intomain's history. Both ratchets fail when re-run againstmaintoday.The mechanism works perfectly pre-merge and is erased by the merge.
Measured
#954 raised two debt ceilings and declared both correctly. The PR-branch commits carried:
governance / Debt ratchetpassed on the PR — correctly, becausecheck-debt-ratchet.sh:133scansgit log --format=%B "${BASE_REF}..HEAD"and the trailers were there.The squash merge then collapsed those two commits into
9c256b67, whose message carries neither trailer at column 0:The only surviving trace is indented, backticked prose inside the PR description, which the gate's
grep -iE '^Debt-exception'cannot match by design.Both ratchets now fail against
main's own history:It has never worked, not once
Across every commit that has ever touched
.machine_readable/Debtfile.a2ml:Debt-exceptiontrailers9c256b6708f77c140afcfd4c092dedad5db75ff7e083dfe75fcf81f243ab303cZero out of eight.
Root cause — a repository setting, not a script bug
PR_BODYmeans the squash commit's message is the pull request description, not the concatenated branch commit messages. So a trailer written into a commit is discarded at merge by design. Only text in the PR body survives — and only at column 0 would the gate ever match it.This is not specific to
standards. Both comparison repos share the setting:hyperpolymath/standardsPR_TITLE/PR_BODYhyperpolymath/rsr-template-repoPR_TITLE/PR_BODYmetadatastician/stapelnPR_TITLE/PR_BODYAny repo adopting these ratchets inherits the same hole.
Why it matters
mainfor "who raised a ceiling and why", which is the one question the trailer was invented to answer.Proposed cures — three options, owner's call
COMMIT_MESSAGES. Branch commit messages are concatenated into the squash commit, so trailers survive verbatim. Cost: the curated PR body no longer becomes the commit message, and squash commits get noisier.github.event.pull_request.bodyis available to the workflow. This makes the gate consistent with what actually persists underPR_BODY, and can be paired with (2).My recommendation is (1) plus (3): (1) makes the record durable regardless of author behaviour, and (3) makes the gate measure the thing that actually survives. (2) alone is the weakest arm — it has already been tried implicitly and failed.
Acceptance criteria
mainleaves a column-0Debt-exception:line greppable ingit logonmain.bash scripts/check-debt-ratchet.sh <base of the merge>exits 0 when re-run againstmainafter such a merge.check-exemption-ratchet.shandRatchet-exception:.rsr-template-repoand the template, so adopting repos do not inherit the hole.Related: #955 (the debt breach that surfaced this), #787 (decision surface).