Repository navigation
Fleet Studio wiring — W1b: retire the single attachment pointer, feed the owner-map from the projection #1449
Description
Important
Problem — Dispatch still uses the window-wide single attachment pointer (one peer live at a time). The multiplexer's per-session routing needs the SessionOwnerMap populated — but SessionOwnerMap.update() has no caller and no client sets the X-Amicode-Owner header, so owner-routing has no live input today.
Approach — Feed the owner-map from the N-peer projection's owner tags (W2), switch the ATTACHED arm of dispatch to per-session owner routing (the flag-ON path from W1a), and retire the single attachment pointer. Do NOT treat resolveTarget's bare undefined as authoritative for owned sessions: resolve the owner via the owner-map; if the owner is a known peer whose transport is currently unreachable, emit the named FLEET_PEER_UNREACHABLE 503 (the server.ts:451-455 shape) — never local. Only a keyless / unowned / owner-is-local request resolves local (using W1a's unreachable ResolvedTarget variant to keep the two distinct).
Scope — in: the owner-map feed loop; per-session owner routing for non-SSE /amicode + engine requests on the ATTACHED arm; retiring the single pointer on BOTH the request path (server.ts:399-405) and the upgrade path (server.ts:525-537). out: the SSE fan-out (W1c); path-less file.* owner routing via X-Amicode-Owner (no client sets it yet — see Constraints); the keeper / /amicode/fleet/* arms (preserved).
Assumptions — W1a (#1448) has inserted the flagged resolveTarget + the unreachable variant; W2 (#1447) populates the owner tags feeding the map.
Acceptance Criteria
-
SessionOwnerMap.update()is fed by a live loop (not a test stub): a timer callsbuildFleetProjectionon an interval andownerMap.update(projection.sessions)(routing must NOT depend on the sidebar being polled). Test: as the projection reports session→owner, the owner-map reflects it. - Two SESSION-PATHED requests owned by different reachable peers route to their respective owners; an owned-but-UNREACHABLE session yields
FLEET_PEER_UNREACHABLE503 (never local); a keyless/unowned request resolves local. Test: owner-A + owner-B route distinctly; unreachable-owned → 503; keyless → local. - The single global attachment pointer is removed from the attached arm on BOTH the request and upgrade paths; the keeper (
/amicode/roster) +/amicode/fleet/*-local arms are preserved; non-fleet still resolves local. Structural guard +single_attach_nonfleet_smokestays green.
Testing Decisions
Extend the session-relay integration suite; assert per-verb routing, the 503-not-local degrade, and the attached-arm-only retirement. Honesty: cross-machine routing is proven against stubbed peers, not a real fleet.
Key Decisions
Per-session owner routing replaces the pointer's ATTACHED arm (ADR 0031 §D1); owned-but-unreachable → named 503, never a silent local fallback (the #1382 invariant, server.ts:439-441) — enabled by W1a's unreachable ResolvedTarget variant; keyless ⇒ local. The projection is pull-only (built per-request at index.ts:483), so the owner-map is fed by an interval timer, not a subscription.
Constraints & Invariants
SSE stays out (W1c); the local path is unchanged; the honesty surface never proxies. Path-less engine file.* requests route by the X-Amicode-Owner header, which no client sets yet — that arm is out of scope here and stub-tested until a client (the Work Column bound session) sets it.
Prior Art
The multiplexer's SessionOwnerMap + owner arm of resolveTarget (session_multiplexer.ts:59-66,149-174); W1a's unreachable variant; the merged projection's owner overlay (W2); the single pointer on request + upgrade paths (server.ts:399-405,525-537); the FLEET_PEER_UNREACHABLE 503 shape (server.ts:451-455); the #1382 honesty invariant (server.ts:439-441).
Activity
Fleet Studio wiring W1a (#1448): insert session multiplexer into disp…
Fleet Studio wiring W1b (#1449): retire the single attachment pointer…
Fleet Studio wiring (#1436): connect dormant slices W0–W5 [WIP] (#1455)
jeonghun-jj-lee commentedon Sep 23, 2026
Closed as a partial Fleet Studio foundation: #1455 landed reusable pieces, but the remaining acceptance is superseded by #1482 under #1475. This is not a claim that the original end-to-end feature is complete.
feat(app): owner-header producer + pre-flight gate wiring (#1643, S3+S4)