Skip to content

Plans and tasks link up: plan notifications, plan links, backlog and plan review statuses - #542

Open
alex-clickhouse wants to merge 5 commits into
mainfrom
alex/fb-plan-links
Open

alex-clickhouse wants to merge 5 commits into
mainfrom
alex/fb-plan-links

Conversation

@alex-clickhouse

Copy link
Copy Markdown
Collaborator

A proposed plan was easy to miss: plan_propose sent no notification, agents sent a
free-text notify with no link, and task notes named plans as plain text.

What changes:

  • New statuses. Migration v059 adds backlog ("Backlog") and plan_review ("Plan in
    review", protected). backlog goes before pending, plan_review after it; other
    statuses keep their order. No built-in job selects backlog.
  • Plan review status. plan_propose and plan_update move a pending, backlog or
    in_progress task to plan_review. A task in a custom status keeps it. Approve moves
    the task to in_progress, a revision request keeps plan_review, decline closes it.
  • One notification per plan. The plan tools send "Plan ready for review: " with
    plan_id and task_id in the metadata. A new version replaces the older card, approve
    and decline dismiss it, and it makes no sound during quiet hours. The notifications page and the toast show
    "Open plan" and "Open task". Telegram shows an "Open plan" button that opens the plan
    card of /plans. Prompts, templates and guides no longer ask the agent to notify
    after plan_propose, and the tool result tells it not to.
  • Links in notes and bodies. Task notes from the plan tools link to /plans/<id> and
    /chat/<session>. Notification bodies render as markdown. App links open in place.
  • New Task dialog. A status picker, default backlog, with a hint that the agent can
    pick up pending tasks. The agent's task_create default stays pending.
  • Docs. docs/tasks.md, docs/plans.md and the worker guide describe the statuses
    and the flow.

Verification: full backend suite (6687 collected, all pass; the plan and notification
tests again after the review fixes), npm run build, npm test (1002 pass), migration
number check. Screenshots of the toast, the notifications page,
task notes and the dialog in light and dark.

Known gaps: an install from before keeps its old task-planner prompt in system.yaml
until the Automation step writes the file again, so its planner can still plan a
backlog task and still asks the agent to notify (the tool result tells it not to).
Slack has no link to the plan (no web UI address is configured).

🤖 Generated with Claude Code

alex-clickhouse and others added 5 commits October 21, 2026 17:09
Migration v059 adds two built-in statuses. `backlog` is for a task that
is not ready for work: no built-in cron job or gate selects it, so the
agent does not pick it up. `plan_review` means that a plan for the task
waits for a human decision; it is protected, because the plan tools
depend on it. `backlog` goes before `pending` and `plan_review` after
it. The other statuses keep their order, and a status that already has
one of the names stays as it is.

The New Task dialog gets a status picker with the configured statuses.
It starts on `backlog`, or on the status of the board column that
opened it, and falls back to `pending` when there is no `backlog`. A
hint says that the agent can pick up tasks in `pending`. The default of
the agent's `task_create` stays `pending`.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`plan_propose` and `plan_update` move a `pending`, `backlog` or
`in_progress` task to `plan_review`. A task in a custom status stays
there. The move names the task revision that was read, so a status that
another writer set in the meantime stays too. Approve still moves the
task to `in_progress`, a revision request keeps `plan_review`, and
decline still closes the task. The tool result says when the task moved.

The task notes that the plan tools and the plan service write use
markdown links: `[plan-<id>](/plans/plan-<id>)` for plans and
`[impl-<id>](/chat/impl-<id>)` for the implementation session. The
shared markdown renderer opens a link to a path in the app through the
router and other links in a new tab, so these notes open the plan or
the chat in place on the task page.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
`plan_propose` and `plan_update` send one notification themselves:
"Plan ready for review: <task title>", priority high, with `plan_id`
and `task_id` in its metadata. `send_notification` takes the metadata,
stores it on the row and sends it with the web event, also for a
silenced row. The notifications page and the toast show "Open plan" and
"Open task" for such a row. Telegram adds an "Open plan" button that
sends the `plan:view:` callback of the `/plans` command, so the plan and
its review actions open in the chat. Slack and the hosted channels have
no web UI address, so they show the plan id in the body only.

Notification bodies render as markdown through the shared renderer, so
links work and app links open in place. A single line break stays a line
break.

The planner, skill-extractor and skill-reviser prompts, the templates and
the guides no longer tell the agent to `notify` after `plan_propose`, so
the user gets one notification for a plan. The tool result says that the
notification was sent, which also covers prompts that an install wrote
before. The task planner lists only `pending` tasks, so it leaves
`backlog` alone. The worker guide uses the built-in `plan_review` for a
plan that waits, and keeps a custom status only for other waits, such as
a PR review.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
A new plan version dismissed nothing, so each revision left another
pending "Plan ready for review" card, and the older ones opened
superseded plans. The plan notification now dismisses the task's
pending plan notifications before it is sent, and approve and decline
dismiss the last one. A plan notification is a `notify` row whose
metadata names a plan and the task.

The tools send the notification on their own, so the agent can no
longer hold it back in quiet hours. It is now sent without sound during
quiet hours, as the task escalation reminders are.

The tool result no longer tells the agent to write a relative plan
link: Telegram and Slack cannot open it. TOOLS.md limits that link form
to the web UI.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
The markdown renderer sent every link that starts with `/` through the
router. A link to `/api/...`, such as a file download, then replaced the
page with an empty route. Server URLs open in a new tab again.

The toast body lost a margin class that had no effect. The worker guide
describes `plan_update` once. docs/tasks.md says that an install from
before keeps its old task-planner prompt, which can still plan a
`backlog` task, until the Automation step writes `system.yaml` again.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@nerveai

nerveai commented Oct 21, 2026

Copy link
Copy Markdown

Nerve PR review · ✅ Ready to merge

This closes a real gap in the plan loop. Proposing a plan now moves the task to a protected plan_review status and sends one notification with links: "Open plan"/"Open task" on the web, and a Telegram button into the existing /plans card. It goes out silent in quiet hours, and approve or decline dismisses it. The logic sits in the shared plan handlers and plan_service, so all three tool paths and both backends get it, and every ctx factory passes notification_service. Because a planned task leaves pending, the task-planner gate also stops firing for tasks that already have a plan.

Completeness: 15 flow tests cover the revision-checked move, keeping a custom status, dismissal on a decision, a silenced row and the Telegram button. Migration v059 is unique among open PRs (#545 and the stacked #547 use v060). Docs, both template sets and the goldens are updated, and the system.yaml upgrade gap is disclosed.

Worth considering:

  • nerve/agent/plan_service.py:418: the dismissal runs unguarded between the committed implementing claim and the dispatch at :439. If that write raises, the plan stays implementing with nothing running and cannot be approved again. Wrap it as _notify_plan_ready does (handlers/plans.py:76-87), or move it after the dispatch.

Checked: full backend suite in an offline sandbox at 314751e, in 3 chunks without test_slack_integration.py: 6638 passed, 38 skipped. Read plan_service, the plan handlers, the notification service and store, v059, the Telegram plan callbacks and the web diff. Frontend not run locally (CI frontend build green). Merges cleanly with current main and with #490 · automated review by nerveai — mention @nerveai to ask a follow-up.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants