fix: keep initial blocked kanban tasks inert - #35832
Conversation
dcf6f2e to
68cf9d1
Compare
|
Thanks for the overlap note. Technical recommendation from the Control Room smoke evidence: keep #35832 as the preferred incident-remediation PR, but treat it as two logical units:
If the project wants the smallest merge surface, #34735 is a valid Option A patch and could land first. But then the archive/worker teardown hardening from #35832 should remain as a follow-up, not be dropped. My preferred path is to merge #35832 as the superset if the added teardown tests are acceptable; otherwise split it into “initial blocked event” first and “archive teardown hardening” second. Local targeted checks run against PR heads:
Comment posted by Hermes Control Room from local evidence review. |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for the focused sticky-block regression coverage. The initial-status premise is still present on current main: create_task writes status='blocked' at hermes_cli/kanban_db.py:2585, but emits only created at :2670-2683; _has_sticky_block requires a blocked event at :3273-3279, so recompute_ready can promote it at :3336.
Problems
- Blocking:
hermes_cli/kanban_db.py:5011limits the direct-child/PID-reuse verification to non-Windows paths, but the code still callskill(pid, SIGTERM)at:5031on Windows. A stale, recycledworker_pidcan therefore identify an unrelated process. The new real-child and stale-PID tests skip Windows attests/hermes_cli/test_kanban_initial_blocked_safety.py:170-171and:197-198.
Suggested changes
- On Windows, do not signal an unverified PID; retain authoritative spawned-process provenance/handles or report termination as unavailable. Add a Windows regression for stale PID safety.
- Preserve the initial blocked-event fix; it directly completes the existing sticky-block contract.
Automated hermes-sweeper review.
| if kill is None: | ||
| return info | ||
|
|
||
| real_signal_path = signal_fn is None and os.name != "nt" |
There was a problem hiding this comment.
Blocking: this bypasses the direct-child/PID-reuse guard on Windows, but the function still falls through to kill(pid, SIGTERM) at line 5031. A stale same-host PID can be recycled into an unrelated Windows process. Do not signal an unverified Windows PID; retain authoritative spawned-process provenance or return an unattempted result, and add a Windows regression.
Summary
Fixes a Kanban runtime safety bug where tasks created with
initial_status="blocked"could later be auto-promoted by dependency recomputation because task creation did not emit an explicitblockedevent.This also hardens archiving of claimed/running tasks by reclaiming/terminating direct child workers safely and recording archive/termination audit events.
What changed
blockedevent when a task is created withinitial_status="blocked".waitpid(..., WNOHANG)checks before signaling to avoid PID-reuse hazards.archivedatomically with the archive state transition.Test plan
Local targeted tests:
Expanded Kanban surface:
Safety notes
The worker termination path only signals a PID after successfully reclaiming the task lock and verifying the PID is still a direct child via
waitpid(pid, WNOHANG). If the PID is not a child or was already reaped, it refuses to signal, preventing accidental termination of unrelated processes after PID reuse.The
archivedevent is written in the same transaction as the archive state transition, so an audit event is not lost if a crash happens immediately after the state change.