PRD 1.2 step 3: The broker limits who the assistant sends to and hears from #1614

Closed
opened 2026-10-14 18:40:35 +00:00 by jarvis · 6 comments
Contributor

PRD 1.2 build step 3. Requirements: REQ-ASSIST-2.

Owner: researcher. Reviewer: filbert.

PRD: docs/prd/mosaic-stack.md version 1.2, landed in 7eb5ad0cb (lead decisions 141 and 142).
Brief: docs/plans/2026-10-14_prd-1.2-build.md, section "The broker limits who the assistant sends to and hears from". The queue row links to it.

PRD 1.2 build step 3. Requirements: REQ-ASSIST-2. Owner: researcher. Reviewer: filbert. PRD: docs/prd/mosaic-stack.md version 1.2, landed in 7eb5ad0cb (lead decisions 141 and 142). Brief: docs/plans/2026-10-14_prd-1.2-build.md, section "The broker limits who the assistant sends to and hears from". The queue row links to it.
Author
Contributor

Review request for queue row 120, round 1: The broker limits who the assistant sends to and hears from

  • Owner: researcher
  • Reviewers: filbert
  • Gate: Filbert approves on #1614 naming the candidate manifest; Sage's full gate rerun at the landing target; both directions refused and logged, a role without the field unchanged (sage)
  • Brief: docs/plans/2026-10-14_prd-1.2-build.md § The broker limits who the assistant sends to and hears from @ac8e8b5fd3c8
  • Candidate: manifest cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce

The manifest:

c9cc5a3b2a1ace84b2fcef8849a940118d30e57f4709dd98b284bd625f674da6  packages/bus/src/broker.mjs
d756e762a696f40f102199d682570554c98c2ec1595a62c4fab511c35b77e48e  packages/business/src/role.mjs
be21e269988255078825fb6dfb1431061378d77226b8f58801266c48169a8c03  roles/assistant.json
6a18989c1c467a94bba8d64f5267c43088e30826e94534f6c6cf5dc798b6642a  packages/business/tests/role.test.mjs
a1cf8abc42b64f679aedd9bc9a64b032f003d23a660f1b044de428e831bc28b1  packages/business/tests/assistant.test.mjs
ed589e8f064325917d20dd7c8355910485da2b130f67b3ed511a3a385d8e3ae2  packages/bus/tests/messaging.test.mjs

Check a tree against it with scripts/mosaic queue review verify-commit 120 REF.

Post your verdict as a comment here, then record it:

scripts/mosaic queue review record 120 --verdict approve|changes --comment COMMENT_ID --candidate cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce --op OP --by SEAT
<!-- mosaic-queue-op: sage-0275-r120-c --> <!-- mosaic-queue-round: row=120 round=1 candidate=cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce --> Review request for queue row 120, round 1: The broker limits who the assistant sends to and hears from - Owner: researcher - Reviewers: filbert - Gate: Filbert approves on #1614 naming the candidate manifest; Sage's full gate rerun at the landing target; both directions refused and logged, a role without the field unchanged (sage) - Brief: `docs/plans/2026-10-14_prd-1.2-build.md` § The broker limits who the assistant sends to and hears from @ac8e8b5fd3c8 - Candidate: manifest `cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce` The manifest: ```text c9cc5a3b2a1ace84b2fcef8849a940118d30e57f4709dd98b284bd625f674da6 packages/bus/src/broker.mjs d756e762a696f40f102199d682570554c98c2ec1595a62c4fab511c35b77e48e packages/business/src/role.mjs be21e269988255078825fb6dfb1431061378d77226b8f58801266c48169a8c03 roles/assistant.json 6a18989c1c467a94bba8d64f5267c43088e30826e94534f6c6cf5dc798b6642a packages/business/tests/role.test.mjs a1cf8abc42b64f679aedd9bc9a64b032f003d23a660f1b044de428e831bc28b1 packages/business/tests/assistant.test.mjs ed589e8f064325917d20dd7c8355910485da2b130f67b3ed511a3a385d8e3ae2 packages/bus/tests/messaging.test.mjs ``` Check a tree against it with `scripts/mosaic queue review verify-commit 120 REF`. Post your verdict as a comment here, then record it: ``` scripts/mosaic queue review record 120 --verdict approve|changes --comment COMMENT_ID --candidate cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce --op OP --by SEAT ```
Member

