The Zustand store persisted to sessionStorage, which is tab-volatile — a
hard reload / new tab / closing the tab dropped the whole session,
including the board binding (device.connected, nodeUrl, teamId). The
workshop runs on the team's own laptop, so switch the store (and the
offline outbox) to localStorage: the binding + progress now survive a
refresh, hard reload, navigation, and tab close.
Clearing is now explicit only: a new `disconnect()` action drops the board
binding (keeping team/domain/phases/ADD so they can re-bind and resume),
surfaced as a "Disconnect" button on the claimed-board card. `reset()`
still wipes everything.
Tests: add an in-memory localStorage to setupTests (Node 22's disabled
experimental localStorage shadows jsdom's) + clear it per test.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
The board is now a Claude-powered ZeroClaw agent with expert skills that teams
talk to directly (its own dashboard / Telegram / voice). The frontend was built
on the older sensor+harness model; this repoints it.
- State/DTO: AddLayers remapped to the 5 design layers (Domain/Skills/Policies/
Harness/Loops); added session.domain (+ mirrored through TeamSnapshot, sync,
and the SQLite store with a guarded migration); dropped Harness/Provider/RunMode;
persist v2 migrate resets stale state.
- Removed the harness/sim/failover machinery (HarnessProviderSelect, HarnessTuner,
HarnessTomlPreview, ResiliencePanel, TriggerButtons, harness.ts, useSerial,
LiveFeed/serial classifier) and every sim-vs-live branch.
- Onboarding: EnvSetup rebuilt into 'Meet your node' — Open-your-node hero (new
reusable OpenYourNode CTA), say-hi-to-your-agent, a free-text DomainPicker
(domain drives L1-L5), Telegram/voice pointers, and the open->locked lockdown
policy step. Domain is required to proceed.
- Modules repointed: M1 Domain & events (L1), M2 Skills & Policies (L2/L3, skills
reference + actuation-gate framing), M3 Harness (reasoning+tiering) & Loops
(cadence) (L4/L5). BuildFlash reframed as a guided 'ask your node to build X'
that hands off to the node dashboard.
- Judge rubric -> Domain fit/Skills/Policies/Harness/Loops; Lecture + Landing
re-storied to the Claude-node + talk-to-your-node narrative.
Verified: web tsc + 181 tests, api tsc + 58 tests, dead-ref sweep clean.
Co-Authored-By: Claude Opus 4.8 <[email protected]>
- src/lib/api.ts: typed client for the collective — pushTeam/pushSubmission
(public), getTeams/getSubmissions/getSubmission/postScore/getLeaderboard
(code-gated), and openCollective WS with auto-reconnect
- src/lib/useCollectiveSync.ts: offline-first sync mounted once in App —
projects the store to a TeamSnapshot, pushes on phase change + submission,
throttles stat churn, and routes failures to a sessionStorage outbox that
retries on interval + window 'online'. Never blocks the participant flow.
11 new tests (incl. backend-down path); suite 112/112 green, typecheck + lint clean.
Co-Authored-By: Claude Opus 4.8 (1M context) <[email protected]>