The separate issue #854 promised but did not file.
The TUI's supervisor-scoped cancel writes cancel.request.json into the run dir (src/tui/top-app.ts:421). Nothing in the published runtime reads that file — grep confirms the TUI is its only mention in src/. The only live reader anywhere is the unpublished loops Pi host, which polls it every 1s and aborts its in-process root handle (loops/extensions/pi/loops.ts:453-459). A run hosted any other way — supervise() called directly, a service, CI — gets NOTHING from that file.
The TUI notice discloses this ('host-honored; not runtime-acknowledged'), so the operator is not lied to, but the capability gap from #758 remains for the root scope: a non-retained tree has no root handle an external client can reach, and no acknowledged effect to read back.
The worker-scoped contract (#854) shows the shape: a durable request inbox plus an acknowledgement record written by a loop the runtime already runs. The root case needs a party that owns the ROOT abort — the host process — so the contract likely belongs at the supervise() entry: an opt-in that mounts a root-cancel acknowledger reading the same layout, reusing RetainedRunEffect.
The separate issue #854 promised but did not file.
The TUI's supervisor-scoped cancel writes
cancel.request.jsoninto the run dir (src/tui/top-app.ts:421). Nothing in the published runtime reads that file — grep confirms the TUI is its only mention insrc/. The only live reader anywhere is the unpublished loops Pi host, which polls it every 1s and aborts its in-process root handle (loops/extensions/pi/loops.ts:453-459). A run hosted any other way —supervise()called directly, a service, CI — gets NOTHING from that file.The TUI notice discloses this ('host-honored; not runtime-acknowledged'), so the operator is not lied to, but the capability gap from #758 remains for the root scope: a non-retained tree has no root handle an external client can reach, and no acknowledged effect to read back.
The worker-scoped contract (#854) shows the shape: a durable request inbox plus an acknowledgement record written by a loop the runtime already runs. The root case needs a party that owns the ROOT abort — the host process — so the contract likely belongs at the
supervise()entry: an opt-in that mounts a root-cancel acknowledger reading the same layout, reusingRetainedRunEffect.