Repository navigation
Add comments on tasks, with the person or agent that wrote each one - #545
alex-clickhouse wants to merge 1 commit into
Conversation
People and the agent can now add comments to a task. Each comment
records who wrote it and on whose behalf, like the other attributed
writes: a person through the UI or REST is both, and the agent is the
system actor writing for the cause of its session. The UI shows
"Nerve for <person>" for an agent comment.
Storage: migration v060 adds the table task_comments and the column
tasks.comment_count. Comments are not in the task's markdown file,
because a file cannot hold a trustworthy author and an agent that
rewrites the file would rewrite the comments too. Adding or deleting a
comment also updates comment_count, updated_at and revision in the same
transaction. Thus the count is on every task row, the task_updated
broadcast refreshes open task views, and an agent that read the task
before the comment gets a revision conflict on a guarded write.
Agent: the new tool task_comment adds a comment. task_read shows the
newest 50 comments in a marked block before the revision line, and
task_write strips that block, so a read-edit-write round trip does not
copy comments into the file. task_read indents each file line that
starts with "<!-- nerve:", so only Nerve's own lines start with a
marker: file content cannot pose as comments or be removed by the strip.
REST: GET, POST and DELETE on /api/tasks/{id}/comments. POST goes
through the task_comment handler. Only the author of a comment can
delete it, because accounts have no roles.
UI: the task detail shows the comments below the content in preview
mode, with a box to add one and a delete button on your own comments.
Board and list cards show the comment count.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
Nerve PR review · ✅ Ready to merge This PR adds attributed comments on tasks. Comments go in a Completeness: 19 backend and 7 frontend tests; docs ( Worth considering:
Checked: 866 task/DB/attribution/registry tests in an offline sandbox at |
Builds on #541 (merged), which added the plan section to the task detail.
What
People and the agent can add comments to a task. Each comment shows who wrote it:
The task detail shows the comments below the task content, with a box to add one. A delete button shows on your own comments only. Board and list cards show the comment count.
The agent gets a new tool,
task_comment.task_readshows the newest 50 comments.Why
Tasks had no place for discussion. The only options were to edit the task body or to use
task_update(note=...). Neither one records who wrote the text. On an instance with more than one person, the reader cannot tell who asked for what.How
Storage. Migration v060 adds the table
task_comments(id,task_id,body,actor_id,caused_by_actor_id,created_at) and the columntasks.comment_count. The two actor columns follow the existing attribution model (nerve/identity.py, registered innerve/db/actor_columns.py):Comments are not in the task's markdown file. A file cannot hold a trustworthy author, and an agent that rewrites the file would rewrite the comments too.
The task row. Adding or deleting a comment also updates
comment_count,updated_atandrevision, in the same transaction:comment_countputs the count on every task row, so the board needs no extra query.updated_atlets the existingtask_updatedbroadcast refresh open task views.TaskCommentsreads the comments again whenupdated_atchanges, the same wayTaskPlandoes. A comment by another person or by the agent shows without a reload.revisionchanges becausetask_readshows comments. An agent that read the task before a new comment gets a conflict on anexpect_revisionwrite, and reads the task again.Agent.
task_comment(task_id, body)adds a comment.task_readputs the comments between two marker lines, before the revision line.task_writeremoves that block, so a read-edit-write round trip does not copy comments into the file. Each comment line is indented, so comment text cannot match a marker.REST.
GET /api/tasks/{id}/commentsPOST /api/tasks/{id}/comments: goes through thetask_commenthandler, likePOST /api/tasksgoes throughtask_create. Returns 404 for an unknown task and 422 for an empty body or a body longer than 10,000 characters.DELETE /api/tasks/{id}/comments/{comment_id}: only the author can delete. Accounts have no roles, so no person can delete the words of another. Returns 403 for anybody else. Comments cannot be edited.UI. New
TaskCommentscomponent inTaskDetailBody, in preview mode, below the content. Both the full page and the board modal show it. It usesActorAttributionfor authors andMarkdownContentfor bodies. Ctrl+Enter or Cmd+Enter sends.BoardCardandTaskCardshow the count.Not in this PR: editing, mentions, notifications, threads, comments in search, and waking the agent when a person comments. The agent sees a new comment the next time it reads the task.
Merge note
PR 3A of the user-test fixes (
alex/fb-plan-links, not opened yet) also adds a migration, v059. This PR uses v060. Whichever of the two merges second must have its migration numbered above the other one (scripts/check_migration_numbers.pyenforces it).Testing
tests/test_task_comments.py(19 tests): migration rerun; counter,updated_atandrevisionon add and delete; rollback when the foreign key refuses an actor; REST attribution, 404, 422, author-only delete; agent attribution (system actor for the session's cause);task_readblock, authors and the 50 limit;task_writeround trip, including a comment that contains the end marker; a task file that contains marker lines and a fake comments block; a guarded write that a new comment refuses.test_tool_registry.pylists the new tool. The existingtest_the_registry_lists_every_attribution_columncovers the two new columns.ACTOR_COLUMNS; it now checks membership.npm run buildclean;npm test1005 passed (the base has 998; 7 new inTaskComments.test.tsx). eslint finds no new problems.🤖 Generated with Claude Code