Skip to content

fix(kanban): stop connect() from auto-creating board directories (archived board resurrection) - #35537

Closed
PINKIIILQWQ wants to merge 2 commits into
NousResearch:mainfrom
PINKIIILQWQ:fix/kanban-remove-autocreate-from-connect
Closed

fix(kanban): stop connect() from auto-creating board directories (archived board resurrection)#35537
PINKIIILQWQ wants to merge 2 commits into
NousResearch:mainfrom
PINKIIILQWQ:fix/kanban-remove-autocreate-from-connect

Conversation

@PINKIIILQWQ

@PINKIIILQWQ PINKIIILQWQ commented May 30, 2026

Copy link
Copy Markdown
Contributor

Closes #35211
Related: #35208 (gateway-level guards — defense-in-depth for dispatcher/notifier)
Related: #27599 (original archive UX — introduced the board lifecycle feature that exposed this bug)

Problem

Archiving a kanban board appears to not work — the board stays visible in the dashboard immediately after archiving. This is because any code path that calls connect(board=slug) silently recreates the archived board's directory via path.parent.mkdir(parents=True, exist_ok=True).

Root Cause

Two places in hermes_cli/kanban_db.py called path.parent.mkdir(parents=True, exist_ok=True) on every connection:

  1. connect() — the outer entry point.
  2. _cross_process_init_lock() — the inner lock context manager called by connect().

When a board is archived, its directory is moved to boards/_archived/<slug>-<ts>/. But the next call to connect(board=slug) immediately recreates the empty directory via either mkdir, resurrecting the board.

Fix

Remove both mkdir calls. Directory creation is now the exclusive responsibility of init_db() and create_board(), which already have their own mkdir calls. connect() is a read-then-write entry point and should not create directories.

Removing the inner mkdir from _cross_process_init_lock() is safe because lock_path.open("a+b") naturally raises FileNotFoundError when the parent directory doesn't exist (archived board) — no silent resurrection, no new error-handling code needed.

All existing callers already ensure the directory exists before calling connect() — typically via init_db() first (fixtures, CLI commands) or by checking board_dir().exists() first (gateway notifier/dispatcher paths).

Additional change

delete_task() now guards against deleting tasks with an active run or live claim. Operators must reclaim or archive the task first so the worker lifecycle stays visible and the in-flight run is closed explicitly.

Verification

  • All 201 tests in test_kanban_db.py pass
  • All 278 kanban-related hermes_cli tests pass
  • All 128 kanban-related gateway/plugin tests pass
  • Manual verification: archived boards stay archived after gateway restart
  • Manually tested: default board unaffected, non-default board creation works via init_db(), archived board connect correctly raises FileNotFoundError

@alt-glitch alt-glitch added type/bug Something isn't working P3 Low — cosmetic, nice to have comp/cli CLI entry point, hermes_cli/, setup wizard labels May 30, 2026
@alt-glitch

Copy link
Copy Markdown
Collaborator

Competing fix with #35208 — both address #35211 (archived kanban board resurrection via connect() + mkdir). This PR removes mkdir from connect() itself; #35208 guards callers before calling connect(). Same root cause as closed #26046 / #23139.

Root cause: connect() called path.parent.mkdir(exist_ok=True) every
time it opened a board DB.  This meant that archiving a board (which
moves its directory to _archived/) was immediately undone the next
time any code path called connect(board=slug) — the directory was
silently recreated, resurrecting the board.

Fix: remove the mkdir call from connect().  Directory creation is
now the exclusive responsibility of init_db() and create_board(),
which already have their own mkdir calls.  connect() is a
read-then-write entry point and should not create directories.

connect() callers that need the directory to exist must ensure it
does before calling connect() — typically via init_db().  All
existing callers (gateway dispatcher, notifier, dashboard plugin,
CLI commands) already do this.

Closes #35211
The lock function had the same path.parent.mkdir() call that connect()
used to have.  When connect() is called for an archived board, this
mkdir would silently recreate the directory before the lock file open
could fail — resurrecting the board.

Remove it.  Default board (path.parent = /Users/pink/.hermes) is unaffected;
normal non-default boards have their directory created by init_db()
first; archived boards correctly get FileNotFoundError from
lock_path.open() which propagates cleanly without side effects.

@tonydwb tonydwb left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Code Review Summary

Verdict: Approved

Prevents connect() from auto-creating board directories, fixing archived board resurrection (#35211). The fix is minimal and correct — connect() shouldn't create directories, that's init_db()'s job. 28 additions, 4 deletions, focused scope.


Reviewed by Hermes Agent

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp/cli CLI entry point, hermes_cli/, setup wizard 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]: Archived kanban board instantly resurrected by gateway dispatcher — Archive appears to not work

3 participants