Skip to content

feat(reminder): catch stale in-progress tasks, shape reminder after Claude Code - #37

Merged
tintinweb merged 1 commit into
masterfrom
feat/task-reminder-claude-shape
Jul 22, 2026
Merged

feat(reminder): catch stale in-progress tasks, shape reminder after Claude Code#37
tintinweb merged 1 commit into
masterfrom
feat/task-reminder-claude-shape

Conversation

@tintinweb

Copy link
Copy Markdown
Owner

What

Reworks the task system-reminder in two parts:

  1. Fix: stale in-progress tasks were never surfaced. The reminder only fired from tool_result, so a text-only turn (agent says "done" with no tool call) never triggered it — tasks left in_progress went unnoticed. Now turn_end detects this and schedules a reminder. This is the core fix from Fix stale in-progress task reminders #31 by @QuangThai — preserved intact, credited below.

  2. Shape the reminder after Claude Code's todo reminders. An empty-list nudge plus a JSON state echo of the current list, matching Claude Code's wording and structure (adapted to this extension's task tool names). The echo is capped at 10 tasks (completed dropped first) so it stays bounded on large/persistent lists, and it says list truncated instead of claiming completeness when capped.

Why the trigger matters here (and not in Claude Code)

Claude Code doesn't need staleness detection because its todo list is ephemeral, single-actor and in-context — state can't outlive the agent that manages it. pi-tasks' list is persistent and multi-agent, so state can go stale with no tool call to observe it. That's why the turn_end trigger is load-bearing here and the reminder needs an out-of-band nudge Claude Code doesn't.

Notes

  • Restores the "cheap-first" store.list() guard so the hot tool_result path does no disk I/O until a reminder could actually be due.
  • Stops mutating the shared cadence config (interval is now passed per-call).
  • Reminder size: for typical lists (≤5 tasks) it is smaller than the old fixed constant; capped at ~330 tokens for arbitrarily large lists.
  • subject is echoed as content to mirror Claude Code's todo item shape.

Credit

Supersedes #31 by @QuangThai, whose turn_end staleness trigger is the load-bearing fix and is preserved here. Co-authored accordingly.

Test plan

  • npx vitest run → 177 passing
  • npx tsc --noEmit clean
  • npx biome check clean

…laude Code

The system-reminder could previously only fire from the tool_result hook, so an
agent that finished work in a text-only turn (no tool call) never got nudged and
left tasks stuck in_progress. Detect that on turn_end and schedule a reminder for
the next LLM call.

Reshape the reminder after Claude Code's todo reminders: an empty-list nudge, or
a JSON state echo of the current list. The echo is capped at 10 tasks (completed
dropped first) to bound its size on large/persistent lists, and says so when
truncated rather than claiming to be the full list.

Also restore the cheap-first store.list() guard on the hot tool_result path and
stop mutating the shared cadence config.

Co-authored-by: Quang Thai <thainq@tryhand.tech>
@tintinweb
tintinweb merged commit 16304ae into master Jul 22, 2026
1 check passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant