pi-checkpoint-bridge
v0.1.0
Published
Pi extension: lets sub-agent sessions ask the human user questions through the main session's UI — the checkpoint channel for the openspec* workflow family (grill rounds, apply blockers, any user-interaction checkpoint).
Maintainers
Readme
checkpoint-bridge
A pi extension that lets sub-agent sessions ask the human user questions through the main session's UI — the checkpoint channel from ADR-0001.
How it works
pi-subagents spawns sub-agent sessions in the same process as the main
session, and every session activates this extension. The relay runs over a
process-global bus — a Symbol.for-keyed EventEmitter on globalThis —
because pi.events turned out to be session-scoped in practice (a request
emitted on a sub-agent session's bus never reached the main session's
listener; live-tested 2026-09-06, see ADR-0001's amendment).
- On
session_starteach instance tries to claim the host role via aglobalThissymbol. The main session always starts first, so first claim wins = main session hosts. - A sub-agent calls the
ask_user_via_hosttool with a batch of questions. - The agent instance emits
checkpoint-bridge:requeston the bus. - The host instance renders each question as a
ctx.ui.select(when options are given) orctx.ui.inputdialog — one dialog at a time (requests queue serially so concurrent askers never interleave). - Answers return as
checkpoint-bridge:responseand become the tool result.
Timeouts: per-question dialogs auto-dismiss after 180s (or the call's remaining budget); the whole call defaults to a 300s budget.
Fallback contract
ask_user_via_host never throws for environmental reasons. It returns a structured
result the caller can branch on:
| status | meaning | expected caller behavior |
|---|---|---|
| ok | user answered every question | proceed |
| timeout-or-cancelled | user dismissed a dialog (or it timed out) | proceed with answers so far, or fall back to needs_input |
| timeout | call budget expired | fall back to needs_input |
| cancelled | tool call aborted | stop gracefully |
| no-host | no main session armed (headless/print mode) | fall back to needs_input |
| error | host-side dialog failure | fall back to needs_input |
Workflows should treat every non-ok status as "produce a structured
needs_input return instead of guessing."
In RPC mode the host's ctx.ui dialogs translate to the Extension UI Protocol
(extension_ui_request / extension_ui_response), so the same design serves
IDE/UI embeddings without changes.
Scope discipline
Do not expose ask_user_via_host to every agent. In custom agent frontmatter, load the
extension narrowly:
extensions: [checkpoint-bridge]extensions: [checkpoint-bridge] arms the relay; add tools: "*, ext:checkpoint-bridge"
in agents that should be able to call ask_user_via_host.
Smoke test
node extensions/checkpoint-bridge/smoke.mjsRuns three in-process scenarios (hosted relay, local-host call, no-host fallback) against a mocked bus and UI — no pi process needed.
