fix(kanban): linking a ready card under an unfinished parent records why it dropped to todo (#110996, salvage #111005) - #111468
Conversation
૮ >ﻌ< ა ci reviewran on 1f3a0e0 — fix(kanban): gate create-with-parents like link; archived pa
|
Review: fix(kanban) ready-card demotion records its reasonSummary: Linking a What changed:
Strengths: Event gating on Findings: Return-type change from Verdict: Looks good to merge. Reviewed using Hermes-Agent |
A ready child linked under an unfinished parent drops to todo with no event and no operator signal; the only trace used to be claim_rejected after a forced promote. Record a dependency_wait event when the demotion fires, return the gate from link_tasks, warn in the CLI link command, report gated in the kanban_link tool, and document the gate.
…iant tests The dashboard's POST /links is the fourth writer of link_tasks (CLI, tool, dashboard, plus the graph builder); return the same ``gated`` flag so every surface that can create the deadlock can see it. Document the ``dependency_wait`` payload the link path emits and the delegation rule the reporter derived (never link a support card under the card it unblocks). Drops the CLI output test (a change-detector on prose); the two DB-level invariants (event emitted on demotion / none for a done parent) stay.
…erminal
create_task(parents=[open parent]) — the reporter's actual incident path —
parked the card in todo with only a `created` event, and kanban_create's
payload carried no `gated`, so the board still showed an unexplained todo
while only the link surface was fixed. create_task now appends the same
dependency_wait {reason: parent_not_done, parent} event and kanban_create
returns gated/gated_by, mirroring kanban_link.
link_tasks gated on `status != 'done'`, but _parents_satisfied and
recompute_ready treat `archived` as terminal: linking a ready child under an
archived parent demoted it to todo with a false parent_not_done event and the
next recompute promoted it straight back. Gate on not in ('done','archived').
Review finding: create_task(parents=...) emitted no dependency_wait/gated; link under an archived parent flapped ready->todo->ready with a false reason.
1f3a0e0 to
b3a07fb
Compare
Linking a
readycard under a parent that is notdoneno longer demotes it totodosilently: the board records adependency_waitevent, andhermes kanban link, thekanban_linktool and the dashboard API'sPOST /linksall report the gate (the dashboard UI itself does not yet surface it).Fixes #110996
hermes_cli/kanban_db.py::link_tasksreturnsTruewhen it demoted the child and appendsdependency_wait {reason: parent_not_done, demoted: true, parent}(mirrors theclaim_review_taskdemotion event; gated onrowcount == 1so atodochild gets no spurious event).hermes_cli/kanban.py::_cmd_linkprints a one-line note naming the parent and theunlinkescape hatch;tools/kanban_tools.py::kanban_linkreturnsgated/gated_by;plugins/kanban/dashboard/plugin_api.py::add_linkreturnsgated.dependency_waitevent row documents the new payload; a caution block in thedelegate_taskvs Kanban section states the rule the reporter's fleet adopted (never link a support card under the card it exists to unblock; reference it in the body).tests/hermes_cli/test_kanban_db.py(event on demotion; none for adoneparent), both red onorigin/main.--force) is not taken.promote_taskonorigin/mainalready refuses undone parents with an error pointing atunlink(02005cf, kanban promote --force prints "Promoted <id> -> ready" and does not change the status (false success) #106195), and the thread (reporter included) endorsed the visibility half over re-opening that door. fix(kanban): allow forced support children of blocked parents #110999 by @KoNit-K implements option 1 and is a design reversal for the maintainer to rule on, not a salvage.Live repro:
env -u HERMES_DELEGATED_CHILD_CONTEXT python /tmp/batch111/kanban/probe_kanban_db.py <tree> <label>— tempHERMES_HOME, blocked parent,readychild,link_tasks(parent, child).origin/main(2179a27)readychild under blocked parentchild ready->todo events=['created', 'linked']→ SILENT DEMOTIONchild ready->todo events=['created', 'dependency_wait', 'linked']doneparentstatus=ready events=['created', 'linked']promote_taskon the gated childunsatisfied parent dependencies … drop the link with hermes kanban unlinkRoot cause:
link_tasksran theready → tododemotion as a bare UPDATE and appended onlylinked, so the only trace of the deadlock was the laterclaim_rejectedevents.Credit
Salvages #111005 by @kokhlo (cherry-picked as-is; follow-up commit adds the dashboard surface, the docs rule, and drops the CLI prose test). Option 1 alternative #110999 by @KoNit-K noted above.
Infographic
Review fixes
create_task(parents=[open parent])/kanban_create(the reporter's actual incident path) parked the card intodowith nodependency_waitevent and nogatedin the tool payload. Now emits the samedependency_wait {reason: parent_not_done, parent}event andkanban_createreturnsgated/gated_by, mirroringkanban_link. Test:test_create_task_with_open_parent_emits_dependency_wait+gatedassertion intest_create_happy_path.link_tasksgated onstatus != 'done'while_parents_satisfied/recompute_readytreatarchivedas terminal, so linking areadychild under an archived parent demoted it with a false reason and the next recompute promoted it back. Gate is nownot in ('done', 'archived'). Test:test_link_tasks_archived_parent_is_terminal_no_gate.dist/index.jsaddLink/addChilddiscard the response, so only the API reports the gate; PR body wording adjusted above rather than editing the built bundle.