Conversation
teknium1
left a comment
There was a problem hiding this comment.
Thanks for covering both the exception and false-return failure shapes; the current-main premise is valid (hermes_cli/kanban.py:1949-1957, 1866-1908, 2071-2096).
Problems
hermes_cli/kanban.py:1908cannot scan another board whenHERMES_KANBAN_DBis set. Current main resolves that env override beforeboard=(hermes_cli/kanban_db.py:530-538), and spawned workers always receive it (hermes_cli/kanban_db.py:8154). The scan therefore reconnects to the active DB and finds no owning board.- The tests set only
HERMES_KANBAN_BOARD(tests/hermes_cli/test_kanban_cross_board_error.py:41-117), so they miss the dispatcher environment and the documented worker isolation contract (website/docs/user-guide/features/kanban.md:80-89).
Suggested changes
- Preserve DB-pinned worker isolation explicitly, then add a regression test for that environment and the intended output.
Automated hermes-sweeper review.
| other = meta.get("slug") | ||
| if not other or other == active: | ||
| continue | ||
| other_conn = kb.connect(board=other) |
There was a problem hiding this comment.
HERMES_KANBAN_DB overrides board= in current kanban_db_path() (hermes_cli/kanban_db.py:530-538). Dispatcher-spawned workers set that pin, so this reconnects to the active DB instead of other and the hint is never found. Please preserve the worker isolation contract explicitly and add coverage with the DB pin set.
…-board hint The wrong-board hint scan called connect(board=other), but kanban_db_path() honours HERMES_KANBAN_DB first — and the dispatcher always pins that into worker env (kanban_db.py worker handoff). So under a real dispatch the scan reopened the active board's DB for every 'other' board, never found the owning board, and the hint stayed silent (NousResearch#65101 regressed under dispatch, NousResearch#65128). - Add board_db_path(board): a pure path resolver that ignores HERMES_KANBAN_DB (and has no active-board fallback), refactored out of kanban_db_path so both share _board_db_path_for_slug. - The scan now connects via connect(db_path=board_db_path(other)), the explicit-db_path branch of connect() which bypasses the env override. Worker isolation is untouched — business connections still resolve via the pinned env path. - Regression test pins the dispatcher scenario: with HERMES_KANBAN_DB pinned to the active board, the hint still names the owning board. RED-verified (fails on the pre-fix connect(board=other)).
|
Thanks @teknium1 — root-caused and fixed in Root cause: the scan called Fix:
Regression test ( One subtlety the test had to get right: the task must be created on |
SummaryOne PR directly addresses issue #65101. #65128 adds owning-board and switch-command hints to both exception-based and false-return failures for block, archive, and complete, while suppressing those hints for genuine wrong-state or unknown-ID failures. Related pull requests
Suggested consolidationKeep #65128 open with a salvage path: retain its cross-board lookup, actionable hints across both failure shapes, and pinned-worker regression test. It is the recorded best fix and the only PR in this complex; the current diff explicitly addresses the contributor’s keep_open concern, so there is no competing PR to close as a duplicate. Complex graphflowchart LR
classDef open fill:#dbeafe,stroke:#1d4ed8,color:#1e3a8a
classDef merged fill:#dcfce7,stroke:#15803d,color:#14532d
classDef closed fill:#e5e7eb,stroke:#6b7280,color:#1f2937
classDef unverified fill:#f3f4f6,stroke:#9ca3af,color:#374151
classDef best stroke-width:3px,stroke:#b45309
classDef target stroke-width:3px,stroke:#4338ca
I65101(["issue #65101 (open)"])
P65128["PR #65128 (open)"]
P65128 -->|best fix| I65101
class I65101 open
class P65128 open
class P65128 best
class P65128 target
click I65101 "https://github.com/NousResearch/hermes-agent/issues/65101"
click P65128 "https://github.com/NousResearch/hermes-agent/pull/65128"
Graph: solid arrow = fixes / best fix, dashed arrow = partial or unverified (see edge label); boxed group = PRs duplicating each other; amber border = best fix; indigo border = target; gray node = closed (state tag in the node label). Cross-PR triage: Reviewed 1 pull request and 1 issue in this complex. Each diff was read against this issue; Assessment working set: 18 kB of PR diffs, 6 kB of issue/PR text, 5 kB of discussion (3 comments), 2 verify verdicts. verdicts reflect diff content, not PR titles. Part of an automated triage batch. |
…ard id (NousResearch#65101) When a kanban verb (block/archive/complete) fails because the task id is real but lives on a different board, the operator sees an opaque 'unknown task {id}' exception or a bare 'cannot <verb> {id}' line. The id is known and the card is in a valid state — it is simply on the wrong board — yet nothing in the error says so or suggests the 'hermes kanban boards switch <slug>' fix. This caused operators to retry the same failing command many times (NousResearch#65101). Two failure shapes are covered: * 'unknown task {id}' raised before a verb's state check (e.g. block with a reason calls add_comment first). Caught in kanban_command's shared except (ValueError, RuntimeError) branch that all verbs funnel through. * 'cannot <verb> {id}' printed when a verb's task op returns False (e.g. block without a reason reaches block_task -> False). Both now attach a one-line hint naming the owning board and the exact switch command, but only when the id is actually found on another board. No hint when the task is on the active board (a genuine wrong-state failure) or absent from all boards (so we never chase the operator elsewhere). The cross-board scan reuses the existing list_boards + connect(board=...) pattern; a get_task check on the active connection gates the scan so the common wrong-state case stays cheap.
…-board hint The wrong-board hint scan called connect(board=other), but kanban_db_path() honours HERMES_KANBAN_DB first — and the dispatcher always pins that into worker env (kanban_db.py worker handoff). So under a real dispatch the scan reopened the active board's DB for every 'other' board, never found the owning board, and the hint stayed silent (NousResearch#65101 regressed under dispatch, NousResearch#65128). - Add board_db_path(board): a pure path resolver that ignores HERMES_KANBAN_DB (and has no active-board fallback), refactored out of kanban_db_path so both share _board_db_path_for_slug. - The scan now connects via connect(db_path=board_db_path(other)), the explicit-db_path branch of connect() which bypasses the env override. Worker isolation is untouched — business connections still resolve via the pinned env path. - Regression test pins the dispatcher scenario: with HERMES_KANBAN_DB pinned to the active board, the hint still names the owning board. RED-verified (fails on the pre-fix connect(board=other)).
f421662 to
14ed07b
Compare
What does this PR do?
When a kanban verb (
block/archive/complete) fails because the task id is real but lives on a different board, the operator gets an opaque error and no idea aboards switchwould fix it. The id is known and the card is in a valid state — it is simply on the wrong board. Per #65101, this caused an operator to retry the same failing command 8 times.Today the operator sees one of two equally-unhelpful messages depending on the verb path:
kanban: unknown task t_4dff09c7— raised before the verb's state check (e.g.block <id> <reason>callsadd_commentfirst, which throws on the missing id), surfaced throughkanban_command's sharedexcept (ValueError, RuntimeError)branch.cannot block t_4dff09c7— printed when the verb's task op itself returnsFalse(e.g.block <id>with no reason reachesblock_task→False).Neither names the current board, neither mentions that the task exists elsewhere, and neither suggests
hermes kanban boards switch <slug>.This PR attaches a one-line hint to both failure shapes:
The hint is shown only when the id is actually found on another board. When the task is on the active board (a genuine wrong-state failure) or absent from all boards, no hint is shown — so we never chase the operator to a board where the task still isn't.
The cross-board scan reuses the existing
list_boards+connect(board=...)pattern; aget_taskcheck on the active connection gates the scan so the common wrong-state path stays cheap.Related Issue
Fixes #65101
Type of Change
Changes Made
hermes_cli/kanban.py_locate_task_on_other_board()/_cross_board_hint(): scan other boards for a task id, return a switch hint (orNone). Reuseslist_boards+connect(board=...)._task_ids_from_unknown_task_message(): recovert_<hex>ids from theunknown task …/unknown task(s): …error strings so the hint can fire in the shared exception branch.kanban_commandsharedexcept (ValueError, RuntimeError): when the message isunknown task …, parse the id(s) and attach the cross-board hint. This covers every verb that touches a task before its own state check (block-with-reason viaadd_comment, etc.)._cmd_block/_cmd_archive/_cmd_completeFalsebranches: attach the hint after the existingcannot <verb> {id}line. Also clarified the inline parenthetical forblock/archive(previously bare) to matchcomplete's style.How to Test
pytest tests/hermes_cli/test_kanban_cross_board_error.py -q— 9 tests, all passing. Covers:block/archive/completeof a task on another board → hint with owning board + switch command.blockwith no reason reachingblock_task→False→cannot block+ hint.donetask) → no hint._cross_board_hintand the message parser (singular, plural, dedup, non-id tokens ignored).Manual repro (the exact scenario from the issue):
Checklist
Code
fix(scope):,feat(scope):, etc.)Documentation & Housekeeping