review
On this page
A proposal is a change waiting for a decision. review decides proposals: accept applies the change exactly as previewed, reject closes it, defer keeps it waiting.
Anyone whose role may review decides a proposal: a person, or an agent working for one, the proposal's author included. An agent acts with its person's role unless it has a membership of its own. Other roles are refused (not_authorized: your role (editor) cannot review). A context proposal is decided by its maintainer or an administrator; an agent with no membership of its own whose person maintains it decides it too (below). Background agents, such as an overnight crawler, only propose: they are set up with the editor role, so they never decide.
If your role may review, status lists what you may decide under "Needs your review". Fetch a proposal to see whether you may decide it.
Find and read proposals
wirk query proposal=proposed,deferred
wirk query c4a1e902
Fetching a proposal shows exactly what it would change. This is what an editor sees:
c4a1e902 · proposal · proposed · r1 · by nightly-agents (agent) · changed 1h ago · read-only
Mark webhook retries completed
Reason
The retry fix merged in 4f2a9c1 and the retry tests pass.
Diff
~ 5c1e7a90 r3 Retry failed webhooks
status in_progress → completed
Can accept: no, your role (editor) cannot review
more: query c4a1e902 depth=all
A proposal's title is the first line of its reason, and the rest of the reason shows under Reason; a one-line reason has no Reason block. Lists and status show only that title, so fetch a proposal to see what it would change.
Anyone who may decide it sees Can accept: yes and a line decide with: review c4a1e902@1 ACTION --reason REASON instead.
r1 is the proposal's revision. Every decision, including defer, makes a new one.
Decide
wirk review c4a1e902@1 accept --reason 'Tests pass on main'
wirk review c4a1e902@1 e7b35d16@2 defer --reason 'Wait for the load test'
The command requires a real reason and refuses the placeholders ACTION and REASON, so a pasted decide with: line decides nothing until it is filled in.
In MCP, wirk_review takes the same decisions (Request, below).
Request
Sent with your token:
POST /v2/review
Authorization: Bearer <your token>
{"request_id": "r-5d0e3a9c71",
"decisions": [
{"id": "c4a1e902",
"revision": 1,
"action": "accept",
"reason": "Tests pass on main"}]}
| Key | Notes |
|---|---|
decisions | Required. 1–32; each is decided on its own |
id | A full (proposal_…) or short proposal ID |
revision | The rN you read |
action | accept, reject or defer |
reason | Up to 2,048 characters. The CLI requires one |
request_id | 1–200 characters. Required on the wire; the CLI makes one when you leave it out |
workspace_id, format | As everywhere |
Response
Reviewed r-5d0e3a9c71 · 1 decision: 1 decided
accepted c4a1e902 r1 → r2 · Tests pass on main
{"ok": true,
"data": {"request_id": "r-5d0e3a9c71",
"results": [{"id": "proposal_c4a1e902…", "action": "accept", "outcome": "accepted", "r": 2,
"reason": "Tests pass on main"}]},
"errors": [], "notices": [], "page": {"complete": true, "next_cursor": null}, "timing_ms": {"total": 7.9}}
Each decision stands on its own. When some are decided and others are not, the answer is HTTP 207 and says which and why:
Reviewed r-9a4c2e6b18 · 3 decisions: 1 decided · 1 conflicted · 1 skipped
accepted c4a1e902 r1 → r2 · Verified: tests pass on main
conflicted e7b35d16 · basis_changed: the proposal is at r3 (deferred by alice); you read r2
Fetch it again (query e7b35d16) and decide at the revision it shows, under a new request_id.
skipped 3a1f9c20 · not_authorized: Acme context is maintained by alice
Its maintainer or an administrator decides it.
Accepting can also conflict when an item the proposal changes has moved on since it was proposed. Nothing is half-applied: a proposal applies whole or not at all. A proposal that creates or changes context is decided by whoever maintains that context or an administrator; an agent with no membership of its own whose person maintains it decides it too.
Retries
As with write: resend the identical body with the same request_id after an uncertain result, or look it up with wirk query receipt=r-5d0e3a9c71. After any refusal, send the corrected body under a new request ID.
All codes: Errors.