fix(tasks): persist task_history row at task START, not only at finish — restart-kills leave no audit trail #1107
Labels
No labels
area:agents
area:dashboard
area:database
area:design
area:design-review
area:flows
area:infra
area:meta
area:security
area:sessions
area:webhook
area:workdir
security
type:bug
type:chore
type:meta
type:user-story
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference
charles/claude-hooks#1107
Loading…
Add table
Add a link
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
User story
As an operator investigating a stuck/lost task after a service restart, I want every dispatched task to have a
task_historyrow from the moment it starts, so that the recovery hint can flag it asinterruptedand I can see what was in flight.Background
On 2026-05-11, task
ca432f8f-d29e-4cab-8d42-22db730c9419ran for ~36 minutes ondev(issue #1104), got SIGKILL'd by ajust restartat ~15:13 UTC, and left no row intask_history. Boot-time recovery printed hints for other interrupted tasks (#994, #957, #1018, #1033) but nothing for #1104 because the row didn't exist.This means:
interruptedrow to trigger a session-invalidate sweep.Acceptance criteria
Start-time persistence
task_historyrow inserted withstatus='running'at the moment the worker callsstarting <id>(registry / worker boundary).id,repo,issue_number,user,agent,agent_type,model,provider,started_at. (Tokens / cost / turns / artifacts populated on finish as today.)success,failure,cancelled,interrupted,aborted_no_skill), the row is UPDATEd, not re-INSERTed.Schema / migration
finished_at,cost_usd,turns,artifacts, etc.status='running'is permitted for in-flight rows.finished_atto NULL for any pre-existing rows already markedinterrupted(no-op for the current set; defensive).Boot-time recovery
status='running'row whose worker is no longer alive is transitioned tostatus='interrupted'and emitted to the recovery hint log.claude_sdk_sessionsrow at the same time.Tests
task_historyrow present withstatus='running'.runningrow → on next boot, row becomesinterrupted+ recovery hint printed.success(no duplicate INSERT).Out of scope
agent_run_eventtable covers that separately.task_history; will pick up new rows automatically.References
apps/server/src/infrastructure/database/task-store.ts::persistTask(currently called on finish only).apps/server/src/background/worker.tsboot path; grep[recovery]log prefix.