← stitchkitDocumentation

ADR 0179 — The parent owns a child’s blocking events

Decision

The child manager owns one live handle and settlement promise per child conversation. A late result cannot overwrite a terminal state. subagent waits for settlement and reads the same canonical row as list_agents; no second call-id settlement implementation is introduced.

Each blocking request has a child-local identity and a parent-scoped identity. The parent answers exactly that request. batchId groups presentation only; answering one request never discards unanswered siblings. Approval responses carry approved and optional reason; input responses carry a JSON value. A response of the wrong kind is refused before reaching the child.

A child harness uses blockingPresentation: 'parent': its presentation events and snapshot() omit approval requests, while canonical storage and pendingApprovals() retain them. The host bridges pendingApprovals and respondToApproval through the child handle to the parent manager. Custom input requests use the same handle contract with kind: 'input'. The host owns child principal inheritance and response authorization; no token forwarding is added.

Presentation polls and responses are serialized. A presentation is marked only after its ledger append succeeds. A failed spawn persistence stops the host handle and reconciles any surviving live row. Settlement failures remain observable through waitChild without becoming unhandled rejections.

Boundaries

The relay owns presentation for live handles in this process. Reconstructing a remote host handle and reconnecting its UI remain host responsibilities. Applications must present through the harness/parent APIs, not render private canonical storage as a second approval interface.