Skip to content

fix(ci): one NOW entry per file, and retire merge=union - #2298

Merged
gHashTag merged 1 commit into
masterfrom
fix/2297-now-entries-per-file
Aug 21, 2026
Merged

fix(ci): one NOW entry per file, and retire merge=union#2298
gHashTag merged 1 commit into
masterfrom
fix/2297-now-entries-per-file

Conversation

@gHashTag

Copy link
Copy Markdown
Owner

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 the
shared 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 the
mechanism is exercised end to end rather than described.

Why not just keep merge=union

Because it was measured and it does not work. Both halves below were run against
master @ 7e8de87b1 from a worktree checked out at origin/master, so
master's own .gitattributes was in force:

The damage is on master right now — docs/NOW.md has 137 # NOW headings
against 136 Last updated: lines.

So the rule suppressed real conflict detection locally while providing no
benefit remotely. It is retired for both NOW.md and docs/NOW.md.

The gate asserts strictly more than before, not less

assertion before after
entry present grep -x 'docs/NOW.md' — any modification, incl. a whitespace touch diff must ADD (--diff-filter=A) a docs/now/<date>-<slug>.md
entry fresh first Last updated: line anywhere in a 6,258-line file the filename date, same [yesterday .. tomorrow] UTC window
entry non-empty not checked new: >= 1 heading and >= 1 bullet

Freshness 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 != base so no case could pass vacuously:

case expect got
this PR vs master accept exit 0
no entry added reject exit 1
stale date (2020-01-01) reject exit 1
empty entry file reject exit 1
heading but no bullet reject exit 1
entry modified, not added reject exit 1
far-future date (2030-01-01) reject exit 1
a second, differently-named entry accept exit 0
push event, entry added accept exit 0
push event, no change reject exit 1

scripts/pre-commit Gate 1 and the .githooks/pre-commit staged-entry warning
were exercised separately (fresh / empty dir / stale-only / README-only /
unstaged / staged / absent). The BSD-date fallback was verified with the system
date on macOS, not only with a GNU shim.

Every consumer updated

Enforcing

  • .github/workflows/now-sync-gate.yml — two steps collapse into one; the
    separate grep -m1 "Last updated:" step is deleted, since the script now
    establishes presence and freshness in a single pass.
  • scripts/ci/now-sync-gate-diff.sh — the gate itself.
  • bootstrap/src/suite.rs check_now_sync — scans docs/now/. Also fixes a
    local/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.rs now-gatethis gate was dead. It matched
    ^\*\*Last updated:\*\*, a bold label; nownote.rs has only ever written
    the 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 used git diff, which never
    sees an untracked new file; it now uses git status --untracked-files=all.
  • scripts/pre-commit Gate 1, scripts/verify.sh gate preview.

Writer

  • cli/tri/src/nownote.rstri now add becomes a plain create instead of a
    read-modify-write. Adds slugify with 7 tests, one asserting the filename it
    produces satisfies the CI gate's own pattern.

Docs / help text

  • .gitattributes (with the reasoning in the file), docs/NOW.md archive
    header, 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 covers
docs/now/ recursively, so review routing is unchanged.
tools/withdrawn_live_baseline.txt — its 11 docs/NOW.md keys stay valid
because no existing entry moves.

