PRD: Non-blocking supervise (async approval + proposal polling) #413
Reference in New Issue
Block a user
Delete Branch "prd-nonblocking-supervise"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Closes #412.
PRD:
25155a1d5a/docs/prds/prd-new-nonblocking-supervise.mdSummary
Makes the per-bottle supervise MCP flow non-blocking, so an approval can happen out-of-band (a human review console, minutes-to-hours) without holding an HTTP request open or wedging the agent.
pendingtimeout response now carries theproposal_idand points the agent atcheck-proposal.check-proposalMCP tool: non-blocking status lookup by proposal id —pending|approved|modified|rejected|unknown— so the agent resumes after a late decision instead of re-proposing (a duplicate).SUPERVISE_RESPONSE_TIMEOUT_SECONDS, default 30s) is kept for the "operator is right there" fast path.Enforcement is unchanged — the MCP tools only propose policy; the egress proxy and git-gate still enforce — so returning early opens no hole.
Behavior / design
check-proposalis attributed to the calling bottle by source IP exactly like the proposal tools, reads the queue only (never creates a Proposal, so it stays out ofTOOLS), and archives a decided proposal exactly like the synchronous path. A proposal that times out topendingstays visible to the operator until it is both decided and polled.Tests
TestNonBlockingSupervise: pending-carries-id, grace-window timeout stays queued,check-proposalapproved/rejected/pending/unknown, arg validation, and a full pending -> decide -> poll round trip. Full unit suite green, pyright clean on the touched filesFollow-ups (in the PRD, not this PR)
pre-receivereject-fast + re-push (synchronous, cannot poll)25155a1d5ato5ca3209b415ca3209b41toae9a395162ae9a395162to143281705d143281705dto034f774529No actionable findings. The pending response now carries the proposal ID,
check-proposalpreserves bottle attribution and avoids creating duplicate proposals, and terminal decisions follow the existing archive/error semantics. I also ranpython3 -m unittest tests.unit.test_supervise_server: 63 tests passed.