LearnNewsExamplesServices
Frontmatter
id15333
titleFleet activitySource composer: the producer for a slot consumed since it was written
stateOpen
labels
enhancementaiarchitecture
assigneesneo-opus-ada
createdAt2:39 AM
updatedAt4:53 AM
githubUrlhttps://github.com/neomjs/neo/issues/15333
authorneo-opus-ada
commentsCount2
parentIssuenull
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[]
blocking[]

Fleet activitySource composer: the producer for a slot consumed since it was written

Open Backlog/active-chunk-6 enhancementaiarchitecture
neo-opus-ada
neo-opus-ada commented on 2:39 AM

Context

Leaf of epic #13015 (Fleet Manager MVP). Surfaced while driving #15293/#15331 and independently re-verified before filing.

FleetControlBridge consumes an activitySource whose documented readActivitySnapshot(params) contract had no producer. The A2A and PR-lane adapters already existed, but the composer implied by their shared source: 'fleet:activity-adapters' capability did not.

This ticket owns that composer only. Production installation in devFleetServer, identity/read binding, and live server/cockpit receipts are the substantive successor #15339. That split corrects the ticket's original mixed scope: PR #15335 delivers the producer; it does not claim the wiring.

The Problem

At the filing baseline:

  • ai/services/fleet/FleetControlBridge.mjs:87 documented a source exposing readActivitySnapshot(params) and returning bounded {capability, events}.
  • ai/services/fleet/FleetControlBridge.mjs:355 consumed that method.
  • No module produced the source. fleetA2AActivityAdapter.mjs and fleetPrLaneActivityAdapter.mjs produced the two input truths, but nothing composed them.

Without a composer, callers could not distinguish a healthy quiet fleet from a feed that could not read one or both contributors. An empty event list is valid under a healthy capability; it must not stand in for blindness.

The Architectural Reality

  • FleetControlBridge is dependency-injected and authors no admission fact. The composer is a source it consumes, not a capability the bridge invents.
  • The two landed adapters are the truth producers. The composer bounds and merges them behind the bridge contract; it does not re-derive their facts.
  • Composite sight is pessimistic: wired requires every contributor to read, degraded preserves partial sight, and not-wired is reserved for nothing readable.
  • Contributor identity belongs to the composer-owned slot, not to a failing adapter's self-reported capability.source.
  • Reader functions remain injected and required. Missing readers fail at construction rather than silently producing a one-legged composite.

The Fix

Add one bounded createFleetActivityReadSource({readA2ASnapshot, readPrLaneSnapshot}) producer which:

  1. Exposes readActivitySnapshot(params) per the FleetControlBridge.mjs:87 contract.
  2. Invokes both required readers with one normalized finite bound and caps the merged result.
  3. Contains synchronous and asynchronous reader failures as honest per-slot degradation.
  4. Redacts, flattens, and caps operator-visible failure reasons.
  5. Preserves readable events when the other contributor is blind.
  6. Is exercised through an unstubbed real-bridge → real-composer seam test.

Contract Ledger

Target surface Source of authority Behavior owned here Fallback / failure Evidence
readActivitySnapshot(params) producer FleetControlBridge.mjs:87,355 Exactly one injected composer satisfies the consumed {capability, events} shape Missing reader throws at construction Focused composer specs + real bridge/composer seam
Composite capability Landed A2A + PR-lane adapter capabilities wired on unanimity; degraded on partial sight; not-wired only when neither reads Every blind contributor is named by composer-owned slot Quiet-wired, partial, total-blind, forged-source controls
Reader invocation Injected reader contract Sync and async failures are both contained Redacted, single-line, bounded reason Sync-throw, async-reject, credential, and length witnesses
Read/result bounds Bridge caller parameters Honest positive bounds pass through; malformed values fall back; oversized values clamp; merged events stay capped Invalid configured defaults are refused Malformed, huge, honest-bound, and result-cap witnesses
Production installation Successor #15339 Not owned by this ticket Bridge remains honestly unwired until #15339 lands Live server + cockpit receipts belong to #15339

Acceptance Criteria

  • readActivitySnapshot has exactly one producer satisfying the FleetControlBridge.mjs:87 contract; the consumer reaches it unchanged through an unstubbed real-bridge → real-composer test.
  • Both readers are injected and required; no singleton reader is smuggled into the composer.
  • A healthy composer with no events emits events: [] under a wired capability.
  • A contributor that cannot read degrades naming its composer-owned slot, while the readable half still reaches the cockpit payload.
  • Synchronous and asynchronous reader failures are contained; operator-visible reasons are redacted, single-line, and bounded.
  • Caller bounds are normalized and capped before fan-out and again at the merged result; an invalid configured fallback is refused.
  • No stub source is introduced in devFleetServer.

Explicitly rejected: a stub source

A stub activitySource in devFleetServer is not an acceptable shortcut. #15293 AC4 requires a real fleet server path; a fixture behind a real transport would only make the journey green while leaving its named producer unproven. #15339 inherits this rejection because it owns the live installation.

Out of Scope

  • Wiring the composer into devFleetServer, binding production readers, and obtaining live fleetActivity / cockpit receipts: #15339.
  • #15293's AC4 journey itself: #15339 unblocks it; neither this ticket nor the wiring leaf authors that e2e.
  • Fleet ingress authentication (#15320), the mailbox pane (#15316), or the banner taxonomy owned by #15284.
  • New activity adapters beyond composing the two that already exist.

Related

Epic #13015 · successor #15339 (production wiring) · #15293 (AC4 remains blocked on #15339) · #15331 · #14560 · #15284.

Retrieval Hint: fleet activitySource composer readActivitySnapshot bounded capability injected readers no producer

Origin Session ID: ad475320-6bdc-4555-ba3f-b78d51de0b17

— Euclid (@neo-gpt) · OpenAI GPT-5.6 Sol Ultra