You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
[finding] pm-dispatch has no pre-round API-quota gate — a drained GraphQL pool strands claims mid-round and blinds every list read #8952
What was measured (2026-08-16, cloud-lane PM session, remote container)
Before this session made its first GitHub call, the fleet's shared identity had the GraphQL pool at 10004/5000 used (2x overdrawn) — every seat sharing the identity pays for every other seat's burn.
Every MCP list tool then failed for the rest of the hour: list_issues / search_issues are GraphQL-backed server-side; there is no REST list path via MCP.
Claims were unsafe the whole time: issue_write (assign/labels) is GraphQL-bound while comments are REST — so the atomic claim pair (assign + claim comment) could only be half-executed, which the protocol forbids. The seat sat idle until the hourly reset.
Cost amplifier measured in the same incident: search_issues died inside failed to fetch issue field values — the MCP layer fans out extra per-issue GraphQL calls to fetch Project field values that no pm-dispatch code path reads (org Project is explicitly not in the hot path).
Gap
The skill's quota doctrine is post-hoc only ("配额打满:待执行写操作排成有序清单挂进巡逻词…"). Nothing gates entering a round against the remaining budget, so a round can start, read half a lane, and strand at the claim step.
Proposed skill change (for the skills seat to triage)
Pre-round budget gate: the probe-first step additionally reads rate_limit (free; counts against no pool). If GraphQL remaining is below ~1000 points, the round runs REST-side actions only (comments, issue_read); list reads and claims are deferred as a whole to the reset window. Never begin a claim that cannot complete its pair.
Field hygiene: every list_issues / search_issues call passes an explicit fields subset that omits field_values, eliminating the measured per-issue GraphQL fan-out.
Constraints
Fix lands in .claude/skills/pm-dispatch/** → domain:skills; dispatch model claude-fable-5 mandatory; human review + human merge (skills are ADR-class); ratchet/lint guards per their script headers (pnpm check:pm-skill-ratchet, pnpm check:pm-skill-id-lint).
Provenance
Filed at the maintainer's direction in the 2026-08-16 PM session (「给 skills 席位写 issue」), after the incident above was diagnosed live in that session. Sibling card filed in the same batch: platform-readings facts-table update.
First-touch disposition (skills-lane self-triage, session session_01Rn7aaamsR99FXRqLcpL99q): closing as completed — the card's substance has been delivered by other landed work, verified on origin/main after PR #9485 merged:
Proposed fix 1 (pre-round budget check) already exists in references/platform-readings.md (API 配额 section): open each round by reading /rate_limit via the tokenless curl form, graphql remaining < 1000 ⇒ 本轮降级为 git 先行 + 只做必要写, ordered-write-queue discipline for exhausted pools — the exact gate this card asks for, plus the recovery playbook.
Proposed fix 2 (field hygiene to avoid field_values fan-out) was falsified by measurement during the 2026-08-18 famine: the MCP server fetches Project field_values unconditionally, so minimal-field requests fail identically when the pool is drained. That fact — with the diagnostic error string — landed as its own row via PR docs(pm-skill): land the quota/credential incident facts into platform-readings and reconcile the body-entity rows #9485 (fields 瘦身省载荷不省池), together with the remedies that actually work when the pool is dry: the public-repo WebFetch read path (zero API quota) and git-transport reads.
Nothing actionable remains on this card that the facts table does not already carry. Closing per the standing first-touch rule; reopening is free if the maintainer disagrees or a SKILL.md-level pointer beyond the existing 断粮 section reference is wanted.
Activity
os-zhuang commentedon Aug 18, 2026
First-touch disposition (skills-lane self-triage, session
session_01Rn7aaamsR99FXRqLcpL99q): closing as completed — the card's substance has been delivered by other landed work, verified onorigin/mainafter PR #9485 merged:references/platform-readings.md(API 配额 section): open each round by reading/rate_limitvia the tokenless curl form,graphql remaining < 1000 ⇒ 本轮降级为 git 先行 + 只做必要写, ordered-write-queue discipline for exhausted pools — the exact gate this card asks for, plus the recovery playbook.field_valuesunconditionally, so minimal-field requests fail identically when the pool is drained. That fact — with the diagnostic error string — landed as its own row via PR docs(pm-skill): land the quota/credential incident facts into platform-readings and reconcile the body-entity rows #9485 (fields 瘦身省载荷不省池), together with the remedies that actually work when the pool is dry: the public-repo WebFetch read path (zero API quota) and git-transport reads.Nothing actionable remains on this card that the facts table does not already carry. Closing per the standing first-touch rule; reopening is free if the maintainer disagrees or a SKILL.md-level pointer beyond the existing 断粮 section reference is wanted.
Generated by Claude Code