fix: surface silent task loss from auto-clear and disk failures#15
Open
kylesnowschwartz wants to merge 1 commit into
Open
fix: surface silent task loss from auto-clear and disk failures#15kylesnowschwartz wants to merge 1 commit into
kylesnowschwartz wants to merge 1 commit into
Conversation
Failure modes addressed:
- TaskStore.update() returned the same shape for both 'task missing' and
'task deleted', forcing callers to disambiguate by inspecting fields.
Subagent listeners in index.ts ignored the return entirely, so a
TaskExecute task that was auto-cleared while the subagent was running
would silently swallow the completion event.
- AutoClearManager.onTurnStart returned a boolean, hiding which task IDs
were just removed. The LLM had no way to know its earlier-known task
IDs had been auto-cleared, so subsequent TaskUpdate calls returned
'Task #X not found' for tasks the user could clearly see in context.
- TaskStore.load() silently swallowed JSON parse errors despite a
'start fresh' comment that did not match the code. No signal to the
user, no signal to the host.
- mkdirSync ran only in the constructor, so removing the tasks
directory mid-stream caused acquireLock and save to throw ENOENT
and lose the in-flight mutation.
Changes:
- task-store.ts: update() returns notFound: boolean; load() splits
ENOENT (silent) from parse errors (calls onCorruptFile callback);
ensureDir() runs inside acquireLock and save for auto-heal.
- auto-clear.ts: onTurnStart returns { cleared, ids } so the host can
tell the LLM exactly which tasks vanished.
- index.ts: subagent listeners check notFound and surface a UI notice
if work completed for a vanished task; tool_result handler drains
pendingAutoClearedIds onto the next tool result as a system-reminder
so the LLM stops trying to update vanished tasks; pendingAutoClearedIds
is reset on session_switch alongside other session-scoped state.
- 6 new tests covering file deletion, dir deletion, missing-id update,
successful update return shape, deletion return shape, and corrupt-file
preservation.
pe200012
added a commit
to pe200012/pi-tasks
that referenced
this pull request
May 16, 2026
Adapt the reminder cadence refactor to preserve PR tintinweb#15 auto-cleared task ID reminders and missing-task hardening.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Disclosure
This patch was AI-generated (Claude) at my request, motivated by a few silent-failure modes I noticed while using
pi-tasksin real work — most painfully, completed-tool events for an auto-cleared task being swallowed and the LLM repeatedly trying to update task IDs that had vanished from its context.QA level: light. I've verified the on-disk durability paths manually (corrupt file, deleted directory, missing-ID update) and the included unit tests pass (
151 passed, plusbiome checkandtsc --noEmitclean). I have not end-to-end exercised the auto-clear → system-reminder pathway or the subagent-vanish-during-run pathway in a live session — those rely on session-lifecycle timing I didn't try to synthesize. Treat accordingly; happy to iterate on whatever you'd like tightened, simplified, or reverted.Failure modes addressed
TaskStore.update()returned the same shape for both task missing and task deleted, forcing callers to disambiguate by inspecting fields. The subagent listeners inindex.tsignored the return entirely, so aTaskExecutetask that was auto-cleared while the subagent was running would silently swallow the completion event.AutoClearManager.onTurnStartreturned a boolean, hiding which task IDs were just removed. The LLM had no way to know its earlier-known task IDs had been auto-cleared, so subsequentTaskUpdatecalls returnedTask #X not foundfor tasks the user could clearly see in context.TaskStore.load()silently swallowed JSON parse errors despite a "start fresh" comment that did not match the code. No signal to the user, no signal to the host.mkdirSyncran only in the constructor, so removing the tasks directory mid-stream causedacquireLockandsaveto throwENOENTand lose the in-flight mutation.Changes
task-store.ts:update()returnsnotFound: boolean;load()splitsENOENT(silent) from parse errors (callsonCorruptFilecallback);ensureDir()runs insideacquireLockandsavefor auto-heal.auto-clear.ts:onTurnStartreturns{ cleared, ids }so the host can tell the LLM exactly which tasks vanished.index.ts: subagent listeners checknotFoundand surface a UI notice if work completed for a vanished task;tool_resulthandler drainspendingAutoClearedIdsonto the next tool result as a system-reminder so the LLM stops trying to update vanished tasks;pendingAutoClearedIdsis reset onsession_switchalongside other session-scoped state.What I actually verified
biome check src/ test/tsc --noEmitvitest runTaskUpdateof nonexistent IDrm -rf .pi/tasksmid-session, thenTaskUpdatetasks-*.jsonmid-sessiononCorruptFilewarning toast appeared in pi UI, next save healed the filependingAutoClearedIdssystem-reminder pathnotFoundUI noticeDiffstat:
5 files changed, +248, -30.