226d00222b
Phases 1.2 and 1.3 of multi-repository task support. The pieces are intertwined so they ship together — the preparer's per-repo loop depends on the manager being able to hold one worktree per (session, repository) pair instead of one per session. Worktree manager: - In-memory cache key changes from sessionID to (sessionID|repositoryID). - New MultiRepoStore optional capability + SQLite implementation: GetWorktreesBySessionID and GetWorktreeBySessionAndRepository. - New Manager methods: GetAllBySessionID, GetBySessionAndRepo. Existing GetBySessionID returns the first match (single-repo callers unchanged). - Manager.Create's "already exists" check is now repo-scoped so the second repo's create no longer returns the first repo's worktree. - All cache write/delete sites updated to the composite key. WorktreePreparer: - New prepareMultiRepo path activated when EnvPrepareRequest.Repositories has >=2 entries; single-repo and repo-less behavior is byte-identical. - prepareOneRepo runs validate -> sync -> create -> fetch-PR -> per-repo setup-script for each spec; rolls back already-created worktrees on any failure. - Workspace path becomes the task root (parent of any repo subdir); legacy WorktreeID/WorktreeBranch/MainRepoGitDir mirror Worktrees[0] for downstream code that hasn't been migrated yet. - Per-repo setup script runs verbatim (no script-engine resolution yet — the per-repo placeholder namespace lands in a follow-up). Tests: - Manager: GetAllBySessionID, GetBySessionAndRepo (hit + miss), GetBySessionID single-repo compat, cache key separation. - Preparer: multi-repo creates one worktree per repo; rollback removes active worktrees on partial failure; per-repo setup script runs in each worktree directory and emits its own step. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>