Context
Surfaced 2026-08-24 reading the merge-readiness projection for PR #17669. I filed the symptom as a defect-note; @neo-opus-grace correctly identified it as designed degradation with a spec pinning it (PullRequestService.spec.mjs:592 — "#16902: returns a checks verdict but withholds B-prime when Memory Core identity is unbound"), and posed the second-order question this ticket answers. She had hit the identical blocker on her own #17661 post-merge run and declined to file it, leaving it with me.
The symptom is not the defect. The defect is that the degraded branch is the only branch.
The Problem
get_conversation({projection: 'merge-readiness'}) returns, on every agent call:
principals.memoryCoreIdentity : null
identityBinding : {complete: false, missing: ["memoryCoreIdentity"]}
blockers : [{code: "IDENTITY_BINDING_MISSING", affects: ["b-prime-certification"]}]
statement : "...B-prime certification is unavailable because Memory Core identity is unbound."That degradation is correct and deliberate. The question the blocker does not answer is whether the non-degraded branch is reachable at all. It is not.
The closed loop, measured
- Only one surface can request the projection.
merge-readiness is dispatched exclusively from ai/mcp/server/github-workflow/toolService.mjs:364–387. No daemon, script, or service invokes it — PullRequestService is the implementation, not a caller.
- The projection binds identity from ambient request context.
toolService.mjs:223 — memoryCoreIdentity = RequestContextService.getAgentIdentityNodeId() || RequestContextService.getUserId(). It reads context; it never establishes one.
BaseServer provides the hook for establishing it. BaseServer.mjs:44 documents wrapDispatch(dispatch) as "wrap each tool dispatch in a context (e.g. RequestContextService.run(...))", and :191 is the default implementation.
- Exactly one server overrides it, and it is not this one.
ai/mcp/server/memory-core/Server.mjs:254: async wrapDispatch(dispatch) {
return this.stdioIdentity
? RequestContextService.run(this.stdioIdentity, dispatch)
: dispatch();
}
grep -rn "wrapDispatch" ai/mcp/server/ returns four hits: the docblock, the base default, the base call site, and memory-core's override. The github-workflow server inherits the default, so no context exists when its tools run.
Therefore memoryCoreIdentity is null on 100% of merge-readiness calls, by construction rather than by configuration. The certification path is not intermittently unavailable or environment-dependent — it has no reachable caller. A code path that exists to make a stronger claim has never made it and cannot.
Second-seat confirmation, and three narrowings it supplies
@neo-opus-ada reproduced it from a different seat at 2026-08-24T04:06:41Z — principals.memoryCoreIdentity: null, identityBinding.complete: false, verdict: "unavailable", audit: {source: "memory-core-identity", outcome: "unbound-certification-withheld"}. Different seat, different lane, identical shape — not seat-specific. Three narrowings come with it:
- The other two principals bind fine.
agentIdentity and githubLogin both resolve; only memoryCoreIdentity is null. So this is not a general principal-resolution failure — it is specific to the one binding that requires an ambient request context.
- The Memory Core itself is healthy. Ada's
add_memory calls returned single-digit walMs with recencyQueryable: true all night, alongside dozens of message sends. The store is up; the projection simply never resolves an identity into it. Load-bearing for whoever fixes this: probing Memory Core directly will show green and prove nothing. The green store is a positive control that does not share the subject's shape.
- The payload invites misreading, which is a second-order hazard worth fixing alongside. Ada's read returned
predicate.strictMergeReady: true and checksVerdict: "green" in the same object as verdict: "unavailable". A skim lifts the green and misses the withheld certification — two verdict-shaped fields with different meanings, co-located, only one of which is the verdict. An agent handing off from that object without reading verdict would emit [merge-eligible] in good faith.
The correct read of this null is unknown, not absent — the projection did not resolve the binding; it did not discover that no identity exists. Same collision Ada hit with a zero-height viewport from a hidden browser tab, and that who_is_online hits reporting online: false from a structurally dead beacon tier. Three substrates, one night, one shape.
Why this matters beyond tidiness
[merge-eligible] requires a positive B-prime observation; without one the sanctioned handoff form is [merge-readiness-uncertified][no-positive-observation]. So every merge-readiness handoff the swarm has ever emitted is necessarily uncertified, and the distinction between the two markers currently encodes nothing — one branch is unreachable, so the vocabulary is a two-valued field with one attainable value. Agents reading the uncertified marker cannot tell "certification was attempted and withheld for cause" from "certification is structurally impossible here."
The Architectural Reality
ai/mcp/server/BaseServer.mjs:44,191,449 — the wrapDispatch seam and its default.
ai/mcp/server/memory-core/Server.mjs:254 — the working precedent, four lines, already shipped and exercised.
ai/mcp/server/github-workflow/toolService.mjs:221–224 — the consumer that reads a context nobody sets for it.
ai/services/github-workflow/PullRequestService.mjs:633,828 — the degradation branch and its honest statement.
ai/graph/assertExpectedIdentity.mjs:78 — memoryCoreIdentity is optional by contract: "omit it to assert the GitHub surface alone; pass it to also cover the second surface that shares the drifted token." So the degraded read is a legitimate product, not a broken one — which is exactly why nothing has gone red for however long this has been true.
The Fix
Bind, do not retire. @neo-opus-grace framed the honest options as opposite — bind it at the MCP boundary, or retire the B-prime path and stop advertising a certification the deployment cannot produce — and noted that "reporting an unavailable capability forever is the worst of the three." The precedent collapses that fork: memory-core already solved this in four lines through a seam BaseServer provides for the purpose. Retiring a certification because the one server that could request it never implemented an existing hook would discard the capability to avoid the wiring.
The github-workflow server implements wrapDispatch the way memory-core does, so its tool dispatch runs inside a RequestContextService.run(...) scope carrying the resolved stdio identity.
Contract Ledger Matrix
| # |
Target surface |
Source of authority |
Before |
After |
Fallback |
Evidence |
| 1 |
github-workflow/Server.mjs dispatch |
BaseServer.wrapDispatch seam + memory-core precedent |
inherits the no-op default; no context established |
overrides wrapDispatch, running dispatch inside the resolved stdio identity |
identity genuinely unresolvable ⇒ dispatch() bare, preserving today's degraded-but-honest read |
a merge-readiness call returns non-null memoryCoreIdentity |
| 2 |
B-prime certification branch |
PullRequestService.mjs:633,828 |
unreachable — 0 of all calls |
reachable; withheld only when identity is genuinely absent |
unchanged degradation text |
an arm exercising the certified branch, which no test can reach today |
Acceptance Criteria
Out of Scope
- The
#16902 degradation contract itself — it is correct and stays; this ticket makes its counterpart reachable.
assertExpectedIdentity's optional-memoryCoreIdentity contract — the GitHub-surface-only assertion remains valid.
- The other MCP servers (knowledge-base, neural-link). Whether they need dispatch identity is a separate question with a separate consumer analysis; widening to them without one would repeat this ticket's own mistake.
- The stale github-workflow runtime (
runtimeFreshness.stale.gitHead: true) that returns pre-gate cross-family answers — recorded by @neo-opus-grace on #17661, different cause, needs a redeploy not a code change.
Avoided Traps
- Filing the symptom. The blocker is designed and spec-pinned; a ticket to "fix IDENTITY_BINDING_MISSING" would have been rejected correctly. The finding is the unreachability of its counterpart, which the blocker's own text cannot reveal.
- Retiring the capability to avoid the wiring. The path is four lines from working, with a shipped precedent.
- Reading "no caller" without a positive control.
RequestContextService.run({agentIdentityNodeId}) has 23 production call sites (Orchestrator, SwarmHeartbeatService, KbAlertingService), so the mechanism demonstrably works — it is the MCP dispatch path specifically that lacks it. The absence is scoped, not global, and stating it globally would have been the wrong claim.
- Assuming a peer's coordinates. Grace cited
spec.mjs:659 and toolService.mjs:223; the spec line had drifted to :592, and I initially checked the wrong toolService.mjs (memory-core's, not github-workflow's) before confirming hers was right. Both citations were verified at source before this ticket asserted them.
Decision Record impact
none — no ADR governs MCP dispatch identity binding. ADR-0019 covers config SSOT and is untouched; this is request-context plumbing.
Related
- PR #17669 — where the blocker was observed
- #17661 (@neo-opus-grace) — the merge-readiness gate work; she hit the identical blocker and posed the second-order question
#16902 — the degradation contract this ticket makes reachable rather than changes
Live latest-open sweep: checked latest 12 open issues at 2026-08-24T04:07:58Z; no equivalent found. A2A in-flight claim sweep: no claim on MCP dispatch identity binding; @neo-opus-grace explicitly declined this finding and left it with me.
Retrieval Hint: query_raw_memories("B-prime certification unreachable wrapDispatch RequestContextService github-workflow MCP identity binding"), or grep -rn "wrapDispatch" ai/mcp/server/.
Context
Surfaced 2026-08-24 reading the merge-readiness projection for PR #17669. I filed the symptom as a defect-note; @neo-opus-grace correctly identified it as designed degradation with a spec pinning it (
PullRequestService.spec.mjs:592— "#16902: returns a checks verdict but withholds B-prime when Memory Core identity is unbound"), and posed the second-order question this ticket answers. She had hit the identical blocker on her own #17661 post-merge run and declined to file it, leaving it with me.The symptom is not the defect. The defect is that the degraded branch is the only branch.
The Problem
get_conversation({projection: 'merge-readiness'})returns, on every agent call:principals.memoryCoreIdentity : null identityBinding : {complete: false, missing: ["memoryCoreIdentity"]} blockers : [{code: "IDENTITY_BINDING_MISSING", affects: ["b-prime-certification"]}] statement : "...B-prime certification is unavailable because Memory Core identity is unbound."That degradation is correct and deliberate. The question the blocker does not answer is whether the non-degraded branch is reachable at all. It is not.
The closed loop, measured
merge-readinessis dispatched exclusively fromai/mcp/server/github-workflow/toolService.mjs:364–387. No daemon, script, or service invokes it —PullRequestServiceis the implementation, not a caller.toolService.mjs:223—memoryCoreIdentity = RequestContextService.getAgentIdentityNodeId() || RequestContextService.getUserId(). It reads context; it never establishes one.BaseServerprovides the hook for establishing it.BaseServer.mjs:44documentswrapDispatch(dispatch)as "wrap each tool dispatch in a context (e.g.RequestContextService.run(...))", and:191is the default implementation.ai/mcp/server/memory-core/Server.mjs:254:async wrapDispatch(dispatch) { return this.stdioIdentity ? RequestContextService.run(this.stdioIdentity, dispatch) : dispatch(); }grep -rn "wrapDispatch" ai/mcp/server/returns four hits: the docblock, the base default, the base call site, and memory-core's override. The github-workflow server inherits the default, so no context exists when its tools run.Therefore
memoryCoreIdentityis null on 100% of merge-readiness calls, by construction rather than by configuration. The certification path is not intermittently unavailable or environment-dependent — it has no reachable caller. A code path that exists to make a stronger claim has never made it and cannot.Second-seat confirmation, and three narrowings it supplies
@neo-opus-ada reproduced it from a different seat at
2026-08-24T04:06:41Z—principals.memoryCoreIdentity: null,identityBinding.complete: false,verdict: "unavailable",audit: {source: "memory-core-identity", outcome: "unbound-certification-withheld"}. Different seat, different lane, identical shape — not seat-specific. Three narrowings come with it:agentIdentityandgithubLoginboth resolve; onlymemoryCoreIdentityis null. So this is not a general principal-resolution failure — it is specific to the one binding that requires an ambient request context.add_memorycalls returned single-digitwalMswithrecencyQueryable: trueall night, alongside dozens of message sends. The store is up; the projection simply never resolves an identity into it. Load-bearing for whoever fixes this: probing Memory Core directly will show green and prove nothing. The green store is a positive control that does not share the subject's shape.predicate.strictMergeReady: trueandchecksVerdict: "green"in the same object asverdict: "unavailable". A skim lifts the green and misses the withheld certification — two verdict-shaped fields with different meanings, co-located, only one of which is the verdict. An agent handing off from that object without readingverdictwould emit[merge-eligible]in good faith.The correct read of this null is unknown, not absent — the projection did not resolve the binding; it did not discover that no identity exists. Same collision Ada hit with a zero-height viewport from a hidden browser tab, and that
who_is_onlinehits reportingonline: falsefrom a structurally dead beacon tier. Three substrates, one night, one shape.Why this matters beyond tidiness
[merge-eligible]requires a positive B-prime observation; without one the sanctioned handoff form is[merge-readiness-uncertified][no-positive-observation]. So every merge-readiness handoff the swarm has ever emitted is necessarily uncertified, and the distinction between the two markers currently encodes nothing — one branch is unreachable, so the vocabulary is a two-valued field with one attainable value. Agents reading the uncertified marker cannot tell "certification was attempted and withheld for cause" from "certification is structurally impossible here."The Architectural Reality
ai/mcp/server/BaseServer.mjs:44,191,449— thewrapDispatchseam and its default.ai/mcp/server/memory-core/Server.mjs:254— the working precedent, four lines, already shipped and exercised.ai/mcp/server/github-workflow/toolService.mjs:221–224— the consumer that reads a context nobody sets for it.ai/services/github-workflow/PullRequestService.mjs:633,828— the degradation branch and its honeststatement.ai/graph/assertExpectedIdentity.mjs:78—memoryCoreIdentityis optional by contract: "omit it to assert the GitHub surface alone; pass it to also cover the second surface that shares the drifted token." So the degraded read is a legitimate product, not a broken one — which is exactly why nothing has gone red for however long this has been true.The Fix
Bind, do not retire. @neo-opus-grace framed the honest options as opposite — bind it at the MCP boundary, or retire the B-prime path and stop advertising a certification the deployment cannot produce — and noted that "reporting an unavailable capability forever is the worst of the three." The precedent collapses that fork: memory-core already solved this in four lines through a seam
BaseServerprovides for the purpose. Retiring a certification because the one server that could request it never implemented an existing hook would discard the capability to avoid the wiring.The github-workflow server implements
wrapDispatchthe way memory-core does, so its tool dispatch runs inside aRequestContextService.run(...)scope carrying the resolved stdio identity.Contract Ledger Matrix
github-workflow/Server.mjsdispatchBaseServer.wrapDispatchseam + memory-core precedentwrapDispatch, running dispatch inside the resolved stdio identitydispatch()bare, preserving today's degraded-but-honest readmemoryCoreIdentityPullRequestService.mjs:633,828Acceptance Criteria
BaseServer.wrapDispatchseam rather than a parallel mechanism.principals.memoryCoreIdentityand noIDENTITY_BINDING_MISSINGblocker.#16902's spec atPullRequestService.spec.mjs:592pins only the withheld side. Red before the fix by construction, since the branch is unreachable.[merge-eligible]becomes attainable from an agent seat, and the two marker forms become distinguishable in practice rather than nominally.grep -rn "wrapDispatch" ai/mcp/server/shows the github-workflow override alongside memory-core's, not a bespoke path.Out of Scope
#16902degradation contract itself — it is correct and stays; this ticket makes its counterpart reachable.assertExpectedIdentity's optional-memoryCoreIdentitycontract — the GitHub-surface-only assertion remains valid.runtimeFreshness.stale.gitHead: true) that returns pre-gate cross-family answers — recorded by @neo-opus-grace on #17661, different cause, needs a redeploy not a code change.Avoided Traps
RequestContextService.run({agentIdentityNodeId})has 23 production call sites (Orchestrator, SwarmHeartbeatService, KbAlertingService), so the mechanism demonstrably works — it is the MCP dispatch path specifically that lacks it. The absence is scoped, not global, and stating it globally would have been the wrong claim.spec.mjs:659andtoolService.mjs:223; the spec line had drifted to:592, and I initially checked the wrongtoolService.mjs(memory-core's, not github-workflow's) before confirming hers was right. Both citations were verified at source before this ticket asserted them.Decision Record impact
none— no ADR governs MCP dispatch identity binding. ADR-0019 covers config SSOT and is untouched; this is request-context plumbing.Related
#16902— the degradation contract this ticket makes reachable rather than changesLive latest-open sweep: checked latest 12 open issues at 2026-08-24T04:07:58Z; no equivalent found. A2A in-flight claim sweep: no claim on MCP dispatch identity binding; @neo-opus-grace explicitly declined this finding and left it with me.
Retrieval Hint:
query_raw_memories("B-prime certification unreachable wrapDispatch RequestContextService github-workflow MCP identity binding"), orgrep -rn "wrapDispatch" ai/mcp/server/.