Files

164 lines
9.6 KiB
Markdown

---
phase: 02-lifecycle-command-safety
plan: 03
type: execute
wave: 3
depends_on: [02-02]
files_modified:
- tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx
- tauri-app/src/features/runtime/components/RuntimeStatusCard.css
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.css
- tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
autonomous: true
requirements: [CTRL-01, CTRL-02, CTRL-03]
must_haves:
truths:
- The runtime workspace tells the user exactly which lifecycle action is happening, what completed, and whether a saved draft is live now or waiting for restart/apply.
- Status-card and drawer controls disable or relabel themselves consistently while a conflicting lifecycle action is in progress.
- Restart-required and save-before-apply guidance is visible before the user commits a high-impact action.
artifacts:
- path: tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx
provides: authoritative status-card action labels, blocked states, and completion messaging for runtime lifecycle actions
- path: tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
provides: explicit apply-semantics guidance and lifecycle CTA copy inside the draft editor
- path: tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
provides: integrated UI regression coverage for lifecycle commands and apply feedback
key_links:
- from: tauri-app/src/features/runtime/useRuntimeManager.ts
to: tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx
via: active lifecycle command, lifecycle result, and action guards passed as props
pattern: start|stop|retry|result
- from: tauri-app/src/features/runtime/useRuntimeManager.ts
to: tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
via: applyImpact and lifecycle status passed into drawer CTA and helper copy
pattern: restart_required|save_before_apply|lifecycleBusy
---
<objective>
Finish Phase 2 by making lifecycle command safety visible and trustworthy in the runtime workspace.
Purpose: expose the backend and manager semantics from plans 02-01 and 02-02 through the status card and settings drawer without regressing Phase 1 draft UX.
Output: clear CTA labels, restart/apply guidance, blocked-state rules, and end-to-end UI regressions for lifecycle safety.
</objective>
<execution_context>
@$HOME/.config/opencode/get-shit-done/workflows/execute-plan.md
@$HOME/.config/opencode/get-shit-done/templates/summary.md
</execution_context>
<context>
@.planning/PROJECT.md
@.planning/ROADMAP.md
@.planning/STATE.md
@.planning/REQUIREMENTS.md
@.planning/phases/02-lifecycle-command-safety/02-RESEARCH.md
@.planning/phases/02-lifecycle-command-safety/02-01-SUMMARY.md
@.planning/phases/02-lifecycle-command-safety/02-02-SUMMARY.md
@tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx
@tauri-app/src/features/runtime/components/RuntimeStatusCard.css
@tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
@tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.css
@tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
<interfaces>
From `tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx`:
```tsx
interface Props {
snapshot: RuntimeSnapshot;
loading: boolean;
busy: boolean;
onOpenSettings: () => void;
onStart: () => void;
onStop: () => void;
}
```
From `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx`:
```tsx
interface Props {
open: boolean;
snapshot: RuntimeSnapshot;
busy: boolean;
onSave: (patch: Partial<RuntimeConfig>) => Promise<RuntimeSnapshot>;
onStart: () => Promise<unknown>;
onStop: () => Promise<unknown>;
}
```
</interfaces>
</context>
<tasks>
<task type="auto" tdd="true">
<name>Task 1: Update the runtime status card for action-specific lifecycle feedback</name>
<files>tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx, tauri-app/src/features/runtime/components/RuntimeStatusCard.css, tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx</files>
<read_first>
- tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx
- tauri-app/src/features/runtime/components/RuntimeStatusCard.css
- tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- tauri-app/src/features/runtime/useRuntimeManager.ts
- .planning/phases/02-lifecycle-command-safety/02-02-SUMMARY.md
</read_first>
<behavior>
- Test 1: while a start command is active, the primary status-card action reads `Starting local API...` and conflicting controls are disabled.
- Test 2: while a stop command is active, the primary status-card action reads `Stopping local API...` and start is not re-enabled until completion.
- Test 3: after a blocked or failed command, the status card surfaces the latest lifecycle result message with retry guidance.
</behavior>
<action>Refactor `tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx` to consume the explicit lifecycle fields from the runtime manager instead of only `busy`. Replace the generic label `Working...` with concrete command labels `Starting local API...` and `Stopping local API...`. Add a visible result banner or note area that renders the latest lifecycle result message from manager state, including blocked/failed copy such as `Local API start already in progress.` or `Local API stopped.`. Update `RuntimeStatusCard.css` so the new note/banner styles match the existing runtime card tone system and remain readable on desktop and mobile layouts.</action>
<acceptance_criteria>
- `tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx` no longer renders the generic text `Working...`.
- `tauri-app/src/features/runtime/components/RuntimeStatusCard.tsx` contains the strings `Starting local API...` and `Stopping local API...`.
- `tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx` asserts lifecycle result messages or banners on the status card.
</acceptance_criteria>
<verify>
<automated>npm test -- RuntimeSurface</automated>
</verify>
<done>The runtime status card becomes a trustworthy summary of what lifecycle command is happening and what just completed.</done>
</task>
<task type="auto" tdd="true">
<name>Task 2: Make drawer CTA copy and apply guidance explicit</name>
<files>tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx, tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.css, tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx</files>
<read_first>
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.css
- tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- tauri-app/src/features/runtime/runtime-utils.ts
- .planning/phases/02-lifecycle-command-safety/02-RESEARCH.md
</read_first>
<behavior>
- Test 1: when a dirty local draft changes only non-restart fields, the drawer continues to offer `Save changes` and `Save and start local API` with immediate-apply helper copy.
- Test 2: when a running local runtime has dirty restart-impact fields, the drawer shows `Restart required to apply saved changes` and disables conflicting lifecycle actions until the user saves or stops.
- Test 3: when the user changes connection mode from remote to local, the drawer keeps the existing `Save mode before applying` safeguard and pairs it with explicit apply guidance.
</behavior>
<action>Update `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx` so the footer CTA copy is driven by `applyImpact` and active lifecycle command state. Keep `Save changes` for plain saves, keep `Save mode before applying` for pending mode switches, and add explicit helper or warning copy using these exact phrases when relevant: `Applies immediately after save.`, `Restart required to apply saved changes.`, and `Stop the local API or save first before applying this change.`. When the process is already running and restart-impact fields are dirty, disable `Save and start local API` as a conflicting action and render restart guidance instead of pretending the change is live. Update `RuntimeSettingsDrawer.css` so apply-guidance rows, warning banners, and disabled CTA states are visually distinct but consistent with the existing drawer styling.</action>
<acceptance_criteria>
- `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx` contains the strings `Applies immediately after save.` and `Restart required to apply saved changes.`.
- The drawer still contains `Save mode before applying` for mode-switch safeguards.
- `tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx` covers immediate-apply, restart-required, and conflicting-action-disabled states.
</acceptance_criteria>
<verify>
<automated>npm test -- RuntimeSurface</automated>
</verify>
<done>The draft editor explains exactly when a change goes live, when restart is required, and why conflicting lifecycle actions are disabled.</done>
</task>
</tasks>
<verification>
- `npm test -- RuntimeSurface`
</verification>
<success_criteria>
- Status card and drawer use action-specific lifecycle copy instead of one generic busy state.
- Restart-required and save-before-apply semantics are visible before the user commits a conflicting action.
- End-to-end tests prove lifecycle safety across start, stop, retry/block, and apply-guidance flows.
</success_criteria>
<output>
After completion, create `.planning/phases/02-lifecycle-command-safety/02-03-SUMMARY.md`
</output>