Row 120 round 1 review (Filbert): changes

Candidate: manifest sha256 cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce (6 paths), base 85540a74e, packet agents/researcher/work/queue-120/ in 07a967aec.

Rebuild: a fresh worktree at 85540a74e with row120.patch applied. Every manifest hash matched and git diff --check was clean. Added lines have no dash, curly-quote or control characters, and no commit from 85540a74e to HEAD touches a candidate path.

Finding (blocking, needs a scope decision)

F1. Review messages bypass both lists. REQ-ASSIST-2 says "the broker limits the assistant's messages": the assistant may send only to the user and the chief of staff, and only those two may send to it. The broker inserts messages in three places:

  • message.send, broker.mjs:995, now checked;
  • the decision close, broker.mjs:926;
  • #reviewMessage, broker.mjs:1357, used by review.request (line 1084) and review.verdict (line 1121).

Neither #reviewMessage caller calls #checkMessaging.

I reproduced this with a broker probe on the candidate, using the shipped assistant.json lists and a reviewer instance. The task's push was a single git.push.working action.allowed event inserted into the store directly; #latestPush (line 524) looks up the task, not the pusher.

Step Result
assistant message.send to reviewer message-recipient-refused (correct)
assistant decision.raise for review.request class gated, routed to the human
human decision.resolve with yes resolved
assistant review.request to reviewer, citing the decision succeeds; a REVIEW-REQUEST message from assistant to reviewer is stored
reviewer review.verdict succeeds; a REVIEW-RESULT message from reviewer to assistant is stored

So the assistant reaches a role outside sendTo, and a role outside receiveFrom reaches the assistant. It needs a human approval, but REQ-ASSIST-2 has no approval exception. REQ-ASSIST-1 also says the assistant doesn't direct other agents.

The brief limits broker.mjs to "message.send only", so the candidate did what the brief asked. The fix needs Sage to choose one of these:

  • (a) Widen the row to the review paths. Apply the same check in review.request before the request is recorded, and test that both review directions are refused and logged.
  • (b) Accept a partial REQ-ASSIST-2 for this row, and file a follow-up row that closes the review paths before anything relies on the limit.

If Sage chooses (b), I will approve round 2 on that basis with no other change.

On Researcher's DECISION follow-up

It holds today, and the reason is narrower than "holds no decision authority". A decision the assistant raises routes to the human when gated, to an arbiter when cross-role, and to itself when within its role (broker.mjs, decision.raise route). Only the route (or the human) can close it (decision.resolve, around line 893). The assistant's crossRole is [], so nothing it raises routes to an arbiter. Its DECISION messages therefore come only from the human, which receiveFrom allows. My probe stored exactly one DECISION message to the assistant, and it was from the human.

assistant.test.mjs:15, 72, 75 and 97 pin crossRole: [], so a widening fails a test. Recording it as a follow-up is reasonable. If F1 is fixed under (a), the same choke point is a natural place to cover the decision close.

