112 lines
5.6 KiB
Markdown
112 lines
5.6 KiB
Markdown
---
|
|
phase: 01-draft-state-ownership
|
|
plan: 03
|
|
subsystem: ui
|
|
tags: [react, typescript, vitest, async-state, validation]
|
|
requires:
|
|
- phase: 01-02
|
|
provides: controlled draft drawer and explicit draft/live UI semantics
|
|
provides:
|
|
- stale-safe field-scoped async handling for model folders, rescans, and picker flows
|
|
- invalid draft preservation with inline errors and save blocking
|
|
- save failure recovery that keeps current draft values visible and editable
|
|
affects: [phase-2-lifecycle-safety, runtime-validation, runtime-workspace]
|
|
tech-stack:
|
|
added: []
|
|
patterns: [shared async request guard for field-scoped operations, invalid draft preservation instead of silent fallback, helper-level model-selection validation]
|
|
key-files:
|
|
created: []
|
|
modified:
|
|
- 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/RuntimeSurface.test.tsx
|
|
- tauri-app/src/features/runtime/useRuntimeManager.ts
|
|
key-decisions:
|
|
- "Use a shared request key for model-selection async work so stale scan responses cannot overwrite later browse or picker intent."
|
|
- "Preserve invalid drafted model values and surface inline errors rather than auto-selecting a replacement model."
|
|
patterns-established:
|
|
- "Async folder and model operations update only their owned draft fields and attach pending or invalid metadata instead of rehydrating the full form."
|
|
- "Save stays disabled while invalid or pending field metadata exists, and failed saves keep the draft intact."
|
|
requirements-completed: [CONF-01, CONF-03, CONF-04]
|
|
duration: 18min
|
|
completed: 2026-03-29
|
|
---
|
|
|
|
# Phase 1 Plan 3: Async Draft Safety Summary
|
|
|
|
**Field-scoped async guards, invalid draft preservation, and save-failure recovery for runtime settings**
|
|
|
|
## Performance
|
|
|
|
- **Duration:** 18 min
|
|
- **Started:** 2026-03-29T02:53:00Z
|
|
- **Completed:** 2026-03-29T03:10:41Z
|
|
- **Tasks:** 2
|
|
- **Files modified:** 5
|
|
|
|
## Accomplishments
|
|
- Added helper logic in `runtime-settings-form.ts` to distinguish valid selection preservation from invalid drafted model paths
|
|
- Hardened `RuntimeSettingsDrawer.tsx` so async scans and pickers update only their owned fields, ignore stale results, and keep invalid draft values visible inline
|
|
- Added regression coverage for stale async protection, invalid draft save blocking, and failed-save draft preservation
|
|
|
|
## Task Commits
|
|
|
|
Each task was committed atomically:
|
|
|
|
1. **Task 1: Make async picker and rescan handlers field-scoped and stale-safe** - `80883c2` (feat)
|
|
2. **Task 2: Preserve invalid drafts visibly and block save until resolved** - `80883c2` (feat)
|
|
|
|
**Plan metadata:** pending
|
|
|
|
## Files Created/Modified
|
|
- `tauri-app/src/features/runtime/components/RuntimeSettingsDrawer.tsx` - Shared async request guarding, inline invalid-state messaging, and save blocking for pending or invalid draft fields
|
|
- `tauri-app/src/features/runtime/runtime-settings-form.ts` - Draft model resolution helper that keeps missing selections visible and marked invalid
|
|
- `tauri-app/src/features/runtime/runtime-settings-form.test.ts` - Unit coverage for preserved selections and invalid draft outcomes
|
|
- `tauri-app/src/features/runtime/components/RuntimeSurface.test.tsx` - Runtime regression tests for stale async responses, invalid draft preservation, and failed-save recovery
|
|
- `tauri-app/src/features/runtime/useRuntimeManager.ts` - Draft metadata update helpers used by the controlled drawer for pending and invalid field state
|
|
|
|
## Decisions Made
|
|
- Unified scan, folder browse, and file-pick draft updates under one model-selection request channel so later user intent always wins over earlier async work
|
|
- Disabled `Save changes` whenever invalid or pending draft metadata exists to match the locked Phase 1 trust contract
|
|
|
|
## Deviations from Plan
|
|
|
|
### Auto-fixed Issues
|
|
|
|
**1. [Integration] Extended manager metadata APIs for pending and invalid field state**
|
|
- **Found during:** Task 2 (invalid draft preservation)
|
|
- **Issue:** The typed manager contract existed, but the drawer needed a write path for field-level pending and invalid metadata
|
|
- **Fix:** Added `updateDraft` and `updateDraftFieldMeta` support in `tauri-app/src/features/runtime/useRuntimeManager.ts`
|
|
- **Files modified:** `tauri-app/src/features/runtime/useRuntimeManager.ts`
|
|
- **Verification:** `npm test -- RuntimeSurface`; `npm test -- runtime-settings-form`; `npm run build`
|
|
- **Committed in:** `80883c2`
|
|
|
|
---
|
|
|
|
**Total deviations:** 1 auto-fixed (integration)
|
|
**Impact on plan:** Required to complete the planned invalid-state behavior. No user-facing scope expansion beyond Phase 1 draft safety.
|
|
|
|
## Issues Encountered
|
|
- The stale-response test originally used two rescan requests, but the UI correctly disables a second rescan while one is already in flight; the regression was adjusted to cover a pending initial scan followed by a later folder browse request against the same model-selection guard
|
|
|
|
## User Setup Required
|
|
|
|
None - no external service configuration required.
|
|
|
|
## Next Phase Readiness
|
|
- Phase 1 draft safety is complete: polling, discard, invalid values, async rescans, and save failures now preserve user intent
|
|
- Phase 2 can build explicit lifecycle command semantics on top of a trusted settings surface instead of compensating for draft-state bugs
|
|
|
|
## Self-Check
|
|
|
|
PASSED
|
|
|
|
- Verified helper-level selection and invalid-draft behavior with `npm test -- runtime-settings-form`
|
|
- Verified stale async guards, invalid draft blocking, and save-failure recovery with `npm test -- RuntimeSurface`
|
|
- Verified production compile with `npm run build`
|
|
|
|
---
|
|
*Phase: 01-draft-state-ownership*
|
|
*Completed: 2026-03-29*
|