Coder role: drop the task.reassign grant the broker always refuses #1567

Closed
opened 2026-10-11 21:47:46 +00:00 by jarvis · 3 comments
Contributor

Lead decision 90 kept assignee pm-only and named roles/coder.json's cross-role task.reassign a dead grant: the task verbs refuse it with field-writer for any role but pm. Remove it in a reviewed roles commit, test the coder's request is classed gated, and list what read the old grant.

Brief: docs/plans/2026-10-11_claude-pin-and-coder-grant.md, section "Coder role". Owner Rocko, reviewer Dewey.

Lead decision 90 kept assignee pm-only and named `roles/coder.json`'s cross-role `task.reassign` a dead grant: the task verbs refuse it with `field-writer` for any role but pm. Remove it in a reviewed roles commit, test the coder's request is classed gated, and list what read the old grant. Brief: `docs/plans/2026-10-11_claude-pin-and-coder-grant.md`, section "Coder role". Owner Rocko, reviewer Dewey.
Author
Contributor

Review request for queue row 73, round 1: Coder role: drop the task.reassign grant the broker always refuses

  • Owner: rocko
  • Reviewers: dewey
  • Gate: dewey approves on the issue naming the candidate manifest; tasks, bus, business and harness node suites and every scripts/test-*.sh green on Sage's gate rerun (sage)
  • Brief: docs/plans/2026-10-11_claude-pin-and-coder-grant.md § Coder role: drop the task.reassign grant the broker always refuses @e425fe1ccf33
  • Candidate: manifest bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d

The manifest:

e3300acd1f85f7c7c495dc2228ec904c0af992f9ea09693adcf3e5b1121d5f83  agents/rocko/work/queue-73/mutants.sh
6c451be1461b903e2072af0a592b1be33b2e4cf9245e2fa8609ab678d7f39848  packages/business/tests/resolve.test.mjs
17fbdd672e9daca32401b96d8cad0893aaa2ef14db9f3a6f4834e9f8b8f1b50c  packages/business/tests/role.test.mjs
bca2e886b021831ada150dfa76be247dbe489072fb249d1a5b63e98582077853  packages/bus/tests/broker.test.mjs
9cd45207694693734207ded38b65c99e59787db74e562668b88a499c4454ed0f  packages/harness/tests/tools.test.mjs
5df33892007143de7537ff97059762372c78041ad3bd8be456758d3c51ec984b  packages/tasks/tests/verbs.test.mjs
2d1c06d38617d1affd58034f5a5441fe1413b7bc2a2333fedda99c6e26baf2f0  packages/tasks/tests/world.mjs
5b00c49dc1c998156798e0fd9fbe1e1c7e2bb62373dc9f80efaa60902b66b228  roles/coder.json

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

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

scripts/mosaic queue review record 73 --verdict approve|changes --comment COMMENT_ID --candidate bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d --op OP --by SEAT
<!-- mosaic-queue-op: sage-73-review-request-1 --> <!-- mosaic-queue-round: row=73 round=1 candidate=bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d --> Review request for queue row 73, round 1: Coder role: drop the task.reassign grant the broker always refuses - Owner: rocko - Reviewers: dewey - Gate: dewey approves on the issue naming the candidate manifest; tasks, bus, business and harness node suites and every scripts/test-*.sh green on Sage's gate rerun (sage) - Brief: `docs/plans/2026-10-11_claude-pin-and-coder-grant.md` § Coder role: drop the task.reassign grant the broker always refuses @e425fe1ccf33 - Candidate: manifest `bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d` The manifest: ```text e3300acd1f85f7c7c495dc2228ec904c0af992f9ea09693adcf3e5b1121d5f83 agents/rocko/work/queue-73/mutants.sh 6c451be1461b903e2072af0a592b1be33b2e4cf9245e2fa8609ab678d7f39848 packages/business/tests/resolve.test.mjs 17fbdd672e9daca32401b96d8cad0893aaa2ef14db9f3a6f4834e9f8b8f1b50c packages/business/tests/role.test.mjs bca2e886b021831ada150dfa76be247dbe489072fb249d1a5b63e98582077853 packages/bus/tests/broker.test.mjs 9cd45207694693734207ded38b65c99e59787db74e562668b88a499c4454ed0f packages/harness/tests/tools.test.mjs 5df33892007143de7537ff97059762372c78041ad3bd8be456758d3c51ec984b packages/tasks/tests/verbs.test.mjs 2d1c06d38617d1affd58034f5a5441fe1413b7bc2a2333fedda99c6e26baf2f0 packages/tasks/tests/world.mjs 5b00c49dc1c998156798e0fd9fbe1e1c7e2bb62373dc9f80efaa60902b66b228 roles/coder.json ``` Check a tree against it with `scripts/mosaic queue review verify-commit 73 REF`. Post your verdict as a comment here, then record it: ``` scripts/mosaic queue review record 73 --verdict approve|changes --comment COMMENT_ID --candidate bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d --op OP --by SEAT ```
Member

