apply-impact classification and lifecycle command label helpers
start|stop|restart|required
Teach the frontend runtime state layer how to represent lifecycle operations and apply semantics before any surface copy or button behavior changes.
Purpose: keep lifecycle trust rules in one manager-owned place, just as Phase 1 centralized draft ownership.
Output: typed frontend lifecycle state, reusable apply-impact helpers, and test coverage proving the manager exposes the right action-specific states.
Task 1: Mirror backend lifecycle metadata and define frontend apply-impact contracts
tauri-app/src/features/runtime/types.ts, tauri-app/src/features/runtime/api.ts, tauri-app/src/features/runtime/runtime-utils.ts
- tauri-app/src/features/runtime/types.ts
- tauri-app/src/features/runtime/api.ts
- tauri-app/src/features/runtime/runtime-utils.ts
- tauri-app/src-tauri/src/runtime/types.rs
- .planning/phases/02-lifecycle-command-safety/02-RESEARCH.md
- Test 1: the frontend `RuntimeSnapshot` includes the backend lifecycle command fields added in plan 02-01.
- Test 2: a helper can classify a draft as `immediate`, `restart_required`, or `save_before_apply` from `savedBaseline`, `draftConfig`, and `snapshot.process_running`.
Update `tauri-app/src/features/runtime/types.ts` to mirror the new backend lifecycle snapshot fields using concrete frontend unions for active command values `idle | save | start | stop | save_and_start`, command outcomes `succeeded | blocked | failed`, and apply-impact values `immediate | restart_required | save_before_apply`. Update `tauri-app/src/features/runtime/api.ts` to preserve these fields in the local fallback snapshot shape instead of dropping them. Add reusable helpers in `tauri-app/src/features/runtime/runtime-utils.ts` that classify draft impact using the backend restart-impact field list (`connection_mode`, `model_path`, `addr`, `gpu_layers`, `ctx_size`) and current runtime state.
- `tauri-app/src/features/runtime/types.ts` exports frontend lifecycle command and apply-impact types.
- `tauri-app/src/features/runtime/api.ts` fallback snapshots include the new lifecycle metadata fields.
- `tauri-app/src/features/runtime/runtime-utils.ts` contains logic that references `connection_mode`, `model_path`, `addr`, `gpu_layers`, and `ctx_size` when determining restart-required impact.
npm test -- RuntimeSurface
The frontend type layer can represent both backend lifecycle results and user-facing apply semantics without ad hoc string handling.
Task 2: Replace generic busy handling with action-specific manager state
tauri-app/src/features/runtime/useRuntimeManager.ts, tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- tauri-app/src/features/runtime/useRuntimeManager.ts
- tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- tauri-app/src/features/runtime/runtime-utils.ts
- tauri-app/src/features/runtime/types.ts
- .planning/phases/02-lifecycle-command-safety/02-01-SUMMARY.md
- Test 1: starting the runtime exposes an active command of `start` and resolves to a completion result with a stable success message.
- Test 2: stopping the runtime exposes an active command of `stop` and blocks duplicate lifecycle actions while the command is active.
- Test 3: when draft changes hit restart-impact fields while the process is running, the manager exposes `restart_required` instead of pretending the save is immediately applied.
Refactor `tauri-app/src/features/runtime/useRuntimeManager.ts` so it exposes explicit manager-owned fields for `activeLifecycleCommand`, `lastLifecycleResult`, `lifecycleBusy`, and `applyImpact` rather than relying only on `busy`. Map `saveDraft`, `saveConfig`, `startLocal`, and `stopLocal` to concrete command names `save`, `save_and_start`, `start`, and `stop`. Preserve Phase 1 draft safety: polling must still avoid overwriting dirty draft values. When a command resolves, store a result message based on the backend snapshot metadata or fallback defaults such as `Local API started.`, `Local API stopped.`, `Save completed.`, or the backend-provided blocked/failed message. Update `RuntimeSurface.test.tsx` so the feature harness asserts action-specific state instead of only the generic `busy` boolean.
- `tauri-app/src/features/runtime/useRuntimeManager.ts` exports `activeLifecycleCommand`, `lastLifecycleResult`, or equivalent explicit action-specific fields.
- The manager still preserves dirty draft values across polling while lifecycle state changes.
- `tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx` contains lifecycle assertions for start, stop, blocked duplicates, and restart-required saves.
npm test -- RuntimeSurface
The runtime manager becomes the single source of truth for lifecycle command progress, completion, and apply semantics.
- `npm test -- RuntimeSurface`
<success_criteria>
Frontend state exposes action-specific lifecycle progress and completion information.