Skip to content

test(gates): the published gate count becomes a build product — two lanes writing the same N+1 auto-merge CLEAN against a loop of N+2 - #104

Merged
joyful-ii-V-I merged 3 commits into
mainfrom
lane/gatecount-generated-2026-09-10
Sep 10, 2026
Merged

joyful-ii-V-I merged 3 commits into
mainfrom
lane/gatecount-generated-2026-09-10

Conversation

@joyful-ii-V-I

@joyful-ii-V-I joyful-ii-V-I commented Sep 10, 2026 •

Copy link
Copy Markdown
Collaborator

The published gate count was hand-written at eight sites across three files. Two lanes that
each add one gate both write N+1; git auto-merges the identical text clean, and the tree
then publishes N+1 against a loop of N+2 — with every existing check green, because "my count
equals my own loop" holds on each branch, "my loop equals main's loop" holds after the merge,
and the member sets differ at the same number. It collided seven times in one night on
2026-09-10 and serialised every gate-adding lane.

This makes the number a build product, the way docs/COMMANDS.md and docs/LIMITS.md
already are.

docs/gatecount_build.py derives the count from the single for _g in …; do loop in
test/regression.sh and rewrites all eight sites. --check exits 1 on drift, --root
retargets a synthetic tree, --sites prints the site list.

The marker. Each site carries a comment the generator owns — <!-- gatecount --> in
markdown (invisible when rendered on GitHub) and // gatecount in the deck's JavaScript. A
count claim on an unmarked line is a hand-written count and the generator refuses the tree
rather than leave it behind; a marker that has lost its claim is refused too.

test/gatecountcheck.sh, written before the generator and watched red:

arm what it proves
A the generator's count matches an independent derivation of the loop
B every marked site states what the loop names right now
C can-go-red on a synthetic tree via --root (never a probe file in this one — that perturbs the crawl other gates measure); a second added gate reds it again
D a stripped marker is refused in both --check and write mode
E an unparseable loop is a refusal, not a fabricated number
F the three hand-kept copies of the site list (generator, gate, manifestcheck) agree

manifestcheck's arms are all kept, none weakened. The generator is how the sites are
written; manifestcheck is what notices one written some other way. Arm (F) closes the gap
those two site lists left — nothing compared them before.

Also proven by hand: editing the deck's stat(s, "578", …) spelling by hand reds arm (B) and
naming the site; stripping a marker from README.md reds (A) and (B) with both claim lines
listed; regenerating clears each.

The merge recipe for a gate-adding lane is now: union the for _g in … sets, run
python3 docs/gatecount_build.py, done. 577 → 578 in this PR was produced by that command,
not by hand.

Registered in the same commit: the loop, binoverridecheck's pinned exemption list (the gate
binds no ripwire binary, so (2b)'s static tell needs no row), docs/README.md's index, the
CONTRIBUTING.md submission checklist, and docs/EVALS.md §6/§8.

Touches no src/ — the binary is unchanged, so --for / --pack-task / the flagless map are
byte-identical by construction.

Local: gatecountcheck, manifestcheck, limitstablecheck, readmedriftcheck,
docscommandscheck, deckcheck, deckclaimcheck, ripwirepubliccheck, gateexitcheck,
gateabilitycheck, pargatescheck, loopconservationcheck, qschemetripcheck,
runhintcheck, testmacrocheck, affectedcheck — all green. binoverridecheck (runs every
non-exempt gate against a broken stub) is left to CI.

The motivating case, observed on a real rebase an hour after this PR opened

A lane rebased onto dc48e1e9. test/regression.sh was the ONLY conflict, and all eight published count sites auto-merged clean to 577 while the resolved loop named 578, with not one conflict marker among them, because main's string and the lane's string were both literally "577 gate scripts". The number was wrong in eight places and the only thing that could see it was manifestcheck.

The sites do not conflict because both sides agree on a stale value, so "resolve the conflicts and you are done" is exactly the reasoning that ships the wrong number. After this PR the recipe is: union the for _g in sets, run python3 docs/gatecount_build.py, done. A marker whose claim was deleted is refused (a claim deleted is a claim drifted).

The one red run, for the record

Shard 2 went red on every platform: forrankordercheck arm (3) pins 4% byte bands on ten --for reference queries over the live repo, and the new generator's function named rewrite became a rank-1 name-exact hit for "compact legend rewrite" (+15%). Renamed to rewrite_marked_sites. That arm measures the corpus, not the tool, and two other queries already sit at +3.5% of the band from ordinary growth; filed as a follow-up.

