Context
The 2026-06-14 identity-drift incident showed a concrete split between local git identity and the identity used for public GitHub writes. In the affected Codex lane, git config user.name/user.email stayed neo-gpt <neo-gpt@neomjs.com>, while GitHub API / PR-opening identity drifted to neo-opus-ada. PR #13242 added Codex-only worktree discipline in .codex/CODEX.md, but it deliberately left tool-level fail-closed viewer.login enforcement out of scope.
Ada is taking the healthcheck assertion side of the detection seam. This ticket owns the complementary write-boundary guard: state-changing GitHub Workflow MCP tool calls should verify the effective GitHub viewer identity before they mutate public GitHub state.
Live latest-open sweep: checked latest open issues and targeted write-boundary identity guard searches on 2026-06-14T16:46Z; no equivalent open issue or PR found. #13234 is closed and covers GoldenPath/cross-family identity-source hardening, not the write-boundary fail-closed guard. #13239 documents the incident/runbook. #13242 documents Codex worktree discipline and explicitly defers this guard. KB semantic duplicate sweep attempted with ask_knowledge_base(type='ticket'), but the Knowledge Base was unavailable (Failed to access collections); creation is based on live GitHub + A2A freshness plus source inspection.
A2A in-flight sweep: checked recent inbox messages on 2026-06-14T16:46Z. The only overlapping current coordination signal is Ada's split request (MESSAGE:75dd3dd7-38e1-499b-afcb-30ec01f0662b), which assigns healthcheck assertion to Ada and asks whether this deferred write-boundary guard is mine.
Release classification: post-release hardening (Agent Harness / GitHub Workflow identity safety; not v13-blocking).
The Problem
The GitHub Workflow MCP server already has multiple state-changing tools: creating/updating comments, creating issues/discussions, assigning issues, managing labels/projects, posting formal PR reviews, requesting reviewers, updating discussion bodies, updating issue relationships, and sync_all. These operations currently trust the process's effective GitHub credentials once the server is healthy.
That is not enough for agent-authored public writes. The incident showed that an agent harness can believe it is @neo-gpt while the GitHub API caller is actually another maintainer account. If that drift reaches a write tool, public artifacts are mis-attributed and native GitHub review/self-review gates can break. A docs-only Codex rule lowers the chance of recurrence, but the mutating tool boundary should still fail loud when the caller identity diverges from the expected agent identity.
The Architectural Reality
ai/mcp/server/github-workflow/toolService.mjs is the tool dispatch boundary for the GitHub Workflow MCP server.
serviceMapping in that file maps read tools and write tools to service methods.
- Existing precedent:
sync_all is already wrapped at the tool boundary by buildDevBranchGuard(), because library-level policy was the wrong layer and OpenAPI description-as-policy was insufficient.
ai/services/github-workflow/RepositoryService.mjs caches viewer permission, but it does not expose or validate the effective viewer login.
learn/agentos/tooling/MemoryCoreMcpAuth.md documents NEO_AGENT_IDENTITY as the harness-bound identity signal, with gh api user as a local fallback.
.codex/CODEX.md now instructs Codex to run gh api user --jq .login before state-changing GitHub actions, but this remains discipline-only.
The Fix
Add a GitHub Workflow write-boundary identity guard at the MCP tool dispatch layer.
Expected shape:
- Define a small guard helper in or near
ai/mcp/server/github-workflow/toolService.mjs that wraps mutating tool handlers.
- For guarded tools, resolve the expected identity from the runtime-bound agent identity (
NEO_AGENT_IDENTITY / request context if available) to a GitHub login.
- Resolve the effective GitHub viewer login through a cheap, injectable probe (
gh api user --jq .login or GraphQL viewer.login), with unit tests using injected probes rather than live GitHub.
- If expected and effective identities disagree, reject before invoking the delegate and return/throw a clear
GITHUB_IDENTITY_MISMATCH failure naming both identities.
- Read-only tools remain unguarded.
healthcheck remains usable even when identity cannot be confirmed.
- The guard must be testable without network access and must not log secrets or token values.
Contract Ledger Matrix
| Target Surface |
Source of Authority |
Proposed Behavior |
Fallback |
Docs |
Evidence |
| GitHub Workflow mutating MCP tools |
#13242 deferred guard + 2026-06-14 identity incident |
Before public GitHub writes, verify effective GitHub viewer login matches the expected agent identity; reject on mismatch |
If expected identity cannot be resolved, fail closed for agent-bound writes with a clear diagnostic; read-only tools remain available |
Tool JSDoc / PR body; .codex/CODEX.md remains the Codex discipline layer |
Unit tests prove delegate is not called on mismatch and is called on match |
| Expected identity source |
NEO_AGENT_IDENTITY / request-bound identity substrate |
Map canonical @neo-gpt style identity to GitHub login neo-gpt |
If no agent identity is bound, return an explicit unresolved-identity error for guarded writes |
JSDoc + test names |
Unit tests for @neo-gpt normalization and unresolved identity |
| Effective GitHub identity source |
GitHub API viewer identity |
Probe viewer.login/gh api user --jq .login immediately before guarded writes or via short-lived cache with invalidation semantics |
If the probe fails, reject guarded writes rather than guessing |
JSDoc + failure message |
Unit tests for probe failure and no delegate call |
Decision Record impact
Aligned with the Agent Harness identity discipline and AGENTS.md Verify-Before-Assert / Friction-to-Gold core values. No ADR change expected unless implementation discovers a broader MCP identity contract change.
Acceptance Criteria
Out of Scope
- Rewriting historical PR authorship or review attribution.
- Replacing per-agent GitHub tokens or editing
.zshenv.
- Changing GoldenPath cross-family author-family logic already handled by #13234.
- Blocking direct
gh CLI calls outside the MCP server.
- Broadly redesigning MCP authentication across all servers.
Avoided Traps
- Trusting
git config — rejected; commit author and GitHub API caller are separate surfaces.
- Relying on docs-only discipline — rejected; #13242 is useful, but public writes need an executable guard.
- Guarding reads — rejected; read-only diagnostics must remain usable to recover from identity failures.
- Logging token material — rejected; diagnostics name identities, never secrets.
Related
- PR #13242 — Codex identity-safe worktree discipline; explicitly deferred this guard.
- Issue #13239 / PR #13240 — identity-drift incident record and runbook.
- Issue #13234 — GoldenPath/cross-family author-family hardening; closed, separate surface.
- A2A coordination:
MESSAGE:75dd3dd7-38e1-499b-afcb-30ec01f0662b.
Origin Session ID: 4ed21ddf-b92f-45ce-8689-bb3ebb563dd9
Retrieval Hint: "GitHub Workflow MCP write-boundary identity guard GH_TOKEN drift viewer.login NEO_AGENT_IDENTITY #13242 #13239"
Context
The 2026-06-14 identity-drift incident showed a concrete split between local git identity and the identity used for public GitHub writes. In the affected Codex lane,
git config user.name/user.emailstayedneo-gpt <neo-gpt@neomjs.com>, while GitHub API / PR-opening identity drifted toneo-opus-ada. PR #13242 added Codex-only worktree discipline in.codex/CODEX.md, but it deliberately left tool-level fail-closedviewer.loginenforcement out of scope.Ada is taking the healthcheck assertion side of the detection seam. This ticket owns the complementary write-boundary guard: state-changing GitHub Workflow MCP tool calls should verify the effective GitHub viewer identity before they mutate public GitHub state.
Live latest-open sweep: checked latest open issues and targeted
write-boundary identity guardsearches on 2026-06-14T16:46Z; no equivalent open issue or PR found. #13234 is closed and covers GoldenPath/cross-family identity-source hardening, not the write-boundary fail-closed guard. #13239 documents the incident/runbook. #13242 documents Codex worktree discipline and explicitly defers this guard. KB semantic duplicate sweep attempted withask_knowledge_base(type='ticket'), but the Knowledge Base was unavailable (Failed to access collections); creation is based on live GitHub + A2A freshness plus source inspection.A2A in-flight sweep: checked recent inbox messages on 2026-06-14T16:46Z. The only overlapping current coordination signal is Ada's split request (
MESSAGE:75dd3dd7-38e1-499b-afcb-30ec01f0662b), which assigns healthcheck assertion to Ada and asks whether this deferred write-boundary guard is mine.Release classification: post-release hardening (Agent Harness / GitHub Workflow identity safety; not v13-blocking).
The Problem
The GitHub Workflow MCP server already has multiple state-changing tools: creating/updating comments, creating issues/discussions, assigning issues, managing labels/projects, posting formal PR reviews, requesting reviewers, updating discussion bodies, updating issue relationships, and
sync_all. These operations currently trust the process's effective GitHub credentials once the server is healthy.That is not enough for agent-authored public writes. The incident showed that an agent harness can believe it is
@neo-gptwhile the GitHub API caller is actually another maintainer account. If that drift reaches a write tool, public artifacts are mis-attributed and native GitHub review/self-review gates can break. A docs-only Codex rule lowers the chance of recurrence, but the mutating tool boundary should still fail loud when the caller identity diverges from the expected agent identity.The Architectural Reality
ai/mcp/server/github-workflow/toolService.mjsis the tool dispatch boundary for the GitHub Workflow MCP server.serviceMappingin that file maps read tools and write tools to service methods.sync_allis already wrapped at the tool boundary bybuildDevBranchGuard(), because library-level policy was the wrong layer and OpenAPI description-as-policy was insufficient.ai/services/github-workflow/RepositoryService.mjscaches viewer permission, but it does not expose or validate the effective viewer login.learn/agentos/tooling/MemoryCoreMcpAuth.mddocumentsNEO_AGENT_IDENTITYas the harness-bound identity signal, withgh api useras a local fallback..codex/CODEX.mdnow instructs Codex to rungh api user --jq .loginbefore state-changing GitHub actions, but this remains discipline-only.The Fix
Add a GitHub Workflow write-boundary identity guard at the MCP tool dispatch layer.
Expected shape:
ai/mcp/server/github-workflow/toolService.mjsthat wraps mutating tool handlers.NEO_AGENT_IDENTITY/ request context if available) to a GitHub login.gh api user --jq .loginor GraphQLviewer.login), with unit tests using injected probes rather than live GitHub.GITHUB_IDENTITY_MISMATCHfailure naming both identities.healthcheckremains usable even when identity cannot be confirmed.Contract Ledger Matrix
.codex/CODEX.mdremains the Codex discipline layerNEO_AGENT_IDENTITY/ request-bound identity substrate@neo-gptstyle identity to GitHub loginneo-gpt@neo-gptnormalization and unresolved identityviewer.login/gh api user --jq .loginimmediately before guarded writes or via short-lived cache with invalidation semanticsDecision Record impact
Aligned with the Agent Harness identity discipline and AGENTS.md Verify-Before-Assert / Friction-to-Gold core values. No ADR change expected unless implementation discovers a broader MCP identity contract change.
Acceptance Criteria
GITHUB_IDENTITY_MISMATCHdiagnostic and does not call the delegate.healthcheckare not blocked by the guard.Out of Scope
.zshenv.ghCLI calls outside the MCP server.Avoided Traps
git config— rejected; commit author and GitHub API caller are separate surfaces.Related
MESSAGE:75dd3dd7-38e1-499b-afcb-30ec01f0662b.Origin Session ID: 4ed21ddf-b92f-45ce-8689-bb3ebb563dd9 Retrieval Hint: "GitHub Workflow MCP write-boundary identity guard GH_TOKEN drift viewer.login NEO_AGENT_IDENTITY #13242 #13239"