Context
Split out of #17278 at review time. #17278 bundled two things: a payload that reported an empty backlog when it meant "I could not look" (delivered by PR #17280), and the reason the census failed in the first place — this ticket. @neo-opus-grace flagged the bundling on PR #17280: a Resolves #17278 closes the ticket on merge regardless of a PR body saying it stays open, so the undelivered half needs its own leaf.
The Problem
GraphqlService.#getAuthToken() (ai/services/github-workflow/GraphqlService.mjs:127-149) resolves in three branches: an explicit override → GH_TOKEN / GITHUB_TOKEN → gh auth token via subprocess. Measured inside the running plane, every branch fails by construction:
| container |
GH_TOKEN |
GITHUB_TOKEN |
gh binary |
mc-server |
unset |
unset |
absent |
orchestrator |
unset |
unset |
— |
kb-server |
unset |
unset |
— |
fleet-server |
unset |
unset |
— |
A container has no gh binary and no keychain to hold a login, so the third branch is not a fallback there — it is dead code. The host is unaffected (gh auth token exits 0), which is exactly why this stayed invisible: every diagnosis run from a shell succeeds.
Observed symptom: explore_lane_landscape degrades on every call, its census reading zero items. That symptom's reporting is fixed by PR #17280; the cause is here.
The Fork — this ticket exists to decide it, not to presume it
Both readings are defensible and the choice belongs to whoever owns the plane's outbound stance:
- The plane SHOULD read GitHub. Then a credential is wired into the compose environment for the services that need it, scoped to those services, and the
gh auth token branch is documented as host-only so the next reader does not treat it as a container fallback.
- The plane should NOT read GitHub. Then a container-side census is the wrong architecture:
explore_lane_landscape either moves to a host-side reader or declares the capability unavailable on this plane rather than attempting a call that cannot succeed. Note this reading also means the current code is asking for a credential it is not supposed to have, which is its own smell.
Deliberately not decided by the filer. Wiring a PAT into four containers to quiet one tool would be widening a security boundary to silence a symptom, and the plane may be credential-free on purpose.
Acceptance Criteria
Out of Scope
- The payload-honesty half — delivered by PR #17280 on #17278. That fix is correct under either answer here, because a transient GitHub outage produces the same degraded path even with a credential wired.
- Broadening any container's outbound network posture beyond what the fork decides.
Avoided Traps
- Wiring a token because it makes the error stop. That is the symptom-silencing path, and it widens a boundary by default.
- Assuming the
gh auth token branch is a fallback everywhere. It is host-only by construction; treating it as universal is what let this survive.
Related
#17278 (the symptom's reporting — the payload half) · PR #17280 · ai/services/github-workflow/GraphqlService.mjs:127-149 · ai/deploy/docker-compose.local-agent-os.yml · ai/services/graph/laneLandscapeCensusSource.mjs
Live latest-open sweep: open queue checked 2026-08-17T08:0xZ; the only adjacent item is #17278, which this splits from by reviewer request.
Origin Session ID: 80b326bf-b37a-4efd-8313-1a9eae09e9c4
Context
Split out of #17278 at review time. #17278 bundled two things: a payload that reported an empty backlog when it meant "I could not look" (delivered by PR #17280), and the reason the census failed in the first place — this ticket. @neo-opus-grace flagged the bundling on PR #17280: a
Resolves #17278closes the ticket on merge regardless of a PR body saying it stays open, so the undelivered half needs its own leaf.The Problem
GraphqlService.#getAuthToken()(ai/services/github-workflow/GraphqlService.mjs:127-149) resolves in three branches: an explicit override →GH_TOKEN/GITHUB_TOKEN→gh auth tokenvia subprocess. Measured inside the running plane, every branch fails by construction:GH_TOKENGITHUB_TOKENghbinarymc-serverorchestratorkb-serverfleet-serverA container has no
ghbinary and no keychain to hold a login, so the third branch is not a fallback there — it is dead code. The host is unaffected (gh auth tokenexits 0), which is exactly why this stayed invisible: every diagnosis run from a shell succeeds.Observed symptom:
explore_lane_landscapedegrades on every call, its census reading zero items. That symptom's reporting is fixed by PR #17280; the cause is here.The Fork — this ticket exists to decide it, not to presume it
Both readings are defensible and the choice belongs to whoever owns the plane's outbound stance:
gh auth tokenbranch is documented as host-only so the next reader does not treat it as a container fallback.explore_lane_landscapeeither moves to a host-side reader or declares the capability unavailable on this plane rather than attempting a call that cannot succeed. Note this reading also means the current code is asking for a credential it is not supposed to have, which is its own smell.Deliberately not decided by the filer. Wiring a PAT into four containers to quiet one tool would be widening a security boundary to silence a symptom, and the plane may be credential-free on purpose.
Acceptance Criteria
GraphqlService's third branch names its host-only nature at the point a reader meets it.orchestratorsync tasks are the obvious candidate and were not measured beyond their env.Out of Scope
Avoided Traps
gh auth tokenbranch is a fallback everywhere. It is host-only by construction; treating it as universal is what let this survive.Related
#17278 (the symptom's reporting — the payload half) · PR #17280 ·
ai/services/github-workflow/GraphqlService.mjs:127-149·ai/deploy/docker-compose.local-agent-os.yml·ai/services/graph/laneLandscapeCensusSource.mjsLive latest-open sweep: open queue checked 2026-08-17T08:0xZ; the only adjacent item is #17278, which this splits from by reviewer request.
Origin Session ID: 80b326bf-b37a-4efd-8313-1a9eae09e9c4