Harden the controlled draft flow so field-scoped async work, rescans, and validation failures preserve user intent instead of silently mutating the draft.
Purpose: finish the phase by protecting the highest-risk interactions: folder pickers, model rescans, stale async responses, and save failure recovery.
Output: field-scoped async safety, invalid-draft preservation, save blocking, and regression tests for the full draft-safety contract.
- D-07: picker updates only the launched field
- D-08: rescans preserve current draft selection unless invalid
- D-10: stale responses for the same field are ignored
- D-11: invalid drafted values remain visible, inline, and block save
Task 1: Make async picker and rescan handlers field-scoped and stale-safe
tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx, tauri-app/src/features/runtime/runtime-settings-form.ts, tauri-app/src/features/runtime/runtime-settings-form.test.ts
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
- tauri-app/src/features/runtime/runtime-settings-form.ts
- tauri-app/src/features/runtime/runtime-settings-form.test.ts
- .planning/phases/01-hf-model-discovery/01-CONTEXT.md
- Test 1: folder/file pickers update only their target draft fields and do not rehydrate unrelated inputs (D-07).
- Test 2: model rescans preserve the current draft selection when it is still valid and only mark it invalid when it disappears (D-08, D-11).
- Test 3: only the latest request for a field can update draft-facing UI; older responses are ignored (D-10).
Refactor async handlers in `RuntimeSettingsDrawer.tsx` so each operation has field-scoped state and a latest-request guard. Concretely: `handlePickDir`, `handlePickFiles`, `handleRescan`, and any async validation/search path must update only the field(s) they own rather than resetting the full draft. Add explicit request sequencing per field or operation key so older responses are ignored when a newer request for that same field has started. Update `runtime-settings-form.ts` helpers so rescans preserve the current drafted model path when it still exists, and return an invalid-draft signal when the drafted path no longer exists instead of auto-falling back to another model silently. Add helper-level tests in `runtime-settings-form.test.ts` for preserved selection, invalid-selection detection, and non-silent fallback rules.
- `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx` contains explicit stale-request protection for field-level async handlers.
- `tauri-app/src/features/runtime/runtime-settings-form.ts` exposes helper logic that distinguishes valid preservation from invalid drafted selections.
- `tauri-app/src/features/runtime/runtime-settings-form.test.ts` covers preserved selection and invalid-selection outcomes.
npm test -- runtime-settings-form
Async field helpers can no longer silently rewrite unrelated fields or let older responses override the latest user intent.
Task 2: Preserve invalid drafts visibly and block save until resolved
tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx, tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx
- tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx
- .planning/phases/01-hf-model-discovery/01-UI-SPEC.md
- .planning/phases/01-hf-model-discovery/01-CONTEXT.md
- Test 1: an invalid model or folder draft remains visible with inline error text and destructive styling instead of being cleared (CONF-04, D-11).
- Test 2: `Save changes` is disabled while invalid draft metadata exists.
- Test 3: a failed save keeps the current draft values in place and surfaces the failure message instead of resetting the form (CONF-04).
In `RuntimeSettingsDrawer.tsx`, render inline invalid-state messaging for drafted values that fail validation or disappear during rescan. Preserve the user's typed or selected value in the control, add the destructive invalid styling from the Phase 1 color contract, and disable `Save changes` whenever invalid draft metadata exists. Keep save failures drawer-visible without resetting the draft or clearing helper state. Extend `RuntimeSurface.test.tsx` to assert concrete UI outcomes: invalid drafted values stay in the control, inline error copy is rendered near the affected field, `Save changes` is disabled until corrected, and a rejected save preserves the user's current draft state.
- `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx` renders inline invalid/error UI near affected fields and disables `Save changes` when invalid draft state exists.
- `tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx` asserts that invalid draft values remain visible and save failures preserve the draft.
npm test -- RuntimeSurface
Phase 1 ends with durable draft safety: invalid values are visible, saves are blocked until fixed, stale async work is ignored, and user intent survives failures.
- `npm test -- runtime-settings-form`
- `npm test -- RuntimeSurface`
- `npm run build`
<success_criteria>
Async field updates never overwrite unrelated draft fields.
Invalid model/folder drafts remain visible, explain the problem inline, and block save until fixed.
Save failures and rescans preserve user intent rather than silently replacing or clearing values.
</success_criteria>
After completion, create `.planning/phases/01-hf-model-discovery/01-03-SUMMARY.md`