What this does NOT fix

  • The damaged entry is not repaired. docs/NOW.md has 137 headings and 136
    Last updated: lines; the entry headed
    Wave Loop 421 close-out / Wave Loop 422 setup (2026-07-06) lost its date to a
    union 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.)
  • The existing entries are not migrated. All 137 stay in 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.
  • Every open PR still needs one rebase. All 18 open PRs put their entry
    on docs/NOW.md, a path the new gate no longer accepts, so each must move its
    entry to docs/now/. There is no migration that spares them. Only tri triage: five ordered classes, and blocked is tested before actionable (#2156) #2157 and
    chore: 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 this
    change.
  • The same bottleneck exists elsewhere and is untouched.
    .trinity/experience.md, .trinity/current-issue.md, and especially
    bootstrap/stage0/FROZEN_HASH — a one-line file every PR rewrites — are the
    identical pathology.
  • Throughput is the root cause. ~35 PRs/day against one master with several
    mandatory single-file artifacts. Removing one contention point does not remove
    the pattern that creates them.
  • The root NOW.md is left alone. It is a divergent regular file stamped
    Last updated: 2026-08-09, not the symlink .gitattributes claimed. The
    comment is corrected; the file's fate is the owner's call.
  • .github/workflows/check-now-freshness.yml is left alone. Found while
    mapping consumers: a workflow named "Check Now Freshness" whose only step is
    echo "Checking repository freshness...". It checks nothing. Wiring or
    deleting it changes which checks exist and is a separate decision.
  • Not compiled. cargo was not run (disk was at ~955 MB free). The Rust
    changes were parse-checked with rustfmt and are rustfmt-clean relative to
    master'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.

@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-20 05:27:18 UTC

Summary

Status Count
Total Open PRs 19
PRs with Failing Checks 4
PRs with All Checks Green 15
READY 7
FAILING 4
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=cbbfac87dff3 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag

Copy link
Copy Markdown
Owner Author

CI status: the gate this PR rewrites is green; the three red checks are inherited

check-now-freshness PASSED on this PR, accepting
docs/now/2026-08-20-retire-the-now-md-single-file-bottleneck.md under the new
rules. That is the end-to-end proof: the rewritten gate ran in real CI against an
entry written in the new format.

Three checks are red. All three already fail on 7e8de87b1, this PR's exact
base commit
— verified by run id, not inferred:

check workflow master run on 7e8de87b1 cause
build FPGA E2E Build 32331938258 era, failure fpga::tests::test_smoke_gate_json_synthetic_verify_lean[smoke-gate] SKIP: yosys not on PATH
coverage Seal Coverage failure pre-existing
withdrawn-live Withdrawn Number Gate 32331938258 failure pre-existing

withdrawn-live deserves a specific note, because this PR does touch
docs/NOW.md and the line numbers in its output shift by 21:

  • It reports docs/NOW.md:813 here and docs/NOW.md:792 on master. Same line,
    shifted by the 21-line archive header.
  • The gate keys on path | pattern | sha1(line), not on line number, so the
    shift is irrelevant. The flagged line is byte-identical to master's:
    - **The "FPGA 35/35 at 323 MHz Artix-7" dispute is NOT settled here.** A
    with sha1[:12] = 93e256f28d7c, which is absent from
    tools/withdrawn_live_baseline.txt on master too.
  • It was introduced by 400850702 (docs(arxiv): XC7A100T LUT count is 63,400 — the docs give its flip-flop count #2281), which added the line without
    updating the baseline. Fixing it means adding that hash to the baseline —
    a claims-registry decision, unrelated to the NOW layout, so it is not
    done here.

For the same reason this PR does not re-key the baseline's 11 docs/NOW.md
entries: no existing entry moves, and the keys are content hashes, so they stay
valid.

On compilation

cargo was not run locally. The build job compiled the Rust changes on CI and
reported 163 passed, 1 failed, the single failure being the yosys-dependent
FPGA smoke test above. The new slugify and now_gate tests are in that
passing set.

@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-20 06:31:51 UTC

Summary

Status Count
Total Open PRs 19
PRs with Failing Checks 4
PRs with All Checks Green 15
READY 7
FAILING 4
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=cbbfac87dff3 != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

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
@gHashTag
gHashTag force-pushed the fix/2297-now-entries-per-file branch from 57f7b50 to facd33e Compare August 21, 2026 07:19
@github-actions

Copy link
Copy Markdown
Contributor

📓 NotebookLM Notebook linked to this PR

This notebook contains session context, decisions, and artifacts for this work.

@github-actions

Copy link
Copy Markdown
Contributor

PR Dashboard

Generated at: 2026-08-21 07:19:36 UTC

Summary

Status Count
Total Open PRs 19
PRs with Failing Checks 4
PRs with All Checks Green 15
READY 7
FAILING 4
PENDING 0

Seal Status

  • ⚠️ STALE -- sha256(compiler.rs)=c3ec9fba947b != manifest seal=87e5cbd3ad94.
    The committed NMSE numbers were certified against an older compiler.rs.
    Run scripts/reseal-check.sh locally for the two-step reseal command (advisory; not a merge gate).

@gHashTag
gHashTag merged commit f5be7dc into master Aug 21, 2026
24 of 27 checks passed
gHashTag added a commit that referenced this pull request Aug 21, 2026
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
gHashTag added a commit that referenced this pull request Aug 21, 2026
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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

NOW.md is a single-file merge bottleneck: every open PR is CONFLICTING, and merge=union makes it worse

2 participants