Skip to content
This repository was archived by the owner on Jul 24, 2026. It is now read-only.

test(up): the DECISIVE decoupling test — killing convoy up must not kill its agents - #105

Merged
myobie merged 1 commit into
mainfrom
decoupling-decisive-test
Jul 22, 2026
Merged

test(up): the DECISIVE decoupling test — killing convoy up must not kill its agents#105
myobie merged 1 commit into
mainfrom
decoupling-decisive-test

Conversation

@myobie

@myobie myobie commented Jul 22, 2026

Copy link
Copy Markdown
Collaborator

What & why

The permanent regression guard for the Nomad decoupling invariant after the 2026-07-22 incident: a convoy up restart mid-cutover self-severed and took the whole hetz fleet down (exit 143 across 11 agents).

This settles the forensic a-vs-b the CoS raised:

  • (a) a teardown misuse (someone ran convoy down / a session-or-pgroup kill), or
  • (b) a real bug where the decoupling does not hold in practice.

How

A process-level test (by necessity — real daemons + real signals) that:

  1. Stands up real, detached agent daemons via convoy's OWN production spawn primitive (spawnFromPtyFilespawnDaemon) — a dummy sleep harness so it needs no claude/st on the box.
  2. Supervises them with a real convoy up subprocess.
  3. Kills that subprocess BOTH waysSIGTERM (clean stop) and SIGKILL (hard crash, no graceful teardown) — and asserts every agent is still alive at the SAME pid.
  4. A fresh convoy up ADOPTS the survivors (same pids; no launch/respawn/replay of them in the JSON stream).
  5. The inverse: convoy down does tear them down (the one true kill path).

Result

All four pass. ⇒ The decoupling holds in practice, so the incident was misuse (a), not bug (b). If these ever fail, this file is the reproduction of (b).

Everything is scoped to a throwaway XDG_STATE_HOME, so it can never touch a live network. It runs in the vitest gate (test.yml, a normal runner — the lane that already shells out to real bin/convoy), not the hermetic nix flake check.

This is part 1 of 4 of the decoupling-hardening task (decisive test → recovery-parking fix → convoy restart → self-sever guard).

🤖 Generated with Claude Code

https://claude.ai/code/session_014gbfntB6cu21sL4YBp21LF

… kill its agents

The permanent regression guard for the Nomad invariant after the 2026-07-22 incident
(a `convoy up` restart mid-cutover took the whole hetz fleet down, exit 143 across 11).

Settles the forensic a-vs-b: (a) a teardown MISUSE vs (b) a real decoupling bug. It stands
up real, detached agent daemons via convoy's OWN production spawn primitive
(spawnFromPtyFile → spawnDaemon), supervises them with a real `convoy up` subprocess, then
kills that subprocess BOTH ways (SIGTERM and SIGKILL) and asserts every agent is still alive
at the SAME pid. A fresh `convoy up` must then ADOPT the survivors (same pids, no
launch/respawn/replay), and the inverse — `convoy down` — must actually tear them down.

Result: all four pass => the decoupling HOLDS in practice, so the incident was misuse (a),
NOT bug (b). If these ever fail, this file is the reproduction of (b).

Process-level by necessity (real daemons + real signals), scoped to a throwaway
XDG_STATE_HOME so it can never touch a live network. Runs in the vitest gate (test.yml,
normal runner) — the lane that already shells out to real bin/convoy — not the hermetic nix
flake check.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_014gbfntB6cu21sL4YBp21LF
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant