T-VVNK-sdf-project-setup-prompt-ui
State: closed/done · Impact: medium · Complexity: medium
With the setup action in place (T-1D8N), the operator still has no way
to reach it from the app. This task adds the prompt: after a project is
added, and whenever the focused project is not set up, SDF shows what
setup would change and offers to run it. Nothing is written until the
operator clicks.
| Location | Role today |
|---|---|
solutions/ontological/desktop/src-nuxt/app/composables/useFocusedProject.ts | add() creates the registered project, re-lists, and publishes the registry topic; nothing follows. |
solutions/ontological/desktop/src-nuxt/app/components/ProjectSwitcher.vue | The header switcher with the add form (submitAdd). |
solutions/ontological/desktop/src-nuxt/app/components/ProjectScopePane.vue | The scope pane with its own add form. |
solutions/ontological/desktop/src-nuxt/app/composables/useActions.ts | Wraps the generated action client for the existing buttons. |
solutions/ontological/desktop/src-nuxt/app/app.vue | The shell; where a focus-level banner belongs. |
solutions/ontological/desktop/src-nuxt/app/generated/transport.ts | After T-1D8N: actionProjectSetupStatus(projectId) and actionSetupProject(projectId, installHarness). |
solutions/ontological/desktop/src-nuxt/app/components/*.stories.ts | Storybook stories, which sit beside the component they cover. |
Proposed
Section titled “Proposed”useProjectSetup(projectId)composable:status(the read, a POST —project_setup_statusfollowsorchestrate_watch_probe, a read that spawns),refresh(),run(installHarness: boolean),busy,error, andneedsSetup(true whenroot_existsand notsdlc_yaml_present). The boolean is what the UI holds; the wire takes a required string, and the Rust side reads anything but the literal"false"as on.ProjectSetupPanel.vue: the project label and path, the item list from the dry run grouped by status, a “Register Claude Code harness” checkbox defaulting to on, a “Set up” button, and the result list once run. An unreachable root renders the path and a note instead of the button.- Trigger one: after
add()succeeds in either add form, the panel opens for the new project. - Trigger two: when the focused project’s status says
needsSetup, a banner in the shell names the project and opens the panel. Dismissing the banner is remembered per project id inlocalStorageonly; the status read itself is not cached. - The panel calls
recordfor the copy affordances the same way the existing buttons do, and shows the audit outcome line after a run.
Approach
Section titled “Approach”- Write
useProjectSetup.tsover the generated client with a vitest suite mockinguseTransport: status threading,needsSetup,runsuccess and failure, and no read whenprojectIdis null. - Build
ProjectSetupPanel.vuewith a Storybook story per state: needs setup, already set up, root missing, running, done, failed. - Wire trigger one in
ProjectSwitcher.vueandProjectScopePane.vue: bothsubmitAddpaths emit the new project’s id (returned fromadd(), which today returns only a boolean; change it to return the id or null) and open the panel. - Wire trigger two in
app.vue: watchfocusedProjectId, read status, render the banner. - Capture before and after screenshots with Playwright of the add flow and the banner, commit them under the SDF docs directory, and embed them in a PR comment.
| Area | Note |
|---|---|
solutions/ontological/desktop/src-nuxt/app/composables/useProjectSetup.ts | Status read, run, needsSetup. |
solutions/ontological/desktop/src-nuxt/app/composables/useProjectSetup.test.ts | Vitest suite. |
solutions/ontological/desktop/src-nuxt/app/components/ProjectSetupPanel.vue | The panel. |
solutions/ontological/desktop/src-nuxt/app/components/ProjectSetupPanel.stories.ts | One story per state. |
solutions/ontological/desktop/src-nuxt/app/composables/useFocusedProject.ts | add() returns the new id. |
solutions/ontological/desktop/src-nuxt/app/composables/useFocusedProject.test.ts | Cover the returned id. |
solutions/ontological/desktop/src-nuxt/app/components/ProjectSwitcher.vue | Open the panel after add. |
solutions/ontological/desktop/src-nuxt/app/components/ProjectScopePane.vue | Open the panel after add. |
solutions/ontological/desktop/src-nuxt/app/app.vue | Focus banner. |
solutions/ontological/desktop/docs/screenshots/ | Before and after captures for the PR. |
Acceptance criteria
Section titled “Acceptance criteria”- AC-1: Adding a project whose root has no
sdlc.yamlopens the panel listing at least thesdlc.yamlanddocs/planning/tasksitems aswould-create; nothing is written until “Set up” is clicked. - AC-2: Clicking “Set up” with the harness checkbox on calls
actionSetupProjectwithinstallHarnessas""; with it off, as"false"(vitest on the composable, pinning both directions). - AC-3: Focusing a registered project that lacks
sdlc.yamlshows the banner naming that project; focusing one that has it shows no banner. - AC-4: With no focused project,
useProjectSetupissues no read. - AC-5: A project whose root directory does not exist renders the path and a note, with no “Set up” button.
- AC-6: Storybook builds with the six panel states;
moon run sdf:checkand the SDF vitest suite pass. - AC-7: The PR carries before and after screenshots of the add flow and the banner.
Out of scope
Section titled “Out of scope”- Editing
sdlc.yamlfrom the panel; the verbs stay commented suggestions for the operator to edit in a text editor. - Surfacing
entities auditorproject doctoroutput. - Auto-running setup without a click.
Dependencies
Section titled “Dependencies”T-1D8Nprovides the two service fns and the generated client.
Discovery context
Section titled “Discovery context”The user-facing half of the 2026-09-20 survey into setting up SDLC configuration from SDF.
Depends on
Section titled “Depends on”T-1D8N