🤖 Generated with Claude Code

@coderabbitai

coderabbitai Bot commented Sep 10, 2026 •

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Advanced

Run ID: 18bedc8d-e112-4f00-add7-8fca35962b00

📥 Commits

Reviewing files that changed from the base of the PR and between ccb5c7e and d46d864.

📒 Files selected for processing (5)
  • README.md
  • docs/EVALS.md
  • docs/gatecount_build.py
  • present/deck5_ripwire_build.js
  • test/regression.sh
🚧 Files skipped from review as they are similar to previous changes (3)
  • present/deck5_ripwire_build.js
  • README.md
  • docs/EVALS.md

Included review availability: Your plan provides up to 4 included reviews per hour; 1 remains after this review.


📝 Summary

Summary by CodeRabbit

  • Documentation

    • Updated the published test-gate count from 577/578 to 579 across the README, evaluation documentation, and presentation deck.
    • Added contributor guidance for regenerating gate counts and documenting required markers and workflow.
  • New Features

    • Added automatic tooling to derive and update published gate counts from the regression suite.
    • Added validation for stale, missing, or malformed gate-count entries.
  • Tests

    • Added coverage for gate-count generation, synchronization, marker enforcement, and failure handling.

Walkthrough

The change derives the published gate count from the regression loop, updates marked documentation and deck sites to 579, adds generator checks, and documents the regeneration workflow.

Changes

Gate count generation and validation

Layer / File(s) Summary
Derive and validate the gate count
docs/gatecount_build.py, test/regression.sh, test/gatecountcheck.sh
The generator derives the count from the absorb loop, validates marked sites, and supports checking or rewriting. The new gate tests drift, malformed loops, missing markers, regeneration, and site-list agreement.
Update published count sites
README.md, docs/EVALS.md, present/deck5_ripwire_build.js
Published gate counts change to 579. Markdown and JavaScript sites gain generator-owned markers.
Integrate validation and document regeneration
test/binoverridecheck.sh, test/manifestcheck.sh, CONTRIBUTING.md, docs/README.md
Existing checks record the new gate and site-list rules. Contributor documentation describes the generator command and marker requirements.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant RegressionLoop
  participant GatecountBuild
  participant PublishedSites
  participant GatecountCheck
  RegressionLoop->>GatecountBuild: derive gate count
  GatecountBuild->>PublishedSites: check or rewrite marked counts
  GatecountCheck->>GatecountBuild: verify drift and refusal cases
  GatecountBuild-->>GatecountCheck: return validation status
Loading

Suggested reviewers: quaterniondrift

Merge Risk: ⚪ Minimal · up to d46d8

