Skip to content

fix(worker-pool): honor renewed suspension between resumed workers - #5791

Merged
keweichen merged 1 commit into
mainfrom
factory/kc/publication-repair-75cf9db89b58cb7a-ac4d4c851f7a
Oct 21, 2026
Merged

keweichen merged 1 commit into
mainfrom
factory/kc/publication-repair-75cf9db89b58cb7a-ac4d4c851f7a

Conversation

@keweichen

Copy link
Copy Markdown
Collaborator

Priority

Level: medium
Reason: Owner-approved reliability improvement.

Closes

N/A — owner-approved work; no public issue is claimed as closed.

Summary

fix(worker-pool): honor renewed suspension between resumed workers

Review first: skills/worker-pool/scripts/pool_remedy.py, tests/skills/worker-pool/pool-remedy.test.py, tests/skills/worker-pool/pool-resume-suspension.test.py, tests/skills/worker-pool/pool-suspend-resume.test.py.

Checklist

  • Confirmed no other open PR closes the same issue (gh pr list --repo sonichi/sutando --search "closes #N")
  • Git author email matches my CLA-signed email (git log -1 --format='%ae' shows a GH-mapped email, not *.local or noreply@anthropic.com)
  • Single concern per PR — no bundled refactors / drive-by feature additions
  • Confirmed bug exists on upstream/main (or feature isn't already covered)
  • Test added (or N/A explained below)
  • Before/after evidence pasted below — the actual command output for both states, not a description of it (this is the Add demo video to README #1 reason PRs bounce)
  • Every claim in this PR body is verifiable from the diff or the pasted output — no statement the reviewer can't check
  • Live path? If this touches a bridge, network path, delivery loop, or startup, I included a real post-restart round-trip — unit tests / harnesses alone are not accepted for these
  • Stacked PR? I named the parent + merge order and will rebase/update + rerun full checks after the parent lands (or N/A)
  • Scanned added lines for host-specific hardcoded paths and inline home/workspace fallbacks; fixtures are narrowly scoped
  • If this PR adds or edits a CI workflow, I confirmed it actually runs on this PR (see the Checks tab — a branches: filter can silently exclude a stacked PR)
  • Doesn't reinvent workspace / home-path resolution — uses the resolve_workspace / resolveWorkspace / claude_home_path helpers (see CLAUDE.md "Workspace contract"; enforced by the lint-workspace-resolution, lint-claude-home-path, and workspace-leak-check CI checks)

Contribution observations (unchecked items remain reviewer decisions):

These observations used the isolated candidate; no production deployment was performed.

  • Risks / rollback: Change scope: In pool_remedy.py, check current pool suspension in the shared recovery coordinator before beginning a worker recovery. During resume, report workers skipped by a renewed suspension using the existing suspended outcome and preserve their supervision evidence. Preserve the new suspension marker, worker identity, lineage, labels, inbox ownership and existing selection policies. Add focused interleaving and lifecycle regressions. Exclude terminating an already-started worker, interrupting an in-flight launch, atomic suspend-versus-launch coordination, launcher changes, timer installation, delivery reconciliation and desktop presentation.
    Rollback: revert this PR. Production behavior after deployment remains to be observed.
  • Stacking: N/A; one concern against main.
  • Author maps to keweichen; CLA status must be observed on the PR.

Before / after evidence

Before

  • triage-evidence: pool_remedy.py:96-110 resumes selected workers and resets every attempted worker's ladder; recover():218-271 has no suspension check. At 2026-10-20T19:04:33Z, python3 [local path] exited 0: a separate suspend CLI completed after the first recovery while the pool lock was held, yet the second worker recovered and incarnations increased from 1 to 2. The renewed marker survived; second-worker supervision evidence did not. Injecting a suspended outcome independently reproduced evidence loss. This source-level witness used the existing FakeTmux runner, not real lifecycle validation. Results are recorded in diagnostics/triage-baseline-observation.json. The environment-loaded process-tools.py preflight passed private sockets, tmux 3.8 and scoped process inspection; diagnostics/capability-preflight.json explicitly reports product readiness unobserved.

Earlier baseline observations at 7f7f56a. These are historical; current-candidate evidence follows below.

/bin/zsh -c "python3 - <<'PY'
import json, os, subprocess, sys
p='[local path]'
env=os.environ.copy()
env.update(json.load(open(p+'/environment.json')))
r=subprocess.run(['python3',p+'/process-tools.py','preflight'],env=env,text=True,capture_output=True)
print(r.stdout)
print(r.stderr, file=sys.stderr)
print('preflight_exit='+str(r.returncode))
PY"
{"schema": "ag2-runtime-preflight/v1", "product_ready": "not observed", "tmux": {"available": true, "detail": "tmux 3.8\n"}, "process_inspection": {"available": true, "detail": "38961\n"}, "private_socket": {"available": true}}

preflight_exit=0

Exit: 0

/bin/zsh -c "python3 - <<'PY'
import json
from pathlib import Path
p=Path('[local path]')
e=json.loads((p/'environment.json').read_text())
for k in sorted(e):
    print(k+'='+e[k] if not any(s in k.lower() for s in ('secret','token','key','password')) else k+'=<redacted>')
print('runtime_endpoint_source_exists='+str((p/'runtime-endpoint.c').exists()))
print('capability_preflight='+str((p/'capability-preflight.json').exists()))
print('diagnostics='+str((p/'diagnostics').exists()))
PY"
CLAUDE_CONFIG_DIR=[local path]
PATH=[local path]
PYTHONPATH=[local path]
SUTANDO_AGENT_ID=factory-runtime-test
SUTANDO_APP_SUPPORT=
SUTANDO_DEFAULT_WORKSPACE=[local path]
SUTANDO_HA_DIR=[local path]
SUTANDO_HOST_LABEL=factory-runtime-test
SUTANDO_INSTANCE_ID=
SUTANDO_INSTANCE_REGISTRY=[local path]
SUTANDO_PACKAGED=
SUTANDO_RESULTS_DIR=[local path]
SUTANDO_RUNTIME_DB=[local path]
SUTANDO_RUNTIME_SOCKET=[local path]
SUTANDO_RUNTIME_STATE=[local path]
SUTANDO_RUN_DIR=[local path]
SUTANDO_STANDBY_STOP_TIMEOUT=2
SUTANDO_TEST_MODE=1
SUTANDO_TMUX_SOCKET=[local path]
SUTANDO_WATCHER_BEAT=
SUTANDO_WATCHER_TRANSITION_HOOK=
SUTANDO_WORKSPACE=[local path]
SUTANDO_WORKSPACE_DIR=[local path]
TEMP=[local path]
TMP=[local path]
TMPDIR=[local path]
runtime_endpoint_source_exists=True
capability_preflight=False
diagnostics=True

Exit: 0

After

  • acceptance-1: The new lifecycle test used production creation, the unchanged launcher, supplied subprocess environment and foreground private tmux. In the final private-home run, the first recovery launched at 22:10:12 UTC; a separate --suspend completed before recovery continued. At 22:10:13, resume reported the second worker as suspended, with no launch or new incarnation. Commands, readiness and outcomes are retained in lifecycle-evidence.json.

  • acceptance-2: Lifecycle assertions verified preservation of the renewed marker, skipped worker identity, lineage, roster label, pending/accepted ownership, payloads and supervision evidence. Two suspended sweeps launched nothing. Later explicit resume recovered that worker exactly once using its recorded session; another resume launched nothing.

  • acceptance-3: Without renewed local suspension, both workers recovered despite a foreign workspace suspension. Owner-paused workers stayed paused. The already-started worker retained PID 9045 through subsequent sweeps and resume. Focused tests also passed live-worker, indeterminate-probe, failed-launch, runtime-selection and ordinary-restart cases.

  • acceptance-4: Focused tests exercised the shared guard before probes/writes, selective resume evidence reset and existing suspension-between-sweep-actions behavior. Both lifecycle runs cleaned up successfully: six foreground tmux servers were reaped, all 83 recorded process IDs were absent, and scoped pgrep found no tmux, claude or fswatch descendants. See final-audit.json. No model conversation or authentication claim is made.

  • check-resume-suspension: python3 tests/skills/worker-pool/pool-resume-suspension.test.py: 3 tests passed, exit 0, in 95.829 seconds. Repeated at 2026-10-20T22:09:04Z with an explicit private scratch HOME: 3 passed, exit 0, in 84.753 seconds, within the 180-second limit. See resume-suspension-private-home.log and its JSON receipt.

  • check-suspend-resume-regressions: 2026-10-20T22:07:13Z: python3 tests/skills/worker-pool/pool-suspend-resume.test.py — 15 tests passed, exit 0, 0.491 seconds; limit 60 seconds.

  • check-recovery-regressions: 2026-10-20T22:07:13Z: python3 tests/skills/worker-pool/pool-remedy.test.py — 34 tests passed, exit 0, 1.577 seconds; limit 60 seconds.

  • check-restart-regressions: 2026-10-20T22:07:13Z: python3 tests/skills/worker-pool/pool-restart.test.py — 16 tests passed, exit 0, 1.997 seconds; limit 60 seconds.

  • runtime-preflight: Loaded environment.json and ran python3 [local path] preflight. Private sockets, PTY, actual tmux session, scoped process inspection, temporary files and compiler passed. Supplied PATH/PYTHONPATH were preserved, including fswatch poll_monitor, scratch mktemp and xcrun --no-cache adaptations. See capability-preflight.json.

  • coverage: Instrumented all 65 focused regression cases with python3 -m coverage run --rcfile=.coveragerc; all passed. diff-cover against original base 7f7f56a with --fail-under=95 measured 100%: 3 changed executable lines, none missing. No changed product files were unmeasured. Module coverage was 91%. Commands and measurements are retained under diagnostics/coverage.

  • repository-checks: git diff --check against the original base passed. bash scripts/review-checks.sh --diff [local path] passed hardcoded-path, root-artifact and comment-cap checks.

  • candidate-scope: Initial and final HEAD matched the exact candidate. All four changed paths are approved, the launcher is unchanged from the original base, and final git status --porcelain=v1 --untracked-files=all was empty at 2026-10-20T22:10:57Z.

Test plan

python3 tests/skills/worker-pool/pool-resume-suspension.test.py

Observed: PASS; exit 0.

test_both_recover_without_renewal_even_with_foreign_workspace_suspended (__main__.ResumeSuspensionLifecycle.test_both_recover_without_renewal_even_with_foreign_workspace_suspended) ... ok
test_owner_paused_worker_stays_paused (__main__.ResumeSuspensionLifecycle.test_owner_paused_worker_stays_paused) ... ok
test_renewed_suspension_skips_next_worker_and_later_resume_recovers_once (__main__.ResumeSuspensionLifecycle.test_renewed_suspension_skips_next_worker_and_later_resume_recovers_once) ... ok

----------------------------------------------------------------------
Ran 3 tests in 97.001s

OK
python3 tests/skills/worker-pool/pool-suspend-resume.test.py

Observed: PASS; exit 0.

...............
----------------------------------------------------------------------
Ran 15 tests in 0.033s

OK
python3 tests/skills/worker-pool/pool-remedy.test.py

Observed: PASS; exit 0.

test_an_io_failure_mid_close_is_a_recorded_outcome_not_an_exception (__main__.APartialCloseIsBounded.test_an_io_failure_mid_close_is_a_recorded_outcome_not_an_exception) ... ok
test_human_dispatch_rechecks_pause_and_suspension (__main__.ApplyingATick.test_human_dispatch_rechecks_pause_and_suspension) ... ok
test_only_recover_acts_and_escalate_passes_through (__main__.ApplyingATick.test_only_recover_acts_and_escalate_passes_through) ... ok
test_the_whole_loop_observe_decide_remedy_observe (__main__.ApplyingATick.test_the_whole_loop_observe_decide_remedy_observe) ... ok
test_a_codex_worker_without_a_recorded_run_is_not_relaunched (__main__.CodexRecovery.test_a_codex_worker_without_a_recorded_run_is_not_relaunched) ... ok
test_a_failed_codex_relaunch_leaves_no_open_incarnation (__main__.CodexRecovery.test_a_failed_codex_relaunch_leaves_no_open_incarnation) ... ok
test_a_live_codex_worker_is_not_re
[Excerpt: middle omitted; full recorded output SHA256 b4c882a45d8475578a96b719ee61f1068d7eea6b74a10f7611671bae99f2fa7f]
very_is_a_nonzero_exit) ... ok
test_a_malformed_id_is_refused (__main__.TheCommandLine.test_a_malformed_id_is_refused) ... ok
test_exactly_one_mode_is_required (__main__.TheCommandLine.test_exactly_one_mode_is_required) ... ok
test_a_dry_run_reports_the_login_card_it_would_raise (__main__.TheSweepOnALoggedOutWorker.test_a_dry_run_reports_the_login_card_it_would_raise) ... ok
test_a_pane_that_moves_on_to_another_wedge_retires_the_login_card (__main__.TheSweepOnALoggedOutWorker.test_a_pane_that_moves_on_to_another_wedge_retires_the_login_card)
One decision per (episode, kind): the acknowledged login card neither ... ok
test_the_real_run_cards_the_owner_and_restarts_nothing (__main__.TheSweepOnALoggedOutWorker.test_the_real_run_cards_the_owner_and_restarts_nothing) ... ok
test_a_paused_worker_is_never_relaunched (__main__.WhatItRefusesToTouch.test_a_paused_worker_is_never_relaunched) ... ok
test_a_worker_that_is_already_running_is_left_alone (__main__.WhatItRefusesToTouch.test_a_worker_that_is_already_running_is_left_alone) ... ok
test_a_worker_with_no_recorded_session_cannot_be_resumed (__main__.WhatItRefusesToTouch.test_a_worker_with_no_recorded_session_cannot_be_resumed) ... ok
test_an_indeterminate_probe_writes_nothing_and_is_not_already_running (__main__.WhatItRefusesToTouch.test_an_indeterminate_probe_writes_nothing_and_is_not_already_running) ... ok
test_an_unknown_roster_runtime_blocks_recovery_and_supervisor_rearm (__main__.WhatItRefusesToTouch.test_an_unknown_roster_runtime_blocks_recovery_and_supervisor_rearm) ... ok
test_an_unreadable_roster_blocks_recovery_and_supervisor_rearm (__main__.WhatItRefusesToTouch.test_an_unreadable_roster_blocks_recovery_and_supervisor_rearm) ... ok

----------------------------------------------------------------------
Ran 34 tests in 0.723s

OK
python3 tests/skills/worker-pool/pool-restart.test.py

Observed: PASS; exit 0.

................
----------------------------------------------------------------------
Ran 16 tests in 1.744s

OK

Canonical review scanner:

review-checks: PASS (hardcoded-paths + root-artifacts + prose-cap clean)
prose-cap: PASS (comment blocks within cap 2, exts .py)

Verified candidate: 4b455c41f89ede82054913bf2782c61bc53a39b6. Publication commit: d849a655ec2924d86e57e88a84a7805001a967e5. Both have tree 9cead8c68003742b12a536327d3c0bc6125cba4d; only factory-authored commit metadata changed. Acceptance evidence refers to the verified candidate; the scanner ran on the publication tree.

@qingyun-wu qingyun-wu left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reviewed at d849a65. Approving.

The fix matches policy the module already has. restart() and apply() already return SUSPENDED when suspension(workspace) is set. recover() was the one entry point that didn't check, so a suspension written while resume() was mid-loop didn't stop the workers after it. The new guard sits before any probe or write. resume() no longer forgets the ladder for a worker that came back SUSPENDED, so that worker's evidence survives until a real resume.

What I ran on this head:

  • pool-suspend-resume.test.py: 15 pass. pool-remedy.test.py: 34 pass.
  • Mutant: removing the recover() guard makes both suites fail.
  • Mutant: restoring forget=restarted makes pool-suspend-resume fail.
  • pool-resume-suspension.test.py, the real-tmux lifecycle, skips here ("requires the supplied disposable runtime environment"). For that part I'm relying on the PR's evidence.

On §15: the changed behavior is a refusal to relaunch. A running worker's delivery path is not touched. The real-tmux lifecycle test exercises exactly that refusal, so I don't see a further post-restart round trip that this diff needs.

CI is still running on this head. Merging is the repo owner's call.

@sonichi sonichi left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Review at d849a65: the fix is correct, with no code blockers.

recover() now checks suspension before any probe, run-close or spawn (pool_remedy.py:222), so a suspension renewed partway through a resume (e.g. an app quit) is honored. Main has no such check. A skipped worker stays in the renewed marker's stopped list, so a later --resume brings it back exactly once, and resume() keeps ladder evidence for skipped workers (:110). pool-suspend-resume (15) and pool-remedy (34) pass.

Non-blocking:

  • A narrow race remains: a renewal landing after the :222 check but before spawn() still launches the worker. apply() has the same gap already.
  • The new 358-line pool-resume-suspension.test.py skips unless a "supplied disposable runtime" exists, and compiles a runtime-endpoint.c that isn't in the repo. So it never runs in CI or locally. Please either make it self-contained or say plainly in the body that it's an out-of-repo harness. Its comments also refer to a "factory" and a "supplied endpoint" from outside the repo.

REVIEW.md §15 applies (worker restart after an app quit or relaunch). The evidence is harness-only, so one real post-relaunch resume with a renewed suspension is still owed.

@github-actions

Copy link
Copy Markdown
Contributor

Coverage Gate

✅ Diff coverage PASSES the 95% bar. Whole-tree (informational): 93%.

Diff Coverage

Diff: origin/main...HEAD, staged and unstaged changes

  • skills/worker-pool/scripts/pool_remedy.py (100%)

Summary

  • Total: 3 lines
  • Missing: 0 lines
  • Coverage: 100%

@keweichen

Copy link
Copy Markdown
Collaborator Author

Review follow-up evidence at unchanged head d849a655ec2924d86e57e88a84a7805001a967e5. No code or branch update was needed.

  • feedback-1: Retained the complete independent runtime observation on this unchanged commit after authenticating workers/6/events.jsonl against supplied SHA256 fb6f6b1adafc555ad2bfd0d3d8c53f947138d8cc2ab56f15932c553539940b3e and inspecting its witness commands, assertions and outputs. On 2026-10-21 UTC, real server.py PID 52282 started at 03:06:21.940, was stopped/reaped at 03:06:33.844, and relaunched as PID 55901 at 03:06:33.846. After production worker creation and launcher execution, separate --suspend completed at 03:06:39.587 before releasing the resume barrier. The next worker returned suspended; later resume recovered it exactly once. runtime-cli and production routing/inbox resolution also completed a post-relaunch task/result round trip. This satisfies the mandatory runtime request beyond harness tests. Authenticated excerpts are preserved in diagnostics/verify-authenticated-runtime-events.json; remote delivery and review gates remain pending.

Independent verification commands and observations:

/bin/zsh -lc 'git diff HEAD''^ HEAD -- skills/worker-pool/scripts/pool_remedy.py tests/skills/worker-pool/pool-remedy.test.py tests/skills/worker-pool/pool-suspend-resume.test.py tests/skills/worker-pool/pool-restart.test.py'
diff --git a/skills/worker-pool/scripts/pool_remedy.py b/skills/worker-pool/scripts/pool_remedy.py
index d78e4188..35625a63 100644
--- a/skills/worker-pool/scripts/pool_remedy.py
+++ b/skills/worker-pool/scripts/pool_remedy.py
@@ -107,7 +107,8 @@ def resume(workspace, repo, *, runner=None, spawn=None) -> dict:
         dead = [w for w, o in obs.items()
                 if w in stopped and o.session_alive is False and not o.paused]
         restarted = {w: recover(workspace, repo, w, runner=runner, spawn=spawn) for w in dead}
-        _reset_ladders(workspace, forget=restarted)
+        _reset_ladders(workspace, forget=[
+            w for w, out in restarted.items() if out["outcome"] != SUSPENDED])
     return {"was_suspended": was, "restarted": restarted}
 
 
@@ -218,6 +219,8 @@ def close_dead_runs(workspace, worker_id, closed: list | None = None) -> list:
 def recover(workspace, repo, worker_id, *, runner=None, spawn=None) -> dict:
     """Recover one worker. Never raises for an expected refusal: the caller is a
     timer with nobody watching, so every outcome is a value it can record."""
+    if suspension(workspace):
+        return {"worker_id": worker_id, "outcome": SUSPENDED}
     spawn = spawn or sw.spawn
     if sup.is_paused(workspace, worker_id):
         return {"worker_id": worker_id, "outcome": PAUSED}
diff --git a/tests/skills/worker-pool/pool-remedy.test.py b/tests/skills/worker-pool/pool-remedy.test.py
index 64ff2676..8d9e4d62 100644
--- a/tests/skills/worker-pool/pool-remedy.test.py
+++ b/tests/skills/worker-pool/pool-remedy.test.py
@@ -108,6 +108,23 @@ class Base(unittest.TestCase):
 
 
 class ItResumesTheSameWorker(Base):
+    def test_shared_recovery_checks_suspension_before_probes_or_writes(self):
+        rem.suspend(self.ws, "renewed-stop")
+        before = {p: p.read_bytes() for p in wi.worker_dir(self.ws, self.wid).glob("*.json")}
+        with mock.patch.object(sup, "is_paused", side_effect=Assert
[Excerpt: middle omitted; full recorded output SHA256 3bf06fe16fe1cb49812733a11502dc7e8213fe97df19a602671eea593a6cbd2e]
for p in before}, before)
+        self.assertEqual(len(self.t.launches()), self.launched_before)
+
+    def test_another_workspaces_suspension_does_not_block_recovery(self):
+        rem.suspend(self.ws / "other", "unrelated-stop")
+        self.assertEqual(self.recover()["outcome"], rem.RECOVERED)
+        self.assertEqual(len(self.t.launches()), self.launched_before + 1)
+
     def test_a_dead_worker_comes_back_on_its_own_session(self):
         out = self.recover()
         self.assertEqual(out["outcome"], rem.RECOVERED)
