Skip to content

docs(AGENTS.md): read GitHub through REST, and stop mandating GraphQL - #3287

Merged
meshweaver-cloud[bot] merged 1 commit into
mainfrom
docs/rest-not-graphql
Sep 4, 2026
Merged

meshweaver-cloud[bot] merged 1 commit into
mainfrom
docs/rest-not-graphql

Conversation

@rbuergi

@rbuergi rbuergi commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Adds the fleet-shared rest-not-graphql block + its manifest entry, and fixes core's contradictory guidance

Maintainer directive, 2026-09-04: "everyone should use rest".

The occasion. An agent polling gh pr view every 5 s exhausted GitHub's secondary rate limit for the whole session. The limit is per USER, so every concurrent agent lost GitHub access — not just the one polling. Two agents diagnosed it independently and both were misled the same way first:

gh api /rate_limit   →  5000/5000 remaining, 0 used
gh api graphql …     →  "API rate limit already exceeded"

The primary quota is not the signal. That pairing is the signature, so the block says so explicitly — anyone who checks the quota otherwise concludes they are not rate-limited and goes looking somewhere else.

Core was mandating the exact call that causes it

Line 102 said: "Poll the MeshWeaver Build and Test check SUITE by name via GraphQL", and blamed the alternative on "REST rate-limit 403s". Both halves were wrong — that poll is the call that exhausts the limit, and gh run watch / gh pr checks --watch are GraphQL, not REST. It now names the REST form:

gh api "repos/Systemorph/MeshWeaver/actions/runs?head_sha=<sha>"   # filtered on .name

Verified against this org before writing the rule

REST call result
actions/runs?head_sha=<sha> filtered on .name the named workflow's status/conclusion
commits/<sha>/check-runs 41 runs
commits/<sha>/check-suites per-suite status/conclusion
pulls/<n> state, merged, mergeable_state

The block does not forbid GraphQL outright — that would be false guidance. The merge queue's dequeuePullRequest and queue entries have no REST equivalent, so they are named as the reserved exception, and the merge-queue paragraph below is deliberately unchanged.

Two caveats in the text are measured rather than assumed: pulls/<n> answers mergeable: null / "unknown" until GitHub recomputes after a push; and a check suite an installed App never posts runs to stays queued forever — Azure Boards does exactly this here, which is why the existing "never wait for all suites" warning is kept and now names it.

Rollout: text first, manifest last

The six satellites already carry the block — Plugins#1317, Education#268, Reinsurance#161, SocialMedia#137, Manufacturing#51, Memex#179 — verified byte-identical under the gate's own normalisation (soft-wrap collapsed): sha256 0dd144539cdd47f1…, length 1519.

This PR adds the .github/shared-rules.json entry last, because the gate fails RED for a repo that is listed and has no markers. A half-landed rollout must not be able to red the fleet.

🚨 Deliberately a DRAFT. Until those six merge, this PR's own AGENTS.md shared rule blocks check is correctly red — the manifest lists seven repos and only one has the markers on main. Marking it ready before then would be asking the queue to merge a known-red change. Draft is also the documented opt-out from auto-arm.yml.

Incidentally: gh pr create is itself GraphQL and was refused while creating these — all seven PRs were opened over REST (POST /repos/{o}/{r}/pulls), which is the rule demonstrating itself.

🤖 Generated with Claude Code

Adds the fleet-shared `rest-not-graphql` block plus its manifest entry, and
fixes core's own guidance, which currently mandates the thing the block forbids.

Maintainer directive, 2026-09-04: "everyone should use rest".

The occasion: an agent polling `gh pr view` every 5 s exhausted GitHub's
SECONDARY rate limit for the whole session. The limit is per USER, so every
concurrent agent lost GitHub access, not just the one polling. Two agents
diagnosed it independently, and both were initially misled the same way —
`gh api /rate_limit` reads a pristine 5000/5000 remaining, 0 used while every
GraphQL call is refused with "API rate limit already exceeded". The primary
quota is not the signal; that PAIRING is the signature, so the block states it.

