fix(kanban): hard-error when an explicit board selection names a nonexistent board - #65846
fix(kanban): hard-error when an explicit board selection names a nonexistent board#65846ahmadashfq wants to merge 22 commits into
Conversation
Code Review SummaryVerdict: Comment Kanban explicit board hard-error. +8647/-453, 51 files. Very large refactor/feature. Surface-area exceeds shallow-review threshold. No security issues detected but full review deferred to human reviewer. -- |
teknium1
left a comment
There was a problem hiding this comment.
Thanks for documenting the misrouting scenario and adding focused regression coverage.
Problems
- Current
maindeliberately treats staleHERMES_KANBAN_BOARDvalues as recoverable:get_current_board()falls through athermes_cli/kanban_db.py:426-460, and8a64e1580addedtests/hermes_cli/test_kanban_boards.py:361-375to assert that a removed-board pin routes to the persisted board without recreating it. Changing that established behavior to a hard error needs an explicit maintainer compatibility decision. - The PR contains 51 files / +8647/-453, although the stated change is concentrated in
a32b5b195(hermes_cli/kanban_db.pyandtests/hermes_cli/test_kanban_boards.py). The unrelated changes should not be reviewed or salvaged as part of this focused behavior change.
Suggested changes
- After maintainer direction, salvage the focused board-resolution commit and its tests independently of the unrelated branch stack.
Automated hermes-sweeper review.
| kb.create_board("persisted") | ||
| kb.set_current_board("persisted") | ||
| monkeypatch.setenv("HERMES_KANBAN_BOARD", "missing-board") | ||
| assert kb.get_current_board() == "persisted" | ||
| with pytest.raises(kb.BoardNotFoundError) as exc_info: |
There was a problem hiding this comment.
This assertion intentionally reverses the stale-environment compatibility behavior added by 8a64e1580 and currently covered by test_connect_stale_env_uses_fallback_board_without_recreating_it. Please obtain a maintainer decision on making stale worker pins fatal before changing this contract.
(cherry picked from commit 3ee28fa) (cherry picked from commit eeaee70b722ba8ac2b20516397ca49c93ebaa978)
(cherry picked from commit 59eb55a6b3c895f1cdfe7a4b1088b460ef4b1135)
(cherry picked from commit ee222bc) (cherry picked from commit 71513d62bcca3b8044860a4775796a8c4001b57f)
(cherry picked from commit 26637e2) (cherry picked from commit 8fdeeb21abe46016a3dce4bb5a6eabadea878e87)
(cherry picked from commit 1861bc1c1ca08be3b8b6b0ad7d7aabea0e717513)
Two fixes so the consolidated worktree/packet-capture work passes its full acceptance suite on current main (5 tests were red after merging 692de068a): - live_worker_workspace_snapshot: honor the active worker's own task (HERMES_KANBAN_TASK == row id) as authoritative over stale persisted workspace_kind, so show/list packets reflect the real worktree branch even when the row says scratch. The git-worktree probe still gates branch names, so non-worktree active workspaces stay empty. - kanban_create: invert a self-parent edge (parents=[self]) instead of taking it literally — the child is created with no blocking parent (promotes immediately) and the spawning task becomes a CHILD of it (wakes after), mirroring decompose_triage_task. Prevents the orchestrator-reroute deadlock. Full kanban suite: 359 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 52bb6de) (cherry picked from commit 0b012aaa71052138e5278b85e4dd3902828e0624) (cherry picked from commit 01b9df3e42f528e77e80c60e56e251c1c82d3ada) (cherry picked from commit 50b44d5) (cherry picked from commit d81eae644c4684b864085e81a7a4b4c61e935024)
…main) The worktree claim flow hardcoded `origin/main` as the base for new worker worktrees. For a local-only, patch-maintained install whose `origin` is a public fork the fleet must never contact, that is wrong twice over: origin/main lacks all local work, and reaching it risks exposing private code. - Add per-board `worktree_base_ref` config (board.json), default local `main`. Workers now branch `wt/t_<id>` from the local default branch — the source of truth — and `_resolve_worktree_base_commit` fetches ONLY when the ref is a configured remote-tracking ref (e.g. a board that opts into `origin/main`). Local refs never trigger a network fetch. - Thread base_ref through `_ensure_git_worktree` / `_resolve_worktree_workspace`; persist it as `workspace_base_ref`. - Tests: existing origin/main worktree tests opt into `worktree_base_ref= origin/main` (remote path still covered); add a local-main default test proving no remote is contacted. Full kanban suite: 361 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 8b431ba) (cherry picked from commit aed7aab387d260faab251dc17ebac254ec882bd8) (cherry picked from commit c243229d34b394772dd89952bc709c8051b9e2c5) (cherry picked from commit e960a47) (cherry picked from commit f4cff95ce039026b8c90e45377bd53dd50ef22d0)
dispatch_once force-converted EVERY claimed task to a worktree, which (a) required every board to have a git default_workdir, (b) failed any task carrying a legacy scratch workspace_path (not in a git repo -> spawn_failed), and (c) contradicted the documented scratch/dir/worktree coexistence for research/ops workloads. Gate worktree resolution on `_board_is_git_backed(board)` (default_workdir resolves to a repo root) OR an explicit worktree-kind task. Other boards keep their scratch/dir workspace. Restores scratch dispatch while git-backed boards (e.g. fleet-autonomy) still get branch-based, verifiable handoffs from local main. Adds a regression test for scratch dispatch on a non-git board. Full kanban suite: 362 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit 849a1c1) (cherry picked from commit 77003890eafc0e5443b35867baaea8ac4e35b555) (cherry picked from commit dfa32a2277b29a2c9705e79823b9e743575b48fe) (cherry picked from commit 797c6b6) (cherry picked from commit 1a011b6924536264e7a2ac7356bc04c04e28b3e6)
The board-conditional dispatch typed EVERY task on a git-backed board as a worktree, including goal_mode coordination roots (orchestrator goal/epic loops that fan out and wake on child completion, producing no code of their own). The worktree completion gate then blocked them forever (real CI on a code branch they never created). Exempt goal_mode tasks from auto-worktree at dispatch; an explicit workspace_kind=worktree still wins for the rare goal card that genuinely edits code. Adds a regression test. Full kanban suite: 364 passed. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> (cherry picked from commit e708df4) (cherry picked from commit 39a4a6e937abdcc58ce3480d12f77117c73e8708) (cherry picked from commit 799464249096bc0c7d39de8e5f21b6d17f9cc35d) (cherry picked from commit 575bdff) (cherry picked from commit 996bdcdc4a78db07da9d8b030bdec816db9259c8)
(cherry picked from commit bce14134deea070b35fd1603c5851651996f0824) (cherry picked from commit 6ee0419ac5aa041696ef66e9032bc201f085f2ec) (cherry picked from commit c24430d) (cherry picked from commit 4a6094df13baabaf3ff0e0a58119987cf3c962ac)
(cherry picked from commit 5744baf78ec0e39c1983f2a07361bf667e1a99c1) (cherry picked from commit 248652a) (cherry picked from commit 25b17380ff6f07f61dbab3552cf6a790cc42ba3e)
Carry canonical Nostr thread anchors into SessionSource so lifecycle messages can remain attached to an existing Buzz thread. Prefer root markers over immediate reply markers and retain legacy fallback behavior. Co-authored-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com> Signed-off-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com>
Use the triggering Buzz event as the synthetic thread root when an inbound source has no existing thread. This mirrors the upstream behavior proposed in PR NousResearch#77080 and complements canonical inbound root preservation. Co-authored-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com> Signed-off-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com>
Co-authored-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com> Signed-off-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com>
|
Restaged this fix against current local New replay commit: What changed
Fresh current-main verification $ ~/.hermes/hermes-agent/venv/bin/python -m pytest tests/hermes_cli/test_kanban_boards.py -q
31 passed in 2.29s
$ ~/.hermes/hermes-agent/venv/bin/python -m pytest tests/hermes_cli/test_kanban_db.py tests/hermes_cli/test_kanban_decompose.py tests/hermes_cli/test_kanban_lifecycle_hooks.py -q
48 passed in 5.60s
$ ~/.hermes/hermes-agent/venv/bin/python -m pytest tests/tools/test_kanban_tools.py tests/plugins/test_kanban_dashboard_plugin.py -q
49 passed, 8 warnings in 4.80sManual repro on the replay lane Broad repo sweep $ scripts/run_tests.sh
Timed out after 600s at ~61.3%.
Visible failures before timeout were unrelated to this kanban change:
- tests/agent/test_credential_pool_routing.py::TestFailureAttribution::test_unmatched_key_does_not_retry_only_pool_entry
- tests/hermes_cli/test_runtime_provider_resolution.py::test_qwen_oauth_auto_fallthrough_on_auth_failure
- tests/hermes_cli/test_service_manager.py::test_seed_supervise_skeleton_creates_expected_layout
- tests/hermes_cli/test_update_eol_churn.py::test_churn_across_more_files_than_fit_in_one_argv
- plus other pre-existing reds already in progress before timeoutI am pushing this replay commit onto the PR head branch so #65846 reflects current-main state while the original local preservation packet ( |
a32b5b1 to
cb39338
Compare
…xistent board HERMES_KANBAN_BOARD (and the scoped_current_board override) naming a board with no directory under boards_root() used to fall through silently to the on-disk current pointer and then 'default' — explicit intent got redirected to another board's DB with no error. Observed 2026-07-16: HERMES_KANBAN_BOARD=fleet-infra 'hermes kanban create' placed cards on the default board because fleet-infra had been archived to boards/_archived/. Explicit selections (env var, scoped override) now raise the new BoardNotFoundError with remediation hints. The ambient <root>/kanban/ current pointer keeps its fall-through (upstream PR NousResearch#20183 behaviour — hand-edited/stale files must not crash the dispatcher) but now warns on stderr instead of falling back silently. Same failure family as the HERMES_HOME silent-profile-fallback fix (registry: hermes-cli-no-hermes-home-scoped-resolution). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-authored-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com> Signed-off-by: Hafiz Ahmad Ashfaq <28647270+ahmadashfq@users.noreply.github.com>
cb39338 to
8b5b46a
Compare
Summary
BoardNotFoundErrorwhen an explicit kanban board selection (HERMES_KANBAN_BOARDorscoped_current_board(...)) names a missing boardkanban/currentpointer on the existing warn-and-fallback behavior, but make the fallback loud on stderr instead of silentWhy
Explicit board intent should never be silently redirected to another board's DB. On 2026-07-16,
HERMES_KANBAN_BOARD=fleet-infra hermes kanban create ...routed todefaultafterfleet-infrahad been archived, with no error or warning.How to test
python -m pytest tests/hermes_cli/test_kanban_boards.py -qpython -m pytest tests/hermes_cli/test_kanban_db.py tests/hermes_cli/test_kanban_decompose.py tests/hermes_cli/test_kanban_lifecycle_hooks.py -qpython -m pytest tests/tools/test_kanban_tools.py tests/plugins/test_kanban_dashboard_plugin.py -qHERMES_HOME:HERMES_KANBAN_BOARDto a missing boardBoardNotFoundErroris raised and zero tasks land on the fallback boardkanban/currentpointer, and confirm resolution returnsdefaultwith a stderr warningscripts/run_tests.shremains red on both base5ee51c696and patcheda32b5b195on this machine in unrelated areas; touched kanban suites are greenPlatforms tested
Related context
HERMES_HOMEsilent-profile-fallback fix: explicit missing context should fail loudly, not redirect silently