At origin/dev@2263a7e4f986d6e1c4bbeeb6b03b5e42cf0c4399, the reference deploy script treats an unset NEO_DEPLOY_COMPOSE_FILE as permission to select ai/deploy/docker-compose.yml. The base file configures KB and MC for Streamable HTTP but does not select an authentication installer; the local deployment overlay supplies the concrete auth profile.
The existing focused suite proves the current contract: an explicitly empty value fails, while an unset value succeeds with the base-only default. A live reproduction recorded on #16206 shows the expensive result: image build and container mutation happen before AuthService rejects the incomplete composition.
The semantic sweep found broad #16206 and closed #16458. This is not a duplicate of either: #16206 remains a multi-axis needs-re-triage umbrella, while #16458 delivered ordered multi-file support and deliberately preserved the unsafe unset fallback. This ticket isolates the one-PR residual without reopening a resolved ticket.
Live latest-open sweep: checked the newest 20 open issues plus recent A2A claims at 2026-08-08T10:22:00Z; no equivalent or competing claim found.
The Problem
Unset and explicitly empty inputs currently have inverted safety. Empty fails before Docker; unset silently chooses a composition known not to be a complete deployment profile. The reference path can therefore spend revision lookup, build time, and container mutation before failing at server boot.
The pipeline must not choose a security or provider profile. Its safe responsibility is narrower: require the caller to name the deployment composition it intends to operate.
The Architectural Reality
ai/examples/cloud-deployment/deploy-pipeline.sh:34-38 owns the implicit base-only fallback.
ai/deploy/docker-compose.yml:80-104,178-204 configures the HTTP services without selecting an auth mode.
ai/deploy/docker-compose.local-agent-os.yml:10-15 is one concrete auth-complete overlay.
ai/mcp/server/shared/services/AuthService.mjs:124-128 correctly fails closed when no installer exists.
test/playwright/unit/ai/DeployPipelineComposeFileList.spec.mjs:201-220 locks the unsafe unset behavior.
learn/agentos/cloud-deployment/PipelineWiring.md:151-170 already tells callers to discover and pass the real ordered file set.
No new file or ownership move is proposed; the existing pipeline, focused spec, and operator guide remain the owning surfaces.
The Fix
Make NEO_DEPLOY_COMPOSE_FILE mandatory for the reference pipeline.
Unset and values resolving to zero usable entries fail before revision resolution, network access, preflight, or Docker.
The diagnostic names the variable and directs the caller to provide the plane's ordered, auth-complete Compose file set.
Explicit single-file and ordered multi-file inputs retain their current argv and merge-order semantics.
Update the focused spec and Pipeline Wiring guide; remove language calling the implicit fallback compatible.
Contract Ledger
Target Surface
Source of Authority
Proposed Behavior
Fallback / Edge Case
Docs
Evidence
NEO_DEPLOY_COMPOSE_FILE in deploy-pipeline.sh
The plane's own Compose labels plus PipelineWiring.md
Caller supplies one explicit path or a colon-delimited ordered set
Unset, empty, or delimiter-only input exits non-zero before external work
Update PipelineWiring.md and script comments
Focused Playwright unit spec
Deploy transaction boundary
Existing fail-before-Docker guards in the script
Explicit one-file and multi-file invocations remain unchanged
Missing composition produces zero Docker/preflight calls and no revision lookup
Inline contract comment
Recording-stub order assertions
Decision Record impact
Aligned with ADR 0014 and ADR 0019. The deployment pipeline selects an explicit composition; it does not invent runtime configuration or authentication authority.
Acceptance Criteria
Unset, empty, and delimiter-only NEO_DEPLOY_COMPOSE_FILE values exit non-zero before revision resolution, network access, preflight, or Docker.
The error names NEO_DEPLOY_COMPOSE_FILE and the need for an ordered, auth-complete deployment composition.
Explicit single-path behavior and repeated -f ordering for multiple paths remain unchanged.
Project pinning, revision resolution, survivability preflight, up -d --build --wait, and the never-down guarantee remain unchanged for valid input.
Script comments and PipelineWiring.md no longer describe an implicit base-only fallback as compatible.
The focused DeployPipelineComposeFileList.spec.mjs suite is green, with the old unset-success expectation replaced by a fail-before-external-work witness.
Out of Scope
Selecting or changing an auth mode.
Changing AuthService.
Decomposing the base Compose file or adding auth fragments.
Reclassifying required inputs in #16511.
Running a real deployment.
Avoided Traps
Do not inject NEO_AUTH_MODE from the pipeline.
Do not reject an explicitly supplied single file; downstream deployments may provide a self-contained composition.
Do not validate completeness by starting or mutating containers.
Context
At
origin/dev@2263a7e4f986d6e1c4bbeeb6b03b5e42cf0c4399, the reference deploy script treats an unsetNEO_DEPLOY_COMPOSE_FILEas permission to selectai/deploy/docker-compose.yml. The base file configures KB and MC for Streamable HTTP but does not select an authentication installer; the local deployment overlay supplies the concrete auth profile.The existing focused suite proves the current contract: an explicitly empty value fails, while an unset value succeeds with the base-only default. A live reproduction recorded on
#16206shows the expensive result: image build and container mutation happen beforeAuthServicerejects the incomplete composition.The semantic sweep found broad
#16206and closed#16458. This is not a duplicate of either:#16206remains a multi-axis needs-re-triage umbrella, while#16458delivered ordered multi-file support and deliberately preserved the unsafe unset fallback. This ticket isolates the one-PR residual without reopening a resolved ticket.Live latest-open sweep: checked the newest 20 open issues plus recent A2A claims at 2026-08-08T10:22:00Z; no equivalent or competing claim found.
The Problem
Unset and explicitly empty inputs currently have inverted safety. Empty fails before Docker; unset silently chooses a composition known not to be a complete deployment profile. The reference path can therefore spend revision lookup, build time, and container mutation before failing at server boot.
The pipeline must not choose a security or provider profile. Its safe responsibility is narrower: require the caller to name the deployment composition it intends to operate.
The Architectural Reality
ai/examples/cloud-deployment/deploy-pipeline.sh:34-38owns the implicit base-only fallback.ai/deploy/docker-compose.yml:80-104,178-204configures the HTTP services without selecting an auth mode.ai/deploy/docker-compose.local-agent-os.yml:10-15is one concrete auth-complete overlay.ai/mcp/server/shared/services/AuthService.mjs:124-128correctly fails closed when no installer exists.test/playwright/unit/ai/DeployPipelineComposeFileList.spec.mjs:201-220locks the unsafe unset behavior.learn/agentos/cloud-deployment/PipelineWiring.md:151-170already tells callers to discover and pass the real ordered file set.No new file or ownership move is proposed; the existing pipeline, focused spec, and operator guide remain the owning surfaces.
The Fix
Make
NEO_DEPLOY_COMPOSE_FILEmandatory for the reference pipeline.Contract Ledger
NEO_DEPLOY_COMPOSE_FILEindeploy-pipeline.shPipelineWiring.mdPipelineWiring.mdand script commentsDecision Record impact
Aligned with ADR 0014 and ADR 0019. The deployment pipeline selects an explicit composition; it does not invent runtime configuration or authentication authority.
Acceptance Criteria
NEO_DEPLOY_COMPOSE_FILEvalues exit non-zero before revision resolution, network access, preflight, or Docker.NEO_DEPLOY_COMPOSE_FILEand the need for an ordered, auth-complete deployment composition.-fordering for multiple paths remain unchanged.up -d --build --wait, and the never-downguarantee remain unchanged for valid input.PipelineWiring.mdno longer describe an implicit base-only fallback as compatible.DeployPipelineComposeFileList.spec.mjssuite is green, with the old unset-success expectation replaced by a fail-before-external-work witness.Out of Scope
AuthService.#16511.Avoided Traps
NEO_AUTH_MODEfrom the pipeline.Related
#16206 · #16458 · #16511 · PR #16456
Retrieval Hint: "deploy pipeline unset compose file auth-incomplete base composition"