Command

Enum Command 

Source
pub enum Command {
Show 61 variants Register { kind: ClientKind, pid: u32, version: String, }, Ping { nonce: u64, }, Goodbye, ReportWindowOpened { label: String, kind: WindowKind, parent_label: Option<String>, }, ReportWindowClosed { label: String, }, ReportPoolWindowAdded { label: String, saga_id: Option<u64>, }, ReportPoolWindowRemoved { label: String, }, ReportHostCounts { windows: u32, pool: u32, }, ReportHostPoolCount { count: u32, }, ReportBackendWindowIdRegistered { label: String, window_id: String, }, ReportBackendWindowIdUnregistered { label: String, }, ReportHwndOpened { hwnd: u64, class_name: String, title: String, label_hint: Option<String>, }, ReportHwndDestroyed { hwnd: u64, }, ReportHwndVisibilityChanged { hwnd: u64, visible: bool, }, ReportHwndForegroundChanged { hwnd: u64, }, ReportHwndIconicChanged { hwnd: u64, iconic: bool, }, ReportHwndPositionChanged { hwnd: u64, rect: Rect, }, ReportMonitorTopologyChanged { rects: Vec<Rect>, }, GetSnapshot, GetSrvSnapshot, CreateWorkspace { name: String, }, DeleteWorkspace { workspace_id: String, force: bool, }, CreateTab { workspace_id: String, name: String, }, DeleteTab { workspace_id: String, tab_id: String, force: bool, }, SetActiveTab { workspace_id: String, tab_id: String, }, ReorderTab { workspace_id: String, tab_id: String, new_index: u32, }, CreateWindow { window_id: String, workspace_id: String, }, CloseWindowInternal { window_id: String, }, SwitchWorkspace { window_id: String, workspace_id: String, }, ReorderTabsBulk { workspace_id: String, tab_ids: Vec<String>, }, RenameWorkspace { workspace_id: String, name: String, }, RenameTab { tab_id: String, name: String, }, UpdateWorkspaceMeta { workspace_id: String, meta_patch: Value, }, UpdateTabMeta { tab_id: String, meta_patch: Value, }, UpdateBlockMeta { block_id: String, meta_patch: Value, }, UpdateWindowMeta { window_id: String, meta_patch: Value, }, MoveTab { tab_id: String, src_workspace_id: String, dst_workspace_id: String, dst_index: u32, }, MoveBlock { block_id: String, src_tab_id: String, dst_tab_id: String, dst_index: u32, }, CreateBlock { tab_id: String, meta: Value, }, DeleteBlock { tab_id: String, block_id: String, }, SetFocusedNode { tab_id: String, node_id: String, }, SetMagnifiedNode { tab_id: String, node_id: String, }, LayoutInsertNode { tab_id: String, node: LayoutNode, parent_id: Option<String>, index: Option<usize>, focus_after: bool, magnify_after: bool, correlation_id: String, }, LayoutInsertNodeAtIndex { tab_id: String, node: LayoutNode, index_arr: Vec<usize>, focus_after: bool, magnify_after: bool, correlation_id: String, }, LayoutDeleteNode { tab_id: String, node_id: String, correlation_id: String, }, LayoutMoveNode { tab_id: String, node_id: String, new_parent_id: String, index: usize, correlation_id: String, }, LayoutSwapNodes { tab_id: String, node1_id: String, node2_id: String, correlation_id: String, }, LayoutResizeNodes { tab_id: String, ops: Vec<ResizeOp>, correlation_id: String, }, LayoutReplaceNode { tab_id: String, target_id: String, new_node: LayoutNode, focus_after: bool, correlation_id: String, }, LayoutSplitHorizontal { tab_id: String, target_id: String, new_node: LayoutNode, position: SplitPosition, focus_after: bool, correlation_id: String, }, LayoutSplitVertical { tab_id: String, target_id: String, new_node: LayoutNode, position: SplitPosition, focus_after: bool, correlation_id: String, }, LayoutClear { tab_id: String, correlation_id: String, }, LayoutSetTree { tab_id: String, new_tree: Option<LayoutNode>, correlation_id: String, }, GetEvents { since: u64, }, ReportPoolWindowPromoted { label: String, }, SpawnPoolWindow { saga_id: u64, }, ReportPanesReaped { label: String, saga_id: Option<u64>, }, ReportPoolDrainDecision { label: String, was_last: bool, saga_id: Option<u64>, }, ReapPanes { label: String, saga_id: u64, }, DrainPoolIfLast { label: String, saga_id: u64, }, ReportSagaActionFailed { saga_id: u64, reason: String, },
}
Expand description

