Skip to content

fix(kanban): report blocking parents from kanban_complete tool, state delegate handoff contract - #113452

Closed
JoaoMarcos44 wants to merge 1 commit into
NousResearch:mainfrom
JoaoMarcos44:fix-113373-kanban-complete-parents-tool
Closed

JoaoMarcos44 wants to merge 1 commit into
NousResearch:mainfrom
JoaoMarcos44:fix-113373-kanban-complete-parents-tool

Conversation

@JoaoMarcos44

@JoaoMarcos44 JoaoMarcos44 commented Sep 16, 2026 •

Copy link
Copy Markdown

Summary

Fixes the worker-facing half of #113373. A dispatcher-owned worker that finishes genuinely-done work while a parent is unfinished (reopened mid-run) calls the kanban_complete tool — the surface workers actually use — and gets could not complete t_x (unknown id, stale run, or already terminal). The real refusal is unsatisfied parents, so the worker/operator chases stale runs, the run burns, crashes, re-queues, and repeats deterministic work (rewriting artefacts other lanes read).

  • tools/kanban_tools.py — new read-only _unsatisfied_parent_blockers() (same task_links join as kanban_db._parents_satisfied, deterministic ORDER BY p.id). _handle_complete now reports could not complete t_x: unsatisfied parent dependencies: t_p (todo); complete the parents first (done or archived) when blockers exist. Unknown-id and terminal refusals keep the generic text; the dependency invariant is untouched (no force path); the lookup is advisory reporting after the authoritative write, and the task stays running for a retry.
  • tools/delegate_tool.py — spawn-time surfacing (Kanban worker in delegate_task child context cannot close its own card, then the run dies — completed work is unrecordable and the card re-runs #113373 ask 1): one RULES line in the delegate_task description (Children cannot close tracked work: ... the parent applies the transition), so a delegated card no longer burns a full run before learning it can never close. Generic vocabulary, no cross-toolset names; description stays under the 2200-char ceiling (2191).
  • tests/tools/test_kanban_complete_parents_tool.py (new, 6 tests) — parents named + task still running, deterministic multi-parent order, unknown-id/terminal stay generic, happy path unchanged, description contract.

Relationship to existing PRs (not a duplicate)

Root-cause evidence

Reproduced on main at 8a25cb9 and re-verified after rebasing onto current main (4716ec0, head ac8c8d1): parent done -> child claimed (running) -> parent reopened (todo) -> worker's _handle_complete returned could not complete t_6d9a0938 (unknown id, stale run, or already terminal) before the fix, and could not complete t_x: unsatisfied parent dependencies: t_p (todo); ... after.

RED proof (single-file revert, no stash): with only tools/kanban_tools.py reverted, test_complete_names_unsatisfied_parent + test_complete_multiple_parents_deterministic_order fail with the verbatim pre-fix message and the other 4 pass; with only tools/delegate_tool.py reverted, the description contract test fails and the rest pass.

Test plan

  • scripts/run_tests.sh tests/tools/test_kanban_complete_parents_tool.py — 6 passed (also green after the rebase onto 4716ec0)
  • scripts/run_tests.sh tests/tools/test_kanban_complete_parents_tool.py tests/tools/test_kanban_tools.py — 44 passed
  • scripts/run_tests.sh tests/tools/test_delegate.py tests/tools/test_delegate_kanban_isolation.py — 87 passed
  • python -m compileall on touched files — clean; git diff --check — clean

Limitations

  • The live card t_aeaf817e from the issue lives on the reporter's board and could not be inspected from here; verification is via the deterministic timeline reproduction above.
  • request_review already surfaces its parents reason (with_reason=True); kanban_block has no parents gate (blocking is always allowed) — kanban_complete was the only masking sibling.

Closes #113373

… delegate handoff contract

kanban_complete tool collapsed every complete_task refusal into
'unknown id, stale run, or already terminal'. When a parent reopens
mid-run, a worker with genuinely done work is refused for a reason the
message hides, and the run burns (then crashes, re-queues, and repeats
deterministic work). Name the unsatisfied parents (id, status) from a
read-only task_links mirror of _parents_satisfied so the worker and the
operator complete the gates instead of re-running; unknown-id and
terminal refusals keep the generic text, and the dependency invariant
itself is untouched (no force path).

Complementary to the CLI-surface PRs NousResearch#110323/NousResearch#110330/NousResearch#110334, which
touch hermes_cli/kanban_db.py + hermes_cli/kanban.py; this change is
tool-surface only (tools/kanban_tools.py).

Also surface the delegate_task handoff contract at spawn time: children
cannot close tracked work and must return findings for the parent to
apply, so a delegated card no longer burns a full run before learning
it can never close (NousResearch#113373 ask 1).

Tests: tests/tools/test_kanban_complete_parents_tool.py (6) — parents
named, deterministic multi-parent order, unknown/terminal generic,
happy path, description contract. Proven red on unfixed sources.
@JoaoMarcos44
JoaoMarcos44 force-pushed the fix-113373-kanban-complete-parents-tool branch from 6f28ee9 to ac8c8d1 Compare September 16, 2026 20:34
@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cron Cron scheduler and job management comp/tools Tool registry, model_tools, toolsets tool/delegate Subagent delegation labels Sep 16, 2026
teknium1 added a commit that referenced this pull request Sep 18, 2026
Salvage follow-up on the cherry-picked #113398 (@fangliquanflq) and #113452
(@JoaoMarcos44) commits, trimmed to the salvage bar and widened to the class.

- link: drop the HERMES_KANBAN_BOARD binding on the run-id ownership proof
  (tools._worker_run_id / kanban._worker_run_id_for). complete/block prove
  ownership with the same task-scoped run id and never board-bind it; the
  guarded case is a forged cross-board task-id collision, not a live path.
  Dropped the two cross-board tests and the duplicate db owner test.
- complete: move the open-parents enumeration into kanban_db.unsatisfied_parents
  next to _parents_satisfied so the tool, the CLI (`hermes kanban complete`
  printed "unknown id or terminal state" for the same refusal), kanban_show
  (`unsatisfied_parents`) and diagnostics share one query.
- show: new `running_with_open_parents` diagnostic (hermes kanban show /
  diagnostics / dashboard) for a running card whose parent is not done —
  the "surface unresolved parents on a running card" ask of #113374.
- tests trimmed to invariants; docs for the refusal text, the show field and
  the diagnostic.

Co-authored-by: fangliquanflq <fangliquan@qq.com>
Co-authored-by: joaomarcos <joaomarcosdias444@gmail.com>
@teknium1

Copy link
Copy Markdown
Collaborator

Thanks @JoaoMarcos44. Your change was salvaged into #114786 with your authorship preserved (cherry-picked); #114786 — fix(kanban): kanban_link refuses a running child and dependency refusals name the open parents (#113374, #113373, salvage #113398, #113452) — is now merged on main at e6a8eb7f95aa, closing issues #113374, #113373. Closing this PR in favour of the landed change; if you see a case it does not cover, please open a fresh issue with the repro and tag it.

@teknium1 teknium1 closed this Sep 18, 2026
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 comp/tools Tool registry, model_tools, toolsets P3 Low — cosmetic, nice to have tool/delegate Subagent delegation type/bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Kanban worker in delegate_task child context cannot close its own card, then the run dies — completed work is unrecordable and the card re-runs

3 participants