Sub of epic #17018 (AC-B runtime-proof boundary and AC-D stage 3). This leaf consumes the merged #17021provider-lane-composition.v1 receipt after #17024 has elected and published every required resource input. It does not own the {1,2,4} election, candidate context/refusal probes, or joint-load SLO.
Context
Discussion #17015 r6 makes the D+F provider split conditional on Neo-owned canonical-plane proof. PR #17028 has now merged the static producer ai/scripts/diagnostics/providerLaneComposition.mjs: it validates rendered Compose, source consumers, endpoints, immutable identities, resources, and deployment inputs, then emits one stable receipt.
That static receipt is necessary but not sufficient. The remaining proof must bind the selected receipt to running disposable services, show that an admitted embedding request becomes idle after the caller disconnects, and show that restarting either lane leaves the other lane's identity and route intact.
Live duplicate/successor sweep (2026-08-12T15:30Z): no other issue owns this final-runtime composition/containment/restart proof. #17021 is delivered static authority. #17024 owns the candidate matrix, /api/ps + /slots candidate truth, over-limit refusals, joint load, and immutable input election. #17026 owns the cumulative release package.
The Problem
The merged analyzer can prove what Compose declares and what source consumers are wired to use. It cannot prove that the selected containers actually expose those identities, that the replacement embedding runtime releases admitted work after disconnect, or that one provider lane can restart without moving or recycling the other.
The original ticket prescribed providerLaneComposition.mjs for this runtime role. That name is now occupied by #17021's static analyzer and receipt validator. Reusing or widening it would collapse producer and runtime-consumer authority back into one module.
The Architectural Reality
This leaf is a runtime receipt consumer, never another configuration parser or election layer.
providerLaneComposition.mjs remains the sole rendered-Compose analyzer and receipt validator.
#17024 supplies the selected immutable resource inputs; the provider profile intentionally has no defaults.
The runtime proof imports only the stable validator/constants, starts a uniquely named disposable Compose project from Neo's canonical files, and derives its environment from the already-validated receipt.
It exposes no arbitrary host, endpoint, credential, existing-project, or external-plane option.
The combined proof is static role-map authority from #17021 plus observed final-runtime identity/containment/isolation from this leaf. This runner does not duplicate per-role source census or candidate benchmarking.
Structural pre-flight (2026-08-12): ai/scripts/diagnostics/providerLaneRuntimeProof.mjs matches the active, disposable one-shot actor pattern of captureParityLatencyPair.mjs in ai/scripts/diagnostics/. Both own a uniquely named Compose project, bounded child commands, machine receipts, and cleanup. ArchitectureOverview.md classifies ai/scripts/ as one-shot operator scripts; ADR-0014 requires provider runtimes to remain separate from the orchestrator control plane. Sibling-file-lift applies; no novel directory or map update is required. The full structure-map currently fails with V8's maximum-string error, so it is not used as placement authority.
The Fix
Add ai/scripts/diagnostics/providerLaneRuntimeProof.mjs, a bounded runtime consumer that:
accepts one ready provider-lane-composition.v1 JSON receipt and rejects unknown, incomplete, or non-ready evidence before Docker work,
creates its own unique disposable Compose project from the canonical base + provider-lane files using only the receipt's exact deployment inputs,
binds running service/image/container identities and observed model endpoints back to the receipt,
dispatches one controlled embedding request, proves admission through /slots, disconnects the caller, and observes all slots settle idle within a declared bound,
restarts the chat lane and proves the embedding container identity, endpoint identity, and route remain unchanged,
restarts the embedding lane and proves the chat container identity, endpoint identity, and route remain unchanged,
emits deterministic JSON with per-arm evidence and PASS, FAIL, or NOT_PROVEN, then removes only the project it created.
Reuse #17021's receipt validator and established disposable-Compose actor patterns. Do not create a provider client abstraction, parse Compose a second time, or import #17024's election core.
emit one deterministic secret-free receipt with exact source head, composition digest, arm states, cleanup state, and terminal verdict
any missing required evidence remains NOT_PROVEN or FAIL; never PASS-by-omission
receipt schema in JSDoc and PR body
schema/omission/mutation tests + published canonical receipt
Acceptance Criteria
providerLaneRuntimeProof.mjs imports only #17021's receipt validator/constants at the configuration boundary; it does not parse Compose, read provider env as authority, or import #17024's election core.
A non-ready, unknown-schema, incomplete, or non-selected receipt fails before any Docker mutation.
The runner creates a unique disposable project from Neo's canonical base + provider-lane files, applies exactly the receipt's deployment inputs, binds the exact source revision, and cleans up only that project.
Running chat and embedding container/image/model/endpoint identities match the selected receipt; the combined receipt binds #17021's exact four-role map to these observed lane identities.
The embedding arm proves admission via /slots, caller disconnect, caller settlement, and bounded transition to all-slots-idle. Missing admission/idle evidence is NOT_PROVEN, never PASS.
Restarting chat leaves the embedding container identity, model identity, endpoint, and route unchanged and healthy; no fallback is accepted.
Restarting embedding leaves the chat container identity, model identity, endpoint, and route unchanged and healthy; no fallback is accepted.
Unit mutations cover non-ready/forged receipts, external or existing-project input, admission never observed, post-disconnect work not settling, opposite-lane identity drift, hidden fallback, interrupted cleanup, and PASS-by-omission.
The CLI emits deterministic secret-free JSON and a concise stderr verdict; required failure or inconclusive evidence exits non-zero.
The production-shaped run is restricted to Neo's canonical/disposable plane. No external-plane endpoint, token, corpus, project name, or deployment mutation can be supplied.
Focused Neo unit coverage passes and git diff --check is clean.
The PR publishes the exact machine receipt without claiming #17024's election or #17023/#17025 vector-generation work complete.
Decision Record Impact
ADR successor-risk: adr-aligned — ticket #17022 (2026-08-12) follows the accepted 2026-08-12 ADR-0014 role-isolated provider amendment delivered by #17019/#17020. No new ADR or AiConfig leaf is required.
Static rendered-Compose/source consumer analysis or receipt schema authority (#17021/#17028).
KB/MC vector-generation identity, rebuild, promotion, or rollback (#17023/#17025).
Cumulative release packaging or external deployment (#17026).
Arbitrary benchmark framework or external-plane diagnostics.
Intake Record
Ticket age: created 2026-08-12T12:11:14Z; updated same day.
Bot stale-band: pre-stale under the repository's 90-day stale + 14-day close workflow; no stale or no auto close label.
Currency/successor risk: PR #17028 merged after filing and occupied the original filename/static authority; #17024 is the newer owner of elected inputs and candidate runtime truth. No merged PR closes or completes this final-runtime proof.
Historical prior art: Memory Core eb02ffd0-1df3-4860-942b-564c92eaa659 confirms the same-session consumer-graph gap and role split; no prior runtime-proof implementation surfaced.
Ticket reality: corrected from needs-relinking/overlap to valid-as-written only after the native #17022 blocked by #17024 edge is present.
ROI: positive after narrowing—one bounded disposable proof closes a release claim; duplicating the election or static analyzer would be negative ROI.
Sub of epic #17018 (AC-B runtime-proof boundary and AC-D stage 3). This leaf consumes the merged #17021
provider-lane-composition.v1receipt after #17024 has elected and published every required resource input. It does not own the{1,2,4}election, candidate context/refusal probes, or joint-load SLO.Context
Discussion #17015 r6 makes the D+F provider split conditional on Neo-owned canonical-plane proof. PR #17028 has now merged the static producer
ai/scripts/diagnostics/providerLaneComposition.mjs: it validates rendered Compose, source consumers, endpoints, immutable identities, resources, and deployment inputs, then emits one stable receipt.That static receipt is necessary but not sufficient. The remaining proof must bind the selected receipt to running disposable services, show that an admitted embedding request becomes idle after the caller disconnects, and show that restarting either lane leaves the other lane's identity and route intact.
Live duplicate/successor sweep (2026-08-12T15:30Z): no other issue owns this final-runtime composition/containment/restart proof. #17021 is delivered static authority. #17024 owns the candidate matrix,
/api/ps+/slotscandidate truth, over-limit refusals, joint load, and immutable input election. #17026 owns the cumulative release package.The Problem
The merged analyzer can prove what Compose declares and what source consumers are wired to use. It cannot prove that the selected containers actually expose those identities, that the replacement embedding runtime releases admitted work after disconnect, or that one provider lane can restart without moving or recycling the other.
The original ticket prescribed
providerLaneComposition.mjsfor this runtime role. That name is now occupied by #17021's static analyzer and receipt validator. Reusing or widening it would collapse producer and runtime-consumer authority back into one module.The Architectural Reality
This leaf is a runtime receipt consumer, never another configuration parser or election layer.
providerLaneComposition.mjsremains the sole rendered-Compose analyzer and receipt validator.Structural pre-flight (2026-08-12):
ai/scripts/diagnostics/providerLaneRuntimeProof.mjsmatches the active, disposable one-shot actor pattern ofcaptureParityLatencyPair.mjsinai/scripts/diagnostics/. Both own a uniquely named Compose project, bounded child commands, machine receipts, and cleanup.ArchitectureOverview.mdclassifiesai/scripts/as one-shot operator scripts; ADR-0014 requires provider runtimes to remain separate from the orchestrator control plane. Sibling-file-lift applies; no novel directory or map update is required. The full structure-map currently fails with V8's maximum-string error, so it is not used as placement authority.The Fix
Add
ai/scripts/diagnostics/providerLaneRuntimeProof.mjs, a bounded runtime consumer that:provider-lane-composition.v1JSON receipt and rejects unknown, incomplete, or non-ready evidence before Docker work,/slots, disconnects the caller, and observes all slots settle idle within a declared bound,PASS,FAIL, orNOT_PROVEN, then removes only the project it created.Reuse #17021's receipt validator and established disposable-Compose actor patterns. Do not create a provider client abstraction, parse Compose a second time, or import #17024's election core.
Contract Ledger
provider-lane-composition.v1receipt +validateProviderLaneCompositionReceipt()ready:false, field drift, or missing selected input exits non-zero before Docker@seeto #17021/#17022providerLaneRuntimeProof.mjsFAIL; interrupted setup enters bounded cleanup; cleanup failure remains visible/slots, disconnect its caller, then observe every slot idle within the declared deadlineNOT_PROVEN; continued processing after bound isFAIL/slotsstate sequence and caller-settlement receiptchat-model; embedding container/image/model/endpoint/route evidence stays unchanged and healthyFAILembedding-model; chat container/image/model/endpoint/route evidence stays unchanged and healthyFAILNOT_PROVENorFAIL; never PASS-by-omissionAcceptance Criteria
providerLaneRuntimeProof.mjsimports only #17021's receipt validator/constants at the configuration boundary; it does not parse Compose, read provider env as authority, or import #17024's election core./slots, caller disconnect, caller settlement, and bounded transition to all-slots-idle. Missing admission/idle evidence isNOT_PROVEN, never PASS.git diff --checkis clean.Decision Record Impact
ADR successor-risk:
adr-aligned— ticket #17022 (2026-08-12) follows the accepted 2026-08-12 ADR-0014 role-isolated provider amendment delivered by #17019/#17020. No new ADR or AiConfig leaf is required.Out of Scope
{1,2,4}scheduling, joint-load SLO, per-slot/refusal election evidence, or immutable input publication (#17024).Intake Record
2026-08-12T12:11:14Z; updated same day.pre-staleunder the repository's 90-day stale + 14-day close workflow; nostaleorno auto closelabel.eb02ffd0-1df3-4860-942b-564c92eaa659confirms the same-session consumer-graph gap and role split; no prior runtime-proof implementation surfaced.needs-relinking/overlap tovalid-as-writtenonly after the native#17022 blocked by #17024edge is present.Related
Parent #17018 · blocked by #17024 (which consumes merged #17021) · source Discussion #17015 r6 · incident evidence #16706/#16853
Origin Session ID: 35e0863b-4d45-4b94-90ff-5e66278bea7d
Retrieval hints:
D#17015 provider lane runtime proof disconnect slots idle restart isolation selected receipt