Skip to content

REQ-F-069: SIGINT Handler Installation

Tier: Framework-Automatic | Priority: P0

Source: Silent assumption — agents send SIGINT to cancel running commands and expect exit code 130 (128 + SIGINT), not 1

Addresses: Severity: High / Token Spend: Medium / Time: Medium / Context: Low


Description

The framework MUST install a SIGINT signal handler for every command at startup. On SIGINT, the handler MUST: invoke the command's registered cleanup() hook, release any framework-managed locks, emit a cancellation JSON object to stdout (with "ok": false, "error": {"code": "CANCELLED", "signal": "SIGINT"}), flush stdout, and exit with code 130 (128 + SIGINT). The handler MUST be re-entrant safe — a second SIGINT during cleanup exits immediately without a double-write.

Agents that enforce time budgets by sending SIGINT (Ctrl+C equivalent) rely on exit code 130 to distinguish "I cancelled this" from "this failed" (exit 1). An uncaught SIGINT that produces exit 1 causes the agent to retry the cancelled operation, compounding side effects.

Acceptance Criteria

  • kill -INT <pid> on a running command produces a valid JSON cancellation response on stdout
  • Exit code after SIGINT is exactly 130
  • All framework-managed lock files are released after SIGINT
  • A second SIGINT during cleanup exits immediately with 130, no duplicate JSON output
  • Exit code 130 is registered in the command's exit code table (REQ-F-001)

Schema

No dedicated schema type — cancellation response uses response-envelope with "ok": false


Wire Format

Cancellation response emitted to stdout on SIGINT:

{
  "ok": false,
  "partial": true,
  "data": null,
  "error": {
    "code": "CANCELLED",
    "message": "Command cancelled by SIGINT",
    "signal": "SIGINT"
  },
  "warnings": [],
  "meta": {
    "request_id": "req_01HZ",
    "command": "deploy",
    "timestamp": "2026-04-01T12:00:00Z"
  }
}

Example

$ tool deploy --env prod &
[1] 12345
$ kill -INT 12345
→ stdout: {"ok":false,"partial":true,"data":null,"error":{"code":"CANCELLED","signal":"SIGINT"},...}
→ exit code: 130

Requirement Tier Relationship
REQ-F-013 F Specializes: SIGTERM handler; SIGINT follows identical pattern with exit code 130 instead of 143
REQ-F-031 F Extends: SIGINT must also forward to tracked child processes
REQ-F-001 F Provides: exit code 130 (128 + SIGINT) as a framework-defined constant
REQ-F-004 F Provides: response envelope used by the cancellation JSON output