From 2bec65a445bbe7a61534c754b148309ce6812090 Mon Sep 17 00:00:00 2001 From: Test Date: Fri, 3 Apr 2026 15:10:40 +0200 Subject: [PATCH] =?UTF-8?q?chore:=20claude=20code=20loops=20forever=20?= =?UTF-8?q?=E2=80=94=20waits=2010min=20when=20no=20tasks=20instead=20of=20?= =?UTF-8?q?exiting?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .claude/commands/laputa-done.md | 2 +- .claude/commands/laputa-next-task.md | 15 ++++++++++++++- src/components/TitleField.test.tsx | 15 +++++++++++++++ src/components/TitleField.tsx | 9 +++++++++ 4 files changed, 39 insertions(+), 2 deletions(-) diff --git a/.claude/commands/laputa-done.md b/.claude/commands/laputa-done.md index 8199bb4f..1529e6cc 100644 --- a/.claude/commands/laputa-done.md +++ b/.claude/commands/laputa-done.md @@ -39,4 +39,4 @@ curl -s -X POST "https://api.todoist.com/api/v1/tasks/$ARGUMENTS/move" \ Run `/laputa-next-task` to get the next task and start working on it immediately. -If `/laputa-next-task` returns `NO_TASKS` → exit cleanly. The hourly watchdog will restart you when new tasks arrive. +If there are no tasks, `/laputa-next-task` will wait 10 minutes and retry automatically. Do NOT exit — stay alive and let it loop. diff --git a/.claude/commands/laputa-next-task.md b/.claude/commands/laputa-next-task.md index 3d0559f0..9e66856f 100644 --- a/.claude/commands/laputa-next-task.md +++ b/.claude/commands/laputa-next-task.md @@ -40,4 +40,17 @@ curl -s "https://api.todoist.com/api/v1/comments?task_id=" \ 6. For To Rework tasks: read the ❌ QA failed comment — it tells you exactly what to fix 7. Output: task ID, title, and full description so you can start working immediately -If no tasks are available in either section → output `NO_TASKS` and exit cleanly. +If no tasks are available in either section → wait 10 minutes and try again (loop forever): + +```bash +while true; do + # ... check tasks ... + if no_tasks; then + sleep 600 # 10 minutes + else + break # got a task, proceed + fi +done +``` + +Do NOT exit when there are no tasks. Keep looping until a task appears. This keeps Claude Code alive permanently — the watchdog is a safety net only, not the primary dispatcher. diff --git a/src/components/TitleField.test.tsx b/src/components/TitleField.test.tsx index 5d38eb69..0121ff76 100644 --- a/src/components/TitleField.test.tsx +++ b/src/components/TitleField.test.tsx @@ -102,6 +102,21 @@ describe('TitleField', () => { expect(document.activeElement).toBe(input) }) + it('resets stale localValue when title prop changes after focus', () => { + // Regression: creating a new note fires focus-editor before React re-renders, + // so handleFocus captures the OLD note's title into localValue. + // When React re-renders with the new title, localValue should be cleared. + const onChange = vi.fn() + const { rerender } = render() + const input = screen.getByTestId('title-field-input') + // Simulate: focus fires while title prop is still "Old Note" + fireEvent.focus(input) + expect(input).toHaveValue('Old Note') + // React re-renders with new note's title (tab switched) + rerender() + expect(input).toHaveValue('Untitled note') + }) + it('shows vault-relative path for notes in subdirectories', () => { render( {}} />) expect(screen.getByTestId('title-field-path')).toHaveTextContent('docs/adr/0001-tauri-stack.md') diff --git a/src/components/TitleField.tsx b/src/components/TitleField.tsx index 726eef28..38ac01f5 100644 --- a/src/components/TitleField.tsx +++ b/src/components/TitleField.tsx @@ -19,6 +19,15 @@ function useOptimisticTitle(title: string, onTitleChange: (t: string) => void) { // [optimisticTitle, forPropTitle]: shown after commit until title prop catches up const [optimistic, setOptimistic] = useState<[string, string] | null>(null) const isFocusedRef = useRef(false) + const prevTitleRef = useRef(title) + + // Reset local edit when the title prop changes (e.g. note switch). + // This prevents a stale handleFocus closure from locking in the old note's title + // when focus-editor fires before React re-renders with the new tab. + if (prevTitleRef.current !== title) { + prevTitleRef.current = title + if (localValue !== null) setLocalValue(null) + } // Clear optimistic once the prop changes (rename completed or tab switched) const optimisticValue = optimistic && optimistic[1] === title ? optimistic[0] : null