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:
- Exposes
readActivitySnapshot(params) per the FleetControlBridge.mjs:87 contract.
- Invokes both required readers with one normalized finite bound and caps the merged result.
- Contains synchronous and asynchronous reader failures as honest per-slot degradation.
- Redacts, flattens, and caps operator-visible failure reasons.
- Preserves readable events when the other contributor is blind.
- 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
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
Context
Leaf of epic #13015 (Fleet Manager MVP). Surfaced while driving #15293/#15331 and independently re-verified before filing.
FleetControlBridgeconsumes anactivitySourcewhose documentedreadActivitySnapshot(params)contract had no producer. The A2A and PR-lane adapters already existed, but the composer implied by their sharedsource: '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:87documented a source exposingreadActivitySnapshot(params)and returning bounded{capability, events}.ai/services/fleet/FleetControlBridge.mjs:355consumed that method.fleetA2AActivityAdapter.mjsandfleetPrLaneActivityAdapter.mjsproduced 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
FleetControlBridgeis dependency-injected and authors no admission fact. The composer is a source it consumes, not a capability the bridge invents.wiredrequires every contributor to read,degradedpreserves partial sight, andnot-wiredis reserved for nothing readable.capability.source.The Fix
Add one bounded
createFleetActivityReadSource({readA2ASnapshot, readPrLaneSnapshot})producer which:readActivitySnapshot(params)per theFleetControlBridge.mjs:87contract.Contract Ledger
readActivitySnapshot(params)producerFleetControlBridge.mjs:87,355{capability, events}shapewiredon unanimity;degradedon partial sight;not-wiredonly when neither readsAcceptance Criteria
readActivitySnapshothas exactly one producer satisfying theFleetControlBridge.mjs:87contract; the consumer reaches it unchanged through an unstubbed real-bridge → real-composer test.events: []under a wired capability.devFleetServer.Explicitly rejected: a stub source
A stub
activitySourceindevFleetServeris 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
devFleetServer, binding production readers, and obtaining livefleetActivity/ cockpit receipts: #15339.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 producerOrigin Session ID:
ad475320-6bdc-4555-ba3f-b78d51de0b17— Euclid (@neo-gpt) · OpenAI GPT-5.6 Sol Ultra