fix(ci): one NOW entry per file, and retire merge=union - #2298
Conversation
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
CI status: the gate this PR rewrites is green; the three red checks are inherited
Three checks are red. All three already fail on
For the same reason this PR does not re-key the baseline's 11 On compilation
|
00dd763 to
57f7b50
Compare
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-08-20 06:31:51 UTC
Summary
Seal Status
|
Entries were prepended to the single file docs/NOW.md, so every PR rewrote its first line and all 18 open PRs are marked CONFLICTING by GitHub. Entries are now one file per unit of work, docs/now/<YYYY-MM-DD>-<slug>.md: two PRs write two different paths, so the shared line is gone rather than papered over. merge=union is retired for both NOW.md and docs/NOW.md. Measured, not assumed: git merge-tree from a worktree checked out at origin/master reports docs/NOW.md clean for PRs GitHub simultaneously calls CONFLICTING, so the driver never ran where the conflicts were reported. Where it did run its failure mode is silent duplication: docs/NOW.md should hold one `Last updated:` line per entry heading and holds it for every entry but one, `Wave Loop 421 close-out / Wave Loop 422 setup (2026-07-06)`, which carries no date line. The gate asserts strictly more than before: presence (the diff must ADD an entry, --diff-filter=A), freshness (filename date in the same [yesterday .. tomorrow] UTC window), plus a new content assertion of one heading and one bullet, which closes the vacuous-touch hole a whitespace edit used to walk through. Freshness reads the filename, so there is no first-Last-updated coupling and no line for two branches to duplicate. Two dead consumers fixed in passing: tri hooks now-gate matched a bold **Last updated:** label that occurs 0 times in docs/NOW.md -- every stamp there is plain -- and so could never pass; suite.rs check_now_sync demanded today's LOCAL date where CI allowed a UTC window, blocking work locally that CI would accept. docs/NOW.md is frozen as a historical archive with a pointer header. The existing entries are NOT migrated and the orphaned entry is NOT repaired. Rebased onto master after #2300 landed. Three notes on that resolution: - #2300 added two now_gate tests that pass a FILE. This change makes now_gate take a directory, so read_dir gives ENOTDIR and neither can survive. One of them, now_gate_agrees_with_the_live_gate_on_the_real_document, was the only test in the module that touched the real repository; dropping it for five temp-fixture tests would have been a net loss of liveness coverage. It is replaced by the directory analogue, now_gate_agrees_with_the_ci_gate_on_the_real_entries_directory, which runs the gate against the real docs/now/ and cross-checks the entry against the independent pattern and content rules in scripts/ci/now-sync-gate-diff.sh. It derives its expected date from the newest entry present rather than from Utc::now(), so it asserts agreement without asserting freshness and cannot go red merely because nobody wrote an entry today. Its one honest limit is recorded in the test: docs/now/ is created by this PR, so today it asserts against the directory this PR itself adds. - The FROZEN ARCHIVE banner is placed at line 1 explicitly. Under union it landed below master's newest entry, which read as though entry #1 were exempt from "do not add entries here". - Absolute counts in the prose (137 headings / 136 date lines) went stale within one wave -- master is at 138/137 now. They are restated as the invariant they were evidence for, in .gitattributes, in the banner, and in the now_gate doc comment. Closes #2297
57f7b50 to
facd33e
Compare
|
📓 NotebookLM Notebook linked to this PR
This notebook contains session context, decisions, and artifacts for this work. |
PR DashboardGenerated at: 2026-08-21 07:19:36 UTC
Summary
Seal Status
|
Rebuilt PR #1815 on top of master (10e3d5e) keeping only content that master does not already carry: - .claude/plans/wave-loop-884.md (new) - docs/reports/FPGA_LOOP_CLOSEOUT_W883_2026-08-06.md (new) - docs/reports/FPGA_LOOP_COOPERATION_W884_2026-08-06.md (new) - .trinity/experience.md: W883 entry inserted between W884 and W777 - .claude/skills/t27-wave-loop.md: worked example for Wave Loop 883 Deliberately dropped: specs/scratch/ witnesses and scratch_*.json seals (both gitignored, and a scratch seal would red the seal gate), docs/NOW.md (frozen archive since #2298), the icarus_lowerable.rs test block and scripts/gen_w882.py / gen_w883.py (already on master, byte-identical), and stale live-status pointers superseded by wave 898. Closes #1814
Rebuilt PR #1815 on top of master (10e3d5e) keeping only content that master does not already carry: - .claude/plans/wave-loop-884.md (new) - docs/reports/FPGA_LOOP_CLOSEOUT_W883_2026-08-06.md (new) - docs/reports/FPGA_LOOP_COOPERATION_W884_2026-08-06.md (new) - .trinity/experience.md: W883 entry inserted between W884 and W777 - .claude/skills/t27-wave-loop.md: worked example for Wave Loop 883 - docs/now/2026-08-21-wave-loop-883-record.md (new coordination entry) Deliberately dropped: specs/scratch/ witnesses and scratch_*.json seals (both gitignored, and a scratch seal is the phantom class the seal gate says to drop), docs/NOW.md (frozen archive since #2298 - the docs/now/ entry above replaces that hunk), the icarus_lowerable.rs hunk and scripts/gen_w882.py / gen_w883.py (already on master, byte-identical), and stale live-status pointers superseded by wave 898. Refs #1814
Two sentences in R12 contradicted machine-readable truths in this repository, and both were wrong on the day they were written. `Refs #N` DOES satisfy `check-linked-issue`. The matcher at `.github/workflows/issue-gate.yml:69` is `(Closes?|Fixes?|Resolves?|Refs?|Updates?)\s*#[0-9]+` and has carried `Refs?` since `5850c302e` (2026-07-07). R12's denial was written 2026-08-20: 44 days late on arrival, not stale. Seven readers in this tree carry that dictionary and R12 was the only dissenter -- while demanding the one spelling R11 forbids nineteen lines above, since `Closes` autocloses on merge. The repair does NOT re-transcribe the dictionary; it points at the gate. A hand-copied copy missing `Refs` once matched 4 references where the gate matched 33, and this sentence was the next copy to go wrong. Recorded in the rule itself so the third copy is not written either. R12 also still told authors to add a section to `docs/NOW.md`, whose first line reads FROZEN ARCHIVE -- do not add entries here, frozen in `f5be7dc1c` (#2298) on 2026-08-21 for exactly the collision reason R12 exists to avoid. `.claude/skills/spec-first-ternary-nn.md:62` carried the same instruction and is corrected with it. The guard is deliberately NOT added, on a measurement rather than on caution. Every mention of `docs/NOW.md` under `.github/workflows/`, `scripts/` and `.githooks/` is a comment: zero lines reject an edit, so the freeze is prose only. But the obvious rule -- fail any diff containing the file -- is too broad: of the 600 commits since the freeze, 2 touched it and one (`458ec0bd6`) REPAIRS damaged entries. The banner forbids ADDING entries, not touching the file, and a guard that blocks a legitimate repair is the shape this repository documents as one that gets muted. The narrow rule is filed in #3368. Resealed: the rule text changed, so `LOOP-RULES.sha256` moves with it in this commit. R6 -- the seal certifies identity, not correctness. Found by the adversarial sweep for #3355. These two are the MIRROR of that class: the truth is machine-readable and the prose is the stale transcription. Co-authored-by: lab <lab@example.com> Co-authored-by: Claude Opus 5 <noreply@anthropic.com>
Closes #2297
Entries move from one prepend-to-the-top file to one file per unit of work:
docs/now/<YYYY-MM-DD>-<slug>.md. Two PRs write two different paths, so theshared line every PR was fighting over no longer exists.
This PR's own entry is written in the new format
(
docs/now/2026-08-20-retire-the-now-md-single-file-bottleneck.md), so themechanism is exercised end to end rather than described.
Why not just keep
merge=unionBecause it was measured and it does not work. Both halves below were run against
master@7e8de87b1from a worktree checked out atorigin/master, somaster's own
.gitattributeswas in force:git merge-treereportsdocs/NOW.mdcleanfor PRs GitHub simultaneously labels
CONFLICTING— including tri triage: five ordered classes, and blocked is tested before actionable (#2156) #2157 andchore: civilian mesh positioning — drop drone wording (bpsk.t27) #1874, which conflict on nothing else. Mergeability on the platform ignores
merge drivers, so the rule bought nothing where the conflicts were reported.
duplication, not removal: two branches editing one
Last updated:linemerge with no conflict into two adjacent
Last updated:lines under asingle heading. Under the default driver that is a conflict a human resolves.
The damage is on master right now —
docs/NOW.mdhas 137# NOWheadingsagainst 136
Last updated:lines.So the rule suppressed real conflict detection locally while providing no
benefit remotely. It is retired for both
NOW.mdanddocs/NOW.md.The gate asserts strictly more than before, not less
grep -x 'docs/NOW.md'— any modification, incl. a whitespace touch--diff-filter=A) adocs/now/<date>-<slug>.mdLast updated:line anywhere in a 6,258-line file[yesterday .. tomorrow]UTC windowFreshness reading the filename removes the prepend-order coupling that made
"newest entry" and "first line of the file" the same fact, and removes the
Last updated:line that two branches could duplicate.The trusted-bot bypass (
dependabot[bot],github-actions[bot]) is unchanged.Gate self-test
The gate was run against real commits, each on its own branch, with a guard
asserting
head != baseso no case could pass vacuously:2020-01-01)2030-01-01)pushevent, entry addedpushevent, no changescripts/pre-commitGate 1 and the.githooks/pre-commitstaged-entry warningwere exercised separately (fresh / empty dir / stale-only / README-only /
unstaged / staged / absent). The BSD-
datefallback was verified with the systemdateon macOS, not only with a GNU shim.Every consumer updated
Enforcing
.github/workflows/now-sync-gate.yml— two steps collapse into one; theseparate
grep -m1 "Last updated:"step is deleted, since the script nowestablishes presence and freshness in a single pass.
scripts/ci/now-sync-gate-diff.sh— the gate itself.bootstrap/src/suite.rscheck_now_sync— scansdocs/now/. Also fixes alocal/CI mismatch: it demanded today's date in the local timezone where
CI allowed a UTC window, so it could block work locally that CI would accept.
Both now use one window.
cli/tri/src/hooks.rsnow-gate— this gate was dead. It matched^\*\*Last updated:\*\*, a bold label;nownote.rshas only ever writtenthe plain form, and master has 0 bold occurrences against 136 plain. It
could never pass on a real checkout. Now a directory scan, with tests.
.githooks/pre-commit— the staged-entry warning usedgit diff, which neversees an untracked new file; it now uses
git status --untracked-files=all.scripts/pre-commitGate 1,scripts/verify.shgate preview.Writer
cli/tri/src/nownote.rs—tri now addbecomes a plain create instead of aread-modify-write. Adds
slugifywith 7 tests, one asserting the filename itproduces satisfies the CI gate's own pattern.
Docs / help text
.gitattributes(with the reasoning in the file),docs/NOW.mdarchiveheader,
docs/now/README.md(new),.github/PULL_REQUEST_TEMPLATE.md,docs/BRANCH-PROTECTION.md,scripts/setup-git-hooks.sh,bootstrap/src/main.rs,cli/tri/src/main.rs.Deliberately not touched:
.github/CODEOWNERS—/docs/already coversdocs/now/recursively, so review routing is unchanged.tools/withdrawn_live_baseline.txt— its 11docs/NOW.mdkeys stay validbecause no existing entry moves.
What this does NOT fix
docs/NOW.mdhas 137 headings and 136Last updated:lines; the entry headedWave Loop 421 close-out / Wave Loop 422 setup (2026-07-06)lost its date to aunion merge. Its date cannot be recovered without guessing, so it is left
as-is. (The brief cited line 4793; measured on master it is at line 5717,
which shifts to 5738 once this PR's header is applied — hence the heading text
rather than a line number.)
docs/NOW.md,now frozen with a pointer header. (The brief said 121;
grep -c '^# NOW'reports 137.) Splitting them is mechanical and would make this unreviewable.
on
docs/NOW.md, a path the new gate no longer accepts, so each must move itsentry to
docs/now/. There is no migration that spares them. Only tri triage: five ordered classes, and blocked is tested before actionable (#2156) #2157 andchore: civilian mesh positioning — drop drone wording (bpsk.t27) #1874 are NOW-only; the rest also collide on
bootstrap/src/compiler.rs,bootstrap/stage0/FROZEN_HASH,scripts/tri,scripts/tri_loop/*.py,bootstrap/tests/icarus_lowerable.rs, three.claude/skills/*.md,.trinity/current-issue.md,.trinity/experience.md, and.github/workflows/schema-validation.yml. No open PR was touched by thischange.
.trinity/experience.md,.trinity/current-issue.md, and especiallybootstrap/stage0/FROZEN_HASH— a one-line file every PR rewrites — are theidentical pathology.
mandatory single-file artifacts. Removing one contention point does not remove
the pattern that creates them.
NOW.mdis left alone. It is a divergent regular file stampedLast updated: 2026-08-09, not the symlink.gitattributesclaimed. Thecomment is corrected; the file's fate is the owner's call.
.github/workflows/check-now-freshness.ymlis left alone. Found whilemapping consumers: a workflow named "Check Now Freshness" whose only step is
echo "Checking repository freshness...". It checks nothing. Wiring ordeleting it changes which checks exist and is a separate decision.
cargowas not run (disk was at ~955 MB free). The Rustchanges were parse-checked with
rustfmtand arerustfmt-clean relative tomaster's baseline, but CI is the first real build.
Owner decision
This changes the contract of a required status check repo-wide, so
auto-merge has deliberately not been armed. Merging is the owner's call.
Once merged, the 18 open PRs need the one-line rebase described above.