Repository navigation
feat(pull): platform-injected execution id; refuse unguarded effects on pull agents (#2392) - #3086
Merged
Merged
Conversation
…on pull agents (#2392) The effect guard de-duplicates outbound messages, calls, shares and A2A calls on the execution id, which reached it only as an optional value the agent typed. Pull re-delivers the same execution after a lease expiry, so a missing id meant a duplicate reaching a real recipient. - Agent MCP config sends X-Trinity-Execution-Id per process: ${TRINITY_EXECUTION_ID:-manual} for Claude Code and Gemini, env_http_headers for Codex. Validator accepts that one extra shape. - MCP server reads the header on every POST; it wins over the tool arg, which stays as the older-image fallback. - effect_guard: on a pull-mode agent an effect with no usable id (absent, unknown, another agent's) is refused with a 422 effect_unguarded and a budgeted operator alarm. `manual` (a person's terminal session) and a lookup error proceed. Other agents proceed and log effect_guard.degraded. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
#2392) A model typing execution_id="manual" as a tool argument (Codex, which sends no header when unset, or an older image) would skip the pull-mode refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
…L_MIGRATION_TESTING.md (#2392) — mechanical, per the merge-train note on the PR Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
|
merge-train: on this train. One mechanical fix pushed to your branch ( Non-blocking notes from validation: the 422 refusal paths in |
This was referenced Sep 29, 2026
Closed
2 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
X-Trinity-Execution-Idwith each spawned process's ownTRINITY_EXECUTION_ID(manualwhen unset: a person's terminal session). The MCP server reads it per request and it wins over the agent-typed tool arg, which stays as the fallback for older images.{"reason": "effect_unguarded"}plus aneffect_unguardedoperator alarm throughcreate_bounded_alert.manualand a DB lookup error proceed.effect_guard.degradedwarning whenever a send skips de-duplication.Policy per
TARGET_ARCHITECTURE.md§Re-Delivery and Side-Effect Recovery. Themanualexception for terminal sessions was agreed during plan review.Changes
trinity_mcp.pywrites the header for Claude Code and Gemini (${TRINITY_EXECUTION_ID:-manual}) and for Codex (env_http_headers).mcp_validator.pyaccepts exactly one extra header with that exact literal; both vendored copies are byte-identical.authenticateparses the header;tools/execution_id.tsresolves header-then-param forsend_message,call_user,send_voice_reply,share_fileandcall_a2a_agent.idempotency_service.effect_guardrefuses on pull-mode agents (effect_dedup_required, the one predicate Phase 5 flips). The messages, voip, agent_files, a2a and internal share routers map the refusal to 422. Alert type registered, id prefix reserved.execution.md,operating-room.md, and T6.3 plus the remaining-work lists in the pull migration docs.Verification
manual. An earlier batch of 3 runs sentmanualwith the variable set and did not reproduce. If it recurs, the effect proceeds unguarded and logged, which is today's behaviour.False, 5 refusal tests go red.tscclean.Test Plan
cd tests && pytest unit/test_2392_effect_guard_fail_closed.py unit/test_2392_execution_id_header.py unit/test_idempotency.py unit/test_736_a2a_outbound_call.py -vcd src/mcp-server && npm test && npx tsc --noEmiteffect:*rows carry the turn id on the eu2 emitting arm (oracle-7-ai-semi)Known limits
execution_id: "manual"skips the refusal. The guard stops omission, not a hostile agent. Through the MCP tools,manualcounts only when it comes from the header./cso --diff: 0 findings (docs/security-reports/cso-diff-2026-09-29-2392-execution-id-injection.md).Fixes #2392
🤖 Generated with Claude Code