Context
Operator-spotted on 2026-08-07 while PR #16643 was in flight in the same file (the PR deliberately did not fold this in — different concern, frozen scope). ai/services/fleet/devFleetServer.mjs re-derives configuration from raw process.env while the Tier-1 fleet subtree (ai/configBase.mjs:272) is the declared home for fleet config — the exact read-then-re-implement class ADR-0019 exists to end, in a file that otherwise consumes injected read paths cleanly.
The Problem
Three env reads, two of them plainly A1-class:
devFleetServer.mjs:71 — const port = Number(process.env.NEO_FLEET_PORT) || 8083; — module-scope capture with a hidden inline default. Doubly wrong per ADR-0019: an A1 re-derivation, frozen at import time rather than resolved at the use site. No fleet.port leaf exists, so the value has no declared home at all.
devFleetServer.mjs:80 — process.env.NEO_FLEET_COCKPIT_ORIGIN || 'http://localhost:8080,...' — A1 with an inline default list; a CSV-typed leaf owns exactly this shape (leaf(default, env, 'csv')).
devFleetServer.mjs:79 + :324 — process.env.NEO_FLEET_BEARER — needs a classification decision, not a blind leaf: the bearer is secret-class, and the ADR-0019 §10.8 census keeps secrets as deployment inputs whose values never become config policy. Env-direct may be the sanctioned shape here; if so, the read deserves the explicit secret-classification comment so the next reader (and the next linter) can tell sanctioned from sloppy.
The Architectural Reality
ai/configBase.mjs:272 — the fleet subtree already declares instanceRoot, planeBase, planeBearer, tenantProbeTimeoutMs, harness binaries — the port and cockpit origins are conspicuously absent siblings.
ai/services/fleet/devFleetServer.mjs — the boot entrypoint; it is an ENTRYPOINT, so importing AiConfig and reading leaves at the use site is exactly the sanctioned C1-side shape (ADR-0019 §5.5).
- Note
planeBearer already exists as a leaf while NEO_FLEET_BEARER (the transport bearer, a different credential) is env-only — whatever the disposition, the two must not be conflated.
The Fix
- Declare
fleet.port (leaf(8083, 'NEO_FLEET_PORT', 'number')) and fleet.cockpitOrigins (leaf(['http://localhost:8080', 'http://127.0.0.1:8080'], 'NEO_FLEET_COCKPIT_ORIGIN', 'csv')) in the fleet subtree.
- Read both at the use site inside
boot() — the module-scope port constant dies (resolve-at-boot, not at import).
- Decide the bearer: either an explicit secret-classification comment on the env-direct read (sanctioned-secret shape), or a leaf if the census discipline prefers declared-secret-binding — follow
ai/scripts/lint/config-leaf-parity.json's existing secret rows as precedent.
- Pin-grep
test/ for NEO_FLEET_PORT / 8083 / cockpit-origin literals before push.
Acceptance Criteria
Out of Scope
- Any behavior change to the transport, auth, or origin semantics — this is a declaration-home move only.
resolveFleetBearer's internals.
Related
- ADR-0019 (the A1 class + §5.5 entrypoint shape + §10.8 secret census) · PR #16643 (adjacent lane in the same file, deliberately not folded) · #14560 (FM lane map).
Live latest-open sweep: checked latest 20 open issues at 2026-08-07T15:44Z; no equivalent found. A2A in-flight sweep: mailbox drained continuously this session; no competing claim.
Origin Session ID: 46db6bad-18a4-4064-8bf3-a140cc9a6243
Retrieval Hint: query_raw_memories("devFleetServer env re-derivation fleet leaves A1") · devFleetServer.mjs:71
Authored by Clio (Claude Fable 5, Claude Code). UNCLAIMED — a clean bounded lane for any peer; operator-spotted instance.
Context
Operator-spotted on 2026-08-07 while PR #16643 was in flight in the same file (the PR deliberately did not fold this in — different concern, frozen scope).
ai/services/fleet/devFleetServer.mjsre-derives configuration from rawprocess.envwhile the Tier-1fleetsubtree (ai/configBase.mjs:272) is the declared home for fleet config — the exact read-then-re-implement class ADR-0019 exists to end, in a file that otherwise consumes injected read paths cleanly.The Problem
Three env reads, two of them plainly A1-class:
devFleetServer.mjs:71—const port = Number(process.env.NEO_FLEET_PORT) || 8083;— module-scope capture with a hidden inline default. Doubly wrong per ADR-0019: an A1 re-derivation, frozen at import time rather than resolved at the use site. Nofleet.portleaf exists, so the value has no declared home at all.devFleetServer.mjs:80—process.env.NEO_FLEET_COCKPIT_ORIGIN || 'http://localhost:8080,...'— A1 with an inline default list; a CSV-typed leaf owns exactly this shape (leaf(default, env, 'csv')).devFleetServer.mjs:79+:324—process.env.NEO_FLEET_BEARER— needs a classification decision, not a blind leaf: the bearer is secret-class, and the ADR-0019 §10.8 census keeps secrets as deployment inputs whose values never become config policy. Env-direct may be the sanctioned shape here; if so, the read deserves the explicit secret-classification comment so the next reader (and the next linter) can tell sanctioned from sloppy.The Architectural Reality
ai/configBase.mjs:272— thefleetsubtree already declaresinstanceRoot,planeBase,planeBearer,tenantProbeTimeoutMs, harness binaries — the port and cockpit origins are conspicuously absent siblings.ai/services/fleet/devFleetServer.mjs— the boot entrypoint; it is an ENTRYPOINT, so importing AiConfig and reading leaves at the use site is exactly the sanctioned C1-side shape (ADR-0019 §5.5).planeBeareralready exists as a leaf whileNEO_FLEET_BEARER(the transport bearer, a different credential) is env-only — whatever the disposition, the two must not be conflated.The Fix
fleet.port(leaf(8083, 'NEO_FLEET_PORT', 'number')) andfleet.cockpitOrigins(leaf(['http://localhost:8080', 'http://127.0.0.1:8080'], 'NEO_FLEET_COCKPIT_ORIGIN', 'csv')) in thefleetsubtree.boot()— the module-scopeportconstant dies (resolve-at-boot, not at import).ai/scripts/lint/config-leaf-parity.json's existing secret rows as precedent.test/forNEO_FLEET_PORT/8083/ cockpit-origin literals before push.Acceptance Criteria
process.env.NEO_FLEET_*read remains indevFleetServer.mjsexcept a deliberately classified secret read (if that disposition wins), carrying its classification comment.fleet.portandfleet.cockpitOriginsleaves exist with the current defaults; the server resolves them at boot, not at module load.Out of Scope
resolveFleetBearer's internals.Related
Live latest-open sweep: checked latest 20 open issues at 2026-08-07T15:44Z; no equivalent found. A2A in-flight sweep: mailbox drained continuously this session; no competing claim.
Origin Session ID: 46db6bad-18a4-4064-8bf3-a140cc9a6243
Retrieval Hint:
query_raw_memories("devFleetServer env re-derivation fleet leaves A1")·devFleetServer.mjs:71Authored by Clio (Claude Fable 5, Claude Code). UNCLAIMED — a clean bounded lane for any peer; operator-spotted instance.