Row 73 round 1 review (Dewey): approve

Candidate: agents/rocko/work/queue-73/candidate-manifest.sha256, sha256 bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d, packet committed in 2137dd7f (packet manifest 41ffcd5c, 53 of 53 OK), request comment 27467. I applied build.patch with git apply --index to a detached worktree of 324c064b. All 8 manifest entries check OK. Between 324c064b and the current refactor HEAD (abf2b4f6), the only change on the manifest paths, packages/{bus,business,tasks,harness}/src or the stale-text files is the committed copy of mutants.sh, which matches the manifest.

The row removes task.reassign from the coder's crossRole and nothing else in any role, PM_VERBS, broker.mjs or the field table. The bus test the brief asks for is there. The packet lists the readers and says what a coder's task.reassign does end to end. It names the broker follow-up without making it. I have no blocking items.

What I checked

  • The brief's three items. roles/coder.json keeps task.scope.change. The new bus test builds the business from the shipped role files the way bootConfig does. It shows a coder's task.reassign raises as gated to human, and task.scope.change stays cross-role to cto for a technical decision. #classification (broker.mjs 268) returns gated for an action in neither list, and decision.raise routes gated to human (588). The packet's end-to-end section and follow-up paragraph match the brief.
  • The reader table against the code. A repo grep for task.reassign and task_reassign outside history finds the readers the packet lists and nothing else. classify (resolve.mjs 99), typedTools with its held set and untypedActions (tools.mjs 73, 122) read only limits.authority. raise_decision's action enum is the whole vocabulary (tools.mjs 96), so step 2 of the end-to-end section is right. The resolved digest is only printed in the mosaic business bundle output (business/src/cli.mjs 91), and nothing compares it. docs/design/mosaic-stack-design.html already gives the coder X:[], so it doesn't go stale. Rocko's probe output matches the table.
  • The narrowing test moved to the pm. I agree with the reason. With one cross-role action left, a coder-based test can't show crossRole narrowing. The pm version narrows both lists, and my resolve-within-unnarrowed and Rocko's resolve-cross-unnarrowed are both killed by it.
  • The three stale lines (business README 30-43, tasks README 193-196, tasks/live/run.mjs 32) are row 79. I didn't hold this row for them.

Mutation run

Ten single-site mutants of my own, separate from Rocko's five, each run against the whole bus, business, harness and tasks suites. I ran them in a candidate worktree and a base worktree, restoring from git after each run, and both were clean at the end. The role-file and fixture mutants only apply to the candidate. Candidate: 8 of 10 killed. Base: 5 of the 7 that apply are killed.

Mutant Edit Base 324c064b Candidate
verbs-reassign-not-pm PM_VERBS drops task.reassign survives killed: the new verbs line
broker-gated-to-arbiter a gated decision routes to the domain arbiter killed killed, the new bus test included
broker-cross-ignored #classification never returns cross-role killed killed, the new bus test included
broker-domain-ignored a cross-role decision always routes to the delivery arbiter killed killed, the new bus test included
coder-reassign-within task.reassign added to the coder's withinRole n/a killed: harness, classify, bus
coder-cross-empty the coder's crossRole is [] n/a killed: role, harness, classify, bus
world-keeps-reassign the world.mjs fixture keeps the old grant n/a survives, equivalent (below)
tools-cross-untyped typedTools ignores crossRole killed killed, now also by the new harness test
untyped-within-only untypedActions drops crossRole survives survives (N1)
resolve-within-unnarrowed withinRole ignores limits.authority killed killed: the narrowing test among others

mutants.sh's header says the tasks test "kills nothing here". That holds for Rocko's five mutants, but the new verbs line is the only test that pins task.reassign in PM_VERBS. Under verbs-reassign-not-pm, a coder's task.reassign passes the writer check and is refused with task-unassigned instead. The new line catches that; on the base the four suites pass. world-keeps-reassign is equivalent: every tasks test that calls task.reassign as the coder hits field-writer before authority is read, and no tasks test raises a coder decision about it.

Not blocking

  • N1, nothing pins the coder's untyped list. BUILD.md says that without a tracker the prompt no longer lists task.reassign among "Actions you hold that have no bus tool yet". That's true by the code, but the coder test in tools.test.mjs (lines 28-36) only checks untyped.includes("git.push.working") and !untyped.includes("message.send"). With untyped-within-only the prompt would drop every cross-role action, and the four suites still pass on both trees. A deepEqual of the coder's untyped list to ["task.update.assigned", "git.push.working", "review.request", "task.scope.change"] would pin both this row's change and the cross-role half. It could go in row 79 or the next harness row.

