Skip to content

fix(kanban): route unblock_task through parent-dependency gate - #22405

Closed
wesleysimplicio wants to merge 1 commit into
NousResearch:mainfrom
wesleysimplicio:fix/kanban-unblock-recompute-ready
Closed

fix(kanban): route unblock_task through parent-dependency gate#22405
wesleysimplicio wants to merge 1 commit into
NousResearch:mainfrom
wesleysimplicio:fix/kanban-unblock-recompute-ready

Conversation

@wesleysimplicio

Copy link
Copy Markdown
Contributor

Summary

Closes #22375.

unblock_task jumped blocked -> ready unconditionally, bypassing the parent-status check that recompute_ready enforces. A child task could land in ready while its parent was still todo/ready, and the dispatcher could then claim and start the child before the parent ever ran. This was the only path in the DB layer that could promote a task to ready without consulting the dependency gate.

Fix

Re-evaluate the gate inside the same write_txn: query parent statuses (same JOIN task_links query recompute_ready uses) and land in ready only when every parent is done, otherwise land in todo. The next dispatcher tick re-runs recompute_ready and promotes the row when it is actually unblocked by dependencies.

The no-parents case is preserved by construction — all([]) is True, so a parent-free task still goes straight to ready (the existing test_block_then_unblock continues to pass unchanged).

Test plan

  • New tests/hermes_cli/test_kanban_unblock_parent_gate.py covers:
    • open parent → todo
    • all parents done → ready
    • partial parents done → todo
    • no parents → ready
    • unblock_task still returns False when row isn't in blocked
  • Stash-verified: with the fix removed, the two parent-gate tests fail with assert 'ready' == 'todo'. With the fix, all 5 pass.
  • Wider kanban suite (test_kanban_db.py, test_kanban_specify*.py, test_kanban_core_functionality.py, test_kanban_tools.py, test_kanban_dashboard_plugin.py): 350 passed, 1 skipped.
  • Full pytest -q: 110 pre-existing failures (file_read_guards, file_staleness, file_state_registry, gateway_wsl, gateway_service, model_switch_custom_providers, terminal_tool_requirements, tui_gateway_server) — confirmed pre-existing by stashing the fix and re-running the same files (identical 8/8 failures in test_file_read_guards.py and test_gateway_wsl.py). None touch kanban_db.py or are in the dependency graph of this change.

🤖 Generated with Claude Code

Closes NousResearch#22375.

`unblock_task` jumped `blocked -> ready` unconditionally, so a child
task could land in `ready` while its parent was still `todo`/`ready` —
the only path in the DB layer that bypassed the parent-status check
that `recompute_ready` enforces.  The dispatcher could then claim the
child and start it before the parent ever ran.

Re-evaluate the gate inside the same write txn: select parent statuses
(same query `recompute_ready` uses) and land in `ready` only when every
parent is `done`, otherwise land in `todo` so the next dispatcher tick
re-runs `recompute_ready` and promotes the row when it's actually
unblocked by dependencies.

The no-parents case (the only one covered by `test_block_then_unblock`)
is preserved: `all([])` is True, so a parent-free task still goes
straight to `ready`.

Regression test in tests/hermes_cli/test_kanban_unblock_parent_gate.py
covers: open parent → todo, all parents done → ready, partial parents
done → todo, no parents → ready, and the unchanged
`returns False when not blocked` contract.
Copilot AI review requested due to automatic review settings May 9, 2026 08:26

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes a kanban DB-layer status transition bug where unblock_task could move a task from blocked directly to ready without re-checking parent dependencies, allowing children to become dispatchable while parents were still open.

Changes:

  • Update unblock_task to compute next_status using the same parent-status gate as recompute_ready (ready only if all parents are done, else todo).
  • Extend unblock_task documentation to reflect the new conditional landing status.
  • Add a regression test suite covering parent-gated unblock scenarios and the existing “returns False when not blocked” contract.

Reviewed changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
hermes_cli/kanban_db.py Routes unblock_task through the parent-dependency gate (matching recompute_ready) before choosing ready vs todo.
tests/hermes_cli/test_kanban_unblock_parent_gate.py New regression tests for #22375 validating unblock behavior with open/done/partial/no parents plus non-blocked no-op behavior.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/plugins Plugin system and bundled plugins labels May 9, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing fix — see #22372 which addresses the same unblock_task parent-dependency bypass (#22375).

@teknium1

Copy link
Copy Markdown
Contributor

Closing as redundant — issue #22375 was fixed on main via commit cda20ee ("fix(kanban): gate claim + unblock on parent completion") on May 9. The fix's inline parent-status JOIN in unblock_task is mechanically very close to your approach here, and it also adds a claim_task chokepoint as defense in depth. Your other two kanban PRs from this batch (#22627 + the unlink_tasks recompute_ready fix in 0c22434) both landed earlier the same day. Thanks @wesleysimplicio!

@teknium1 teknium1 closed this May 10, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/plugins Plugin system and bundled plugins P3 Low — cosmetic, nice to have type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug]: unblock_task bypasses parent-dependency gate

4 participants