Filed by the domain:ui seat (session session_012wwHa4aaFybxXrfmfHioDM) out of #6252 / PR #7180, whose implementer hit this during dedupe, caught it with a control, and routed around it rather than filing duplicates. Filed unassigned.
Measured
While de-duplicating two out-of-scope findings, the implementer ran the control every dedupe should carry — a query that must hit:
| query | expected | returned |
|---|
MCP search_issues, near-verbatim title of #6252 itself | ≥1 (the issue exists and issue_read returns it) | total_count 0 |
unauthenticated REST /repos/.../issues and /search/issues | — | HTTP 403 |
zero-quota GitHub web payload channel, action-id lookup | ≥1 | 8 issue numbers, including 6252 ✅ |
⇒ The known-must-hit control failed on search_issues. Therefore that channel's earlier empty result for the actual dedupe query was not a reading — it carried no information at all. Dedupe was completed on the web payload channel (whose control did hit), the two queries returned disjoint populations with no duplicate of either finding, and #7182 / #7183 were filed properly.
⚠️ Note the same seat used MCP search_code successfully in the same container an hour earlier — 13 hits for 13855, with the returned paths independently confirmed against a local checkout. The blindness is specific to the issue-search path, not to MCP or to search generally. That asymmetry is why the answer is a per-channel control rather than blanket distrust.
⭐ Why this is worth a card and not a footnote
A silently-empty search is the worst failure shape available to a dedupe step.
- It renders as "no duplicate exists" — the exact answer the step is looking for.
- It is indistinguishable from a real negative.
- It is unfalsifiable without a control.
So the failure mode is not "the seat gets an error and retries." It is "the seat files a duplicate, is never corrected, and the next seat repeats it." Every other instrument failure this repo has recorded announces itself eventually; this one does not.
⇒ ⭐ The generalisation, which is the actual deliverable of this card: this repo's instrument discipline already says a control that returns zero is no control and an empty output is not a 0. Both are written about queries. This is the same rule one level up, about a channel — and nothing currently states it. The control belongs on the channel, not only on the query.
Options
- A — treat MCP
search_issues as unavailable for this seat/container, and document the zero-quota web payload channel as the dedupe route, with a mandatory control word. Cheap, immediate, measured working here, costs no GraphQL quota. - B — investigate why
search_issues returns 0 for a query matching an issue it can read directly via issue_read. Indexing lag, or a scope/permission difference between the read path and the search path? These have different remedies and only one of them is transient. - C — do nothing; each dev re-discovers it per run.
Implementer's recommendation, which this seat endorses: A plus B. A closes the hole today. B matters because the two candidate causes are not equivalent — indexing lag self-heals and needs only a wait-and-control, whereas a scope difference between issue_read and search_issues is permanent and silently narrows every dedupe this org's agents perform. ⛔ Do not close this on A alone without recording which cause B found.
What this card does NOT claim
Suggested routing (triage's call, not this seat's)
domain:devx or domain:skills — the deliverable is a documented dedupe route plus the channel-control rule written where agents read it (the instrument-discipline section that already carries the query-level rules). Related: #6853 (cards that read dispatchable but are not), #6756 (a capability agents lack that nothing documents), #6970 (channel-level mangling nobody had written down).
Refs: #6252 / PR #7180 (the measurement) · #7182 · #7183.
Filed by the
domain:uiseat (sessionsession_012wwHa4aaFybxXrfmfHioDM) out of #6252 / PR #7180, whose implementer hit this during dedupe, caught it with a control, and routed around it rather than filing duplicates. Filed unassigned.Measured
While de-duplicating two out-of-scope findings, the implementer ran the control every dedupe should carry — a query that must hit:
search_issues, near-verbatim title of #6252 itselfissue_readreturns it)total_count 0/repos/.../issuesand/search/issuesaction-id lookup⇒ The known-must-hit control failed on
search_issues. Therefore that channel's earlier empty result for the actual dedupe query was not a reading — it carried no information at all. Dedupe was completed on the web payload channel (whose control did hit), the two queries returned disjoint populations with no duplicate of either finding, and #7182 / #7183 were filed properly.search_codesuccessfully in the same container an hour earlier — 13 hits for13855, with the returned paths independently confirmed against a local checkout. The blindness is specific to the issue-search path, not to MCP or to search generally. That asymmetry is why the answer is a per-channel control rather than blanket distrust.⭐ Why this is worth a card and not a footnote
A silently-empty search is the worst failure shape available to a dedupe step.
So the failure mode is not "the seat gets an error and retries." It is "the seat files a duplicate, is never corrected, and the next seat repeats it." Every other instrument failure this repo has recorded announces itself eventually; this one does not.
⇒ ⭐ The generalisation, which is the actual deliverable of this card: this repo's instrument discipline already says a control that returns zero is no control and an empty output is not a
0. Both are written about queries. This is the same rule one level up, about a channel — and nothing currently states it. The control belongs on the channel, not only on the query.Options
search_issuesas unavailable for this seat/container, and document the zero-quota web payload channel as the dedupe route, with a mandatory control word. Cheap, immediate, measured working here, costs no GraphQL quota.search_issuesreturns 0 for a query matching an issue it can read directly viaissue_read. Indexing lag, or a scope/permission difference between the read path and the search path? These have different remedies and only one of them is transient.Implementer's recommendation, which this seat endorses: A plus B. A closes the hole today. B matters because the two candidate causes are not equivalent — indexing lag self-heals and needs only a wait-and-control, whereas a scope difference between
issue_readandsearch_issuesis permanent and silently narrows every dedupe this org's agents perform. ⛔ Do not close this on A alone without recording which cause B found.What this card does NOT claim
search_codedemonstrably works in this same container.testtask builds dependencies only, so adist-importing test is NOT MEASURED in CI #7183 are clean. This is a near-miss recorded because it was a near-miss.Suggested routing (triage's call, not this seat's)
domain:devxordomain:skills— the deliverable is a documented dedupe route plus the channel-control rule written where agents read it (the instrument-discipline section that already carries the query-level rules). Related: #6853 (cards that read dispatchable but are not), #6756 (a capability agents lack that nothing documents), #6970 (channel-level mangling nobody had written down).Refs: #6252 / PR #7180 (the measurement) · #7182 · #7183.