Skip to content

docs(handoff): review plumbing — GraphQL budget, thread-state source, an inert reviewer - #2827

Merged
POWERFULMOVES merged 7 commits into
mainfrom
docs/review-plumbing-graphql-budget
Aug 30, 2026
Merged

POWERFULMOVES merged 7 commits into
mainfrom
docs/review-plumbing-graphql-budget

Conversation

@POWERFULMOVES

Copy link
Copy Markdown
Owner

Four findings from today's merge wave, recorded together because they share one fix surface: the GitHub App plus the bus. Everything here is measured; nothing is implemented, and the doc says so.

1. One identity carries the whole fleet's GitHub load

gh CLI, the github-official MCP, and direct gh api all authenticate as the same user — and GitHub's secondary rate limits are per-user. One agent's burst throttles every node. Decentralisation here shares an identity, not capacity.

The App isn't missing: it's in 12+ workflows, and the runbook already states the benefit — "Higher rate limits (15,000/hr vs 5,000/hr)". The migration checklist covers workflow secrets, not agent CLI auth. CI migrated; agents never did.

Not a build: PMOVES-Archon/packages/core/src/github-auth already mints installation tokens with a three-tier cache and ships installCredentialHelper as the CLI seam.

Bypass already exists too — worth stating because the obvious check disagrees: the classic endpoint reports bypass_apps: [], but the [ main ] ruleset grants two Integrations always-bypass. Rulesets are the live mechanism.

2. No budget counter, and the obvious one lies

gh api rate_limit reports all 15 buckets at full capacity with used=0 while GraphQL refuses every request. Secondary limits are invisible to it, so any preflight reading it asserts more than it measured.

What trips it is a burst of content-creating calls, not volume — today's resolve loops ran with no pacing. Wanted: per-node attribution on the bus, so the fleet can see its spend instead of discovering the ceiling by hitting it.

3. Thread resolution has two sources; we subscribe to neither useful one

method direction available
GraphQL reviewThreads.isResolved query yes — the only queryable source
pull_request_review_thread webhook event yes — resolved/unresolved, carries thread
REST query none
Timeline API query none

REST checked four ways: docs, a live comment object's 27 keys, the timeline API on a PR whose threads had just been resolved, and two 404s.

Auth type changes quota, not surface — so the App grants no REST path; it grants the availability GraphQL needs. That webhook is a separate event from pull_request, and is not subscribed.

4. CodeRabbit reviews nothing, and reports success for it

.coderabbit.yaml, its branch patterns, its path_instructions, and CODERABBIT_HARDENING_PROFILE.md are all inert. Every PR gets the same comment regardless of branch:

This repository does not receive automatic reviews because it has fewer than 10 stars.

