Files
ForgeLM/.planning/phases/01-hf-model-discovery/01-03-SUMMARY.md
T

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*