docs(slice-21 FR-4d): closure ≠ acceptance — JSDoc on /api/queue/update + CLI help on rig queue update (OPR.0.3.2.21.FR-4)

Codifies the closure-vs-acceptance distinction the external-host
orchestrator review surfaced: `state=done closure_reason=handed_off_to`
records that the source seat DELIVERED the work to the next stage;
it does NOT record that the next stage ACCEPTED the work. The
receiving stage's acceptance is its own verdict on its own qitem,
not this closure.

Vocabulary table (now documented in both the JSDoc and CLI help):
- handed_off_to    delivered to next stage; acceptance pending
                   that stage's verdict on its own qitem
- blocked_on       waiting on a named blocker (closureTarget)
- denied           the source seat refuses the work
- canceled         work no longer needed (no follow-on)
- no-follow-on     completed in place; no further routing
- escalation       routed to a higher-authority seat

Scope (docs only; NO schema change):

(1) packages/daemon/src/routes/queue.ts — JSDoc block above the
    POST /:qitemId/update handler explains closure ≠ acceptance
    + the closure vocabulary + cites that the "accepted" state
    schema change is deferred to release-0.3.3 (FR-4d-state).
    No behavior change.

(2) packages/cli/src/commands/queue.ts — the .description() for
    the `rig queue update` subcommand gains a one-line clarifier
    naming the closure ≠ acceptance distinction. The existing
    enumeration of the 6 closure reasons is preserved; the
    addition is appended. Operators running `rig queue update
    --help` now see the distinction in the help text.

Out of scope (per slice mission split note):
- New "accepted" queue state — schema change deferred to 0.3.3
  (FR-4d-state follow-on slice).
- Closure-reason enum mutation — preserved as the existing 6
  values; no new values added.

Verification:
- packages/daemon tsc EXIT=0.
- packages/cli tsc EXIT=0.
- packages/cli queue.test.ts: 28/28 PASS (no behavior change, no
  test deltas).
- Commit body verification grep clean per banked discipline.
- git diff --cached --stat: 2 files (+24 / -2).

Branch: slice-21-fr-4-queue-ergonomics off LOCAL main 58713e0c.
Chain: 2f731b84 (FR-4a, CLEAR) → 207ad5f1 (FR-4b, CLEAR) →
50b17c73 (FR-4c, pending verdict) → this commit. A follow-on
cleanup commit will roll in the two non-blocking notes from
guard's FR-4(a) review (TTY comment reconcile + --body-file
directory path → 3-part error). LOCAL only, NO push.
This commit is contained in:
mvschwarz committed 2026-06-01 05:39:43 -07:00
1 parent 50b17c73d5
commit 164a67bef2
2 files changed
+24 -2

No files matched your search

+1 -1
View File
@@ -247,7 +247,7 @@ export function queueCommand(depsOverride?: QueueDeps): Command {
cmd
.command("update <qitemId>")
.description("Mutate qitem state. state=done REQUIRES --closure-reason (one of: handed_off_to, blocked_on, denied, canceled, no-follow-on, escalation)")
.description("Mutate qitem state. state=done REQUIRES --closure-reason (one of: handed_off_to, blocked_on, denied, canceled, no-follow-on, escalation). Closure ≠ acceptance: handed_off_to records delivery to the next stage; acceptance is the next stage's verdict on its own qitem, not this closure.")
.option("--actor <session>", "Actor session performing the transition (defaults to OPENRIG_SESSION_NAME)")
.requiredOption("--state <state>", "New state: pending | in-progress | done | blocked | failed | denied | canceled | handed-off")
.option("--closure-reason <reason>", "Required for state=done")
+23 -1
View File
@@ -187,7 +187,29 @@ export function queueRoutes(): Hono {
}
});
// POST /:qitemId/update — general state mutator (incl. done)
// POST /:qitemId/update — general state mutator (incl. done).
//
// OPR.0.3.2.21.FR-4(d-docs) — closure ≠ acceptance.
//
// `state=done` with `closure_reason=handed_off_to` records that the
// source seat has DELIVERED the work to the next stage. It does NOT
// record that the next stage has ACCEPTED the work — that's the next
// stage's verdict on its own qitem (typically a separate close with
// its own closure_reason).
//
// Closure vocabulary:
// - handed_off_to delivered to next stage; acceptance pending
// that stage's verdict on its own qitem
// - blocked_on waiting on a named blocker (closureTarget)
// - denied the source seat refuses the work
// - canceled work no longer needed (no follow-on)
// - no-follow-on completed in place; no further routing
// - escalation routed to a higher-authority seat
//
// The "accepted" state IS NOT a queue state in v0.3.x — the qitem
// model captures delivery + the receiving stage owns acceptance as
// a separate transaction. (FR-4d-state schema change adding a
// distinct "accepted" state is deferred to release-0.3.3.)
app.post("/:qitemId/update", async (c) => {
const qitemId = c.req.param("qitemId");
const body = await c.req.json<{