I0906 — Termination is graceful and proved against the real container
Handle SIGTERM and SIGINT so that a Machine that is being stopped, redeployed or autostopped finishes its in-flight responses and exits inside the platform's timeout.
BLOCKED wave 3 · p1 · implementation profile · parallel safe
Blocked. This issue cannot start until I0904 is done. The status is derived from that, not declared.
Objective
Handle SIGTERM and SIGINT so that a Machine that is being stopped, redeployed or autostopped finishes its in-flight responses and exits inside the platform's timeout.
Why
A profile with autostop and zero minimum machines means the process is terminated routinely rather than exceptionally. A server that is killed mid-response makes every deploy and every idle window a source of truncated requests.
Current state
Stopping is cooperative for the owner's own call — workers are unblocked and joined and an in-flight response is finished — but nothing binds that to a process signal.
Desired state
A termination signal stops accepting new connections, finishes what is in flight, and exits within a bounded, documented timeout, proved against the production container rather than against a unit test alone.
Scope
- apps/majordomus-cli/src/http/server.rs
- apps/majordomus-cli/src/commands/serve.rs
Out of scope
- Draining application state; the served layer is read-only
- Configuring provider kill signals unless a measurement shows the default is wrong
Dependencies
What waits on this
Acceptance criteria
- SIGTERM and SIGINT both begin an orderly stop
- A request in flight when the signal arrives receives its complete response
- The process exits within the documented timeout and reports a non-error exit
- The behaviour is proved against the production container, not only in-process
Validation
- cargo test --workspace --all-features
- bash test/run.sh
Evidence required
- sigterm_clean
- inflight_finished
- exit_within_timeout
Evidence
None recorded. Every token above needs a command or an artifact behind it before this issue can be completed; narrative is refused.
Risk
A signal handler that waits for an unbounded connection never exits and the platform kills it anyway. The timeout is part of the contract and must be declared.
Timeline
- started
- —
- verified
- —
- completed
- —
Those three fields, the evidence above and the state of the dependencies are all the status is made of. There is no status field to disagree with them.
Canonical record: .ai/repo/project/issues/I0906.yaml. Read it back with majordomus plan show I0906.