Skip to content

fix(kanban): emit blocked event for initial_status="blocked" tasks (fixes #47777) - #48437

Closed
ochsec wants to merge 1 commit into
NousResearch:mainfrom
ochsec:fix/issue-47777-created-blocked-sticky
Closed

fix(kanban): emit blocked event for initial_status="blocked" tasks (fixes #47777)#48437
ochsec wants to merge 1 commit into
NousResearch:mainfrom
ochsec:fix/issue-47777-created-blocked-sticky

Conversation

@ochsec

@ochsec ochsec commented Jun 18, 2026

Copy link
Copy Markdown

Fixes #47777

Problem

A task created with initial_status="blocked" is auto-promoted to ready on the next dispatch tick (≤60s) because recompute_ready() calls _has_sticky_block(), which looks for a "blocked" event in task_events. No such event is emitted at creation time, so _has_sticky_block() returns False and the task is promoted — even though its status is blocked. This can cause unwanted worker spawns and, in the worst case, fabricated human approvals for decision records (as described in the issue).

Root Cause

In create_task() (hermes_cli/kanban_db.py), when initial_status="blocked" is passed, the task row gets status='blocked' but only a "created" event is appended to task_events. The "blocked" event is never emitted. By contrast, kanban_block() (the explicit block path) does emit a "blocked" event, so explicitly-blocked tasks are correctly treated as sticky-blocked by _has_sticky_block(). Created-blocked tasks diverge purely because of this missing event row.

Fix

After the "created" event in create_task(), emit a "blocked" event when task_status == "blocked":

if task_status == "blocked":
    _append_event(conn, task_id, "blocked", {"reason": "created with initial_status=blocked"})

This ensures created-blocked tasks are treated identically to explicitly-blocked tasks by _has_sticky_block() and recompute_ready(). Only an explicit unblock_task() releases them.

Changes

  • hermes_cli/kanban_db.pycreate_task(): emit "blocked" event when initial_status="blocked" (5 lines added)
  • tests/hermes_cli/test_kanban_blocked_sticky.py — 3 new regression tests:
    • test_created_blocked_task_stays_blocked — standalone blocked task survives 5 recompute ticks
    • test_created_blocked_with_done_parents_stays_blocked — blocked child with done parents stays blocked
    • test_created_blocked_can_be_unblocked — explicit unblock works and promotes correctly

Impact

  • Minimal: No change to recompute_ready() logic or any existing behavior for non-blocked tasks, explicitly-blocked tasks, or normal todo → ready promotion.
  • Correct: Created-blocked tasks now match the established sticky-block semantic — they stay blocked until an explicit unblock_task() call.
  • Data-integrity: Prevents the race window where a parked task can be auto-promoted, spawned, and auto-completed with fabricated approvals within seconds of creation.
  • All 9 tests in test_kanban_blocked_sticky.py pass.

@alt-glitch alt-glitch added type/bug Something isn't working comp/cron Cron scheduler and job management P3 Low — cosmetic, nice to have duplicate This issue or pull request already exists labels Jun 18, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Duplicate of #34735 — both PRs fix #47777 with the identical mechanism: in create_task(), emit an explicit "blocked" event (_append_event(conn, task_id, "blocked", ...)) when task_status == "blocked", so _has_sticky_block() treats created-blocked tasks as sticky and recompute_ready() no longer auto-promotes them. #34735 (by @begjb, 2026-05-29) is the earliest still-open PR with this approach and is the canonical fix. #46565 also uses the same mechanism. Consolidating on #34735.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approved

Looks Good

  • Correct root cause identified: Tasks created with initial_status=blocked had no blocked event in task_events, so _has_sticky_block() returned False and the task was auto-promoted to ready
  • Minimal, targeted fix: 5-line addition to create_task() emits the missing blocked event when task_status == blocked
  • Good regression tests: 3 new tests covering the sticky-blocked behavior from creation, including parent-completion and unblock paths
  • Security note: Fixes a data-integrity issue where tasks could be auto-promoted and auto-completed with fabricated human approvals within seconds of creation
  • No debug artifacts or secrets

Reviewed by Hermes Agent

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

Labels

comp/cron Cron scheduler and job management duplicate This issue or pull request already exists P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

3 participants