Phase 13: Workspaces, dependencies, worktrees, and local routing
Implemented
- Added a workspace domain with validated DAGs, member roles, health gates, rollback/continue policies, profiles, recipes, immutable execution snapshots, and explicit per-member progress.
- Added dependency-ordered start and reverse-order stop. Ready independent branches run concurrently within the selected profile ceiling; low-memory profiles provide dependency-closed subsets and bounded parallelism.
- Routed every child start/stop through the existing durable operation coordinator, retaining per-project serialization, cancellation, audit facts, idempotency, and workspace attribution.
- Added SQLite migrations 9 and 10 for workspace graphs/runs and registered project environments. Interrupted workspace runs reconcile before generic operation recovery without hiding already-running runtimes.
- Added explicit trusted Git worktree registration with stable environment IDs, unique Compose names, port-lease namespaces, exact leases, logical offsets, and friendly hostnames. Nested monorepo project paths are projected into each checkout rather than incorrectly using the Git root.
- Added private mode-
0600Compose override generation for exact loopback port bindings, includingdocker compose configvalidation before lifecycle use. - Added optional loopback-only HTTP
.localhostrouting with normalized host names, loopback target validation, forwarding-header removal, no-store responses, and explicit active/unavailable/conflict/disabled states. - Added reviewed post-start recipes for URLs, terminals, editors, Codex, and Claude Code. Recipe failure is reported independently and never fabricated as lifecycle success.
- Added generated REST, Go, and TypeScript contracts plus CLI, MCP, and browser adapters. MCP member scope resolves environment IDs to their trusted base project before authorization, and data removal remains admin-confirmed.
- Added a responsive workspace builder, dependency graph, profile controls, execution progress, worktree member selection, and project Git-tab environment registration. TanStack Query owns server state and visual regression covers the complete graph/progress state.
- Split Phase 13 HTTP client methods into a cohesive transport file after the original client crossed the repository’s 600-line review threshold.
Architecture decisions
No new ADR was required. The implementation follows ADR-0001’s modular-monolith dependency direction, ADR-0004’s shared generated transport contract, ADR-0005’s domain-owned SQLite boundaries, ADR-0006’s Compose isolation, ADR-0010’s thin MCP adapter, ADR-0013’s explicit permissions, and ADR-0014’s bounded/redacted responses.
Workspace coordination does not bypass runtime ownership. The workspace domain plans and records graph execution; operations serialize mutations; runtime drivers own lifecycle; environments own worktree identities; ports own exact lease evidence; and routing owns only safe local HTTP forwarding.
Safety properties
- Worktree registration is explicit and post-trust; deterministic discovery still executes no repository command.
- Every runtime worktree uses a distinct Compose and port namespace. Exact host ports are conflict-checked and observed before a route becomes active.
- Routing is disabled by default, binds only loopback, accepts only loopback
HTTP targets, and returns
503for unknown or unavailable hosts. - Bulk stop preserves runtime data unless removal and confirmation are both present. MCP additionally requires destructive capability.
- Launch recipes are typed and reviewed; no generic shell recipe or MCP shell tool exists.
Tests added
- DAG cycles, start/stop ordering, parallel branches, health gates and timeouts, rollback, continue/partial outcomes, cancellation, profiles, recipe timing, and data-preserving/destructive stop behavior.
- Workspace SQLite round trips, optimistic revisions, execution progress, restart recovery, and environment-member persistence.
- Worktree identity/allocation collisions, registration replacement, bare and removed checkouts, cancellation, exact leases, runtime route state, and nested monorepo subdirectory projection.
- Compose exact-port override permissions, validation, argument construction, and lifecycle binding evidence.
- Hostname/target validation, route conflicts, unavailable states, proxy header stripping, unknown-host rejection, and disabled routing.
- Workspace/environment HTTP handlers, CLI contracts, MCP discovery/scope/ permission behavior, and browser workspace visual regression.
Acceptance criteria status
- A workspace starts dependencies in order and independent branches in parallel, bounded by its selected profile.
- Rollback and continue behavior produce durable, visible per-project outcomes, including partial success and cancellation.
- Multiple worktrees receive collision-resistant Compose names and distinct exact port leases; tests cover simultaneous allocations and lifecycle facts.
- Friendly
.localhostURLs resolve only to the matching active environment and safely reject conflicts, inactive targets, and unknown hosts. - Bulk stop preserves data by default and requires an explicit destructive request plus confirmation before removal.
Verification evidence
make quality passed on 2026-07-16 after the final monorepo regression fix. It
covered generated-artifact drift, Go/Vue lint, architecture constraints,
TypeScript checks, every Go and web unit test, go test -race ./..., migration
from an empty database through schema version 10, govulncheck with no known
vulnerabilities, four real-runtime browser E2E tests, eight visual-regression
tests, and production Go/web builds.
The release binary then ran against an isolated /tmp data directory with API
and routing listeners on separate loopback ports. The real CLI deterministically
scanned and explicitly trusted the Compose fixture, registered its Git worktree,
created an environment-backed low-memory workspace, and read both records back
after a full daemon restart. The route listener returned 503 for an unknown
.localhost host. This live run exposed and verified the fix for nested
monorepo projects: the environment reconciled from the Git root to
test/fixtures/compose-runtime, observer errors stopped, and the corrected path
survived restart.
Known limitations and deferred work
- Local TLS and certificate management remain separate from the opt-in HTTP router, as required by the phase scope guard.
- Routing selects a validated HTTP target from exact active environment facts; non-HTTP bound services remain visible but are not proxyable.
- Worktrees are observed and registered but never created, removed, or checked out by Switchyard. Repository mutation remains outside this phase.