Identical across docs/, feat/, chore/ (#2811, #2807, #2812, #2818), with zero inline comments on any. Every review in this wave came from Codex alone.

The sharp end: a CodeRabbit status context reports success for a review that never ran. Not required, so it blocks nothing — but a green tick reads as "reviewed".


These are one lane because they are one defect — a gate or signal asserting more than it measured — the same shape found repeatedly today (git worktree prune exiting 0 while every delete failed; grep -c returning 318 while grep printed 140; pr_closeout printing "4 green" without reading a check's state).

Deferred to the Cipher/NATS bring-up rather than patched here, per the operator: the App makes GitHub reliably reachable, the bus makes what it tells us locally queryable.

🤖 Generated with Claude Code

https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f

…NATS lane

Recorded from a merge wave on 2026-08-29. All four are measured; none are
implemented, and the doc says so.

1. ONE IDENTITY CARRIES THE FLEET. gh CLI, the github-official MCP and direct
   `gh api` all authenticate as the same user, and GitHub's SECONDARY rate
   limits are per-user — so one agent's burst throttles every node. The App
   already exists and is wired into 12+ workflows; the migration checklist
   covers workflow secrets, not local agent CLI auth. Archon's
   packages/core/src/github-auth already mints installation tokens with a
   three-tier cache and ships `installCredentialHelper` as the CLI seam, so
   this is wiring, not building. Bypass already exists too: the classic
   endpoint says `bypass_apps: []`, but the `[ main ]` RULESET grants two
   Integrations always-bypass. Rulesets are the live mechanism.

2. NO BUDGET COUNTER, AND THE OBVIOUS ONE LIES. `gh api rate_limit` reports
   all 15 buckets at full capacity with used=0 WHILE GraphQL refuses every
   request. Secondary limits are invisible to it, so any preflight reading it
   asserts more than it measured. What trips the limiter is a BURST of
   content-creating calls, not volume — the wave's resolve loops ran with no
   pacing. Wanted: per-node attribution published to the bus, so the fleet can
   see its own spend instead of discovering the ceiling by hitting it.

3. THREAD RESOLUTION HAS TWO SOURCES. GraphQL to ask; the
   `pull_request_review_thread` webhook (`resolved`/`unresolved`) to be told.
   REST has neither — verified four ways: the docs, a live comment object's 27
   keys, the timeline API on a PR whose threads had just been resolved, and two
   404s. Auth type changes quota, not surface, so the App grants no REST path;
   it grants the availability GraphQL needs. That webhook is a SEPARATE event
   from `pull_request` and is not subscribed.

4. CODERABBIT REVIEWS NOTHING AND REPORTS SUCCESS FOR IT. `.coderabbit.yaml`,
   its branch patterns, its path_instructions and CODERABBIT_HARDENING_PROFILE
   are all inert: every PR gets "this repository does not receive automatic
   reviews because it has fewer than 10 stars", identical across docs/, feat/
   and chore/ branches, with zero inline comments on any. Every review in this
   wave came from Codex alone. Meanwhile a `CodeRabbit` status context reports
   SUCCESS for the review that did not happen.

They are one lane because they are one defect — a gate or signal asserting
more than it measured — and one fix surface: an App identity that keeps GitHub
reachable, plus a bus that makes what it tells us locally queryable.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Aug 29, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-08-29T14:26:40.244394Z c6222b8 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@coderabbitai

coderabbitai Bot commented Aug 29, 2026

Copy link
Copy Markdown
Contributor

Important

  • 🔍 Trigger review

This repository does not receive automatic reviews because it has fewer than 10 stars.

⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro Plus

Run ID: fafffeb2-e982-4c2f-9ea7-caf3e912cb59


Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@github-actions github-actions Bot added the docs Documentation label Aug 29, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: c6222b852b

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread pmoves/docs/handoffs/4090-review-plumbing-graphql-budget-2026-08-29.md Outdated
Comment thread pmoves/docs/handoffs/4090-review-plumbing-graphql-budget-2026-08-29.md Outdated
Two Codex findings, both correct, both fixed. The first is a design flaw in
the prescription, not a wording problem.

1. THE EVENT STREAM IS NOT SUFFICIENT. `pull_request_review_thread` emits
   `resolved`/`unresolved` TRANSITIONS. It does not emit thread CREATION. So a
   thread created and never touched again has no record, and every thread
   predating the subscription has no record -- both of which read as "no
   unresolved threads" to a cache built from that stream alone.

   That is a false green on the one question pr_closeout must never get wrong,
   since it blocks on EVERY unresolved thread. The design is now a cache PLUS
   reconciliation, not a cache instead of the query: ingest creation as well,
   keep a fail-closed GraphQL reconciliation before the merge decision, and
   treat a cache miss as UNMEASURED rather than zero. The win is that the query
   becomes a cheap confirmation of known state instead of the sole source.

2. READS COUNT TOO. The doc claimed "reading PRs never does" trigger the
   secondary limiter. GitHub also applies secondary CONCURRENCY, CPU-TIME and
   REQUEST-POINT limits to reads and GraphQL queries, so a parallel or heavily
   paginated read loop can be throttled with no content created at all.

   That claim was inferred from which calls happened to trip it here, not
   measured. A counter recording only writes would reproduce exactly the
   false-green this handoff exists to remove: quiet counter, throttled fleet.
   The wave is now presented as the OBSERVED trigger, not the sole cause, and
   the wanted counter covers reads and queries.

Worth stating plainly: a handoff about gates asserting more than they measured
did the same thing twice. Both claims were reasoning from one observation.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
POWERFULMOVES added a commit that referenced this pull request Aug 29, 2026
Same region, same append-only resolution: both sides kept, main's first.

Eight in one session. The cost is no longer per-merge, it is per-PAIR: with N
open claim-bearing PRs, landing them takes N sequential resolve-CI-merge
cycles even though no two claims overlap. Only their position in one file
does. Recorded as a design item in the review-plumbing handoff (#2827).

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
POWERFULMOVES and others added 5 commits August 29, 2026 13:06
…rialisation

Measured 2026-08-29: 8 PRs merged, 10 `Merge main` resolution commits (more
than merges -- several collided repeatedly), 13 still open.

The register collision is real and already documented here: every CLAIM row
appends to the end of one file, so concurrent claims conflict by construction.
But it is the visible half of a wider cost.

`main` sets `required_status_checks.strict: true`, so every merge marks every
other open PR out-of-date and each needs an update plus a FULL CI re-run --
whether or not it touches an overlapping file. Four completely unrelated PRs
went from green to `behind` the moment an unrelated fifth landed today.

Merging N ready PRs takes N sequential update-CI-merge cycles; keeping the set
current as you go costs up to N(N-1)/2 CI runs. At 13 open that is ~78
rebuilds to land work that does not conflict at all.

So the two fixes address different problems and both are worth doing:

  register shape  -> stops PRs CONFLICTING with each other
  strict + queue  -> stops PRs INVALIDATING each other

No merge queue is configured: `merge_queue_enabled` is absent and the
`[ main ]` ruleset carries deletion, pull_request, copilot_code_review and
non_fast_forward with no queue rule. A merge queue is the mechanism built for
this -- batch the pending PRs, test the COMBINED result once, merge the batch
-- which is what `strict` is trying to guarantee without paying per-PR.

Not proposed blindly. A queue changes when checks run and what a green tick on
an individual PR means, and this repo's gates are what it trusts most. Same
decision family as the App and the bus: measure it against one real batch
before switching.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
…ust ours

The strict-serialisation section argued from measurement. GitHub documents the
same case in its own words, which makes the recommendation checkable rather
than a local opinion.

From "Managing a merge queue":

  when to use    branches "that have a relatively high number of pull requests
                 merging each day from many different users" -- 14 merges
                 landed on 2026-08-29
  what it        a queue "does not require a pull request author to update
  replaces       their pull request branch and wait for status checks to finish
                 before trying to merge" -- that update-and-wait IS the tax
                 measured here, named by GitHub as what the queue removes
  mechanism      changes are "grouped into a `merge_group` with the latest
                 version of the `base_branch` as well as changes from pull
                 requests ahead of it in the queue", merged "once the checks
                 required by the branch protections of `base_branch` pass"

That last point is the important one: the queue tests the COMBINED result,
which is the guarantee `strict` is reaching for and paying per-PR to obtain.

So a queue is not a workaround for these protection settings. It is the
supported answer to them, and the measurements in this section are what its
absence costs.

Live example from the same session: #2828 burned four update-CI cycles without
conflicting with anything, and green PRs were deliberately held unmerged
because each merge would have pushed it to a fifth. That scheduling decision
should be the tooling's, not an operator's.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
@POWERFULMOVES
POWERFULMOVES merged commit 36f17fa into main Aug 30, 2026
22 checks passed
@POWERFULMOVES
POWERFULMOVES deleted the docs/review-plumbing-graphql-budget branch August 30, 2026 07:29
POWERFULMOVES added a commit that referenced this pull request Aug 30, 2026
…lisions

main moved while #2818 sat blocked: #2813, #2822, #2825, #2826, #2827,
#2830, #2831, #2832, #2837, #2838 all landed, plus the CodeQL alert
cleanup on main. Automatic merge, no conflicts.

Re-ran the checks that matter for a merge of this size rather than
assuming a clean `git merge` means a correct one:

  duplicate top-level definitions  4 modules, all 4 already shadowed on
                                   main. mcp_server.py stays clean, so
                                   the collision fixed earlier held and
                                   nothing new joined it.
  hardening_ratchet                debt=6, no new, no stale
  validate-dockerfile-paths        OK (93 dockerfiles, 83 referenced)
  validate-command-anchors         498 baselined, 0 new, no stale

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01X9mpK1ZFjexjthZbvcb94f
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

docs Documentation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant