Files
Claw3D/src
JimmyBlanquetandGitHub 40be0d5253 fix(office): unblock Hermes adapter + stop persistence loops (#140)
* fix(office): unblock Hermes adapter integration (Phase 2 Claw3D)

Two bugs prevent the Hermes adapter from auto-connecting on /office:

1. useSearchParams() at OfficeScreen root suspends during hydration in
   Next.js dev mode, keeping the parent Suspense fallback stuck on
   "Loading..." indefinitely. Replace with sync useMemo reading
   window.location.search so debugEnabled is stable across renders.

2. hasLastKnownGoodState only became true when
   gateway.lastKnownGood.adapterType matched the currently selected
   adapter. Switching to Hermes never auto-connected because
   lastKnownGood was still "openclaw" from the prior OpenClaw session.
   Allow auto-connect for auto-managed adapters (hermes/openclaw/demo)
   when a persisted URL exists for the selected adapter, regardless of
   lastKnownGood.

E2E pipeline validated via node WS shell:
- ws://127.0.0.1:3030/api/gateway/ws receives connect.challenge
- connect frame returns hello-ok with adapterType=hermes + full method list
- Upstream chain: proxy(:3030) → adapter(:18790) → Hermes API(:8642)

* fix(office,gateway,coordinator): stop persistence loops causing PUT /api/studio spam

Three distinct bugs caused the persistence layer to schedule patches on
every render after the OfficeScreen mounted, generating PUT /api/studio
~1/second indefinitely and triggering React "Maximum update depth
exceeded" warnings:

1. GatewayClient.ts:1102 — schedulePatch effect compared against a
   stale baseline (`loadedGatewaySettings.current` frozen at boot).
   After a valid adapter switch (e.g. to Hermes), each render still
   saw the state as "dirty" and re-scheduled the same patch. Fix: add
   a snapshot ref + update the baseline after scheduling.

2. useTaskBoardController.ts:833 — taskBoard effect persisted on every
   `state.cards` reference change without semantic equality check. Fix:
   add a JSON-snapshot ref guard.

3. useTaskBoardController.ts:1154 — dedupe effect dispatched archive
   marks for duplicate cards, which mutated `state.cards` and re-ran
   the effect. Fix: snapshot ref so a structurally-identical card set
   doesn't re-enter dedupe.

4. coordinator.ts:354 — `mergeStudioPatch` `!current` branch missed
   copying `taskBoard`, allowing the merged patch to drop persisted
   task-board state on first write.

Validated via Playwright + dev server logs:
- Before: ~1 PUT /api/studio per second
- After:  0 PUT in a 30s steady-state window post-mount
- React "Maximum update depth" warnings reduced from ~3-4/30s to ≤1/30s
2026-05-30 15:44:12 -05:00
..
2026-03-19 23:14:04 -05:00