feat(database,web): automation scope, repositories, and run target (expand migration 1)
PR 1 of the approved automations plan (docs/proposals/automations-scope.md §4, round 3). This is the expand step only: additive, with nothing dropped.
Schema (automation):
organization_id: the workspace. Nullable for now, cascading with the workspace.scope:personalorworkspace, defaultpersonal.repositories: an ordered jsonb list ofowner/name, the first where the agent starts. It holds one entry until full multi-repo (automations-multi-repo.md).target_kind:new-agentorsame-agent.target_agent_id: the agent a Same-agent run continues, set null when that agent is deleted.archive_successful: default false.plan_idbecomes nullable, and the contract step drops it.- Index
(organization_id, scope, created_at).
Migrations:
20261014210424_automation_scope: generated, then hardened to be idempotent (IF NOT EXISTS, guarded constraints) so a preview database that ran an earlier draft folder runs it as a no-op.20261014210429_automation_scope_backfill: a custom backfill, following the precedent ofplan_organization_backfill. Each existing row takes its plan's workspace and[plan.repository]. The backfill is idempotent.
Wire (automation-wire.ts, all optional, so v0.12.0 is unaffected; it has no automations UI):
AUTOMATION_SCOPEandAUTOMATION_TARGET.- Create and change accept
scope,target({kind: new-agent}or{kind: same-agent, agentId}) andarchiveSuccessful. - The summary answers
scope,repositories,targetandarchiveSuccessful.
API:
- A new automation takes its plan's workspace and repository. Where the maker names neither scope nor target, it is personal and gets a new agent each run.
- A Same-agent target must name an agent the account can read; otherwise the request is refused as invalid.
- A workspace scope is refused in the account's personal workspace (D8).
- Who may see and change an automation by scope (D2) is the next PR. Runs don't read the target yet (PR 10).
A plan's automations follow it. updatePlan carries a plan's new workspace or repository onto its automations, in the same transaction, so a moved plan's automations never cascade away with the workspace it left. A row an older build inserted during the rollout, with no workspace and empty repositories, reads its plan's values until the contract step fills it.
Tests:
automations-app.test.ts: the defaults; Same agent plus archive round-trip; an unreadable agent refused; a workspace scope refused in a personal workspace and accepted in a team one.automation-store.test.ts: a new row takes its plan's workspace and repository; a plan given another repository and moved to another workspace takes its automations along; an older build's empty row reads its plan's values.- The migrations test and
drizzle-kit checkpass.
No Mac UI. pnpm check:affected exits 0.
š¤ Generated with Claude Code
Summary by cubic
Adds workspace ownership, scope, repositories, and run target to automations, with existing rows backfilled from their plans.
automationgainsorganization_id,scope(personal/workspace),repositories,target_kind(new-agent/same-agent),target_agent_id, andarchive_successful;plan_idbecomes nullable.- Existing rows are backfilled from their plan's workspace and repository; the backfill is idempotent, and rows an older build inserted during rollout read their plan's values until the contract step fills them.
- Create and change requests accept
scope,target, andarchiveSuccessful; all optional, so clients without the automations UI are unaffected. - A new automation defaults to personal scope with a new agent each run; a same-agent target must name an agent the account can read, and a workspace scope is refused in a personal workspace.
- Moving a plan to another workspace or repository takes its automations along.
- The migrations are idempotent and keep their original names, so a database that already ran them, or an earlier draft folder, reruns them as a no-op.