The change generates gate counts from the regression loop and validates published sites; current validation reports pass with no actionable merge-blocking risk identified.

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 6 files. (2 skipped: 2… Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly identifies the main change: the published gate count becomes a generated build product and addresses the merge issue that motivated it.
Description check ✅ Passed The description directly explains the generator, validation gate, marker design, merge failure mode, registered files, and validation results.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
Full details: Docstring Coverage

Explanation

Docstring coverage is 40.00% which is insufficient. The required threshold is 80.00%. Docstring coverage is scoped to functions touched by this diff. Analyzed 5 functions across 6 files. (2 skipped: 2 unsupported.)

  • Fix all pre-merge checks with AI
✨ Finishing Touches 💡 1
📝 Generate docstrings 💡
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch lane/gatecount-generated-2026-09-10

Comment @coderabbitai help to get the list of available commands.

joyful-ii-V-I and others added 3 commits September 10, 2026 09:04
…anes writing the same N+1 auto-merge CLEAN against a loop of N+2

The number was hand-written at eight sites across three files. Two lanes that each add
one gate both write N+1; git auto-merges the IDENTICAL text clean, and the tree then
publishes N+1 against a loop of N+2 with every existing check green — "my count equals
my own loop" holds on each branch, "my loop equals main's loop" holds after the merge,
and the member SETS differ at the same number. That collided seven times in one night
on 2026-09-10 and serialised every gate-adding lane.

So the number stops being written by hand, the way docs/COMMANDS.md and docs/LIMITS.md
already did:

- docs/gatecount_build.py derives it from the single `for _g in …; do` loop in
  test/regression.sh and rewrites all eight sites. --check exits 1 on drift, --root
  retargets a synthetic tree, --sites prints the site list.
- Each site carries a marker the generator owns: `<!-- gatecount -->` in markdown
  (invisible when rendered) and `// gatecount` in the deck's JavaScript. A count claim
  on an UNMARKED line is a hand-written count and the generator refuses the tree rather
  than leave it behind; a marker that has lost its claim is refused too.
- test/gatecountcheck.sh, written first and watched red: (A) the generator's count
  against an independent derivation, (B) --check over the real tree, (C) can-go-red
  against a SYNTHETIC tree via --root (never a probe file in this one — that perturbs
  the crawl other gates measure), (D) a stripped marker refused in both modes, (E) an
  unparseable loop refused, (F) the three hand-kept copies of the site list agree.

manifestcheck's derived-vs-stated arms are all KEPT and none weakened: the generator is
how the sites are WRITTEN, manifestcheck is what notices one written some other way.
The new arm (F) closes the gap those two lists left — nothing compared them before.

The merge recipe for a gate-adding lane is now: union the `for _g in …` sets, run
`python3 docs/gatecount_build.py`, done. 577 -> 578 here was produced by that command,
not by hand.

Touches no src/; the binary is unchanged, so --for/--pack-task/the flagless map are
byte-identical by construction.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
… for a reference query

test/forrankordercheck.sh arm (3) pins byte bands on ten `--for` reference queries run over THIS
repository. Query q2 is "compact legend rewrite"; adding a Python function literally named `rewrite`
made it the rank-1 name-exact hit, served with its body, and q2 went 9,961 → 11,483 B (+15.3%) against
a 4% band — red on every shard-2 job, all platforms. Nothing about the tool changed; the corpus did.

`rewrite` → `rewrite_marked_sites`, which is also the more honest name (it rewrites only the marked
sites, never a bare count). q2 is back to 9,991 B. forrankordercheck, gatecountcheck, manifestcheck
and limitstablecheck all pass locally against the 633a1d2 binary.

Recorded as a follow-up, not fixed here: arm (3) measures the live repo, so ordinary corpus growth
erodes its band (q3 +3.57% and q9 +3.51% of 4% before this lane touched anything); it should measure a
frozen fixture or re-pin per commit.

touches no src/: --for, --pack-task and the flagless map are byte-identical by construction

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
…he loop is the union, the number is 579

main (6f91fed) gained dartcheck while this PR was in CI; both sides had written the identical
"578 gate scripts" at all eight sites, so every one of them conflicted only because of this PR's
markers — without them they would have auto-merged clean at 578 against a loop of 579, which is the
exact failure this PR exists to end. Resolution: keep the marked line per block, union the two
`for _g in` sets (dartcheck + gatecountcheck), run `python3 docs/gatecount_build.py`.

touches no src/: --for, --pack-task and the flagless map are byte-identical by construction

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@joyful-ii-V-I
joyful-ii-V-I force-pushed the lane/gatecount-generated-2026-09-10 branch from a684da8 to d46d864 Compare September 10, 2026 13:05
@joyful-ii-V-I
joyful-ii-V-I merged commit 1d11c8d into main Sep 10, 2026
27 checks passed
@joyful-ii-V-I

Copy link
Copy Markdown
Collaborator Author

Landed as main 1d11c8d. Loop membership = the 578 members main had at 6f91fed (Dart) plus exactly gatecountcheck = 579, and the eight published sites read 579 because the generator wrote them. For every lane behind this: union your for _g in set with main's, run python3 docs/gatecount_build.py, commit the result. Nobody needs the number.

joyful-ii-V-I added a commit that referenced this pull request Sep 10, 2026
… join the integration branch

Count sites: markers on both sides, digits regenerated at the tip. regression.sh: union. docs/README.md and
test/binoverridecheck.sh: the integration side is a superset of main's. docs/LIMITS.md, docs/COMMANDS.md and
test/printf_parity.manifest are re-derived from the rebuilt binary at the tip, never merged.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
joyful-ii-V-I added a commit that referenced this pull request Sep 10, 2026
…r that retires the first one

Rebased 633a1d2 -> dc48e1e -> 6f91fed -> 1d11c8d while main landed nine times. Both recorded
failure modes fired, in opposite directions, and the second rebase is what makes the pair legible.

1. SAME NUMBER, DIFFERENT MEMBERS — the silent one. Against 6f91fed, main had added `dartcheck` and
   this lane `claudeconfigdircheck`, so BOTH loops read 578 and all eight published sites auto-merged
   CLEAN at 578. Every count-comparison check passes on that and it is wrong: `comm -3` on the member
   lists shows one addition on each side, so the union was 579. Only test/regression.sh conflicted
   loudly; it is resolved as the UNION (main's line with claudeconfigdircheck inserted), never
   `--ours`/`--theirs` on a file whose other rows merged correctly.

   The final rebase onto 1d11c8d makes that unnecessary going forward: PR #104 turned the number
   into a build product. So this lane no longer hand-writes it. The count sites now conflict LOUDLY
   (main's lines carry the `<!-- gatecount -->` / `// gatecount` markers, this lane's did not), each
   block is resolved to main's marked line, and the number is DERIVED:

       python3 docs/gatecount_build.py --check   ->  loop names 580, 8 sites say 579  (red)
       python3 docs/gatecount_build.py           ->  wrote 580 to 8 marked sites
       python3 docs/gatecount_build.py --check   ->  all 8 state 580                  (green)

   580 is the union re-derived on the merged tree — main's 579 (which already includes dartcheck and
   gatecountcheck) plus claudeconfigdircheck — and the generator arrives at it independently of the
   `comm -3` above, which is the point of it existing.

2. NEITHER SIDE OF A PIN CONFLICT IS CORRECT. On the 6f91fed rebase, test/printf_parity.manifest's
   `help_all` row conflicted because main moved it (Dart's flags widened --help --all) and this lane
   moved it (the --scan-skills entry now prints ${CLAUDE_CONFIG_DIR:-~/.claude}). main's 886001ce was
   wrong on that tree and this lane's 648a6c05 was wrong on it; the merged tree's value, 6f808e43,
   exists on neither side and came only from rebuilding after the merge. Re-pinned there with
   UPDATE_GOLDEN_EXPECT=help_all (one row moved, 41 unchanged), and re-verified on this tip: a
   --clean-first rebuild and a fresh UPDATE_GOLDEN move NOTHING, so 6f808e43 is still the merged
   tree's answer and the row is correct as it stands.

docs/COMMANDS.md likewise regenerates byte-identically here, so the merge of main's Dart regen with
this lane's help line needed no hand-editing.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
joyful-ii-V-I added a commit that referenced this pull request Sep 10, 2026
…eventh it did not, and the census gate

Contributed by @s0undt3ch as PR #101. Every path that resolved Claude Code's config directory read
$HOME/.claude and ignored CLAUDE_CONFIG_DIR, the variable Claude Code itself honours; the fix follows
the ${CODEX_HOME:-} / ${AGENTS_HOME:-} / ${HERMES_HOME:-} pattern already beside it.

REVIEW FINDING. The six sites #101 names are correct and are NOT the whole census. The seventh is
claudeInspect() in src/codexdoctor.h, which builds both <claudeHome>/skills and
<claudeHome>/settings.json. Measured on #101 as submitted: with CLAUDE_CONFIG_DIR set,
skills/install.sh deploys into the relocated home and reports success, and --doctor --agent=claude
then reports claude-skills ok="0" manifest="0" declared="0" live="0" with a hint to re-run the
installer that had just worked.

GATE. test/claudeconfigdircheck.sh, 16 arms: 12 fail on unmodified main, 5 on #101 as submitted
(arm A names src/codexdoctor.h by line; all three --doctor arms red), 16 pass here. Arm (A) is a
CENSUS over executable code rather than a list of the known sites, so an eighth is red on the commit
that adds it; its mutation control reverts by the variable NAME and requires all eleven resolution
lines to be exposed. Arms (G)/(H)/(I) pin what a relocation raises beyond the diff: unset unchanged,
empty-is-unset in shell and C++ alike, and a relocation naming a missing directory never silently
reading the ~/.claude beside it.

CHANGED ON THE CONTRIBUTOR'S BRANCH, both stated in their own commits:
  * agentDetector() — the second hand-written exception took it 13 -> 19 against a bar of 15 and
    --quality-delta exited 2, the same refusal that function's comment already records at 19 -> 24.
    Its claude branch and the existing opencode branch now share relocatableRootDetector();
    behaviour identical on both sides.
  * the gate and its consequences — registration, printf_parity's help_all row, docs/COMMANDS.md,
    and the README installer line brought into line with the two below it.

Gate loop 579 -> 580, derived by docs/gatecount_build.py (PR #104's generator) rather than written
by hand. Full local suite green; CI 27/27 on 7ceab40; CodeRabbit: no actionable comments.
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.

1 participant