refactor(stack): simplify managed stack architecture - #6218
Conversation
There was a problem hiding this comment.
💡 Codex Review
When the linked active branch has a matching [remotes.<name>] block, calling loadProjectConfig without its projectRef deliberately returns the unmerged base document. Passing that document to managedPortIntents means a remote-defined api.port, db.port, or other sticky port is treated as omitted or replaced by the base value, so startup allocates a different port and status misses the corresponding drift. Resolve the active branch ref from ProjectLinkState and pass it to this load (and the equivalent status/restart loads).
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: eefc4a093b
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: a77f181c8d
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 5958f9536c
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: be018f16b5
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
Summary
Replace the managed local-stack coordination design with a smaller architecture centered on one atomic JSON document per stack, deterministic loopback ownership, and one detached supervisor.
@supabase/stackpackageWhy
The previous implementation spread these guarantees across SQLite, repository adapters, claims and publication protocols, transition state machines, operation polling, and a large contract-fixture corpus. Those layers duplicated ownership and recovery responsibilities and made ordinary user journeys difficult to follow.
The simplified model gives each invariant one owner:
Identity and monorepos
A stack key combines workspace ID, checkout ID, development-context ID, canonical local-project key, and stack name.
The local-project key is the canonical project path relative to its Git worktree, or
.for an ordinary non-Git folder. It is local identity only: it is not a remote project reference or a configproject_id.This keeps sibling Supabase projects in one repository independent, keeps the same relative project isolated across worktrees, and preserves identity when a whole worktree moves. Renaming a project directory deliberately creates a new local identity.
Lifecycle and ports
Automatic allocations avoid the deterministic control namespace and remain sticky. Explicit exact ports remain usable, including inside that namespace, unless they collide with a known stack control endpoint or an actual listener. A future identity with no document can theoretically derive an endpoint already used as an exact service port; that low-probability collision fails at control acquisition rather than requiring a global registry or forbidding 22,768 legitimate configured ports.
Exact durable reservations and automatic runtime reservations are combined behind one scoped lease while each child lease receives only the fields it owns. This keeps placeholders held until the corresponding service binds without leaking ownership assumptions across allocation strategies.
Startup, attachment, early stop, stop-during-start, start-during-stop, owner death, concurrent shutdown, deletion, and stale lifecycle recovery share one bounded ownership protocol. Node and Bun route stop through the same daemon shutdown transaction. Store listing degrades corrupt or unreadable entries independently, and read-only project discovery treats unsupported Git metadata as no managed stacks while mutating operations still fail loudly.
Moved checkouts can be repaired through the package API while preserving identity and ports; duplicate checkout adoption remains intentionally unsupported.
Deliberate boundaries
Follow-ups
Supersedes #6202, #6214, and #6216