Parent #16136 was created after a stale board claim said four pull requests remained merge-eligible when three had already merged. Its first code-ready leaf, #16165 / PR #16170, now gives every list_pull_requests row the current merge, review-request, head, and merge-state fields.
The remaining parent prescription is still too broad. Live source and Euclid's intake comment on #16136 prove that a timestamp cannot reconstruct historical aggregate reviewDecision or headRefOid, and a bounded open page cannot truthfully derive exhaustive unlisted membership. Neither updatedAt nor an empty delta may substitute for unavailable history.
This leaf keeps only the mechanism that directly falsifies the motivating claim: submit the exact PR numbers currently believed open and read their current membership in one source-owned operation.
Fresh duplicate sweep on 2026-07-30:
live latest-20 open issues and GitHub title/body search found #16136 only;
open-PR search found no competing branch;
repository issue/discussion archive and Knowledge Base search confirmed #16136 is the broad parent, while #16165 explicitly leaves this leaf out of scope;
current A2A last-30 claim sweep found no competing implementation claim;
npm run --silent ai:structure-map -- --files --loc confirms the existing owners remain ai/mcp/server/github-workflow and ai/services/github-workflow; no new .mjs file or subsystem is needed.
The Problem
The widened board can tell an agent what is open now, but it still cannot mechanically refute the list the agent is about to repeat. A caller who believes [16129, 16133, 16134, 16135] are open must compare that memory against current rows by hand. That manual subtraction is the step that failed in #16136's incident.
Coupling the belief check to state or limit would reproduce the defect: a believed PR outside the returned open page is neither proven terminal nor proven missing. Adding unlisted would overclaim board completeness unless the whole open connection were exhausted. Adding since / moved would overclaim historical coordinates GitHub does not expose at a timestamp.
The Architectural Reality
list_pull_requests is already the owning MCP operation; no new tool is warranted.
FETCH_PULL_REQUESTS and PullRequestService.listPullRequests() own the current snapshot.
GitHub's repository GraphQL object can resolve multiple validated pullRequest(number: N) fields under aliases in one request. The exact submitted numbers therefore need neither server state nor a per-PR network loop.
GraphqlService.query() already supports aliased partial-data semantics, but a missing/inaccessible pull request normally resolves to null; the projection must preserve that as explicit uncertainty rather than silently dropping the number.
The current default call shape delivered by #16170 must remain unchanged when no belief is supplied.
The Fix
Add optional believedOpen: number[] to list_pull_requests, bounded to 100 unique positive integers. Over-cap input is rejected before GitHub I/O; the service never truncates or silently partitions the coordinate.
When absent, execute the existing query and return the existing response byte-for-byte in behavior.
When present, build one GraphQL request containing:
the existing bounded board connection; and
one alias per validated believed number, returning number, state, and mergedAt.
caller can discover believedOpen without a new operation
no catalog growth
x-neo-tool-summary + description
tool-limit/catalog tests
Acceptance Criteria
list_pull_requests accepts optional believedOpen with at most 100 unique positive integers and rejects invalid input before GitHub I/O.
With believedOpen absent, the captured query, variables, and returned response remain unchanged from PR #16170.
With believedOpen present, one GraphQL call resolves the board and every submitted number; no per-PR network loop or server state is introduced.
Every submitted currently-open number appears exactly once in belief.stillOpen.
Every submitted terminal number appears exactly once in belief.falsified with current state and mergedAt (null when closed-unmerged).
A missing or inaccessible number appears exactly once in belief.unverifiable with reason not-found-or-inaccessible; it is never silently dropped or reported as falsified.
Every submitted number appears exactly once across stillOpen, falsified, and unverifiable.
belief classification is independent of the board state and limit; page absence is never used as terminal evidence.
The opt-in response includes an ISO checkedAt; the default response does not gain it.
x-neo-tool-summary names believedOpen within 120 characters and the full description remains within 1,024 characters.
The MCP operation count does not grow; OpenAPI/tool registration tests remain green.
No since, arrived, moved, departed, or unlisted claim enters this leaf.
Out of Scope
Timestamp-based history or reconstructing earlier head/review coordinates; current head staleness is already observable through the existing headRefOid field.
Exhaustive current-open pagination or unlisted membership.
Changing the board's state, limit, ordering, or default response.
Server-side/per-identity watermarks.
Rewriting the freshness skills; parent #16136 retains that final alignment after the instrument shape converges.
A new board/overview MCP operation.
Avoided Traps
Infer falsification from board absence: a bounded page cannot prove terminal state.
Treat inaccessible as falsified: lack of an observation cannot refute a caller belief.
Add unlisted: exhaustive complement requires exhausting the current-open connection.
Call each PR separately: recreates the N-call cost that made the freshness gate easy to skip.
Use updatedAt for moved: unrelated comments and metadata advance it.
Add server memory: makes identical calls non-idempotent and hides the caller coordinate.
Change the default shape: forces all consumers to pay for an opt-in falsifier.
Decision Record impact
None. This is an additive, stateless projection on the existing GitHub Workflow read operation, aligned with #16126's derive-from-caller-coordinate precedent and the no-new-tool constraint in #16136.
Context
Parent #16136 was created after a stale board claim said four pull requests remained merge-eligible when three had already merged. Its first code-ready leaf, #16165 / PR #16170, now gives every
list_pull_requestsrow the current merge, review-request, head, and merge-state fields.The remaining parent prescription is still too broad. Live source and Euclid's intake comment on #16136 prove that a timestamp cannot reconstruct historical aggregate
reviewDecisionorheadRefOid, and a bounded open page cannot truthfully derive exhaustiveunlistedmembership. NeitherupdatedAtnor an empty delta may substitute for unavailable history.This leaf keeps only the mechanism that directly falsifies the motivating claim: submit the exact PR numbers currently believed open and read their current membership in one source-owned operation.
Fresh duplicate sweep on 2026-07-30:
npm run --silent ai:structure-map -- --files --locconfirms the existing owners remainai/mcp/server/github-workflowandai/services/github-workflow; no new.mjsfile or subsystem is needed.The Problem
The widened board can tell an agent what is open now, but it still cannot mechanically refute the list the agent is about to repeat. A caller who believes
[16129, 16133, 16134, 16135]are open must compare that memory against current rows by hand. That manual subtraction is the step that failed in #16136's incident.Coupling the belief check to
stateorlimitwould reproduce the defect: a believed PR outside the returned open page is neither proven terminal nor proven missing. Addingunlistedwould overclaim board completeness unless the whole open connection were exhausted. Addingsince/movedwould overclaim historical coordinates GitHub does not expose at a timestamp.The Architectural Reality
list_pull_requestsis already the owning MCP operation; no new tool is warranted.FETCH_PULL_REQUESTSandPullRequestService.listPullRequests()own the current snapshot.pullRequest(number: N)fields under aliases in one request. The exact submitted numbers therefore need neither server state nor a per-PR network loop.GraphqlService.query()already supports aliased partial-data semantics, but a missing/inaccessible pull request normally resolves tonull; the projection must preserve that as explicit uncertainty rather than silently dropping the number.The Fix
Add optional
believedOpen: number[]tolist_pull_requests, bounded to 100 unique positive integers. Over-cap input is rejected before GitHub I/O; the service never truncates or silently partitions the coordinate.When absent, execute the existing query and return the existing response byte-for-byte in behavior.
When present, build one GraphQL request containing:
number,state, andmergedAt.Add an opt-in response projection:
{ checkedAt: '2026-07-30T…Z', belief: { stillOpen: [16133], falsified: [ {number: 16129, state: 'MERGED', mergedAt: '…'} ], unverifiable: [ {number: 999999, reason: 'not-found-or-inaccessible'} ] } }Keep this projection independent of
stateandlimit: submitted numbers are resolved directly, not inferred from board-page absence.Document the opt-in capability in
x-neo-tool-summaryand the operation description within the existing tool-description budgets.Contract Ledger
believedOpeninputstillOpenstateOPENfalsifiedstate/mergedAtunverifiablecheckedAtbelievedOpenis absentbelievedOpenwithout a new operationx-neo-tool-summary+ descriptionAcceptance Criteria
list_pull_requestsaccepts optionalbelievedOpenwith at most 100 unique positive integers and rejects invalid input before GitHub I/O.believedOpenabsent, the captured query, variables, and returned response remain unchanged from PR #16170.believedOpenpresent, one GraphQL call resolves the board and every submitted number; no per-PR network loop or server state is introduced.belief.stillOpen.belief.falsifiedwith current state andmergedAt(nullwhen closed-unmerged).belief.unverifiablewith reasonnot-found-or-inaccessible; it is never silently dropped or reported as falsified.stillOpen,falsified, andunverifiable.beliefclassification is independent of the boardstateandlimit; page absence is never used as terminal evidence.checkedAt; the default response does not gain it.x-neo-tool-summarynamesbelievedOpenwithin 120 characters and the full description remains within 1,024 characters.since,arrived,moved,departed, orunlistedclaim enters this leaf.Out of Scope
headRefOidfield.unlistedmembership.state,limit, ordering, or default response.Avoided Traps
unlisted: exhaustive complement requires exhausting the current-open connection.updatedAtformoved: unrelated comments and metadata advance it.Decision Record impact
None. This is an additive, stateless projection on the existing GitHub Workflow read operation, aligned with #16126's derive-from-caller-coordinate precedent and the no-new-tool constraint in #16136.
Related
Narrow leaf of #16136 · field-parity predecessor #16165 / PR #16170 · source-owned projection precedent #16029 / PR #16126.
Origin Session ID:
b1ebc46a-5a83-496c-aa8b-385af785e9cbRetrieval Hint:
list_pull_requests believedOpen batched aliases exact membership falsified no unlisted no sinceAuthored by Emmy (GPT-5.6 Sol Ultra, Codex)