feat(database,web): an agent with no plan is reached through its own workspace, and the tools that need a plan refuse it
Merged
DA
6d ago+238+238+012345678901234567890123456789-68-68-01234567890123456789
Step 3 of the automations plan (docs/proposals/automations-scope.md). It builds on #2637 (merged), which gave coding_agent its own organization_id and made plan_id optional.
What changes
- Agents are reached through their workspace, not their plan.
agentReachableBynow checks membership of the agent's workspace: its ownorganization_id, or its plan's on a row the backfill hasn't reached. An agent on a plan is reached exactly as before, because #2637's plan move carries the agent's workspace along. An agent an automation starts with no plan (from step 4 on) is reached by every member of its workspace and by no one else.CodingAgentnow carriesorganizationId, andplanIdisstring | null. - eve admits a planless agent's session.
namedByReachableWork(recorded-session.ts) gates an agent's conversation on the sameagentReachableByrule, now kept inworkspace-store.tsbesideplanReachableBy. eve's ownership check and turn admission therefore take a planless agent's session for any member of its workspace. - The workspace hops follow the agent.
agentWorkspaceresolves the installation used for checkout, the published PR read, repository skills, and steer: the plan's workspace for an agent on a plan, otherwise the agent's own workspace while the caller is still a member. - Tools that need a plan refuse a planless agent:
edit_plananswers its existingNO_PLAN.- The Inbox tools and
show_pageanswer a newPLANLESSrefusal that tells the agent what to do instead. - Step 5 gives planless agents their Inbox, and the Inbox refusal goes away then.
- Nothing on the wire changes yet. Summaries, the plan's agent list, and the agent lines in the plan list keep naming a plan, so planless agents are left out of them.
reachedAgentrefuses a planless agent as not found before any agent route acts, so nothing lands only to answer 404. Both hold until step 7 makes the wire'splanIdoptional. No planless agent exists until step 4, so v0.12.0 and v0.13.0 see no difference.
Tests
coding-agent-store.test.ts: a planless agent is read by a teammate who didn't start it, and reads as none for an account outside the workspace. This fails before the change, because the old reach required a plan row.- The same test asserts
conversationReachableByis true for the starter and a teammate and false for an outsider. It fails without therecorded-session.tschange. coding-agents-app.test.ts: a planless agent's message and transcript routes answer 404, and eve is sent nothing. This fails without theagent-reach.tschange.- Existing coder-host, steer, terminal, and Inbox tests pass unchanged.
pnpm check:affected passes. This change is server-only; 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