Commands flow client → launcher.

Variants§

§

Register

Identifies the connection. MUST be the first command on every new connection. Server enforces.

Fields

§pid: u32

PID of the connecting process — used for cross-checking against the launcher’s ProcessRecord map and for log correlation.

§version: String

Free-form version string of the client binary, for log correlation across version skew.

§

Ping

Health probe — server replies with Event::Pong carrying the same nonce. NOT a polling heartbeat (per spec §4.3) — sent only on demand by clients that need round-trip confirmation.

Fields

§nonce: u64
§

Goodbye

Graceful disconnect. Server logs and closes the connection. In B.3+ this becomes Quit { reason } with shutdown semantics; for B.2 it’s just a polite goodbye.

§

ReportWindowOpened

Phase B.4: host reports that a real window has been created (CEF on_after_created fired). Launcher records it in its read-only mirror and broadcasts Event::WindowOpened to other subscribers. Pool windows do NOT report via this command — they get their own ReportPool* commands in a follow-up so the mirror can distinguish user-visible windows from pool inventory.

Fields

§label: String

Stable label assigned by the host (e.g. “main”, “window-{uuid}”).

§parent_label: Option<String>

For Subwindow only: label of the FullInstance parent. None for FullInstance.

§

ReportWindowClosed

Phase B.4: host reports a window is closing (on_before_close). Launcher removes from mirror, broadcasts Event::WindowClosed. Idempotent: a missing label is logged but not an error (covers the close-before-launcher-saw-the-open race).

Fields

§label: String
§

ReportPoolWindowAdded

Phase B.4 follow-up — host reports a pre-warmed pool window being added (spawn_pool_window). Pool windows live in a SEPARATE map from the user-visible window mirror; the host transitions them out of the pool with ReportPoolWindowRemoved

  • ReportWindowOpened on promote, or just ReportPoolWindowRemoved on pre-promote destroy.

Fields

§label: String
§saga_id: Option<u64>

Phase CPD-1 (cross-process dispatch) — saga correlation echo. Some(N) when the host is replying to a saga-issued Command::SpawnPoolWindow { saga_id: N }; None for organic refills (e.g. host’s implicit spawn_pool_window inside promote_pool_window). The launcher reducer passes the value through to Event::PoolWindowAdded so per-saga correlation (CPD-4) can match the response to the originating saga.

#[serde(default)] for forward-compat with hosts running pre-CPD-1 builds — they emit no saga_id field, which deserializes as None (organic). Removed once CPD-1+CPD-3 have soaked one release cycle.

§

ReportPoolWindowRemoved

Phase B.4 follow-up — host reports a pool window leaving the pool (promote, destroy, or app exit).

Fields

§label: String
§

ReportHostCounts

Phase B.4 follow-up — drift detection (full snapshot). Host sends its own post-mutation counts after each window-level transition; the launcher reducer compares both dimensions to its mirror counts and emits Event::DriftDetected per disagreeing dimension. Sent in a separate command (rather than embedded in each Report*) so the existing wire shapes stay unchanged.

