From 21122c3b0e836ebcba368f2e6483aebc285bef08 Mon Sep 17 00:00:00 2001 From: Jason Woltje Date: Sun, 11 Oct 2026 16:34:56 -0500 Subject: [PATCH] docs(plans): slice 1 field table follows the code for comments and title (lead decision 90, #1550) Darkwing found, reading ahead on row 61, that message.send never writes a tracker comment and that task.scope.change has no writer named. The prose moves to what the verbs enforce; row 61 rules out changing writers. Co-Authored-By: Claude Opus 5.5 --- docs/plans/2026-09-26_lead-decisions.md | 24 ++++++++++++++++++++++++ docs/plans/2026-10-04_slice-1.md | 8 ++++++-- 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/docs/plans/2026-09-26_lead-decisions.md b/docs/plans/2026-09-26_lead-decisions.md index fa84db257..109eb8365 100644 --- a/docs/plans/2026-09-26_lead-decisions.md +++ b/docs/plans/2026-09-26_lead-decisions.md @@ -1895,3 +1895,27 @@ which stay with him. Each item names who decided it and what happened. The tradeoff: the root-owned package doesn't auto-update and a session running as the user can't rewrite it, against needing Jason's sudo before the first PM launch. The upgrade is Jason's. +90. **The slice 1 field table follows the code for comments and for + title and description (2026-10-11).** Darkwing, reading ahead on row + 61 (#1550), found the prose and the task verbs disagree. Row 61's + brief keeps the prose as the reviewed source and rules out changing + who may write a field, so the prose moves, not the code. + - Comments. The prose said any role on the task, through + `task.update.assigned` and `message.send`. `message.send` writes a + bus message and never calls the tracker. The only comment writer is + `task.update.assigned`, which refuses `not-assigned` unless the + caller's bot is an assignee. The row now says the assigned role. + - Title and description. The prose named no writer after create. The + verb gate refuses only the pm verbs to other roles, and + `task.scope.change` isn't one, so any role whose authority lists it + writes, with a resolved decision since every grant is cross-role. + Today that's pm, cto and coder. Nothing checks "after assignment", + and that reading is dropped. + - Assignee stays pm only. `roles/coder.json` grants `task.reassign` + cross-role, which always ends in `field-writer`. That dead grant is + a roles cleanup for its own row with a reviewed commit, not part of + row 61. + - The tradeoff: a narrower comment writer than the design meant. A + reviewer who isn't assigned can't comment on the task through the + bus. If slice 1 acceptance needs that, it is a new verb or a + change to `task.update.assigned`, decided then. diff --git a/docs/plans/2026-10-04_slice-1.md b/docs/plans/2026-10-04_slice-1.md index 72d11de21..c8dfaee06 100644 --- a/docs/plans/2026-10-04_slice-1.md +++ b/docs/plans/2026-10-04_slice-1.md @@ -59,9 +59,13 @@ REQ-CRED-2 cover the service tokens, Gitea and Vikunja. From addendum B section 4. The broker's task verbs enforce it (REQ-TASK-1). +The title, description and comments rows were corrected to what the code +enforces on 2026-10-11 (lead decision 90). `message.send` is a bus +message and never writes a tracker comment. + | Field | Writer | Action | Vikunja call | |---|---|---|---| -| title, description | pm at create; after assignment only through a resolved `task.scope.change` | `task.create`, `task.scope.change` | `POST /projects/{p}/tasks`; `PATCH /tasks/{t}` | +| title, description | pm at create; afterwards a role whose authority lists `task.scope.change` (pm, cto and coder today, each cross-role), with a resolved decision | `task.create`, `task.scope.change` | `POST /projects/{p}/tasks`; `PATCH /tasks/{t}` | | due date, priority | pm | `task.schedule`, `task.priority.change` | `PATCH /tasks/{t}` | | percent done | the assigned role | `task.update.assigned` | `PATCH /tasks/{t}` | | state (bucket) other than `done` | the assigned role | `task.update.assigned` | `PUT /projects/{p}/views/{k}/buckets/{b}/tasks` | @@ -69,7 +73,7 @@ From addendum B section 4. The broker's task verbs enforce it (REQ-TASK-1). | assignee | pm | `task.assign`, `task.reassign` | `POST /tasks/{t}/assignees`; `DELETE /tasks/{t}/assignees/{u}` | | labels | pm | `task.create`, `task.schedule` | `POST /tasks/{t}/labels`; `DELETE /tasks/{t}/labels/{l}` | | relations | pm | `task.create`, `task.schedule` | `POST /tasks/{t}/relations`; `DELETE /tasks/{t}/relations/{kind}/{other}` | -| comments | any role on the task, append only | `task.update.assigned`, `message.send` | `POST /tasks/{t}/comments` | +| comments | the assigned role, append only | `task.update.assigned` | `POST /tasks/{t}/comments` | A `PATCH` body carries only `title`, `description`, `due_date`, `priority` and `percent_done`, and only the keys the action owns. Vikunja