diff --git a/tests/skills/worker-pool/pool-suspend-resume.test.py b/tests/skills/worker-pool/pool-suspend-resume.test.py
index a25f39e6..c30a72b3 100644
--- a/tests/skills/worker-pool/pool-suspend-resume.test.py
+++ b/tests/skills/worker-pool/pool-suspend-resume.test.py
@@ -159,6 +159,53 @@ class Suspended(Base):
 
 
 class Resume(Base):
+    def test_renewed_suspension_preserves_only_the_skipped_workers_evidence(self):
+        self.roster(DEAD, ALIVE)
+        evidence = ps.WorkerEvidence(watcher_consecutive=3, wedge_consecutive=2,
+                                     wedge_first_detected_at=1.0, last_pane_id="old-pane")
+        rem.sup.save_state(self.ws, ps.SupervisionState(
+            last_sample_at=2.0, workers={DEAD: evidence, ALIVE: evidence}))
+        rem.suspend(self.ws, "initial-stop")
+        real_recover = rem.recover
+        renewed = []
+
+        def recover(ws, repo, wid, **kw):
+            if wid == DEAD:
+                rem.suspend(ws, "renewed-stop")
+                renewed.append(rem.suspended_path(ws).read_bytes())
+                return {"worker_id": wid, "outcome": rem.RECOVERED}
+            return real_recover(ws, repo, wid, **kw)
+
+        with mock.patch.object(rem.sup, "observe", return_value={DEAD: obs(False), ALIVE: obs(False)}), \
+                mock.patch.object(rem, "recover", side_effect=recover), \
+                mock.patch.object(rem.sup, "tick", return_value=tick_result()) as tick, \
+                mock.patch.object(rem, "ensure_supervisors") as supervisors, \
+                mock.patch.object(rem, "ensure_input_watches") as watches, \
+                mock.patch.object(rem.sw, "spawn", side_effect=AssertionError("launched skipped worker")):
+            rc, out = self.run_main("--resume")
+        self.assertEqual(rc, 0)
+        self.assertEqual(out["resume"]["restarted"], {
+            DEAD: {"worker_id": DEAD, "outcome": rem.RECOVERED},
+            ALIVE: {"worker_id": ALIVE, "outcome": rem.SUSPENDED}})
+        self.assertEqual(rem.suspended_path(self.ws).read_bytes(), renewed[0])
+        self.assertEqual(rem.sup.load_state(self.ws).workers, {ALIVE: evidence})
+        self.assertFalse(tick.call_args.kwargs["persist"])
+        supervisors.assert_not_called()
+        watches.assert_not_called()
+
+    def test_non_suspended_outcomes_keep_the_existing_evidence_reset(self):
+        for outcome in (rem.RECOVERED, rem.ALREADY_RUNNING, rem.PAUSED,
+                        rem.NO_SESSION, rem.INDETERMINATE, rem.FAILED):
+            with self.subTest(outcome=outcome):
+                self.roster(DEAD)
+                rem.sup.save_state(self.ws, ps.SupervisionState(workers={
+                    DEAD: ps.WorkerEvidence(wedge_consecutive=2)}))
+                rem.suspend(self.ws, "initial-stop")
+                with mock.patch.object(rem.sup, "observe", return_value={DEAD: obs(False)}), \
+                        mock.patch.object(rem, "recover", return_value={"outcome": outcome}):
+                    rem.resume(self.ws, REPO)
+                self.assertNotIn(DEAD, rem.sup.load_state(self.ws).workers)
+
     def test_resume_without_a_marker_is_just_a_sweep(self):
         with mock.patch.object(rem.sup, "observe") as observe, mock.patch.object(rem, "recover") as rec:
             self.assertEqual(rem.resume(self.ws, REPO), {"was_suspended": None, "restarted": {}})

