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 <[email protected]>
This commit is contained in:
2026-10-11 16:34:56 -05:00
co-authored by Claude Opus 5.5
parent f2f2861b7f
commit 21122c3b0e
2 changed files with 30 additions and 2 deletions
+24
View File
@@ -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 The tradeoff: the root-owned package doesn't auto-update and a
session running as the user can't rewrite it, against needing session running as the user can't rewrite it, against needing
Jason's sudo before the first PM launch. The upgrade is Jason's. 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.
+6 -2
View File
@@ -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). 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 | | 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}` | | due date, priority | pm | `task.schedule`, `task.priority.change` | `PATCH /tasks/{t}` |
| percent done | the assigned role | `task.update.assigned` | `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` | | 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}` | | 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}` | | 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}` | | 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`, A `PATCH` body carries only `title`, `description`, `due_date`,
`priority` and `percent_done`, and only the keys the action owns. Vikunja `priority` and `percent_done`, and only the keys the action owns. Vikunja