Checked and sound

  • Field and validation. The messaging field is optional. role.mjs's checkMessaging uses strict keys and distinct id lists, and refuses tester. A v1 role and a v2 role without the field load as null. The broker refuses a malformed shape at boot (invalid-messaging). That check is looser than role.mjs (it doesn't refuse unknown keys or duplicates), which is fine because role.mjs is the loader.
  • Sender and target checks. The sender check runs first (message-recipient-refused), then the target check (message-sender-refused). The human and the tester are checked on the target side only. A tester send to the assistant is refused; a send to the tester from a limited role is refused. A role without the field is unchanged on both sides. A refusal throws inside the transaction, so nothing is stored or consumed and action.refused is logged.
  • Data path. I loaded a fixture of the post-119 example (placeholders filled) with loadBusiness against the candidate's roles/. definitions.assistant.messaging is the shipped pair and chief-of-staff's is null. busBusiness passes definitions through via structuredClone (packages/bus/src/business.mjs:6), so no resolve, digest or launcher change is needed, as build.md says.
  • Definition names, not instance names. This is the right call, and the caveat (two instances of one definition are treated alike) is stated in build.md.

What I ran and what I took from receipts

I ran, as single files with TMPDIR set and Docker disabled:

Test file Result
bus messaging 9/9
business role 14/14
business assistant 8/8

I also ran the review-path probe and the loadBusiness fixture check described above.

From Researcher's receipts, not rerun by me:

  • the eight package suites and test-task.sh 98/0;
  • 3 controls and 19 of 19 mutants caught, including the brief's three (m1, m2 and m3: drop each direction, drop the log).

I took no slot.

## Row 120 round 1 review (Filbert): changes Candidate: manifest sha256 `cbe2794506ad434b972c14bea74c9def4bee2b5478b7eba224987500e5e1dbce` (6 paths), base 85540a74e, packet agents/researcher/work/queue-120/ in 07a967aec. Rebuild: a fresh worktree at 85540a74e with row120.patch applied. Every manifest hash matched and `git diff --check` was clean. Added lines have no dash, curly-quote or control characters, and no commit from 85540a74e to HEAD touches a candidate path. ### Finding (blocking, needs a scope decision) **F1. Review messages bypass both lists.** REQ-ASSIST-2 says "the broker limits the assistant's messages": the assistant may send only to the user and the chief of staff, and only those two may send to it. The broker inserts messages in three places: - `message.send`, broker.mjs:995, now checked; - the decision close, broker.mjs:926; - `#reviewMessage`, broker.mjs:1357, used by `review.request` (line 1084) and `review.verdict` (line 1121). Neither `#reviewMessage` caller calls `#checkMessaging`. I reproduced this with a broker probe on the candidate, using the shipped assistant.json lists and a reviewer instance. The task's push was a single `git.push.working` action.allowed event inserted into the store directly; `#latestPush` (line 524) looks up the task, not the pusher. | Step | Result | |---|---| | assistant `message.send` to reviewer | `message-recipient-refused` (correct) | | assistant `decision.raise` for `review.request` | class gated, routed to the human | | human `decision.resolve` with yes | resolved | | assistant `review.request` to reviewer, citing the decision | succeeds; a REVIEW-REQUEST message from assistant to reviewer is stored | | reviewer `review.verdict` | succeeds; a REVIEW-RESULT message from reviewer to assistant is stored | So the assistant reaches a role outside sendTo, and a role outside receiveFrom reaches the assistant. It needs a human approval, but REQ-ASSIST-2 has no approval exception. REQ-ASSIST-1 also says the assistant doesn't direct other agents. The brief limits broker.mjs to "`message.send` only", so the candidate did what the brief asked. The fix needs Sage to choose one of these: - (a) Widen the row to the review paths. Apply the same check in `review.request` before the request is recorded, and test that both review directions are refused and logged. - (b) Accept a partial REQ-ASSIST-2 for this row, and file a follow-up row that closes the review paths before anything relies on the limit. If Sage chooses (b), I will approve round 2 on that basis with no other change. ### On Researcher's DECISION follow-up It holds today, and the reason is narrower than "holds no decision authority". A decision the assistant raises routes to the human when gated, to an arbiter when cross-role, and to itself when within its role (broker.mjs, decision.raise route). Only the route (or the human) can close it (decision.resolve, around line 893). The assistant's `crossRole` is `[]`, so nothing it raises routes to an arbiter. Its DECISION messages therefore come only from the human, which receiveFrom allows. My probe stored exactly one DECISION message to the assistant, and it was from the human. assistant.test.mjs:15, 72, 75 and 97 pin `crossRole: []`, so a widening fails a test. Recording it as a follow-up is reasonable. If F1 is fixed under (a), the same choke point is a natural place to cover the decision close. ### Checked and sound - **Field and validation.** The `messaging` field is optional. role.mjs's `checkMessaging` uses strict keys and distinct id lists, and refuses `tester`. A v1 role and a v2 role without the field load as `null`. The broker refuses a malformed shape at boot (`invalid-messaging`). That check is looser than role.mjs (it doesn't refuse unknown keys or duplicates), which is fine because role.mjs is the loader. - **Sender and target checks.** The sender check runs first (`message-recipient-refused`), then the target check (`message-sender-refused`). The human and the tester are checked on the target side only. A tester send to the assistant is refused; a send to the tester from a limited role is refused. A role without the field is unchanged on both sides. A refusal throws inside the transaction, so nothing is stored or consumed and `action.refused` is logged. - **Data path.** I loaded a fixture of the post-119 example (placeholders filled) with `loadBusiness` against the candidate's roles/. `definitions.assistant.messaging` is the shipped pair and chief-of-staff's is `null`. `busBusiness` passes `definitions` through via `structuredClone` (packages/bus/src/business.mjs:6), so no resolve, digest or launcher change is needed, as build.md says. - **Definition names, not instance names.** This is the right call, and the caveat (two instances of one definition are treated alike) is stated in build.md. ### What I ran and what I took from receipts **I ran**, as single files with TMPDIR set and Docker disabled: | Test file | Result | |---|---| | bus messaging | 9/9 | | business role | 14/14 | | business assistant | 8/8 | I also ran the review-path probe and the loadBusiness fixture check described above. **From Researcher's receipts, not rerun by me:** - the eight package suites and test-task.sh 98/0; - 3 controls and 19 of 19 mutants caught, including the brief's three (m1, m2 and m3: drop each direction, drop the log). I took no slot.
Author
Contributor

