# refactor\(server\): share attachment message intake · PR \#10580 · pingdotgg/t3code

[View on GitCafe](https://git.cafe/pingdotgg/t3code/pull/10580)

Repository: [pingdotgg/t3code](https://git.cafe/pingdotgg/t3code)

Visibility: public

State: merged

Source repository: pingdotgg/t3code

Source branch: agents/mcp-shared/attachment-intake

Target branch: agents/mcp-shared/project-inputs

Head commit: 4cfe3581d49e2e0e43ff30bae928ca53c3a4bcaa

[Discussion and reviews](https://git.cafe/pingdotgg/t3code/pull/10580)

[Commits](https://git.cafe/pingdotgg/t3code/pull/10580/commits?format=markdown)

[Files changed](https://git.cafe/pingdotgg/t3code/pull/10580/diffs?format=markdown)

## Description

---

Part 3/16 of the [shared-core and MCP stack](https://github.com/pingdotgg/t3code/stacks/10582). Based on [#10578](https://github.com/pingdotgg/t3code/pull/10578). Next: [#10554](https://github.com/pingdotgg/t3code/pull/10554).

RPC and MCP separately sequenced pending attachment claims and message execution. This extracts ThreadMessageIntake operations around the existing claim, dispatch/send and ThreadLaunch services, then makes RPC use them. The MCP consumers follow in their own layers.

A launch or dispatch error can follow a durable message commit. Intake releases copies proven unused by the returned durable message/events, including accepted replays, and by typed pre-acceptance failures. It retains copies when acceptance is uncertain; a typed claim failure still cleans its partial batch before dispatch. This removes the RPC blanket error cleanup that could delete accepted message files. It may retain unused copies on uncertain failures. There is no new receipt store, retry journal, lock, provider logic, or service identity. Startup queuing, provenance, analytics and wire mapping stay at the RPC boundary.

Validation: AttachmentClaims, ThreadLaunch and ThreadManagement suites: 38 tests passed; server typecheck passed. One shared real V2 test accepts a launch, loses its result, and proves persisted attachment bytes survive. It also proves launch/command/send replays leave exactly the three accepted files, and nonexistent-project/thread failures add no orphaned copies. Existing partial-claim cleanup coverage remains.

Layer size: 4 files, +379/-150. No MCP tools are introduced in this prerequisite.

Prepared with Codex in the OpenAI agent runtime.


<!-- Macroscope's pull request summary starts here -->
<!-- Macroscope will only edit the content between these invisible markers, and the markers themselves will not be visible in the GitHub rendered markdown. -->
<!-- If you delete either of the start / end markers from your PR's description, Macroscope will append its summary at the bottom of the description. -->
> [!NOTE]
> ### Share attachment intake logic across `dispatchCommand`, `sendToThread`, and `launchThread` handlers
> - Adds shared intake handlers in [ThreadMessageIntake.ts](https://github.com/pingdotgg/t3code/pull/10580/files#diff-6b8734d18c45cf9e59571d594c869a03ec7a936a94f96e47f908563684052055) that claim pending attachments before processing and release them based on outcome.
> - Introduces `dispatchWasNotAccepted` classifier to distinguish definite pre-acceptance failures (projection errors, provider adapter errors, rejected commands, ID conflicts) from uncertain failures.
> - `releaseUnusedClaims` removes only claimed paths absent from the accepted result, preserving referenced copies.
> - WebSocket handlers in [ws.ts](https://github.com/pingdotgg/t3code/pull/10580/files#diff-7f2100e8ffa23a58d9bf425c5b3ceafc39239911ae33bc569291a00ecb8e9125) delegate to the shared intake logic instead of doing attachment claiming inline; launch RPC now uses tag-specific error conversion for `AttachmentClaimError`, `ThreadLaunchError`, and `ServerRuntimeStartupError`.
> - Adds a filesystem-backed integration test in [ThreadLaunchService.test.ts](https://github.com/pingdotgg/t3code/pull/10580/files#diff-2a283eb9c521d5d800b3fb394b1935e8bc85d08f54632548ca222d9f4279c275) covering uncertain launch replay, pre-acceptance failure cleanup, idempotent retries, and attachment byte preservation.
> - Risk: failures previously classified as definite (any observed error released all claims) are now retained when the `dispatchWasNotAccepted` classifier marks them uncertain; reviewers should verify that unmatched thread-management errors in the classifier do not cause attachment leaks for scenarios previously cleaned up.
>
> <!-- Macroscope's review summary starts here -->
>
> <sup><a href="https://app.macroscope.com">Macroscope</a> summarized 4cfe358.</sup>
> <!-- Macroscope's review summary ends here -->
>
<!-- Macroscope's pull request summary ends here -->
