-
_launch_candidate() spawns a real `python -m src.backend_server` process (`revived`) to re-verify the previous version during a post-cutover rollback. On the success path it's correctly left running -- it IS the new Live. But on every failure path (never bound live_port, failed re-verification, git revert conflict) nothing ever terminated it -- found via 31 accumulated orphaned processes on this machine, one per failed rollback_path_b call across many real test runs this session. This is also the likely cause of RollbackPathBFailureTest's own reported non-determinism (three independent real Validator sessions saw it fail, never reproduced manually): a leaked process from an earlier failed run can still be squatting on the port a later run's _find_free_port() picks, producing a false "alive" health-check reading. Fix: call deploy_cutover._stop_process(revived.pid) in both failure branches before raising, mirroring the pattern cutover() already uses for its own stop_timeout-bounded process teardown. Also fixes RollbackPathBHappyPathTest's own matching leak (it re-appended bad_live.pid a second time instead of tracking the actual revived process, a copy-paste bug, not real cleanup) by capturing the real pid via a thin _launch_candidate wrapper. 31 pre-existing orphaned processes killed by hand; verified 5 repeated test runs after the fix leak zero new ones. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Three real self-hosting fixes (log content never written, skill detail page missing real content, artifact list not clickable), two design questions set aside per user's request (unified Planner-driven work graph across all org agents, loop visualization on the graph), three bugs left for a future batch, and two infrastructure bugs found and fixed along the way (manual_resume not actually continuing execution for most block reasons, run_goal_to_completion crashing instead of blocking on unrouted exceptions). Also upgrades the RollbackPathBFailureTest flakiness note -- three independent real sessions have now hit it. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
…1a79-main-checkout-drift
-
…ea4d-main-checkout-drift
-
…d9ae-main-checkout-drift
-
Found for real: a work_graph_execute.WorkGraphExecuteError ("API Error: Response stalled mid-stream") wasn't in _ROUTABLE_EXCEPTIONS, so it propagated uncaught and crashed the calling process entirely -- leaving the task neither running nor blocked_pending_human, just stuck with blocked_reason=NULL. run_scheduler_once's own try/except only protects OTHER goals in the same batch from one goal's failure; it never applied the task-level blocked_pending_human consequence either. Add a catch-all mirroring task_execution._mark_blocked's existing fallback for its own (Start-button) entry point, so both ways of running a task now guarantee it always lands on a real terminal-ish status with the real error message persisted, never a caller-crashes-and-the-task-is-just-stuck outcome nothing can manual_resume from. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> -
…0a72-main-checkout-drift
-
…2b85-main-checkout-drift
-
…f2cf-main-checkout-drift
-
Second real self-fix (after order 2) -- 12 skills migrated verbatim from ~/.hermes/profiles/, Validator caught and redacted a leaked Feishu API token in 3 of them via byte-diff against source. Also records two operational lessons from actually running it (a real network blip, and my own mistake killing a daemon thread by running it from a one-shot script) and a flaky supervisor test failure that didn't reproduce on independent recheck. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
-
Auto-continuation after a successful manual_resume only fired for blocked_reason in ('user_paused', 'user_stopped'). A real transient network blip ("API Error: Unable to connect to API (ENOTFOUND)") blocks a task with blocked_reason='execution_error' the same way any other unroutable exception does -- resuming it only flipped the status field back, with no path to actually re-trigger execution (/execute requires status='queued', but a resumed task lands on 'planning_brd_prd_sdd'/'coding' instead). Clicking "resume" was a dead end a second click couldn't fix. The user has already made the judgment call to retry by clicking resume at all. Withholding continuation only made sense for the two reasons with their own dedicated resume path requiring a different action first: budget_exceeded (must raise the limit) and loop_limit_reached (excluded by name, not just by its usual restored status). Every other blocked_reason now auto-continues on a successful resume to a resumable status. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>