Problem
PR #345 had to expand the same contract three times: after a tool creates a surface, every later
failure must return enough created identity for the caller to recover or close it. The contract is
currently implemented independently in each tool catch block, so a new or uncommon failure branch can
silently omit it.
The missed paths found during #345 included:
- managed launch/readiness failures in
spawn_agent
- post-creation boot-prompt failures in
new_worktree_split
- a later failure in
spawn_in_workspace, including identities from earlier successful batch members
- post-creation rename and
SurfaceGoneError failures in new_split and new_surface
The repeated omissions show that enumerating error types in every handler is not a durable guarantee.
Desired structural guarantee
Introduce one shared creation/failure wrapper (or equivalent typed primitive) through which
surface-creating operations pass. Once a surface or managed agent identity exists, the wrapper must
attach that identity to any subsequent thrown error before it reaches a tool response.
The design should preserve the public identity shape appropriate to each tool:
- managed spawn:
agent_id, surface_id, workspace_id
- raw surface creation:
surface, workspace, and stable surface_id when available
- batch spawn: all prior created identities plus the current failing identity
Acceptance criteria
- a single implementation point makes post-creation identity omission impossible for new failure types
- all current surface-creating entry points use it
- pre-creation failures do not invent identity
- existing structured error metadata remains intact and cannot overwrite the created identity
- focused tests inject an unclassified post-creation error and prove identity survives without adding a
new per-error branch
This is a follow-up to #345; do not fold it into that PR.
Problem
PR #345 had to expand the same contract three times: after a tool creates a surface, every later
failure must return enough created identity for the caller to recover or close it. The contract is
currently implemented independently in each tool catch block, so a new or uncommon failure branch can
silently omit it.
The missed paths found during #345 included:
spawn_agentnew_worktree_splitspawn_in_workspace, including identities from earlier successful batch membersSurfaceGoneErrorfailures innew_splitandnew_surfaceThe repeated omissions show that enumerating error types in every handler is not a durable guarantee.
Desired structural guarantee
Introduce one shared creation/failure wrapper (or equivalent typed primitive) through which
surface-creating operations pass. Once a surface or managed agent identity exists, the wrapper must
attach that identity to any subsequent thrown error before it reaches a tool response.
The design should preserve the public identity shape appropriate to each tool:
agent_id,surface_id,workspace_idsurface,workspace, and stablesurface_idwhen availableAcceptance criteria
new per-error branch
This is a follow-up to #345; do not fold it into that PR.