1619c0e503
Found during full-stack live-test of the kanban system: two bugs where
the kernel and CLI didn't match the documented contract.
Kernel
- `connect()` now auto-runs schema creation + migrations on the
first connection to a given DB path, matching its docstring
('Open (and initialize if needed)' — which was aspirational until
now). Module-level _INITIALIZED_PATHS cache keeps subsequent
connects cheap. Previously the docstring lied: every path that
went through connect() on a fresh HERMES_HOME raised 'no such
table: tasks' — only `hermes kanban init` and `daemon` triggered
schema creation.
- `init_db()` always re-runs the migration pass (clears the cache
entry first). Callers that know the on-disk schema may have
drifted — tests writing legacy event kinds, external tools
upgrading an old DB file — can force re-migration.
CLI
- `kanban_command()` entry point auto-inits the DB before
dispatching any subcommand. Idempotent; the underlying
connect-based init pattern makes this a one-line SELECT against
sqlite_master after the first call.
- `hermes kanban show --json` now includes:
- `runs`: full attempt history (id, profile, step_key, status,
outcome, summary, error, metadata, worker_pid, started_at,
ended_at)
- `run_id` on every event object
Dashboard API already had both; CLI was behind. Now scripts that
inspect a task can use `show --json` alone.
- `hermes kanban show` (human-readable) prints a Runs section
matching the `runs` subcommand's format, and each Event line
prefixes its run_id when present. Makes attempt attribution
visible at a glance without a second command.
Tests (+3)
- cli_create_on_fresh_home_auto_inits (subprocess, no init_db call,
must succeed — covers the most common first-user path)
- connect_auto_inits_fresh_db (direct kernel use without init_db)
- cli_show_json_carries_runs (runs[] present; events carry run_id)
174/174 kanban suite pass under scripts/run_tests.sh.
Live-tested end-to-end
- Phases 1-6: CLI subprocess (create/claim/complete/bulk-guard/
synthetic-run/reclaim-via-TTL/multi-attempt history)
- Phases 7-10: Dashboard FastAPI TestClient (POST/PATCH with
summary+metadata, drag-drop running->ready, archive-while-
running, mark-done-with-handoff)
- Phases 11-13: Dispatcher with stub spawn_fn (3 tasks success,
3 failures -> gave_up circuit breaker, event.run_id attribution
across retries)
- Phases 14-15: WebSocket /events (run_id payload, auth rejects
wrong tokens with code 1008)
- Phase 16: Gateway notifier (unseen_events_for_sub returns
run_id on events, message renders 'done — title' + handoff
summary from event payload, crashed event path, sub cleanup)
Every surface — kernel, dispatcher, CLI, dashboard REST, dashboard
WebSocket, gateway notifier — exercised end-to-end against a live
FastAPI app with a real SQLite DB in an isolated HERMES_HOME. All
passed.