Core's line 102 told you to "Poll the MeshWeaver Build and Test check SUITE by
name via GraphQL", and blamed the alternative on "REST rate-limit 403s". Both
halves were wrong: the poll is exactly the call that exhausts the limit, and
`gh run watch` / `gh pr checks --watch` are GraphQL, not REST. It now names the
REST form:

    gh api "repos/Systemorph/MeshWeaver/actions/runs?head_sha=<sha>"   filtered on .name

Verified against this org before writing the rule: actions/runs?head_sha
returns the named workflow's status/conclusion, commits/<sha>/check-runs
returned 41 runs, commits/<sha>/check-suites gives per-suite state, and
pulls/<n> gives state/merged/mergeable_state.

The block does NOT forbid GraphQL outright — that would be false guidance. The
merge queue's `dequeuePullRequest` and queue entries have no REST equivalent
and are named as the reserved exception, which is why the merge-queue paragraph
below is unchanged.

Two caveats in the text are measured, not assumed: pulls/<n> answers
mergeable: null / "unknown" until GitHub recomputes after a push; and a check
suite an installed App never posts runs to stays queued forever — Azure Boards
does exactly this on core, which is why the existing "never wait for all
suites" warning is kept and now names it.

Adopted TEXT-FIRST. The six satellites carry the block already (Plugins#1317,
Education#268, Reinsurance#161, SocialMedia#137, Manufacturing#51, Memex#179),
byte-identical under the gate's own normalisation — sha256 0dd144539cdd47f1,
length 1519. This PR adds the manifest entry LAST, because the gate fails RED
for a repo that is listed and has no markers, so a half-landed rollout must not
be able to red the fleet.

🚨 Held as a DRAFT until those six merge: until then this PR's own
`AGENTS.md shared rule blocks` check is correctly red.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
Copilot AI lite review requested due to automatic review settings September 4, 2026 07:28

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 Changes recommended

The new REST polling guidance introduces SHA placeholders without defining how to obtain them in a REST-only flow, which undermines the goal of avoiding GraphQL usage.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR updates the fleet-wide agent guidance to prefer GitHub REST API usage over GraphQL to avoid triggering GitHub’s secondary rate limits, and registers the new guidance as a shared-rule block for enforcement across repositories.

Changes:

  • Replaces core PR-operations guidance to poll CI status via REST rather than GraphQL-based CLI commands.
  • Adds a new fleet-shared rest-not-graphql shared-rule block to AGENTS.md.
  • Registers the rest-not-graphql block in .github/shared-rules.json so the shared-rule gate can enforce adoption.
File summaries
File Description
AGENTS.md Updates CI polling guidance to REST and adds the rest-not-graphql shared-rule block.
.github/shared-rules.json Adds the rest-not-graphql block definition and required repo list to the shared-rule manifest.
Review details

Suppressed comments (1)

AGENTS.md:129

  • Inside the shared rest-not-graphql block, the {sha} placeholder is never defined. Adding a one-liner for how to read it via REST helps keep the whole watcher loop GraphQL-free.
🚨 **Read GitHub through REST, not GraphQL.** GraphQL exhausts first, and the limit that bites is the **SECONDARY** one — `gh api /rate_limit` keeps reporting `5000/5000 remaining, 0 used` while every GraphQL call is refused with *"API rate limit already exceeded"*. The primary quota is therefore NOT the signal; that pairing IS the secondary limit. `gh pr view --json …`, `gh pr checks` and `gh run watch` all issue GraphQL, so a watcher built on them takes the whole session's GitHub access down with it, for every concurrent agent. REST does everything a PR watcher needs: `gh api "repos/{o}/{r}/actions/runs?head_sha={sha}"` filtered on `.name` for one workflow's `status`/`conclusion`; `.../commits/{sha}/check-runs` and `.../commits/{sha}/check-suites` for the checks; `.../pulls/{n}` for `state`, `merged` and `mergeable_state`. Reserve GraphQL for what REST cannot express — merge-queue entries and `dequeuePullRequest` — and never put one in a loop. 🚨 **Fast retries EXTEND a secondary limit**: on a refusal STOP for at least 5 minutes, do not retry, and do not switch to a different GraphQL query hoping it is cheaper. Poll no faster than 60 s and run ONE watcher, not several. Two REST caveats, both measured: `pulls/{n}` answers `mergeable: null` / `mergeable_state: "unknown"` until GitHub recomputes after a push — re-read, never read that as a verdict; and a check SUITE an installed App never posts runs to stays `queued` forever, so wait on the ONE workflow you care about by name, never on all suites.<!-- shared-rule:end rest-not-graphql -->
  • Files reviewed: 2/2 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread AGENTS.md
🚨 **PR capability is CREDENTIAL × REPO — measure it for the repo you are in, never remember it** (`gh api repos/Systemorph/<repo> --jq '.permissions'`; `gh auth status`). The same repo answers differently to two sessions on the same day. **Never reach for `--admin`** — a refusal is information about the gate, not an obstacle to route around; on `FORBIDDEN`, re-authenticate with `! gh auth login`.

🚨 **Poll the `MeshWeaver Build and Test` check SUITE by name via GraphQL and merge only on `COMPLETED/SUCCESS`.** Never wait for *all* check suites (an installed App that posts no runs leaves its suite `queued` forever), and never poll with `gh run watch` / `gh pr checks --watch` (REST rate-limit 403s masquerade as CI-red). `Consolidate test results` is the required check and the only one to require.
🚨 **Poll the `MeshWeaver Build and Test` workflow by name over REST and merge only on `completed`/`success`** — `gh api "repos/Systemorph/MeshWeaver/actions/runs?head_sha=<sha>"`, filtered on `.name`. Never wait for *all* check suites (an installed App that posts no runs leaves its suite `queued` forever — `Azure Boards` does exactly this here), and never poll with `gh run watch` / `gh pr checks --watch`: both issue GraphQL, and exhausting the SECONDARY limit takes GitHub access away from every concurrent agent while `/rate_limit` still reads `5000/5000`. `Consolidate test results` is the required check and the only one to require.
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 0)

