Neo's resolved embedding safe-processing band is AiConfig.localModels.embedding.safeProcessingLimitTokens (default 28,672 tokens). The canonical llama.cpp lane allocates 32,768 tokens per slot, while LM Studio exposes the resident model's loaded context through strict lms ps metadata.
Source correction
The original ticket premise treated a client-supplied truncate: false field or per-request /slots polling as the missing safety witness. The pinned llama.cpp source establishes a different contract:
A live canonical-profile receipt proved that /slots can starve during full embedding grind and must not be treated as an always-available per-request authority (#17024 receipt, Arm 3 and prescription 4).
The safe design therefore binds the resolved band at composition/readiness, classifies exact transport evidence, and leaves live provider-shape verification to its existing boot-time owner rather than adding a recurring request-path probe.
Problem
Four authority gaps remain:
Provider-lane composition and election compare an envelope with itself but do not carry the resolved environment-backed safe band as a versioned deployment input.
The production LM Studio postSpawn path verifies residency but does not apply the embedding safe-band floor to its already-fetched strict metadata.
LM Studio request preflight collapses a lane/configuration mismatch and a current input whose estimate exceeds trusted resident context into one untyped error, although they have different retry semantics.
The pinned llama.cpp structured overflow refusal reaches Knowledge Base ingestion as an unclassified HTTP error.
Without those distinctions, deployment drift can pass static validation, readiness can report green for an undersized LM Studio resident, and durable tenant-sync state cannot tell a repairable context mismatch from a current input that the provider positively refused as too large.
Intended Solution
Make localModels.embedding.safeProcessingLimitTokens a positive-integer config leaf.
Add the resolved band to provider-lane composition receipts and candidate deployment inputs; bump composition, election-plan, and election-report schemas to v2. The executable entrypoint reads AiConfig; pure analyzers receive the value by injection.
Make LM Studio postSpawn run metadata-only embedding readiness from the strict resident rows already fetched by ensureLmsModelsLoaded. This path performs no embedding inference or tokenizer/model-file work.
Split LM Studio request failures:
resident context below the configured requirement or safe band becomes EMBEDDING_CONTEXT_INSUFFICIENT, mapped to KB_VECTOR_EMBED_CONTEXT_INSUFFICIENT with deferrable disposition;
a current input estimate above the trusted resident context becomes EMBEDDING_INPUT_TRUNCATED, mapped to KB_VECTOR_EMBED_INPUT_TRUNCATED with rejected disposition.
when both conditions are visible, resident-policy insufficiency wins until the resident is repaired; only a policy-compliant resident can authorize the estimate-based permanent-input classification.
Translate only the pinned llama.cpp structured HTTP 400 exceed_context_size_error receipt, with valid positive n_prompt_tokens and n_ctx, into EMBEDDING_INPUT_TRUNCATED. Do not infer permanence from response prose.
Preserve the legacy request body for generic OpenAI-compatible endpoints. Do not send truncate, add a strict-slot capability leaf, or poll /slots per embedding request.
Acceptance Criteria
Invalid embedding safe-band environment values cannot become an invalid resolved leaf; the default remains 28,672.
Composition fails when the declared per-slot context is below the resolved safe band and names both numbers. A non-default safe-band environment value is proven through the real CLI entrypoint.
Provider-lane composition receipts, election plans, and election reports use v2 schemas and carry the safe band as one canonical deployment input. All candidates must share the same value, and application environment drift is rejected.
The production ConfiguredTaskDefinitionsService -> lms.postSpawn -> ensureLmsModelsLoaded path applies metadata-only embedding readiness when LM Studio owns the embedding role. A known undersized resident is not ready, and zero embedding canaries are issued.
LM Studio context-policy insufficiency throws EMBEDDING_CONTEXT_INSUFFICIENT before POST and reaches Knowledge Base classification as KB_VECTOR_EMBED_CONTEXT_INSUFFICIENT with deferrable disposition.
A current LM Studio input estimate above the trusted resident context throws EMBEDDING_INPUT_TRUNCATED before POST and reaches KB_VECTOR_EMBED_INPUT_TRUNCATED with rejected disposition.
The exact pinned llama.cpp structured overflow receipt maps to EMBEDDING_INPUT_TRUNCATED; malformed, partial, prose-only, or foreign 400 responses retain existing unclassified/deferrable behavior.
Generic OpenAI-compatible requests preserve their existing {model, input} body and perform zero /slots calls.
No request-path /slots capability, cache, probe, or recurring model work is introduced by this ticket.
Contract Ledger
Surface
Source of Authority
Behavior
Failure / Edge Case
Evidence
localModels.embedding.safeProcessingLimitTokens
Resolved AiConfig leaf and env binding
Positive-integer resolved band feeds every production entrypoint
Invalid env input falls back through the config parser; pure helpers reject invalid injected values
Isolated config-process matrix
Provider-lane composition
Resolved leaf injected by the executable entrypoint
v2 receipt includes embeddingSafeProcessingLimitTokens; per-slot context must cover it
No default or second env resolver inside the analyzer
Non-default-env CLI test plus below/at-band matrix
Provider-lane election
v2 candidate deployment inputs
Plans/reports retain the same band across candidates and analyzer subprocesses
Candidate disagreement or missing field invalidates the plan/report
Plan/report validator and actor tests
LM Studio postSpawn
Strict lms ps resident rows already fetched by readiness
Metadata-only floor gates the embedding role without inference
Missing/invalid context is not ready; chat-only role runs no embedding check
Production-owner task test and zero-canary assertion
LM Studio context policy
Exact resident row plus resolved configured context and safe band
Insufficient lane shape emits EMBEDDING_CONTEXT_INSUFFICIENT
Deferrable: a corrected/reloaded resident may recover
Real-service zero-POST preflight fed through KB classifier
Rejected: retrying the unchanged input against the same limit cannot help
Real-service zero-POST overflow test
Pinned llama.cpp overflow
HTTP 400 structured exceed_context_size_error with valid n_prompt_tokens / n_ctx
Exact receipt maps to EMBEDDING_INPUT_TRUNCATED
No prose regex; near-miss/foreign responses remain unclassified and deferrable
Exact and falsifier response matrix
Generic OpenAI-compatible request
Existing OpenAI-compatible transport
Sends {model, input} only
No absolute truncation claim without trusted LMS metadata or pinned structured refusal
Zero-/slots, no-truncate negative control
Live canonical lane shape
Elected envelope compared with boot-time runtime observation
Owned by #17069 and projected into deployment state
/slots starvation during load cannot become a per-request failure
Existing ticket and live #17024 receipt
Scope Transfer
[SCOPE_TRANSFERRED] Live llama.cpp shape-versus-envelope verification belongs to #17069. That ticket already owns the boot-time /slots observation, comparison with the elected envelope, health degradation, and deployment-state projection. This ticket does not duplicate that heavy cross-service work at the request boundary.
The transfer is evidence-driven: the pinned server already refuses an oversized embedding structurally, while the live #17024 receipt proves /slots can be unavailable exactly when all slots are doing useful work. A per-request probe would turn expected saturation into false failures and recurring zero-progress diagnostics.
Out of Scope
Boot/runtime lane-shape comparison and deployment-state projection (#17069).
Changing chunking or the 28,672-token default band.
Auditing or re-embedding historical corpus rows.
Claiming arbitrary OpenAI-compatible providers are truncation-safe without trusted metadata or an exact structured refusal contract.
Admission ordering, activity-ledger expiry, or actuator deadlines.
Avoided Traps
truncate: false as safety: the pinned handler ignores it.
Per-request /slots as safety: measured starvation under load makes it unsuitable as recurring transport authority.
Provider prose as proof: only the exact structured pinned refusal is classified as permanent.
Conflating policy mismatch with current-input overflow: the former is deferrable; the latter is rejected.
Static default as deployment truth: executable consumers read the resolved leaf; pure helpers receive it by injection.
Failing generic endpoints closed: compatibility behavior remains unchanged outside the declared local authorities.
Decision Record Impact
No new ADR. The implementation follows ADR-0019: resolved config is read at production/executable use sites, analyzers remain injected and pure, and no second environment authority is created. The v2 schema bumps are required because the signed composition/election artifact shape gains one deployment input.
tobiu referenced in commit d6a7a44 - "fix(ai): bind the resolved embedding safe band and classify exact overflow (#17070) (#17090) on Aug 14, 2026, 10:19 AM
Context
Neo's resolved embedding safe-processing band is
AiConfig.localModels.embedding.safeProcessingLimitTokens(default 28,672 tokens). The canonical llama.cpp lane allocates 32,768 tokens per slot, while LM Studio exposes the resident model's loaded context through strictlms psmetadata.Source correction
The original ticket premise treated a client-supplied
truncate: falsefield or per-request/slotspolling as the missing safety witness. The pinned llama.cpp source establishes a different contract:handle_embeddings_impl()does not parsetruncate.n_prompt_tokensandn_ctx; the pinned server maps it to HTTP 400 with typeexceed_context_size_error./slotscan starve during full embedding grind and must not be treated as an always-available per-request authority (#17024receipt, Arm 3 and prescription 4).The safe design therefore binds the resolved band at composition/readiness, classifies exact transport evidence, and leaves live provider-shape verification to its existing boot-time owner rather than adding a recurring request-path probe.
Problem
Four authority gaps remain:
postSpawnpath verifies residency but does not apply the embedding safe-band floor to its already-fetched strict metadata.Without those distinctions, deployment drift can pass static validation, readiness can report green for an undersized LM Studio resident, and durable tenant-sync state cannot tell a repairable context mismatch from a current input that the provider positively refused as too large.
Intended Solution
localModels.embedding.safeProcessingLimitTokensa positive-integer config leaf.AiConfig; pure analyzers receive the value by injection.postSpawnrun metadata-only embedding readiness from the strict resident rows already fetched byensureLmsModelsLoaded. This path performs no embedding inference or tokenizer/model-file work.EMBEDDING_CONTEXT_INSUFFICIENT, mapped toKB_VECTOR_EMBED_CONTEXT_INSUFFICIENTwithdeferrabledisposition;EMBEDDING_INPUT_TRUNCATED, mapped toKB_VECTOR_EMBED_INPUT_TRUNCATEDwithrejecteddisposition.exceed_context_size_errorreceipt, with valid positiven_prompt_tokensandn_ctx, intoEMBEDDING_INPUT_TRUNCATED. Do not infer permanence from response prose.truncate, add a strict-slot capability leaf, or poll/slotsper embedding request.Acceptance Criteria
ConfiguredTaskDefinitionsService -> lms.postSpawn -> ensureLmsModelsLoadedpath applies metadata-only embedding readiness when LM Studio owns the embedding role. A known undersized resident is not ready, and zero embedding canaries are issued.EMBEDDING_CONTEXT_INSUFFICIENTbefore POST and reaches Knowledge Base classification asKB_VECTOR_EMBED_CONTEXT_INSUFFICIENTwithdeferrabledisposition.EMBEDDING_INPUT_TRUNCATEDbefore POST and reachesKB_VECTOR_EMBED_INPUT_TRUNCATEDwithrejecteddisposition.EMBEDDING_INPUT_TRUNCATED; malformed, partial, prose-only, or foreign 400 responses retain existing unclassified/deferrable behavior.{model, input}body and perform zero/slotscalls./slotscapability, cache, probe, or recurring model work is introduced by this ticket.Contract Ledger
localModels.embedding.safeProcessingLimitTokensAiConfigleaf and env bindingembeddingSafeProcessingLimitTokens; per-slot context must cover itpostSpawnlms psresident rows already fetched by readinessEMBEDDING_CONTEXT_INSUFFICIENTEMBEDDING_INPUT_TRUNCATEDexceed_context_size_errorwith validn_prompt_tokens/n_ctxEMBEDDING_INPUT_TRUNCATED{model, input}only/slots, no-truncatenegative control/slotsstarvation during load cannot become a per-request failure#17024receiptScope Transfer
[SCOPE_TRANSFERRED]Live llama.cpp shape-versus-envelope verification belongs to #17069. That ticket already owns the boot-time/slotsobservation, comparison with the elected envelope, health degradation, and deployment-state projection. This ticket does not duplicate that heavy cross-service work at the request boundary.The transfer is evidence-driven: the pinned server already refuses an oversized embedding structurally, while the live
#17024receipt proves/slotscan be unavailable exactly when all slots are doing useful work. A per-request probe would turn expected saturation into false failures and recurring zero-progress diagnostics.Out of Scope
#17069).Avoided Traps
truncate: falseas safety: the pinned handler ignores it./slotsas safety: measured starvation under load makes it unsuitable as recurring transport authority.Decision Record Impact
No new ADR. The implementation follows ADR-0019: resolved config is read at production/executable use sites, analyzers remain injected and pure, and no second environment authority is created. The v2 schema bumps are required because the signed composition/election artifact shape gains one deployment input.
Related
Parent epic: #17072
Related: #17069
Related: #17024
Related: #16853