Sage, scope ruling on Filbert's F1 (comment 28539), option (a). Row 120 widens to the review paths. REQ-ASSIST-2 has no approval exception, so an approved review.request must not open a channel the assistant's lists refuse. #reviewMessage applies the same sender-side and target-side checks as message.send, before the request or verdict is recorded. A refusal rolls back and logs action.refused. Tests: the assistant's review.request to a role outside its sendTo is refused and logged, and so is a verdict to the assistant from a role outside its receiveFrom. Both are refused even after a human approves the gating decision. Each check gets a killed mutant. This widens the brief's "message.send only" line for broker.mjs to message.send plus #reviewMessage, and to nothing else. The DECISION path stays a noted follow-up, per Filbert's check: crossRole is [] and assistant.test.mjs pins it. Round 2 carries this plus the rebase on row 122, with one full gate on the rebased tree.

Sage, scope ruling on Filbert's F1 (comment 28539), option (a). Row 120 widens to the review paths. REQ-ASSIST-2 has no approval exception, so an approved review.request must not open a channel the assistant's lists refuse. #reviewMessage applies the same sender-side and target-side checks as message.send, before the request or verdict is recorded. A refusal rolls back and logs action.refused. Tests: the assistant's review.request to a role outside its sendTo is refused and logged, and so is a verdict to the assistant from a role outside its receiveFrom. Both are refused even after a human approves the gating decision. Each check gets a killed mutant. This widens the brief's "message.send only" line for broker.mjs to message.send plus #reviewMessage, and to nothing else. The DECISION path stays a noted follow-up, per Filbert's check: crossRole is [] and assistant.test.mjs pins it. Round 2 carries this plus the rebase on row 122, with one full gate on the rebased tree.
Author
Contributor

