diff --git a/packages/bus/README.md b/packages/bus/README.md index 7293f98db..4694e08b5 100644 --- a/packages/bus/README.md +++ b/packages/bus/README.md @@ -140,11 +140,11 @@ an operator inspect content and delivery evidence after an uncertain result. | `role.release` | No args; only its current holder releases. | | `role.revoke` | `{role,decision}`; needs human-approved gated decision for this exact target and holder incarnation. | | `decision.raise` | `{action,question,options:[{key,text}],recommendation,blocking,domain?,target?,project?,task_ref?,requirement_ref?,supersedes?,choice?,approvalChoice?}`. Returns decision with decoded options and authorization context. A blocking decision holds a task: `blocking` true with no `task_ref` refuses `task-required`. A non-blocking one needs no task, and a gated action such as `prd.approve` or `role.revoke` still routes to the human's inbox. | -| `decision.resolve` | `{id,choice,note?}`; option must exist, resolver must be routed role or outside-agent human CLI. | +| `decision.resolve` | `{id,choice,note?}`; option must exist, resolver must be routed role or outside-agent human CLI. Sends the raising role a DECISION message (Decision close messages, below). | | `decision.seen` | `{id,note?}`; acknowledgement by resolver, not a resolution. | -| `decision.withdraw` | `{id,note?}`; raiser or human. Never rewrites the decision. | +| `decision.withdraw` | `{id,note?}`; raiser or human. Never rewrites the decision. A human withdraw sends the raising role a DECISION message; the raising run's own withdraw sends none. | | `message.send` | `{to,body,class?,in_reply_to?,corrects?,decision?}`; returns `{id,request}`. Human instruction's `request` is its `human.input` event ID. | -| `message.receive` | No args; up to 100 undelivered messages for current holder, including originating `request` for human instructions. | +| `message.receive` | No args; up to 100 undelivered messages for current holder, including originating `request` for human instructions. A human decision close's message carries the close's `human.input` answer event as its `request`; a role close's has `null`. | | `message.read` | `{id}`; recipient holder's acknowledgement; no new holder can acknowledge old holder's delivery. | | `review.request` | `{task_ref,commit,to,note?,decision?}`; action `review.request` (row 93, #1587). `commit` must be the task's latest pushed commit: an older one refuses `stale-commit`, any other `unknown-commit`. `to` must be another role holding `review.verdict` (`unknown-role`, `self-review`, `not-a-reviewer`). Writes a `review.requested` event `{task_ref,project,ref,commit,to,message,held}` and sends `to` a REVIEW-REQUEST message naming it. `held` is the run id holding the `to` role when the request is routed (row 105, #1599), or `null` when no run holds it: the message then waits for a claim, and the requester should tell whoever launches roles. Returns `{request,message,commit,ref,held}`. | | `review.verdict` | `{task_ref,request,verdict,body,decision?}`; action `review.verdict`. `verdict` is `approve` or `changes`. `request` must be a `review.requested` event on the task addressed to the caller's role (`request-not-found`), with no verdict yet (`verdict-exists`). Writes a `review.verdict` event `{task_ref,request,commit,verdict,message}` and sends the requesting role a REVIEW-RESULT in reply to the request's message. Returns `{verdict,message,commit}`. | @@ -250,6 +250,32 @@ an uncertain external outcome must not be retried with that approval. S3/S6 must implement their own external-operation identity and uncertain-outcome handling. Raising/superseding and resolving are transactional. +### Decision close messages (row 115, #1609) + +A `decision.resolve` or `decision.withdraw` by anyone but the raising run sends +the raising role one message, written in the same transaction as the close, so +a refused close sends nothing. It goes to `raised_by_role` with class +`DECISION`, `decision` set to the decision's id, and no `in_reply_to` or +`corrects`. A human close is sent `from_role 'human'`, `from_run 'human-cli'`; +a role close is sent from the closing role and run. It is routed like +`message.send`'s: to the role's current holder, or with no holder until the +next claim routes it. The body is + +``` +Decision on was resolved by : (