# Plan 04-01: Source-Mode Validation Contract **Wave:** 1 **Phase:** 4 **Requirements addressed:** MODL-01, MODL-02 --- ## Objective Add source-mode compatibility validation to the runtime config so that selecting an invalid combination of connection mode and model/source settings is detected before saving. --- ## Read First - `tauri-app/src/features/runtime/types.ts` — RuntimeConfig, RuntimeDraftFieldMeta, RuntimeDraftFieldState - `tauri-app/src/features/runtime/runtime-settings-form.ts` — createRuntimeConfigPatch, resolveDraftModelSelection - `tauri-app/src/features/runtime/runtime-utils.ts` — RESTART_REQUIRED_FIELDS, draft utilities - `tauri-app/src/features/runtime/useRuntimeManager.ts` — draft state management - `.planning/phases/04-model-source-validation/04-RESEARCH.md` — validation patterns research --- ## Action 1. **Add validation types** in `runtime-utils.ts`: ```typescript export type ValidationSeverity = "error" | "warning"; export interface FieldValidation { valid: boolean; severity: ValidationSeverity; message: string | null; } export interface SourceModeValidation { mode: ConnectionMode; valid: boolean; fieldValidations: Record; } ``` 2. **Create validation functions** in `runtime-utils.ts`: ```typescript export function validateSourceMode(config: RuntimeConfig): SourceModeValidation { const fieldValidations: Record = {}; let valid = true; if (config.connection_mode === "local") { // Validate local mode requirements if (!config.model_path) { fieldValidations.model_path = { valid: false, severity: "error", message: "Select a model file for local runtime" }; valid = false; } // models_dir is optional for local mode } else if (config.connection_mode === "remote") { // Validate remote mode requirements if (!config.server_url) { fieldValidations.server_url = { valid: false, severity: "error", message: "Server URL is required for remote runtime" }; valid = false; } } return { mode: config.connection_mode, valid, fieldValidations }; } ``` 3. **Add path validation helper** that checks if model files exist (calls backend or uses frontend check): ```typescript export interface PathValidation { path: string; exists: boolean; isValid: boolean; message: string | null; } export function validateModelPath(path: string | null): PathValidation { if (!path) { return { path: "", exists: false, isValid: false, message: null }; } // For now, return pending - actual existence check happens via scan return { path, exists: true, isValid: true, message: null }; } ``` 4. **Integrate into draft field state** in `useRuntimeManager.ts`: - Import `validateSourceMode` from runtime-utils - In `updateDraftField`, run source-mode validation after field update - Store validation results in `draftState.fields` using existing RuntimeDraftFieldMeta --- ## Acceptance Criteria - [ ] `runtime-utils.ts` exports `validateSourceMode(config)` returning SourceModeValidation - [ ] `runtime-utils.ts` exports `validateModelPath(path)` returning PathValidation - [ ] `useRuntimeManager.ts` calls validation on field updates in updateDraftField - [ ] Invalid source-mode combinations produce field-level validation messages - [ ] Validation state is stored in draftState.fields and reflected in UI --- ## Notes - Reuse existing RuntimeDraftFieldMeta structure for validation messages - Keep validation functions pure where possible for testability - Path existence validation will be enhanced in plan 04-02 with actual filesystem checks