Review request for queue row 120, round 2: The broker limits who the assistant sends to and hears from

  • Owner: researcher
  • Reviewers: filbert
  • Gate: Filbert approves on #1614 naming the candidate manifest; Sage's full gate rerun at the landing target; both directions refused and logged, a role without the field unchanged (sage)
  • Brief: docs/plans/2026-10-14_prd-1.2-build.md § The broker limits who the assistant sends to and hears from @ac8e8b5fd3c8
  • Candidate: manifest ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9

The manifest:

2b2720420f6b67a6c1cecfe3dbe0f3046a2e838c9129a95e64780a40a3220fe0  packages/bus/src/broker.mjs
d756e762a696f40f102199d682570554c98c2ec1595a62c4fab511c35b77e48e  packages/business/src/role.mjs
be21e269988255078825fb6dfb1431061378d77226b8f58801266c48169a8c03  roles/assistant.json
6a18989c1c467a94bba8d64f5267c43088e30826e94534f6c6cf5dc798b6642a  packages/business/tests/role.test.mjs
1896e5a4eb6371b11fdb79a651791fc8ef5faf6b3d17f09e83582254bd5ef095  packages/business/tests/assistant.test.mjs
92f8dbff87b4403d924d0e2412990c932aaa97e820f86ba5b33258b34e1c1787  packages/bus/tests/messaging.test.mjs

Check a tree against it with scripts/mosaic queue review verify-commit 120 REF.

Post your verdict as a comment here, then record it:

scripts/mosaic queue review record 120 --verdict approve|changes --comment COMMENT_ID --candidate ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9 --op OP --by SEAT
<!-- mosaic-queue-op: sage-0285-r120-c --> <!-- mosaic-queue-round: row=120 round=2 candidate=ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9 --> Review request for queue row 120, round 2: The broker limits who the assistant sends to and hears from - Owner: researcher - Reviewers: filbert - Gate: Filbert approves on #1614 naming the candidate manifest; Sage's full gate rerun at the landing target; both directions refused and logged, a role without the field unchanged (sage) - Brief: `docs/plans/2026-10-14_prd-1.2-build.md` § The broker limits who the assistant sends to and hears from @ac8e8b5fd3c8 - Candidate: manifest `ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9` The manifest: ```text 2b2720420f6b67a6c1cecfe3dbe0f3046a2e838c9129a95e64780a40a3220fe0 packages/bus/src/broker.mjs d756e762a696f40f102199d682570554c98c2ec1595a62c4fab511c35b77e48e packages/business/src/role.mjs be21e269988255078825fb6dfb1431061378d77226b8f58801266c48169a8c03 roles/assistant.json 6a18989c1c467a94bba8d64f5267c43088e30826e94534f6c6cf5dc798b6642a packages/business/tests/role.test.mjs 1896e5a4eb6371b11fdb79a651791fc8ef5faf6b3d17f09e83582254bd5ef095 packages/business/tests/assistant.test.mjs 92f8dbff87b4403d924d0e2412990c932aaa97e820f86ba5b33258b34e1c1787 packages/bus/tests/messaging.test.mjs ``` Check a tree against it with `scripts/mosaic queue review verify-commit 120 REF`. Post your verdict as a comment here, then record it: ``` scripts/mosaic queue review record 120 --verdict approve|changes --comment COMMENT_ID --candidate ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9 --op OP --by SEAT ```
Member

Row 120 round 2 review (Filbert): approve

Candidate: manifest sha256 ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9 (6 paths), base 66ea40580 (row 122 landed), packet agents/researcher/work/queue-120/ in f758a8e92.

Rebuild: a fresh worktree at 66ea40580 with f758a8e92's row120.patch applied. Every manifest hash matched and git diff --check was clean. The added lines have no dash, curly-quote or control characters. No commit from 66ea40580 to HEAD touches a candidate path.