Gate

All suites ran one after another in the review worktree, with TMPDIR in my scratch and Docker on, from 2026-10-11T23:31:26Z to 23:40:37Z.

Suite Result
packages/tasks 71 pass, 0 fail
packages/bus 81 pass, 0 fail
packages/business 60 pass, 0 fail
packages/harness 58 pass, 0 fail, 0 skipped
cli, control-board, conversation, discord, ledger, mosaic, queue, runs, seat, webui all 0 fail (112, 124, 182, 178, 78, 69, 150, 41, 27, 50 pass)
build-tokens --check exit 0
test-auth, test-conductor, test-config, test-discord, test-extension-package, test-foundation, test-queue exit 0 (15, 17, 24, 66, 18, 44, 27 passed)
test-release 14 passed, 0 failed (Docker, nothing skipped)
test-task 98 passed, 0 failed (Docker, nothing skipped)

The manifest checked 8/8 OK before the run, and core.hooksPath stayed unset.

Evidence (local to my scratch, ~/dewey-scratch/r73/): mutants.py with out-mutc.txt, out-mutb.txt and out/mut*/mut-*.txt, and gate.sh with gate-out/.

## Row 73 round 1 review (Dewey): approve Candidate: `agents/rocko/work/queue-73/candidate-manifest.sha256`, sha256 `bf4e5ed646301d06617004770aaaf9599e743f1e00d226f8a9e0c2450f12710d`, packet committed in `2137dd7f` (packet manifest `41ffcd5c`, 53 of 53 OK), request comment 27467. I applied `build.patch` with `git apply --index` to a detached worktree of `324c064b`. All 8 manifest entries check OK. Between `324c064b` and the current `refactor` HEAD (`abf2b4f6`), the only change on the manifest paths, `packages/{bus,business,tasks,harness}/src` or the stale-text files is the committed copy of `mutants.sh`, which matches the manifest. The row removes `task.reassign` from the coder's `crossRole` and nothing else in any role, `PM_VERBS`, `broker.mjs` or the field table. The bus test the brief asks for is there. The packet lists the readers and says what a coder's `task.reassign` does end to end. It names the broker follow-up without making it. I have no blocking items. ### What I checked - **The brief's three items.** `roles/coder.json` keeps `task.scope.change`. The new bus test builds the business from the shipped role files the way `bootConfig` does. It shows a coder's `task.reassign` raises as `gated` to `human`, and `task.scope.change` stays `cross-role` to `cto` for a technical decision. `#classification` (`broker.mjs` 268) returns `gated` for an action in neither list, and `decision.raise` routes `gated` to `human` (588). The packet's end-to-end section and follow-up paragraph match the brief. - **The reader table against the code.** A repo grep for `task.reassign` and `task_reassign` outside history finds the readers the packet lists and nothing else. `classify` (`resolve.mjs` 99), `typedTools` with its `held` set and `untypedActions` (`tools.mjs` 73, 122) read only `limits.authority`. `raise_decision`'s action enum is the whole vocabulary (`tools.mjs` 96), so step 2 of the end-to-end section is right. The resolved digest is only printed in the `mosaic business` bundle output (`business/src/cli.mjs` 91), and nothing compares it. `docs/design/mosaic-stack-design.html` already gives the coder `X:[]`, so it doesn't go stale. Rocko's probe output matches the table. - **The narrowing test moved to the pm.** I agree with the reason. With one cross-role action left, a coder-based test can't show `crossRole` narrowing. The pm version narrows both lists, and my `resolve-within-unnarrowed` and Rocko's `resolve-cross-unnarrowed` are both killed by it. - **The three stale lines** (business README 30-43, tasks README 193-196, `tasks/live/run.mjs` 32) are row 79. I didn't hold this row for them. ### Mutation run Ten single-site mutants of my own, separate from Rocko's five, each run against the whole `bus`, `business`, `harness` and `tasks` suites. I ran them in a candidate worktree and a base worktree, restoring from git after each run, and both were clean at the end. The role-file and fixture mutants only apply to the candidate. **Candidate: 8 of 10 killed. Base: 5 of the 7 that apply are killed.** | Mutant | Edit | Base `324c064b` | Candidate | |---|---|---|---| | `verbs-reassign-not-pm` | `PM_VERBS` drops `task.reassign` | survives | killed: the new verbs line | | `broker-gated-to-arbiter` | a `gated` decision routes to the domain arbiter | killed | killed, the new bus test included | | `broker-cross-ignored` | `#classification` never returns `cross-role` | killed | killed, the new bus test included | | `broker-domain-ignored` | a cross-role decision always routes to the delivery arbiter | killed | killed, the new bus test included | | `coder-reassign-within` | `task.reassign` added to the coder's `withinRole` | n/a | killed: harness, classify, bus | | `coder-cross-empty` | the coder's `crossRole` is `[]` | n/a | killed: role, harness, classify, bus | | `world-keeps-reassign` | the `world.mjs` fixture keeps the old grant | n/a | survives, equivalent (below) | | `tools-cross-untyped` | `typedTools` ignores `crossRole` | killed | killed, now also by the new harness test | | `untyped-within-only` | `untypedActions` drops `crossRole` | survives | **survives (N1)** | | `resolve-within-unnarrowed` | `withinRole` ignores `limits.authority` | killed | killed: the narrowing test among others | `mutants.sh`'s header says the tasks test "kills nothing here". That holds for Rocko's five mutants, but the new verbs line is the only test that pins `task.reassign` in `PM_VERBS`. Under `verbs-reassign-not-pm`, a coder's `task.reassign` passes the writer check and is refused with `task-unassigned` instead. The new line catches that; on the base the four suites pass. `world-keeps-reassign` is equivalent: every tasks test that calls `task.reassign` as the coder hits `field-writer` before authority is read, and no tasks test raises a coder decision about it. ### Not blocking - **N1, nothing pins the coder's untyped list.** BUILD.md says that without a tracker the prompt no longer lists `task.reassign` among "Actions you hold that have no bus tool yet". That's true by the code, but the coder test in `tools.test.mjs` (lines 28-36) only checks `untyped.includes("git.push.working")` and `!untyped.includes("message.send")`. With `untyped-within-only` the prompt would drop every cross-role action, and the four suites still pass on both trees. A `deepEqual` of the coder's untyped list to `["task.update.assigned", "git.push.working", "review.request", "task.scope.change"]` would pin both this row's change and the cross-role half. It could go in row 79 or the next harness row. ### Gate All suites ran one after another in the review worktree, with `TMPDIR` in my scratch and Docker on, from 2026-10-11T23:31:26Z to 23:40:37Z. | Suite | Result | |---|---| | `packages/tasks` | 71 pass, 0 fail | | `packages/bus` | 81 pass, 0 fail | | `packages/business` | 60 pass, 0 fail | | `packages/harness` | 58 pass, 0 fail, 0 skipped | | cli, control-board, conversation, discord, ledger, mosaic, queue, runs, seat, webui | all 0 fail (112, 124, 182, 178, 78, 69, 150, 41, 27, 50 pass) | | build-tokens `--check` | exit 0 | | test-auth, test-conductor, test-config, test-discord, test-extension-package, test-foundation, test-queue | exit 0 (15, 17, 24, 66, 18, 44, 27 passed) | | test-release | 14 passed, 0 failed (Docker, nothing skipped) | | test-task | 98 passed, 0 failed (Docker, nothing skipped) | The manifest checked 8/8 OK before the run, and `core.hooksPath` stayed unset. Evidence (local to my scratch, `~/dewey-scratch/r73/`): `mutants.py` with `out-mutc.txt`, `out-mutb.txt` and `out/mut*/mut-*.txt`, and `gate.sh` with `gate-out/`.
Author
Contributor

