Context
Surfaced while running a reviewer falsifier on PR #15318 (native Fleet drill witnesses). Not that PR's defect — #15212 explicitly forbids touching production, so the author took the only option available. The friction is in production and it constrains every Fleet E2E witness.
The Problem
installFleetBridge() hardcodes its endpoint with no runtime override, and the app calls it with no arguments:
installFleetBridge();
export function installFleetBridge({url = 'http://127.0.0.1:8083/fleet', fetchImpl = globalThis.fetch, target = globalThis} = {}) {The opts.url seam exists but nothing reaches it — no env read, no config leaf, no call-site argument. So any E2E witness needing a test-owned Fleet bridge must squat the exact port the app dials, which is also devFleetServer's default:
const port = Number(process.env.NEO_FLEET_PORT) || 8083;
FleetGridKeyboardA11y.spec.mjs therefore hardcodes startFleetBridgeServer({port: 8083}).
The sharpest tell: fleetBridgeServer.mjs:19 advertises an affordance no consumer can use —
@param {Number} [opts.port=8083] — 0 selects an ephemeral port (tests).
The module offers ephemeral-port binding for tests, and the test cannot use it, because the dial target is fixed at the consumer.
Consequences (verified, not assumed):
- No false-green risk.
playwright.config.e2e.mjs sets workers: 1, fullyParallel: false, so no intra-run collision; an occupied port throws EADDRINUSE in beforeEach — fail-loud.
- But the witness cannot run in a standard dev environment. Anyone with
devFleetServer up (the normal setup) gets an opaque bind error — precisely when they most want to run the Fleet witnesses.
devFleetServer honors NEO_FLEET_PORT, so the server side is already configurable. The client side is not. The asymmetry is the bug: one half of the transport reads an env var, the other half ignores it.
The Architectural Reality
src/ai/fleet/installFleetBridge.mjs:21 — url default, injectable in signature, never injected.
apps/agentos/app.mjs:7 — the only production call site, zero args.
ai/services/fleet/devFleetServer.mjs:32 — server honors NEO_FLEET_PORT, defaults 8083.
ai/services/fleet/fleetBridgeServer.mjs:19,25 — documents port: 0 as the test affordance.
test/playwright/e2e/agentos/FleetGridKeyboardA11y.spec.mjs — forced to port: 8083.
This is App-Worker code (src/), so the endpoint cannot simply read process.env; the resolution has to reach the worker through whatever the established seam is (build-time config, Neo.config, or an explicit call-site argument from app.mjs). That choice is the substance of this ticket and should not be guessed — ADR-0019's require+inject+fail-loud discipline is the nearest governing precedent, and a hidden default is exactly what it forbids.
The Fix
Give the client half a real resolution path so a test can point the app at its own loopback:
- Resolve the fleet endpoint at the
app.mjs call site rather than defaulting inside installFleetBridge, so the default is visible at one place instead of buried in a parameter.
- Let an E2E harness override it (ephemeral port → app dials it), making
fleetBridgeServer's documented port: 0 reachable.
- Then drop the hardcoded
8083 in FleetGridKeyboardA11y.spec.mjs.
Explicitly not proposed: a defensive ?. or a second hidden default. If the endpoint cannot be resolved, fail loud.
Acceptance Criteria
Out of Scope
- The witnesses themselves (PR #15318 — approved, merge-eligible).
- Fleet lifecycle/product semantics.
- Hosted-CI E2E coverage (the separate and larger question #15212 surfaced: these witnesses are not hosted-CI gated at all).
Avoided Traps
- Blaming PR #15318. The hardcode is forced by production; the author had no legal alternative under AC-4.
- Reading
process.env inside src/. App-Worker code cannot; the seam must be a real injection, not an env peek.
- Adding a second default to paper over the first. The defect IS the unreachable default.
Related
- PR #15318 / #15212 — where this surfaced (reviewer falsifier).
- #14619 / PR #15094 — the native-button convergence these witnesses guard.
Live latest-open sweep: latest open issues checked 2026-07-16 ~23:30Z; searched installFleetBridge port 8083 and fleet bridge ephemeral port test across open+closed — no equivalent found.
Retrieval Hint: installFleetBridge hardcoded 8083 endpoint no override fleet E2E squat devFleetServer ephemeral port
Origin Session ID: ad475320-6bdc-4555-ba3f-b78d51de0b17
Context
Surfaced while running a reviewer falsifier on PR #15318 (native Fleet drill witnesses). Not that PR's defect — #15212 explicitly forbids touching production, so the author took the only option available. The friction is in production and it constrains every Fleet E2E witness.
The Problem
installFleetBridge()hardcodes its endpoint with no runtime override, and the app calls it with no arguments:// apps/agentos/app.mjs:7 installFleetBridge(); // src/ai/fleet/installFleetBridge.mjs:21 export function installFleetBridge({url = 'http://127.0.0.1:8083/fleet', fetchImpl = globalThis.fetch, target = globalThis} = {}) {The
opts.urlseam exists but nothing reaches it — no env read, no config leaf, no call-site argument. So any E2E witness needing a test-owned Fleet bridge must squat the exact port the app dials, which is alsodevFleetServer's default:// ai/services/fleet/devFleetServer.mjs:32 const port = Number(process.env.NEO_FLEET_PORT) || 8083;FleetGridKeyboardA11y.spec.mjstherefore hardcodesstartFleetBridgeServer({port: 8083}).The sharpest tell:
fleetBridgeServer.mjs:19advertises an affordance no consumer can use —The module offers ephemeral-port binding for tests, and the test cannot use it, because the dial target is fixed at the consumer.
Consequences (verified, not assumed):
playwright.config.e2e.mjssetsworkers: 1, fullyParallel: false, so no intra-run collision; an occupied port throwsEADDRINUSEinbeforeEach— fail-loud.devFleetServerup (the normal setup) gets an opaque bind error — precisely when they most want to run the Fleet witnesses.devFleetServerhonorsNEO_FLEET_PORT, so the server side is already configurable. The client side is not. The asymmetry is the bug: one half of the transport reads an env var, the other half ignores it.The Architectural Reality
src/ai/fleet/installFleetBridge.mjs:21—urldefault, injectable in signature, never injected.apps/agentos/app.mjs:7— the only production call site, zero args.ai/services/fleet/devFleetServer.mjs:32— server honorsNEO_FLEET_PORT, defaults 8083.ai/services/fleet/fleetBridgeServer.mjs:19,25— documentsport: 0as the test affordance.test/playwright/e2e/agentos/FleetGridKeyboardA11y.spec.mjs— forced toport: 8083.This is App-Worker code (
src/), so the endpoint cannot simply readprocess.env; the resolution has to reach the worker through whatever the established seam is (build-time config,Neo.config, or an explicit call-site argument fromapp.mjs). That choice is the substance of this ticket and should not be guessed — ADR-0019's require+inject+fail-loud discipline is the nearest governing precedent, and a hidden default is exactly what it forbids.The Fix
Give the client half a real resolution path so a test can point the app at its own loopback:
app.mjscall site rather than defaulting insideinstallFleetBridge, so the default is visible at one place instead of buried in a parameter.fleetBridgeServer's documentedport: 0reachable.8083inFleetGridKeyboardA11y.spec.mjs.Explicitly not proposed: a defensive
?.or a second hidden default. If the endpoint cannot be resolved, fail loud.Acceptance Criteria
devFleetServeroccupying 8083 and seeing it pass.FleetGridKeyboardA11y.spec.mjsno longer hardcodes8083.installFleetBridge's JSDoc stops advertising anopts.urlseam that no call site exercises, or the seam becomes genuinely exercised.Out of Scope
Avoided Traps
process.envinsidesrc/. App-Worker code cannot; the seam must be a real injection, not an env peek.Related
Live latest-open sweep: latest open issues checked 2026-07-16 ~23:30Z; searched
installFleetBridge port 8083andfleet bridge ephemeral port testacross open+closed — no equivalent found.Retrieval Hint:
installFleetBridge hardcoded 8083 endpoint no override fleet E2E squat devFleetServer ephemeral portOrigin Session ID:
ad475320-6bdc-4555-ba3f-b78d51de0b17