Exit: 0

/bin/zsh -lc "rg -n 'def test_' tests/skills/worker-pool/pool-suspend-resume.test.py tests/skills/worker-pool/pool-restart.test.py"
tests/skills/worker-pool/pool-restart.test.py:70:    def test_an_escalated_worker_restarts_now_and_its_ladder_starts_clean(self):
tests/skills/worker-pool/pool-restart.test.py:80:    def test_a_running_worker_is_left_alone_and_loses_only_its_death_ladder(self):
tests/skills/worker-pool/pool-restart.test.py:86:    def test_a_wedged_live_worker_keeps_its_wedge_and_watcher_ladders(self):
tests/skills/worker-pool/pool-restart.test.py:97:    def test_resume_and_restart_share_the_ladder_reset(self):
tests/skills/worker-pool/pool-restart.test.py:110:    def test_a_paused_worker_is_not_restarted_and_keeps_its_ladder(self):
tests/skills/worker-pool/pool-restart.test.py:116:    def test_a_suspended_pool_restarts_nothing(self):
tests/skills/worker-pool/pool-restart.test.py:124:    def test_every_other_outcome_is_failed_exits_one_and_names_why(self):
tests/skills/worker-pool/pool-restart.test.py:134:    def test_a_bookkeeping_crash_after_the_restart_is_reported_not_raised(self):
tests/skills/worker-pool/pool-restart.test.py:142:    def test_any_unexpected_error_is_still_one_json_line(self):
tests/skills/worker-pool/pool-restart.test.py:148:    def test_an_empty_id_is_the_json_reply_with_exit_two(self):
tests/skills/worker-pool/pool-restart.test.py:154:    def test_restart_refuses_dry_run(self):
tests/skills/worker-pool/pool-restart.test.py:159:    def test_an_invalid_id_is_failed_with_exit_two(self):
tests/skills/worker-pool/pool-restart.test.py:169:    def test_restart_is_one_mode_among_the_others(self):
tests/skills/worker-pool/pool-restart.test.py:196:    def test_a_restart_waits_for_a_sweep_then_acts(self):
tests/skills/worker-pool/pool-restart.test.py:207:    def test_a_restart_that_cannot_get_the_lock_fails_without_acting(self):
tests/skills/worker-pool/pool-restart.test.py:218:    def test_the_sweep_holds_the_same_lock_for_its_whole_act_and_save(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:73:    def test_suspend_records_reason_time_and_the_workers_the_stop_takes_down(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:83:    def test_an_unreadable_pool_still_suspends_and_names_no_workers(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:89:    def test_a_bad_worker_id_on_resume_exits_2_not_a_traceback(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:97:    def test_a_marker_that_is_not_a_record_still_suspends_and_names_no_workers(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:105:    def test_the_cli_suspends_and_exits_zero(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:110:    def test_exactly_one_mode(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:118:    def test_apply_takes_no_action_while_suspended_but_still_reports_escalations(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:128:    def test_a_quit_landing_mid_sweep_stops_the_remaining_actions(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:140:    def test_a_suspended_sweep_observes_without_advancing_the_ladder_or_starting_anything(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:152:    def test_a_suspended_sweep_still_reports_escalations(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:162:    def test_renewed_suspension_preserves_only_the_skipped_workers_evidence(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:196:    def test_non_suspended_outcomes_keep_the_existing_evidence_reset(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:209:    def test_resume_without_a_marker_is_just_a_sweep(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:214:    def test_resume_restarts_only_what_the_stop_took_down_and_keeps_an_escalation(self):
tests/skills/worker-pool/pool-suspend-resume.test.py:233:    def test_the_cli_resumes_then_sweeps_and_a_failed_restart_exits_nonzero(self):

Exit: 0

Running-product observation:

  • monitor-user-journey: python3 -u [local path] exited 0. On 2026-10-21 UTC, real server.py PID 52282 started at 03:06:21.940, stopped/reaped at 03:06:33.844, and relaunched as PID 55901 at 03:06:33.846. Both logs confirmed the private socket listener; runtime-cli successfully submitted tasks after relaunch. Production create_worker.py, pool_remedy.py, pool_route_handler.py and resolve-inbox-entry exercised creation, suspension, recovery and preserved payload consumption. At 03:06:39.841, resume reported one recovered worker and one suspended worker. runtime-cli task get-result subsequently returned the operator-published test result, and task status returned done. This demonstrates local product flow, not automatic watcher consumption or model inference. Full commands, PIDs, timestamps and outputs are in monitor3-journey.jsonl.

  • monitor-repeatability: The successful witness invoked pool_remedy.py --workspace [local path] --resume, then separately completed --suspend monitor3-renewed-quit at 03:06:39.587 before releasing its launch barrier. Two subsequent --sweep commands returned suspended='monitor3-renewed-quit 1792551999', with no recovery or state loss. Later --resume recovered the held worker as PID 59059; repeating --resume returned restarted={}. First-worker PID 57261 stayed unchanged. Repeating runtime-cli task submit with the same idempotency key returned the same task ID and state=done. Exact argv and outputs are recorded in monitor3-journey.jsonl.

  • feedback-1: Supplied the mandatory current-head post-relaunch witness using real server.py, runtime-cli, foreground private tmux, production worker creation/launcher and recovery CLI. Renewed suspension held the next worker; persisted ownership survived; later resume recovered it once. This is additional running-product evidence beyond the frozen tests. Automatic watcher consumption and authenticated conversation continuity are not claimed. Controller publication, description updates, CI/CLA and replacement of CHANGES_REQUESTED remain pending delivery gates.

/bin/zsh -c "sed -n '1,240p' skills/worker-pool/scripts/pool_route_handler.py; sed -n '1,230p' skills/worker-pool/scripts/worker_delivery.py; sed -n '1,160p' tests/skills/worker-pool/pool-suspend-resume.test.py; sed -n '1,140p' skills/worker-pool/scripts/launch-worker-session.sh; sed -n '1,130p' src/pool_supervision.py; git show --stat --format=fuller HEAD"
#!/usr/bin/env python3
"""The router, as the core watcher's task-event handler.

One process, two watches: the core's watcher already watches `tasks/`, so the
router runs inside it rather than as a second daemon. This file is dispatch
only — every routing decision belongs to `pool_router`/`pool_roster`.

The watcher's handler protocol carries the design's recipient rules exactly:

    probe 3   decline    not a roster hit -- unbound, or a name never created.
                          The core takes it; it is a recipient, not a fallback.
    probe 0   accept     every target is on the roster; the real run delivers.
    4         must-handle a header id that is not the file's, or an admitted
                          target left without a sentinel: the core must not
                          inherit it, and 0 would release the claim on nothing.

Run: called by src/watch-tasks-stream.sh; see dispatch_task there.
"""
from __future__ import annotations

import argparse
import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parent))
# local_task_protocol lives in the core; repo root is parents[3] from here
sys.path.insert(0, str(Path(__file__).resolve().parents[3] / "src"))

import local_task_protocol as ltp  # noqa: E402

import pool_roster as pr  # noqa: E402
import worker_picker_commands as wpc  # noqa: E402

import pool_router as rt  # noqa: E402
import pool_advertise as pa
import pool_routing_receipt as prr  # noqa: E402

DECLINE = 3
MUST_HANDLE = 4
PICKER_WIRE = "worker-picker"


def read_task(task_file: str) -> dict:
    """The watcher hands a task FILE; the router takes a task DICT.

    `requested_worker` (and its legacy alias) is read only from ABOVE `task:`,
    so a body cannot forge it. `channel_id`/`source` are read leniently: the gateway stamps them
    below `task:`, where the strict parse never looks.
    """
    text = Path(task_file).read_text(encoding="utf-8", errors="re
[Excerpt: middle omitted; full recorded output SHA256 4fa08bf53079df901bedf574f0ccde5301c1ae06c17e8fb6534ba4d84b0a746d]
# Third half of that seam: without the resolver a worker reads the sentinel
# itself, so an unforwarded one is the zero-byte read, not a missing option.
[ -n "${SUTANDO_INBOX_RESOLVER:-}" ] && ENV_ARGS+=(-e "SUTANDO_INBOX_RESOLVER=$SUTANDO_INBOX_RESOLVER")
[ -n "${SUTANDO_INBOX_RESOLVER_TIMEOUT:-}" ] && ENV_ARGS+=(-e "SUTANDO_INBOX_RESOLVER_TIMEOUT=$SUTANDO_INBOX_RESOLVER_TIMEOUT")
# The worker gate `/startup --worker` runs, named by the spawner: this script
# is the worker's own, but the path itself is still spawn_worker.py's to name
# (it points at worker_bootstrap.py in this same skill) — forward, don't
# hardcode, so a future spawner can still override it.
[ -n "${SUTANDO_WORKER_BOOTSTRAP:-}" ] && ENV_ARGS+=(-e "SUTANDO_WORKER_BOOTSTRAP=$SUTANDO_WORKER_BOOTSTRAP")
# The done-flag writer, same seam: tmux hands a new session the SERVER's env,
# so an unforwarded writer leaves the hook complete but never reached.
[ -n "${SUTANDO_POOL_DELIVERY_SCRIPT:-}" ] && ENV_ARGS+=(-e "SUTANDO_POOL_DELIVERY_SCRIPT=$SUTANDO_POOL_DELIVERY_SCRIPT")
# This worker's own watcher command, forwarded absolute: the session's cwd is
# the spawner's --cwd, which need not be the repo, so a relative path would
# resolve against the wrong directory.
ENV_ARGS+=(-e "SUTANDO_WATCHER_CMD=$REPO/src/watch-tasks-stream.sh")
# The worker's own watcher beats state/watchers/<id>.alive, so the pool can
# observe it as a file rather than a process scan.
ENV_ARGS+=(-e "SUTANDO_WATCHER_BEAT=$REPO/skills/worker-pool/scripts/pool_beat.py")
# Canonical + executable, or EMPTY: a relative/`..` interpreter path resolves
# against the worker's cwd, and only an explicit -e overrides a stale
# server-global value.
WORKER_PY=""
if [ -n "$PY" ] && [ -x "$PY" ]; then
  _pyd="${PY%/*}"; [ "$_pyd" = "$PY" ] && _pyd="."
  _pyd="$(cd "$_pyd" 2>/dev/null && pwd -P)" && WORKER_PY="$_pyd/${PY##*/}"
  [ -n "$WORKER_PY" ] && [ -x "$WORKER_PY" ] || WORKER_PY=""
fi
ENV_ARGS+=(-e "SUTANDO_PY=$WORKER_PY")
# Forward the embedder-provided default workspace for the same reason as
# above (tmux takes the server env, not this shell's).
[ -n "${SUTANDO_DEFAULT_WORKSPACE:-}" ] && ENV_ARGS+=(-e "SUTANDO_DEFAULT_WORKSPACE=$SUTANDO_DEFAULT_WORKSPACE")
if [ "${SUTANDO_SELF_DEVELOPMENT_ENABLED+x}" = x ]; then
  ENV_ARGS+=(-e "SUTANDO_SELF_DEVELOPMENT_ENABLED=$SUTANDO_SELF_DEVELOPMENT_ENABLED")
fi
forward_skill_manifest_config
ENV_ARGS+=(${SKILL_MANIFEST_ENV_ARGS[@]+"${SKILL_MANIFEST_ENV_ARGS[@]}"})
resolve_claude_credential_proxy
if [ -n "${ANTHROPIC_BASE_URL:-}" ]; then
  ENV_ARGS+=(-e "ANTHROPIC_BASE_URL=$ANTHROPIC_BASE_URL")
fi
# Test probe: dump the assembled worker env forwarding and exit — same shape
# as the core launcher's --print-core-env, so a regression suite can assert
# the allowlist/proxy-routing policy without touching tmux. No production
# caller passes this.
if [ "${1:-}" = "--print-env" ]; then
  printf '%s\n' ${ENV_ARGS[@]+"${ENV_ARGS[@]}"}
  exit 0
fi

# The watcher sees SUTANDO_INSTANCE_ID in every worker session and therefore
# requires the pool delivery writer. Fail before creating a session that could
# receive tasks but cannot safely acknowledge them.
if [ -z "${SUTANDO_POOL_DELIVERY_SCRIPT:-}" ] || \
sed: src/pool_supervision.py: No such file or directory
commit d849a655ec2924d86e57e88a84a7805001a967e5
Author:     keweichen <15038247+keweichen@users.noreply.github.com>
AuthorDate: Tue Oct 20 22:04:23 2026 +0000
Commit:     keweichen <15038247+keweichen@users.noreply.github.com>
CommitDate: Tue Oct 20 22:04:23 2026 +0000

    fix(worker-pool): honor renewed suspension between resumed workers

 skills/worker-pool/scripts/pool_remedy.py          |   5 +-
 tests/skills/worker-pool/pool-remedy.test.py       |  17 +
 .../worker-pool/pool-resume-suspension.test.py     | 358 +++++++++++++++++++++
 .../skills/worker-pool/pool-suspend-resume.test.py |  47 +++
 4 files changed, 426 insertions(+), 1 deletion(-)

Exit: 0

/bin/zsh -c "python3 - <<'PY'
from pathlib import Path
r=Path('[local path]')
s=(r/'monitor2-witness.py').read_text().replace('monitor2-','monitor3-').replace('print(json.dumps(row,default=str),flush=True)','print(json.dumps(row,default=str),flush=True,file=sys.stderr)')
(r/'monitor3-witness.py').write_text(s);(r/'diagnostics/monitor3-witness-script.txt').write_text(s)
print((r/'diagnostics/monitor2-resume.stdout').read_text())
PY
python3 -u [local path]"
{"at": "2026-10-21T03:05:57.551697+00:00", "milestone": "post-launch barrier", "pid": 44467, "worker": "6e2c751584e943988d9e0f0ec7b6e304", "session": "bff4ba39-1528-42b9-a448-ba75d7159164"}
{
  "auth_expired": [],
  "cards": {},
  "decisions": {
    "66871af817ae4f3a9c7d761aee756734": "nothing",
    "6e2c751584e943988d9e0f0ec7b6e304": "nothing"
  },
  "escalations": [],
  "rearms": {},
  "recoveries": {},
  "resume": {
    "restarted": {
      "66871af817ae4f3a9c7d761aee756734": {
        "outcome": "suspended",
        "worker_id": "66871af817ae4f3a9c7d761aee756734"
      },
      "6e2c751584e943988d9e0f0ec7b6e304": {
        "closed_runs": [
          "69098e2057d54093a48fd138d730565a"
        ],
        "outcome": "recovered",
        "session_id": "bff4ba39-1528-42b9-a448-ba75d7159164",
        "worker_id": "6e2c751584e943988d9e0f0ec7b6e304"
      }
    },
    "was_suspended": "monitor2-initial-quit 1792551950"
  },
  "suspended": "monitor2-renewed-quit 1792551957"
}

{"at": "2026-10-21T03:06:21.598204+00:00", "milestone": "candidate", "commit": "d849a655ec2924d86e57e88a84a7805001a967e5", "adaptations": ["supplied PATH and PYTHONPATH preserved", "synthetic C endpoint: lifecycle and argv only", "scratch HOME/Library/LaunchAgents regular file prevents timer installation before launchctl", "trace-only post-launch barrier; no product function replaced"]}
{"at": "2026-10-21T03:06:21.701838+00:00", "milestone": "process started", "name": "monitor3-tmux", "command": ["tmux", "-D", "-f", "/dev/null", "-S", "[local path]"], "pid": 52221}
{"at": "2026-10-21T03:06:21.939765+00:00", "milestone": "process started", "name": "monitor3-api-before", "command": ["python3", "./src/runtime-api/server.py"], "pid": 52282}
{"at": "2026-10-21T03:06:22.257075+00:00", "milestone": "API ready", "pid": 52282, "health": {"state": "offline"}}
{"at": "2026-10-21T03:06:27.379529+00:00", "milestone": "worker ready", "worker": "086cadf4f3ab4da2b0873b29c3c
[Excerpt: middle omitted; full recorded output SHA256 989a09bc02135df635ffb64d5e14d021beb259d9b5e9cf4b187f6d7d8a85d864]
mmand,command:python3 './hooks/gdocs-write-guard.py' --repo '.'}]},{matcher:Bash|Write|Edit|MultiEdit|NotebookEdit,hooks:[{type:command,command:python3 './hooks/native-pim-guard.py'}]}],PostToolUse:[{matcher:Skill,hooks:[{type:command,command:python3 './hooks/skill-usage-telemetry.py'}]},{matcher:mcp__.*__composio_exec,hooks:[{type:command,command:python3 './hooks/gdocs-write-guard.py' --repo '.'}]}]}}", "--resume", "0db9b135-fbdf-4380-94a4-ea1fc7e6c09f", "--", "/startup", "--worker"], "pane": "factory synthetic endpoint ready; no conversation or authentication"}
{"at": "2026-10-21T03:06:47.455176+00:00", "milestone": "later resume recovered exactly once", "held": "032897115e664051b23f79838449a964", "pid": 59059, "original_session": "596c9376-e9fc-4867-a312-94f3c760778e", "later": {"auth_expired": [], "cards": {}, "cards_closed": [], "decisions": {"032897115e664051b23f79838449a964": "nothing", "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"}, "escalations": [], "escapes": {}, "input_watches": {"032897115e664051b23f79838449a964": {"outcome": "watching", "started": true, "worker_id": "032897115e664051b23f79838449a964"}, "086cadf4f3ab4da2b0873b29c3c1c75a": {"outcome": "watching", "started": true, "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"}}, "rearms": {}, "recoveries": {}, "resume": {"restarted": {"032897115e664051b23f79838449a964": {"closed_runs": ["1ec972e4981a49e38911b64007a9cf3d"], "outcome": "recovered", "session_id": "596c9376-e9fc-4867-a312-94f3c760778e", "worker_id": "032897115e664051b23f79838449a964"}}, "was_suspended": "monitor3-renewed-quit 1792551999"}, "supervisors": {"032897115e664051b23f79838449a964": {"outcome": "supervised", "worker_id": "032897115e664051b23f79838449a964"}, "086cadf4f3ab4da2b0873b29c3c1c75a": {"outcome": "supervised", "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"}}}, "repeated": {"auth_expired": [], "cards": {}, "cards_closed": [], "decisions": {"032897115e664051b23f79838449a964": "nothing", "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"}, "escalations": [], "escapes": {}, "input_watches": {"032897115e664051b23f79838449a964": {"outcome": "watching", "worker_id": "032897115e664051b23f79838449a964"}, "086cadf4f3ab4da2b0873b29c3c1c75a": {"outcome": "watching", "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"}}, "rearms": {}, "recoveries": {}, "resume": {"restarted": {}, "was_suspended": null}, "supervisors": {"032897115e664051b23f79838449a964": {"outcome": "supervised", "worker_id": "032897115e664051b23f79838449a964"}, "086cadf4f3ab4da2b0873b29c3c1c75a": {"outcome": "supervised", "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"}}}, "incarnations": 2}
{"at": "2026-10-21T03:06:48.325428+00:00", "milestone": "real API post-relaunch task round trip", "server_before": 52282, "server_after": 55901, "task_id": "task-rtapi-ce23ab8f25b64fe3fb94e6b47f8823103041c8aaa3c8efbaf1423432eabbd985", "worker": "032897115e664051b23f79838449a964", "resolver_payload": "[local path]", "result": {"taskId": "task-rtapi-ce23ab8f25b64fe3fb94e6b47f8823103041c8aaa3c8efbaf1423432eabbd985", "result": "Local monitor consumed the preserved post-relaunch payload; synthetic lifecycle endpoint, no model conversation."}, "status": {"taskId": "task-rtapi-ce23ab8f25b64fe3fb94e6b47f8823103041c8aaa3c8efbaf1423432eabbd985", "state": "done"}, "repeated_submission": {"taskId": "task-rtapi-ce23ab8f25b64fe3fb94e6b47f8823103041c8aaa3c8efbaf1423432eabbd985", "state": "done"}, "consumer": "production one-shot routing and inbox resolver; operator-published test result, no automatic watcher/model claim"}
{"at": "2026-10-21T03:06:48.429200+00:00", "milestone": "journey assertions passed"}
{"at": "2026-10-21T03:06:53.419370+00:00", "milestone": "cleanup complete", "processes": [{"pid": 56087, "exit": 0, "reaped": true}, {"pid": 55901, "exit": 0, "reaped": true}, {"pid": 52282, "exit": 0, "reaped": true}, {"pid": 52221, "exit": 0, "reaped": true}], "tracked_remaining": []}

Exit: 0

Please reassess the requested evidence and leave a fresh review.

@sonichi sonichi left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On my REVIEW.md §15 request at d849a65: not yet satisfied. The follow-up evidence (#5791 (comment)) is the diff, the unit-test listings, and a hashed events log I can't inspect from the PR. None of that shows a real worker pool.

The exact observation still missing: on a real pool (scratch workspace and scratch tmux socket are fine), with one worker stopped and its session dead:

  1. start pool_remedy --resume;
  2. renew the suspension (write the marker, as an app quit does) before that worker's recover() runs;
  3. show that its outcome is SUSPENDED, that no new tmux session or process was spawned for it, and that it stays in the renewed marker's stopped list;
  4. then a later --resume brings it back exactly once.

A slowed recover(), or a breakpoint to force the ordering, is fine. Post the commands and the observed outputs, and I'll clear this.

@keweichen

Copy link
Copy Markdown
Collaborator Author

The earlier evidence comment omitted the middle of the completed runtime trace, including the renewed suspension and the first resume result. Here are those observations and the driver that produced them; this is retained evidence from the same run, not a new run.

Checked head: d849a655ec2924d86e57e88a84a7805001a967e5. Observation time: 2026-10-21 03:06 UTC.

The pool used real foreground tmux, the checked head's create_worker.py, worker launcher, pool_remedy.py, suspension marker, worker registry and incarnation files in a scratch workspace. Both worker sessions were stopped and confirmed absent before resume. A trace breakpoint after the first successful production spawn() forced renewal before the next worker's recover() ran. No production function was replaced.

The worker process was a disclosed synthetic lifecycle endpoint. It exercised real tmux sessions, process creation and original session arguments; it did not provide an authenticated model conversation. The separate API task result was operator-published test data and is not offered as proof of automatic watcher/model consumption. The observation relevant here is the real pool's suspension and resume behavior.

Commands and synchronization used by the retained driver (S is the checked repository's skills/worker-pool/scripts; R is the scratch directory):

if len(sys.argv)>1 and sys.argv[1]=='trace-entry':
 barrier=Path(sys.argv[2]);target=sys.argv[3];sys.argv=sys.argv[3:]
 def trace(frame,event,arg):
  if frame.f_code.co_filename==str(S/'spawn_worker.py') and frame.f_code.co_name=='spawn':
   if event=='return' and isinstance(arg,dict) and arg.get('worker_id'):
    record(milestone='post-launch barrier',pid=os.getpid(),worker=arg['worker_id'],session=arg['runtime_session_id'])
    barrier.with_suffix('.ready').write_text(json.dumps(arg))
    wait(lambda:barrier.with_suffix('.release').exists(),'separate suspend completion',90)
    sys.settrace(None)
   return trace
  return None
 sys.settrace(trace)
 runpy.run_path(target,run_name='__main__');sys.exit(0)
# ... scratch setup and production worker creation; full driver below ...
 command=['python3',R/'monitor3-witness.py','trace-entry',barrier,S/'pool_remedy.py','--workspace',ws,'--repo',REPO,'--resume']
 output=(D/'monitor3-resume.stdout').open('w');error=(D/'monitor3-resume.stderr').open('w');logs.extend([output,error])
 resume=subprocess.Popen(list(map(str,command)),env=E,cwd=REPO,stdout=output,stderr=error);children.append(resume);record(command=command,pid=resume.pid)
 wait(lambda:barrier.with_suffix('.ready').exists() or resume.poll() is not None,'first successful resume launch',60)
 assert resume.poll() is None,(D/'monitor3-resume.stderr').read_text()
 ready=json.loads(barrier.with_suffix('.ready').read_text());assert ready['worker_id']==first
 firstpid=endpoint_pid(first,'--resume',ready['runtime_session_id']);assert absent(held)
 renewed=remedy('--suspend','monitor3-renewed-quit');marker=rem.suspended_path(ws).read_bytes();assert held in json.loads(marker)['stopped']
 record(milestone='separate suspend completed before barrier release',marker=json.loads(marker),resume_pid=resume.pid)
 barrier.with_suffix('.release').touch();assert resume.wait(timeout=60)==0
 result=json.loads((D/'monitor3-resume.stdout').read_text());record(milestone='post-relaunch resume outcome',pid=resume.pid,result=result)
 assert result['resume']['restarted'][held]['outcome']=='suspended' and result['resume']['restarted'][first]['outcome']=='recovered'
 def unchanged():
  assert absent(held)
  assert rem.suspended_path(ws).read_bytes()==marker
  assert owned()==before_owned
  assert wi.incarnations_path(ws,held).read_bytes()==before_runs
  assert wi.current_path(ws,held).read_bytes()==before_current
  assert sup.load_state(ws).workers[held]==evidence
  assert endpoint_pid(first,'--resume',ready['runtime_session_id'])==firstpid
 unchanged()
 for n in range(2):
  sweep=remedy('--sweep');assert sweep['suspended'].startswith('monitor3-renewed-quit');unchanged();record(milestone='repeat suspended sweep',repeat=n+1,result=sweep,preserved_files={k:hashlib.sha256(v).hexdigest() for k,v in before_owned.items()},held_incarnations=len(wi.incarnations(ws,held)))
 original_session=wi.sessions(ws,held)[-1]['session_id'];later=remedy('--resume');assert list(later['resume']['restarted'])==[held] and later['resume']['restarted'][held]['outcome']=='recovered'
 heldpid=endpoint_pid(held,'--resume',original_session);assert len(wi.incarnations(ws,held))==before_total[held]+1 and owned()==before_owned
 assert endpoint_pid(first,'--resume',ready['runtime_session_id'])==firstpid
 again=remedy('--resume');assert again['resume']['restarted']=={};assert len(wi.incarnations(ws,held))==before_total[held]+1
 record(milestone='later resume recovered exactly once',held=held,pid=heldpid,original_session=original_session,later=later,repeated=again,incarnations=len(wi.incarnations(ws,held)))

The recorded output below preserves the complete resume result and suspension marker. For the two suspended sweeps, only the unrelated preserved_files hash map was omitted; the result and incarnation count are retained. The held worker was 032897115e664051b23f79838449a964. The assertions above checked that its tmux session stayed absent and its incarnation/current files stayed byte-identical; the later resume increased incarnations from one to two, and another resume restarted nothing.

[
  {
    "at": "2026-10-21T03:06:32.625830+00:00",
    "milestone": "fixture setup through production writers",
    "first": "086cadf4f3ab4da2b0873b29c3c1c75a",
    "held": "032897115e664051b23f79838449a964",
    "binding": "runtime-api",
    "supervision": {
      "first_detected_at": null,
      "consecutive": 0,
      "recover_issued_at": null,
      "escalated": false,
      "watcher_first_detected_at": 10.0,
      "watcher_consecutive": 3,
      "rearm_issued_at": 20.0,
      "watcher_escalated": false,
      "wedge_first_detected_at": 30.0,
      "wedge_consecutive": 2,
      "wedge_escalated": false,
      "wedge_kind": null,
      "last_pane_id": "monitor3-evidence"
    }
  },
  {
    "at": "2026-10-21T03:06:33.843848+00:00",
    "milestone": "API stopped",
    "pid": 52282,
    "exit": 0,
    "reaped": true
  },
  {
    "at": "2026-10-21T03:06:39.587481+00:00",
    "milestone": "separate suspend completed before barrier release",
    "marker": {
      "reason": "monitor3-renewed-quit",
      "at": 1792551999,
      "stopped": [
        "032897115e664051b23f79838449a964",
        "086cadf4f3ab4da2b0873b29c3c1c75a"
      ]
    },
    "resume_pid": 56087
  },
  {
    "at": "2026-10-21T03:06:39.841225+00:00",
    "milestone": "post-relaunch resume outcome",
    "pid": 56087,
    "result": {
      "auth_expired": [],
      "cards": {},
      "decisions": {
        "032897115e664051b23f79838449a964": "nothing",
        "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"
      },
      "escalations": [],
      "rearms": {},
      "recoveries": {},
      "resume": {
        "restarted": {
          "032897115e664051b23f79838449a964": {
            "outcome": "suspended",
            "worker_id": "032897115e664051b23f79838449a964"
          },
          "086cadf4f3ab4da2b0873b29c3c1c75a": {
            "closed_runs": [
              "2664d519ad694523b56a7195a6f7b119"
            ],
            "outcome": "recovered",
            "session_id": "0db9b135-fbdf-4380-94a4-ea1fc7e6c09f",
            "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"
          }
        },
        "was_suspended": "monitor3-initial-quit 1792551992"
      },
      "suspended": "monitor3-renewed-quit 1792551999"
    }
  },
  {
    "at": "2026-10-21T03:06:40.674299+00:00",
    "milestone": "repeat suspended sweep",
    "repeat": 1,
    "result": {
      "auth_expired": [],
      "cards": {},
      "decisions": {
        "032897115e664051b23f79838449a964": "nothing",
        "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"
      },
      "escalations": [],
      "rearms": {},
      "recoveries": {},
      "suspended": "monitor3-renewed-quit 1792551999"
    },
    "held_incarnations": 1
  },
  {
    "at": "2026-10-21T03:06:41.272469+00:00",
    "milestone": "repeat suspended sweep",
    "repeat": 2,
    "result": {
      "auth_expired": [],
      "cards": {},
      "decisions": {
        "032897115e664051b23f79838449a964": "nothing",
        "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"
      },
      "escalations": [],
      "rearms": {},
      "recoveries": {},
      "suspended": "monitor3-renewed-quit 1792551999"
    },
    "held_incarnations": 1
  },
  {
    "at": "2026-10-21T03:06:47.455176+00:00",
    "milestone": "later resume recovered exactly once",
    "held": "032897115e664051b23f79838449a964",
    "pid": 59059,
    "original_session": "596c9376-e9fc-4867-a312-94f3c760778e",
    "later": {
      "auth_expired": [],
      "cards": {},
      "cards_closed": [],
      "decisions": {
        "032897115e664051b23f79838449a964": "nothing",
        "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"
      },
      "escalations": [],
      "escapes": {},
      "input_watches": {
        "032897115e664051b23f79838449a964": {
          "outcome": "watching",
          "started": true,
          "worker_id": "032897115e664051b23f79838449a964"
        },
        "086cadf4f3ab4da2b0873b29c3c1c75a": {
          "outcome": "watching",
          "started": true,
          "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"
        }
      },
      "rearms": {},
      "recoveries": {},
      "resume": {
        "restarted": {
          "032897115e664051b23f79838449a964": {
            "closed_runs": [
              "1ec972e4981a49e38911b64007a9cf3d"
            ],
            "outcome": "recovered",
            "session_id": "596c9376-e9fc-4867-a312-94f3c760778e",
            "worker_id": "032897115e664051b23f79838449a964"
          }
        },
        "was_suspended": "monitor3-renewed-quit 1792551999"
      },
      "supervisors": {
        "032897115e664051b23f79838449a964": {
          "outcome": "supervised",
          "worker_id": "032897115e664051b23f79838449a964"
        },
        "086cadf4f3ab4da2b0873b29c3c1c75a": {
          "outcome": "supervised",
          "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"
        }
      }
    },
    "repeated": {
      "auth_expired": [],
      "cards": {},
      "cards_closed": [],
      "decisions": {
        "032897115e664051b23f79838449a964": "nothing",
        "086cadf4f3ab4da2b0873b29c3c1c75a": "nothing"
      },
      "escalations": [],
      "escapes": {},
      "input_watches": {
        "032897115e664051b23f79838449a964": {
          "outcome": "watching",
          "worker_id": "032897115e664051b23f79838449a964"
        },
        "086cadf4f3ab4da2b0873b29c3c1c75a": {
          "outcome": "watching",
          "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"
        }
      },
      "rearms": {},
      "recoveries": {},
      "resume": {
        "restarted": {},
        "was_suspended": null
      },
      "supervisors": {
        "032897115e664051b23f79838449a964": {
          "outcome": "supervised",
          "worker_id": "032897115e664051b23f79838449a964"
        },
        "086cadf4f3ab4da2b0873b29c3c1c75a": {
          "outcome": "supervised",
          "worker_id": "086cadf4f3ab4da2b0873b29c3c1c75a"
        }
      }
    },
    "incarnations": 2
  },
  {
    "at": "2026-10-21T03:06:48.429200+00:00",
    "milestone": "journey assertions passed"
  },
  {
    "at": "2026-10-21T03:06:53.419370+00:00",
    "milestone": "cleanup complete",
    "processes": [
      {
        "pid": 56087,
        "exit": 0,
        "reaped": true
      },
      {
        "pid": 55901,
        "exit": 0,
        "reaped": true
      },
      {
        "pid": 52282,
        "exit": 0,
        "reaped": true
      },
      {
        "pid": 52221,
        "exit": 0,
        "reaped": true
      }
    ],
    "tracked_remaining": []
  }
]

The driver exited 0; cleanup reaped all direct children and found no remaining tmux descendants. The original requester should evaluate whether these concrete observations satisfy the remaining requirement; this does not grant approval or waive any repository gate.

Complete retained observation driver (scratch path replaced by <scratch>)

This is the successful script reconstructed from its recorded creation command and two recorded temporary observer corrections. It is shown for inspection, not as a portable one-command test: environment.json and the lifecycle endpoint source below were supplied disposable test prerequisites. The scratch LaunchAgents path deliberately prevents host timer installation.

import os,sys,json,time,subprocess,signal,shlex,hashlib,runpy,traceback
from pathlib import Path
from datetime import datetime,timezone
R=Path('<scratch>');D=R/'diagnostics';REPO=Path.cwd();S=REPO/'skills/worker-pool/scripts'
E=os.environ.copy();E.update(json.loads((R/'environment.json').read_text()));E.update({'PYTHONDONTWRITEBYTECODE':'1','HOME':str(R/'monitor3-home'),'SUTANDO_TELEMETRY':'0','ANTHROPIC_BASE_URL':'http://factory-runtime.invalid','SUTANDO_NOTIFIER_GRACE_PERIOD':'300','SUTANDO_NOTIFIER_ROLE_POLL':'1','SUTANDO_TMUX_SOCKET':str(R/'monitor3-tmux.sock')})
E.update({'SUTANDO_WORKSPACE':str(R/'monitor3-workspace'),'SUTANDO_WORKSPACE_DIR':str(R/'monitor3-workspace'),'SUTANDO_DEFAULT_WORKSPACE':str(R/'monitor3-workspace'),'SUTANDO_RESULTS_DIR':str(R/'monitor3-workspace/results'),'SUTANDO_RUNTIME_STATE':str(R/'monitor3-workspace/state'),'SUTANDO_RUNTIME_DB':str(R/'monitor3-workspace/state/runtime.sqlite'),'SUTANDO_HA_DIR':str(R/'monitor3-workspace/state/ha'),'SUTANDO_RUNTIME_SOCKET':str(R/'monitor3-api.sock'),'CLAUDE_CONFIG_DIR':str(R/'monitor3-claude')})
if len(sys.argv)>1 and sys.argv[1]=='trace-entry': E['PATH']=str(R/'monitor3-endpoint')+os.pathsep+E['PATH']
os.environ.clear();os.environ.update(E)
J=D/'monitor3-journey.jsonl'
def record(**kw):
 row={'at':datetime.now(timezone.utc).isoformat(),**kw}
 with J.open('a') as f:f.write(json.dumps(row,default=str)+'\n')
 if 'milestone' in row: print(json.dumps(row,default=str),flush=True,file=sys.stderr)

def wait(pred,desc,timeout=25):
 stop=time.monotonic()+timeout
 while time.monotonic()<stop:
  if pred():return
  time.sleep(.1)
 raise AssertionError('timeout: '+desc)

if len(sys.argv)>1 and sys.argv[1]=='trace-entry':
 barrier=Path(sys.argv[2]);target=sys.argv[3];sys.argv=sys.argv[3:]
 def trace(frame,event,arg):
  if frame.f_code.co_filename==str(S/'spawn_worker.py') and frame.f_code.co_name=='spawn':
   if event=='return' and isinstance(arg,dict) and arg.get('worker_id'):
    record(milestone='post-launch barrier',pid=os.getpid(),worker=arg['worker_id'],session=arg['runtime_session_id'])
    barrier.with_suffix('.ready').write_text(json.dumps(arg))
    wait(lambda:barrier.with_suffix('.release').exists(),'separate suspend completion',90)
    sys.settrace(None)
   return trace
  return None
 sys.settrace(trace)
 runpy.run_path(target,run_name='__main__');sys.exit(0)

home=Path(E['HOME']);(home/'Library').mkdir(parents=True,exist_ok=True)
(home/'Library/LaunchAgents').write_text('Disposable timer-installation exclusion: deliberate non-directory.\n')
endpoint=R/'monitor3-endpoint';endpoint.mkdir(exist_ok=True)
children=[];logs=[];tm=None;api=None;barrier=R/'monitor3-resume-unique';ws=Path(E['SUTANDO_WORKSPACE']);ws.mkdir(exist_ok=True)

def run(argv,check=True,timeout=40,stdin=None,env=None):
 argv=list(map(str,argv));start=datetime.now(timezone.utc).isoformat()
 p=subprocess.Popen(argv,cwd=REPO,env=env or E,stdin=subprocess.PIPE if stdin is not None else subprocess.DEVNULL,stdout=subprocess.PIPE,stderr=subprocess.PIPE,text=True)
 try:out,err=p.communicate(stdin,timeout=timeout)
 except BaseException:
  p.terminate();out,err=p.communicate(timeout=10);record(command=argv,pid=p.pid,start=start,exit=p.returncode,stdout=out[-16000:],stderr=err[-16000:],timed_out=True);raise
 record(command=argv,pid=p.pid,start=start,exit=p.returncode,stdout=out[-16000:],stderr=err[-16000:],reaped=True)
 if check:assert p.returncode==0,(argv,p.returncode,out,err)
 return subprocess.CompletedProcess(argv,p.returncode,out,err)

def start(argv,name):
 log=(D/(name+'.log')).open('w');logs.append(log)
 p=subprocess.Popen(list(map(str,argv)),cwd=REPO,env=E,stdout=log,stderr=log);children.append(p)
 record(milestone='process started',name=name,command=argv,pid=p.pid);return p

def tmux(*args,check=True):return run(['tmux','-S',E['SUTANDO_TMUX_SOCKET'],*args],check=check)
def cli(*args):return json.loads(run(['python3',REPO/'src/runtime-cli/sutando-runtime.py',*args]).stdout)
def remedy(*args):return json.loads(run(['python3',S/'pool_remedy.py','--workspace',ws,'--repo',REPO,*args],timeout=90).stdout)
def api_start(name):
 p=start(['python3',REPO/'src/runtime-api/server.py'],name)
 sock=Path(E['SUTANDO_RUNTIME_SOCKET'])
 wait(lambda:sock.exists() or p.poll() is not None,'runtime socket')
 assert p.poll() is None
 health=cli('runtime','health');record(milestone='API ready',pid=p.pid,health=health)
 return p

def gone(pid):
 try:os.kill(pid,0);return False
 except ProcessLookupError:return True

def descendants(pid):
 p=run(['pgrep','-P',pid],check=False)
 assert p.returncode in (0,1),p.stderr
 return [nested for c in map(int,p.stdout.split()) for nested in [*descendants(c),c]]

try:
 commit=run(['git','rev-parse','HEAD']).stdout.strip();assert commit=='d849a655ec2924d86e57e88a84a7805001a967e5'
 assert not run(['git','status','--porcelain=v1']).stdout
 record(milestone='candidate',commit=commit,adaptations=['supplied PATH and PYTHONPATH preserved','synthetic C endpoint: lifecycle and argv only','scratch HOME/Library/LaunchAgents regular file prevents timer installation before launchctl','trace-only post-launch barrier; no product function replaced'])
 run(['cc',R/'runtime-endpoint.c','-o',endpoint/'claude'])
 E['PATH']=str(endpoint)+os.pathsep+E['PATH'];os.environ['PATH']=E['PATH']
 tm=start(['tmux','-D','-f','/dev/null','-S',E['SUTANDO_TMUX_SOCKET']],'monitor3-tmux')
 wait(lambda:Path(E['SUTANDO_TMUX_SOCKET']).exists() or tm.poll() is not None,'private tmux');assert tm.poll() is None
 tmux('set-option','-g','default-shell','/bin/bash');tmux('new-session','-d','-s','monitor3-anchor','sleep','900')
 api=api_start('monitor3-api-before')
 sys.path.insert(0,str(S));import pool_remedy as rem
 wi,sw,sup,pd,ps=rem.wi,rem.sw,rem.sup,rem.pd,rem.ps
 def absent(w):return tmux('has-session','-t','='+wi.tmux_session_name(w),check=False).returncode==1
 def endpoint_pid(w,flag,sid):
  name=wi.tmux_session_name(w)
  pid=int(tmux('list-panes','-t','='+name+':0','-F','#{pane_pid}').stdout)
  argv=shlex.split(run(['ps','-p',pid,'-o','args=']).stdout)
  assert Path(argv[0]).name=='claude' and argv[argv.index(flag)+1]==sid and argv[argv.index('--name')+1]==name,argv
  pane=tmux('capture-pane','-p','-t','='+name+':0.0').stdout
  assert 'factory synthetic endpoint ready' in pane
  record(milestone='worker ready',worker=w,pid=pid,argv=argv,pane=pane.strip());return pid
 workers=[]
 for label in ['Monitor first','Monitor second']:
  folder=R/label.replace(' ','-');folder.mkdir(exist_ok=True)
  row=json.loads(run(['python3',S/'create_worker.py','--workspace',ws,'--repo',REPO,'--folder',folder,'--label',label,'--runtime','claude','--socket',E['SUTANDO_TMUX_SOCKET'],'--json'],timeout=60).stdout)
  assert row['remedy_timer']['ensured'] is False and 'FileExistsError' in row['remedy_timer']['why'],row
  endpoint_pid(row['worker_id'],'--session-id',row['runtime_session_id']);workers.append(row)
 ids=list(sup.supervised_workers(ws));assert len(ids)==2
 first,held=ids
 sw.pr.bind_room(ws,'runtime-api',held)
 evidence=ps.WorkerEvidence(watcher_consecutive=3,watcher_first_detected_at=10.0,rearm_issued_at=20.0,wedge_consecutive=2,wedge_first_detected_at=30.0,last_pane_id='monitor3-evidence')
 sup.save_state(ws,ps.SupervisionState(last_sample_at=time.time(),workers={w:evidence for w in ids}))
 record(milestone='fixture setup through production writers',first=first,held=held,binding='runtime-api',supervision=evidence.__dict__)
 remedy('--suspend','monitor3-initial-quit')
 for w in ids:
  pid=int(tmux('list-panes','-t','='+wi.tmux_session_name(w)+':0','-F','#{pane_pid}').stdout)
  os.kill(pid,signal.SIGTERM);wait(lambda:absent(w),'worker stopped');wait(lambda:gone(pid),'worker reaped')
 wait(lambda:tmux('list-sessions','-F','#{session_name}').stdout.strip()=='monitor3-anchor','old worker supervisors exited',40)
 before_pid=api.pid;api.terminate();api.wait(timeout=10);record(milestone='API stopped',pid=api.pid,exit=api.returncode,reaped=True)
 api=api_start('monitor3-api-after');assert api.pid!=before_pid
 taskids=[]
 for tag in ['pending','accepted']:
  out=cli('task','submit','Monitor post-relaunch '+tag,'--idempotency-key','monitor3-'+tag)
  tid=out['taskId'];taskids.append(tid)
  run(['python3',S/'pool_route_handler.py','--workspace',ws,'--task-file',ws/'tasks'/(tid+'.txt')])
  sentinel=pd.find(ws,held,tid);assert sentinel is not None
  payload=Path(run([S/'resolve-inbox-entry',sentinel,'--workspace',ws]).stdout.strip())
  assert 'Monitor post-relaunch '+tag in payload.read_text()
  if tag=='accepted':pd.accept(sentinel);pd.mark_done(ws,held,tid,published=False)
 assert len(pd.pending(ws,held))==1 and len(pd.accepted(ws,held))==1
 def owned():
  paths=[wi.sessions_path(ws,held),sw.pr.roster_path(ws)]
  for base in [pd.deliveries_dir(ws,held),ws/'tasks',ws/'state/attribution',wi.worker_dir(ws,held)/'done']:
   if base.exists():paths.extend(p for p in base.rglob('*') if p.is_file())
  return {str(p.relative_to(ws)):p.read_bytes() for p in paths}
 before_owned=owned();before_runs=wi.incarnations_path(ws,held).read_bytes();before_current=wi.current_path(ws,held).read_bytes()
 before_total={w:len(wi.incarnations(ws,w)) for w in ids}
 command=['python3',R/'monitor3-witness.py','trace-entry',barrier,S/'pool_remedy.py','--workspace',ws,'--repo',REPO,'--resume']
 output=(D/'monitor3-resume.stdout').open('w');error=(D/'monitor3-resume.stderr').open('w');logs.extend([output,error])
 resume=subprocess.Popen(list(map(str,command)),env=E,cwd=REPO,stdout=output,stderr=error);children.append(resume);record(command=command,pid=resume.pid)
 wait(lambda:barrier.with_suffix('.ready').exists() or resume.poll() is not None,'first successful resume launch',60)
 assert resume.poll() is None,(D/'monitor3-resume.stderr').read_text()
 ready=json.loads(barrier.with_suffix('.ready').read_text());assert ready['worker_id']==first
 firstpid=endpoint_pid(first,'--resume',ready['runtime_session_id']);assert absent(held)
 renewed=remedy('--suspend','monitor3-renewed-quit');marker=rem.suspended_path(ws).read_bytes();assert held in json.loads(marker)['stopped']
 record(milestone='separate suspend completed before barrier release',marker=json.loads(marker),resume_pid=resume.pid)
 barrier.with_suffix('.release').touch();assert resume.wait(timeout=60)==0
 result=json.loads((D/'monitor3-resume.stdout').read_text());record(milestone='post-relaunch resume outcome',pid=resume.pid,result=result)
 assert result['resume']['restarted'][held]['outcome']=='suspended' and result['resume']['restarted'][first]['outcome']=='recovered'
 def unchanged():
  assert absent(held)
  assert rem.suspended_path(ws).read_bytes()==marker
  assert owned()==before_owned
  assert wi.incarnations_path(ws,held).read_bytes()==before_runs
  assert wi.current_path(ws,held).read_bytes()==before_current
  assert sup.load_state(ws).workers[held]==evidence
  assert endpoint_pid(first,'--resume',ready['runtime_session_id'])==firstpid
 unchanged()
 for n in range(2):
  sweep=remedy('--sweep');assert sweep['suspended'].startswith('monitor3-renewed-quit');unchanged();record(milestone='repeat suspended sweep',repeat=n+1,result=sweep,preserved_files={k:hashlib.sha256(v).hexdigest() for k,v in before_owned.items()},held_incarnations=len(wi.incarnations(ws,held)))
 original_session=wi.sessions(ws,held)[-1]['session_id'];later=remedy('--resume');assert list(later['resume']['restarted'])==[held] and later['resume']['restarted'][held]['outcome']=='recovered'
 heldpid=endpoint_pid(held,'--resume',original_session);assert len(wi.incarnations(ws,held))==before_total[held]+1 and owned()==before_owned
 assert endpoint_pid(first,'--resume',ready['runtime_session_id'])==firstpid
 again=remedy('--resume');assert again['resume']['restarted']=={};assert len(wi.incarnations(ws,held))==before_total[held]+1
 record(milestone='later resume recovered exactly once',held=held,pid=heldpid,original_session=original_session,later=later,repeated=again,incarnations=len(wi.incarnations(ws,held)))
 tid=taskids[0];sentinel=pd.find(ws,held,tid);payload=Path(run([S/'resolve-inbox-entry',sentinel,'--workspace',ws]).stdout.strip());assert 'Monitor post-relaunch pending' in payload.read_text()
 answer='Local monitor consumed the preserved post-relaunch payload; synthetic lifecycle endpoint, no model conversation.\n'
 run(['python3',REPO/'src/result_publish.py',ws/'results'/(tid+'.txt')],stdin=answer)
 retrieved=cli('task','get-result',tid);assert answer.strip() in json.dumps(retrieved)
 status=cli('task','status',tid)
 repeat=cli('task','submit','Monitor post-relaunch pending','--idempotency-key','monitor3-pending');assert repeat['taskId']==tid
 record(milestone='real API post-relaunch task round trip',server_before=before_pid,server_after=api.pid,task_id=tid,worker=held,resolver_payload=payload,result=retrieved,status=status,repeated_submission=repeat,consumer='production one-shot routing and inbox resolver; operator-published test result, no automatic watcher/model claim')
 assert not run(['git','status','--porcelain=v1']).stdout
 (D/'monitor3-outcome.json').write_text(json.dumps({'status':'PASS','commit':commit,'first':first,'held':held,'first_pid':firstpid,'held_pid':heldpid,'server_before':before_pid,'server_after':api.pid,'task_ids':taskids,'owned_sha256':{k:hashlib.sha256(v).hexdigest() for k,v in before_owned.items()}},indent=2))
 record(milestone='journey assertions passed')
except BaseException:
 record(milestone='journey error',error=traceback.format_exc());raise
finally:
 barrier.with_suffix('.release').touch()
 cleanup=[]
 for p in reversed(children):
  if p is tm:continue
  if p.poll() is None:p.terminate()
  try:p.wait(timeout=10)
  except subprocess.TimeoutExpired:p.kill();p.wait(timeout=5)
  cleanup.append({'pid':p.pid,'exit':p.returncode,'reaped':True})
 if tm is not None:
  try:
   for pid in descendants(tm.pid) if tm.poll() is None else []:
    try:os.kill(pid,signal.SIGTERM)
    except ProcessLookupError:continue
    try:wait(lambda:gone(pid),'descendant '+str(pid),6)
    except AssertionError:
     try:os.kill(pid,signal.SIGKILL)
     except ProcessLookupError:pass
     wait(lambda:gone(pid),'killed descendant '+str(pid),5)
   remaining=descendants(tm.pid) if tm.poll() is None else [];assert not remaining,remaining
  finally:
   if tm.poll() is None:tmux('kill-server',check=False)
   tm.wait(timeout=10);cleanup.append({'pid':tm.pid,'exit':tm.returncode,'reaped':True})
 for f in logs:f.close()
 record(milestone='cleanup complete',processes=cleanup,tracked_remaining=[p.pid for p in children if p.poll() is None])
 (D/'monitor3-cleanup.json').write_text(json.dumps({'processes':cleanup,'tracked_remaining':[p.pid for p in children if p.poll() is None]},indent=2))
Disclosed lifecycle endpoint source used for the worker processes

This small endpoint keeps a real process and terminal alive and exposes its session arguments. It performs no model inference or authentication.

/* Synthetic long-lived process for launcher argument/lifecycle tests only.
 * It is NOT a model, authentication fixture, or conversation implementation.
 * Compile under a disposable directory with output name claude or codex.
 * Observe its actual argv and PID through the scoped process observer.
 */
#include <signal.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
static volatile sig_atomic_t done = 0;
static void stop(int sig) { (void)sig; done = 1; }
int main(int argc, char **argv) {
    if (argc == 2 && strcmp(argv[1], "--version") == 0) {
        puts("factory synthetic runtime endpoint v1 (no model)"); return 0;
    }
    if (argc == 3 && strcmp(argv[1], "login") == 0 && strcmp(argv[2], "status") == 0) {
        puts("factory synthetic login-status response; no account or authentication tested"); return 0;
    }
    signal(SIGTERM, stop); signal(SIGINT, stop); signal(SIGHUP, stop);
    puts("factory synthetic endpoint ready; no conversation or authentication");
    fflush(stdout);
    while (!done) sleep(1);
    return 0;
}

@sonichi sonichi left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

My REVIEW.md §15 request is satisfied at d849a65 by #5791 (comment). On real tmux, using this head's pool scripts in a scratch workspace, the suspension was renewed after the first worker's launch and before the held worker's recover(). The output shows:

  • the held worker's outcome was "suspended";
  • no new session or process was spawned for it;
  • it stayed in the renewed marker's stopped list, and the marker and incarnation files were unchanged across repeated suspended sweeps;
  • the first worker kept its pid;
  • a later --resume recovered the held worker exactly once, on its original session, with exactly one new incarnation.

The synthetic endpoint is disclosed, and it doesn't affect the behaviour under test. I'm no longer holding this PR.

@keweichen
keweichen merged commit 7ad48f5 into main Oct 21, 2026
49 of 51 checks passed
@keweichen
keweichen deleted the factory/kc/publication-repair-75cf9db89b58cb7a-ac4d4c851f7a branch October 21, 2026 04:16

@sonichi sonichi left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Approved at d849a65 on the owner's word: a renewed suspension is honored during resume, live-witnessed on real tmux.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants