Skip to content

Fleet Studio wiring — W1b: retire the single attachment pointer, feed the owner-map from the projection #1449

Closed as not planned

Description

@jeonghun-jj-lee

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 calls buildFleetProjection on an interval and ownerMap.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_UNREACHABLE 503 (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_smoke stays 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).

Source

Part of #1436. Blocked by W1a (#1448) and W2 (#1447).

Activity

  1. added 3 commits that reference this issue on Sep 23, 2026
  2. jeonghun-jj-lee commented on Sep 23, 2026

    @jeonghun-jj-lee
    ContributorAuthor

    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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    afkImplementable without human interaction

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions