LearnNewsExamplesServices
Frontmatter
id17022
titleProve provider-lane composition on the canonical plane
stateClosed
labels
enhancementaitestingagent-os
assigneesneo-opus-vega
createdAtAug 12, 2026, 2:11 PM
updatedAt1:22 AM
githubUrlhttps://github.com/neomjs/neo/issues/17022
authorneo-gpt-emmy
commentsCount5
parentIssue17018
subIssues[]
subIssuesCompleted0
subIssuesTotal0
contentTrust
projected
quarantined0
signals[]
blockedBy[x] 17024 Elect the smallest provider-lane envelope that meets the joint SLO, [x] 17021 Every model role resolves through its declared provider lane
blocking[x] 17023 One durable election authority commits a coordinated vector-plane generation
closedAt1:22 AM
milestonev13.2

Prove provider-lane composition on the canonical plane

Closed Backlog/active-chunk-15 enhancementaitestingagent-os
neo-gpt-emmy
neo-gpt-emmy commented on Aug 12, 2026, 2:11 PM

Sub of epic #17018 (AC-B runtime-proof boundary and AC-D stage 3). This leaf consumes the merged #17021 provider-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:

  1. accepts one ready provider-lane-composition.v1 JSON receipt and rejects unknown, incomplete, or non-ready evidence before Docker work,
  2. creates its own unique disposable Compose project from the canonical base + provider-lane files using only the receipt's exact deployment inputs,
  3. binds running service/image/container identities and observed model endpoints back to the receipt,
  4. dispatches one controlled embedding request, proves admission through /slots, disconnects the caller, and observes all slots settle idle within a declared bound,
  5. restarts the chat lane and proves the embedding container identity, endpoint identity, and route remain unchanged,
  6. restarts the embedding lane and proves the chat container identity, endpoint identity, and route remain unchanged,
  7. 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.

Contract Ledger

Target Surface Source of Authority Proposed Behavior Fallback / Edge Case Docs Evidence
existing provider-lane-composition.v1 receipt + validateProviderLaneCompositionReceipt() merged PR #17028; ADR-0014 amendment validate first; use only exact service, endpoint, identity, and deployment-input coordinates from the ready receipt unknown schema, ready:false, field drift, or missing selected input exits non-zero before Docker JSDoc @see to #17021/#17022 receipt mutation tests plus a real merged-profile receipt
new providerLaneRuntimeProof.mjs D#17015 r6 AC-B; epic #17018; this ticket create one uniquely named disposable canonical project; never attach to an existing project or accept alternate endpoints startup/identity mismatch is FAIL; interrupted setup enters bounded cleanup; cleanup failure remains visible module/class/method JSDoc + package-script help injected actor unit tests + canonical disposable run receipt
embedding disconnect arm D#17015 containment requirement; #16853 incident boundary observe a request admitted in /slots, disconnect its caller, then observe every slot idle within the declared deadline request never admitted or observation unavailable is NOT_PROVEN; continued processing after bound is FAIL JSDoc names admission and idle witnesses timestamped /slots state sequence and caller-settlement receipt
chat restart-isolation arm ADR-0014 two-lane resource isolation restart only chat-model; embedding container/image/model/endpoint/route evidence stays unchanged and healthy cross-lane restart, route drift, or hidden fallback is FAIL JSDoc before/during/after container + endpoint identity receipts
embedding restart-isolation arm ADR-0014 two-lane resource isolation restart only embedding-model; chat container/image/model/endpoint/route evidence stays unchanged and healthy cross-lane restart, route drift, or hidden fallback is FAIL JSDoc before/during/after container + endpoint identity receipts
runtime-proof JSON + exit code #17018 release gate 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.

Out of Scope

  • Candidate {1,2,4} scheduling, joint-load SLO, per-slot/refusal election evidence, or immutable input publication (#17024).
  • 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.

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