Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 10 additions & 0 deletions docs/loop/LOOP-RULES.md
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,16 @@ in `f5be7dc1c` (#2298) precisely because one file per PR is what stops every
concurrent PR colliding on its first line, and this rule went on naming it for
sixteen days.

`docs/NOW.md` is now ENFORCED, not merely labelled: a range that edits it is
refused unless a commit in it carries

Archive-Repair: <what was damaged, and how you know>

Repairing the archive is legitimate -- one of the two post-freeze edits is a
repair of destroyed bodies -- and no textual rule separates a repair from a new
entry, since the repair adds headings too. So the exception is DECLARED rather
than detected. The gate does not judge the reason; it requires one to exist.

Reference the issue in the PR body. `Refs #N` DOES satisfy `check-linked-issue`:
the matcher is `(Closes?|Fixes?|Resolves?|Refs?|Updates?)\s*#[0-9]+` at
`.github/workflows/issue-gate.yml:69`, and seven readers in this tree carry that
Expand Down
2 changes: 1 addition & 1 deletion docs/loop/LOOP-RULES.sha256
Original file line number Diff line number Diff line change
@@ -1 +1 @@
f4c3c52eb779142edd011d3ce39faf71f12a4a69a677ecb5b42ca8b8e7b6fbd9 docs/loop/LOOP-RULES.md
6d68cc1592b9078f888081b8d8cb8bc0f4ea1b9ce1705d38adbff8e130c6a466 docs/loop/LOOP-RULES.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
# NOW -- A frozen file that nothing refused to open (2026-09-07)

## A frozen file that nothing refused to open (Closes #3368)

- `docs/NOW.md` says FROZEN ARCHIVE on line 1, and every mention of it under `.github/workflows/`, `scripts/` and `.githooks/` was a comment -- measured, zero lines rejected an edit. An author following a stale instruction could reopen it and pass all four required checks.
- Both detection rules were measured and BOTH fail: 'refuse any diff touching it' blocks the one legitimate repair in the population, and so does 'refuse an added `## ` heading' -- that repair adds three, because it restored headings whose bodies were destroyed.
- So the exception is DECLARED rather than detected: `Archive-Repair: <reason>` in the commit message, the same shape as `# tri:no-dispatch` and `# tri:cause-removed`. The gate does not judge the reason; it requires one to exist.
- Six controls on a scratch repository -- PR and push, with and without the trailer, a bare trailer, and an untouched file. Historical control: `458ec0bd6` carries no trailer and would be refused, correctly. Blast radius: 2 commits in 600.
58 changes: 58 additions & 0 deletions scripts/ci/now-sync-gate-diff.sh
Original file line number Diff line number Diff line change
Expand Up @@ -79,21 +79,79 @@ if [ "$event" = "pull_request" ]; then
require_rev "$BASE" PR_BASE_SHA
require_rev "$HEAD" PR_HEAD_SHA
ADDED=$(git diff --diff-filter=A --name-only "$BASE" "$HEAD" | grep -E "$ENTRY_RE" || true)
RANGE_FROM="$BASE"; RANGE_TO="$HEAD"
elif [ "$event" = "push" ]; then
BEFORE="${PUSH_BEFORE:?}"
AFTER="${PUSH_AFTER:?}"
require_rev "$AFTER" PUSH_AFTER
if [ "$BEFORE" = "0000000000000000000000000000000000000000" ]; then
ADDED=$(git show --diff-filter=A --name-only --pretty=format: "$AFTER" | grep -E "$ENTRY_RE" || true)
RANGE_FROM=""; RANGE_TO="$AFTER"
else
require_rev "$BEFORE" PUSH_BEFORE
ADDED=$(git diff --diff-filter=A --name-only "$BEFORE" "$AFTER" | grep -E "$ENTRY_RE" || true)
RANGE_FROM="$BEFORE"; RANGE_TO="$AFTER"
fi
else
echo "::error::now-sync-gate-diff.sh: unsupported GITHUB_EVENT_NAME=$event"
exit 1
fi

# --- THE FROZEN ARCHIVE ---------------------------------------------------
# docs/NOW.md carries "FROZEN ARCHIVE -- do not add entries here." on its first
# line, and until now NOTHING enforced it: every mention of that path under
# .github/workflows/, scripts/ and .githooks/ is a comment -- measured, zero
# lines reject an edit. An author following one of the stale instructions that
# still pointed there could reopen the archive and pass all four required checks.
#
# A blanket "refuse any diff touching it" is WRONG, and that was measured too:
# of the 600 commits since the freeze, 2 touched the file and one (458ec0bd6)
# REPAIRS damaged entries. So is the narrower "refuse an ADDED `## ` heading" --
# that same repair adds three of them, because it restored headings whose bodies
# had been destroyed. No textual rule separates adding an entry from repairing
# one: the only difference is POSITION, which is the coupling the one-file-per-
# entry layout exists to remove.
#
# So the exception is DECLARED, where the tool looks, the way `# tri:no-dispatch`
# and `# tri:cause-removed` are. A commit that edits the archive on purpose says
# so in its own message:
#
# Archive-Repair: <what was damaged, and how you know>
#
# The gate does not judge the reason. It requires one to exist, so that reopening
# a frozen file is a decision somebody signed rather than an accident.
if [ -n "$RANGE_TO" ]; then
if [ -n "$RANGE_FROM" ]; then
TOUCHED=$(git diff --name-only "$RANGE_FROM" "$RANGE_TO" -- docs/NOW.md || true)
MSGS=$(git log --format=%B "$RANGE_FROM".."$RANGE_TO" || true)
else
TOUCHED=$(git show --name-only --pretty=format: "$RANGE_TO" -- docs/NOW.md || true)
MSGS=$(git log -1 --format=%B "$RANGE_TO" || true)
fi
if [ -n "$TOUCHED" ]; then
if printf '%s\n' "$MSGS" | grep -qE '^Archive-Repair:[[:space:]]*[^[:space:]]'; then
echo "docs/NOW.md edited under an Archive-Repair trailer -- allowed."
else
echo "::error::docs/NOW.md is a FROZEN ARCHIVE and this range edits it."
echo ""
echo "Its first line says so. Entries go in one file each:"
echo " docs/now/<YYYY-MM-DD>-<slug>.md"
echo ""
echo "If you are REPAIRING the archive rather than adding to it -- restoring a"
echo "body the tooling destroyed, say -- that is allowed, and it has to be said"
echo "out loud. Put a trailer in the commit message:"
echo ""
echo " Archive-Repair: <what was damaged, and how you know>"
echo ""
echo "The gate does not judge the reason; it requires one to exist. A blanket"
echo "refusal was measured and rejected: 1 of the 2 post-freeze edits is a"
echo "legitimate repair, and it adds headings, so no textual rule tells the two"
echo "apart."
exit 1
fi
fi
fi

if [ -z "$ADDED" ]; then
echo "::error::SYNC REQUIRED: this PR/push adds no docs/now/ entry."
echo ""
Expand Down
Loading