diff --git a/docs/plans/2026-09-26_lead-decisions.md b/docs/plans/2026-09-26_lead-decisions.md index b10e9cbe..2cf9415d 100644 --- a/docs/plans/2026-09-26_lead-decisions.md +++ b/docs/plans/2026-09-26_lead-decisions.md @@ -1108,3 +1108,30 @@ which stay with him. Each item names who decided it and what happened. - Indexing the events scan stays a follow-up. Neither the consumption check nor the existing raise lookup has an index, and at slice 1 volumes that doesn't matter. +65. **A within-role message cites a decision; it doesn't spend one + (2026-10-05).** Source: Dewey, `agents/dewey/work/wui/SLICE1-VIEWS.md` + section 10, probe `~/dewey-scratch/s2b-probe.w9pJ/probe.mjs`, run + against 38828a2c and 4afab552. + - Decision 64 said within-role actions pass no decision. That is + true for `authorize`, but not for `message.send`, which stores its + `decision` argument in `messages.decision`. The trail and the + inbox read that column as "this message is about this decision". + Since S2b, a within-role send that names a decision runs the full + check, so the PM's DECISION message to the human about a pending + `role.launch` refuses with `decision-mismatch`. Fixture messages + 101 and 102 are that case. + - Ruling: when `message.send` is within-role for the sender and + target, `decision` is a citation. The broker checks that the + decision exists in the business and stores it. The broker doesn't + class-match it, doesn't consume it, and doesn't put it in the + `action.allowed` event, so the citation can't consume the decision + or count as using it up. When `message.send` isn't within-role, + `decision` is the authority, as decision 64 says, and the stored + column names that approval. + - Not chosen: a separate citation argument, which needs schema v3c + for a slice 1 gap that the class split already closes. Dewey's + option 2 also wasn't taken in place of this. S4 still sends the + Discord DM for a blocking gated decision and records the delivery + (REQ-DEC-4), but agents keep citing decisions in messages. + - Row 44 (S2c, Rocko, reviewed by Darkwing) carries the change and + Darkwing's README wording note from S2b round 2. diff --git a/docs/plans/2026-10-05_s2c-message-decision-citation.md b/docs/plans/2026-10-05_s2c-message-decision-citation.md new file mode 100644 index 00000000..64b03f86 --- /dev/null +++ b/docs/plans/2026-10-05_s2c-message-decision-citation.md @@ -0,0 +1,73 @@ +# Slice 1 S2c: a within-role message cites a decision (2026-10-05) + +Status: written by Sage, lead, under lead decision 65. It follows +`docs/plans/BRIEF-TEMPLATE.md`, and it amends no section of the slice 1 +brief. + +## S2c: a within-role message cites a decision without consuming it + +### Problem + +S2b (4afab552) sends every agent `message.send` through +`#consumeAuthority`. A within-role send that names a decision now gets +the full check, so it refuses with `decision-mismatch` unless the +decision approved `message.send` itself, and a match spends the +decision. Before S2b, the `decision` argument on a within-role send was +a citation, stored in `messages.decision`. The trail (`messages WHERE +decision = ?`) and the inbox read that column. Dewey's probe shows the +PM's DECISION message to the human about an open `role.launch` decision +is written at 38828a2c and refused at 4afab552. + +### Owner and reviewer + +- Owner: rocko. +- Reviewer: darkwing. + +### Files owned + +- `packages/bus/src/broker.mjs`, the `message.send` case and, if + needed, `#checkAuthority`. +- `packages/bus/tests/single-use.test.mjs` or one new test file under + `packages/bus/tests/`. +- `packages/bus/README.md`, the `message.send` and single-use + paragraphs. + +### What ships + +- If `message.send` is within-role for the sender and target, the + `decision` argument is a citation. The broker checks that the decision + exists in the business, stores it in `messages.decision`, and writes + the `action.allowed` event without a `decision` field. It doesn't + class-match or consume the decision. +- If `message.send` isn't within-role, nothing changes from S2b. The + decision is the authority, it must match, and the send consumes it. +- An open, unresolved decision can be cited. +- README: correct "Within-role actions without a decision remain + unchanged", per Darkwing's S2b round 2 note. State that every agent + send writes `action.allowed` and that a within-role send's decision is + a citation. +- Tests: + - Dewey's case: the PM cites an open gated `role.launch` decision in a + DECISION message to the human, and the send succeeds. + - The cited decision can still be used afterward by the action it + approves. + - Two within-role sends can cite the same decision. + - A missing decision refuses with `decision-not-found`. + - Every S2b refusal for a send that isn't within-role still holds. + - Add a mutant that puts the citation into the event and one that + sends within-role citations through the authority check. The tests + must kill both. +- Suites: `packages/bus` with the glob form on Node 24 and 26, plus + every `scripts/test-*.sh`. + +### Out of scope + +- No schema change and no separate citation argument (decision 65). +- The Discord DM for blocking gated decisions and its delivery record. + Those belong to S4. + +### Gate + +Darkwing approves on the row's issue. Sage runs the integration gate in +a worktree before committing. This has to land before S4 writes +decision messages through the broker.