Summary
Follow-up to #671 (DB-level CAS guard). The minimum fix in #671 ensures a user cancel is never overwritten by a late SUCCESS at the database boundary. This ticket tackks the defense-in-depth layer the original report asked for: make the container task-runner aware that a cancel happened and surface it in the response.
Problem (residual after #671)
When the operator cancels mid-run, Claude Code currently catches the signal, emits a graceful final message, exits with code 0, and the agent task-runner reports:
```
INFO:agent_server.routers.chat:[Task] Task completed successfully
INFO: 172.28.0.5:37822 - "POST /api/task HTTP/1.1" 200 OK
```
The DB-level fix in #671 stops this from poisoning the schedule_executions row. But:
- Container logs still say "completed successfully" — confusing during incident triage.
- Agent has no signal that its work was repudiated; for agents with side effects (Slack post, sheet rows, CRM), the agent might still finish a half-baked deliverable on the next turn.
- The HTTP response carries no `status=cancelled` marker — only the gateway knows.
Asks
Related
Summary
Follow-up to #671 (DB-level CAS guard). The minimum fix in #671 ensures a user cancel is never overwritten by a late SUCCESS at the database boundary. This ticket tackks the defense-in-depth layer the original report asked for: make the container task-runner aware that a cancel happened and surface it in the response.
Problem (residual after #671)
When the operator cancels mid-run, Claude Code currently catches the signal, emits a graceful final message, exits with code 0, and the agent task-runner reports:
```
INFO:agent_server.routers.chat:[Task] Task completed successfully
INFO: 172.28.0.5:37822 - "POST /api/task HTTP/1.1" 200 OK
```
The DB-level fix in #671 stops this from poisoning the schedule_executions row. But:
Asks
Related