251 tests  ±0   251 ✅ ±0   2m 19s ⏱️ +7s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 1)

474 tests  ±0   474 ✅ ±0   57s ⏱️ -5s
  1 suites ±0     0 💤 ±0 
  1 files   ±0     0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 5)

    4 files  ±0      4 suites  ±0   1m 42s ⏱️ -30s
1 447 tests ±0  1 447 ✅ ±0  0 💤 ±0  0 ❌ ±0 
1 448 runs  ±0  1 448 ✅ ±0  0 💤 ±0  0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 3)

368 tests  ±0   366 ✅ ±0   39s ⏱️ -9s
  3 suites ±0     2 💤 ±0 
  3 files   ±0     0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 4)

2 265 tests  ±0   2 265 ✅ ±0   2m 30s ⏱️ -8s
    3 suites ±0       0 💤 ±0 
    3 files   ±0       0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Test Results (shard 2)

581 tests  ±0   389 ✅ ±0   2m 38s ⏱️ ±0s
  3 suites ±0   192 💤 ±0 
  3 files   ±0     0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

@github-actions

github-actions Bot commented Sep 4, 2026 •

Copy link
Copy Markdown
Contributor

Test Results

   15 files  ±0     15 suites  ±0   10m 46s ⏱️ -47s
5 386 tests ±0  5 192 ✅ ±0  194 💤 ±0  0 ❌ ±0 
5 387 runs  ±0  5 193 ✅ ±0  194 💤 ±0  0 ❌ ±0 

Results for commit 8d9e0d5. ± Comparison against base commit 1f26a30.

♻️ This comment has been updated with latest results.

@rbuergi
rbuergi marked this pull request as ready for review September 4, 2026 08:12
@meshweaver-cloud
meshweaver-cloud Bot enabled auto-merge September 4, 2026 08:12
@meshweaver-cloud
meshweaver-cloud Bot added this pull request to the merge queue Sep 4, 2026
Merged via the queue into main with commit bc9b516 Sep 4, 2026
43 of 45 checks passed
@rbuergi
rbuergi deleted the docs/rest-not-graphql branch October 10, 2026 13:10
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.

2 participants