Known limitation (B.4 observe-only): emissions originate from multiple execution contexts (CEF UI thread for on_after_created/on_before_close, IPC handler thread for promote_pool_window). Cross-thread interleaving in the outbound channel can produce a snapshot whose counts were taken at a moment that doesn’t match the channel order seen by the reducer, occasionally emitting a transient false DriftDetected. Acceptable for B.4 (drift is diagnostic — false positives are ephemeral and self-correct on the next stable state). B.5 will tighten with a transition-ID protocol once the launcher is authoritative. (codex P2 PR #578 round-4 — accepted as known limitation.)

Fields

§windows: u32

User-visible top-level windows in the host’s authoritative store (browsers minus browser-pane children minus unpromoted pool labels).

§pool: u32

Pre-promote pool inventory size.

§

ReportHostPoolCount

Phase B.4 follow-up — pool-dimension-only drift check. Used by spawn_pool_window (pool transitions) where snapshotting the windows dimension would produce transient false drift: pool refill is triggered DURING on_before_close BEFORE the matching ReportWindowClosed lands, so the host’s window count is mid-flight relative to the launcher mirror. Pool count IS stable at that moment (the new pool label was just added), so checking pool alone preserves the “check every transition” guarantee for the dimension that actually changed. (codex P2 PR #578 round-3.)

Fields

§count: u32
§

ReportBackendWindowIdRegistered

Phase B.5 (window_id_map step a) — host reports the frontend’s register_backend_window call: a window’s label → backend window ID (a srv-side UUID the frontend resolves via WOS.makeORef). The launcher mirrors it for the same reasons it mirrors instance_registry: host’s authoritative copy will be retired through the a→b→c→d→e ratchet.

Fields

§label: String
§window_id: String
§

ReportBackendWindowIdUnregistered

Phase B.5 (window_id_map step a) — host reports a window closing, so the launcher should drop the label→window_id mapping. Sent from the same close path that emits ReportWindowClosed.

Fields

§label: String
§

ReportHwndOpened

Phase B.9.1 (WRR — Window Reality Reconciliation) — host reports a Win32 top-level window was created. Hooked off EVENT_OBJECT_CREATE (objid=OBJID_WINDOW) via SetWinEventHook(WINEVENT_OUTOFCONTEXT). The host filters CEF subprocess HWNDs (renderer, GPU, plugin) at the hook callback so the launcher only sees plausible app windows. label_hint is the host’s best guess from pending_window_creations if it can disambiguate; None when the create event arrives before the host has linked the HWND back to a label (caught up later by the reducer’s pending_hwnds).

Fields

§hwnd: u64
§class_name: String
§title: String
§label_hint: Option<String>
§

ReportHwndDestroyed

Phase B.9.1 — host reports a Win32 top-level window was destroyed. Hooked off EVENT_OBJECT_DESTROY.

Fields

§hwnd: u64
§

ReportHwndVisibilityChanged

Phase B.9.1 — EVENT_OBJECT_SHOW / EVENT_OBJECT_HIDE.

Fields

§hwnd: u64
§visible: bool
§

ReportHwndForegroundChanged

Phase B.9.1 — EVENT_SYSTEM_FOREGROUND. Tells the launcher the user actually saw this window (not just opened it). Used to distinguish “opened but never foregrounded” (drift) from “opened and shown”.

Fields

§hwnd: u64
§

ReportHwndIconicChanged

Phase B.9.1 — EVENT_SYSTEM_MINIMIZESTART / EVENT_SYSTEM_MINIMIZEEND.

Fields

§hwnd: u64
§iconic: bool
§

ReportHwndPositionChanged

Phase B.9.1 — WM_WINDOWPOSCHANGED from the host’s wndproc wrapper. The host coalesces bursts (50ms debounce per HWND) before sending so the wire stays light during topology changes. Reducer compares rect against state.monitors to classify off-monitor drift.

Fields

§hwnd: u64
§rect: Rect
§

ReportMonitorTopologyChanged

Phase B.9.1 — WM_DISPLAYCHANGE. Replaces the launcher’s state.monitors wholesale; reducer re-evaluates every known window’s last_rect against the new topology and emits OffMonitor drift for any that newly fall off.

Fields

§rects: Vec<Rect>
§

GetSnapshot

Phase D.1 — request a Event::Snapshot reply containing the reducer’s current canonical state. Used by --diag wrr for state-now visibility, by the frontend reducer for mid-session resync after disconnect, and by future Tool clients that need to bootstrap without observing every prior event.

§

GetSrvSnapshot

Phase E.1b — srv-side equivalent of GetSnapshot. Routed to the srv pipe; reducer replies with Event::SrvSnapshot. Separate from GetSnapshot (launcher) per spec §4.3 — each reducer is canonical for its domain and replies on its own pipe.

Reply contents grow with each phase: E.1b had lifecycle + version only; E.2 added workspaces; E.2b+ will add tabs / blocks / layouts. See Event::SrvSnapshot for the current shape.

§

CreateWorkspace

Phase E.2 — create a new workspace. The reducer assigns the oid (UUID) and emits Event::WorkspaceCreated. In E.2 the reducer is a session-only projection (no persist subscriber); E.2c adds the persist subscriber + migrates HTTP/WS RPC to flow through the reducer.

Fields

§name: String
§

DeleteWorkspace

Phase E.2 — delete a workspace. Reducer removes from canonical state and emits Event::WorkspaceDeleted. Cascade-to-tabs + SQLite write happen via wcore today (RPC path); migrating to reducer-driven persistence is E.2c.

Fields

§workspace_id: String
§force: bool

Step 5 PR 2 — provenance marker for the delete_workspace saga. true means the dispatch is being driven by the saga coordinator (per-tab DeleteTab dispatches already happened in saga steps; this final cascade is just the workspace row + window mappings). false for legacy / internal compensation paths (e.g. tear_off_tab / tear_off_block rolling back a freshly-created empty workspace) which keep the existing cascade behaviour.

The reducer’s handle_delete_workspace cascades regardless of force — the reducer is a pure mutator and the cascade must always execute to keep state consistent. The flag is recorded in the saga log purely for provenance, mirroring the saga-as-narrator pattern documented in docs/retro/phase-fg-roadmap-2026-05-01.md.

Defaults to false via #[serde(default)] so all existing producers (RPC, internal compensation) keep working.

§

CreateTab

Phase E.2b — create a tab inside an existing workspace. The reducer assigns the tab_id (UUID), appends to the workspace’s ordered tab list, and emits Event::TabCreated. Validates the parent workspace exists; returns Event::Error if not. Session-only projection (no persist subscriber yet).

Fields

§workspace_id: String
§name: String
§

DeleteTab

Phase E.2b — delete a tab from a workspace. Reducer removes the tab from canonical state, removes its id from the workspace’s ordered tab list, and emits Event::TabDeleted. If the deleted tab was the active tab, also emits Event::ActiveTabChanged pointing at the new active (next-or-prev tab, or empty if the workspace has no tabs left).

Fields

§workspace_id: String
§tab_id: String
§force: bool

(codex P2 PR #633 round 4 + codex P1 round 2.) Bypass the reducer’s atomic last-tab guard. false for user-facing flows (close button, keyboard shortcut) — reducer rejects last-tab deletes to keep workspaces non-empty. true for internal compensation paths (CreateTab rollback, PromoteBlockToTab compensation) where rolling back a just-created tab requires deleting the only tab.

Defaults to false via #[serde(default)] for backwards compatibility — pre-existing producers that don’t set the field get the safe (guarded) behavior.

§

SetActiveTab

Phase E.2b — set a workspace’s active tab. No-op if already active. Errors if the workspace doesn’t exist or the tab isn’t in that workspace’s tab list.

Fields

§workspace_id: String
§tab_id: String
§

ReorderTab

Phase E.2c.3b — reorder a tab within its workspace’s tab_ids. new_index is clamped to the list length; no-op if the tab is already at that position. Errors if the workspace doesn’t exist or the tab isn’t in its tab list.

Fields

§workspace_id: String
§tab_id: String
§new_index: u32
§

CreateWindow

Phase E.5 — record a new window in the srv reducer’s state.windows map. Caller pre-assigns window_id (sagas use a fresh UUID; RPC migration in PR 4 will likewise mint the id at the RPC boundary). Validates the parent workspace exists; errors otherwise. Used by CreateWindow + TearOff sagas to track window↔workspace association.

Fields

§window_id: String
§workspace_id: String
§

CloseWindowInternal

Phase E.5 — remove a window’s workspace mapping from the reducer. Called by CloseWindow sagas after the host’s CEF window-close completes. Idempotent silent no-op on missing.

Fields

§window_id: String
§

SwitchWorkspace

Phase E.5 — switch which workspace a window points at. Errors if the window or destination workspace is unknown.

Fields

§window_id: String
§workspace_id: String
§

ReorderTabsBulk

Phase E.5.3 — replace a workspace’s tab_ids with the given list. The new list must be a permutation of the current set (same elements, possibly different order); reducer errors otherwise. Used by the drag-reorder UI’s bulk-reorder path (replaces wcore-direct UpdateTabIds).

Fields

§workspace_id: String
§tab_ids: Vec<String>
§

RenameWorkspace

Phase E.5.3 — rename a workspace. Errors if the workspace doesn’t exist; no-op if the name is identical.

Fields

§workspace_id: String
§name: String
§

RenameTab

Phase E.5.3 — rename a tab. Errors if the tab doesn’t exist; no-op if identical.

Fields

§tab_id: String
§name: String
§

UpdateWorkspaceMeta

Phase E.5.3 — apply a meta-patch to a workspace. The reducer validates the entity exists and emits Event::WorkspaceMetaUpdated with the patch payload; the persist subscriber performs the actual merge against wstore. Reducer state does NOT track meta in E.5.3 — pass-through preserves the reducer’s small footprint without losing the migration property (every mutation goes through the reducer’s broadcast bus).

Fields

§workspace_id: String
§meta_patch: Value
§

UpdateTabMeta

Phase E.5.3 — apply a meta-patch to a tab. Same pass-through shape as UpdateWorkspaceMeta.

Fields

§tab_id: String
§meta_patch: Value
§

UpdateBlockMeta

Phase E.5.3 — apply a meta-patch to a block. Same pass-through shape as UpdateWorkspaceMeta.

Fields

§block_id: String
§meta_patch: Value
§

UpdateWindowMeta

Phase E.5.x — apply a meta-patch to a window’s meta map. Same pass-through shape as UpdateWorkspaceMeta. Migrated through the reducer per issue #855 so Event::WindowMetaUpdated lands on srv_events_tx and the WaveObjUpdate broadcast bridge picks it up — replaces the wcore-direct fallback that bypassed reducer + bridge entirely.

Fields

§window_id: String
§meta_patch: Value
§

MoveTab

Phase E.5.5 — move a tab from one workspace to another. Reducer:

  • Removes tab_id from src_workspace_id.tab_ids.
  • Updates tab.workspace_id = dst_workspace_id.
  • Inserts tab_id at dst_index in dst_workspace_id.tab_ids, clamping to the dst list length.
  • If tab_id was the source workspace’s active_tab_id, the source’s active reverts to its first remaining tab (or None if the source becomes empty). Errors if any of: source workspace, dest workspace, or tab is missing; if tab.workspace_id != src_workspace_id; or if the tab is the source workspace’s last tab AND no caller has arranged a fallback (callers like tear-off should reject the move at the saga layer if removing the tab would empty the source — preserving the “workspaces have at least one tab” invariant most UI paths assume). Used by the TearOffTab, MoveTabToWorkspace, and RestoreTornOffTab sagas.

Fields

§tab_id: String
§src_workspace_id: String
§dst_workspace_id: String
§dst_index: u32
§

MoveBlock

Phase E.5.5 — move a block from one tab to another (or to a different position in the same tab). Reducer:

  • Removes block_id from src_tab_id.block_ids.
  • Updates block.tab_id = dst_tab_id.
  • Inserts block_id at dst_index in dst_tab_id.block_ids, clamping to the dst list length. Errors if source tab, dest tab, or block is missing, or if block.tab_id != src_tab_id. Used by TearOffBlock and the MoveBlockToTab saga.

Fields

§block_id: String
§src_tab_id: String
§dst_tab_id: String
§dst_index: u32
§

CreateBlock

Phase E.3 — create a block inside an existing tab. Reducer validates parent tab exists, assigns the block_id (UUID), appends to the tab’s block_ids, emits Event::BlockCreated. Session-only projection (no persist subscriber yet).

Fields

§tab_id: String
§meta: Value

Phase E.2c.4 — block metadata (view, layout hints, etc.) passed through to the persisted Block row. The reducer itself doesn’t track meta — it forwards it untouched into Event::BlockCreated so the persist subscriber writes the Block with the correct meta map. #[serde(default)] for forward-compat with old log entries that pre-date the meta field.

§

DeleteBlock

Phase E.3 — delete a block from a tab. Idempotent silent no-op on missing tab or missing block.

Fields

§tab_id: String
§block_id: String
§

SetFocusedNode

Phase E.4 (Option A) — set a tab’s focusednodeid. Errors if the tab is unknown to the reducer; no-op short-circuit when the value is already current. Empty node_id clears the field. Routes through the reducer so the persist subscriber writes the new value into LayoutState.focusednodeid for the tab. The rest of LayoutState (rootnode/leaforder/pendingbackendactions) keeps its existing wcore-direct path until Option B lands.

Fields

§tab_id: String
§node_id: String
§

SetMagnifiedNode

Phase E.4 (Option A) — set a tab’s magnifiednodeid. Same shape as SetFocusedNode; empty node_id clears (toggle-off).

Fields

§tab_id: String
§node_id: String
§

LayoutInsertNode

Insert a new node into the tree. If parent_id is None, the heuristic findNextInsertLocation is used (first available slot); index positions within the parent’s children (None = append).

Fields

§tab_id: String
§parent_id: Option<String>
§index: Option<usize>
§focus_after: bool
§magnify_after: bool
§correlation_id: String
§

LayoutInsertNodeAtIndex

Insert at an exact index path through the tree (e.g. [0, 2]).

Fields

§tab_id: String
§index_arr: Vec<usize>
§focus_after: bool
§magnify_after: bool
§correlation_id: String
§

LayoutDeleteNode

Remove a node by id; collapse empty parents.

Fields

§tab_id: String
§node_id: String
§correlation_id: String
§

LayoutMoveNode

Reparent a node to a new parent at the given child index.

Fields

§tab_id: String
§node_id: String
§new_parent_id: String
§index: usize
§correlation_id: String
§

LayoutSwapNodes

Swap two sibling (or cross-parent) nodes. Sizes travel with nodes.

Fields

§tab_id: String
§node1_id: String
§node2_id: String
§correlation_id: String
§

LayoutResizeNodes

Apply N resize operations atomically. Rejected entirely if any size is out of range (reducer validates; early-return on first invalid op, matching the frontend’s existing semantic).

Fields

§tab_id: String
§correlation_id: String
§

LayoutReplaceNode

Replace a node with a new one, preserving the target’s flex size.

Fields

§tab_id: String
§target_id: String
§new_node: LayoutNode
§focus_after: bool
§correlation_id: String
§

LayoutSplitHorizontal

Horizontal split: inserts new_node before/after target_id in a Row parent (or wraps them in a new Row group if parent is not Row).

Fields

§tab_id: String
§target_id: String
§new_node: LayoutNode
§position: SplitPosition
§focus_after: bool
§correlation_id: String
§

LayoutSplitVertical

Vertical split: inserts new_node before/after target_id in a Column parent (or wraps them in a new Column group).

Fields

§tab_id: String
§target_id: String
§new_node: LayoutNode
§position: SplitPosition
§focus_after: bool
§correlation_id: String
§

LayoutClear

Wipe the entire tree (sets rootnode = None, clears focus/magnify).

Fields

§tab_id: String
§correlation_id: String
§

LayoutSetTree

Bulk-replace the tree. Used during Phase 7a writer migration and for tear-off where the whole subtree changes atomically.

Fields

§tab_id: String
§new_tree: Option<LayoutNode>
§correlation_id: String
§

GetEvents

Phase D.3 — request an Event::EventList reply containing the events the launcher has emitted with version > since. Used by subscribers that hold a snapshot at version V and want to catch up to the live stream by replaying missed events.

Typical resync flow:

  1. RegisterRegistered { version: V0 }
  2. GetSnapshotSnapshot { version: V1 } (V1 > V0) — apply the snapshot
  3. GetEvents { since: V1 }EventList { events, version: V2 } — apply replay events to catch up to V2
  4. live broadcast events flow with version > V2

Replay is best-effort: the launcher’s in-memory ring is bounded; if since is older than the oldest retained event, the reply still contains all retained events but the subscriber may have missed some. Caller should treat the result as “everything I have for you” and re-fetch a snapshot if state inconsistency is detected.

Fields

§since: u64

Exclusive lower bound — events with version > since are returned, in ascending order.

§

ReportPoolWindowPromoted

Phase F.5 — host explicitly reports that a pool window was promoted to a user-visible top-level window (the promote_pool_window flow in agentmux-cef). Sent BETWEEN the ReportPoolWindowRemoved + ReportWindowOpened pair so the launcher reducer has unambiguous evidence the transition was a promote (vs a destroy followed by an unrelated open) and can emit Event::PoolWindowPromoted. The pool-respawn saga consumes the event to bracket the implicit refill in SagaStarted/SagaCompleted.

Host-only — same gate as ReportPoolWindowRemoved.

Fields

§label: String
§

SpawnPoolWindow

Phase F.5 — launcher-side saga coordinator asks the host to spawn a fresh pool window (refill after promote).

Status: live. Cross-process dispatch (CPD-1 through CPD-5) shipped; the saga coordinator’s apply_action for PipeTarget::Host writes this command through host_pipe (agentmux-launcher/src/host_pipe/) and waits on the Event::PoolWindowAdded { saga_id: Some(N) } echo. Host’s implicit spawn_pool_window call inside promote_pool_window remains the organic refill path for non-saga-driven promotions (with saga_id: None).

saga_id: every host-bound command carries the originating saga’s id so the host can echo it on the corresponding Report* reply. 0 is reserved as “no saga” and treated as a non-saga dispatch. #[serde(default)] retained for forward-compat with any pre-CPD-1 deserializers (no real-world consumer today; portable runtime is bundled per release).

Fields

§saga_id: u64
§

ReportPanesReaped

Phase F.6 — host reports that all browser-pane HWNDs belonging to a closing top-level window have been reaped. Emitted from client.rs::on_before_close after the subwindow cascade and pane lifecycle drain finish for the closing window.

Distinct from ReportWindowClosed — that event marks the CEF browser leaving the host’s browsers map; this one marks the host’s pane bookkeeping (lifecycle entries, pane HWND map) for that label being fully drained. Today both happen in the same on_before_close body so the events arrive back-to-back, but the saga distinguishes them so future fine-grained reapers (e.g. async pane teardown for embedded browsers) can land without rewriting the saga.

Host-only — same gate as ReportWindowClosed.

Fields

§label: String
§saga_id: Option<u64>

Phase CPD-1 — saga correlation echo. Some(N) when the host is replying to a saga-issued Command::ReapPanes { saga_id: N }; None for organic reports (e.g. host’s existing implicit pane drain inside on_before_close that wasn’t saga-driven).

#[serde(default)] for forward-compat with pre-CPD-1 hosts.

§

ReportPoolDrainDecision

Phase F.6 — host reports the result of the post-close drain-pool-if-last decision. was_last == true when the closing window was the last user-visible window and the host just kicked off the warm-pool drain (Stage 1 of the two-stage close cascade in client.rs::on_before_close); false when other user-visible windows remain and the pool stays warm.

The launcher’s window-cleanup-cascade saga uses this to close out its bracket regardless of which branch fires (both are terminal for the saga).

Host-only.

Fields

§label: String
§was_last: bool
§saga_id: Option<u64>

Phase CPD-1 — saga correlation echo. Some(N) when the host is replying to a saga-issued Command::DrainPoolIfLast { saga_id: N }; None for organic reports.

#[serde(default)] for forward-compat with pre-CPD-1 hosts.

§

ReapPanes

Phase F.6 — launcher-side saga coordinator asks the host to reap all browser-pane HWNDs for a window that just closed.

Status: live. Wired through host_pipe post-CPD-3. The saga issues this with target = PipeTarget::Host; the coordinator’s apply_action writes it through the host pipe and waits for the Event::PanesReaped { saga_id: Some(N) } echo. Host’s organic pane drain inside on_before_close still emits the same Report with saga_id: None for non-saga-driven closes.

saga_id: mandatory on the wire (host echoes back on ReportPanesReaped). #[serde(default)] retained for forward-compat (see SpawnPoolWindow for rationale).

Fields

§label: String
§saga_id: u64
§

DrainPoolIfLast

Phase F.6 — launcher-side saga coordinator asks the host to drain the warm pool if the just-closed window was the last user-visible window (i.e. trigger Stage 1 of the close cascade).

Status: live (same shipping path as ReapPanes). Wired through host_pipe post-CPD-3; saga waits on Event::PoolDrained { saga_id: Some(N) } / Event::PoolNotLast { saga_id: Some(N) } echo. Host’s on_before_close still runs the equivalent inline check organically (with saga_id: None).

saga_id: mandatory on the wire. #[serde(default)] retained for forward-compat.

Fields

§label: String
§saga_id: u64
§

ReportSagaActionFailed

Phase CPD-1 — host-emitted report that a saga-issued action failed (e.g. window not found, IPC error). Carries the originating saga_id and a human-readable reason. The launcher reducer translates this into Event::SagaActionFailed so the saga coordinator can terminate the matching saga as SagaFailed.

Schema-only in CPD-1: hosts don’t yet read commands from the pipe (CPD-2 wires that), so no producer for this command exists yet. The shape is added now so launcher reducer arms

  • saga coordinator wiring can soak before CPD-3 makes the dispatch live.

Fields

§saga_id: u64
§reason: String

Trait Implementations§

Source§

impl Clone for Command

Source§

fn clone(&self) -> Command

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Command

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<'de> Deserialize<'de> for Command

Source§

fn deserialize<__D>(__deserializer: __D) -> Result<Self, __D::Error>
where __D: Deserializer<'de>,

Deserialize this value from the given Serde deserializer. Read more
Source§

impl Serialize for Command

Source§

fn serialize<__S>(&self, __serializer: __S) -> Result<__S::Ok, __S::Error>
where __S: Serializer,

Serialize this value into the given Serde serializer. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

§

impl<T> Instrument for T

§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided [Span], returning an Instrumented wrapper. Read more
§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
§

impl<T> WithSubscriber for T

§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a [WithDispatch] wrapper. Read more
§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a [WithDispatch] wrapper. Read more
Source§

impl<T> DeserializeOwned for T
where T: for<'de> Deserialize<'de>,