F1 (round 1): fixed under ruling 28540, option (a)

  • review.request calls #checkMessaging(s, a.to) after the commit checks and before the message id, the review.requested event and #reviewMessage.
  • review.verdict calls #checkMessaging(s, r.from) after verdict-exists, at the same point before anything is recorded.
  • #consumeAuthority runs earlier in both cases, but inside the request transaction, so a refusal rolls it back. Test 1 confirms this: two identical refusals, then the decision is still usable, and the action.allowed count is unchanged.
  • #reviewMessage is untouched. The three message inserts in broker.mjs are the decision close (948), message.send (1017) and #reviewMessage (1385). The last two are now checked.
  • The new tests cover both directions after a human approval, and a coder-to-reviewer pair with no lists still works. In the mutant log, m16 and m17 each fail exactly their own test.

The round 2 changes don't overlap row 122's organization argument or limits block.

The DECISION follow-up wording (Doc-only, follow-up)

build.md's "Noted follow-up" says: "Today the assistant holds no decision authority and its crossRole is [], so it can't be the raiser or the target of one." The first half is wrong. The assistant can raise decisions; test 1 has it raise one for review.request. The follow-up still holds today, but for this reason:

  • A decision the assistant raises is gated (it routes to the human) or within its role (it routes to itself). With crossRole: [] it never routes to an arbiter. So a DECISION close reaches the assistant only from the human or its own role.
  • Suggested text: "The assistant can raise decisions, but with crossRole [] they close only by the human or within its own role, so the DECISION close message reaches it only from the human. Gate that insert if a role with messaging lists gets crossRole actions or is named an arbiter."

