Phase E.5.5 — apply a BlockMoved event to SQLite.
Handles both cross-tab moves and intra-tab repositioning.
Idempotent on re-delivery (checks current parent before mutating).
Apply one reducer event to the on-disk store. Idempotent: each
arm checks for the entity’s current SQLite state before writing
so duplicate events (from at-least-once delivery semantics) don’t
produce duplicate rows or wcore errors.
Phase E.4 (Option A) — write the reducer-emitted focused node id
onto the tab’s LayoutState.focusednodeid column. Tab→layout is
a join through Tab.layoutstate. Idempotent: silent no-op when the
tab is unknown (deleted concurrently), the layout row is missing
(legacy tab without one), or the value already matches. Other
LayoutState fields stay on their existing wcore-direct path until
Option B lands.
Phase E.4 (Option A) — write the reducer-emitted magnified node id
onto the tab’s LayoutState.magnifiednodeid column. Same shape as
apply_focused_node_changed.
Phase E.5 — delete the persisted Window row + remove the id
from Client.windowids. Mirrors wcore::close_window’s order:
prune client.windowids FIRST (so any read between the two ops
doesn’t see a dangling id), then delete the Window row.
(codex P1 #619.)
Phase E.5 — record/update a window’s workspace pointer on the
persisted Window row. Idempotent: inserts if missing, updates
if workspaceid differs, no-ops if identical.
Phase E.5.5 — apply a TabMoved event to SQLite.
Idempotent: detects already-moved state (tab in dst, not in src)
and returns Ok(()) without re-mutating.
Phase E.5.3 — replace the workspace’s tabids with the new
list and drain any legacy pinnedtabids rows. Pinning was a
Waveterm feature removed from AgentMux; bootstrap merges legacy
pinned tabs into the reducer’s tab_ids, so the next reorder
is the canonical full ordering. Leaving stale pinnedtabids
in SQLite would cause UI double-insertion (workspace.tsx
builds the displayed tab list as [...pinnedtabids, ...tabids]).
Phase E.5.x (issue #855) — apply a meta-patch to a window’s meta
map. Same shape as apply_workspace_meta_updated. Silent no-op if
the window doesn’t exist in wstore (preserves the idempotency
contract — duplicate or stale events fold to no-op).
Phase E.5.3 — apply a meta-patch to a workspace’s meta map.
Reducer doesn’t track meta in WorkspaceRecord; this subscriber
is the sole authority that mutates persisted meta. Patch is a
JSON object that merges shallow-key-by-shallow-key on top of the
existing meta. null values in the patch delete the key.
Phase E.5.3 — shallow merge a JSON object patch into a
MetaMapType. Mirrors backend::obj::merge_meta semantics so
UpdateObjectMeta keeps behaving the same way after the reducer
migration:
Snapshot state.workspaces and reconcile against SQLite —
INSERT/UPDATE only, no deletes. Workspace-scoped (tab/block
resync expands here as each entity’s RPC layer migrates).
Spawn the persist subscriber task. Runs until the broadcast
channel closes (i.e., the reducer’s bus is dropped at process
shutdown). The state handle is used for workspace-scoped
full-resync after a RecvError::Lagged.