Skip to content

feat(cli): add experimental stack list - #6509

Open
jgoux wants to merge 8 commits into
feat/experimental-stack-statusfrom
feat/experimental-stack-list
Open

feat(cli): add experimental stack list#6509
jgoux wants to merge 8 commits into
feat/experimental-stack-statusfrom
feat/experimental-stack-list

Conversation

@jgoux

@jgoux jgoux commented Sep 7, 2026

Copy link
Copy Markdown
Contributor

supabase experimental stack list discovers managed stacks across branches and worktrees, including stopped and unconfigured stacks. It reports persisted identity, runtime, and desired lifecycle in a stable order, with text and structured output.

This PR builds on experimental stack status and reads the managed registry without loading project configuration or contacting stack owners.

@jgoux
jgoux requested a review from a team as a code owner September 7, 2026 23:36

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Superseded by a newer AI review

🤖 AI Review

Only Claude's independent review was available; Codex's review did not complete. All eight Claude findings were verified and confirmed. No major or critical defects were identified.

Findings

Severity Location Category Sources Claim
🟡 MINOR apps/cli/src/commands/experimental/stack/list/list.handler.ts:61 error-handling claude One unreadable registry entry aborts the entire listing, and the resulting error does not identify the affected stack directory.
🟡 MINOR apps/cli/src/commands/experimental/stack/list/list.handler.ts:56 consistency claude The legacy output-flag rejection omits an actionable suggestion, causing text output to show the generic --debug troubleshooting hint instead.
🟡 MINOR apps/cli/src/commands/experimental/stack/list/list.handler.ts:43 maintainability claude renderRuntime handles StackRuntime with a non-exhaustive fallback, so a new runtime variant would silently render its kind rather than cause a compile-time failure.
⚪ NIT apps/cli/src/commands/experimental/stack/list/list.handler.ts:21 naming claude compareCodepoint is misnamed because JavaScript string relational comparison orders UTF-16 code units rather than Unicode code points.
⚪ NIT apps/cli/src/commands/experimental/stack/list/list.command.ts:11 telemetry claude Passing empty flags and config records to withLegacyCommandInstrumentation has no effect.
⚪ NIT apps/cli/src/commands/experimental/stack/list/list.handler.ts:46 readability claude The complete multi-line stack display is embedded in one long template expression, making user-visible output harder to review and modify.
⚪ NIT apps/cli/src/commands/experimental/stack/list/list.integration.test.ts:161 test-quality claude A single test combines two independent scenarios: legacy output-flag rejection and registry-read failure.
⚪ NIT apps/cli/src/commands/experimental/stack/list/list.integration.test.ts:42 test-quality claude mutationCalls also counts read-only findStack and inspectStack calls, so its name misstates what the assertion measures.

Stats

Claude findings: 8 · Codex findings: 0 · Confirmed: 8 · Refuted: 0 · Uncertain: 0


Models: claude-opus-5 + gpt-5.6-sol · Trigger: auto · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment thread apps/cli/src/commands/experimental/stack/list/list.handler.ts
Comment thread apps/cli/src/commands/experimental/stack/list/list.handler.ts
Comment thread apps/cli/src/commands/experimental/stack/list/list.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/list/list.handler.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/list/list.command.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/list/list.handler.ts
Comment thread apps/cli/src/commands/experimental/stack/list/list.integration.test.ts Outdated
Comment thread apps/cli/src/commands/experimental/stack/list/list.integration.test.ts Outdated
@jgoux
jgoux force-pushed the feat/experimental-stack-list branch from 92e35d8 to a3e8e9b Compare September 8, 2026 05:31
@jgoux
jgoux force-pushed the feat/experimental-stack-list branch from a3e8e9b to a0e49b1 Compare September 8, 2026 06:02
@jgoux
jgoux force-pushed the feat/experimental-stack-list branch from a0e49b1 to edeccb4 Compare September 8, 2026 12:32
@github-actions

github-actions Bot commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

Supabase CLI preview

npx --yes https://pkg.pr.new/supabase/cli/supabase@edeccb4273a62bdd4e9316aaf6cf45353ec4e4cd

Preview package for commit edeccb4.

@jgoux

jgoux commented Sep 8, 2026

Copy link
Copy Markdown
Contributor Author

/ai-review

@github-actions github-actions Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🤖 AI Review

Only Claude's independent review was available; the Codex pass did not complete. Three findings are confirmed: one minor telemetry classification issue and two test-quality issues. Two findings are refuted because fail-closed discovery is deliberate existing behavior and the empty JSON case adds no distinct branch beyond existing coverage.

Findings

Severity Location Category Sources Claim
🟡 MINOR apps/cli/src/commands/experimental/stack/list/list.handler.ts:34 error-handling claude All stack-discovery failures are classified as invalid configuration, including registry filesystem and permission failures.
🟡 MINOR apps/cli/src/commands/experimental/stack/list/list.integration.test.ts:172 test-coverage claude The two error tests can pass with an unexpected error type because their substantive assertions are conditional on instanceof LegacyExperimentalStackListError without asserting that type.
⚪ NIT packages/stack/src/public/effect-stack.integration.test.ts:1015 test-quality claude The new failure-inspection block duplicates the immediately preceding StackStateInvalidError assertion.
Refuted findings (kept for transparency, not posted as review comments)
  • packages/stack/src/public/EffectStack.ts:1101 (reliability): A single unreadable or unsupported registry entry aborts the entire list operation and prevents healthy stacks from being returned.
    Refuted: The propagation is deliberate fail-closed behavior, not introduced by this change. trusted/packages/stack/src/public/EffectStack.ts:1089-1091 already propagates every read failure except the explicitly recoverable remnant case, and trusted/packages/stack/src/public/effect-stack.integration.test.ts:967-987 explicitly verifies that durable missing-state remnants remain fail-closed. The PR preserves that contract while adding stack-id context.
  • apps/cli/src/commands/experimental/stack/list/list.integration.test.ts:152 (test-coverage): There is no dedicated test for an empty registry using JSON output.
    Refuted: There is no distinct empty-JSON implementation branch to leave untested. apps/cli/src/commands/experimental/stack/list/list.handler.ts:77-78 sends every non-text result through the same output.success call, already exercised by the structured-output test at :116-136, while the empty-array result is independently exercised at :152-159.

Stats

Claude findings: 5 · Codex findings: 0 · Confirmed: 3 · Refuted: 2 · Uncertain: 0


Models: claude-opus-5 + gpt-5.6-sol · Trigger: manual · Workflow run

This review runs once per PR. A maintainer can request another with a /ai-review comment.

Comment on lines +34 to +41
const mapStackError = (error: StackDiscoveryError) =>
new LegacyExperimentalStackListError({
reason: "invalid-config",
message: error.message,
suggestion:
"Inspect the managed stack registry under $SUPABASE_HOME/managed/stacks or ~/.supabase/managed/stacks.",
cause: error,
});

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MINOR · error-handling · source: claude

All stack-discovery failures are classified as invalid configuration, including registry filesystem and permission failures.

Evidence: apps/cli/src/commands/experimental/stack/list/list.handler.ts:34-41 always assigns reason "invalid-config". packages/stack/src/public/EffectStack.ts:1089-1097 converts failures from exists/readDirectory into StackStateInvalidError, so platform I/O failures reach that classification.

Suggested fix: Preserve enough platform-error information in the stack API to distinguish registry I/O failures, then give those failures a non-configuration actionability and targeted filesystem guidance.

Comment on lines +172 to +176
if (Option.isSome(error) && error.value instanceof LegacyExperimentalStackListError) {
expect(error.value.message).toContain("legacy -o/--output flag");
expect(error.value.suggestion).toContain("--output-format");
expect(error.value[ErrorActionabilityId]).toEqual(actionability.provideFlags);
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

🟡 MINOR · test-coverage · source: claude

The two error tests can pass with an unexpected error type because their substantive assertions are conditional on instanceof LegacyExperimentalStackListError without asserting that type.

Evidence: apps/cli/src/commands/experimental/stack/list/list.integration.test.ts:169-177 and :199-208 assert only that some error exists before conditionally entering the expected-type branch.

Suggested fix: Assert toBeInstanceOf(LegacyExperimentalStackListError) before narrowing in both tests.

Comment on lines +1015 to +1025
if (Exit.isFailure(listed)) {
const error = Cause.findErrorOption(listed.cause);
expect(Option.isSome(error)).toBe(true);
if (Option.isSome(error)) {
expect(error.value).toBeInstanceOf(StackStateInvalidError);
if (error.value instanceof StackStateInvalidError) {
expect(error.value.stackId).toBe(orphanId);
expect(error.value.message).toContain(orphanId);
}
}
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

⚪ NIT · test-quality · source: claude

The new failure-inspection block duplicates the immediately preceding StackStateInvalidError assertion.

Evidence: packages/stack/src/public/effect-stack.integration.test.ts:1009-1014 already extracts the failure and asserts StackStateInvalidError; :1015-1025 repeats both operations before checking stackId and message.

Suggested fix: Remove the older assertion block and retain the new narrowed block containing the additional checks.

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.

1 participant