diff --git a/AGENTS.md b/AGENTS.md index 982adfa..e131c95 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -78,6 +78,17 @@ Before marking feature work complete: - [ ] Local test run passes for impacted packages - [ ] CI test checks are expected to pass with the changes +### UI Form Behavior Test Rules (REQUIRED FOR FORM CHANGES) + +When changing any UI form or input handling logic, apply all of these rules: + +1. **MUST** add/extend tests that simulate realistic typing sequences (single char -> multi-char -> edit) for each changed text field +2. **MUST** cover all changed input types (text, textarea, number, select, checkbox/radio where applicable), not just one happy-path field +3. **MUST** include at least one integration-level test that exercises the full user flow (open form -> type -> submit -> assert payload/API call) +4. **MUST** include assertions that no crash/regression occurs during rapid consecutive changes +5. **MUST** avoid reading React synthetic event objects inside deferred/functional state updaters; capture `const value = event.currentTarget.value` before async or queued updates +6. **SHOULD** include edge-case behavior for user edits (clearing fields, trimming, retyping, invalid intermediate numeric input) + --- ## CRITICAL: Constitution Validation (NON-NEGOTIABLE) diff --git a/CLAUDE.md b/CLAUDE.md index 982adfa..e131c95 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -78,6 +78,17 @@ Before marking feature work complete: - [ ] Local test run passes for impacted packages - [ ] CI test checks are expected to pass with the changes +### UI Form Behavior Test Rules (REQUIRED FOR FORM CHANGES) + +When changing any UI form or input handling logic, apply all of these rules: + +1. **MUST** add/extend tests that simulate realistic typing sequences (single char -> multi-char -> edit) for each changed text field +2. **MUST** cover all changed input types (text, textarea, number, select, checkbox/radio where applicable), not just one happy-path field +3. **MUST** include at least one integration-level test that exercises the full user flow (open form -> type -> submit -> assert payload/API call) +4. **MUST** include assertions that no crash/regression occurs during rapid consecutive changes +5. **MUST** avoid reading React synthetic event objects inside deferred/functional state updaters; capture `const value = event.currentTarget.value` before async or queued updates +6. **SHOULD** include edge-case behavior for user edits (clearing fields, trimming, retyping, invalid intermediate numeric input) + --- ## CRITICAL: Constitution Validation (NON-NEGOTIABLE) diff --git a/apps/web/src/components/project/TaskForm.tsx b/apps/web/src/components/project/TaskForm.tsx index cc6f15e..4818a21 100644 --- a/apps/web/src/components/project/TaskForm.tsx +++ b/apps/web/src/components/project/TaskForm.tsx @@ -41,6 +41,9 @@ export function TaskForm({ const [error, setError] = useState(null); const candidateParents = tasks.filter((task) => task.id !== currentTaskId); + const updateField = (field: K, value: TaskFormValues[K]) => { + setValues((current) => ({ ...current, [field]: value })); + }; const handleSubmit = async (event: FormEvent) => { event.preventDefault(); @@ -68,7 +71,10 @@ export function TaskForm({ Title setValues((current) => ({ ...current, title: event.currentTarget.value }))} + onChange={(event) => { + const value = event.currentTarget.value; + updateField('title', value); + }} placeholder="Task title" disabled={submitting} /> @@ -78,7 +84,10 @@ export function TaskForm({ Description