Make new project setup agent-driven#2211
Conversation
📝 WalkthroughWalkthroughAdds project-configuration launch prompt support: DB schema, TRPC endpoints to read/write the prompt, a renderable prompt/template, a self-managing Node CLI and wrapper, UI/settings to edit the prompt, integration into agent setup, and modal-based project opening flows. Changes
Sequence Diagram(s)sequenceDiagram
autonumber
participant User as "User (UI)"
participant Renderer as "Renderer (NewWorkspaceModal / PromptGroup)"
participant TRPC as "TRPC Server (settings router)"
participant DB as "Local DB (settings)"
participant AgentSetup as "Agent Setup / Launcher"
participant FS as "Filesystem (CLI & wrapper)"
User->>Renderer: create/open project (select agent, provide prompt)
Renderer->>TRPC: query getProjectConfigurationLaunchPrompt()
TRPC->>DB: read settings.project_configuration_launch_prompt
DB-->>TRPC: prompt value / null
TRPC-->>Renderer: prompt (or default)
Renderer->>AgentSetup: request agent launch with computed launchPrompt
AgentSetup->>FS: ensure project-config CLI & wrapper exist (createProjectConfigCli)
FS-->>AgentSetup: script + wrapper present
AgentSetup->>FS: (agent-run) CLI show/write as needed
AgentSetup-->>Renderer: agent started / first-turn config executed
Renderer-->>User: UI shows configuration note / progress
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~25 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 2 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (2 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
There was a problem hiding this comment.
1 issue found across 18 files
Prompt for AI agents (unresolved issues)
Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.
<file name="apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx">
<violation number="1" location="apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx:179">
P2: During the loading state of the `projectConfig` query, `shouldUseProjectConfigurationPrompt` defaults to `true` because `undefined` content is treated the same as empty content. This causes the configuration banner to flash on mount and risks injecting the configuration prompt if the user submits before the query resolves. Gate on the data being loaded (e.g., check `projectConfig !== undefined`).</violation>
</file>
Since this is your first cubic review, here's how it works:
- cubic automatically reviews your code and comments on bugs and improvements
- Teach cubic by replying to its comments. cubic learns from your replies and gets better over time
- Add one-off context when rerunning by tagging
@cubic-dev-aiwith guidance or docs links (includingllms.txt) - Ask questions if you need clarification on any suggestion
Reply with feedback, questions, or to request a fix. Tag @cubic-dev-ai to re-run a review.
There was a problem hiding this comment.
Actionable comments posted: 4
🧹 Nitpick comments (2)
apps/desktop/src/lib/trpc/routers/settings/index.ts (1)
682-718: Add regression coverage for the default/null round-trip.This pair encodes a subtle contract: blank or default prompts are normalized to
nullon write and expanded back to the default template on read. A focused router test for blank input, exact-default input, and custom input would make this much safer to evolve.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/lib/trpc/routers/settings/index.ts` around lines 682 - 718, Add regression tests for the round-trip behavior implemented by getProjectConfigurationLaunchPrompt and setProjectConfigurationLaunchPrompt: verify that (1) passing a blank string results in null stored and reads back as DEFAULT_PROJECT_CONFIGURATION_LAUNCH_PROMPT_TEMPLATE, (2) passing the exact DEFAULT_PROJECT_CONFIGURATION_LAUNCH_PROMPT_TEMPLATE stores null and reads back as the default, and (3) passing a custom non-default prompt stores and reads back the same custom string. In the router test suite, exercise setProjectConfigurationLaunchPrompt (via the publicProcedure/mutation) and then getProjectConfigurationLaunchPrompt (query), asserting on localDb/settings contents where appropriate to ensure normalization to null on write and expansion on read.apps/desktop/src/main/lib/agent-setup/project-config-cli.test.ts (1)
12-95: Add one smoke test for the managed wrapper path.These cases validate the generated JS script directly, but the shipped feature depends on
createProjectConfigCli()/ wrapper generation wiring too. A small integration test that creates the managed CLI and invokesshowthrough the wrapper would catch the more realistic failure mode.🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed. In `@apps/desktop/src/main/lib/agent-setup/project-config-cli.test.ts` around lines 12 - 95, Add a smoke/integration test that exercises the managed-wrapper generation path by calling createProjectConfigCli(...) to produce the wrapper script, then invoke it with the existing runCli helper and assert the same basic "show" behavior; locate and reuse the test helpers in this file (runCli, TEST_ROOT, projectRoot, configPath) and reference createProjectConfigCli and getProjectConfigCliScriptContent so the test ensures the wrapper wiring delegates to the generated JS script correctly. Ensure the test creates the wrapper in TEST_ROOT, makes it executable, runs runCli(["show","--project-root", projectRoot]), parses the JSON output, and checks exists/path/config like the existing "shows missing config" test.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.
Inline comments:
In `@apps/desktop/src/main/lib/agent-setup/project-config-cli.ts`:
- Around line 165-176: The current write path always assigns setup and teardown
to new arrays, wiping existing values when the caller omits those flags; change
the logic so you only replace a section when the caller explicitly provided it.
For both setup and teardown, if options.setupJson / options.teardownJson is
defined use that (even if it is an empty array to mean “clear”); else if
options.setup / options.teardown are provided use those (merging/appending into
an array as intended); otherwise keep existing.setup / existing.teardown from
readExistingConfig. Update the block around command === "write" where setup,
teardown, existing, and nextConfig are computed to conditionally set each
section using existing.setup/existing.teardown when the corresponding flags are
not present.
In
`@apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx`:
- Around line 125-133: The component is deriving the first-turn prompt before
the config/settings queries settle (projectConfig,
projectConfigurationLaunchPrompt, gitInfo, globalBranchPrefix), causing
fallbacks to defaults; update the logic in PromptGroup to wait for those queries
to be loaded before computing shouldUseProjectConfigurationPrompt and calling
buildLaunchRequest() (or to disable the create/submit action until loaded).
Specifically, gate uses of projectConfig?.content and
projectConfigurationLaunchPrompt behind the queries' settled/loaded flags (from
electronTrpc.config.getConfigContent.useQuery and the three settings.useQuery
calls) and adjust the create/submit handlers to early-return or show a
loading/disabled state until those queries are finished so the launch prompt
reflects saved configuration.
In
`@apps/desktop/src/renderer/routes/_authenticated/settings/behavior/components/BehaviorSettings/BehaviorSettings.tsx`:
- Around line 364-367: When saving projectConfigurationLaunchPromptDraft via
setProjectConfigurationLaunchPrompt.mutate, normalize whitespace-only drafts to
null so saving matches renderProjectConfigurationLaunchPrompt() semantics:
compute a value = projectConfigurationLaunchPromptDraft?.trim() === "" ? null :
projectConfigurationLaunchPromptDraft and pass that value as prompt in the
mutate call; update the onClick handler that calls
setProjectConfigurationLaunchPrompt.mutate({ prompt:
projectConfigurationLaunchPromptDraft }) to use this normalized value.
In `@apps/desktop/src/renderer/screens/main/components/StartView/index.tsx`:
- Around line 40-44: The code only uses projects[0]?.id so when multiple
projects are returned by openNew() only the first triggers the agent-first
modal; update the logic in StartView to iterate over the returned projects array
(the projects variable from openNew()) and call
openNewWorkspaceModal(project.id) for each successful entry instead of using
firstProjectId, ensuring every project returned by openNew() opens its workspace
modal.
---
Nitpick comments:
In `@apps/desktop/src/lib/trpc/routers/settings/index.ts`:
- Around line 682-718: Add regression tests for the round-trip behavior
implemented by getProjectConfigurationLaunchPrompt and
setProjectConfigurationLaunchPrompt: verify that (1) passing a blank string
results in null stored and reads back as
DEFAULT_PROJECT_CONFIGURATION_LAUNCH_PROMPT_TEMPLATE, (2) passing the exact
DEFAULT_PROJECT_CONFIGURATION_LAUNCH_PROMPT_TEMPLATE stores null and reads back
as the default, and (3) passing a custom non-default prompt stores and reads
back the same custom string. In the router test suite, exercise
setProjectConfigurationLaunchPrompt (via the publicProcedure/mutation) and then
getProjectConfigurationLaunchPrompt (query), asserting on localDb/settings
contents where appropriate to ensure normalization to null on write and
expansion on read.
In `@apps/desktop/src/main/lib/agent-setup/project-config-cli.test.ts`:
- Around line 12-95: Add a smoke/integration test that exercises the
managed-wrapper generation path by calling createProjectConfigCli(...) to
produce the wrapper script, then invoke it with the existing runCli helper and
assert the same basic "show" behavior; locate and reuse the test helpers in this
file (runCli, TEST_ROOT, projectRoot, configPath) and reference
createProjectConfigCli and getProjectConfigCliScriptContent so the test ensures
the wrapper wiring delegates to the generated JS script correctly. Ensure the
test creates the wrapper in TEST_ROOT, makes it executable, runs
runCli(["show","--project-root", projectRoot]), parses the JSON output, and
checks exists/path/config like the existing "shows missing config" test.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 02b4ca2f-6f5b-4016-94b6-81cbc5506375
📒 Files selected for processing (18)
apps/desktop/src/lib/trpc/routers/settings/index.tsapps/desktop/src/main/lib/agent-setup/agent-wrappers.tsapps/desktop/src/main/lib/agent-setup/index.tsapps/desktop/src/main/lib/agent-setup/project-config-cli.test.tsapps/desktop/src/main/lib/agent-setup/project-config-cli.tsapps/desktop/src/renderer/components/NewWorkspaceModal/NewWorkspaceModal.tsxapps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsxapps/desktop/src/renderer/routes/_authenticated/_onboarding/new-project/hooks/useProjectCreationHandler/useProjectCreationHandler.tsapps/desktop/src/renderer/routes/_authenticated/settings/behavior/components/BehaviorSettings/BehaviorSettings.tsxapps/desktop/src/renderer/routes/_authenticated/settings/utils/settings-search/settings-search.tsapps/desktop/src/renderer/screens/main/components/StartView/index.tsxapps/desktop/src/renderer/screens/main/components/WorkspaceSidebar/SidebarDropZone/SidebarDropZone.tsxapps/desktop/src/shared/project-configuration.test.tsapps/desktop/src/shared/project-configuration.tspackages/local-db/drizzle/0036_add_project_configuration_launch_prompt_setting.sqlpackages/local-db/drizzle/meta/0036_snapshot.jsonpackages/local-db/drizzle/meta/_journal.jsonpackages/local-db/src/schema/schema.ts
| const projects = await openNew(); | ||
| const firstProjectId = projects[0]?.id; | ||
| if (firstProjectId) { | ||
| navigate({ | ||
| to: "/project/$projectId", | ||
| params: { projectId: firstProjectId }, | ||
| replace: true, | ||
| }); | ||
| openNewWorkspaceModal(firstProjectId); | ||
| } |
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
fd 'projects\.(ts|tsx)$' apps/desktop/src/renderer/react-query --exec sed -n '1,240p' {}
rg -n -C4 'showOpenDialog|openDirectory|multiSelections' apps/desktop/src -g '!**/*.test.*'Repository: superset-sh/superset
Length of output: 6561
🏁 Script executed:
rg -n 'openNew|useOpenNew' apps/desktop/src/renderer/screens/main/components/StartView/ -A 5Repository: superset-sh/superset
Length of output: 3489
🏁 Script executed:
rg -n 'function openNew|const openNew|export.*openNew' apps/desktop/src -A 10 -g '!**/*.test.*'Repository: superset-sh/superset
Length of output: 7866
🏁 Script executed:
rg -n 'projects\.open\.' apps/desktop/src/lib/trpc/routers/projects/projects.ts -A 30 | head -100Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
cat -n apps/desktop/src/renderer/react-query/projects/useOpenProject.tsx | head -150Repository: superset-sh/superset
Length of output: 4848
🏁 Script executed:
rg -n 'useOpenNew|function useOpenNew|const useOpenNew|export.*useOpenNew' apps/desktop/src -A 30 -g '!**/*.test.*'Repository: superset-sh/superset
Length of output: 46106
🏁 Script executed:
rg -n 'openNew.*procedure|\.openNew\s*=' apps/desktop/src/lib/trpc/routers/projects/ -A 40 | head -150Repository: superset-sh/superset
Length of output: 46
🏁 Script executed:
cat -n apps/desktop/src/renderer/react-query/projects/processOpenNewResults.tsRepository: superset-sh/superset
Length of output: 1845
🏁 Script executed:
rg -n 'openNew\s*:\s*publicProcedure|\.openNew' apps/desktop/src/lib/trpc/routers/projects/projects.ts -A 60 | head -200Repository: superset-sh/superset
Length of output: 2045
Loop through all returned projects, not just the first, when opening multiple projects.
The openNew() backend procedure explicitly supports multiSelections (line 505 in apps/desktop/src/lib/trpc/routers/projects/projects.ts) and processes all selected paths, returning the complete array of outcomes. The frontend hook correctly resolves with all successfully opened projects. However, StartView takes only projects[0] and ignores the rest, meaning every project after the first bypasses the agent-first configuration step that this PR introduces.
Each project returned from openNew() should trigger openNewWorkspaceModal(), not just the first one.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.
In `@apps/desktop/src/renderer/screens/main/components/StartView/index.tsx` around
lines 40 - 44, The code only uses projects[0]?.id so when multiple projects are
returned by openNew() only the first triggers the agent-first modal; update the
logic in StartView to iterate over the returned projects array (the projects
variable from openNew()) and call openNewWorkspaceModal(project.id) for each
successful entry instead of using firstProjectId, ensuring every project
returned by openNew() opens its workspace modal.
There was a problem hiding this comment.
Intentionally keeping the current behavior. The workspace modal is designed for a single project at a time. Multi-select is an edge case, and opening the modal for just the first project is a reasonable UX -- opening multiple modals in sequence would be more disorienting than helpful.
There was a problem hiding this comment.
@zmanian, understood — that's a reasonable UX call. Opening multiple modals sequentially would indeed be more disorienting than helpful. I'll note this for future reviews.
(´• ω •`) 🐇
✏️ Learnings added
Learnt from: zmanian
Repo: superset-sh/superset PR: 2211
File: apps/desktop/src/renderer/screens/main/components/StartView/index.tsx:40-44
Timestamp: 2026-03-08T18:46:23.885Z
Learning: In `apps/desktop/src/renderer/screens/main/components/StartView/index.tsx`, `openNew()` can return multiple projects (multi-select is supported by the backend), but only the first project's id is passed to `openNewWorkspaceModal()`. This is intentional: the workspace modal is designed for a single project at a time, and opening multiple modals in sequence was considered a worse UX. Do not flag this as a bug.
Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.
- Gate shouldUseProjectConfigurationPrompt on projectConfig being loaded to prevent flash and race condition during query loading state - Preserve existing setup/teardown in project-config CLI when caller omits those flags instead of silently wiping them - Normalize whitespace-only launch prompts to null on save
There was a problem hiding this comment.
♻️ Duplicate comments (1)
apps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsx (1)
177-206:⚠️ Potential issue | 🟠 MajorWait for the launch-prompt setting before rendering the first-turn prompt.
This still has the same race on fast submit: once
projectConfigresolves,shouldUseProjectConfigurationPromptflips totrue, butprojectConfigurationLaunchPromptmay still beundefined, sorenderProjectConfigurationLaunchPrompt()can fall back to the default template and ignore the saved custom prompt. Gate this path on the settings query settling as well, or blockhandleCreate()/ disable the button until that query has loaded.
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro
Run ID: 95a589a3-947f-4d46-9971-9ccb134f83d6
📒 Files selected for processing (3)
apps/desktop/src/main/lib/agent-setup/project-config-cli.tsapps/desktop/src/renderer/components/NewWorkspaceModal/components/PromptGroup/PromptGroup.tsxapps/desktop/src/renderer/routes/_authenticated/settings/behavior/components/BehaviorSettings/BehaviorSettings.tsx
Summary
superset-project-configCLI plus a configurable launch prompt so the first agent turn interviews the user and writes.superset/config.jsonTesting
Summary by cubic
Route newly opened projects into an agent-first flow. The agent interviews the user and writes
.superset/config.jsonvia a managedsuperset-project-configCLI with a configurable launch prompt.New Features
superset-project-configCLI during agent setup; supports show/write and preserves existingsetup/teardownwhen flags are omitted.{{show_command}},{{write_command}},{{project_root}},{{user_request}}), plus Reset/Save in Settings; whitespace-only values normalize to the default.Migration
project_configuration_launch_promptto thesettingstable; no manual steps. Existing installs default to the built-in template when the setting is null.Written for commit df1253a. Summary will update on new commits.
Summary by CodeRabbit
New Features
Tests
Chores