Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions internal/context/prompt_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,12 @@ func TestDefaultToolUsagePromptIncludesPermissionAndAntiLoopGuidance(t *testing.
if !strings.Contains(toolUsage, "`todo_write`") {
t.Fatalf("expected Tool Usage to mention todo_write for task state, got %q", toolUsage)
}
if !strings.Contains(toolUsage, "If the user clearly switches to a different task") {
t.Fatalf("expected Tool Usage to describe task-switch todo handling, got %q", toolUsage)
}
if !strings.Contains(toolUsage, "mark it `canceled` before planning or executing the new task") {
t.Fatalf("expected Tool Usage to require canceling stale todos on task switches, got %q", toolUsage)
}
if !strings.Contains(toolUsage, "Execute todos sequentially in the main loop") {
t.Fatalf("expected Tool Usage to enforce sequential todo execution, got %q", toolUsage)
}
Expand Down
3 changes: 2 additions & 1 deletion internal/context/source_todos.go
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ func (todosSource) Sections(ctx context.Context, input BuildInput) ([]promptSect

lines = append(lines, "",
"stale_todo_reminder: If any todo above is no longer relevant to the current task,",
"cancel it via todo_write set_status=canceled before signaling completion.",
"or the user clearly switches to a different task, use todo_write to mark it completed",
"only if the work is actually done; otherwise set_status=canceled before moving on.",
)

return []promptSection{
Expand Down
8 changes: 7 additions & 1 deletion internal/context/source_todos_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -54,13 +54,19 @@ func TestTodosSourceSections(t *testing.T) {
if sections[0].Title != "Todo State" {
t.Fatalf("title = %q, want %q", sections[0].Title, "Todo State")
}
if strings.Contains(sections[0].Content, "done") {
if strings.Contains(sections[0].Content, `id="done"`) {
t.Fatalf("expected terminal todo filtered, got %q", sections[0].Content)
}
lines := strings.Split(sections[0].Content, "\n")
if len(lines) < 2 || !strings.Contains(lines[0], "in-progress") {
t.Fatalf("expected in_progress todo first, got %q", sections[0].Content)
}
if !strings.Contains(sections[0].Content, "user clearly switches to a different task") {
t.Fatalf("expected stale todo reminder to mention task switching, got %q", sections[0].Content)
}
if !strings.Contains(sections[0].Content, "only if the work is actually done") {
t.Fatalf("expected stale todo reminder to distinguish completed from canceled, got %q", sections[0].Content)
}
}

func TestTodosSourceSectionsBoundaries(t *testing.T) {
Expand Down
1 change: 1 addition & 0 deletions internal/promptasset/templates/core/tool_usage.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
- For multi-step implementation, debugging, refactoring, or long-running work, keep task state explicit via `todo_write` (plan/add/update/set_status/claim/complete/fail) instead of relying on implicit memory.
- Create todos that map to real acceptance work, not vague activity.
- Required todos are acceptance-relevant and must converge before finalization.
- If the user clearly switches to a different task, do not carry unfinished todos forward blindly: mark each old todo `completed` only when the work is actually done, otherwise mark it `canceled` before planning or executing the new task.
- `todo_write` parameters must match schema strictly: `id` must be a string (for example, `"3"` instead of `3`).
- `todo_write` does not auto-dispatch subagents. Setting todo metadata does not trigger execution by itself.
- `todo_write` `set_status` requires: `{"action":"set_status","id":"<todo_id>","status":"pending|in_progress|blocked|completed|failed|canceled"}`.
Expand Down
Loading