feat(features,web,desktop): an agent with no plan is messaged, stopped, and changed like any other, its summary naming no plan

Merged
DA
4d ago
+189-93

Step 8 (second part) of the automations plan (docs/proposals/automations-scope.md). It is stacked on #2710.

What changes

  • A planless agent works through every agent route. reachedAgent admits an agent with no plan again, so message, stop, model and effort, rename, archive, MCP servers, transcript, pull request, changes, and terminals all work on one. #2663 had refused it until the wire could say so. This is what the desktop agent page needs to drive one.
  • The summary's planId is nullable. codingAgentSummarySchema.planId is now NullOr(uuid).
    • Only a read that names the agent can answer a planless one. A plan's list holds the plan's own agents, and the account Inbox keeps planless items under their own keys (#2688).
    • A build that predates planless agents never learns such an id, so it never meets a null.
    • status.ts drops the PlannedCodingAgent narrowing, the plan list and the Start answer no longer filter, and codingAgentPageSchema no longer overrides planId (the summary carries it).
  • The desktop handles a null plan in its three places:
    • The notices ledger passes over a planless agent named by a message's answer, since every read it keeps is a plan's; step 9 gives planless agents notices of their own.
    • A message refused for an unreachable repository says its words alone for a planless agent, since every remedy is pressed on a plan.
    • A test fixture.
  • Wire goldens. Only planId's schema changes, from a uuid to a uuid or null, in codingAgentSummarySchema and the four answers that carry it. They were re-recorded with LUKE_UPDATE_FIXTURES=1. None of these is a model-facing tool schema.

Tests

  • coding-agents-app.test.ts: a planless agent is messaged (eve gets the line, and the answer's summary has planId null) and its transcript is read by a member. This replaces the test that asserted 404s.
  • coding-agent-model.test.ts: a repository-unreachable refusal names the plan's remedy on a plan, and only the words for a planless agent.
  • agent-notices.test.ts: a planless agent in a message's answer reads no plan list and announces nothing. This fails without the guard.

pnpm check:affected passes. The desktop changes are type-level handling of a null plan, with no new drawing; CI cannot verify the Mac UI, and ./scripts/verify.sh was not run (LUKE-159 stands in before the first release).

🤖 Generated with Claude Code


Open workspace in Conductor


Devin Review


Summary by cubic

An agent with no plan now works through every agent route—messaged, stopped, and changed like any other—so the desktop agent page can drive one. Previously these routes refused a planless agent because the wire summary required a planId; codingAgentSummarySchema.planId is now NullOr(uuid), the summary carries it, and the plan-only filters are gone.

  • Only a read that names the agent answers a planless one: a plan's list holds the plan's own agents, and the account Inbox keeps planless items under their own keys.
  • The desktop passes over a planless agent in the notices ledger, and a repository-unreachable refusal keeps the remedy that needs no plan—giving the repository to Luke on GitHub—while saying only its words where the remedy is pressed on the plan.
  • Wire goldens were re-recorded for the nullable planId; tests replace the former 404 assertions with messaging, transcript, refusal, and notice coverage.