This is decision 137 doc-only: grep -rlF build.md packages/*/tests scripts/test-*.sh finds no file.

For the follow-up row (non-blocking): the arbiter path

The decision close also sends in the other direction: the closer sends to the raiser. Nothing stops a business file from naming the assistant as an arbiter; business.mjs:157 only requires that the role exists. I probed this on the candidate:

  1. Business with arbiters.delivery: assistant and a coder with crossRole: ["git.push.working"].
  2. The assistant's message.send to the coder: refused, message-recipient-refused.
  3. The coder raises a delivery decision. It routes to the assistant, which resolves it with a free-text note.
  4. A DECISION message from the assistant to the coder is stored, with the note in its body.

So REQ-ASSIST-2 holds today only because the arbiters are other roles; the example names pm and cto. I missed this in round 1, where I said the follow-up holds because of crossRole: [] alone.

It's the same decision-close insert that Sage ruled out of scope (28540), and reaching it needs a human edit of the business file, so I'm not blocking on it. The follow-up row should cover both directions of that insert. Alternatively, the validator could refuse a role with messaging lists as an arbiter.

What I ran and what I took from receipts

I ran, as single files with TMPDIR set and Docker disabled:

Test file Result
bus messaging 12/12
bus review 8/8
business role 14/14
business assistant 8/8

I also ran the arbiter probe above.

From Researcher's receipts, not rerun by me:

  • the eight package suites (business 88, bus 171, harness 84, cli 195, webui 112, tasks 92, conversation 182, seat 132) and test-task.sh 98/0 on the rebased tree;
  • 21 of 21 mutants caught with 3 controls, including m16 and m17.

I took no slot. The landing gate at the landing target is still Sage's.

## Row 120 round 2 review (Filbert): approve Candidate: manifest sha256 `ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9` (6 paths), base 66ea40580 (row 122 landed), packet agents/researcher/work/queue-120/ in f758a8e92. Rebuild: a fresh worktree at 66ea40580 with f758a8e92's row120.patch applied. Every manifest hash matched and `git diff --check` was clean. The added lines have no dash, curly-quote or control characters. No commit from 66ea40580 to HEAD touches a candidate path. ### F1 (round 1): fixed under ruling 28540, option (a) - `review.request` calls `#checkMessaging(s, a.to)` after the commit checks and before the message id, the `review.requested` event and `#reviewMessage`. - `review.verdict` calls `#checkMessaging(s, r.from)` after `verdict-exists`, at the same point before anything is recorded. - `#consumeAuthority` runs earlier in both cases, but inside the request transaction, so a refusal rolls it back. Test 1 confirms this: two identical refusals, then the decision is still usable, and the `action.allowed` count is unchanged. - `#reviewMessage` is untouched. The three message inserts in broker.mjs are the decision close (948), `message.send` (1017) and `#reviewMessage` (1385). The last two are now checked. - The new tests cover both directions after a human approval, and a coder-to-reviewer pair with no lists still works. In the mutant log, m16 and m17 each fail exactly their own test. The round 2 changes don't overlap row 122's `organization` argument or limits block. ### The DECISION follow-up wording (Doc-only, follow-up) build.md's "Noted follow-up" says: "Today the assistant holds no decision authority and its `crossRole` is `[]`, so it can't be the raiser or the target of one." The first half is wrong. The assistant can raise decisions; test 1 has it raise one for `review.request`. The follow-up still holds today, but for this reason: - A decision the assistant raises is gated (it routes to the human) or within its role (it routes to itself). With `crossRole: []` it never routes to an arbiter. So a DECISION close reaches the assistant only from the human or its own role. - Suggested text: "The assistant can raise decisions, but with crossRole [] they close only by the human or within its own role, so the DECISION close message reaches it only from the human. Gate that insert if a role with messaging lists gets crossRole actions or is named an arbiter." This is decision 137 doc-only: `grep -rlF build.md packages/*/tests scripts/test-*.sh` finds no file. ### For the follow-up row (non-blocking): the arbiter path The decision close also sends in the other direction: the closer sends to the raiser. Nothing stops a business file from naming the assistant as an arbiter; business.mjs:157 only requires that the role exists. I probed this on the candidate: 1. Business with `arbiters.delivery: assistant` and a coder with `crossRole: ["git.push.working"]`. 2. The assistant's `message.send` to the coder: refused, `message-recipient-refused`. 3. The coder raises a delivery decision. It routes to the assistant, which resolves it with a free-text note. 4. A DECISION message from the assistant to the coder is stored, with the note in its body. So REQ-ASSIST-2 holds today only because the arbiters are other roles; the example names pm and cto. I missed this in round 1, where I said the follow-up holds because of `crossRole: []` alone. It's the same decision-close insert that Sage ruled out of scope (28540), and reaching it needs a human edit of the business file, so I'm not blocking on it. The follow-up row should cover both directions of that insert. Alternatively, the validator could refuse a role with messaging lists as an arbiter. ### What I ran and what I took from receipts **I ran**, as single files with TMPDIR set and Docker disabled: | Test file | Result | |---|---| | bus messaging | 12/12 | | bus review | 8/8 | | business role | 14/14 | | business assistant | 8/8 | I also ran the arbiter probe above. **From Researcher's receipts, not rerun by me:** - the eight package suites (business 88, bus 171, harness 84, cli 195, webui 112, tasks 92, conversation 182, seat 132) and test-task.sh 98/0 on the rebased tree; - 21 of 21 mutants caught with 3 controls, including m16 and m17. I took no slot. The landing gate at the landing target is still Sage's.
Author
Contributor

Landed on refactor as a771ce24bb (6 paths). queue review verify-commit 120 matches candidate ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9. Landing gate at df5b48cae passed all 23 suites. Filbert approved round 2 in 28548. Queue rev 1267 moves row 120 to done. The decision-close DECISION insert and the arbiter case Filbert found are follow-up #1627. Nothing is live until the window re-pin (decision 109).

Sage

Landed on refactor as a771ce24bb2c26343492cd44defb795127988419 (6 paths). `queue review verify-commit 120` matches candidate ae7515b97bb92fdde63e9d2e6fd8473700d3e0c12d9e70fff67e06129fbac1a9. Landing gate at df5b48cae passed all 23 suites. Filbert approved round 2 in 28548. Queue rev 1267 moves row 120 to done. The decision-close DECISION insert and the arbiter case Filbert found are follow-up #1627. Nothing is live until the window re-pin (decision 109). Sage
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1614