diff --git a/agents/darkwing/work/queue-115/r2/build.md b/agents/darkwing/work/queue-115/r2/build.md new file mode 100644 index 000000000..23eb81fca --- /dev/null +++ b/agents/darkwing/work/queue-115/r2/build.md @@ -0,0 +1,130 @@ +# Row 115 (#1609) round 2: a closed decision sends the raising role a message + +## Round 2 + +Filbert asked for changes in round 1 (comment 28422, rev 1131). Their C1: nothing tested the op filter in `#request`'s fallback query, `json_extract(body,'$.op') IN ('resolved','withdrawn')`. A human `decision.seen` on a human-routed decision also writes a `human.input` answer with the decision as its subject, with op `seen`. Without the filter, a seen before the close becomes the close message's `request`, which breaks brief item 3. Their f4 dropped the filter and the suites still passed. + +The fix is test-only, and broker.mjs is the same as in round 1. In packages/bus/tests/decision-close.test.mjs: + +- A new test, "a human seen before the close leaves the request on the close's answer, not the seen". The human sees two human-routed decisions, then resolves one and withdraws the other. Each close message's `request` is that close's own answer, and not the seen's. +- The `answer()` helper takes an op, `resolved` by default, so it can't return a seen's answer either. The human withdraw test now asks for `withdrawn`. + +f4 is m4 in mutants.py. Round 1 sections below are updated where the counts changed. + + +Brief: docs/plans/2026-10-14_decision-close-message.md. Mos found the gap. Jason resolved decision 03130d08, and the PM, which raised it, never got a turn, because a close wrote only `decision_events` and nothing reached the role. + +BASE: 94ece491f05ecbb737227da8a7ba1d57a1ac75fd. I built the candidate on 54b7c7b3e and moved the worktree to 94ece491f before the mutants and the gate. The commits between them touch only packages/ledger, docs/SESSIONS.md and the queue files, none of the manifest paths. +Candidate: build.patch against BASE. candidate-manifest.sha256 lists the 5 files, of which only decision-close.test.mjs changed since round 1. I applied the patch to a fresh `git archive 94ece491f` export and every digest matched (DIGESTS_OK). HEAD has moved past 94ece491f since, with docs commits and the PRD v1.1 merge f7c8537b3. That merge changes docs/prd/mosaic-stack.md, packages/tasks/requirements.json and two requirements tests, packages/tasks/tests/requirements.test.mjs and packages/bus/tests/requirements.test.mjs (2 lines). None of them is a manifest path, but the bus one is in the bus suite, so the landing gate at the new target covers it and mine at 94ece491f doesn't. + +## What changed + +### The close message + +packages/bus/src/broker.mjs, the `decision.resolve`/`decision.seen`/`decision.withdraw` case. After the `decision_events` insert and the human's `human.input` answer event, a close with `op !== 'seen'` by a human, or by a run other than `raised_by_run`, inserts one message: + +| Column | Value | +|---|---| +| `from_role`, `from_run` | `human`, `human-cli` for a human close; the closing role and run for a role close | +| `to_role` | `d.raised_by_role` | +| `class` | `DECISION` | +| `decision` | the decision's id | +| `in_reply_to`, `corrects` | null | +| `body` | `Decision on was resolved by : (