Read before changing model routing, cache-read telemetry, VPS acceptance, lint configuration, or Deno app inventory. These are scoped decisions, not general policy; they narrow global defaults only for this repository and never weaken higher authority.
Provider routing decisions are maintained separately in docs/provider-decision-journal.md.
The direct Claude subscription and native Messages lane omits every hosted web_search declaration from the upstream request instead of rejecting the whole turn. This includes Codex's default external_web_access:true declaration, which the TUI restores after a per-thread disable. Function, namespace, MCP and other representable tools remain unchanged. Surplus and other reseller adapters retain their existing rejection of an enabled hosted declaration.
Reason: production request 8ed33374-67b5-4a65-9d87-9369a4c3450a failed before dispatch with claude_code_request_invalid solely because the TUI re-enabled its built-in hosted search declaration. A thread-scoped web_search=disabled workaround lasted only one turn; the gateway must not depend on clients changing their tool catalog.
Reversal risk: the direct lane no longer advertises provider-side web search to Claude models. They can still use any function, MCP, browser or command tools supplied by the client, but a request that specifically requires the hosted search tool cannot be served on this lane. Reintroducing hosted search requires a real native server-tool translation and response-stream mapping.
The direct Claude subscription and native OpenLux Messages translator now flattens Codex namespace tools as <namespace>_<tool>, retains the reverse mapping for Responses output and signed replay, and keeps ordinary function names unchanged. Late developer/system text is preserved in native system blocks because Messages has no interleaved developer role. JSON-schema text.format maps to native output_config.format. A hosted web_search declaration is omitted only when the caller explicitly sets external_web_access:false; enabled web search remains unsupported on this lane.
Reason: Codex 0.166 TUI requests include namespaced Clock, collaboration and MCP tools, late hook/time developer messages, a concise reasoning-summary preference, and a disabled web-search declaration. The previous translator rejected the first such request before dispatch as having no lossless native representation.
Reversal risk: flattening changes the model-visible tool name, so response mapping and replay must retain the reverse table. Treating a late developer message as system context changes its position relative to user content, but preserves its instruction authority and avoids dropping it. Omitting a disabled web-search tool does not restore external search access.
CI runs native test profiles after portable gates and uses pinned prebuilt wasm-bindgen - 2026-10-29
After portable validation succeeds, the Linux native job runs the existing deploy-guards, vps, main, sentinel, quality and benchmark profiles with its independently bound native KV receipt. It retains frozen lint-tool preparation, the Bun type patch and native preflight fixtures, and aggregates profile failures. The portable strict TypeScript preflight remains because the scoped aggregate can select zero tests and exit before static gates. Local verify.sh keeps its complete aggregate default.
WASM preparation supports Linux ARM64 only and downloads the official wasm-bindgen 0.2.129 GNU archive with SHA256 1797c349a0f45d30946e8986b184135e12839ab576c9a04203e85febfc5dcb35. The existing checked archive extraction places the binary under the fresh task's tools/wasm-bindgen; WASM_BINDGEN_BIN binds that absolute path for both version verification and Worker compilation. worker-build 0.8.7 remains a locked source install. Fresh application targets, frozen source receipts and offline verification remain required.
Reason: Actions run 40168689356 repeated about 338.3 seconds of portable static gates in the native job, and WASM preparation serially compiled wasm-bindgen from source. This removes those repeated invocations without changing selected native-mode tests or release profiles. The sampled public-repository timing API reported zero billable milliseconds; these are runner-work reductions, not measured quota savings or candidate hosted timings. The manually disabled workflow stays disabled.
First-party Codex catalog records carry the existing shared automatic compaction policy alongside their context window. The limit is the earlier valid source limit or the shared 85-percent-or-50,000-token-reserve derivation. A 1,050,000-token GPT window therefore carries an 892,500-token limit; an earlier source limit remains authoritative. This repairs native records that previously widened their window while leaving clients to derive a later default trigger.
Verified cached bodies receive the same projection before client conditional validation, including caches persisted before this correction. Stored source bytes, source integrity metadata and the upstream ETag remain unchanged; upstream 304 revalidation still starts from those original bytes. Client ETags continue to hash the final served representation, so an old validator cannot hide the repaired compaction limit.
Reason: real Mac sessions exhausted context near 923,000 tokens before the client's 945,000-token default trigger. Their native catalog advertised the widened window without the gateway's earlier compaction policy. This change adds no interception, provider routing, model choice or user configuration. Exact upstream output reservation is not inferred from those failures.
The Claude meter and current capacity projection use an explicitly marked response-header observation captured by the existing ordinary-inference quota acceptance path. Subscription windows and API-key limit families retain their own observation timestamps; missing families and headerless responses invent no measurements. Canonical routing quota, proofs, cooldowns and settlement keep their existing behavior. Old canonical values without header provenance and retained direct-usage snapshots are not relabeled as header evidence. New header history carries source: "response_headers"; legacy history without a direct snapshot remains readable as header history.
The capacity sampler never calls Claude's OAuth usage endpoint, and direct-usage freshness cannot force a capacity refresh. The former manual refresh route is a passive compatibility read that reports refreshed: false with a response-headers reason. The visible meter waits for normal Claude traffic when no proven headers exist. This supersedes the 2026-10-25 direct-usage collection decision and adds no OAuth grant, credential work, synthetic inference, timer or service activation.
Claude history follows the active account in each capacity snapshot without an account dropdown or a pinned manual selection. A missing active projection may use matching subscription metadata, but an explicit empty projection or account/cohort mismatch remains empty. This is a view-only choice: retained history is preserved and other provider charts are unchanged.
A direct usage HTTP 429 with a valid Retry-After stores an absolute retry deadline in that account cohort's usage metadata. Automatic capacity collection and manual usage refresh share the deadline across KV reopen and process restart. A suppressed manual refresh returns HTTP 429 with the remaining Retry-After; a successful read clears the deadline. Missing or malformed deadlines retain the existing 30-second attempt freshness, and an expired deadline does not extend that freshness. Failed reads preserve the last successful meter snapshot and never set an inference quota block or cooldown.
Reason: the HTTP reader parsed Retry-After but the collector discarded it, allowing another usage request after 30 seconds even when the provider requested a longer pause. Reversal risk: discarding this usage-only deadline restores early retries; placing it in the inference cooldown would incorrectly deny otherwise eligible model requests.
The Bun gateway requests an explicitly opted-in persistent Passport app grant only through a fresh browser SSO code exchange, using PKCE S256 and the existing fixed issuer, client, audience, origin and callback. Its host-only HttpOnly/Secure/SameSite cookie contains a random local session identifier; existing private KV stores its SHA-256 key and the app-scoped upstream grant without a time-based expiry or a saved administrator-role authority. Every authenticated request introspects the grant against Passport's current user. Demotion denies admin access, deletion or authoritative revocation removes local authority, and temporary verification failures return 503 while retaining the saved session. Legacy JWT cookies remain verification-only until their normal expiry and cannot create permanent grants.
Successful browser auth checks renew the platform-bounded persistent cookie; browser storage removal or browser retention limits can still require sign-in. Explicit logout deletes local authority before best-effort upstream grant revocation and reports an unavailable upstream revoke honestly. An in-flight read cannot recreate a deleted session. Failed login callbacks clear only state and verifier cookies, preserving an existing session; a successfully stored replacement atomically removes the previous local session. The admin UI preserves its last known state during temporary failures, shows an unavailable/retrying status and rechecks on foreground without authorizing server operations from cached roles.
Reason: the previous app cookie directly held a Passport access token whose default lifetime was fifteen minutes, and network or verification failures also appeared as sign-outs. The persistent app grant separates sign-in lifetime from access-token expiry while preserving current central authorization. The same change uses the existing theme surface/text appearance for Ubiquity sign-in buttons without changing their shape or interactions. This source decision does not activate the unshipped Rust port or authorize production credential, database or service changes.
OpenRouter's decision models are discovered with output_modalities=text,decisions and served through POST /v1/decisions, which mirrors the upstream Decisions API's state, typed questions (noul, choice, score, box), optional provider routing, trace, session, and user fields, and returns the typed answers envelope unchanged. Text models remain limited to Chat Completions and Responses; decision models remain limited to /v1/decisions. /v1/systemone stays as the bounded Jev compatibility route. Every listing surface attributes decision rows to /v1/decisions, while the Codex-native versioned catalog excludes them because Codex cannot select a non-text decision response.
Reason: OpenRouter's default model list omits decision models, so the admin picker and public catalog silently missed newly listed rows such as baseten/elephant-1:free; merely widening discovery without a matching request wire would have advertised models that no gateway route could serve.
Reversal risk: returning to the default text-only discovery hides every decision model again. Advertising decision rows on Chat Completions or Responses, or accepting text rows on /v1/decisions, would produce guaranteed upstream failures and break the gateway's listed-equals-servable contract.
The admin Analytics view restores the Claude subscription capacity rows and chart series. Claude accounts join the existing lease-guarded capacity sampler, so opening Analytics, its visible 30-second poll, foreground resume and existing capacity events collect direct usage for every configured account, including accounts with no prior inference or unavailable inference state. Each row retains a targeted Refresh usage action using the same account-fenced helper; a short durable account/cohort lease coalesces manual and automatic collection. The action calls POST /admin/providers/claude-code/quota/refresh, which sends GET https://api.anthropic.com/api/oauth/usage with the account's OAuth credential and the Claude Code OAuth headers, parses the five-hour and weekly utilization percentages and reset instants, converts the percentages to the existing fractional quota windows, and publishes the accepted observation through the existing quota and history writer. It never sends a Messages request or starts an inference turn. A direct usage attempt within the previous 30 seconds returns the current evidence without another provider call; inference-header recency does not suppress this independent source. The capacity response reads the Claude roster and history after collection so it includes newly persisted observations. Cached reads never invent measurements. Anthropic's OAuth usage endpoint is undocumented and may change; gateway traffic continues to update the meter through the existing rate-limit-header observation path.
Reason: the owner required a working independent usage source and rejected synthetic inference probes. The direct endpoint is the same server-side evidence used by Claude Code's account panel, so it refreshes both windows without spending subscription capacity. A stored OAuth setup token without user:profile cannot read this endpoint; that result is recorded as an explicit scope_missing usage state, leaves inference routing and health untouched, and is shown in the row diagnostics instead of being treated as credential invalidity.
Reversal risk: removing the refresh action returns the meter to gateway-traffic-only updates. Polling the endpoint too frequently can trigger upstream rate limits, so only one stale-load attempt, one explicit operator read, and a 60-second freshness window are permitted. Reintroducing an inference request as the usage source would make quota observation consume the quota it is trying to measure.
Direct OAuth usage has a separately timestamped, account/cohort-bound successful snapshot. A successful partial reply replaces its complete prior shape; a failed read keeps the original last-success clock and exposes the failed attempt. Inference headers keep their existing canonical 5h/7d routing semantics and never renew the direct snapshot. A valid server limits array, including an empty array, defines the displayed meters in server order with the supplied kind, group, scope labels, severity and headline choice; missing or null limits uses independently present legacy subscription windows. Source values and nullable resets remain preserved, including percentages above 100; chart bounds are presentation only. Separate spend and credit fields are diagnostics, not quota capacity or management controls.
Claude history retains the snapshot at the accepted-observation seam; direct meter rollups use a separate namespace and keep each meter/cohort/reset independent. Existing legacy records remain readable without backfill or a new shared capacity denominator. No named or dynamic scoped meter gains global routing authority. The Rust source adapter does not yet preserve these additive fields, so Rust adoption requires a separate source-contract preservation gate rather than claiming TypeScript/Rust round-trip parity.
Reason: the native Claude Code 2.1.310 schema permits independent null/missing windows and server-selected scoped meters; requiring both canonical windows discarded valid replies and hid returned quota. Reversal risk: merging individual fields from older snapshots would present missing windows as current, and deriving global guards from scoped meters would block unrelated models.
The admin console and chat present the Ubiquity-branded Passport sign-in button established in the Passport sign-in-buttons study: the Ubiquity mark plus the label "Sign in with Ubiquity". The admin page exposes only that browser sign-in; its former secondary "Sign in" gate, passkey controls, and admin-token controls are removed from the visible page. Hidden compatibility nodes preserve existing client code and local automation. Programmatic admin tokens and existing passkey relay routes remain available to command-line tooling and separately supported clients.
Reason: the owner reported two login choices and requested Passport as the only login service.
Reversal risk: re-exposing passkey or token fields restores the second visible login path. Removing the server-side token and passkey authorities would break automation and approved relay clients, so that broader change requires a separate decision.
The production Bun gateway implements the existing Passport ai registration at /auth/login, /auth/callback, and /auth/logout, matching the fixed issuer, audience, origin, callback, RS256/JWKS verification, host-only secure cookies, and cookie-only admin authority used by the Rust implementation. An administrator claim is required for admin access; agent tokens never become admin sessions, and foreign-origin cookie mutations are rejected. The admin button requests /admin as its return destination; that fixed choice is bound into the random login state, while ordinary chat login returns to /chat.
Reason: the shared admin page advertised Passport sign-in while the production Bun router returned 404 for /auth/login; Rust-only coverage did not exercise the runtime serving the public page.
Reversal risk: removing the Bun routes strands the advertised sign-in button. Accepting arbitrary callback destinations, JWT key sources, audiences, or bearer credentials as admin authority would expand the existing trust boundary.
Automatic banked resets are now live-only. The CODEX_BANKED_RESET_MODE selector and shadow-decision arming gate are retired; CODEX_BANKED_RESET_ENABLED remains the immediate kill switch. When enabled, an eligible blocked cohort performs fresh inventory, selects one exact credit, claims the deterministic redemption, and submits it in the same request. The existing one-per-account-per-UTC-day and one-per-window caps, exact fence checks, at-most-once transaction, and post-reset probe remain unchanged. Historical shadow decisions remain readable for audit but do not gate a live redemption.
Reason: the owner explicitly required automatic live behavior; shadow mode and arming made a redeemable reset require a prior decision and a later request.
Reversal risk: removing the arming and audit gate allows an external spend on the first eligible blocked request. Exact caps and fences plus the enabled kill switch are mandatory; unknown remains possibly spent and is never replayed.
This supersedes the merge-group, queue-canary, Sentinel-authored PR, and development-push trigger requirements in "Real CI checks for Sentinel and merge groups" for the current GitHub Actions quota policy. pull_request: closed and workflow_dispatch are the only triggers, and every job requires a merged pull request or explicit manual dispatch. After scope, the portable x64 portable gate must pass before rust-native; rust-wasm follows rust-native; native and macOS/Darwin work start only after their selected earlier gates pass. The validate job remains the required check name and fails closed when a selected portable or Rust gate is missing, skipped, cancelled, or failed. Each job has an explicit timeout, and the workflow never deploys.
Reason: recent failed runs spent 70-90 job-minutes because native, rust-wasm, and macOS work started even after rust-native failed, while validate waited for both Rust jobs before running portable checks. The dependency chain preserves every selected check but skips work that cannot be accepted once an earlier selected gate fails.
Reversal risk: removing the dependencies restores parallel quota consumption on failures; treating skipped or cancelled dependencies as success would hide missing checks. Manual dispatch with an explicit scope_base remains necessary for squash or rebase merges, whose commits are not ancestry-preserving merge commits.
The owner authorized a pre-merge verification path for Sentinel-authored AI pull requests under the manual-only quota policy. A manual workflow_dispatch may pass base_ref=development and sentinel_pr_author=ubiquity-sentinel[bot] with the exact PR scope_base; the workflow then selects the same complete check set as a Sentinel-authored pull request. This does not add an automatic trigger, a push trigger, a merge-queue trigger, or a deployment. The resulting check runs remain bound to the exact dispatched head and are accepted only when every selected job succeeds; skipped, cancelled, neutral, or missing jobs are not success. The normal pull_request: closed post-merge run remains the hosted receipt for ordinary merged changes.
A fresh 100%-used capacity observation with a future reset deadline now reconciles an existing class block even when the
block still carries an older future stable observation. It replaces that observation with the sample's deadline, clears
banked_reset_generation_ambiguous, and preserves the credential/account fences, probe lease, and recovery-probe
pending state. A live 429 observed after the sample remains newer and cannot be replaced by the older sample.
Reason: the older identity kept a creditless sibling ambiguous while the pool was otherwise fully exhausted. The
automatic reset evaluator rechecked every blocked account, returned routing_fence_stale, and the intentionally
conservative overage fallback refused that reason. Both enabled bonus paths therefore dead-ended on a gateway quota
refusal even though another account held an available reset.
Reversal risk: allowing any stale identity to override a newer live signal can spend a reset against the wrong quota window. The observation timestamp, account identity, credential fence, and active probe lease remain hard gates.
API-key audit fields and target names preserve the source slice(0, 200) contract, including a lone surrogate when the cut splits a pair. Audit writes retain ordinary Json records when lossless and use the existing ProfileV2 encoding only when ordinary JSON values cannot represent the event. The audit-only read projection uses validated SourceJson and retains existing Json compatibility, scalar-field selection, timestamp-only visibility and event ordering. This adds no storage family, general codec reinterpretation or live-state conversion.
Reason: Unicode-scalar truncation changed the retained text, and ordinary Rust strings could not represent every source audit value. Source-golden persistence and read-page fixtures cover the exact code units. Migration and latest-state inverse must preserve the same existing ProfileV2 representation before operational acceptance.
The VPS deploy CLI reuses the selected immutable release's node_modules and .native/kv payload when the root lockfile
and native input manifest match exactly. A mismatch falls back to the existing fresh install/build path. This avoids
recompiling the unchanged native KV addon for routing and client-only changes.
Reason: repeated Cargo builds delayed small TypeScript releases and kept the service on stale behavior longer than necessary. Reuse is bound to the selected release's verified provenance and the current tracked native inputs.
Reversal risk: reusing across a changed lockfile or native input would violate the immutable release identity, so either mismatch must continue to rebuild and verify from source.
Gateway routing errors retain their durable quota or reset deadline, but the client-facing Retry-After hint is capped
at 60 seconds. A weekly Codex quota block previously emitted the full remaining duration, such as 561,000 seconds, and
clients slept for days instead of retrying or entering an available failover.
Reason: routing availability can change through paid failover, reset recovery, or operator action long before the upstream subscription window resets. The upstream deadline is still enforced internally and is not shortened.
Reversal risk: removing the cap restores multi-day client sleeps on ordinary weekly exhaustion. Emitting no header would instead invite tight retry loops.
In banked-reset shadow mode, shadow_selected and already_would_spend_once prove that no reset credit was
redeemed: shadow persists a decision but never consumes it. Both outcomes now qualify for the existing single bounded
overage probe when the account's Allow overage spending setting is on. The per-account allow setting remains a hard
gate; live_armed, a completed live redemption, and fence or configuration failures still never fall back.
A durable reset record stuck at local claimed without a provider submission likewise returns
unsubmitted_transaction. Reconciliation cannot advance that record and no external reset was consumed, so the same
bounded overage probe may proceed. In-progress, live-armed, submitted, unknown, and ambiguous states remain ineligible.
Enabled overage is a serving path, not a single-flight reset recovery probe. It does not claim the reset probe lease, so concurrent client requests may use the account directly; each request still performs at most one bounded upstream attempt.
Reason: an exhausted account with overage enabled remained stuck behind an existing shadow decision and fell through to paid routing, even though shadow mode could not spend the reset it observed.
Reversal risk: removing these reasons restores that dead-end. Adding live-arming or completed-redemption reasons would risk spending both a banked reset and overage for one episode.
An authenticated admin may use one banked reset for a selected Codex account through POST /admin/providers/codex/banked-resets/consume. This explicit manual action works independently of the Automatic resets switch and automatic shadow arming; global enabled=false and mode=disabled still make zero provider calls. Manual and automatic redemptions share the existing one-per-account-per-UTC-day submission budget, account/window idempotency, exact credential and quota fences, and unknown-consumption refusal. An uncertain consume is never replayed.
After a documented verified consume outcome, the manual action synchronously reads that account's current usage. One atomic transaction stores the fresh account-bound observation, reconciles only quota classes proven recovered, records completed manual promotion and selects that same account with reason manual_reset. This explicit operator transition may supersede a healthy active account; ordinary serial routing, provider selection, authentication and model eligibility remain unchanged. Pending propagation or a failed promotion never claims success, and a repeated completed action cannot restore an old priority. The manual intent contains opaque account/credential hashes and quota metadata, never tokens. KV export/import retains the intent together with its authoritative reset-window and account-day ledgers; importing only the intent would lose the consumption and daily-budget proof.
Reason: a manual reset outside the gateway could leave exhausted routing state until a later capacity sample. The button owns verification and promotion directly, without waiting for chart sampling or issuing inference. Acceptance uses isolated upstream fixtures; agents remain forbidden from directly redeeming live credits.
The per-account Allow overage spending setting is a hard gate. With the setting off, the gateway may redeem a banked reset, but it must never dispatch an overage probe, including after the reset preflight returns no_eligible_credit, empty or ineligible inventory, inventory_unavailable, or account_day_limit_reached. That case returns the ordinary codex_quota_blocked response. With the setting on, the existing resets-first flow and one bounded overage fallback remain unchanged.
Reason: the previous implementation treated off as "try resets first" and still spent overage when no reset was redeemable, which contradicts the operator-facing switch. This change governs gateway-routed inference only; a native Codex client that authenticates directly to ChatGPT is outside the gateway and must be configured or authenticated separately.
Reversal risk: turning the setting off now stops serving an exhausted subscription instead of silently drawing paid overage. That is the requested safe behavior, and re-enabling the setting restores the bounded fallback.
Issue #1206 preserves real successful checks for Sentinel's delivery and base-failure attribution. Run the complete job set for merge groups, PRs targeting exactly queue-canary, Sentinel-authored PRs targeting exactly development, development pushes, and development PRs changing the CI workflow or selector itself. Use the PR author, not the actor who reruns a workflow. Ordinary owner PRs retain changed-path job selection.
This selects jobs without broadening dependency-scoped test selection. Native KV and Darwin signing fixtures retain their existing eligibility rules; admitted native, sandbox and artifact jobs still execute their real verification commands. Documentation wrappers may truthfully select zero tests. Never substitute successful placeholder checks or accept skipped checks as success. Development and merge-group runs retain their non-cancelling concurrency groups, and CI never deploys.
Sentinel R81 attributes a red head check using the same check name on the exact base. Restoring successful base jobs provides that evidence for future runs; it does not prove identical test-file coverage across differently scoped runs or repair historical skipped evidence. Reversing this exception can strand otherwise eligible Sentinel repairs or queue entries without usable check evidence.
PR #1156 closed #1132 on 2026-10-18 without resolving the two owner-only actions below. #1176 tracks both; this entry records pending work, not an owner decision or authorization to change runtime behavior. Keep #1176 open until the owner resolves these actions or each is transferred to a linked open owner task.
- #1073 item 2 / #139 — hard-cap disposition. Oldest-first eviction has not been implemented. The retention document previously attributed a decline to the owner on 2026-10-16 in #139, but no supporting owner record is available in #139 or this journal. The owner must confirm and record that reported decline in a comment on #139 or a dated decision here, or correct the attribution. If declined, consider changing #139's close reason from "completed" to "not planned"; its current close reason does not prove eviction exists. The 5 GiB figure remains a growth-alert threshold, not an eviction limit.
- #1077 item 2 — non-loopback macOS live e2e. Darwin live e2e accepts only a host-loopback
BASE_URL; the defaulthttps://ai.ubq.fifails closed. The owner must explicitly accept that limit or open a task for a destination-scoped CONNECT relay (or equivalent). No relay implementation or broader network permission is authorized while that decision is pending.
For issue #1165, keep PID 1 rows about ai-ubq-fi.service out of request counts, but retain completed exit/restart timestamps as lifecycle evidence. Once a fully covered window has an unmatched admission before such a marker, persist unavailable / terminal_lost, stop its forward scan and release its slice pin. A startup notice, a mere stopping/starting notice or unrelated manager output is not evidence that an admitted request was lost. With Type=simple, a Started row can follow a live admission from the new process, so it never establishes this cutoff. Matched requests remain countable. Checkpoint schema 3 includes lifecycle markers and terminal-lost state; older schemas fail closed rather than silently discarding that evidence. This does not impose a new maximum stream lifetime or activate the standalone release bridge.
Retain the conservative orphan-terminal rule from #1155: an unmatched accepted-stage or legacy null-stage terminal at or after a window's start can refuse that window even when at - latency_ms - VPS_METRICS_SLICE_MS >= windowEnd. Its reported latency bounds the backward admission search, but is not trusted to exclude it from the cohort. Ignoring it would let an under-reported latency hide a lost admission and produce falsely complete counts. Prefer a monitoring restart over that fail-open result; explicit pre_admission terminals remain excluded.
Pending windows retain whole ledger slices. Evidence therefore grows with request rate times the longest in-flight lifetime, plus backward lookback and slice/proof overhead, until a terminal/lifecycle bound resolves the window or a configured limit refuses it. The hard byte cap is a refusal boundary, not a promise of constant-size or always-completable evidence. Sizing examples and the remaining no-lifecycle-marker limitation are in ops/README.md.
Responses output_text accepts the official logprobs field when it is an array, including an empty array. Validation intentionally checks only the array shape, matching the existing annotations rule; neither field's entries affect generation. Both fields are dropped when constructing MessageContentItem, so the Codex subscription and paid provider request bodies carry only the replayed text. Non-array values retain a precise nested field error, non-assistant output_text remains invalid, and genuinely unknown fields remain rejected.
Reason: Codex 0.163.0 replays output_text.logprobs, so the missing documented field made the gateway reject the next model call. The content allowlist audit records the remaining field, type and nullability decisions. Other existing content allowlists already include their documented field names; unrelated unsupported modalities and nullable values do not justify accepting arbitrary metadata.
Reversal risk: rejecting this output metadata again breaks replay, while forwarding it unnecessarily extends every provider's input contract. This source change makes no claim of deployment or live client acceptance.
The first cross-codec deployment uses ops/first-bun-cutover.ts through a private pinned operator invocation. Ordinary CLI and bound-driver tracked-clean guards remain unchanged. The new operator executes from the complete accepted CI artifact and proves current shipping push CI, every required job, hosted ZIP digest, exact Git source archive/materialized source, dependency/native/permissions trees and matching service bootstrap bytes. The mutable checkout is a data/runtime anchor and immutable Git-object store; unrelated working-tree or submodule state never supplies executable source or a fabricated clean predicate.
The operator captures actual prior health and loaded-unit identity before stop, holds the existing deployment lock and release pins, verifies and reasserts only its own kernel-enforced supervisor limit across reload/start/recovery boundaries, and journals intent before each service transition. A prepared-only recovery receipt has no stopping intent: recovery verifies the original live selector/process/unit/health and never stops or restarts it. Conversion requires a stopped, checkpointed source, private consistent backup, exclusive NEW Bun target, complete metadata/typed-value proof and full reverse proof. Starting is authorized by this verified stopped boundary instead of requiring the old writable service to restart. The separately owned Sentinel acceptance receipt is pinned and strictly compared against the final gateway artifact/runtime and all required denial evidence; its exact receipt and evidence files are bound read-only at their recorded paths inside the private namespace.
After any possible Bun startup, recovery converts the latest stopped Bun state into a NEW Deno destination. Once legacy adoption is published, later Deno writes are authoritative and recovery never overwrites them from an older Bun snapshot. A pinned offline capture and recovery entry support the supervisor's ExecStopPost without model, GitHub, download, install or compiler dependency during outage. Failed recovery retains every copy and reports unproved service state. Effective typed unit commands and resource-only drop-ins are pinned; an existing candidate must match the independently accepted CI manifest. Partial forward publication is retained separately while the unchanged stopped legacy source stays authoritative. Capacity includes WAL bytes and is rechecked after checkpoint. Runtime hashing streams database files, the codec cache stays task-local, and finite private phase budgets are bound in the operator authorization. Health success keeps client acceptance pending and retains release pins until the coordinator proves direct authenticated Mac-to-VPS inference and settles ownership.
This change does not authorize live activation itself; the user's explicit deployment instruction and the coordinator's exact reviewed operation remain necessary. Source CI, external-reader acceptance, stopped-store rehearsal, runtime custody and live client acceptance are separate evidence surfaces.
Both private Bun entries use a cleared environment, an independently checksum-pinned explicit Bun configuration and a frozen working directory outside the mutable checkout. Disabling dotenv discovery and auto-install alone does not block configuration preloads or inherited runtime options. Private workspaces and receipts retain mode700/600; only the source archive extraction child uses umask022 to reproduce the exact hosted CI entry modes.
The gateway launcher and its Bun legacy-rollback verifier independently select ops/runtime-bunfig.toml, check its fixed byte hash before invoking Bun, and remove inherited preload/module-selection options while preserving the service credential environment. That config is part of the artifact-bound bootstrap comparison; a modified root bunfig.toml cannot supply executable source before verification. Persisted unit identities use the existing canonical encoding so journal key sorting cannot reject unchanged live state.
Deployment fixtures bind their frozen JavaScript graph, matching native headers and independently attested native KV artifact through an internal store preparation capability. Both the graph's lock and the candidate's lock must match the bound digest before packaging. The fixture imports the exact relocated deployment entry and supplies this capability to its actual candidate preparation; service environment variables do not select packaging inputs.
The production CLI keeps real frozen dependency and native artifact preparation before immutable publication. Runtime startup only verifies and loads the published payload. Source, archive, manifest, graph, native provenance, OS confinement, fresh candidate publication and rollback checks remain unchanged. Focused hosted preflights run before the complete aggregate and never replace its acceptance.
The owner authorized same-model paid failover after the Mac gateway stalled on 2026-10-14.
Each selected subscription must prove exhausted applicable quota or invalid current credentials.
Only matching credential fingerprints count. Generic 429s, timeouts, probe leases and unknown state never count.
Exhaustion proof and banked-reset eligibility remain separate. Existing paid caps and provider selection still apply.
A mixed pool returns codex_subscriptions_unavailable with no multi-day retry delay when paid routing cannot serve.
Current-invalid credentials retain the original actionable authentication body and re-auth warning. Fresh proof is internal.
Reason: an exhausted account and failed sibling refresh returned a five-day 429 without attempting any paid provider.
Reversal risk: treating credential failure as quota exhaustion could redeem a reset or spend against unproved capacity.
The owner authorized recovery of the Mac primary and Ubiquity profiles from working same-user/workspace peers. The
gateway accepts the official native chatgptAuthTokens access-only leaf only from its fixed primary or
.codex-ubiquity home, with an empty refresh field and identical access/id JWT. Durable external ownership records the
native home, user, workspace, and credential generation; ordinary uploads, env seeds and managed donor candidates remain
strict. The existing repair CLI validates the current regular local leaf, preserves valid managed accounts and siblings,
checks passive authorization, rechecks file bytes and commits the matching slot with pool CAS. External consumers never
invoke local native refresh or OAuth; their owner must publish renewed access authorization before expiry. Managed
native refresh retains its existing expiry and precise generation-order guards.
The named home receives read permission for its auth file only. The gateway never writes either credential file. Native daemon adoption and relay ownership remain separate watchdog operations: a file proves the pool's local source, not the running daemon's auth mode. Initial managed-to-external native migration changes relay ownership; subsequent same-user/workspace renewal must preserve it. A missing, stale or mismatched publication defers with an owner error rather than switching accounts or rotating a donor. Native persistent external file loading is source-confirmed for 0.162.1 but undocumented and requires separate synthetic and passive runtime acceptance. Age-order protection remains in this release, so recovery from an older peer generation is not a universal failover guarantee.
The native Codex catalog orders standard tiers from none through ultra only when projecting external provider
metadata. This is a permutation of advertised values: omitted tiers stay omitted, custom strings retain their positions,
and uploaded Codex records retain their own order and defaults. Raw external snapshots and official unversioned model
responses remain unchanged.
Reason: external provider metadata can advertise standard tiers in descending order, for example
max,xhigh,high,medium,low, reversing the native Codex scalar picker. The native client's Plan-mode preset is a
separate concern; catalog ordering does not override an effort selected for an inference request.
Validation: regression cases cover a descending standard ladder, custom tiers, and uploaded-record precedence. Live client refresh and native Plan-mode effort preservation must be verified separately.
Each DeepSeek paid hop owns a separate internal billing request id derived from the client request id and provider.
The original client correlation and request-quota reservation remain shared across the complete waterfall.
Reason: reusing one paid row let a failed Surplus attempt retain ownership of a later successful OpenLux response.
Provider request ids, terminals, spend and reconciliation must belong to the provider that produced them.
Ordinary paid routes keep their current billing identity. Existing limits and pending-billing guards still apply.
Reversal risk: a shared paid id mixes providers and can leave successful fallback billed or reconciled as a failure.
Jev compaction and its ordinary Responses fallback share one executeInference lifetime and quota reservation.
A failed local compaction cannot release admission before the fallback provider dispatches. Settlement runs once.
Successful local compaction still releases unused request quota. Cancellation still stops before fallback.
Reason: a failed Jev attempt released the reservation, so every DeepSeek waterfall hop failed before transport.
The live compaction-marked reproduction returned 503; the same unmarked request completed through LithosAI.
Reversal risk: settling either attempt separately restores false quota failures across the entire provider chain.
The synthetic route owns its paid-hop context internally; clients cannot enable it with a request-body field.
An enabled ubiquity selection permits its configured paid hops, even when their standalone providers are unchecked.
For its exact deepseek-v4.1-flash OpenLux hop, an existing catalog row also permits native Responses dispatch.
Reason: OpenLux advertises only openai and anthropic for this model, but its native Responses endpoint completes.
A direct authenticated probe on 2026-10-10 returned HTTP 200, status: completed, and pong from that endpoint.
Ordinary routes retain their catalog and selection gates. Paid admission, accounting, and per-hop pins still apply.
Reversal risk: removing the scoped capability restores a local refusal before the working final hop can dispatch.
Admin authentication is unchanged: admin tokens, allowlist tokens, Deno Deploy tokens, and admin passkey sessions still
authenticate, and unauthenticated requests still 401. The console now has no super-admin tier: every /admin route in
src/handler/index.ts is registered without a superAdmin gate, requireSuperAdminAuth is removed, every registered
view (including Supervisor and passkey users) renders for any signed-in admin, and any authenticated admin may register
another admin passkey. The is_super_admin flag survives only where it describes the credential that authenticated
(/v1/auth reporting and API-key audit rows), never as an admin-route gate.
Reason: the owner required one admin console with no differences for super admins; the split hid Supervisor, passkey users, migration, and incident/replay tooling from working admins who operate them.
Reversal risk: removing the restriction widens the blast radius of a compromised normal admin credential to every admin action (KV migration import, incident and replay export, supervisor reads, passkey administration); restore the per-route gates if that trade stops being acceptable.
A fresh capacity observation that shows the requested quota class at 100% used with a future reset deadline is now
authoritative quota-block evidence for banked-reset routing: the account yields a blocked identity (quotaResetAtMs =
the observed reset) instead of a bare skip, and the blocked-cohort evaluator materializes the durable class block
through the same persisted path a live 429 uses before it evaluates the pool. Without a deadline the account stays
half-open as a bounded probe (claimable without a class-block deadline) so either the request serves or a fresh 429
re-arms the fences. A live stable future deadline supersedes an absent or expired prior observation for the ambiguity
gate; the durable redemption ledger still makes every quota window spend-once. Empty blocked cohorts are logged
(codex_banked_reset_preflight, reason no_blocked_identity) instead of returning silently.
Reason: production spent four weeks unable to redeem resets because capacity-only exhaustion dead-ended locally with no
dispatch path, so no fence could ever arm and stuck ambiguity could never clear (incident
docs/incident-codex-banked-reset-capacity-deadlock-2026-10-05.md).
Reversal risk: restoring the silent skip reintroduces the dead end and hides it from telemetry; treating deadline-less exhaustion as a blocked cohort fabricates an identity the claim fence cannot prove; removing the materialization step leaves evaluations that pass in memory but fail the KV fence at claim time.
Implemented: a banked-reset submission budget is one redemption per account per UTC day instead of one redemption per
UTC day across all accounts. CODEX_BANKED_RESET_MAX_PER_ACCOUNT_PER_DAY replaces the retired
CODEX_BANKED_RESET_MAX_GLOBAL_PER_DAY, which is no longer read; the parse default is 1, and live mode requires
exactly 1. The terminal-outcome provider keeps a dedicated failure reason
(terminal_outcome_account_day_limit_must_be_one); every other non-positive or non-one live value fails closed as
per_account_day_limit_invalid. Each account's budget is the durable record at
["uos_ai", "codex_reset_redemption", "account_day", "v1", account_id_hash, day], charged atomically at the same
durable submitted boundary the global record used, and refusals report account_day_limit_reached. The exact-once per
account per quota window ledger, the shadow arming gate, and the at-most-once submission semantics are unchanged. Legacy
["uos_ai", "codex_reset_redemption", "global_day", "v1", day] records are retained for rollback and never enforced, so
a nonzero legacy count cannot block any account.
Reason: the global cap made two expiring credits unusable on the same night (only one redemption was possible across all accounts).
Reversal risk: granting more than one redemption per account per day widens the worst-case credit burn if a loop fabricates distinct exhaustion episodes; deleting or enforcing the retained legacy global_day rows would break the rollback path or reintroduce cross-account blocking.
Implemented: every Codex subscription carries an "Allow overage spending" switch stored at
["uos_ai", "codex_overage_usage", "account", "v1", account_id_hash] as { allow: boolean }; an absent row is false
and no existing record is rewritten. GET/PATCH /admin/providers/codex/overage-usage and the Providers view checkbox
mirror the banked-reset settings surface. The default (false) keeps resets first: an exhausted account still routes
through the banked-reset cohort, and only when that request cannot redeem a reset (no_eligible_credit, empty or
ineligible inventory, inventory_unavailable, or the per-account daily cap) does one bounded overage probe serve the
request, logging codex_overage_served with the redemption-unavailable reason. Arming (live_armed), a completed
spend, and fence/config failures never fall back so the next request can still redeem. With the switch on, a
capacity-100% exhaustion routes directly as the bounded half-open probe while banked resets still redeem when their
gates pass. Changing the switch never calls OpenAI, never redeems, and never mutates banked-reset state. The approved
spec is docs/codex-overage-usage-toggle-spec.md.
Reason: overage spending was previously invisible and implicit, and the global cap incident showed the gateway could silently prefer the paid backup balance over an available banked reset.
Reversal risk: enabling overage by default restores silent credit spending; removing the fallback refusal reasons makes the gateway serve overage while a redeemable reset existed for the same request.
Stage 1 key administration shows effective limits and audits every key change for 90 days - 2026-10-04
The API Keys view presents request-quota and paid-overflow limits with the same explicit Unlimited checkbox in the
create form and the per-key editor. A checked box disables its numeric input, sends the existing -1 wire sentinel, and
displays no negative number; unchecking restores the last finite value (50 requests and 1 credit when the key has none).
A finite value must parse as a non-negative integer (requests) or a positive credit amount with at most six decimals, so
an empty or malformed entry is refused instead of becoming unlimited. Paid overflow stays three distinct states:
disabled, enabled with unlimited credits, and enabled with a finite cap. The existing expiry Never selector is
unchanged.
The key panel labels the effective request limit, window, used count, reset time and observation time, and the
paid-overflow section shows enablement, the window cap (or "Not enabled"), settled and reserved credits, pending
requests and the existing paid-fallback history. No new history path was added; the panel reuses
/admin/api-keys/:id/paid-fallbacks.
Every create, edit, revoke, unrevoke and delete that actually changes key state appends one compact event to
["uos_ai","api_keys","change"] in the same kv.atomic() commit as the key-state change, so an injected audit-commit
failure leaves the key unchanged and returns failure. A no-op PATCH and an unrevoke of an already-active key keep their
original success response and append no event: the contract is that a real state change cannot succeed without its audit
event, not that an idempotent call fabricates one. Deletion events are written before the purge loops and live under a
prefix the purge does not touch, so a deleted key keeps a minimal nonsecret event. An event carries a stable id,
timestamp, action, target key id, the key name, the safe changed policy fields (allowlisted: name, expiry, request
limit, window, paid-overflow enablement/limit, reset, revocation), the admin request id and the release identity. Actor
kinds distinguish an identified passkey user (principal_id = passkey user id) from the shared admin allowlist/deploy
credential, a local admin with auth disabled, and unknown; a shared credential never records a human identity. No token,
token hash, Authorization header, prompt or raw error is persisted or served.
GET /admin/api-keys/changes is an admin-only read surface (ordinary admin auth, not super-admin) returning
newest-first events with a bounded limit (default 20, maximum 50) and an opaque cursor; events carry KV TTLs of 90
days and the response reports retention_days. The reader additionally drops any event whose own at_ms is older than
90 days, because TTL expiry alone is not an exact-time visibility guarantee. Audit coverage begins at deployment: no
historical actor is reconstructed, and the UI says so.
Wire schemas, -1 sentinel semantics, paid-accounting enforcement, reservation guards and the outstanding-billing
deletion guard are unchanged.
Reason: the approved Stage 1 plan requires clear effective-limit presentation, iPhone-safe unlimited entry without negative numbers, and durable, safely attributed key-change history so an operator can see who changed a key's policy and when.
Reversal risk: re-enabling negative-number entry reintroduces the iPhone input problem and lets a malformed finite value become unlimited; moving the audit append out of the key-state commit makes a success without a durable event possible; recording tokens, hashes or shared-credential human identities would leak secrets or fabricate attribution; dropping the cursor/limit bound or the 90-day TTL makes the history unbounded.
Only the Mac gateway launcher uses the official aarch64 Deno 2.9.5 artifact in
.data/runtimes/deno/2.9.5-b5bd08edab254d42d7b05aa5b6cb4c9b8d4dede4975aff76951ce2cce18866fa/deno. Released Deno 2.9.6
and 2.9.7 split read/write permission lists without decoding doubled commas, which breaks literal comma paths in
CODEX_HOME; 2.9.5 retains that decoder. This is a service-specific compatibility rollback, not a global downgrade, and
omits the later releases' fixes. CI remains pinned to 2.9.5. The released-source comparison is retained in the issue
#812 runtime prerequisite record, with exact commits 17fadf33a8df3af9488b9f42efd1f2290d6dc7a3 (2.9.5) and
0c071246a412575e07423263404a5d13e7ed6aa2 (2.9.7).
The fixed official archive SHA-256 is b796aadd131f6930560c1ee040cf0d6f53933fbb987464e9ff46bd7ea4830615; the extracted
binary SHA-256 is b5bd08edab254d42d7b05aa5b6cb4c9b8d4dede4975aff76951ce2cce18866fa. Deployment prepares and verifies
this immutable path under the existing deployment lock before release selection or service interruption, refuses corrupt
or symlink destinations, and publishes only completed verified bytes. The launcher checks the binary again, uses it for
both the dotenv-loading task and frozen application, selects the physical release's configuration, preserves literal
native-home permissions and limits native writes to app-server-control. The application denies writes to
.data/runtimes; missing or corrupt runtime state fails closed without falling back to the global binary.
Existing synthetic proof: runtime preparation and actual disposable deploy ordering passed 14 tests in receipt
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/4fa44cf3-59d5-4fa1-9b5b-dadc5685e414; the actual
managed launcher passed all 11 native-home, configuration/lock, write-denial, failure and shutdown cases in
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/6ac18d06-c49d-438e-a398-b22be79ddd65. A disposable
native KV roundtrip seeded with 2.9.7, updated with 2.9.5 and reread with 2.9.7 preserved exact values and rejected
stale CAS, with every child and KV handle settled; its result is
.codex-worktrees/plan-issue-812-abcb41d3034/.data/issue-812/kv-compatibility/roundtrip-result.json. These proofs cover
synthetic state, not the live gateway database or service.
The normal test task adds three separate scoped Mac fixtures, retaining all existing suite segments and permissions. The
launcher matrix must execute 2.9.5, including on Linux: only its disposable runtime coordinates and checksum comparison
are substituted, and comma, symlink, absent-directory and runtime-write-denial cases remain required. Running that
matrix with 2.9.7 must report the unsupported runtime rather than skip assertions. The existing verify.sh task call
and CI test call include these fixtures without duplicate invocations or new tasks.
Status: source and focused synthetic evidence accepted for integration; committed combined verification and
whole-gateway synthetic acceptance remain required. Preparing the runtime in the canonical store or adopting it through
live deploy:mac/launchd requires the separately approved concrete rollout. This decision authorizes no global binary
or PATH change, other service downgrade, real credential mutation, live database probe, automatic upgrade, runtime
fallback or runtime-store pruning. Reversal risk: restoring the global 2.9.6/7 launcher breaks escaped native-home
paths; removing integrity checks or the runtime write denial lets the service use or alter an unverified executable.
Codex clients expose the multi-agent tools (spawn_agent, followup_task, send_message, wait_agent,
interrupt_agent, list_agents) as a single namespace tool named collaboration, and resolve a returned call by its
(namespace, name) pair. The Chat-only projection behind the DeepSeek, LithosAI, and Cerebras routes flattened
namespace groups into bare Chat function names and returned only a name, so every call for a namespaced tool reached the
client unqualified and failed as unsupported call: spawn_agent even though the tool had been delivered to the model.
Three changes to that one adapter fixed the loop, all deployed as Mac release 92493574:
ee641318stores{name, namespace}for every namespace-grouped function, not only for renamed collisions, and both response emitters writenamespaceonfunction_callitems.963f44d9projects anagent_messageinput item (author, recipient, content) onto a user turn that names both endpoints. Before this the projection rejected every input type other thanmessage, so a parent turn failed withinput item type 'agent_message' is not supportedas soon as a sub-agent answered.92493574forwards an unsealedencrypted_contentagent-message payload verbatim and marks a Fernet-shaped payload (gAAAAAprefix, at least 100 characters) as omitted. On these routes the client moves the payload text into that field in the clear, so dropping it left every sub-agent with an empty task and its own "payload arrived encrypted/unreadable" report.
Evidence on 2026-10-03, against the local Mac service: spawn_agent returns {"task_name":"/root/<name>"} from a
deepseek parent for both a deepseek child and a qwen-3.8-27b child; a deepseek worker received its task, wrote its
handoff file, and the parent read pong back from disk; separately a parent received a worker's mailbox reply pong
without any file handoff. Measured overhead: 884 ms from tool call to spawn result and 192 ms more until the child's
first turn.
Cross-backend delegation does not carry a payload (measured 2026-10-03). A parent whose model is served by the Codex
backend (gpt-6-astra, gpt-6.1-sol) emits the spawn message as a sealed Fernet token (gAAAAA...), because that
backend seals every encrypted: true tool argument and only it can open the seal. A gateway-served child therefore
receives an empty task: two deepseek-ai/DeepSeek-V4.1-Flash-ultra children of a gpt-6-astra parent reported the
assignment arrived as an unreadable blob, and neither edited a file (agent_message items carried the plaintext
envelope and a sealed encrypted_content part that this gateway correctly marks omitted). Delegation payloads survive
only when both ends are served by the same backend: gateway parent to gateway child (deepseek or qwen) works, Codex
parent to Codex child works, and a cross-backend assignment needs an out-of-band handoff. Gateway-side unsealing is not
available: forwarding the same tool schemas with the encrypted annotation removed is rejected by the Codex backend
("Invalid Value: 'tools'. Function 'collaboration.followup_task' is reserved for use by this model and must match the
configured schema."), so the annotation is enforced server-side and only a client-side change could carry a
cross-backend payload another way. The recorded convention is a file at /tmp/codex-agent-tasks/<task_name>.md written
by the parent before the spawn and read by the child first, which works because the plaintext envelope still carries the
task name and sender.
Limits recorded with the same evidence: a sealed payload from a ChatGPT-backed thread stays opaque to this gateway
because the opening key lives in that backend and the client implements no such crypto, so it is declared rather than
invented; a sub-agent receives no collaboration tools in this client build, so fan-out depth is 1; qwen-3.8-27b
rejects reasoning_effort: max (none/low/medium/high only) and its Cerebras quota can be exhausted, so an orchestrator
should retry a rate-limited child with a deepseek model; and a child is aborted when its parent session exits, so the
parent must wait for it.
To re-verify the loop, run a headless session on the orchestrator model that spawns a child, waits for it, and prints
what it received; the client-side knobs that matter are [agents] default_subagent_model and
default_subagent_reasoning_effort in ~/.codex/config.toml, where a max default serves deepseek children and is
rejected by qwen-3.8-27b. The Mac service deploys from a clean canonical checkout with deno task deploy:mac, which
snapshots HEAD into .data/releases/<sha> and restarts the launch agent; client builds are never patched.
Reason: the owner asked for deepseek orchestrators that spawn deepseek and Qwen workers through this gateway, after
spawn_agent failed with unsupported call: spawn_agent on every attempt.
Reversal risk: reverting any one change restores its exact failure (unsupported call: spawn_agent, agent_message
request rejection, or empty child tasks). If a future client seals payloads locally the gAAAAA heuristic would forward
ciphertext as text until the marker is updated.
The admin Analytics view no longer renders the "Quota forecast" (quota runway) card, and the Provider analytics card
renders only the two Codex pool accounts: the "Metered 2 refill" chart series and legend entry, the "Metered 2" and
"Metered 1" (surplus) capacity rows, the metered staleness caption note, and the client-side quota-projection fetch,
snapshot-cache restore, visible-poll refresh, and app-resume refresh are removed. The quota-projection HTTP endpoints
and src/quota-projection.ts remain for operator and backfill use, and the Metered wallet/paid-fallback surfaces in the
Defaults and Providers views are unchanged. This supersedes the 2026-10-02 "Admin Analytics quota panels refresh on a
visible poll and on app resume" decision only where it named the quota runway panel; provider health and provider
capacity keep the 30-second visible poll and the resume refresh.
Reason: the owner reported that the quota forecast and Metered 1/2 "never showed any useful info" and asked for their removal from Analytics (2026-10-03).
Reversal risk: restoring the card re-adds the fetch, cache restore, and resume hook; the removed refill series was Analytics' only rendering of the Metered wallet refill cycle, so metered wallet state is now observable only in the Defaults metered-quota panel.
GET /admin/providers/capacity serves the persisted snapshot only while it is younger than
PROVIDER_CAPACITY_READ_FRESH_MS (30 s, matching the Analytics visible poll) and otherwise awaits the existing
lease-guarded refreshProviderCapacity() probe before responding. Concurrent stale reads coalesce through the same
lease and its bounded cold wait, so one refresh serves them all and no request stacks a duplicate upstream call.
?refresh=live keeps its documented force-probe semantics. Durable history keeps its fifteen-minute bucket:
PROVIDER_CAPACITY_HISTORY_BUCKET_MS is unchanged and a same-bucket refresh overwrites that bucket's point rather than
adding one. A refresh that throws keeps the last known persisted snapshot; a refresh that reaches upstream but fails
leaves the affected source unavailable instead of reporting a fabricated percentage.
Reason: the default read was persisted-only, so the Analytics quota cards could show a fifteen-minute-bucket-old Codex percentage, or an unbounded older one on a quiet gateway, while the client already polled every 30 seconds. The displayed value therefore did not change even though the poll and render path were correct.
Reversal risk: restoring the persisted-only default read brings back the stale display; shortening the window below the poll cadence only repeats upstream probes, and making the read await an unbounded probe would reintroduce the latency the persisted-only boundary avoided. The probe itself stays read-only: usage reads with existing credentials, no OAuth refresh, inference, account, provider-selection, or quota-accounting change.
Only exact account and credential equality binds the local CLI file account to a durable native_owner in its KV pool
entry. The gateway then requests refresh from the existing native daemon, verifies its initialize.codexHome and
ChatGPT identity, and adopts the same-account persisted generation with pool CAS; it never writes auth.json or
performs its own OAuth for that owner. Uploaded sibling accounts retain their existing refresh path. Upload and repair
cannot erase the binding or replace it with stale credentials.
A changed generation requires a usable access token and nonregressing access expiry. When two native rotations share a
JWT expiry, the native owner's persisted last_refresh orders them, including its submillisecond precision. This
metadata never bootstraps ownership, and filesystem mtime never selects a credential source. Missing or mismatched
files, daemon failures and inconclusive replies refuse gateway refresh with local owner errors; they do not establish
current-credential invalidity or quota exhaustion.
The observed CLI sessions share one native daemon, whose in-process semaphore serializes refreshes. Independent native processes have no cross-process mutex; guarded reload and reuse recovery remain necessary. This change preserves CLI sign-in and sync and does not repair an external stale sync writer or change VPS credentials, service permissions or configuration.
Status: focused synthetic ownership, existing auth regressions and concurrent native CLI/gateway loopback acceptance passed. The native proof used strict HTTPS and a task-owned test CA; no real credentials were refreshed by this work.
2026-10-14: A newer expired generation may request one native-owner refresh. Adoption still requires usable tokens.
Rollback and missing order proof still refuse refresh. A revoked native chain still requires native sign-in.
Call creation resolves the authenticated principal (resolveIdempotencyPrincipal, e.g. api-key:<key_id>) and persists
it alongside the account in the codex_live_calls v1 mapping; the sideband join must present the same principal. A join
by a different valid principal, and a legacy mapping that records no principal at all, are both refused with 403 before
the WebSocket upgrade, with no permissive compatibility fallback; a reconnect by the creating principal still upgrades
and rejoins on the mapped upstream account. The mapping TTL is unchanged at one hour.
Reason: /v1/live authenticated the request but bound the call only to the upstream account, so any valid gateway
principal that learned a call id could attach to another principal's call and use the creator's upstream credentials.
Status: implemented and locally tested (focused loopback HTTP/WebSocket regression and changed-file lint, receipts
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/58ac6b41-8949-40a6-9eff-46f2de4d9bcf and
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/e08bfb68-25ca-48fd-ab60-3be8a56082aa); not deployed.
Reversal risk: dropping the principal comparison restores cross-principal sideband attachment and creator-credential
use; treating an absent principal_id as authorized would reopen it for every mapping written before this change, and
extending the TTL would lengthen that window.
The admin console's Analytics quota panels (provider health, provider capacity, and the quota runway) keep the existing
30-second visible poll, and bindForegroundRefresh now also refreshes them immediately when a resume is observed:
window focus, visibilitychange to visible, or a bfcache pageshow (event.persisted === true; the first load's
pageshow is ignored). The helper coalesces those events into one scheduled refresh and each loader returns early while
its own request is in flight, so focusing a window, returning to the tab, and restoring from bfcache cannot stack
duplicate requests or timers. The quota-projection request keeps its 30-day window and the capacity endpoint keeps
serving the persisted snapshot, so this client lifecycle change adds no upstream polling: the metered quota snapshot
still refreshes upstream only at its own METERED_QUOTA_FRESH_MS (5 minute) boundary.
Reason: Analytics is the authenticated default view, but the foreground-refresh binding only refreshed the Defaults view, so an app resumed from background or bfcache kept showing a stale quota until the next visible poll tick, which mobile background timer suspension can delay indefinitely, or until a full reload.
Reversal risk: removing the resume hook restores the stale-after-resume display; removing the pageshow initial-load
guard refreshes on every ordinary page load; adding a second interval instead of reusing the existing poll duplicates
requests.
The Codex-native catalog GET /v1/models?client_version=X.Y.Z and the normalized ["ubq_ai","codex_models"] snapshot
are built from the union of every pool account's own /codex/models answer: rows deduplicate by slug in pool order,
the first-in-pool-order row is kept verbatim, and a single configured account keeps the previous single-account response
including its conditional-request and 304 revalidation contract. Per-account catalog rows and learned account+model
rejections live in ["uos_ai","codex_account_models","v1"] as a non-secret routing hint; the operator whitelist filter
stays downstream and unchanged, so it still narrows whatever the union advertises.
A named model an account provably cannot serve — a learned rejection, or a stored catalog for the same client version
that lacks a model a sibling's same-version catalog lists — is skipped in routing without touching quota fences,
invalidating a credential, or opening an upstream-timeout circuit; unknown availability never skips. When the durable
active account is skipped for that reason and an entitled sibling exists, the ordinary election advances once with the
new transition reason model_unavailable, and when no account is entitled the gateway answers a graceful OpenAI-shaped
404 model_not_found naming the model rather than 429 or 503.
Upstream's The '<model>' model is not supported when using Codex with a ChatGPT account. 400 is the one learned
eligibility signal: that account+model pair is recorded and the request makes exactly one bounded sibling attempt
through the existing reselection machinery before falling back to the same graceful 404. Every other 400 passes through
byte-for-byte with no retry and no new state. Single-active-account admission, quota and credential fencing, and
paid-fallback authorization are otherwise unchanged.
Reason: on 2026-10-02 the catalog refresh stored one account's answer, so gpt-daybreak-blue-latest — served only by
pool account 54e77f76-... — disappeared from both the versioned catalog and the normalized snapshot, and the gateway's
own model validation rejected the client's request while its entitled account was healthy.
Reversal risk: reverting to a single account's catalog hides per-account entitlements again; treating an ineligible account as quota-exhausted or credential-invalid writes fences, unlocks paid fallback, or wedges routing; learning from any 400 other than the exact upstream shape misattributes ordinary request errors and can skip a capable account.
The Chat-only Responses routes (DeepSeek, LithosAI, Cerebras) minted synthetic item ids as ${responseId}_<kind>_<n>,
but OpenAI validates replayed item ids by their type prefix (rs, msg, fc, ctc), so a Codex thread that had
completed a DeepSeek turn failed every later gpt-6.1-sol turn with
Invalid 'input[n].id' ... Expected an ID that begins with 'fc'; a replayed synthetic reasoning item also cannot be
resolved under store: false (Item with id ... not found). The shared output builders now emit
<kind>_${responseId}_<n> (the streamed custom tool call included, so it carries the same ctc_ prefix the buffered
builder uses), and buildCodexRequest is the Codex seam that repairs an already-stored history: a replayed reasoning
item whose id matches either producer shape and carries no non-empty encrypted_content is dropped, every other
recognized synthetic id (message, function call, custom tool call) loses only its id while keeping content, order and
call_id, and genuine OpenAI ids, encrypted reasoning bytes, and the DeepSeek/LithosAI/Cerebras request bodies are
untouched. The Responses assembler now forwards the builder's repaired input to the Codex upstream and hands the
original input back to the removed-provider fallback, so only the Codex replay is repaired. Live probes: omitting one
synthetic function-call id alone returned response.completed with pong, while an unencrypted reasoning item
re-prefixed to rs_ still answered 404.
Reason: the upstream validator sees another provider's replayed history on a model switch, and a stateless
(store: false) upstream can only resolve reasoning it can decrypt; both must be repaired at the one place that builds
the Codex request.
Reversal risk: widening the drop to every reasoning item without encrypted_content would discard items a store: true
client can legitimately replay; matching ids by a loose resp_ substring would rewrite genuine ids, so only the
producer's exact <kind>_... shapes are recognized.
Apply the operator whitelist to every /uos/models/catalog row, including OpenRouter.
/models renders this feed. An empty or absent whitelist keeps the existing no-filter behavior.
Admin discovery, /v1/models, and /uos/models/capabilities retain their existing contracts.
Reason: disabled OpenRouter rows were appended after filtering and appeared on the public page.
Reversal risk: bypassing the filter again makes disabled models visible.
On 2026-10-02 the user's intent is that the enabled-model policy, the operator's model whitelist, controls what a Codex
client can select. The Codex-native versioned contract GET /v1/models?client_version=X.Y.Z therefore filters every
assembled row through that one authority, OpenRouter's dynamic rows included; neither the stored-catalog cache fast path
nor the metered fallback may serve rows past a nonempty whitelist. An absent or empty whitelist remains no filter at
all, so OpenRouter's rows still list on their own snapshot TTL without an operator re-save. Per-model metadata is
preserved verbatim; only the advertised set is narrowed. The unversioned GET /v1/models and the provider-discovery
surfaces (/uos/models/catalog, /uos/models/capabilities) keep their existing contracts unchanged, deliberately,
because the reported bug is the Codex client picker and this entry expands no policy beyond it.
Reason: the operator enabled 16 ids while Codex showed 477, because OpenRouter's rows were appended after the whitelist
on every listing surface (commit 9531d8b8, 2026-09-30) and the versioned catalog's cache fast path bypassed the filter
entirely. The versioned catalog is the one Codex selects from, and it is the seam corrected for this report; the other
surfaces were not part of the reported defect and are intentionally left as they are.
Reversal risk: appending OpenRouter rows after the filter again restores hundreds of unenabled models in the Codex picker; treating an absent or empty whitelist as "nothing enabled" hides the dynamic catalogue without an operator selection; extending this gate to the unversioned or discovery surfaces is a separate decision this entry does not authorize.
/v1/live relays call creation to the ChatGPT backend and the sideband to api.openai.com - 2026-09-30
The Codex client's realtime voice (TUI, v3/frameless) creates a WebRTC call with POST <provider-base>/live (multipart
sdp + session parts) and joins the call's control socket at wss://<ws-base>/v1/live/<call_id>. The gateway serves
both under src/live/: call creation is translated to the ChatGPT backend JSON shape at
${CODEX_BASE_URL}/realtime/calls?intent=quicksilver&architecture=avas on one eligible Codex pool account, the returned
Location is rewritten to /v1/live/<call_id>, and the creating account is mapped to that id (1 h TTL) so the sideband
rejoins on the same credentials; the sideband then bridges text frames to wss://api.openai.com/v1/live/<call_id>. The
two legs cannot share one upstream base: the ChatGPT backend rejects the multipart shape
(400 Unsupported content type), and the API host refuses subscription-created calls
(403 Voice session access denied) while accepting the sideband join with the same subscription token. SDP, ICE, and
media are passed through untouched, so WebRTC media still flows between the client and OpenAI directly.
Reason: live calls are metered on the ChatGPT backend route while the call's control socket lives on the API host; only the two-step relay keeps both legs on one account without terminating WebRTC in the gateway.
Reversal risk: pointing creation at api.openai.com/v1/live restores the 403; dropping the call-id-to-account map makes
sideband joins fail closed with 404; and a client without experimental_realtime_ws_base_url set to the gateway base
joins api.openai.com directly with the gateway's own credential and fails, so that client-side setting is part of this
deployment contract. /v1/live stays outside inference metering and admission, but its responses feed Codex provider
health/capacity.
DSH's workspace-write file sandbox permits writes only under the workspace root, /tmp, and os.tmpdir()
(writableRoots in @deepseek-ai/dsh-sandbox). GnuPG must write its homedir — trustdb.gpg, random_seed, and the
S.gpg-agent* sockets — so a signed commit from a confined shell failed with
gpg: can't connect to the gpg-agent: Operation not permitted while GNUPGHOME stayed at ~/.gnupg. Committing
therefore required a per-commit danger-full-access escalation.
~/bin/gpg-dsh is to be installed from ops/gpg-dsh.sh and set as gpg.program. Merging a change to the helper
changes no machine: the installed copy keeps its old behaviour until the owner installs the new one, so this entry
describes the repository helper, not what ~/bin/gpg-dsh runs today. The helper uses the real homedir when that is
genuinely writable (a probe file can be created there). Otherwise it signs from a homedir seeded at
$TMPDIR/dsh-gnupg-<uid>/seed from ~/.gnupg: the *.kbx and *.gpg files plus every file in private-keys-v1.d.
Interactive shells take the passthrough branch and are unaffected.
To install it, compare it with the installed helper first, diff ops/gpg-dsh.sh ~/bin/gpg-dsh, then run
install -m 0755 ops/gpg-dsh.sh ~/bin/gpg-dsh && git config --global gpg.program ~/bin/gpg-dsh. The repository helper
does not seed gpg.conf, gpg-agent.conf (for example a pinentry-program pinentry-mac line), or keyboxd's
public-keys.d. If the installed helper seeds any of these, installing over it can make sandboxed signing fail closed,
with no usable pinentry or with a public key missing under keyboxd. The first sandboxed call after an install discards
the old seed and stops its agent (added 2026-10-17, #1139).
Every seeded file invalidates the seed, not pubring.kbx alone. This entry first said the seed was refreshed only
"when pubring.kbx changes", and the installed helper compared only that file's mtime and size. Deleting a secret key
or changing its passphrase leaves pubring.kbx untouched, so the old private key stayed usable from the seed
(corrected 2026-10-16, #587). Every sandboxed call now records the name and SHA-256 digest of each seeded file and
compares that manifest with the one recorded when the seed was built. Any difference, including a deleted, added, or
re-protected private key, stops the seed's gpg-agent, discards the seed, and rebuilds it before gpg runs. The
manifest is written only after a complete copy, so an interrupted rebuild is rebuilt on the next call. The seed and
its dsh-gnupg-<uid> parent must be real directories owned by the caller and are forced to mode 0700; anything else
fails closed before gpg runs. tests/gpg-dsh.test.ts covers each trigger.
The #1141 helper changes from #1159 are combined with staged rebuilds (2026-10-18, #1168). A GnuPG configuration
file in the seed (gpg.conf or a versioned gpg.conf-<version>, gpg-agent.conf, scdaemon.conf, common.conf, or any
other top-level *.conf or *.conf-*, including dangling symlinks) invalidates the recorded manifest and stops the
seed's agent before replacing the seed. The helper never writes configuration files, so one was planted from inside
the sandbox; a planted pinentry-program could capture the passphrase at the next agent start. The seed's parent is
per user, even when TMPDIR is unset and /tmp is shared. Under the new rebuild lock, the helper also stops the agent
and removes this user's earlier $TMPDIR/dsh-gnupg/<uid> seed, rebuild locks and leftover staging/set-aside copies,
but only when this user owns the real legacy parent and copies. Do not run an older installed helper concurrently during migration.
Each manifest uses one digest process for all inputs: macOS shasum is a perl script, so one process per file added a
perl start per seeded file to every sandboxed commit. A mismatch is re-hashed under the lock before copying, and all
copies still go into the private stage, never into a published seed.
Rebuilds are serialized and published whole (added 2026-10-17, #1139). Before this, every call that found a stale
manifest stopped the agent, removed the shared seed, and rebuilt it in place, with no lock. Calls started together after
one input change deleted the seed under each other: with real GnuPG 2.4.4, 2 to 8 of every 8 concurrent signings after
an added *.gpg file exited 2. A cp that had opened a just-deleted key could also write it into a seed that another
call had already stamped with the new manifest. Now a call whose manifest matches the seed's takes no lock. Any other
call (a mismatch, a missing seed, or a leftover copy beside it) waits for <seed>.lock, a directory created with
mkdir whose owner file records the holder's pid and start time. Under the lock it checks again and re-reads the
inputs, so a burst of calls after one change rebuilds once and the others reuse that seed. The holder copies the inputs
into a private sibling (<seed>.new.XXXXXX) and records the manifest there. It then stops the seed's gpg-agent,
renames the old seed aside (<seed>.old.XXXXXX), renames the new one into place, and only then removes the old one. No
call writes into a seed that another call has published, and no call sees a partly copied seed. Leftover copies from
a killed rebuild are removed under the lock, including any nested *.new.* or *.old.* copies. The post-publication
check removes unexpected copies and fails closed if portable mv nested a stage rather than renaming it. A lock held
for 15 seconds with no live owner is treated as left by a killed holder and broken. A live slow or hung holder
retains the lock: taking it over by age alone would let that holder resume and publish alongside its replacement.
Breakers serialize on <seed>.lock.break and re-check the owner under that gate before deleting; lock creation/owner
writes and release use the same gate so
neither a blank-owner observation nor delayed cleanup can delete a fresh lock. The owner is read before sampling the
clock, and a future start time is treated as live, not stale (2026-10-18, #1168). Failed stale-lock removals return to
waiting rather than aborting the signing, and a waiter gives up (exit 2) after 60 seconds. A SIGKILL while holding
the short-lived breaker gate can leave it behind: callers time out fail-closed, and the owner must confirm no helper
is running before removing that gate. A signing that is already running from the seed when an input changes can
still fail, because the rebuild removes the old seed once the new one is in place.
Reason: the sandbox exposes no configuration hook for adding writable roots — writableRoots takes only the policy and
hard-codes the three roots — so the only durable fix inside the existing policy is to put the signing homedir where the
sandbox already allows writes. Escalating every commit instead is not a fix, and danger-full-access grants far more
than signing needs.
Reversal risk: pointing gpg.program back at the real gpg restores the denial under workspace-write; copying the
private key to a stable non-writable-root location such as ~/.local/share looks persistent but is unwritable under the
restricted policy and silently reintroduces the escalation. The seed is not trusted to disappear by itself: $TMPDIR
is not cleared at boot for every caller, and an unset TMPDIR falls back to /tmp. The manifest check on every call
is what keeps the seed from becoming a second long-lived key store. Going back to a pubring.kbx-only trigger lets a
deleted or re-protected secret key keep signing from the seed. Rebuilding in place, or without the lock, brings back
the failed concurrent signings after an input change and the window in which a deleted key survives in a seed stamped
as current. Dropping the planted-configuration check restores the pinentry-capture risk, and returning to a shared
dsh-gnupg parent breaks other users under /tmp once one user owns it.
Forwarded payloads are bounded by a declared, versioned policy, and truncation: "disabled" fails closed - 2026-09-25
The DeepSeek/Lithos translation counts every forwarded byte as text tokens. On 2026-09-24 a single 744,586-byte
view_image tool result took one session from 736,213 to 1,250,713 requested tokens against the 1,048,576-token window;
the provider rejected every later replay, including compaction, and the thread could not be resumed. The first repair
cut each payload at an undeclared 64 KiB constant. That stopgap is replaced by FORWARDED_PAYLOAD_POLICY
(deepseek-forwarded-payload/v1, one source of truth in src/deepseek/forwarded-payload-policy.ts): a versioned
per-message byte limit, advertised to Codex clients as a forwarding_policy extension on the gateway-served catalog
records, carried in the visible elision marker and the forwarding_elision operator log line, and enforced
deterministically (byte prefix plus marker inside the declared limit).
Behavior: an absent truncation field or "auto" keeps the bounded reduction, because the clients this route serves
omit the field and cannot repair a rejected history; an explicit truncation: "disabled" fails closed with HTTP 400
context_length_exceeded naming the item path, byte counts, and declared limit instead of mutating the input; any other
value is rejected with param: "truncation". This is a deliberate gateway policy, not an OpenAI guarantee: the
documented default for an absent field would reject rather than reduce.
Reversal risk: reverting to silent cutting restores unreported evidence loss; removing the bound restores the 2026-09-24
poisoning; treating an absent field as "disabled" wedges Codex clients that cannot alter their history. Residual gap:
aggregate admission (the whole rendered prompt against the model window minus the output reserve) is not implemented;
this policy bounds one message, not the sum.
The first real coverage measurement of src/ came from running all three segments of deno task test with --coverage
and merging them with deno coverage .data/cov-main .data/cov-oss .data/cov-meas --include='^file://<repo>/src/': 83.4%
lines and 82.8% branches at tip 125185c5c, with src/types.ts the only source file absent because it is type-only and
erased at runtime. Measuring one segment under-reports: tests/oss-gateway-http.test.ts runs under stripped
SURPLUS_API_KEY/METERED_API_KEY with --unstable-kv, and tests/usage-optimization-measurement.test.ts runs with
only UOS_AI_TOKEN/DENO_DEPLOY_TOKEN.
The program target is 90% for both lines and branches, and it is now met: four coverage waves took src/ from 83.4%
lines and 82.8% branches at 125185c5c to 92.15% lines and 90.10% branches, with sh scripts/verify.sh green and 2101
tests passing. That work added 21 test files plus tests/helpers/sentinel-kv-stub.ts. No gate enforces the threshold
yet; this entry records the measurement and its command so a later decision can add one without re-deriving either.
sentinel went from 58.0% to 96.3% of its replay cluster by driving those modules with an in-memory KV stub, which is
required because Deno.openKv is undefined in the default test task (no --unstable-kv): a KV-backed path is reachable
in that suite only when the test passes a stub.
What is still uncovered is recorded per file in the lane handbacks and falls into four kinds, none reachable by a test
without changing production code or widening the test command's permissions: permission-denied environment reads for
keys the allowlist excludes (SENTINEL_REPLAY_KEY, the deploy-runtime slugs) plus the deny-listed
.data/codex-supervisor.json and --allow-read state-DB paths in supervisor-inventory.ts; branches unreachable by
construction, such as the deflate ciphertext ceiling, validation re-checks of values the same function just validated,
and typeof x !== "string" guards after JSON.stringify; timer-driven reservation machinery whose pending ops would
leak across tests; and fixtures that need a concurrent writer or a real WebAuthn attestation.
Two traps found while measuring. A process-wide fetch stub counts unrelated background traffic: the paid-fallback
quota refreshes schedule their own requests on timers that outlive the test that armed them (src/provider/metered.ts,
src/provider/surplus.ts), which intermittently failed tests/codex-account-routing-part3.test.ts with two dispatches
inside a zero-dispatch window, so its counters now attribute dispatches by the test's own request body. Coverage is also
not a review: the first wave needed manual repair of nine guessed expectations, for example a JSON byte length asserted
as 20 where {"model_ids":["gpt-5"]} is 23 bytes, and listKernelUsageLimits projecting a malformed acme/demo/extra
key onto a second acme/demo row because kernelPolicyRow reads only the first two key segments.
check-file/filename-naming-convention in tools/lint/eslint.config.mjs uses the built-in KEBAB_CASE naming
convention with { ignoreMiddleExtensions: true }, over **/*.{js,ts} at any depth. ignoreMiddleExtensions is
required: without it the convention rejects the dot in *.test.ts, so every test file reported.
The rule had been in this config since the ruleset was ported, but it did not enforce anything. Its naming pattern was
the ts-template default "+([-._a-z0-9])", a micromatch expression that admits _ and ., so snake_case filenames
satisfied it and the whole src/ tree passed. That pattern was never intended as kebab-case enforcement: the canonical
ubiquity/ts-template config carries the same string and uses camelCase filenames. Measured with the plugin's own
micromatch dependency, isMatch("admin_api_keys.ts", "+([-._a-z0-9])") is true, so the file passed; the plugin
strips the extension and tests the resulting basename against the KEBAB_CASE expression
+([a-z])*([a-z0-9])*(-+([a-z0-9])), which that basename does not match. Two further traps sat behind it:
eslint-plugin-check-file@3 bails out of the check when the glob key itself matches a predefined convention, and its
micromatch.capture returns the directory in capture group 0 for a nested path, so a nested file is validated against
its parent directory name rather than its basename.
The enforcement change is inseparable from the rename, because the rule is repo-wide and one unrenamed *.ts file fails
the gate. src/ is now grouped by domain - admin/, auth/, cache/, catalog/, chat/, codex/, deepseek/,
embeddings/, handler/, harmony/, kernel/, models/, paid-fallback/, provider/, sentinel/ - with genuinely
shared singletons left at the src/ root. tests/ keeps one flat directory and is only kebab-renamed, so the
../src/... depth in every test import is unchanged.
Reversal risk: this config is also where three measured, file-scoped exemptions live, and each names its target by path.
Renaming or moving a file silently orphans its exemption, and the gate then reports the suppressed rule as if the code
had regressed - which is exactly what happened here to sonarjs/function-return-type on src/models/codex-models.ts
(formerly src/codex_models.ts). When you move a file, grep this config for its path first. Widening the naming pattern
back to a character-class expression would also silently stop enforcing the convention without failing anything, so
prefer a predefined convention, or verify any custom pattern against a known-bad filename.
scripts/file-size-ratchet.ts, run by sh scripts/verify.sh, caps source files at 1000 lines and test files at 1500.
The 31 files already above their caps are grandfathered by a recorded per-file ceiling in file-size-baseline.json,
checked in at the repository root. Their ceilings were recorded with --init on 2026-09-23 at HEAD 411b3db04f.
The check fails whenever the tree and the baseline disagree: a file over its cap with no entry, a recorded file above
its recorded ceiling, a recorded file that shrank below its recorded ceiling, a recorded file that fell back within its
cap, or a recorded path with no file left. deno task size:update is the only writer; it lowers or drops ceilings and
refuses to raise one or to record a file that is over its cap. That is stricter than the ESLint max-lines rule the
flat config leaves off: a recorded ceiling tracks the file's real size, so shrinking a 14,296-line file to 12,000 must
be committed with a 12,000 ceiling before the next change can grow past it. ESLint bulk suppressions are deliberately
not used, because they count violations rather than lines and would let a file grow from 1,001 to 10,000 unchecked.
Reversal risk: deleting an entry from the baseline re-authorizes unbounded growth for that file while a verify run
would only start failing after the file passes the deleted ceiling, and disabling size:update in favor of hand edits
removes the raise-refusal. The recorded ceilings are intentionally large numbers; do not read them as targets.
LITHOS_EFFECTIVE_CONTEXT_WINDOW_PERCENT in src/provider/lithos.ts is 100, not the 95 percent reserve the other
providers keep: the direct LithosAI route advertises its full 1,048,576-token window to /v1/models and the Codex
catalog instead of a padded one. The 95 percent value would publish an effective window 52,428 tokens smaller than the
one the provider advertises, and nothing in the panel or the catalog would show that the difference is a local choice.
Reversal risk: lowering it again silently shrinks every consumer's view of this route, so change it only with a
measurement showing the upstream refuses the advertised size.
Immutable releases are pruned after a verified deploy: the newest five plus the running one - 2026-09-23
Both deploy paths unpack a full git archive of the released revision into .data/releases/<sha>, so a repeatedly
deployed checkout carried one complete copy of src, tests, docs and static per revision: 47 directories and 391
MB on the Mac, roughly 12,000 duplicate TypeScript files that every recursive search and editor walk pays for. Retention
is now enforced by the deploy itself rather than left to an operator. ops/release_retention.ts keeps the five newest
releases by mtime plus whatever .data/current resolves to, and ops/deploy-mac.ts and ops/deploy.ts call it only
after the health check proves the new release is live, so a pruning fault is reported in the JSON receipt
(releases_pruned) instead of failing a verified deployment.
Guardrails: only a directory whose name is a full 40-character Git revision is a candidate; a candidate is skipped when
it resolves outside the store, so a planted symlink cannot redirect the delete; .staging-* directories and plain files
are never touched; the running release survives even when it is the oldest directory present. deno task prune:releases
applies the same policy by hand for a checkout that predates retention, and deno task test:vps carries the retention
tests inside the verify gate.
Retention is a policy constant (RELEASE_RETENTION_KEEP = 5), not a per-invocation flag: rollback only needs recent
releases, and an operator-facing knob would be tuned ad hoc. The Mac was pruned once under the new policy (47
releases/391 MB to 5 releases/47 MB) with .data/current and the live git sha health identity unchanged; the VPS
prunes on its next deno task deploy:vps. The separate duplication in .codex-worktrees (about 90,000 TypeScript
files, mostly tools/node_modules materialized per worktree by scripts/_bootstrap.sh) is acknowledged and remains
unaddressed by this decision.
The owner authorized capturing private request contents and deleting the oldest capture-owned records when storage
grows, around a 1 GiB per-host budget. Each host therefore keeps one fixed 1 GiB budget for capture-owned encoded KV
payload (base64-expanded ciphertext chunks plus metadata/status/dedupe/index row overhead) plus in-flight charges, with
a hard record-count bound. Durable per-capture accounting rows are the source of truth and the ledger is derived
cached state: admission, publication, release, eviction, payload expiry and status admit/prune change a charge in the
same kv.atomic() commit as its row, checking both exact versionstamps. Accounting rows are timestamp-first keyed (the
oldest-first index), carry no KV TTL, and stop existing only through the atomic commit that deletes them and decrements
the ledger. Bootstrap materializes each missing legacy accounting row together with its ledger charge; cleanup of a
manifest that predates request ownership retains only its fingerprint tombstone rather than inventing an owner status.
Admission reserves in durable KV before any chunk is written. A fence-advance commit precedes each batch, and one atomic
chunk transaction checks its committed accounting-row versionstamp before writing at most twelve 48 KiB chunks (576 KiB
payload plus bounded keys/check overhead, below the 800 KiB atomic limit). Revoke or release changes that row, so a
paused transaction cannot append after capacity was reclaimed. Publish transitions reserved -> stored together with
the manifest, dedupe, request status, incident evidence and ledger; a refused admission is skipped with a visible
storage_full status instead of storing unaccounted data. Eviction claims a victim by CAS before deleting anything,
releases the charge only once its chunk prefix is provably empty, and CAS-deletes the dedupe row only when it still
references that victim's manifest key. TTL expiry is a separate reclamation path reporting expired/payload_expired
with no evicted_* increment. Capture-owned status and tombstone rows are bounded by a fixed 64 MiB reserve inside the
1 GiB (payload admissions may use at most budget - 64 MiB) and a 50,000-row bound, pruned oldest-first; a pruned
lookup reports status_not_retained. Native metadata TTL deletion is not an atomic ledger update: maintenance and
metadata pressure reconstruct those derived counters only after a complete bounded strong scan of both prefixes and a
CAS on the ledger version captured before scanning. Concurrent accounted mutations invalidate the scan; TTL deletion
during scanning can leave a conservative overcount until a later pass, without incrementing pruning history.
Pre-existing captures are counted by a resumable bootstrap that sweeps every capture-owned prefix, counts scanned
entries and fails closed on a corrupt in-scope row or an unreadable ledger, never assuming zero.
The budget deliberately does not bound the shared SQLite database, its WAL, reusable allocated pages, other namespaces,
the incident index namespace in src/sentinel/incident-outbox.ts (separate incident bookkeeping whose capture reference
rows are TTL-bound to evidence expiry), or auth/quota/usage state, and eviction never touches them. Host text logs are
separate: the Mac gateway's launchd mac.stdout.log/mac.stderr.log sizes are reported stat-only as null when
unmeasured, with an independent 1 GiB warning, and no rotation or truncation is performed by this feature. The 32 MiB
request and 4 MiB/4,096-chunk/8-attempt trace ceilings are unchanged; one derived limit module now feeds serialization,
encryption, export/decode and the offline reader so the previous mismatched 256 KiB metadata cap and reader bound cannot
disagree. The admin error-history panel shows usage, cap, eviction and skip notices from the existing capture-retention
status.
Reversal risk: reverting to unbounded growth, counting raw ciphertext instead of the encoded payload, publishing a manifest before its budget transition, letting an expired lease free budget while an unfenced writer can still append chunks, making the ledger authoritative instead of the rows, applying a ledger delta in a commit separate from its row change, releasing a charge before the chunk prefix is provably empty, evicting without a claim CAS, or letting capture-owned status metadata grow without bound would each restore silent unbounded growth, double-charge capacity or lose accounting.
POST /v1/responses answers an explicitly marked Codex compaction locally instead of dispatching a main model. The
predicate is header-only: x-codex-turn-metadata must parse as JSON with request_kind: "compaction" and
compaction.implementation: "responses" (the one enum variant verified against official Codex rust-v0.155.1). Absent,
malformed, unknown and responses_compaction_v2 markers keep the existing route; prompt text is never inspected. The
seam is inside runResponsesRoute in src/handler/terminal-route.ts, after authenticateClient and admission, so the
route keeps executeInference ownership and its terminal wrapper, and an ordinary request's body, abort signal and
provider routing are untouched.
The handler reuses the finished selection and rendering core of 0x4007/fast-jev-compaction (MIT) at
c1eab5fdbd6bde7d67f2da070116496558836884, pinned with its license and a file map in lib/jev_compaction/; the gateway
adapter is src/jev_compaction/compaction.ts. Only the library and Codex item mapping were ported; the upstream HTTP
proxy, CLI and server are not part of this gateway. One handled compaction may make several bounded Jev batches (state
ceiling 25,000 tokens, request ceiling 30,000 tokens, 30-second per-call transport bound, caller abort forwarded), and
local code renders retained text verbatim under the existing 400,000-character summary cap.
Failure is closed and local: malformed or empty input, no unpinned candidates, no measured reduction, Jev error or
timeout, partial decisions, empty or oversized summary, and cancellation each return a non-success response before any
completion is emitted, so Codex keeps its existing history. There is no main-model fallback, no account rotation, no
invented usage, and no encrypted_content. TYPESAFE_API_KEY is read lazily with Deno.env only when a recognized
compaction is handled; a missing or denied value is an explicit 503, never a startup failure. A successful local answer
carries explicit completion telemetry (setResponseCompletionTelemetry in src/openai-telemetry.ts: completed,
semantic output observed, a response.completed stream terminal, and usage counters left null), so the normal terminal
wrapper's own completion decision commits the repository reservation after delivery instead of releasing it as a stream
that ended without a completion; a failed or cancelled answer stays unmarked and releases through the same wrapper. No
main-model token, allowance, model or cost counter is fabricated either way.
Reason: the official client decides when to compact and must keep its normal history and routing; only the summary text for an explicitly marked local compaction is gateway-owned. The alternative client-side fork would need per-client maintenance and was rejected by the user.
Status: implemented and accepted as a prototype on 2026-09-22. The focused tests and the credential-free real HTTP
fixture exercise the real handler over loopback HTTP with an injected asker, including the actual completion/telemetry
settlement and the history-preserving failure path. Historically, the stock Mac Codex client 0.155.1 against the
hash-verified candidate completed one manual and one automatic compaction with real Jev, each path making one Jev API
request; the next requests carried the adopted summaries, and normal turns made zero Jev calls. The live receipt is
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/9baf75f6-b2e7-4a74-9962-e61ceb3ad0df. The current
port was additionally accepted on the installed stock Codex 0.160.0 in credential-free fake-asker mode: the real CLI
completed one manual and one automatic compaction, the next request adopted the automatic summary, an injected Jev
outage left the original history intact, normal turns invoked no Jev asker, no marked compaction reached the main-model
upstream, and the run made zero real Jev API requests and no paid API calls. Repository verification and PR/CI delivery
remain pending, and nothing here is deployed.
Reversal risk: removing the predicate restores main-model compaction dispatch, and widening it to prompt matching or to unverified metadata variants would claim requests the gateway cannot answer. Treating a Jev failure as success, or truncating kept content to force a summary, would silently replace the client's history.
Gateway reliability program: finite admission, terminal parity, deadlines, optional analytics - 2026-09-22
A finite process-resource guard now bounds terminal inference routes at 64 active requests and 128 waiting requests with
a 5-second queue bound, fair rotation across authenticated principals, and idempotent release; a permit is held from
before provider dispatch until the response body and delivery settle, and the overload refusal is a local 503
local_inference_overload with Retry-After, distinct from the 499 a cancelled caller receives. The narrow
supersession of the 2026-08-25 admission ban, and why process-resource occupancy is not upstream quota and never
advances paid tiers, is recorded in docs/provider-decision-journal.md.
Terminal truthfulness fixes carried by the same program: streamed DeepSeek Responses events now stamp a monotonic
sequence_number at the single encoder seam while keeping every output_index/content_index stable, refusal
delta/done remain answer-bearing parts, truncated streams and buffered truncations stay truthful response.incomplete
results, and the stream deadline factories now release their timers when an attempt is aborted or cleared instead of
holding a budget handle to the deadline.
Optional analytics durability boundary: only the aggregate prompt-cache analytics write is enqueued on a bounded
best-effort queue (256 entries, 256 KiB, 60-second age, 4 concurrent writes, absolute 5-second drain deadline). The
prompt-cache telemetry gate counters, admin error evidence, Sentinel replay capture and degradation, and
quota/accounting settlement stay awaited and lossless, and a stalled optional sink cannot extend or hang the terminal
handoff. Bounded shutdown is exported from serve.ts and awaited by both the Mac and VPS launchers after server work
settles and before the KV handle closes; one sanitized counter snapshot is logged when the queue existed.
Status: implemented and locally verified. On the frozen candidate at HEAD d71cf726eb3004264501671ed665692313ed72f5
plus the resolved merge and worktree changes, the registered real HTTP capture passed all three cases (repository key
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5, receipt 348beddd-498c-4eac-a8ad-1bb7bc9a180b,
13411ms) and the registered integrated capture passed together with all five module suites (receipt
64b8b95b-3e9b-41bf-b93e-188a3d6092d0, 23915ms). The deno task test command runs tests/oss-gateway-http.test.ts as
its own isolated deno test --unstable-kv process, because that suite uses a real in-memory Deno KV while the ordinary
suite keeps its established monkeypatched KV tests unchanged. Full sh scripts/verify.sh is still pending and none of
this is deployed.
Codex premature turn endings: real reproduction, and the continuation-guidance contract - 2026-09-22
The case that Codex can end a turn with an outstanding requested action is recorded here as reproduced, not inferred
from the unverified frequencies corrected below. The contract this repository now carries is: on the DeepSeek Responses
translation seam, a tool-bearing request whose mapped executable tools exist and whose tool_choice is not none gets
one short neutral continuation instruction appended to the caller's own instructions, or carried as the system message
when the caller sent none. It never forces a tool call, forbids a legitimate final answer, or claims a tool action
happened.
The reproduced pair, one real codex-cli 0.155.1 run per variant against a task-owned loopback bridge serving the
Responses wire API, same fixed cwd, same provider id, same captured native catalog, same model deepseek-flash at
effort max, and the same 16-step read-only chain prompt (receipt
591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/509ce225-f066-4bf6-af9c-fcd85739173f):
| Variant | Reads | Terminal state | Exit | Checksum |
|---|---|---|---|---|
baseline (a4d0b470) |
11 of 16 files, in order | one turn.completed, final text Step 12 of 16, reading nodes/2c/rotate-4571.snippet; last upstream call HTTP 200, finish_reason stop, zero tool calls, 20 completion tokens of an 8192 allowance, [DONE] present, no error, no truncation |
0 | absent |
| candidate (continuation guidance) | 16 of 16 files, in order | one turn.completed, one marker per successful tool result, no human confirmation and no goal auto-continuation |
0 | 3961 |
The probe's own incomplete-chain classification wins its check order, and its earlyTextOnlyStopObserved: false is a
consequence of that ordering; neither refutes the captured upstream facts above.
Scope and limits, so the claim is not overstated: this is one paired long run, so it establishes that the behaviour
occurs and that in this pair the baseline stopped while the candidate completed; that supports the reminder as a
mitigation, not a rate, a probability, a universal cure, or a causal claim from n = 1. The mechanism that makes the
model stop mid-chain is still not identified. A frozen historical replay did not reproduce the stop, and a real-Codex
phase-only A/B ended after one request for both commentary and final_answer, so changing output phase alone did not
make Codex continue. This change does not modify phase, and that phase-only test says nothing about upstream
history-phase effects. Related but non-causal measurements: the served native catalog's deepseek-flash entry has empty
base_instructions and the native client sends instructions: "" with the developer/system input text still present;
that catalog fact alone is not claimed as the cause. The vendor thinking field is now accepted on DeepSeek and
projected to reasoning_effort (PR #391, the base revision for this measurement), and that compatibility change did not
fix these premature stops.
Reversal risk: the guidance is appended to every DeepSeek tool-bearing request that permits tool use, so removing it
restores the measured baseline, while widening or rewording it can make the model prefer tool calls over a legitimate
final answer or pad otherwise ordinary agent traffic. The truthfulness, tool_choice: none, non-agent and
legitimate-final cases in tests/deepseek-responses.test.ts preserve the request and terminal contracts; they do not
detect a model's semantic preference, and the real-client controls are what check that a legitimate final answer is not
displaced.
Residual obligation: the visible behaviour above was measured against a task-owned loopback. Loopback evidence and served-release acceptance are distinct: the exact served identities, and the actual client outcomes against them, must be recorded in the release handoff, using the served-client probe beside this entry's evidence directory.
The PR #395 reminder was merged and deployed as e04f67ff. The VPS real 16-step run passed, but on the Mac the real
client stopped at 10 of 16 with final text step 11 of 16, reading nodes/7b/tally.sql, exit 0, one completed turn, and
receipt 591bceabb6cc0ae63ee09ee9914b02c17ad0b9b53f9be3f4389670cde15755a5/cb7c10e7-08d5-41b3-8e0b-e421cdaa969a. That
outcome establishes that the reminder alone is insufficient. The original paired reproduction stays recorded as
historical evidence of the baseline stop, and it must not be recast as proof that the reminder never works.
For part of that day the gateway also carried one semantic recheck on a successful, text-only stop where mapped
executable tools existed, tool_choice was automatic, the stop carried no refusal, usage was known, and positive output
remained. It ran the same model with the same tools and effort, added no wire fields or settings, buffered the recheck,
kept the first stream progressive and kept the original response identity; accepted returned tools were delivered before
the terminal event and no duplicate recheck text was emitted. The original answer was preserved on a legitimate final
answer, on no tools, and on advisory failure. The guard skipped the recheck for none, required, or named tool
choice, truncation, empty output, a refusal, no tools, an unmeasured first-leg usage, a non-finite numeric allowance,
and an exhausted known budget. A null allowance was neither a skip nor a zero budget: real Codex high/max traffic
omits max_output_tokens, so no finite original cap was requested and no provider default for those tiers has been
measured, which is why telemetry kept that allowance unknown instead of back-filling a fabricated default while the one
advisory call still proceeded, bounded at 8,192 tokens and reporting no aggregate remaining budget because none is
known. When a numeric allowance did exist, an explicit caller cap or the measured none-tier default, the recheck
subtracted the first leg's use and took min(remaining, 8192). Cancellation aborted the extra call, and there was no
second admission or reservation. One extra provider request was the cost for an eligible text-only final: input cost and
latency rose, and the output cap was min(remaining original allowance, 8192). Actual usage from both requests was
summed; missing fields stayed partial and no cache zeros were invented. Refusal metadata was preserved through provider
normalization so the guard could observe it; on this route a refusal is also rendered as an answer-bearing content part,
and the guard skipped the recheck for it.
The semantic recheck described above is retired. The user's rule is explicit: invisible inference, or an inference leak,
is never allowed. A gateway that repeats a caller's task with a hidden appended user prompt is a second generation the
requesting client never asked for, cannot see, and cannot audit, so it is not a permitted mitigation regardless of its
effect on premature stops. The implementation was removed from src/openai.ts and src/deepseek/responses.ts: no
hidden recheck prompt, no second upstream dispatch, no folding of a second generation's tools into the first response,
and no combined two-request usage accounting remain. After a successful text-only first response the gateway completes
with that provider output, and the streamed and buffered single-dispatch regression checks assert exactly one upstream
provider invocation, the original text, the first call's own measured usage, and one terminal response.
Output-budget availability is not authorization. A positive caller max_output_tokens, or a measured provider tier
default, only bounded the extra request; neither made the extra inference visible or consented. Combined accounting is
not authorization either: summing both requests' usage truthfully described a second generation that should not have
happened, and truthful bookkeeping cannot retrofit consent. Extra model work, if it is ever explicitly opted into, must
be exposed by the requesting client with an attributable, persisted visible record; the gateway must not invent that
opt-in on the client's behalf.
The previous semantic recheck's historic acceptance receipts do not prove a currently supported behavior: any receipt describing a second dispatch, a merged two-request total, or cancellation of a pending recheck records a retired operation. The historic failure evidence stays recorded, including the Mac run above, because the retained original-request reminder remains an imperfect mitigation. The premature-stop problem is not claimed to be universally fixed by this decision, and no client hook or other client-side continuation mechanism is installed by it. The deterministic gateway repair is the removal itself; a visible, officially supported client action would be a separate, authorized change.
The app-wide design is the shared token system in static/style.css, ported from the deno-universal-auth reference
contract: OS-driven light and dark, system-UI type at 14px body and 20px headings, 10px control and 14px panel radii,
44px controls, quiet shadows, and blue reserved for actions and selection.
- Palette, light:
--bg#f7f9fc,--surface#ffffff,--surface-2#f1f5f9,--surface-3#e2e8f0,--text#111827,--muted#5f6b7a,--muted-2#55606e. - Palette, dark:
--bg#09090b,--surface#141418,--surface-2#1d1d22,--surface-3#29292f,--text#f5f5f7,--muted#a1a1aa,--muted-2#8e8e99. - Light is the base block and
@media (prefers-color-scheme: dark)overrides only the palette;color-schemestays native (light dark) and no page declares a theme class, toggle, or stored preference. - Actions use
--accent#0063d1,--accent-hover#006fe6, and white--accent-ink; dark uses#0a6ae0and#0f70e0with the same white label, while the brighter--link#4da3ffand translucent--selectioncarry dark link, focus, and selected states. - The contrast repairs are deliberate: the reference's
#007aff-on-white action,#0a84ff-with-white dark label, and 1.3:1#d5dee9input border are replaced, so quiet text clears 4.5:1 and--input-border,--border-strong, and--focus-ringclear 3:1. - Page styles consume
--radius-smfor controls,--radius-lgfor panels, and--control-heightinstead of redeclaring a palette; no page adds a second alias token system. - Motion uses
--duration-fastat 140ms for press and hover feedback and--duration-medat 220ms for occasional surface changes; hover motion is gated by(hover: hover) and (pointer: fine), keyboard actions stay immediate, and reduced motion keeps short fades while dropping transforms.
Reason: the app was dark-only, with hardcoded rgba(255,255,255,...) surfaces through the shared sheet, a pinned
color-scheme: dark, and a visual contract that lived only in tests/static-assets.test.ts. Recording the tokens, the
light and dark ownership, and the contrast repairs here keeps the next page-local restyle from re-deriving a divergent
palette.
Reversal risk: a page-local :root palette, a pinned color-scheme: dark, or a light-only literal re-splits the app
and restores the measured contrast failures, and deleting the token assertions in tests/static-assets.test.ts removes
the only automated guard because no browser or screenshot check exists in the repository.
The generalized terminal-truthfulness program asked two specification questions before any stop-reason mapping could be written. Both are answered from primary OpenAI specification sources, and the merged mapping depends on the answers, so they are recorded here rather than left open in the handoff.
Q1 - the incomplete reason vocabulary. The current Responses schema defines incomplete_details.reason as exactly
max_output_tokens, max_messages, content_filter, steered, and the response status enum as
completed | failed | in_progress | cancelled | queued | incomplete. The reasoning guide states that reaching either
the context-window limit or max_output_tokens yields status: "incomplete" with
incomplete_details.reason: "max_output_tokens". Therefore output-budget exhaustion and context-window exhaustion share
max_output_tokens; no separate context reason is invented, and the mis-spelled max_tokens found in one
streaming-reference example is never emitted.
Q2 - reasoning-only output with stop reason stop. This is not a specified incompletion, so no incomplete reason
may be fabricated for it. Under this gateway's own declared route contract, a stream that accumulated no tool call, no
non-empty assistant text and no refusal is an unusable completion, and it is classified with the existing
empty_upstream_completion failure kind rather than as response.incomplete. An explicit upstream truncation or
filtering signal is an incompletion and wins over that classification.
Reason: without a recorded answer, the next provider adapter would re-derive the rule, and the two plausible readings
differ in exactly the case (reasoning-only stop) that the gateway now classifies. The reason spelling is a wire
contract, so max_output_tokens is not a stylistic choice.
Reversal risk: emitting max_tokens, inventing a context-specific reason, or reporting a reasoning-only stop as
either a clean completion or an incomplete response would each restate a fact the specification does not support, and
would silently change what clients and operators read from a terminal event.
The generalized mapping emits response.incomplete with incomplete_details.reason for a truncated generation. Whether
that is a safe change depends on how the actual Codex client reacts, which no amount of reading the gateway can settle.
It was therefore measured directly with a controlled A/B: two byte-identical Responses SSE streams that differ only in
their terminal event, served to codex-cli 0.155.1 as a configured Responses provider.
| Terminal served | Codex output | Exit | task_complete.error |
|---|---|---|---|
response.incomplete, reason max_output_tokens |
the streamed text, then stream disconnected before completion: Incomplete response returned, reason: max_output_tokens |
1 | that message |
response.completed, same text |
the streamed text, no error | 0 | none |
Each run made exactly one HTTP request to the scripted upstream, so an incomplete terminal causes neither a silent acceptance nor a retry loop.
Two consequences are recorded here so they are not re-derived:
- The mapping is safe to keep. Codex parses the incomplete terminal natively, surfaces the reason string verbatim, and fails the turn. A truncated generation therefore moves from "accepted as success with exit 0" to "reported with the reason and exit 1", which is the intended trade rather than a regression.
- The mapping is already opt-in per provider, so no filter is needed.
deepSeekFinishDispositionreaches a route only through aChatOnlyResponsesProfilethat names it; the per-upstream truncation entry below lists the sites that constructresponse.incompleteand the routes that relay it, so this mapping is not the only constructor (corrected 2026-10-16, #606). Surplus, OpenLux, OpenRouter, and the Codex upstream route through their own paths and cannot inherit it. Adding a provider inherits nothing; a provider that should use it needs its own deliberate mapping.
Reversal risk: removing the mapping restores the silent truncation, and reading a non-completed terminal as a transport failure would discard a partial answer the client can still use. Do not add a per-provider allow/deny list for this mapping on the assumption that it leaks across routes; it does not.
Residual gap: Surplus and OpenLux were not probed, so their truncation-stop behaviour remains unverified. Codex's handling of the terminal is proven; which upstreams ever emit it is not.
The correction "CORRECTION: the narration symptom counts are unverified" below withdraws the premise that motivated this work: the narration counts behind it were not reproduced and are unverified, so they cannot justify a change. In this entry, "retracted" means withdrawn as unverified, not shown to be false. It therefore matters which parts are actually running, and whether any deployed behaviour change was justified by the retracted claim.
Status update, same day: both deployments now run the program. At the time this entry was first written none of it
was deployed, and the two running releases predated every commit in it. The program was then deployed to both surfaces
at 2207a757fb6f8c362e18cbf890d59ee191d53e26, after CI passed on that exact SHA and verify: OK on the same revision:
| Deployment | Release | Identity |
|---|---|---|
VPS (production, and the public https://ai.ubq.fi route) |
2207a757fb |
vps-2207a757fb6f8c362e18cbf890d59ee191d53e26 |
Mac local (localhost:7999) |
2207a757fb |
mac-2207a757fb6f8c362e18cbf890d59ee191d53e26 |
Acceptance ran against the deployed releases, not the branch:
- the truncation reproduction returns
response.incompletewithincomplete_details.reason: "max_output_tokens"andoutput_tokens: 8192on both hosts, where it previously returnedresponse.completedwithincomplete_details: null; - three normal completions still return
status: completedwithincomplete_details: null, so it does not over-fire; - authenticated inference through the public route succeeds, and
gpt-reserveserves on both hosts.
Qualified on 2026-10-16 (#608): acceptance of this release is unverified against
AGENTS.md.AGENTS.mdaccepts a deployment only when a direct Mac-to-VPS authenticated inference request succeeds and/healthreturns the full Git SHA andvps-<full-git-sha>in both its body and identity headers. That rule was already inAGENTS.mdat2207a757fb6f8c362e18cbf890d59ee191d53e26. Neither observation is recorded for this release:
- None of the requests above is recorded as a direct Mac-to-VPS request. The truncation reproduction and the three normal completions were authenticated inference requests "on both hosts" whose route is not recorded; the one whose route is stated went through the public
https://ai.ubq.firoute. None of them shows a direct Mac-to-VPS authenticated inference request succeeding.- The identity table names each host's release and identity, but not where they were read. It does not record that the VPS
/healthreturned2207a757fb6f8c362e18cbf890d59ee191d53e26andvps-2207a757fb6f8c362e18cbf890d59ee191d53e26in both its body and identity headers.The bullets above are kept as first written. They show the fix behaving as intended on both hosts; they do not show that the release met the repository's acceptance rule. This note adds no new observation, and no recorded observation supplies them. The entry does not say how the VPS release was deployed. Had it gone through
deno task deploy:vps, that run could not have succeeded unless the loopback/healthreturned the SHA andvps-<sha>in its body and in thex-uos-git-shaandx-uos-deployment-idheaders (ops/deploy.ts:84-103at2207a757fb), and the identity in the table is thedeployment_idthat tool prints on success. So the/healthhalf is unrecorded, not shown to be unchecked; only the direct Mac-to-VPS inference half has nothing to support it (corrected 2026-10-17, #1141). Read the status line above as "deployed to both surfaces, acceptance unverified".
The retracted premise is now moot in one direction: the deployed G3 is narration-independent by construction - it fires only when a would-be completion carries no assistant text, no refusal and no tool call, so it cannot act on the retracted symptom. Worth revisiting before any future change: the changelog wording that described it as a "no tool call" guard, which reads as narration-targeted although the code does not test for that alone. (Checked 2026-10-17, #1141: the repository keeps no changelog for the gateway. The program's pull requests describe G3 by all three of its clauses (#367) or as the completion-validity check (#368, which merged the program). No record carrying that wording was found, so this entry is the only place the phrase appears.)
Prior state, retained: the two then-running releases (922c33392d on the VPS, 4176e992f5 on the Mac) preceded every
commit in the program, so at that time no production inference behaviour had changed.
No change depends on the retracted premise; only part of G3's original motivation did.
- G5 (report the effective output allowance) - independent. It is telemetry only, changes no generation behaviour,
and was justified by the provider's tier-dependent default (8,192 at
none), measured directly. - G1 (
lengthtoresponse.incomplete) - independent. It was reproduced end to end: an upstreamfinish_reason: "length"reached the client as a cleanresponse.completedwithincomplete_details: nullwhile the gateway's own telemetry recordedoutput_tokens: 8192. That demonstration does not involve narration at all. - G3 (fail closed on a degenerate completion) - partially dependent in motivation only; every clause now stands
independently. Its stated trigger is a stream about to complete "with no tool call, no non-empty assistant text and
no refusal". The no-tool-call clause was written for the narration symptom that has now been retracted. The
no-assistant-text clause stands on its own: it is what fails a reasoning-only completion, which hands the client
nothing and which the Cerebras route already failed closed for independently of any narration claim. The no-tool-call
clause is nonetheless required on its own merits, whatever motivated it. G3's trigger is the negation of the shared
completion-validity predicate,
isAnswerBearingCompletioninsrc/upstream-wire.ts, and the no-tool-call clause is that predicate'stoolCallCount > 0term: a tool call counts as answer-bearing output. Today the stream relay (src/provider/stream-relay.ts) fails a completed terminal closed only when the predicate is false, so it accepts a turn that only calls tools. Removing thetoolCallCount > 0term would fail every tool-call-only turn - an ordinary agent step - closed on every route that uses this predicate to fail closed: the stream relay (asempty_upstream_completion), the buffered DeepSeek and LithosAI Responses paths (src/deepseek/handlers.ts,src/provider/lithos-handlers.ts) and the Cerebras Responses check (src/provider/cerebras-responses.ts), the last three throughchatCompletionHasAnswerBearingOutput. The retracted narration cases carried non-empty assistant text, so they never depended on this clause. The no-refusal clause rests on the same predicate: it is the predicate's refusal term, so a non-empty refusal also counts as answer-bearing output, and removing that term would fail every refusal-only completion closed on the same routes, although a refusal is the model's answer to the request.
Reason for recording this: the correction below removes the motivation for one clause of one change, and a future reader deciding whether to deploy needs to know that the other two changes and every clause of the third stand without it: G1, G5 and G3's no-assistant-text clause on evidence that survived the retraction, and G3's no-tool-call and no-refusal clauses on the completion-validity predicate.
Reversal risk: deploying on the belief that the narration symptom is real, or reverting the whole program because its original motivation was retracted. The first is unfounded; the second discards two independently reproduced fixes.
Post-deployment follow-up (updated 2026-10-16, #608). This entry first ended with a pre-deployment next action: "if the program is to be deployed", re-derive G3's trigger from the surviving evidence alone. The program was deployed on 2026-09-21, so that next action is historical. The G3 bullet above now carries the re-derivation, and it keeps all three clauses of the deployed trigger: no tool call, no non-empty assistant text and no refusal. The no-assistant-text clause stands on the surviving evidence; the no-tool-call and no-refusal clauses rest on the completion-validity predicate, not on the unverified frequency claim (clauses named as the trigger states them, 2026-10-17, #1141). What remains after deployment:
- Before any future change to G3, describe it by its three clauses rather than as a "no tool call" guard; no changelog
or other record carrying that wording was found to revise (see above). Keep the no-tool-call and no-refusal clauses:
G3 is the negation of the shared completion-validity predicate (
isAnswerBearingCompletion), and a tool call and a refusal are each valid output. - Do not cite this entry as an accepted deployment under
AGENTS.md. The missing acceptance observations were not recorded while2207a757fbran, and both surfaces moved to3661bcfd13on 2026-09-22 (see "Buffered-terminal fix deployed to both surfaces" below).
Superseded in part on 2026-09-22. The reported counts were not reproduced and cannot be quoted as a rate. A paired real-client reproduction did observe one premature stop with outstanding work, so these unverified counts are not evidence that the behaviour is absent either. See "Codex premature turn endings: real reproduction, and the continuation-guidance contract - 2026-09-22" above. (Reworded on 2026-10-17, #1132: this note first said the counts "remain unreproducible", called them "invalid counts", and pointed to "the entry at the top of this file", which was that entry when the note was written.)
Qualified on 2026-10-16 (#603): the artifact conclusion is unverified, not established. Two comparisons below do not test the handoff's measurement as it was recorded, so they cannot show that it was an artifact. As first written, this entry was headed "CORRECTION: the narration symptom was itself a measurement artifact", and its body said the counts "are not reproducible from the recorded sessions", that "It appears to be an artifact of how the original count was taken", that "the original measurement cannot be reconstructed from the sessions it cites", that the chain of reasoning "inherits an artifact", that each reversal "propagates the artifact", and that "the defect is most likely in the counting procedure". On 2026-10-17 (#1132) the heading and those sentences were reworded to "not reproduced" and "unverified" below; the counts, tables and examples are unchanged.
- Window. The handoff scopes its counts to the 2026-09-21 13:26–13:56 UTC window. The reconciliation table below counts "the two sessions" and never states that window, so it is not a like-for-like comparison: counts over a different span are not expected to equal the windowed ones, and "no column matches" does not show that the original measurement cannot be reconstructed.
- Classifier. The handoff defines promise-narration as a trailing assistant text that matches a forward-looking phrase and ends the turn with no tool call after it. The two counterexamples below are followed by a tool call, so that classifier counts them as negatives, and the 805-of-1,053 figure measures the bare phrase match over all messages, not that classifier over turn endings. They show only that the phrase alone is not a discriminator.
No recount applying the documented classifier inside the stated window is recorded, so the 154-of-292 and 24-of-67 counts are neither reproduced nor shown to be an artifact. They remain unverified and still must not be quoted as a rate; the sampled turn endings below are examples, not a recount.
The entry below and the terminal-truthfulness handoff both rest on an observed condition: a long-running agent "frequently believes its turn completed mid-task", quantified as 154 of 292 turns in one session and 24 of 67 in another. Those reported counts were not reproduced from the recorded sessions, and are unverified. How the original count was taken may explain them, but that is not shown, and the entries that depend on them should not be cited as evidence that the behaviour is common.
The numbers do not reconcile. For the two sessions the handoff names, counting every plausible unit:
| Session | task_started |
task_complete |
assistant text messages | matching a forward-looking phrase |
|---|---|---|---|---|
sentinel |
423 | 414 | 1,053 | 805 |
oracle-free-arch-vps |
145 | 143 | 497 | 269 |
The handoff reports 292 turns / 154 narrated for sentinel and 67 / 24 for oracle. No column matches either
figure, so these whole-session counts do not reconstruct the original measurement; they apply neither its window nor
its classifier (see the qualification above), so they do not show that it cannot be reconstructed either.
The forward-looking-phrase test does not identify premature endings. Inspecting the messages it matches shows they are ordinary mid-task narration that is followed by a tool call — "Let me load the required harness policy and verify key facts in parallel", "Let me answer the ai.ubq.fi question definitively". The phrase appears in 76% of all assistant messages (805 of 1,053), which is why the test is unusable as a discriminator: it fires on normal working text, not on a malfunction.
What the turns actually look like. Reading turns to their end shows the model doing hundreds of tool calls and then
closing with a substantive summary. The 4211- and 6380-character closers on task_complete are honest completions of
long investigation work, not a model believing it finished early. Turns cluster at a median of 7 response items, with
only 3 of 13 in one sampled window exceeding 10 items.
Reason for recording this: two merged documents and six merged corrections treat this symptom as established and build on it. A future reader must know that the premise is unsupported, or the chain of reasoning above this entry inherits an unverified premise. The gateway trustworthiness findings in the handoff stand on their own evidence and are unaffected; only the claim that the symptom is frequent, and the model-versus-gateway contrast drawn from it, depend on this.
Reversal risk: quoting 154-of-292, treating forward-looking phrasing as a malfunction signal, or building any detector on that regex. Each propagates an unverified count or a phrase test that does not discriminate.
Method note: the original count was never reproduced, and whether the counting procedure or this reconciliation's choice of unit, window and classifier explains the gap is not established. Any replacement measurement must state its unit (turn, message, or item), its window, and how it decides a turn was premature, and must show that the classifier does not fire on ordinary mid-task narration.
Qualified on 2026-10-16 (#603): unconfirmed, not falsified. As first written, this entry was headed "the narration trigger is not context size", headlined "That is falsified", labelled its first measurement "The disconfirming measurement", concluded "Length alone therefore cannot be the trigger, which falsifies both" the trigger and the onset, filed both under "Does not survive" (in "What survives, and what does not"), and called the trigger "a falsified trigger". Its own time-controlled contrasts are non-significant (
p = 0.47each), the only significant contrast (p = 0.016) pools runs from different time windows (the first table's 8/28 against 0/18 gives that value), and the original effect did not replicate on its own payload (p = 0.14). That supports "unconfirmed", not "falsified": context size is not established as the trigger, and context length is not excluded as one either. Those phrases are replaced with "unconfirmed" wording below; the measurements, tables andpvalues are unchanged.
The entry below reports that context size gates narration-without-action. That is unconfirmed. It is retained for history, but the trigger section and the onset threshold must not be relied on. The reason is an external-validity failure in the experiment: every payload used to derive the curve repeated one identical filler block in every tool output, so "long context" and "degenerate repetitive context" were confounded and could not be separated.
The contrasting measurement. A second payload family was built with genuinely distinct tool outputs (20 rotating
result shapes plus per-index text, every output unique) and matched to the original on byte size and item count. Both
were run against deepseek-flash at matched effort:
| Payload | Actual input tokens | n | Narrated | Rate |
|---|---|---|---|---|
| repetitive (original) | 66,533 | 28 | 8 | 29% |
| varied (matched) | 71,295 | 18 | 0 | 0% |
The varied payload is larger than the repetitive one and narrates never. This contrast pools runs from different time windows and does not survive the interleaved control below, so it shows neither that length is the trigger nor that it is not; "context size is the trigger" and the recorded onset of "between roughly 1k and 4k" remain unconfirmed.
A controlled interleaved run, and its non-result. To separate condition from time drift, the three conditions (repetitive ~66k, varied ~71k, small ~1k) were cycled round-robin inside a single time window, eight rounds:
| Condition | Narrated in the interleaved window |
|---|---|
| repetitive ~66k | 2/8 (25%) |
| varied ~71k | 0/8 (0%) |
| small ~1k | 0/8 (0%) |
Neither contrast is significant in this design (p = 0.47 each). Pooling all batches raises the repetitive-vs-varied
contrast to p = 0.016, but that pool mixes runs from different time windows and the original effect did not replicate
across batches on its own payload (5/10, then 1/10, p = 0.14).
What survives, and what is unconfirmed.
- Unconfirmed: context size as the trigger; the onset threshold; the implication that long real sessions narrate because they are long. Real sessions are also full of varied content, so the synthetic confound may explain the original 154-of-292 observation as easily as the model does.
- Weakly survives: that some conditions produce narration at a low rate. The pooled repetitive cells total 8/28, which is not zero. Its true trigger is unidentified; repetitive content is a candidate, not an established cause.
- Survives: that
gpt-reservenever narrated on any payload at any size tested - 0 of 30 pooled across every cell run in this investigation, spanning 61k to 176k input tokens and both payload families. The model contrast is weaker than first reported, because the DeepSeek rate it is measured against fell, but it has not been contradicted (a model-and-route contrast; see the route caveat in the narration entry below).
Reason for recording at this length: the previous entry states a specific causal trigger with statistics behind it, and this repository treats that as load-bearing. Leaving an unconfirmed trigger recorded as established would be worse than the correction itself — a future reader would tune context budgets or payload shapes against a confound.
Reversal risk: acting on the size trigger, quoting the onset threshold, or treating repetitive context as a confirmed cause. Any of those propagates an experiment artifact.
Method note for the next attempt: vary payload content independently of length, and interleave conditions inside one time window. Both were missing here, and both are what caught it.
Superseded. The condition this entry measures - a model frequently believing its turn completed mid-task - was not reproduced from the sessions it cites, and its reported counts are unverified; see "CORRECTION: the narration symptom counts are unverified" above. The context-size trigger and onset threshold are separately unconfirmed. The rates here were measured on a repetitive-filler payload and must not be generalised to real sessions. The gateway trustworthiness findings in the handoff are unaffected, since they rest on their own evidence. (Reworded on 2026-10-17, #1132: this note first said the condition "is not reproducible from the sessions it cites" and "Treat every rate here as an artifact".)
Qualified on 2026-10-16 (#603). The note above first said the trigger and onset were "separately falsified"; the correction above supports only "unconfirmed". Three conclusions below are also narrowed to what this entry's data support; the measurements and tables are kept as first recorded.
- Model versus gateway. The control does not traverse the same gateway path. Explicit DeepSeek ids take the Responses-to-Chat-Completions translation (
handleDeepSeekResponses), whilegpt-reserveis a trusted Codex id (src/request-policy.ts) served on the Codex Responses path. A defect specific to the DeepSeek translation route could drop tool calls on DeepSeek and sparegpt-reserveexactly as measured, so the data show a model-and-route difference and do not clear the gateway for the DeepSeek route. "A translation or transport defect in this gateway would not spare one provider and hit the other on an identical body" is unsupported; clearing the route needs a same-path control, such as the raw DeepSeek upstream on the same high-context bodies.- Pooled rate. The six DeepSeek bands above 1k narrate 3 + 4 + 1 + 5 + 4 + 5 = 22 of 60 runs: 36.7% (37%), not the 38% recorded below. The Fisher exact
p = 0.025of the 951-token band against those 60 runs is correct.- Effort.
gpt-reservewas measured only atmediumandmax, and the DeepSeek sweep ranged from 20% to 60% across four tiers. The supported conclusion is limited to the matchedmax-versus-maxcomparison (DeepSeek 5/10 againstgpt-reserve0/10,p = 0.033): the difference persisted with effort held atmax, subject to the route caveat above. At n = 10 per cell that comparison and the sweep are underpowered, so "reasoning effort is ruled out as the cause" is unsupported; effort is neither established nor excluded as a contributor.
The investigation that produced the terminal-truthfulness work began with a model believing its turn completed mid-task: it narrates the next action in text and terminates without emitting the tool call it described. Earlier measurement could not reproduce that shape and reported the gateway as faithful (a tool call in 19 of 20 requests). That measurement was taken at a context size far below the real sessions, which is why it came back clean.
Measured with a context-size sweep. One payload family, identical tool schemas and identical conversation, varying
only the amount of prior tool history; nothing else differs between the two models except the id and the reasoning
effort. Ten runs per cell, work outstanding, classification by whether a function_call item was emitted:
| Model | Actual input tokens | n | Emitted tool call | Narrated and stopped | Rate |
|---|---|---|---|---|---|
deepseek-flash (effort max) |
951 | 10 | 10 | 0 | 0% |
deepseek-flash (effort max) |
4,400 | 10 | 7 | 3 | 30% |
deepseek-flash (effort max) |
9,003 | 10 | 6 | 4 | 40% |
deepseek-flash (effort max) |
14,186 | 10 | 9 | 1 | 10% |
deepseek-flash (effort max) |
18,787 | 10 | 5 | 5 | 50% |
deepseek-flash (effort max) |
28,558 | 10 | 6 | 4 | 40% |
deepseek-flash (effort max) |
66,533 | 10 | 5 | 5 | 50% |
gpt-reserve (effort medium) |
61,005 | 10 | 10 | 0 | 0% |
gpt-reserve (effort max) |
61,005 | 10 | 10 | 0 | 0% |
gpt-reserve (effort medium) |
175,888 | 10 | 10 | 0 | 0% |
Every run in every cell terminated response.completed; the difference is only whether a tool call accompanied it.
Two conclusions follow, and they are the reason this entry exists:
- It is a model behaviour, not a gateway defect. At the same ~66k context with the same payload, DeepSeek drops the
tool call half the time and
gpt-reservenever does — including at 175k, nearly three times the DeepSeek band. A translation or transport defect in this gateway would not spare one provider and hit the other on an identical body. - Context size is the trigger, and the onset is between roughly 1k and 4k input tokens. Fine-grained bands place it
lower than first recorded: 0% at 951 tokens, then 30% already at 4,400. Above that onset the rate is flat and noisy
across 4k-67k (30 / 40 / 10 / 50 / 40 / 50%) with no monotone trend, pooling to 38% across all bands above 1k. A
Fisher exact test of the tiny band against everything above it gives
p = 0.025. It is a step change, not a gradual degradation, and the earlier clean result was a correctly executed experiment at the wrong scale.
The real symptomatic sessions ran at a median of about 485k input tokens, far above the onset, which is consistent with 154 of 292 turns ending in narration there.
Reason: the honest scope of the merged fix depends on this distinction. The terminal work makes the outcome truthful
(response.completed carrying no tool call is reported accurately instead of being laundered), but no gateway change
can make the model emit the call it decided to describe and skip. Recording the model-versus-gateway separation, with
the control that establishes it, prevents a future reader from either re-deriving it or "fixing" the gateway for a
behaviour it does not cause.
Reversal risk: treating this as a gateway defect and adding gateway-side tool-call requirements or prose heuristics would fire on legitimate completions that end with forward-looking wording, and would misattribute an upstream model behaviour to the transport layer.
Effort is not the variable. The control was re-run at effort max, matching DeepSeek exactly on the same payload:
10 of 10 tool calls, 0% narration at the same 61,005 input tokens, identical to its medium result. So the model
difference survives effort being held constant, and reasoning effort is ruled out as the cause.
Effort does not show a detectable effect on the DeepSeek side either. The curve was swept at the ~66k band across
max, high, low and none (10 runs each): 50%, 20%, 30%, 60% narrated. Those point estimates look like a trend and
are not one — every pairwise Fisher exact comparison among the four levels is non-significant (p from 0.17 to 1.00):
| Comparison | Narrated | p |
|---|---|---|
max vs high |
5/10 vs 2/10 | 0.350 |
max vs low |
5/10 vs 3/10 | 0.650 |
max vs none |
5/10 vs 6/10 | 1.000 |
high vs low |
2/10 vs 3/10 | 1.000 |
high vs none |
2/10 vs 6/10 | 0.170 |
low vs none |
3/10 vs 6/10 | 0.370 |
The model difference, by contrast, is solid on the same data: DeepSeek pooled across effort narrated 16 of 40 (40%)
against gpt-reserve 0 of 20 (0%), Fisher exact p = 0.0005; restricted to the directly matched max-vs-max cells,
5/10 against 0/10, p = 0.033.
Reason for recording the non-result: the four DeepSeek point estimates could easily be read as "lower effort helps" or "higher effort hurts", and neither is supported. n = 10 per cell does not resolve differences of this size, so a future reader should not tune reasoning effort on the strength of those numbers.
Reversal risk: selecting or advertising a reasoning tier as a narration mitigation, or dismissing the model difference because a single-effort cell happened to look clean, would each act on noise rather than on the measured effect.
Residual limits: rates are point estimates from 10 runs per cell, and the intermediate bands are individually noisy enough that only the onset (between ~1k and ~4k) is established rather than a precise threshold. The effort sweep is underpowered to exclude a small effort effect.
Corrected on 2026-10-16 (#606): construction and relaying are separate, and the untested surface is not empty. As first written, this entry said
response.incomplete"is built at exactly one place,src/deepseek/responses.ts", that "No other provider route can emit it", and of Surplus and OpenLux that "neither can currently emit the incompletion at all, so the untested surface is empty". The gateway constructs the terminal in three translations and relays it on further routes, Surplus, OpenLux and OpenRouter included, so those two paragraphs are rewritten below. The provider table, the Cerebras reproduction and the 2026-09-22 recheck are unchanged.
The terminal-truthfulness work changes what a truncated generation reports. Whether that is safe per provider was checked provider by provider rather than assumed from one implementation, because the mapping lives inside a route.
Where the incompletion is constructed. The gateway builds a response.incomplete terminal itself in three
translations, each mapping one upstream stop-reason vocabulary on purpose:
- the shared Chat-only Responses translation:
deepSeekTerminalEnvelopeinsrc/deepseek/responses-payload.ts, used by the buffered payload and by the stream translator insrc/deepseek/responses-stream.ts.deepSeekFinishDispositionmapslengthtoincomplete_details.reason: "max_output_tokens"andcontent_filterto"content_filter", and the DeepSeek, LithosAI and Cerebras profiles insrc/deepseek/responses.tsall reuse it, so a Cerebras truncation that carries content becomesresponse.incompletewhile the reasoning-only case below still fails closed; - the Claude Chat writer,
createClaudeResponsesWriterinsrc/provider/anthropic-response-wire.ts, which maps the same two Chat reasons for Surplus's native Claude path; - the Anthropic Messages translation in
src/provider/anthropic-responses.ts, which mapsmax_tokensto"max_output_tokens"for OpenLux's native Claude path and for the Claude Code route.
Where it is relayed or mapped. relayResponsesStream in src/provider/stream-relay.ts emits the translator's
terminal and settles the request as response.incomplete when the translator's terminal kind is incomplete; the
streamed DeepSeek and LithosAI routes (src/deepseek/handlers.ts, src/provider/lithos-streams.ts) both use it. The
buffered DeepSeek, LithosAI and Cerebras Responses paths map the payload status the same way through
deepSeekTerminalTypeForPayload. The native Responses paths - Surplus, OpenLux and OpenRouter /v1/responses and the
Codex subscription - pass an upstream-authored response.incomplete through as the terminal. OpenRouter's route,
handleOpenRouterResponses in src/provider/openrouter-handlers.ts, is reached directly and as the third hop of the
DeepSeek waterfall. It streams through streamOpenRouterResponses (src/provider/openrouter-streams.ts), which wraps
proxyResponsesStream (src/responses-stream.ts) and forwards every upstream event, the terminal included, and its
buffered path returns the upstream payload unchanged, including a status: "incomplete".
A per-provider allow/deny filter would still be solving a leak that does not exist: every construction is a deliberate per-route mapping, and every relay forwards a terminal that a translator or the upstream already chose. A provider that should use the mapping still needs its own deliberate wiring.
| Provider | Reachable | Truncation behaviour |
|---|---|---|
| DeepSeek | yes | length maps to response.incomplete with incomplete_details.reason: "max_output_tokens" |
| Cerebras | yes | Reasoning-only truncation fails closed as cerebras_upstream_invalid_response (502) |
| Surplus | no | HTTP 402 insufficient_credit: "Insufficient balance to fund this request from prepaid" |
| OpenLux | no | local:insufficient_quota: "user quota is not enough" |
The Cerebras path was reproduced, not inferred. A direct probe with max_completion_tokens: 16 returned
finish_reason: "length" with the content key absent entirely and only reasoning populated (53 characters), on two
consecutive runs. That trips choiceHasNoPayload in src/provider/cerebras.ts, which rejects a choice carrying neither
content, nor a tool call, nor a refusal. Through the gateway the same request returns HTTP 502
cerebras_upstream_invalid_response, recorded in the error ledger as
chat.completions 502 cerebras_upstream_invalid_response model=gpt-oss-120b. Note that reasoning alone is deliberately
not sufficient payload: it is preserved for clients as message.reasoning, but it is not content.
Reason: this is the contrast the whole program turns on. Cerebras already refused to call a reasoning-only truncation a success while the DeepSeek route reported the equivalent outcome as a clean completion. Recording the reproduced mechanism keeps that contrast as evidence instead of as an argument.
Reversal risk: treating reasoning as payload, or reporting a reasoning-only truncation as a completed generation, would restore the silent truncation on both routes.
Residual gap, stated rather than closed. Surplus and OpenLux are blocked on external account state, so their truncation behaviour is unverified, and the untested surface is not empty. Each provider has two paths, and both can deliver the incompletion:
- Native Claude paths construct it. Surplus maps Claude Chat
lengthandcontent_filterthroughcreateClaudeResponsesWriter, and OpenLux maps Anthropicmax_tokensthroughsrc/provider/anthropic-responses.ts. Whether either upstream reports those stop reasons when it truncates is unmeasured, so neither mapping has been exercised against a real truncation. - Native Responses paths relay it. Both pass the upstream's own
/v1/responsesterminal type through, so whether a client seesresponse.incompleteon truncation depends on what that upstream sends, which is also unmeasured.
OpenRouter is reachable, but its truncation behaviour is unmeasured too: its /v1/responses route relays the upstream's
own terminal, and no probe has recorded what OpenRouter sends when a generation is cut off.
LithosAI and the Claude Code route are not in the provider table either, and no truncation probe is recorded for them;
only the routes in that table were measured. LithosAI uses the shared Chat-only construction and relays its stream
through relayResponsesStream, so whether a truncated LithosAI generation reaches the client as response.incomplete
depends on its upstream reporting length, which is unmeasured. The Claude Code route builds the terminal through the
Anthropic Messages translation in src/provider/anthropic-responses.ts, so it depends on its upstream reporting
max_tokens when it truncates, which is also unmeasured.
Probe both paths on both blocked providers, OpenRouter's /v1/responses, LithosAI and the Claude Code route before
trusting any of them, and recheck the blockers before treating them as permanent.
Recheck 2026-09-22, both blockers still hold. Surplus answers a probe on a Surplus-routed id with HTTP 402
Insufficient USDC balance: need ~$1.0000, have $0.9895 (request id 01M33CFBC7AHTBXM365KNCM28D), and the terminal
ledger records provider: "surplus", status: 402, failure_kind: "read_error". OpenLux is still not reached at all:
gpt-5.6-luna and gpt-6-astra both answer provider: "chatgpt_codex" with fallback_reason: null, because the Codex
subscription tier serves them first, so the paid tier is never exercised through those ids. The gap therefore remains
open in the same shape, and no truncation evidence was obtained for either provider. Note also that deepseek-v4-pro is
served by provider: "deepseek", not Surplus, despite the id appearing in the paid catalogue - so probing that id does
not test Surplus truncation.
The buffered DeepSeek Responses fix from PR #387 is live on both surfaces at 3661bcfd13a9c1b9056fe5dc1786bb49b18ad594,
deployed through deno task deploy:vps and deno task deploy:mac off CI-green development.
| Deployment | Release | Identity |
|---|---|---|
VPS (production, and the public https://ai.ubq.fi route) |
3661bcfd13 |
vps-3661bcfd13a9c1b9056fe5dc1786bb49b18ad594 |
Mac local (localhost:7999) |
3661bcfd13 |
mac-3661bcfd13a9c1b9056fe5dc1786bb49b18ad594 |
Acceptance ran against the deployed releases, not the branch, and covered every DeepSeek wire shape plus the subscription path:
- buffered
/v1/responsestruncation still reportsresponse.incompletewithincomplete_details.reason: "max_output_tokens"andoutput_tokens: 8192on both hosts; - three normal buffered completions per host still report
status: "completed"withincomplete_details: null, so the new guard does not over-fire; - the streamed
/v1/responsespath still reachesresponse.completedon both hosts; /v1/chat/completions(the DeepSeek Harness wire) still answersfinish_reason: "stop"with content on both hosts;gpt-reservestill serves on both hosts through the Codex subscription capacity path.
The error ledgers after deployment show no empty_upstream_completion fires on either host - the guard has not fired in
production in either direction. The only rows on the new revision are this acceptance run's own truncation
(max_output_tokens) and two deliberate 400s from a malformed probe.
sh scripts/verify.sh reported verify: OK on the merged revision before deployment. Root checkout is clean on
development, matching origin/development, with the task branches removed.
Qualified on 2026-10-17 (#1141): acceptance of this release is only partly supported against
AGENTS.md.AGENTS.mdaccepts a deployment only when a direct Mac-to-VPS authenticated inference request succeeds and/healthreturns the full Git SHA andvps-<full-git-sha>in both its body and identity headers. That rule was already inAGENTS.mdat3661bcfd13a9c1b9056fe5dc1786bb49b18ad594. This entry records neither observation:
- The
/healthhalf was checked by the deploy tool but not recorded. The VPS release went throughdeno task deploy:vps, which at3661bcfd13ranops/deploy.ts. That run could not have succeeded unless the loopbackhttp://127.0.0.1:7999/healthreturned HTTP 200 with the SHA andvps-<sha>in its body and in thex-uos-git-shaandx-uos-deployment-idheaders (ops/deploy.ts:84-103at that revision). Its output is not recorded here.- Nothing supports the direct Mac-to-VPS half. None of the requests above is recorded as a direct Mac-to-VPS request, and the entry does not state the route any of them took.
The bullets above are kept as first written. Read "live on both surfaces" above as "deployed to both surfaces, with the loopback
/healthidentity checked by the deploy tool and direct Mac-to-VPS inference unverified".
Two questions were left open when the terminal-truthfulness program was recorded: which clients actually fail closed on the terminals the gateway now emits, and exactly where the program added 5xx responses. Both are answered here from direct measurement on the merged revision, not from reading the code alone.
Codex was already measured (the 2026-09-21 A/B above): response.incomplete fails the turn with exit 1 and the
reason string verbatim. DeepSeek Harness is now measured too, because the operator uses both and the harness reaches
the gateway over a different wire.
The harness path is @deepseek-ai/dsh-llm-pi-ai -> @earendil-works/pi-ai openai-completions, and the operator's
ubiquity provider in ~/.dsh/settings.yaml is configured with api: openai-completions against
https://ai.ubq.fi/v1/. Driving that real adapter stack against a scripted upstream (not a reimplementation of it)
gives:
| Wire result the gateway emits | Harness outcome |
|---|---|
finish_reason: "stop" with reasoning and no answer |
stop with a thinking-only message; no error, no empty-content guard fires |
finish_reason: "stop" with content: "" |
stop with an empty message; no error |
finish_reason: "length" |
{ kind: "max-tokens" }, a first-class turn-end reason with its own UI notice |
So the harness is not a backstop for the gateway's completion-validity rule: it maps the wire faithfully and accepts
a degenerate stop as a success. Codex is the stricter client of the two. G3 is gateway-owned where a route implements
it, but this does not mean that G3 protects DeepSeek Chat Completions.
The DeepSeek Chat Completions route deliberately carries no gateway completion-validity guard. On the streamed route,
relayChatCompletionStream's finishStream records completion usage, settles response.completed, records success
health, and emits [DONE] without testing chatCompletionHasAnswerBearingOutput; on the buffered route,
handleDeepSeekChatCompletions uses that predicate only to mark telemetry before returning HTTP 200. A reasoning-only
or empty-content stop is therefore reported as success to the harness. If a guard is added later, the route-local
terminal seams are finishStream for streaming and the buffered handler immediately before its successful 200 response,
not the harness.
The truncated-generation path itself is unchanged for the harness. length maps to max-tokens on both the pi-ai
adapter and the vendored dsh-llm-deepseek adapter, so a truncation the gateway reports stays reported. The gap is
narrow and one-directional: degenerate completions (stop with nothing usable) are invisible to the harness.
A wire boundary worth knowing before repointing any harness route at this gateway. Capture of the pi-ai
openai-completions request shows the operator's ubiquity route sends model, messages, stream, stream_options
and store - and no thinking and no reasoning_effort, because the configured model entries declare no reasoning
capability. That traffic is accepted. The vendored dsh-llm-deepseek adapter sends thinking: { "type": "enabled" }
for any non-off effort. Correction 2026-09-22: that field is no longer rejected. PR #391 (base revision
a4d0b470) accepts the vendor's own thinking field on the DeepSeek route and projects it to reasoning_effort; it
remains outside the official OpenAI schema everywhere else, so the earlier HTTP 400
Unrecognized request argument supplied: thinking no longer describes this route's behaviour. That compatibility change
did not fix the Codex premature turn endings recorded in "Codex premature turn endings: real reproduction, and the
continuation-guidance contract - 2026-09-22", which remain a separate mechanism.
The program added no new 5xx responses. Counting every openaiError(<n>, ...) and streamErrorResponse(<n>, ...)
call in src/openai.ts between the pre-program revision 922c33392d and the merged terminal-truthfulness revision: 31
five-hundred-and-two calls before, 32 after. The one addition was made on 2026-09-22 by the follow-up below, not by the
program. The only status code the original program itself added anywhere in src/ was a single openaiError(400, ...)
for the DeepSeek thinking-mode tool_choice conflict.
Before that follow-up, the three empty_upstream_completion 502s were unchanged from their pre-program locations, and
all three were on routes that already had them:
| Site | Function | Reachable from |
|---|---|---|
src/openai.ts:1132 |
safeFailedAttemptResponse |
Codex Responses attempts (pre-commit) |
src/openai.ts:7901 |
completeChatCompletions |
the ordinary Chat Completions path |
src/openai.ts:10683 |
rejectEmptyChatCompletion |
the shared Chat preflight, not the DeepSeek branch |
The DeepSeek routes bypass rejectEmptyChatCompletion by dispatch order: both DeepSeek handlers return before the
shared preflight runs. The Responses route therefore implements G3 in its own streamed and buffered terminal seams;
DeepSeek Chat Completions deliberately does not implement a completion-validity guard and cannot inherit one from that
shared preflight.
Found while answering the two questions above, fixed by PR #387 (d7472165), and worth recording because it is the one
place the program was not applied consistently.
The streamed DeepSeek Responses path fails a degenerate completion closed. The buffered branch of the same route did
not: a stop carrying only reasoning, or only empty content, returned HTTP 200 status: "completed" with
error: null. The same logical outcome was a failure on one transport and a success on the other.
Reproduced against the real handler with a mocked upstream, before the fix:
RESPONSES streamed -> HTTP 200 | terminal: event: response.failed
RESPONSES buffered -> HTTP 200 | status: completed | error: null
After the fix the buffered branch returns the ordinary gateway 502 with the existing empty_upstream_completion code
and message. Order is preserved: the provider's own reason is read first, so a length truncation still returns
response.incomplete with incomplete_details.reason: "max_output_tokens" and is never converted into the
empty-completion failure. Only a would-be completion is measured for answer-bearing output, through the same one shared
predicate the streamed path and the Chat route consume.
Two facts about why it survived: no test exercised the non-streaming DeepSeek /v1/responses path, and the branch is
reachable in production - 10 non-streaming /v1/responses requests were served on the deployed revision 2207a757fb.
The lesson generalises: "the route is covered" is not the same claim as "every branch of the route is covered", and a
single-transport test does not establish a single-route behaviour.
Reversal risk: removing the buffered guard restores the transport-dependent success/failure split; converting an explicit truncation into the empty-completion failure would break the precedence G1 requires. Both are covered by the five-step regression test beside the existing streamed G3 test.
Four DeepSeek interpretations were compared against the provider's own first-party client
(@deepseek-ai/dsh-llm-deepseek 0.1.1-rc.2, lib/index.js SHA-256
eed9492246cc6451f060de211768d3128388046478deae7f1959de7cde56ea82) and are deliberately kept as they are. Do not "fix"
this gateway toward the vendor client on these four points; each difference serves a different contract.
- Reasoning replay scope (Delta 4). The vendor replays
reasoning_contenton every reasoned assistant turn. This gateway fills an empty string only on the tail after the lastusermessage. Probed 2026-09-21 across four history shapes: the provider accepts a lateruserturn resetting the boundary, so the narrower rule satisfies the same requirement with the smallest mutation. Widening the fill would change token accounting and cache behavior on every request. A related research claim that replay is required "from all prior turns" is contradicted by those probes and must not be used to widen the fill. - Disabling thinking (Delta 5). The vendor sends
thinking: { type: "disabled" }; this gateway sendsreasoning_effort: "none", which the provider documents as the same thing ("nonedisables thinking mode"). Probed equivalent on the response path. The vendor's form is not part of the OpenAI Chat Completions schema, and this route exists to be OpenAI-compatible, so the documented OpenAI-shaped field stays. Re-probe if the provider changes the toggle. - Usage accounting (Delta 6). The vendor subtracts cache reads because its internal convention is disjoint counts.
This gateway relays
prompt_cache_hit_tokensas the officialprompt_tokens_details.cached_tokens, which the OpenAI contract defines as a subset detail ofprompt_tokens. Subtracting here would corrupt the field's meaning for every OpenAI-compatible reader. This is the same rule as "Cache-read telemetry is reported, never defaulted" (2026-09-19). - Translation seam exists by design (Delta 9). DeepSeek now serves a native Responses endpoint (
POST /responsesandPOST /v1/responses, both HTTP 200 with a native envelope, probed 2026-09-21), so the translation layer is no longer required by a provider gap. It stays because the native endpoint is documented as stateless with several control parameters ignored and because this adapter's measuredreasoning_contentfill for tool-bearing tails is a provider requirement a native response would have to reproduce. A migration is a separate evidence-driven evaluation, not an assumed cure.
Reversal risk: reverting any of these four toward the vendor client reintroduces a contract mismatch (wider cache accounting, a non-OpenAI parameter on an OpenAI-compatible route, changed token/cache behavior on every request), or re-justifies the translator with a premise that is no longer true.
DeepSeek answers HTTP 400 Thinking mode does not support this tool_choice for tool_choice: "required" and for the
named-function form whenever thinking mode is active. Probed 2026-09-21 on POST /chat/completions at low, high,
and the omitted default, on the provider's native Responses endpoint, and in the accepting direction with
reasoning_effort: "none" and thinking: { type: "disabled" }; none and auto are accepted in every mode. The
official Chat Completions reference documents the restriction ("required and named tool choices are not supported in
thinking mode; the API returns a 400 error").
The gateway therefore rejects the incompatible combination at its own boundary on both DeepSeek request seams, with one shared predicate and an error naming both conflicting fields, instead of forwarding the request and relaying the provider's message about a parameter the gateway's own contract advertises.
Reason: a client cannot know from this gateway's advertised capabilities that a supported tool_choice combined with a
supported reasoning tier is invalid. The boundary is the only place that sees both.
Reversal risk: removing the guard restores a live client-visible 400 whose message blames the caller for a combination the gateway accepted, and re-opens the gap on both seams.
gpt-reserve is luna served under a second Codex model id the owner authorized on 2026-09-20 as a distinct model with
its own quota limit, so it is not a gateway-only alias: the requested id is passed upstream verbatim and is never
renamed to gpt-5.6-luna. It owns the reserve quota class in src/codex/account-routing.ts, so exhausting the
reserve class must not block the standard class on the same account, and standard-class exhaustion must not block
reserve. The gateway accepts the id as a known Codex model while the upstream discovery catalog still omits it, without
inventing a catalog entry.
Reason: the upstream serves the id today but its discovery catalog may lag, and whether the upstream meters reserve separately is unproven. Keeping the id verbatim and giving it its own durable bucket leaves the distinction observable instead of folding a possibly separate limit into the standard class.
Reversal risk: renaming the id upstream, folding reserve back into standard, or widening the trusted accepted-id
list beyond the owner-authorized id each removes the distinction this authorization depends on.
Relay the upstream cache-read counter when the provider publishes one; report an absent counter as unknown
(usage_telemetry_status: "partial"), never as a measured zero. DeepSeek publishes usage.prompt_cache_hit_tokens,
which this gateway relays as the official prompt_tokens_details.cached_tokens / input_tokens_details.cached_tokens
field so one reader serves either spelling.
Reason: every DeepSeek response previously hard-coded a cache read of zero, so the gateway and the Codex client both reported a 0% cache hit rate for a caching feature that was working. That default erased the measurement the user asked for and made a healthy upstream look unoptimized; a missing measurement and a measured zero are different facts and must not share one value. A reported count larger than the request's own input is impossible, so it is dropped as unknown rather than published.
Provider cache control stays unsupported for DeepSeek, and that is separate from telemetry: DeepSeek's context cache
is automatic, prefix-based, and always on, with no client-facing request to enable, disable, pin, or expire it, so the
gateway still refuses prompt_cache_options and explicit breakpoints instead of forwarding parameters the upstream
cannot honor. Absent cache control is not absent caching.
Reversal risk: defaulting an unreported cache read to zero, publishing prompt_tokens_details when the upstream
reported no counter, or gating the metric on the model's prompt_cache catalog field, each reintroduces a number the
gateway cannot stand behind.
Summary only: docs/provider-decision-journal.md owns this provider-routing decision (entry dated 2026-09-14, "Serial
subscription routing"). Exhaust one Codex subscription before advancing the provider chain; never spread ordinary
requests across subscriptions while the active one still has capacity.
For this named goal, the user excluded the offline Mac and confirmed VPS deployment. Use authenticated VPS-origin inference, superseding this delivery's Mac-only handoff requirement. Preserve exact release checks, bounded inference budget, and reset-credit safeguards.
Use Prettier width 160 and cover all tracked source, tests, scripts, benchmarks, ops, and serve.ts. Fix the full finding set, including behavior-preserving test fixes, rather than adding a suppression baseline. Leave CI unchanged for now. Preserve the existing chore/lint-stack worktree.
Decision evidence: DSH session-8d0f4b3a-9ab5-43e1-96e6-fd092c509c26, recovered during the 2026-09-13 Codex takeover.
For the recorded cleanup, delete unused p-ai-ubq-fi and ai-ubq-fi-feat-shared-admin-toke. Retain ai-ubq-fi and
ubiquity-prospector; the Prospector monorepo's own DECISIONS.md owns the latter's retention and migration decisions.
For the local-development API key only, the retained paid-deletion guard keeps created_at_ms and adds local_deletion with an exclusive owner and completed_at_ms. Admin deletion CAS-claims ownership while the revoked ID exists, checks that claim before deleting the ID, and publishes completion only after all awaited paid-state, request-log, counter and V3 usage cleanup finishes, using the same owner version and an absent-ID CAS. A known settled pre-ID refusal or failure may release only its own claim for explicit admin retry; legacy and crashed active guards remain blocked without owner stealing. Startup reprovision requires a completed local marker, no outstanding billing, pending markers, lease or remaining cleanup rows, and atomically checks the absent ID, token hash and unchanged guard while publishing the replacement and clearing only that local guard. Empty prefixes and an absent ID alone never prove completion; every nonlocal guard keeps its existing meaning.
Client catalog ETags are hashes of the final bytes served to that client, in both the fast path and the assembled path. Raw upstream ETags remain source metadata used only for upstream conditional fetches. Enrichment that changes the served body changes its client validator even when upstream metadata is unchanged; only a validator for the current served body permits a client 304 response.
For supported VPS releases, same-SHA retry uses a private atomic deployment-owned recovery receipt under the existing deploy lock, binding the candidate and previous full SHA, source archive and complete immutable tree digests, exact selectors, verified fixed listener port and known launcher/unit profile. Before ingress changes, a failed candidate restores the supported previous selector and actual listener/public identity; daemon-reload refusal restores only the selector and issues no gateway restart. After successful ingress reload, a public verification failure retains the ready candidate and ingress-applied intent for nondestructive same-SHA verification retry. Candidate bytes remain immutable, and pruning occurs only after exact loopback and public identity acceptance. Unsupported or historical root-relative launchers are refused before destructive activation. The normal deployment command must permit the verified prior loopback port, and verify/CI must provide the scoped shell and loopback capabilities required by every actual launcher fixture.
2026-10-16: A first deployment has no previous release, selector or listener to restore. If it fails before the gateway
restart, recovery removes the selector it created and records rolled_back, and the same SHA starts again. After a
restart attempt the unit can run only the candidate, so recovery leaves that candidate selected and unaccepted rather than
removing a selector that cannot stop it. The next same-SHA run resumes at ingress when the candidate serves its exact
loopback identity, and otherwise restarts only that verified selected candidate. Any other selector or phase state stays
refused. Historical restoration is no longer an open scope: historical root-relative launchers stay refused before
activation, and a Bun startup still refuses automatic rollback to a Deno release under the Bun runtime rules in
AGENTS.md.
Compaction asks Jev through the gateway's normal Jev route: the OpenRouter System One endpoint with the shared
OPENROUTER_API_KEY and default model that /v1/systemone serves with. The standalone TYPESAFE_API_KEY path is
removed; a missing OpenRouter credential is the only missing-key failure. Selection, batching, the 30-second Jev bound,
and fail-closed behavior are unchanged. The adapter's rendered-memory bound is 1.5M characters, raised from the ported
400k because text and pinned segments are never dropped or truncated and a text-heavy session can legitimately exceed
the ported value; fitting first drops additional unpinned kept results, lowest Jev keepResult first, taking the
minimal fitting prefix across re-renders, cap-forced drops count toward the reduction contract, and the request still
fails closed above the raised bound. JEV_COMPACTION_DISABLED=1 bypasses interception entirely for an operator fallback
to the ordinary provider route; it stays unset by default.
A floor-bound render - nothing left that may be dropped or truncated, so text, pinned and already dropped content alone
exceed the 1.5M-character fit target - is no longer an automatic failure. It is accepted when its token estimate (the
library's calibrated estimator) is at most 85% of the token estimate of the request input it replaces. The bound is a
ratio, so it scales with any session size and leaves the client headroom for the continuation after the adopted summary.
Accepted floors are logged with floor_bound=true, floor_tokens and input_estimate_tokens, and the response header
carries floor=1. Every other summary-too-large path is unchanged: a floor that cannot be measured or is not
sufficiently smaller than its input still fails closed with 400. The no-reduction contract still rejects a summary that
did not shrink at all.
Reason: a production VPS session with a ~1M-token context produced a 1.63M-character floor that nothing could shrink, so every compaction attempt failed closed and the session could not continue (the client retried in a loop). The fixed 1.5M cap was chosen for bounded memory, not as a client-window limit; a floor that is token-measurably smaller than the input it replaces is adoptable and is strictly better than a session that can never compact. Reversal risk: a session whose text alone is very large can now adopt a multi-megabyte memory; the input-relative ratio keeps it below the window implied by the input, and summaries that did not shrink are still refused.
A dropped tool interaction is no longer erased. renderSummary (lib/jev_compaction/codex_items.ts) now emits every call
as a provenance line - a kept call renders its input verbatim, a dropped call renders a bounded input head - and every
result as either verbatim (keep), a bounded head (drop_result), or a bounded head labelled truncated (call dropped)
(drop_call); the existing rule already keeps whole any result shorter than the truncation floor. The adapter
(src/jev_compaction/compaction.ts) measures its reduction contract and reports chars_after in the log line and
x-jev-compaction header on the rendered text, not on the decision projection, because the projection still models
erasure; the embedded [fast-jev-compaction stats] line keeps the decision projection.
Measured 2026-10-05 by the eval harness (evals/jev-compaction, offline mode with the real Jev asker on the two saved
fixtures): the tool-output-only fact the deployed renderer lost (f3 receipt UUID) survives, needles are 15/15 and 14/14,
continuation is unchanged (4/4 and 3/4, the same probe-wording miss as the deployed run), and rendered size grows by 38k
chars (f1 111,732 -> 150,085) and 53k chars (f3 ~175k -> 227,920) because each dropped stub carries a bounded head.
Supersession ambiguity is untouched by this change and needs the planned residue pass. Focused tests were updated
deliberately (the old assertions pinned erasure) and pass 11/11.
Reason: the previous policy deleted the call and its result together on drop_call, erasing the evidence layer (57% of
f1's input bytes) and making tool-only facts unrecoverable by construction. Bounded degradation keeps provenance and
identifiers at an explicit, bounded size cost without changing Jev's decisions, the fail-closed paths, or kept-content
verbatimness. Reversal risk: sessions whose dropped material dominates now retain heads and fail closed on the 1.5M-char
cap more readily; fitting still drops the lowest-relevance kept results first, and the cap failure path is unchanged.
The hybrid residue pass adds one best-effort Cerebras gpt-oss-120b call after the verbatim Jev selection: the model
compresses the memory (dedupe, supersession, prose reduction) and deterministic guards append a harvested identifier
ledger (latest occurrences first, capped) and a verbatim tail of the latest memory, so identifier retention never
depends on the model. The pass runs through the gateway's own Cerebras transport with a bounded deadline; any missing
credential, transport failure, timeout, empty or non-shrinking output keeps the pure Jev summary unchanged. The pass
runs by default with no configuration (JEV_COMPACTION_HYBRID=0 is the operator kill switch, and an injected asker seam
bypasses it for tests and diagnostics), and the accepted answer is marked hybrid=1 in the x-jev-compaction header
with hybrid/hybrid_ms in the completion log line, so a hybrid memory is always distinguishable from a verbatim one.
No client usage, model or cost counter is invented: the residue call uses the provider credential, like the Jev calls,
and the route still fails closed on every pre-existing path.
Reason: measured on the eval harness, the hybrid scored 100% needle retention on both fixtures with 4/4 continuation and
no stale-endorsement, materially better than the pure selection renderer, while staying inside the 10-second compaction
budget. Reversal risk: the summary is now partly generated prose, so a degraded residue call could in principle add text
the model invented; the guards copy every identifier mechanically, the output must be strictly smaller than the pure
render, and setting JEV_COMPACTION_HYBRID=0 restores the verbatim-only contract exactly.
ubiquity is now a selectable provider id on the admin provider picker, on equal footing with the upstream routes: the
checkbox stages, saves, reloads, and participates in check-all, invert, and the active-only filter like any other row,
and the roster row reports its catalog count and credential readiness instead of a selection-derived status. Checking it
allows the synthetic ubiquity/deepseek-v4.1-flash route, whose hop plan stays the model's fixed definition (every
configured hop in the measured order); an active selection without ubiquity switches the whole route off, so the model
leaves /v1/models, the public catalog, and the Codex catalog, and a direct request answers 503
deepseek_waterfall_unavailable without dispatching. An absent or empty selection still keeps every provider, this
route included, enabled.
Reason: the operator asked for the gateway identity to behave like every other provider instead of a display-only row,
and unchecking it must mean it is off. Reversal risk: a non-empty stored selection written before this change does not
list ubiquity, so the route stays hidden until the operator checks the new row; the empty default selection is
unaffected.
The ubiquity/deepseek-v4.1-flash synthetic waterfall now runs the cost-first economy order
["lithos","deepseek","openrouter","surplus","openlux"]. The operator chose the economy ordering priorities cost 50 /
reliability 30 / speed 20 (the prior ranking was cost 50 / speed 30 / reliability 20) and the listed per-token costs.
LithosAI Base and the DeepSeek off-peak rate are $0.15/$0.60 per 1M input/output at list price, half of OpenRouter's
$0.30/$1.20 for the same weights, so the cheaper direct routes lead and OpenRouter drops to third; Surplus and OpenLux
remain the two paid hops. The OpenLux hop is now wired to its /v1/responses endpoint through the existing
fetchMeteredResponses transport as the final fallback, instead of being excluded because the earlier chat-wire
benchmark record could not serve Responses. The paid routing layer already accepted options.allowedPaidProviders but
no production caller supplied it, so the Surplus hop could silently advance to metered; the waterfall now threads an
explicit per-hop pin through runOrdinaryResponsesTail to fetchResponsesWithPaidFallback (surplus -> ["surplus"],
openlux -> ["metered"], which is the routing layer's name for OpenLux), keeping the default [surplus, metered]
order for every other caller.
Reason: the operator asked for a cost-first order under the benchmark's stated priorities and for OpenLux to serve as the last resort rather than be skipped by a chat-only wire record, and the pin closes a live correctness gap the recon found. Reversal risk: the paid hops depend on their own tier credentials and catalog records, so a model missing from one paid catalog now fails that hop closed instead of advancing to the sibling tier within the same hop; the next hop in the waterfall still runs, and the pin only narrows one request's paid selection.
claude_code is a new selectable provider, second in roster order after codex and first for Claude models on the
request path. It speaks the native Anthropic Messages wire (https://api.anthropic.com/v1/messages) with the
subscriber's own credential through Authorization: Bearer plus anthropic-version: 2023-06-01 and
anthropic-beta: oauth-2025-04-20, and no synthesized client fingerprint. Every gate is conjunctive and deliberate: the
operator selection must keep the provider on, CLAUDE_CODE_OAUTH_TOKEN must hold a credential (v1: the documented
one-year claude setup-token token), the request principal's key id must be in CLAUDE_CODE_ALLOWED_KEY_IDS (no
wildcard, empty allowlist means nobody), and no authoritative quota window may still block. Any missing gate leaves the
request on the unchanged paid path, and a dormant tier costs no storage read. Durable exhaustion is recorded only from
the documented anthropic-ratelimit-unified-* evidence on a rejection, blocked until the upstream reset plus a margin;
a generic 429 becomes only a short local cooldown, and 401/403 never permanently label the account. The tier is off by
default: no credential and no allowlist exist in the deployment until the owner adds them.
Reason: the operator asked to add Claude Code subscription support to the gateway; the 2026-10-11 research (docs/
research/claude-code-subscription-2026-10-11.md) rates a hosted gateway serving other users on the owner's Pro/Max
credentials RED and an owner-gated proxy AMBER, so the implemented scope is strictly owner-only, fails over to the paid
waterfall on every failure, and never reuses the Codex plumbing to serve team traffic. Reversal risk: the AMBER verdict
means Anthropic has not clearly authorized this exact bridge; the owner must accept that residual account risk in
writing before live activation, and a stored provider selection written after this change must include claude_code to
keep the tier servable, exactly like every other provider.
The gateway's native-owner binding now runs on Linux with the same single canonical home as macOS (CODEX_HOME or
~/.codex). A managed-auth daemon whose active provider does not require OpenAI auth (a gateway-routed custom provider
reports requiresOpenaiAuth: false) returns no account from account/read even though it refreshes the home's ChatGPT
credentials; that exact blank reply is accepted only when it is the daemon's own shape and the home's credential file
holds the account id the pool entry was bound to. Every other reply keeps requiring a matching ChatGPT identity, and the
caller still refuses any rotation that fails to advance the persisted generation. The admin upstream health block also
reports each slot's refresh-token SHA-256 and bound native-owner home so a local watchdog can detect an unbound pool
slot that shares a refresh lineage with a credential file without seeing token material, while treating equality on a
slot bound to that same home as the expected delegation state.
Reason: the 2026-10-13 VPS auth recovery proved a gateway KV slot and the native CLI store rotated one personal lineage
until the first consumer invalidated the second (refresh_token_reused); the VPS daemon cannot name its ChatGPT account
while it routes inference through the gateway, which blocked the previous Darwin-only binding handshake. Reversal risk:
a blank-account reply from a daemon holding the wrong file account stays refused, but a same-account file swap between
bind and refresh is caught only by the generation checks; the fallback trusts the local home configured on that host,
never a remote path.
Claude subscription parity: API-key credential, workspace selection, and admin surfaces - 2026-10-15
The claude_code tier now accepts the Console-billed CLAUDE_API_KEY direction alongside the owner-gated OAuth setup
token, and it carries the operational surface the Codex subscription always had. Credential resolution is KV first and
environment second (CLAUDE_API_KEY, then CLAUDE_CODE_OAUTH_TOKEN), so the admin console can rotate a credential
without a restart; api_key credentials travel as x-api-key and OAuth tokens keep Authorization: Bearer plus
anthropic-beta: oauth-2025-04-20. An organization-scoped key that rejects the first request with the documented "not
scoped to a workspace" error triggers one workspace discovery through /v1/organizations/workspaces (preferring a
workspace named Default), cached in KV and overridable by CLAUDE_CODE_WORKSPACE_ID or an admin pin; the retry reuses
the request's single pre-transport dispatch reservation instead of claiming a second one, because the API-key usage
ledger records exactly one pre-transport dispatch per request. Billing and workspace rejections are classified from the
upstream error body into billing_blocked / workspace_not_found / workspace_required, stored with a bounded
ten-minute configuration cooldown and their sanitized message, and they never become durable quota exhaustion; a served
request clears the recorded configuration error. GET/POST/DELETE /admin/providers/claude-code/auth reads, stores
(validated against the Anthropic models listing), and clears the credential plus an optional workspace pin;
POST /admin/providers/claude-code/quota/clear drops the guards; /admin/providers, /health/upstream, and the admin
panel's Claude subscription card report credential provenance, the workspace selection, the routing gates, unified and
standard rate-limit windows, the last upstream outcome, and health. normalizeApiKeyUsageRequestV3 now derives its
provider allowlist from API_KEY_USAGE_PROVIDERS, because a claude_code dispatch row previously failed normalization
and surfaced as api_key_quota_reservation_unavailable for the paid hop that followed it.
Reason: the operator asked for Claude subscription feature parity with the Codex subscription, including admin switches,
panels, and analytics, and named CLAUDE_API_KEY as the credential to use. The Console API-key direction is the
research's documented authentication path (GREEN) where the raw OAuth bridge is only AMBER, so the owner-gated allowlist
stays in force while the credential itself becomes operator-managed and independently rotatable. Reversal risk: a
workspace pin or discovery result is advisory state that names the workspace sent as anthropic-workspace-id; a wrong
pin fails closed with the recorded workspace_not_found state until it is corrected, and the tier still falls through
to the paid routes on every rejection. The environment's own account state (no API credits in the Console organization,
an admin-only Claude Code workspace) is an account condition, not a gateway defect: the tier records the exact
upstream rejection instead of retrying it per request.
GET /admin/providers/capacity now carries a live claude block next to the Codex/metered sources, and the admin
Analytics capacity list renders it as a third row beside the two Codex subscription rows: state badge, the observed
5-hour and weekly subscription windows as remaining capacity (the upstream fraction is normalized to a percentage), and
diagnostics for credential direction, workspace, guards, standard API-key limits, and the last upstream error. The block
is computed on the admin read from the tier's own credential, workspace, guard, and quota state; it is deliberately not
written into the stored capacity snapshot, because that record is sampled on inference events and its command budget is
pinned by test. Older three-source stored records therefore stay valid and the sampler cost is unchanged.
Reason: the operator asked for Codex-grade analytics parity for the Claude subscription, and the Codex subscriptions are
read from the capacity pipeline. Reversal risk: the analytics row reflects the tier's recorded guard state, so a billing
or workspace rejection shows as unavailable with its exact upstream status and message until the operator fixes the
account and clears the guard; the row never blocks inference itself.
Native KV preparation retains its disk-backed source, Cargo home, compiler target, and logs below the operating-system temporary root rather than below the builder module checkout. The independently supplied artifact and provenance binding remains mandatory for immutable release preparation and isolated release fixtures.
Reason: a builder imported from a staged release must not add retained scratch to the published source tree or change its recorded digest. The scratch remains disk-backed; application startup still never compiles, downloads, or installs.
When the claude_code credential is an OAuth setup token (sk-ant-oat...), buildClaudeCodeRequest prepends the native
client attribution (You are Claude Code, Anthropic's official CLI for Claude.) as the first system block; Console API
keys (sk-ant-usr... / sk-ant-api...) never send it. A 12-variant probe matrix against https://api.anthropic.com on
2026-10-15 established the requirement: without the attribution every /v1/messages request answers an opaque
429 rate_limit_error (message: "Error"), while the same request with it answers 200 and carries the
anthropic-ratelimit-unified-* subscription windows; metadata.user_id and anthropic-workspace-id are not required.
Reason: the operator activated the Claude Max subscription through the documented claude setup-token flow and asked
that it serve the gateway through the existing owner-gated claude_code tier. The endpoint strips the attribution block
before generation, so it changes no request semantics; it is sent only on the credential kind the official client owns,
and no other fingerprint (device id, session id, user agent, or additional headers) is synthesized. Reversal risk: none
beyond the tier's existing fall-through - an attribution-less OAuth request fails closed into the paid waterfall, and the
attribution can be removed at its single call site if the upstream requirement changes.
Claude model discovery belongs in the same model catalog, provider counts, and whitelist surfaces as the other providers. Read the actual authenticated upstream model listing, preserve returned model identifiers, and bind cached discovery to the credential and workspace that produced it. Credential validation must not discard the discovery result, and changing credentials must not publish stale models from the prior credential. No guessed model list substitutes for discovery.
The Claude credential and workspace controls belong under its existing provider entry. Remove the separate card-claude-subscription dashboard card and its duplicated diagnostics; keep quota diagnostics in the shared Analytics capacity list and the existing Kernel summary. Preserve provider selection and credential/guard actions through the existing endpoints.
Reason: the owner reported that the Claude whitelist showed zero models and rejected the invented standalone card because it did not follow the Codex subscription UI. A live quota row and single stored credential do not establish historical-chart or multi-account-pool parity; those capabilities remain separate acceptance requirements.
A real immutable Mac startup, not an in-memory SQLite fixture, is the acceptance surface for database permissions. Grant directory data and metadata only for the literal repository root needed by cwd resolution, plus metadata only for the literal ancestors needed by native SQLite path resolution. Do not grant ancestor contents or recursive reads. The required Darwin native gate must exercise persistent KV open and a separate-process restart using its prepared binding, while retaining unrelated file, write, network, and process denials.
Codec inspection must try ordinary read-only SQLite first so it observes a live WAL. A stopped WAL-mode database without sidecars can fail that query with SQLITE_CANTOPEN; only that failure may use a closed, synchronous immutable inspection, fenced by absent WAL/SHM/journal files and unchanged precise source identity/stat metadata before and after inspection. Any sidecar, race, unsupported stat precision, legacy codec, or missing marker fails closed. Never use unrestricted immutable reads against live WAL, open an unvalidated store writable, or rewrite its journal mode to get startup past validation.
The offline converter may use an explicitly URI-enabled read-only immutable connection only for its exclusive newly copied private snapshot after source/copy hash validation and precise identity and sidecar absence checks. Its reader contract admits only parameterless statements, rejects missing-bind queries before execution, and requires exact safe-integer reads; output databases retain strict and safe-integer configuration. Ordinary read-only opens can create private WAL sidecars on Linux, so do not substitute them or delete sidecars to pass final snapshot validation. This is not permission to open the canonical source immutably or writable. Preserve stopped-source validation and canonical-path rollback receipt binding. Actual private Bun-to-Deno-to-Bun acceptance must preserve raw keys, typed values, revisions and absolute expiry; do not make Deno an ordinary test or CI runtime dependency.
Resolve enabled Claude subscription models from the same credential/workspace-bound discovery used by the shared catalog before a chat-only paid row can reject their Responses route. Preserve Codex precedence, principal eligibility, quota guards, provider selection and the operator whitelist.
Only an observed boolean capabilities.thinking.types.disabled.supported: true authorizes the native thinking: { type: "disabled" } translation of an explicit or effective none; it emits no native effort. This permission is independent of adaptive thinking and effort support, binds the exact dispatch credential/workspace/generation, and is rechecked before transport. False, missing, malformed or stale proof retains lossless refusal and never creates a none preset/default. Stale discovery keeps its recorded model IDs and error state but withdraws this permission. The Models API describes independent thinking-type flags; Haiku effort constraints make omission or a fabricated higher effort an invalid substitute for disabled thinking.
A disabled-thinking request cannot reuse that proof for an automatically discovered different workspace: retain its original workspace-required response and identity without a second attempt. Existing non-none workspace discovery and retry are unchanged; an operator can establish the intended workspace through the existing controls. This bounded correction does not add other reasoning tiers or change the user's global default.
The immutable Mac service launcher prepares a new physical mode700 temporary directory under its existing writable .data anchor after explicitly loading only the root .env, then overrides only the child SQLITE_TMPDIR. It grants no additional sandbox access, does not use a global temporary directory, and leaves the VPS environment unchanged. Cleanup follows child settlement, requires the original directory and anchor identities, preserves any changed identity with a diagnostic, and never adopts or removes retained directories from another launch.
A real same-native, same-profile synthetic spill failed with no such savepoint: denokv_atomic_write when all SQLite temporary roots were denied; binding the private directory made the identical atomic write succeed. The failed batch retained its original rows and revisions without partial quota writes. Keep that negative control, rollback checks and the successful private-path write in the required Darwin-native verifier. Do not classify this masked SQLite I/O failure as provider quota exhaustion, retry missing-savepoint blindly, replace the verified native artifact, or weaken confinement.
The owner explicitly waived the standalone Sentinel reader acceptance prerequisite for this gateway cutover. The supported first-Bun operator accepts either the unchanged strict external-reader acceptance or a separate private, expiring owner-waived record bound to the exact source, runtime, dependencies and immutable artifacts plus the recorded owner instruction. Its discriminated input, authorization digest, journal and recovery preserve which gate was used; owner-waived is never reported as external-reader acceptance. Missing, ambiguous, expired or identity-mismatched input fails before stopping the service. No environment flag silently bypasses the gate.
This exception applies only to the external Sentinel reader prerequisite. It grants no Sentinel repository or caller-write authority and does not weaken shipping CI, deployment locking, stopped-source backups, codec conversion and reverse-conversion proof, credential preservation, operating-system isolation, immutable release checks or actual client acceptance. Legacy captures remain bound to their original source.
Claude subscription state uses a durable account roster with opaque local identifiers, a stable active account and credential/workspace-bound cohorts. Backward-compatible singleton bootstrap preserves existing credentials and access restrictions; an explicit bootstrap tombstone prevents deleted accounts from reappearing from legacy environment state. A never-configured passive read does not persist an empty roster, so later intentional first environment bootstrap remains possible; any existing empty roster or explicit clear remains a durable tombstone. First bootstrap/import and explicit deletion serialize through real KV compare-and-set, while a targeted nonexistent deletion changes no state. A local account label is not verified upstream identity. Credential import does not grant principals access. Explicit stored access policy is authoritative after an intentional admin change, and account-targeted credential, workspace, selection and guarded-clear operations remain in the existing provider controls, not a standalone dashboard card.
Switching the active subscription and advancing to paid providers are separate decisions. Keep the active account across restarts, reordering and unchanged binding; change it only for explicit operator selection, removal or authoritative applicable exhaustion/current-credential invalidity. Paid continuation requires fresh, applicable, current-binding strong evidence for the entire selected eligible pool. Transient transport failures, unknown discovery, configuration rejection and upstream server errors do not prove exhaustion. Quota, health and model capability evidence belongs to its exact account/cohort; an in-flight result cannot overwrite a replacement or reblock a newly cleared guard. Advertised reasoning capabilities and native translations require actual upstream metadata, not a model-name guess.
Claude historical windows and hourly rollups are additive to the existing Codex and metered history contracts. Persist actual upstream observations through the quota writer's accepted-observation seam, registered before the first inference; cached admin reads never create samples; a lease-guarded direct usage refresh records only the actual returned observation. The source observation clock is the gateway receipt time of raw upstream headers, not a provider-issued timestamp; sampling/persistence time is separate. Preserve missing observation times as null, absent windows and gaps across staleness, cohorts and reset anchors. Bounded sampling, retention and truncation remain explicit. Claude window series share the existing Analytics chart without altering the Codex capacity denominator. Retained legacy unbound evidence is not silently relabeled as an account's history, and host-local persistence is not a claim of cross-host synchronization.
Feature parity does not justify invented upstream operations: expose only capabilities supported by the supplied credentials and actual provider contracts. A setup token without refresh material does not establish automatic refresh, a second live account has not been supplied for live failover acceptance, and local fixtures do not establish live banked-reset or redemption support.
DeepSeek's 2026-10-17 release is DeepSeek-V4.1-Flash-1017, a dated refresh of the same Flash family. The official API
keeps deepseek-flash on the latest snapshot; OpenRouter, LithosAI, Surplus, and OpenLux expose provider-owned base
aliases for the same Flash route. A synthetic name that encoded V4.1, or a gateway-side release pin that encoded a
snapshot date, would force a rename or code edit on every DeepSeek refresh.
The gateway-owned model is now ubiquity/deepseek-flash with display name Ubiquity DeepSeek Flash. The previous
ubiquity/deepseek-v4.1-flash remains accepted as a hidden compatibility alias, and saved whitelist entries migrate to
the new id. The waterfall always includes every configured provider and resolves its latest alias from the cached
provider catalogue: deepseek-flash always for the official API, an explicit ~deepseek/deepseek-flash-latest for
OpenRouter when present, and the undated base id of the newest Flash entry for LithosAI, Surplus, and OpenLux. The
static aliases are cold-start fallbacks only. No release number or snapshot date is pinned by the gateway, so a new
provider base id such as deepseek-v4.2-flash is selected automatically.
LithosAI has already republished deepseek-ai/DeepSeek-V4.1-Flash under the same base id with a new catalogue creation
instant while retaining its old -0910 snapshots, confirming that the base alias tracks the current weights. The admin
metadata-refresh button force-fetches provider catalogues, but the synthetic route never waits for or depends on a dated
catalogue row.
Reason: the operator asked for a versionless synthetic model that follows DeepSeek's frequent releases, assumes every
upstream provider will host the latest Flash route, and does not want the gateway to specify a release version or date.
Reversal risk: the provider-owned base ids must actually track the latest weights; if a provider freezes an alias, the
gateway cannot detect that from a dated row. OpenRouter's ~deepseek/deepseek-flash-latest alias must remain routable.
The paid hops use deepseek-v4.1-flash, so paid key policies keep their existing base model id rather than requiring a
new dated snapshot.
The owner requested the complete gateway in Rust/WASM on Cloudflare. The first milestone adds the separate rust/ workspace, pinned dependencies, source-derived domain types, an atomic persistence interface and the actual workers-rs fetch export; it does not replace or activate the existing backend. The foundation contract records the exact boundaries, source references, gates and missing parity. All Rust compiles run on the isolated VPS build workspace unless its recorded failure requires the authorized Mac fallback.
Keep operator provider IDs separate from transport/accounting IDs, preserve distinct administrative/routing account hashes and native-owner credential generations, and retain one original request identity across distinct paid hops. Semantic completion, API-key dispatch quota, kernel settlement, paid reconciliation and actual delivery remain independent; Workers EOF supplies no native delivery receipt and never invents success or a refund. The latest disabled-overage hard gate is unchanged. Hot coordination and retained history share atomic authority without forcing indefinite ledgers into an evicting snapshot.
The foundation refuses every unfinished route with an explicit non-success response; health is only release liveness with validated full-source identity. Full authentication, routing, durable state, native boundaries, protocol/admin parity, migration, CI and live deployment acceptance remain required for the original goal. This scoped Rust decision does not change the existing Bun runtime, locks, production service, credentials, databases, DNS or Sentinel ownership.
Before any Rust persistence or deployment, retire provisional JSON-array key identity. Every read, write, query and future migration uses the core tuple-v1:<lowercase hex> codec and its exact binary sort bytes. Preserve current source bytes/string/bigint/number/boolean distinctions, signed zeros, infinities, positive NaN and the proven negative-NaN refusal. No per-module JSON comparator, dual-codec fallback or live migration is authorized. A shared typed builder and raw validator prevent different modules from naming or ordering the same source key differently.
The additive query interface preserves pinned source selectors: prefix alone or prefix with one strict descendant start/end bound, and ranges with both bounds. Exact-prefix rows are excluded, start is inclusive and end exclusive; empty prefix is the whole-keyspace form. Pages filter absolute expiry before their limit and use opaque version/selector/direction-bound continuations. Changed limits are allowed on resume; malformed and cross-query tokens fail closed. This shared contract adds no new gateway scheduler or provider behavior, and source/runtime/deployment acceptance remains separate.
The agreed native boundary is an HTTP Rust companion reached only through a constructor-injected trusted NativeCarrier/Fetcher capability. The portable version-1 request enum permits supervisor sessions, output and brief operations; it accepts source/thread identifiers and an opaque cursor, never a caller URL, command, token or filesystem path. Fixed POST /v1/native/rpc returns a bounded typed response. A supervisor output reply carries only SupervisorFollow { source_id, thread_id, cursor }; the native companion validates the configured source and sampled session before minting it and again when POST /v1/native/follow opens the actual cancellation-aware SSE stream. A descriptor or JSON/EOF success does not establish stream acceptance.
Requests authenticate with a dedicated constructor-supplied transport identity using HMAC-SHA256 over the exact version/method/path/key-id/time/nonce/body-digest frame defined in gateway-auth/src/native.rs. The header names are x-uos-native-version, x-uos-native-key-id, x-uos-native-time-ms, x-uos-native-nonce and x-uos-native-mac. Nonces contain 32 random bytes; real clock skew is bounded to 30 seconds. The companion consumes a nonce only after valid authentication, caps live nonces at 4096 and refuses capacity rather than evicting a still-valid replay fence. RPC and follow request bodies cap at 1 MiB. Expiry cleanup is request-owned; this adds no scheduler.
The isolated real-runtime fixture uses a dedicated ephemeral transport identity and task-owned immutable source/owner registry, with real OS filesystem/network/process confinement. Provider, admin and synchronized account credentials are not reused for this channel. Access publication remains a separate fixed-owner/account/workspace, monotonic generation/native-refresh contract; a supervisor read capability cannot become arbitrary JSON-RPC or credential mutation. No live binding, secret, default endpoint, host listener, data adoption or production activation is authorized by this decision. The exact candidate carrier route, host placement and dedicated credential residence require a concrete reversible deployment patch and the controller's final activation reconciliation; source and fixture implementation proceed independently.
The explicit source-graph-v1 record encoding preserves native-source shared object and backing-buffer identity, sparse arrays, and source-supported Object/Array/Map/Set cycles. Its closed data-only graph keeps Buffer brand, validates reference kinds and view coordinates, and refuses unknown executable/accessor/class nodes and Error.cause. Json/ProfileV1/ProfileV2 remain separate unchanged contracts; ordinary profile export still refuses cycles and is not complete native capture. Identity-free tree projection is explicit and refuses to duplicate shared references. Migration, native-counter transport, source graph JSON/inverse adapters, runtime schema binding and live adoption retain their existing owners and acceptance gates.
The Rust port preserves SimpleWebAuthn server 13.2.2 certificate-path early termination after a provided self-signed issuer verifies, including an issuer that differs from the appended configured anchor. An accepted path therefore does not establish configured-anchor membership. Source-derived fixtures retain the positive unconfigured-root SafetyNet case and the negative issuer-omitted case in rust/crates/gateway-auth/tests/fixtures/webauthn-source-golden.json; the maintained verifier compatibility notes record the pinned source and its extension. A stricter terminal-anchor policy is a separately scoped owner decision, not an implicit change in this port.
Certificate revocation-list URLs remain untrusted HTTP(S) inputs after path acceptance. Fetch them with ordinary unauthenticated transport and its default redirects, without provider/admin credentials, privileged headers or the native carrier. The pinned source imposes no application timeout or byte cap on that fetch; preserve actual platform and caller constraints without inventing a numeric source bound. Trusted registration time is injected internally from AuthHost::now_ms, and neither these compatibility rules nor passing verifier fixtures authorize a new ceremony origin, RP ID, relay audience or live credential enrollment.
Enable Surplus Secret Masking for every Surplus inference POST with exactly one X-SI-Mask-Secrets: on header from the shared authenticated-header builder. This covers native Responses and native Claude Chat, streamed and buffered. The provider handles masking and restoration while the gateway retains its existing request and response contracts.
Reason: the owner requested the announced feature. Surplus can globally pause masking and forward requests without protection or a receipt, so this opt-in does not guarantee that every request is masked. The gateway does not require or parse a masking receipt.
Reversal risk: removing the header returns request-level enablement to the provider's defaults.
CI run 39168411070 passed 33 of the 45 deployment/recovery cases and began the next controlled launcher before the existing ten-minute per-file cap stopped it. The complete tests/vps-deploy-guards.test.ts file receives a bounded twenty-minute default; every other file keeps ten minutes, individual Bun test deadlines stay five minutes, and an explicit --file-timeout-ms remains capped at ten minutes and overrides the default. No case, assertion, fixture isolation or process-group settlement rule is removed.
Knip treats cloudflare.config.ts, wrangler.config.ts and tools/cloudflare/generate-types.ts as actual external-tool entry points. The configured CLI consumes the two default config exports; cf and wrangler remain pinned dependencies. Prettier excludes vendored Rust bytes and continues to own the supported first-party formats.
The owner moved all remaining Rust/WASM implementation, compilation, testing and candidate preparation to the private Mac after VPS resource failures. The one-time evidence import is complete; do not use the VPS as a build or execution fallback. Hosted GitHub CI remains a required merge gate. Keep one serialized Mac compiler lock and the recorded pinned toolchain; this changes neither production hosting nor deployment authority.
Model identifiers and reasoning controls are source UTF16 data, not necessarily Rust Unicode scalar strings. The shared data-only ModelId and JsString16 carriers retain source-permitted code units through routing, provider preparation, policy, observations and named stored control records. Ordinary wire values remain JSON strings. No replacement character, escape-text identifier, synthetic hash, fallback model or new refusal may stand in for an otherwise valid source value. Reasoning metadata does not become an incoming tier-membership allowlist.
Named record adapters opt into one finite SourceJson to PortableValue codec. Scalar-compatible records retain Json; exact UTF16 strings or object keys use the existing explicit ProfileV2 encoding. The codec preserves revision and absolute expiry without adding family policy, accepts no executable or non-JSON graph nodes, and does not reinterpret generic transaction reads or writes. Each family still validates its complete key, logical version, shape, currentness and original atomic revision fences. Private codecs, imported rows and phase data never reconstruct live authorization.
Fresh ordinary routing journals use logical version 3 and bind the canonical original request using the existing source-request-binding version-2 domain. They have no local-work extension. Legacy ordinary/extras version 1 and local-work version 2 keep their original interpretations; one shared lossless phase parser serves writers, guards and custody readers. No stored request-body transcript, new ledger, key family or lifetime is added.
The source tuple encoder intentionally gives some distinct UTF16 model strings the same physical key bytes. Paid rollup settlement retains the first stored logical label and adds usage, while each attempt retains its own model. Do not invent collision-safe keys or recover logical model labels from replacement-decoded tuple components. Named forward and latest-state inverse validators must preserve those source semantics, original raw keys, revisions and expiries.
These are source-compatibility and execution-location decisions, not final runtime acceptance. Exact combined Mac/WASM/workerd tests, hosted CI, ancestry-preserving integration and candidate evidence remain required. No native networking exception, credential import adaptation, service activation, live-state adoption, provider-credit spend or production hostname cutover is authorized by this entry.
The source-only native gateway runtime uses private constructor-bound verification and expiring current-epoch grants to bind an authenticated native identity to durable request lifetimes. API-key and independently verified kernel scopes are separately nullable; GitHub, passkey, allowlist/admin/deploy and policy-free local authentication retain their source principal identities without fabricated API keys or repositories. Permanent constructor-seeded inference capabilities are retired for migrated consumers.
Private binding and SQLite schema revision 3 accept only the new closed DTO phases within their configured authority epoch: open requestId/route/path after authentication and process permission without accounting or body metadata; reserve the applicable API and kernel families; bind immutable validated model/stream/literal reasoning once at the existing parser boundary; bind request-specific routing through a private source port before dispatch or paid exposure. API-free requests acquire no paid entitlement, and a static key policy cannot grant global unrostered/direct-hop permission. Old v2 admission DTOs and existing schema revisions fail closed; no mixed-version overload, generic remote KV, local ledger fallback or live store migration is introduced.
Current grant/context/intent/expiry and applicable raw H/scope checks remain atomic with new effects and historical permission acknowledgments. Existing request-owned terminal, kernel, billing and definite-no-fetch cleanup preserve their native meaning after key revocation; ambiguous transport start and lost acknowledgments never recreate compensation rights. Existing API/kernel/Codex/paid reducers and all legacy/private-control fixture assertions remain required.
This decision authorizes only the coherent source and synthetic fixture foundation. Real native handler/parser/provider and Worker data-plane adoption, owner selection, credentials, publication, state/scheduler migration, real renewal/spend and production/standby activation remain outside this stage. Exact-source Linux mixed acceptance and integrated CI/artifact receipts must follow the local source-ready handback before delivery.
For the private v3 incomplete-migration vector, current-H authentication retains the existing resolver's 503 server_error before any request/admission/paid effect. The old synthetic cold-capability unauthorized vector moves to that authentication phase; admin no-op/revocation and public gateway HTTP mapping are unchanged. The exact source-bound assertion amendment is retained with the foundation evidence.
A separate constructor-private retained-history verifier permits only API no-fetch release, paid no-fetch release, paid lifecycle observations without fetch/dispatch-start mutation, verified paid billing, paid deferral, and reconciliation claim/finish for existing durable original binding/principal/key/request handles. Current epoch, namespace, expiring grant, private context, intent and target scope are rechecked before effects and replay; cursors and leases also retain the exact grant and handles. It creates no principal or request lifetime and cannot authorize admission, exposure, routing, dispatch or administration. Synthetic restoration of accepted distinct historical principals preserves the all-principal key-deletion invariant while fresh same-key identities remain api-key:<keyid>.
The owner explicitly approved the isolated Mac connector and native-direct credential/profile import adaptation in this goal session. The connector may use a separate credential-free process whose OS sandbox permits outbound TCP 443 while its code fixes the provider destination to api.openai.com; this is not a claim of OS-enforced hostname restriction. The main companion retains its separate confinement and credential custody. Safe descriptor ownership, cancellation, process settlement and actual enforcement checks remain required.
Credential and refresh-bearing profile documents go directly to the trusted native receiver through the scoped admin-client adaptation, not through Cloudflare. This approval does not select an account or authorize unrelated credential rotation, bulk replacement, live database adoption or a production native service launch. Exact native/reverse-authority origin, identity residence and operational activation still require their concrete scoped reconciliation.
The owner reaffirmed Cloudflare as the Rust/WASM candidate deployment target. Implementation, compilation and local acceptance remain on this Mac; the existing exact-source CI and candidate acceptance gates still apply. Production hostname traffic cutover remains excluded. The current staged-Claude/Worker integration and defined acceptance packet precede these separately approved native implementation changes.
ExistingAccount import preparation now requires action version 2 with distinct physical native-source and access-projection generations, exact owner/source revisions and the original admin context/deadline. It reuses the existing operation and generation rows with one consumable start permit; replay or uncertain outcomes remain reconciliation-only. Legacy version-1 import rows remain lossless custody data and cannot acquire effects through defaults. Credential documents and their digests stay native-private, and native receipt recovery rechecks the original authority and exact registered-owner file custody; public credential-generation data is not durability proof.
Production mutation remains unavailable because the existing native transport does not exclude the independent credential writer. The durable writer is exercised only in isolated synthetic fixtures; production ownership exclusion, provider validation, guarded access/catalog/default publication and authentic completion remain incomplete. This records the implemented schema/lifecycle boundary, not approval of a new security or writer-exclusion design, live account selection, credential mutation or service activation. Existing scoped connector and native-direct-import approvals are unchanged.
The owner approved source-only native socket and credential-writer safety corrections. Native import keeps its existing action, start permit and unknown-outcome lifetime. The new ownership foundation verifies the actual writer UID and anchored directory metadata, rejects unanalysed ACLs through a fixed readonly Darwin inspector, and distinguishes actual owned-child settlement from a socket close, process census or available advisory lock. A native-private dirty process epoch blocks automatic recovery after uncertain settlement; it grants no import or refresh permission.
External or shared owners remain mutation-unavailable. Distinct-principal kernel denial, a protected production executable/profile, initial exclusive-owner bootstrap, actual Codex behavior under no-descendant confinement, full import publication and operational activation remain separate acceptance. This source approval does not authorize account provisioning, real credential/home access, stopping unowned clients, provider calls or service changes.
The owner selected compatible Linux execution on existing free standard GitHub Actions ARM64 infrastructure only. Cloudflare Workers remains primary; Pi is optional and cannot gate delivery. A manually requested, separately named capability probe may boot an authenticated Ubuntu ARM64 QEMU/AAVMF guest under TCG, offline-install the pinned kernel/modules, reboot and query/create/close the exact Landlock ABI9 ruleset. The probe has no guest NIC, source/home mounts or user credentials and uploads no VM images or caches. It applies no process restrictions and cannot substitute for the unchanged positive Linux native tests, their 45-second deadlines, or required normal CI. Normal push/PR/merge selection is unchanged; probe-only dispatches use distinct check names and concurrency and cannot count as a successful required validation or deployment. Real guest success and exact-source native acceptance remain separate gates; no provider spend, paid runner, architecture substitution, production activation or security weakening is authorized.
The owner corrected this goal to run native validation directly on the Mac. Required Rust native CI uses the standard macOS 26 ARM64 runner with the existing Darwin verifier and pinned tools; Linux/Pi parity and a positive Linux native gate no longer block the primary Cloudflare Workers delivery. The manual Linux guest input/job and probe-only workflow metadata are retired, not replaced with a synthetic pass. Dormant guest source, historical failures and receipts remain preserved; the existing Knip script/test entries need no artificial use or new exception.
Matching Mac confinement, exact-source native fixture predicates and required Worker/WASM artifact and candidate acceptance remain mandatory. Prior passed Mac runtime/storage/state/native evidence may be reused only where its actual input closure is unchanged; a platform switch alone does not establish new runtime acceptance. Product Linux enforcement remains fail-closed, and no credentials, native service, provider spend, production traffic cutover or automatic deployment is authorized. This entry supersedes the earlier compatible-Linux-runner direction for this goal only.
The source-only compatibility correction retains the local macOS 26.6.1 /bin/ls identity a1cb6fd856f9414ada4cc9682f137c343261d777b8374df1abac7a931fb66f7a and adds only the official GitHub macOS 26.6.2 ARM64 identity 24752389e1d97c9555dd153b644902fadd460dfbe1a166251876c67bbacb0810, observed in native preflight run 39516819139, job 118951218851, at source 3f1721142faf2cd1fd4ee4f54c3b813e352f8f9c. The private inspector and existing CI preflight consume this same exact source-literal set. No OS version, caller value or environment value can authorize another digest; macOS 15 and unknown identities still fail closed. Fixed path, root ownership, NOFOLLOW/regular-file metadata and hash rechecks, ACL parsing, process, network and write constraints remain unchanged. Local matching and original native cases do not establish the new hosted utility's semantics; actual hosted native cases remain required before acceptance. No live credential, provider, service or deployment authority is added.
Isolated local operator bootstrap uses existing native custody and the common authority - 2026-10-21
The owner approved a private one-shot setup composition for the isolated localhost 7998 testing gateway. A real consistent stopped Bun snapshot and independently configured current native owner registrations pass through the existing capture, custody, access-only sanitizer and complete-capture validators. Only the validated access projection reaches the same common Durable Object used by ordinary auth, catalog and admission. A non-HTTP host startup export requires its actual AUTHORITY capability, an empty quiescent target and the existing atomic adoption checks; it emits only the adoption receipt. It is not called by ordinary public fetch and is not a public import route or fixture bootstrap.
This local testing decision grants no shared credential refresh, new native writer/ownership, paid fallback, production publication, existing gateway cutover or replay reset. Refresh-bearing documents remain native; source revisions, absolute expiry, selected account, quota and reset state stay truthful. The runtime owner keeps 7999 and the default Codex profile unchanged, holds public 7998 traffic until setup settles, and preserves rollback by stopping only 7998 and retaining its state directory. Missing or stale genuine custody fails closed; capture data and fixture hosts cannot mint it. Real operator execution and inference acceptance remain separate from source tests.
The Rust Worker native transport supports its existing injected service binding and an explicitly constructed HTTPS origin. The HTTPS constructor accepts only a root origin on the default HTTPS port without userinfo, query or fragment; no request field, ambient environment lookup, binding-name scan, discovery, redirect or retry selects another destination. Both carriers retain the existing signed finite RPC, follow, control and live paths, limits, nonce and authority contracts, cancellation and unknown-effect handling. Live upgrades return the original raw platform response so status 101, status text and the WebSocket remain intact; follow responses retain streaming bodies.
The exported shipping Worker reads only the exact UOS_NATIVE_CARRIER deployment binding. Its closed JSON object contains the root HTTPS origin and the transport identity (key_id, owner_id, owner_epoch, key_base64url, and explicit capabilities); an absent binding leaves the capability unavailable, while a malformed, partial, oversized or unknown configuration fails closed before routing. No request field, alternate binding name, discovery scan or fallback selects a destination. The binding does not install a native owner, grant renewal ownership, create a Tunnel or activate a service. The separately approved isolated candidate still requires its exact owner and access-only custody, fixed origin and listener, confinement, green source and actual runtime acceptance before operational pairing. Credential-bearing imports remain native-direct and outside the carrier's finite path set.
The isolated Rust Worker deployment explicitly enables the existing candidate passkey policy and trusts only https://rust-candidate.ai.ubq.fi as its additional relay origin. This trusted composition retains RP ai.ubq.fi, the generic source-settings translation and all existing exact-origin checks; no request header, environment switch or discovered hostname can expand it. Candidate login stays same-origin: the static remote-client relay classifier and canonical production popup remain unchanged. Actual Worker challenge, assertion, session and browser acceptance remain required before candidate authentication is accepted.
HISTORY-STAGEDv1 adds a private trusted-operator begin/append/seal path for complete captures larger than one32MiB frame. Native preparation retains the existing complete NativeCapturev2 audit, codec, index and configured native-custody checks before emitting canonical rows, inverse mappings and derived records. Append frames preserve raw tuple identities, revisions and absolute expiry, bind count/sequence/hash to the complete prepared inventory and commit each batch atomically. A partial target has no adoption manifest and cannot export as an accepted inverse. Final sealing is staged data readiness, not the old single atomic adoption receipt, live ownership or service activation; existing atomic adopt_empty is unchanged.
The operator must exclusively hold a new empty common authority unpublished and quiescent throughout staging and final reconciliation; deserialized data grants no public capability. No public HTTP/admin import route, arbitrary SQL insertion, live refresh/reset/fallback or active7998/7999change is introduced. Complete preparation and latest inverse remain native-owned; the current inverse uses paginated QueryStore reads and writes directly to private file/sink, with separately held current Rust-control/nonce custody. Native memory is measured with the synthetic large capture before any private real907MBattempt; file output avoids a full WASM response, not a claim of constant native memory. Live target activation and current7998write reconciliation require a separate explicit decision.
HISTORY-STAGEDv2 selects only the fixed synthetic history scenario for the assigned 360-second outer controller envelope; normal fixtures retain 120 seconds and all existing per-operation deadlines and assertions remain unchanged. Metadata-only stage markers attribute native process RSS. The measured 3.528 GiB native peak for a 40.056 MiB synthetic source forbids a real 907 MB attempt: staged transport proof does not establish bounded-memory native preparation or full-history scalability.
The owner selected Cloudflare Workers Free with a hard limit below 100,000 Durable Object row writes per UTC day and stated that historical logs are not necessary for the Rust gateway migration. The bounded offline profile in rust/crates/gateway-migration/CORE_STATE.md selects 2,317 of the 140,220 rows in source 0be69ebcced135ff1d38966aa01691eddc74f1bb / capture af0fb90c917992346f44751ecc645289d170c88b168b0a387472a5b677159939, excludes 137,903 rows, derives five rows, and requires 4,640 writes including the manifest. The count is 2 * selected_rows + derived_rows + 1; it is proven by the selector and focused tests, not estimated from storage bytes.
The profile excludes historical API request logs, paid-fallback history, provider-capacity history and rollups, Metered balance history, API-key audit changes, error logs, Sentinel replay/incident records, and prompt-cache analytics or telemetry gates. It retains auth users/credentials/handles, API keys, Codex auth/routing/capacity/whitelist/reset state, Codex models and catalog, Claude auth/workspace/quota/access/accounts, kernel defaults, Metered current state, current provider capacity/health, runtime configuration, provider selection, migration control, the active API window, and the current paid-fallback request/pending accounting rows. The previous API window is excluded.
The snapshot has no paid-fallback window aggregate. Its current-window 1,877 request rows and 344 matching pending markers are retained because dropping them would lose current settled, reserved, and pending accounting; this is history retained for a current counter, not full-history convenience. Adoption derives one current paid window and the reconciliation gate from those retained rows, so the admin reader sees the current totals without a source reset or historical backfill. The source gate row is excluded because source gate versions use different document shapes.
This decision authorizes only offline selection, preparation and focused local tests for the reduced profile. It does not authorize live adoption, a startup conversion, credential refresh or rotation, a quota reset, production deployment, or a full 140,220-row import. Raw managed Codex credentials still require current native custody and access-only sanitization before preparation; the captured generation does not match the current local auth files and was not refreshed or rotated.
The owner adopted four Rust rules for the port: no first-party crate above 1000 lines, no re-exports, no #[path = "..."], and no include! (https://x.com/dj_d_sol/status/2113543433516421153). A crate is measured by its owned production src/**/*.rs; integration tests and vendored dependencies are separate crates, and the static include_str! and include_bytes! macros are not the prohibited include!.
Reason: the current port is dominated by very large crates, broad pub use forwarding, and path-spliced modules, which hide dependency edges and make agent-generated changes hard to review. The rules are a migration requirement, not a claim that the current tree complies. Existing violations are recorded debt, no change may add or enlarge one, new or substantially rewritten crates must comply immediately, and full compliance remains required before port acceptance.
Reversal risk: allowing crate growth or re-exports restores implicit API surfaces and ambiguous split boundaries; #[path] and include! bypass the conventional module graph and make ownership and compilation scope harder to audit.
The owner adopted the first Rust lint and compile-performance program after the four structural rules. scripts/rust-quality.ts is the structural ratchet: no new oversized crate, visible re-export, #[path], include!, missing [lints] workspace = true, or source suppression; existing debt may only shrink. Lints are selected individually, suppressions remain forbidden, and noisy lints are staged with --force-warn plus a diagnostic baseline rather than weakening -D warnings. Development and test builds use line tables only, while production release settings remain unchanged until a separate release-candidate profile is measured against the complete Worker build. The detailed policy, thresholds, measurement protocol, and migration order are in docs/research/rust-quality-compile-performance-2026-10-23.md.
Reason: the 1000-line crate cap improves reviewability but does not prove compile-time improvement. Mixing structural enforcement with release-profile changes would make both unmeasurable and could trade deployment size or request CPU for a faster build. Suppression-free, individually selected lints keep the policy enforceable without a blanket warning backlog.
Reversal risk: enabling broad lint groups or lowering a lint from deny to warn under -D warnings stages nothing; using --cap-lints or continue-on-error hides real failures. Changing [profile.release] before measuring the full Worker build can regress artifact size or runtime without a build-time benefit.
Provenance: one owner-authorized GPT Pro submission, job 66ca9a42-20cf-4ff8-acd2-e01653d97ea3, 2026-10-23.
First-party Cargo artifacts belong to their resolved workspace source root. The verifier claims an empty target atomically and rejects a foreign, malformed, symlinked or unowned nonempty target before compiler execution. Actual manifest and target-directory overrides participate in that resolution; subcrate manifests in one workspace share the owner, and immutable source archives require no Git directory. Same-root edits may reuse their cache. This follows fresh evidence that shared first-party targets can replay warning spans from another worktree even when Cargo metadata names the current source. Previous shared-target diagnostic captures remain historical diagnosis, not acceptance.
The verifier removes its Darwin debug = 0 environment overrides and excludes ambient dev/test debug overrides. Committed rust/Cargo.toml dev/test profiles remain line-tables-only, as required by the 2026-10-23 decision; production release settings are unchanged. Earlier debug-disabled component captures retain development and behavior evidence, while final combined acceptance requires the exact corrected driver/source and inspection of actual compiler flags.
Fresh structural adoption reproduction retains the immutable base source inventory, target closures and all fourteen adopted target counts with machine-readable provenance. These artifacts prove fresh structural reproduction; they do not recover the original raw Clippy captures or authorize allowance growth. Historical diagnostic identities stay unchanged, and missing historical Clippy proof remains explicit.
The ubiquity/deepseek-flash synthetic model gives its LithosAI hop the immediate-failover refusal policy. A 429 or 402 is returned to the waterfall at once, so the next configured provider is attempted without spending the vendor's reset window. Direct LithosAI model ids keep the existing buffered and streamed wait policies.
Reason: live LithosAI headers reported a 600-request and 8,000,000-token/minute budget, while the gateway's parallel Codex agents sent large contexts that repeatedly emptied the token bucket. Three refusals also reported 402 insufficient_quota and the organization is out of credit. A streamed hop could otherwise hold an open response for five waits and up to 300 seconds before the waterfall advanced, which surfaced as iOS steering timeouts. Immediate failover improves responsiveness and prevents a refused first hop from consuming the next provider's latency budget.
Reversal risk: the waterfall reaches the Official DeepSeek, OpenRouter, Surplus and OpenLux hops sooner, which can change cost mix and exposes more provider churn. The order, paid pins, direct Lithos behavior and credentials are unchanged. If the provider recovers, it is eligible again on the next request.
The VPS gateway stop timeout is 15 seconds, and HTTP shutdown closes lingering idle keep-alive sockets only after every active handler has settled. The previous 180-second stop timeout allowed a deploy to stop accepting requests for three minutes; the Codex app-server backed off through 5, 10, and 20-second retries, and the iOS client discarded pending steers after about 30 seconds.
Reason: a live deploy at 23:11:17 UTC stopped the gateway listener and systemd killed the process at 23:14:17 UTC. Gateway requests during that interval failed at the transport boundary, and the mobile messages were deleted before the next successful model call. The app-server returns to service on its 20-second retry when the listener is restored within 19 seconds, so the stop and restart must complete before that retry. Active HTTP handlers still drain before lingering sockets are closed; no accounting or terminal write is bypassed by the idle-socket cleanup.
Reversal risk: a longer stop timeout restores the three-minute blackout and will drop consecutive mobile steers again. Forcing all connections closed before active handlers settle would lose delivery or settlement evidence, so the close remains gated on an empty active set.
deepseek-forwarded-payload/v2 keeps the 65,536-byte per-message reducer for tool outputs, images, agent messages, tool arguments, reasoning, and ordinary messages, and adds one versioned codex-compaction-summary/v1 exception. The accepted envelope is exactly one user message with exactly one nonempty input_text part whose text begins with the full 399-byte Codex SUMMARY_PREFIX and a newline; the prefix SHA-256 is e9b088e794a6bb9082ac053fcc760bd818d7e720ee4bcdc72c6e480de7b7cb0e. No header, turn metadata, content-kind metadata, role default, extra part, media part, tool part, or second summary envelope can claim the exception. A prefix-bearing message with the wrong role or shape, including a prefix-bearing top-level string or string input item, fails closed with HTTP 400 context_length_exceeded before projection, and an unprefixed oversized message still takes the generic reduction. The 65,536-byte bound applies to each forwarded payload field; aggregate admission is the bound over a complete message and prompt. Oversized tool-call arguments are replaced with a parseable JSON elision object rather than the plain-text marker, so replayed Chat history never contains invalid JSON.
Reason: Codex 0.163.0 renders its adopted local-compaction summary as one readable user text part beginning with this prefix, while it strips internal_chat_message_metadata_passthrough for every provider whose name is not exactly OpenAI; the Ubiquity provider is not, so metadata cannot classify the summary. The prefix is client-controlled request text, not authority: it selects only the versioned exception, never a bypass of whole-prompt admission.
chat-prompt-admission/v1 runs after every Chat field is projected, including instructions, tools, tool arguments, reasoning, messages, images, and the continuation instruction. It serializes the complete body and estimates its tokens with the existing calibrated Jev estimator, which measured 2-18% above usage on real transcripts, then adds 256 request, 16 per-message, and 32 per-tool structural tokens. For Cerebras it measures the provider-projected body so reasoning that provider drops is not counted. It compares the total with each selected provider profile's own window minus an output reserve. The reserve is the larger of 16,384 tokens and the request's max_tokens. Current windows are DeepSeek 1,000,000, LithosAI 1,048,576, and Cerebras 131,072; Cerebras never inherits DeepSeek's larger window. Aggregate overflow returns HTTP 400 context_length_exceeded before dispatch, does not mutate or truncate the exempt summary, and dispatches no payload.
Observability: one [ai.ubq.fi] forwarding_exemption JSON line records policy, request_id, model, prompt_admission, path, kind: "compaction_summary", summaryPolicy, prefixSha256, bytes, contentParts: 1, perMessageLimit, and prefixBytes only after successful projection and aggregate admission. It is distinct from forwarding_elision because no bytes were removed. The model catalog continues to advertise only the v2 policy version, byte mode, and generic per-message limit.
Reversal risk: removing the envelope restores silent loss of the client's replacement history; widening it to any prefix, multiple summaries, additional parts, prompt text, or metadata would let ordinary or mixed payloads escape the generic bound. Treating encrypted remote-v2 compaction items as readable summaries would forward ciphertext as history. Dropping aggregate admission would admit a whole prompt beyond the provider window even when each individual payload is bounded.
The source-only compatibility update adds exactly two reviewed utility identities from macOS 27.0.1 build 26A434, installed 2026-10-23. The /bin/ls SHA-256 is 13f44bfe1c4af602da4465c834dbe7b16a5441ccbd843178b36116ee23422bfb, with Apple identifier com.apple.ls and full CDHash 45d1613a435c6cb05794cbb585587a5245989943ad1999f183d0f165a4750244; the /usr/bin/sandbox-exec SHA-256 is 58839ef01b4eef8aac0d2aa8f9d1c074ae45aafe3533965b030672450064acc8, with Apple identifier com.apple.sandbox-exec and full CDHash 1266e34f192210d9f1ac6dbc9cf297ecff93e5685ecb2284f29f8a9b9a8222d4. Both signatures chain through macOS Software Signing, Apple Code Signing Certification Authority and Apple Root CA; codesign --verify --strict reports each as valid on disk and satisfying its Designated Requirement.
The existing /bin/ls identities a1cb6fd856f9414ada4cc9682f137c343261d777b8374df1abac7a931fb66f7a and 24752389e1d97c9555dd153b644902fadd460dfbe1a166251876c67bbacb0810 remain accepted, as do the existing /usr/bin/sandbox-exec identities e3d7a792c58a5d3783d2f7274c82d70062393830d8cb1ded713ca554a470bd2f and abc5bb136d6b5cce8fa85d789f78e3326c51ca60cae637b2064adfb67a1dcd9a.
No OS version, caller value or environment value authorizes another digest, and unknown identities still fail closed. The private inspector, owner-runtime fixture and fixed-role actor channel consume the same exact literals; the disabled Darwin CI preflight parses the three-entry inspector and fixture-sandbox sets without changing workflow triggers or activation. Fixed paths, root ownership, NOFOLLOW and regular-file metadata checks, exact hash rechecks, ACL parsing, process, network and write constraints, and every negative case remain unchanged. This compatibility correction adds no credential, provider, service, deployment or other operational authority.
The ai.ubq.fi Caddy site retries a refused gateway connection for 25 seconds at 250-millisecond intervals. This is below the roughly 30-second iOS steer discard window and above the observed 19.6-second stop-plus-start interval. Caddy retries only the failed connection attempt; it does not set lb_retry_match, so a POST body is never replayed after an upstream round trip has begun. The 15-second gateway stop bound, active-handler drain, and delivery and accounting settlement rules are unchanged.
Reason: the live deploy at 06:39 UTC took 19.6 seconds. The gateway stopped accepting at 06:39:28, systemd killed it at 06:39:43, and the new listener did not become ready until 06:39:47. The previous 15-second bound only matched the app-server's final retry edge after release verification was added; it did not prevent the listener blackout. With Caddy retrying refused connections, a request issued during that blackout remains connected and reaches the restarted gateway instead of becoming a transport failure. A real Caddy 2.11.7 fixture held a POST for 2.23 seconds while its backend was absent and returned the backend's 200 response once it appeared.
Reversal risk: removing the retry window or lowering it below the restart interval restores dropped mobile steers. Raising it beyond the client's discard window wastes the wait without preserving the request. Enabling lb_retry_match for POST routes could duplicate a non-idempotent inference request after an ambiguous round-trip failure and is not authorized by this decision.
chat-prompt-admission/v2 first estimates the complete projected prompt. If it overflows and the request permits reduction, the gateway finds the one exact adopted Codex compaction summary already validated by codex-compaction-summary/v1, keeps the leading system instructions and the summary, and replaces every earlier message with one visible history-elision notice. It then re-estimates the complete body. The summary itself is never changed, and truncation: "disabled" still fails closed. If the reduced body remains over budget, the gateway still returns HTTP 400 context_length_exceeded before dispatch.
Reason: a live iOS steer reached a 1,032,954-token estimate against the LithosAI 1,032,192-token budget, only 762 tokens over, and could not be sent. The request carried a 961,798-byte adopted compaction summary plus 2,730,984 serialized bytes of history. Messages before that summary are redundant after Codex has adopted it; retaining them made a long thread unusable on DeepSeek while the same client could continue with GPT. The reduction preserves the adopted summary, the current steer, the complete tool schema, and all post-summary messages.
Reversal risk: removing this reduction restores the hard steer failure for long adopted summaries. Dropping post-summary messages, rewriting the summary, applying this to truncation: "disabled", or admitting a still-over-budget projection would lose current work or dispatch an oversized request. The version bump distinguishes this aggregate behavior from v1 in logs and tests.
chat-prompt-admission/v3 supersedes the v2 pre-summary reduction above. An adopted summary does not prove that every earlier user message is redundant. Aggregate admission now measures the complete existing projection without removing pre-summary messages; an oversized projection returns HTTP 400 context_length_exceeded before dispatch for every truncation mode. The existing per-field projection rules, exact summary exemption, provider windows, and output reserves are unchanged.
For the Codex subscription stream only, a generic terminal error with exact code context_length_exceeded and an already tracked response identifier becomes one client-visible response.failed carrying the original error, response identity, template, and observed output. Provider capture, lifecycle callbacks, settlement, and fallback continue to observe the original upstream error. Ordinary errors and other providers retain their existing frames.
Reason: an isolated installed Codex 0.164.0 fixture ignored both flat and nested generic context errors and reported a retryable disconnect; the same code in response.failed.response.error produced the explicit context-window failure. This classification correction preserves the failure rather than shrinking context or claiming automatic recovery. It does not establish behavior of a different installed client version or physical iOS acceptance.
The Chat-backed Responses adapters for DeepSeek, LithosAI and Cerebras distinguish a complete projected prompt that exceeds aggregate admission from every other projection refusal. For requests with stream: true and a parsed existing x-codex-turn-metadata object containing nonempty session_id, thread_id and turn_id, that local failure is encoded as response.created followed by one response.failed carrying the original context_length_exceeded code and message. This metadata selects response encoding only; it grants no authority, credential access, provider eligibility or validation bypass. Missing or malformed native identity, nonstream requests, ordinary OpenAI clients, per-message refusals and other validation failures retain HTTP 400.
This is an explicit Codex-native compatibility contract, separate from the official HTTP context-error contract. The Responses failure event shape is documented, while the official default/disabled truncation contract specifies HTTP 400. Installed Codex 0.164.0 treats the standard HTTP 400 structured context code as an ordinary invalid request; its existing response.failed.response.error.code classifier marks the context full. A credential-free app-server fixture proved that the next input then triggers native compaction automatically, preserving both the failed latest input and the new follow-up. The gateway does not remove history, change provider windows or reserves, or invent usage to trigger recovery.
The local failure remains an incomplete, nonsemantic result with missing usage and no upstream dispatch. Its internal response identity stops the synthetic DeepSeek waterfall before provider-failure retry gating, including paid hops; it is never quota exhaustion or capacity failure. Existing request-owned admission and quota cleanup settles the failure once. Native HTTP error-code classification remains the upstream corrective direction; adopting a patched native binary is separate work because the shared app-server cannot be restarted from one of its own sessions.
Native Codex streamed Responses requests with the existing valid session, thread and turn metadata may flush SSE headers after shared validation, provider-local projection and successful existing dispatch admission. While the original handler still awaits its final Response, one transport-owned timer sends only the standard empty SSE comment :\n\n every 50 milliseconds; it stops before any selected Response body is forwarded, and on abort, close, error or cleanup. Backpressured output skips the comment rather than queuing writes. The node:http transport registers this capability against the original physical Request; no other transport gains it implicitly. The complete handler and telemetry runner remain awaited, preserving the original body observer, outgoing-close abort, one quota admission, provider waterfall and semantic commitment, terminal settlement, real delivery receipt and shutdown drain. Keyless callers keep the existing no-API-key-quota dispatch seam after normal authentication and process/kernel admission. Cerebras buffered contracts, public clients, malformed metadata, nonstream requests and pre-dispatch failures retain their existing behavior.
Reason: installed Codex 0.164.0 acknowledged a steer in under a millisecond but could not reissue while HTTP response headers were pending. A three-second preheader hold delayed adoption by 3015 milliseconds; headers without any body reduced adoption to 5.720 milliseconds. The synthetic DeepSeek waterfall legitimately buffers provider events until semantic selection, so returning an early Response or releasing those events would alter ownership or failover. A transport-only readiness callback sends no API event or usage and keeps those boundaries intact. Header delivery alone allowed prompt steering adoption but did not expose an abandoned quiet native connection. A credential-free installed-client test with a separate raw TCP provider proved that a delayed standard comment caused the original gateway request to abort and upstream TCP EOF 1.086 milliseconds later, before manual provider release; steering ACK was 0.610 milliseconds and adoption 5.203 milliseconds. Comments are transport liveness, not model output.
Cadence update - 2026-10-27: a credential-free actual-gateway fixture using Codex 0.164.0 and a held raw TCP provider measured upstream EOF after an early steer at 188.914 milliseconds with the 200-millisecond cadence and 43.856 milliseconds with 50 milliseconds. Near a timer tick, the measurements were 6.463 and 19.468 milliseconds, so cancellation remains phase-dependent. The shorter cadence reduces abandoned original-request work; replacement adoption still follows admitted headers. It schedules 20 rather than 5 callbacks per second per pending connection, and provides no strict end-to-end latency guarantee.
Once native HTTP 200 headers are committed, a selected late HTTP failure is encoded as standard response.created followed by response.failed with its original error code/message and no invented usage or wire status/retry fields. The selected HTTP error body is consumed directly with the existing 64 KiB/one-second bound. Original status, safe allowlisted headers, error details and capture completeness remain keyed to the original Request and reach the existing structured terminal log across Response/CORS clones; incomplete reads never claim full original error evidence. Existing SSE bytes pass through unchanged. This native compatibility contract changes HTTP error classification: installed Codex 0.164.0 stream-retries late 429/503/401 failures without an HTTP status identity; the HTTP 429 path instead reports responseTooManyFailedAttempts with 429, and late authentication errors become generic stream failures. A late context_length_exceeded remains contextWindowExceeded. These measured limits are explicit; this is not HTTP retry parity or physical iOS acceptance.
Reversal risk: delaying readiness through the first provider byte or synthetic semantic gate restores the steer adoption delay. Readiness before validation/admission, changing Request identity, releasing a quota reservation early, altering provider commitment, or treating header delivery as semantic completion would weaken existing contracts. No provider identity may be promised before selection, no history is removed, and cancellation retains the existing transport compensation owner.
bun --no-env-file run steering:health [endpoint] measures the installed Codex app-server against the selected gateway, defaulting to localhost port 7999. It uses isolated temporary Codex state, preserves HOME, parses the canonical repository-root .env with the pinned Bun-compatible standard parser and selects the first nonempty comma/newline-separated key into memory without credential cycling, and reports the served release and current native catalog. The fixed observed case is ubiquity/deepseek-flash with low effort. An operator may supply an existing SSH-forward endpoint; the command never starts tunnels, deploys, refreshes credentials or touches shared threads.
The probe permits two inference requests, 64 KiB each, 512 output tokens each, zero native retries and a 60-second deadline. JSON output distinguishes RPC acknowledgement, replacement-request adoption, header readiness, original-stream cancellation and changed-answer completion. Session identity must be nonempty and stable independently of the actual thread and turn IDs. Missing header observations mean an incomplete probe rather than an inferred latency. Missing, duplicated, reordered or wrong-turn input, authentication refusal, timeout and failed cleanup are failures, even after HTTP 200. After confirmed child exit, its task-owned native state is removed; private artifacts retain only the bounded receipt and redacted native diagnostics without the gateway key. These are measurements, not a latency guarantee.
Successful request-body EOF marks input consumed, closes its Web stream and removes body listeners without pausing the IncomingMessage. Cancellation, errors and backpressure retain their existing pauses. The admitted early-SSE capability flushes headers only; it has no heartbeat, periodic write or cancellation timer. Existing unfinished outgoing close/error events still abort the original physical Request and reject its real delivery receipt, preserving one admission, provider selection/fallback, terminal settlement and shutdown drain.
Reason: the exact pinned Bun 1.4.0 input adapter consumed a 52 KiB POST, then paused the native handle during EOF before the IncomingMessage was destroyed. Full-close and half-close clients produced no outgoing/socket close during a quiet 700-millisecond held response. Skipping only that terminal pause restored outgoing close within 0.42 milliseconds without response bytes. Independent installed Codex 0.164.0 steer and explicit-interrupt fixtures confirmed prompt original-request abort and upstream TCP EOF without a comment write. No socket-end bridge, extra body reader, request clone, supersession registry or resume workaround is introduced.
The existing 15-second protocol keepalive in responses-stream.ts remains a connection-preservation feature for selected Responses streams. It is separate from the removed 50-millisecond pending-selection heartbeat and is not needed to discover cancellation. A FIN remains directional; this change relies on the runtime's existing terminal response event rather than treating raw input EOF as abandonment.
Reversal risk: pausing successful EOF again suppresses quiet disconnect observation and recreates periodic-write dependence. Omitting pauses for unfinished cancellation/error/backpressure paths would change input flow and early-refusal behavior. Header readiness remains gated on authentication, projection and admission; header delivery is never semantic completion or successful accounting settlement.
The owner authorized retiring eleven TypeScript behavior overrides in favor of the existing defaults and the verified local reset policy. Matching Rust environment reads are removed without changing persisted Rust account/KV policy. No replacement flags or aliases are introduced.
| Retired environment override | Fixed behavior |
|---|---|
JEV_COMPACTION_DISABLED, JEV_COMPACTION_HYBRID |
Stock provider compaction with no request-handler Jev interception or hybrid residue pass. |
CORS_ALLOW_ORIGIN |
CORS fallback origin *, preserving trusted-origin and authentication behavior. |
IMAGE_BASE_MODEL |
Existing selected/default gateway text model. |
CODEX_BASE_URL |
Official Codex upstream https://chatgpt.com/backend-api/codex. |
UOS_API_KEY_DEFAULT_USAGE_LIMIT, UOS_API_KEY_DEFAULT_EXPIRY_DAYS |
New-key defaults of 50 requests per week and 90 days; explicit per-key settings remain available. |
CODEX_BANKED_RESET_ENABLED, CODEX_BANKED_RESET_MAX_PER_ACCOUNT_PER_DAY, CODEX_BANKED_RESET_MAX_PER_ACCOUNT_PER_WINDOW |
TypeScript automatic resets enabled subject to existing per-account consent, eligibility, durable claim fences and at-most-once submission, with one redemption per account per UTC day and one per account/quota window. |
UOS_CAPACITY_OBSERVATION_HOST_ID |
Mac companion capacity identity mac. |
This decision supersedes the earlier Jev interception and hybrid kill-switch decisions, the TypeScript banked-reset environment kill switch, and the earlier documented reset-cap parse default. The previous source default for an absent daily cap was 0, disabling live submissions until an explicit 1 was configured; the verified local service already configured 1. The new constant preserves that accepted local policy. Existing per-account controls, durable caps, claim fences, quota-window ledgers and consent checks remain authoritative. Rust's persisted reset modes, limits and consent are unchanged.
Keep credentials and provider-key families, private account/workspace identifiers, access allowlists, public verification keys, native credential homes and production/security identity settings. In particular, retain the VPS DENO_TIMELINE=production boundary. The repository-root .env is a symlink chain into a shared credential store; no provider credential or metadata is removed merely because TypeScript does not read it. Existing explicit configuration/model/host test seams replace environment setup where required, and sparse test profiles no longer pass IMAGE_BASE_MODEL.
Local activation must first deploy the accepted exact immutable release with the old shared environment intact, then verify the served release identity, authenticated ordinary inference and a bounded marked native-compaction request showing that custom Jev interception is absent. Only afterward may a private, hash-checked backup and narrow edit remove the retired behavior settings from the shared target while preserving all other bytes, symlinks, owner and permissions, followed by a graceful gateway reload. Never restart the shared Codex daemon. Before rolling back to interception-capable code, restore JEV_COMPACTION_DISABLED=1; keep the latest same-codec Bun KV rather than restoring an old database. VPS activation, reset redemption, credential rotation and account mutation are outside this local change.
Reason: these overrides duplicate the accepted gateway behavior and create drift between source, shared credentials, runtime and test profiles. Fixed defaults remove that ambiguity while keeping credential, authorization and host boundaries explicit. Reversal risk: removing the old compaction bypass before compatible code is active can re-enable interception, restoring old code without that bypass can do the same, and deleting shared credentials or broad metadata can break unrelated consumers. Hardcoding must not bypass account consent, widen CORS trust or replace the gateway's selected image model with an arbitrary model id.
The M64 operator uses a completed read-only SQLite online backup as a new closed private input to the existing typed capture and bounded CORE_STATE selector while the original Bun service may keep serving. The copy proves neither stopped-serving-source ownership, latest-write/deletion currentness nor native credential custody, and grants no activation or rollback authority. The October 21 custody/bootstrap and October 22 offline-only CORE_STATE boundaries remain unchanged.
The core-state export keeps Input v1 and returns Receipt v2 naming the actual selected private capture path, byte count and hash. Full and selected capture bytes may contain credential-bearing state and remain private pending the existing current-custody and access-only sanitization checks. The serving source identity stays distinct from the helper source/tree and runtime/artifact provenance; one cannot stand in for another.
Only the exact Darwin prelaunch fixture controller runs outside the ordinary test wrapper so each protected product child receives its first actual OS profile and its Python descendants inherit that boundary. Other tests retain their existing wrapper. The controller binds the observed system Python shim, canonical launcher and terminal interpreter to exact checked paths, root ownership, executable mode, Apple signing identities and recorded hashes. Real startup markers, denial results and matching positive controls remain required; no generic isolation bypass, environment escape or broader process grant is introduced.
Reason: component copy, selector and child-confinement evidence does not establish the staged whole-producer read boundary, which remains unresolved. Neither component evidence nor these source interfaces accept a private copy for live adoption.
Reversal risk: treating a consistent copy or selected-byte receipt as current authority can lose later writes or expose credentials; treating a controller startup failure as a successful denial can falsely claim confinement. Existing stopped-source/currentness, custody, exact-artifact, target-isolation and live-acceptance requirements remain in force.
The offline copy/capture operator uses the canonical Python role from the existing independently verified three-role tuple through a constructor-held binding in a hash-bound immutable launcher. The original v1 private data input cannot choose an executable, binding, environment or capability. The preparer preserves the external signature receipt and stage/source identities; the actual role hashes, root ownership, precise identities and link counts are rechecked before and after execution. The signed fixed system shim may be a hard-linked multiplexer; canonical and terminal interpreter roles remain single-link. Unbound direct entry refuses before effects, with no shim fallback.
The strict profile grants root-directory data and data for only the validated private output-anchor directory, plus existing explicit immutable source/artifact, canonical role, source-file and new-output rules. Literal directory data reveals names only and never authorizes descendant file bytes. Bun SQLite/CoreFoundation also requires one exact root-owned readonly ICU data file. Its bytes, size and hash are bound through the existing immutable files inventory; the profile emits one literal file-read-data rule plus exact metadata, never a directory/subtree or general file-read grant. Current Mac receipt is icudt78l.dat, 36,103,568 bytes, SHA-256 09781b9fdd79428c724099159f85dc522b07ddbf51cb7c23d16606a254d758f1. All unrelated read/write/source-write/exec/outbound denials remain required, including a direct forbidden sibling-file test. Exploratory xcode-select/libxcrun permissions are not production policy.
Existing per-launch SQLite temporary storage is bound internally to the already approved new private output root. This introduces no public setting or new environment name. Actual strict SQLite/ICU runtime qualification passed on the frozen seven-file candidate: five helper cases and five real Darwin boundary cases, evidence bef89a59-bc75-430f-bdb4-a13f4de84165. The executed immutable launcher hash and 0400 identity were checked before/after success and malformed-input runs. Fixture seals a*/b* remain synthetic and are never reported as application Git identities. Final selected static gates passed on commit4980be305a08a929c743a9bd82017d17779474aa/tree966175f1f015ee062893036b0b46f73222052b99; integration and candidate gates remain separate. These source/tooling decisions authorize no private capture read, credential change, service action, live adoption or production deployment.
The owner authorized a separate C++20 direct DeepSeek fixture candidate under cpp/, after the shared TypeScript real-socket foundation merged at db1d78cf9037775ba29b8aa72e89f2b2dbd6ba80. The deployed TypeScript Chat-backed Responses behavior remains the oracle: preserve full history, call-ID and namespace relationships, reasoning and measured usage, source quota reservation/defer/release/dispatch phases, semantic terminal truth and physical delivery as separate facts. Preserve the captured bare-name namespace replay and immediate peer-FIN interruption rather than silently repairing them during the port.
The pilot uses one IO loop, explicit reduced limits, a constructor-bound provider destination, and a separately marked synthetic authority with an exclusive checksummed journal. It never opens or converts production Bun/Deno KV, installs automation, replays generation on restart, refreshes credentials or grants production standby authority. The packaged SDK stays read-only; a task-owned CMake executable view preserves that SDK's loader for generated commands. Compiler memory and actual Pi service memory are measured separately. Root still owns independent resource/client/soak acceptance and delivery; a build, fixture pass or health response authorizes no production activation or provider-credit spend.
Research evidence and standalone CMake pilot changes use first-party import/literal-file reachability before selecting Bun work; consumed data and real configs stay conservative, and CPP TS/JS adapters retain static checks. Private-copy confinement is selected through an explicit affected Darwin segment and is never run by Linux main/portable profiles; existing Darwin job fields and named-file command boundaries remain intact. The pinned synthetic TS/Codex replay is a committed script entrypoint with a fresh native KV reopen receipt, not a Knip suppression or ordinary CI requirement for a host-installed Codex binary.
The first C++ pilot is explicitly stream: true only, matching the qualified pinned Codex profile. False or missing stream requests refuse before provider dispatch with a standard OpenAI-shaped validation error and source-compatible authenticated reserve/release counts. Buffered TypeScript behavior remains unchanged and unsupported in this pilot; supporting it or claiming a general OpenAI replacement requires a separate accepted scope.
The loopback C++ resource profile requests16KiB downstream SO_SNDBUF and records the effective kernel value. Its existing inherited fixture read-state exposes request/write/read counters so a namespace-local paused reader can prove pressure, stable upstream reads and eventual drain/cancellation. This is part of bounded transport acceptance, not a new public control surface.
The requested GPT Pro recommendation selects the existing clang-tidy/Clang Static Analyzer 14.0.6 engine plus exactly clang-analyzer-unix.Malloc and clang-analyzer-unix.MismatchedDeallocator; existing core/C++ and dangling-handle/use-after-move checks remain fatal. The Pi complete workflow enforces the gate, with an explicit always-run CMake target. Its database contains all thirteen real production/test roots and three separately counted analysis-only controls. Checker membership, frontend status, raw diagnostics and a fresh source-matched AST-consumer profile must agree; neither an exit zero nor a profile alone proves successful or exhaustive analysis. Broad header reporting preserves emitted SDK endpoints and first-party caller paths without blanket vendor suppression.
Representative known defects must produce their exact marked diagnostics, and clean ownership/cancellation-pattern controls must pass separately. Existing ASan/UBSan/leak and six real CTests remain required where relevant. Static heap checks do not prove descriptor lifetime, shared-owner cycles or coroutine/cancellation safety. Extra analyzers, alpha checks, annotation rollout and SDK changes are deferred; this tooling changes no runtime/provider behavior or production authority. See cpp/docs/static-analysis.md for commands, measured development evidence and pending canonical acceptance.
The first complete scan's four pinned Beast bugprone-use-after-move findings remain preserved as a failed receipt. Source inspection and a real reduced static probe proved the Asio stackless yield/reentry path-sensitivity limitation, with equivalent explicit-return code clean and genuine same-invocation misuse fatal. A finite checked-in baseline may classify only those four exact Session-TU SDK fingerprints and move/loop notes under matching tool/frontend/header/policy identities, preserving raw exit1 and explicit classified/new counts. New, changed, missing or first-party findings and identity drift remain fatal; no checker, SDK directory or runtime source is suppressed or changed.