Uh oh!
There was an error while loading. Please reload this page.
feat(stack): add managed stack persistence - #6152
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:ec4c93fdb1
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Supabase CLI previewnpx --yes https://pkg.pr.new/supabase/cli/supabase@b060d05441971f615d9f93abc6074cb7b2e5934fPreview package for commit |
…metry - apply requested configuration after awaiting pending publication - trim whitespace in managed state-root environment fallbacks - reject updates to tombstoned stacks in both repository adapters - add coded errors for invalid stack names and unstopped deletion - register managed stack errors in CLI error-actionability telemetry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit:6f9b2e6a36
ℹ️ 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".
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
…nputs - dispatch managed stack errors to their actionability adapter by stable code - add coded InvalidManagedPortError for port validation failures - resolve injected managed state roots to absolute paths at the boundary Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
- guard empty state roots, tombstoned reconciliation, pending updates, and owner pids - recurse initialization causes and link managed error codes mechanically - isolate the in-memory repository to the testing entrypoint and share entrypoint plumbing - align adapter ordering, split fingerprint suffixes, batch port reads - drop dead repository surface and unused context columns (schema v3) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
- filter corrupt owner pids on the provision liveness path - reclaim tombstoned deletions without requiring runtime inspection - fail fast on blank explicit state roots and honor configured poll intervals - report reclaimed stacks only after successful data removal - align port ordering, operation ordering, and owner-pid validation across adapters Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Uh oh!
There was an error while loading. Please reload this page.
…te roots - treat a concurrently resolved delete claim as success after data removal - reject undefined state roots at the service boundary - document forced-recovery tombstone semantics and reclaim asymmetry - drop load-sensitive timing assertions from integration tests Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Uh oh!
There was an error while loading. Please reload this page.
- create the registry directory and stack state directories with mode 0o700 - chmod the registry database to 0o600 before WAL sidecars are created - assert owner-only modes in an integration test Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Uh oh!
There was an error while loading. Please reload this page.
…tomically - pre-create the database file with mode 0o600 so it never exists with umask-derived permissions - retighten a registry file or directory left looser by an earlier build Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
- convert the managed error hierarchy to Data.TaggedError with stable codes - generate tag-keyed telemetry dispatch from the managed-model contract - replace the base class with a union type and runtime guard Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- model the repository and service as Context.Service layers with typed errors - scope SQLite handles, run transactions as effects, and schedule publication polling - keep the Promise facade as a thin ManagedRuntime edge with an unchanged API Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…hitecture - adopt @effect/vitest with an Effect-surface integration suite - document the Effect-native managed architecture and its Promise edge Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- construct the facade through the effect runtime with typed rejections - make handle reads promise-returning and support await-using disposal - replace the blocking WAL contention retry with a scheduled effect retry Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Uh oh!
There was an error while loading. Please reload this page.
…n the managed core - run SQLite transactions as single synchronous blocks immune to fiber preemption - make provisioning and deletion compensation uninterruptible and interrupt-transparent - bridge thenable callbacks, surface layer errors honestly, and export the composed layer Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
You have reached your Codex usage limits for code reviews. You can see your limits in the Codex usage dashboard. |
Uh oh!
There was an error while loading. Please reload this page.
…base#6166) Resolves the deferred hygiene items from the CLI-2106 review cycle (CLI-2174). Follow-up to supabase#6152 (originally stacked on it; rebased onto `develop` after its squash-merge). Supersedes supabase#6163, which GitHub closed during a head-branch rename to the Linear-prescribed name. ## Items 2–5 (original hygiene set) - **Shared atomic claim primitive** (items 2+3): the duplicated temp-write → `link()` → `EEXIST` protocol in `managed/identity.ts` and `StateManager.ts` is extracted into `managed/atomic-claim.ts` as a plain-async primitive; Effect callers wrap it. Each call site keeps its own race semantics (identity re-reads the winning marker, StateManager fails with `StateClaimError`). - **Hardlink-less filesystem fallback** (item 3): when `link()` refuses with `EPERM`/`ENOTSUP` (exFAT, FAT32, some network mounts), the claim falls back to an exclusive `writeFile(..., { flag: "wx" })`, which still settles the race. The link-first rationale and the harmlessness of a SIGKILL-stranded `.tmp.<id>` sibling are documented on the primitive. - **Transaction reentrancy guard** (item 4): `runTransaction` in `managed/sqlite.ts` now refuses a nested call before issuing `BEGIN` — and without issuing `ROLLBACK` — so an inner attempt can never discard the outer transaction's writes. Tracked per handle via a `WeakSet`. - **Coverage-guard comment parsing** (item 5): `error-actionability-coverage.unit.test.ts` strips comments and masks string/template-literal contents (scanning interpolation expressions as code) before looking for error-class definitions, so commented or quoted `class X extends Error` text no longer trips the guard. ## Items 7–12 (Effect-refactor verification follow-ups) - **Explicit closed flag** (item 7): the facade's post-close guard branches on a `closed` flag set by `close()`/`asyncDispose` instead of sniffing "disposed" out of rejection text, so a callback's own rejection is reported as itself. - **Original failure preserved through claim release** (item 8): a new `releasingClaimOnFailure` combinator on the catch paths of `updateStackRecord`/`deleteStack` discards anything the release raises (interruption included) and re-raises the original cause; the interrupt re-raise stays scoped to the recording site. - **Publication-poll runtime guard** (item 9): the poll's final answer is checked at runtime; a bounded schedule ending on `None` dies with a clear message instead of silently yielding `undefined`. - **No fabricated report entries from interrupts** (item 10): the liveness-probe, runtime-inspection, and state-reclamation absorption points re-raise interrupt-only causes instead of recording them. - **Claim-before-mask contract gap documented** (item 11): the provision mask now carries a comment pinning the constraint (sync adapters have no suspension point; the mask must extend over row creation before async repositories become real), cross-referencing the same shape in `deleteStack`. - **`migrateSchema` reuses `runTransaction`** (item 12): migration no longer hand-rolls `BEGIN`/`COMMIT`; it runs on a freshly opened handle before any repository transaction exists, so the new reentrancy guard is not tripped. ## Items resolved without code - **Item 1 (synchronous cold-start WAL retry)**: already fixed on the CLI-2106 branch — WAL conversion now retries via an Effect `Schedule.exponential` instead of a blocking `Atomics.wait`. - **Item 6 (`credentials.*` fixture ownership)**: no existing issue owns credential-reference resolution; proposed CLI-2114 (first CLI slice wiring the managed layer) as the owner on Linear. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
…upabase#6171) Implements [CLI-2107](https://linear.app/supabase/issue/CLI-2107/state-isolate-sibling-worktrees-and-named-stacks-end-to-end): extends the managed-state baseline (supabase#6152) so linked worktrees, ordinary Git checkouts, bare-repository worktrees, branches, and named stacks coexist without sharing mutable runtime state. All identity and isolation policy lives in `@supabase/stack/managed`; no CLI handler changes. ## Git identity storage - **Workspace inspection** (`managed/git.ts`): classifies primary checkouts, linked worktrees, bare-repo worktrees, and ordinary folders by parsing Git metadata files directly (`.git` file/dir, `commondir`, `HEAD`) — read-only inspection performs zero writes and needs no `git` binary. Repositories using the reftable ref backend are refused with a typed `UnsupportedGitWorkspaceError` instead of silently collapsing branch contexts (their `HEAD` compat stub always names `refs/heads/.invalid`). - **Project ID** lives in common-scope git config (`supabase.projectId` in `<commonDir>/config`), so all linked worktrees — including worktrees of a bare repository with no primary worktree — share it, and a fresh `git clone` receives new identity for free (clone copies no config). - **Checkout ID** lives in a versioned JSON marker under each checkout's own git directory (`<gitDir>/supabase-checkout.json`), so every worktree is an independent checkout. - **Branch context IDs** live in `branch.<name>.supabaseContextId` (common scope): worktrees on the same branch share a context, `git branch -m` carries the ID with the section rename, and branch deletion orphans the context without touching stack data. - Config claims use append-and-adopt-first-value (`git config --add`, re-read, adopt the immutable first value, idempotent collapse) with lock-contention retries — a plain set-then-reread protocol demonstrably loses claims under concurrency. - Identity is never inferred from remotes, branch names, commits, basenames, or path hashes. ## Registry schema v4 Branch contexts are project-scoped; detached and workspace contexts are checkout-scoped (partial unique index per checkout). Checkouts record their kind, and each checkout has exactly one canonical location keyed to the checkout **root** (starting from a nested subdirectory resolves and reuses the same location). The live-stack uniqueness keystone `(checkout_id, context_id, name)` is unchanged. The registry file is now `registry-v4.sqlite3`; as with v3, this unreleased POC has no data-migration path. ## resolveStack `resolveStack({ workspacePath, stackName?, operation: "start" | "status" })` is the single identity/decision path — `provisionOrdinaryStack`/`inspectOrdinaryWorkspace` are folded in, not layered over. `status` is strictly read-only (no markers, no config keys, no registry rows); `start` ensures identities and provisions through the existing pending→publish/operation-claim machinery. Interrupt-safety around claim creation was tightened so an op-boundary interrupt cannot leak a pending stack with a live operation claim. Stack names are validated as lowercase DNS labels before any write. `deleteStack`/`updateStack`/`inspectStack`/`listStacks` remain global-by-opaque-ID with no workspace resolution required, and projections now expose full IDs, checkout kind/path, context kind/branch locator, ports, and lifecycle so every sibling instance is deterministically distinguishable. ## Fixtures made executable The CLI-2102 worktree, bare-repo, named-stack, stack-name, and reclamation fixtures in `managed-stack-contract.ts` are now driven through the real service against **both** registry adapters using real git repos/worktrees in temp dirs. Symbolic fixture IDs are checked as equality/inequality relations (shared symbol ⇒ same real UUID, distinct symbols ⇒ distinct UUIDs), so editing fixture data changes test behavior. A three-sibling end-to-end proof (two worktrees + one named stack) shows distinct data roots and ports, and that a global delete-by-ID leaves the survivors' records, ports, and data untouched. ## Reviewer notes - `when` actions expressed as CLI argv in fixtures are driven through their managed-API equivalents; CLI command wiring and human/JSON rendering are later issues, per the issue's implementation boundary. - Duplicate-copy claims, branch-copy collisions, and moved-worktree recovery remain with CLI-2108. - The fixture `identity.valid-stack-names-resolve-deterministically` names a `resolveStackNames` method that does not exist; it is honestly expressed as per-name read-only `resolveStack` calls (zero-write witnessed). A fixture cleanup could rename the method or add the missing `stack` given-facts. - Pre-existing (at HEAD, not introduced here): a failed managed-service handle acquisition leaks the opened SQLite handle; tracked as a follow-up outside this PR. 🤖 Generated with [Claude Code](https://claude.com/claude-code) --------- Co-authored-by: Claude Fable 5 <noreply@anthropic.com>
Summary
Why
CLI-2106 establishes the M2 persistence boundary for managed local stacks. It gives later CLI work a runtime-independent source of truth while keeping ordinary project folders limited to a small identity marker and keeping credentials out of the registry.