| name | e2e |
| description | Run (and extend) the reusable end-to-end test harness for board-steward. Use when the user wants to verify a board-steward overhaul end-to-end โ multi-board routing/isolation, reconciliation (gating + real-Haiku moves), or a future feature โ WITHOUT polluting their live board. Triggers: "run e2e", "/e2e", "test multi-board", "test recon end to end", "verify the overhaul", "regression test the board", "does routing/recon still work". The harness isolates all state, uses throwaway boards, and asserts the live board is untouched. |
e2e โ board-steward end-to-end test harness
A reusable harness that codifies the verification patterns proven during ARCH REDESIGN v2 (multi-board routing + reconciliation). Run it to regression-test those overhauls โ or extend it for the next one โ instead of hand-writing throwaway test scripts each time.
Source of the redesign it tests: ~/Desktop/WorkBoard/docs/ARCH_REDESIGN_V2.md.
The cardinal rule (why this exists)
A test must NEVER pollute the user's live board or global state. The harness enforces this structurally:
- Isolated state โ
BOARD_REGISTRY / BOARD_ASSIGNMENTS / BOARD_ACTIVE are pointed at temp files; BOARD_NO_SERVER=1 forces direct file writes for tests that don't need a server. The real ~/.board-steward/ is never touched.
- Throwaway boards โ every board under test is a temp dir, seeded in-memory or from
templates/board.json.
- Live-board guard โ the live board's (
:7891) card count is captured before the run and asserted unchanged after. If a test touches it, the suite fails.
- Cleanup โ all temp dirs are removed at the end.
How to run
python3 ~/.claude/skills/e2e/e2e_workboard.py multiboard
python3 ~/.claude/skills/e2e/e2e_workboard.py recon
python3 ~/.claude/skills/e2e/e2e_workboard.py recon-haiku
python3 ~/.claude/skills/e2e/e2e_workboard.py all
python3 ~/.claude/skills/e2e/e2e_workboard.py all --haiku
Override the repo with BOARD_REPO=/path/to/WorkBoard (default ~/Desktop/WorkBoard).
Exit code 0 = all passed, 1 = a failure (printed at the bottom), 2 = bad args / repo not found.
Test catalog (what each group proves)
multiboard โ the v2 multi-board work
routing_isolation โ a card added from inside project A lands on A, never B; last-active tracks the last-mutated board.
disambiguation โ at $HOME, the last-active board wins over a newer-mtime board; mtime is only the fallback (the wrong-board bug that started v2).
recon (free) โ the v2 reconciliation work
only_discovered_flag โ reconcile_sweep(only_discovered=True) scopes to bootstrap-mined cards; False reconciles every non-done card (so SessionStart catches live cards).
gates_short_circuit โ --reconcile-only makes no Haiku call when there are no non-done cards (Gate A) or no recorded project activity (Gate B).
claudecode_path โ CLAUDECODE=1 writes a prose recon_pending.json (no Haiku); proves the spawn's env -u CLAUDECODE is load-bearing for the autonomous Haiku path.
recon-haiku (costs ~1 Haiku call) โ the real end-to-end
haiku_e2e โ a real claude -p --model haiku pass moves a shipped In-Progress card โ done and a "nvm/skip" card โ backlog.
Extending for the NEXT overhaul
Add a function test_<group>_<name>(ctx) in e2e_workboard.py and register it in GROUPS. Use the context helpers โ they keep the cardinal rule automatic:
ctx.board(cards=[...]) โ a throwaway project board.json (pass from_template=True for the real seed).
ctx.card(num, column, title, tags=[...]) โ a minimally-valid card dict (real cards always carry an id).
ctx.assert_eq(name, got, want) / ctx.assert_true(name, cond, detail) โ record pass/fail.
- State is already isolated in
Ctx.__init__; the live-board guard runs automatically.
Always: isolate state, use throwaway boards, and never assume the live server's state. If a feature needs a running server, start it on an explicit free port (e.g. 7950) and verify :7891's count is unchanged.