Skip to content

refactor(stack): simplify managed stack architecture - #6218

Merged
jgoux merged 78 commits into
developfrom
juliengoux/cli-2110-state-honor-explicit-config-ports-and-allocate-sticky-ports
Aug 17, 2026
Merged

refactor(stack): simplify managed stack architecture#6218
jgoux merged 78 commits into
developfrom
juliengoux/cli-2110-state-honor-explicit-config-ports-and-allocate-sticky-ports

Conversation

@jgoux

@jgoux jgoux commented Aug 16, 2026

Copy link
Copy Markdown
Contributor

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.

  • derive stack identity from the workspace, checkout, development context, canonical local-project key, and stack name, so multiple Supabase projects inside one monorepo remain isolated
  • keep automatic ports sticky per stack while respecting configured exact ports and deterministic control endpoints
  • support detached start, later-process reattachment, stop, deletion, and recovery after interrupted lifecycle operations
  • keep Docker and native execution behind the same Effect-native @supabase/stack package
  • report running configuration drift without rebinding live services

Why

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:

  • the stack document owns durable identity, sticky ports, lifecycle, launch metadata, and runtime metadata
  • the deterministic loopback endpoint owns process exclusivity and reattachment
  • the manager owns identity resolution, port planning, persistence, and repair
  • the supervisor owns runtime resources from reservation through shutdown

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 config project_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

  • the managed document format is unreleased, so this change does not add migrations or compatibility shims
  • loopback control-token authentication is deferred because the current localhost risk is low
  • a CLI repair command is deferred; the package API remains the source of truth
  • supervisor test runtimes live only in test helpers and are not accepted by production IPC
  • ordinary unit and integration suites use isolated temp state and may run concurrently; the one full-stack Functions hot-reload smoke stays in the opt-in live suite
  • coverage focuses on high-value manager, control, supervisor, storage, and real Git journeys

Follow-ups

  • CLI-2198 — remaining real-Git and project-root contract coverage
  • CLI-2199 — control diagnostics and retry-policy cleanup
  • CLI-2200 — managed list UX and nested-project deletion coverage
  • CLI-2201 — later managed workspace repair workflow
  • CLI-2202 — remaining runtime failure-path qualification
  • CLI-2203 — copied ordinary-folder identity detection

Supersedes #6202, #6214, and #6216

jgoux added 30 commits August 15, 2026 23:27
@jgoux jgoux changed the title feat(stack): allocate sticky managed ports refactor(stack): simplify managed stack architecture Aug 17, 2026

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

const loadedProjectConfig = yield* loadProjectConfig(projectHome.projectRoot);

P2 Badge Load the active remote override before deriving port intent

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".

Comment thread packages/stack/src/supervisor.ts Outdated
Comment thread packages/stack/src/managed/control.ts Outdated
Comment thread packages/stack/src/managed/manager.ts Outdated
Comment thread packages/stack/src/discovery.ts Outdated
Comment thread packages/stack/src/discovery.ts
Comment thread packages/stack/src/managed/manager.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/stack/src/HttpTransportClient.ts
Comment thread packages/stack/src/managed/environment.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/stack/src/managed/manager.ts
Comment thread apps/cli/src/next/commands/start/start.command.ts
Comment thread apps/cli/src/next/commands/branches/switch/switch.handler.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/stack/src/supervisor.ts Outdated
Comment thread packages/stack/src/platform-node.ts

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 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".

Comment thread packages/stack/src/discovery.ts
Comment thread packages/stack/src/managed/lifecycle.ts Outdated
@jgoux
jgoux added this pull request to the merge queue Aug 17, 2026
Merged via the queue into develop with commit 64d954d Aug 17, 2026
14 checks passed
@jgoux
jgoux deleted the juliengoux/cli-2110-state-honor-explicit-config-ports-and-allocate-sticky-ports branch August 17, 2026 20:00
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants