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