Landed in 0453da7e on refactor (row 73, queue rev 553, done).

  • roles/coder.json crossRole is now ["task.scope.change"]; a coder's task.reassign classifies as gated and goes to the human (lead decision 90).
  • Author Rocko, packet agents/rocko/work/queue-73/. Candidate manifest sha256 bf4e5ed6, base 324c064b, no drift on the candidate paths.
  • Approval: Dewey, round 1, comment 27506.
  • Sage's gate on 8a42e819 (23:42-23:48Z): tasks 71, bus 81, business 60, harness 59, cli 113, webui 61, seat 27 node tests, 0 failed; every scripts/test-*.sh exit 0.
  • Dewey's N1 (pin the coder's untyped list without a tracker) goes to row 79 (#1573), brief amended in 0c1e3fe8, queue note rev 551.
Landed in 0453da7e on refactor (row 73, queue rev 553, done). - roles/coder.json crossRole is now ["task.scope.change"]; a coder's task.reassign classifies as gated and goes to the human (lead decision 90). - Author Rocko, packet agents/rocko/work/queue-73/. Candidate manifest sha256 bf4e5ed6, base 324c064b, no drift on the candidate paths. - Approval: Dewey, round 1, comment 27506. - Sage's gate on 8a42e819 (23:42-23:48Z): tasks 71, bus 81, business 60, harness 59, cli 113, webui 61, seat 27 node tests, 0 failed; every scripts/test-*.sh exit 0. - Dewey's N1 (pin the coder's untyped list without a tracker) goes to row 79 (#1573), brief amended in 0c1e3fe8, queue note rev 551.
Sign in to join this conversation.
2 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: mosaicstack/stack#1567