The 3 -> 8 bump in callWithCopilotModelRetry was shared by the generic
retryable branch, so a persistent status-less transport blip on Copilot
would ramp across 8 attempts (~11.2s of dead time) instead of the 3 it
took before, and a repeated Retry-After 429 could stretch the same way
on top of the transport's own fetchWithRetry budget.
Derive the budget from the failure kind: model-availability 400s keep the
8-attempt reroll, everything else caps at the previous 3.
Also read COPILOT_TRANSIENT_MODEL_CODES with Object.hasOwn — `code` is
provider-controlled, so a 400 body whose code was `__proto__` or
`toString` classified as transient through the prototype chain.
Any Copilot model in the middle of a rollout (claude-sonnet-4.6,
claude-opus-4.6, gpt-5.4, gpt-5.3-codex, ...) returned a raw HTTP 400 on
roughly half of all turns. GET /models on api.githubcopilot.com returns
two different catalogs across repeated calls: part of the fleet serves
those ids, part rejects them with
400 {"error":{"message":"The requested model is not available for
integrator \"copilot-language-server\". ...",
"code":"model_not_available_for_integrator", ...}}
The absorb machinery already existed and was correct
(isCopilotTransientModelError -> isProviderRetryableError -> the
Anthropic transport's PROVIDER_MAX_RETRIES). Only the classifier missed:
it matched the older model_not_supported code and probed err.code /
err.error.code, while the real code is model_not_available_for_integrator
sitting at err.error.error.code (the SDK stores the parsed body on
.error, and Copilot's body is itself {error:{code}}). So
isProviderRetryableError fell through to "4xx => terminal".
Fix the classifier: providerErrorCode() walks the error envelope up to
depth 3 instead of hardcoding a shape, both Copilot model-availability
codes are accepted, and a wire-body text match backs it up because SDK
envelope shapes drift between provider families while the stringified
message does not. This alone restores the retry path, because
isProviderRetryableError consults the provider hook before its
4xx short-circuit.
Retry shape, since a rejection is a per-request replica reroll rather
than upstream backpressure:
- both transports wait a flat delay between model-flap attempts instead
of the growing backoff; generic retryable failures (429/5xx/transport)
keep their linear ramp and Retry-After handling
- the OpenAI-transport budget goes 3 -> 8 attempts, because a measured
~70% flap window produced a turn that needed 6 wire attempts and
exhausting the budget escalates to the agent-level retry, which
restarts the whole turn
Absorbed attempts cost no tokens: rejections are gateway-side, carry no
usage block, and return in ~208ms median versus ~1884ms for a served
request.
Also refresh the exhausted-retry guidance text, which cited a
nonexistent model id and described the cause as a per-client rollout gap
rather than fleet skew.
Bare anthropic.claude-* Bedrock rows already derived eu.* selectors; also
emit us-gov.* so GovCloud accounts can resolve system inference profiles
without requiring a full partition ARN.
- Restored required-before-optional property ordering in JSON Schema emission; downstream wire consumers (pi-ai toolWireSchema) rely on that stable ordering.
- Mapped Type.Optional with a default to a plain defaulted key in the TypeBox shim, since omptype (like ArkType) rejects optional keys that specify defaults.
- Added support for bigint, RegExp literals, and regex execution in the string DSL alongside intersection and pipe operators.
- Enhanced error aggregation, cycle detection, and alternative branch rendering for union and collection validations.
- Updated object compilation and evaluation to support symbol and pattern indexes.
- Extended type methods with subtyping, type intersection, and scope building features.
- Cleaned up test suites by removing redundant JSON property and schema assertions.
- Updated validation error messages and assertions to adopt bracket and string formats.
- Replaced internal structure inspections with runtime evaluation and allows checks.
- Standardized type equality checks using Eq type assertion helpers.
- Add extensive test suites covering arrays, objects, keywords, and core type operations.
- Introduce ArkType development dependencies and project configuration updates.
- Configure tsconfig to exclude the new ArkType test directory from compilation.
- Support `io: 'input'` and `io: 'output'` in `toJsonSchema` to control morph and default representation.
- Track `.to(target)` step output IR to drive output-side JSON schemas for piped types.
- Update string DSL inference to correctly handle input-side union members and morph sources.
- Added a new SQuAD-based context-compression benchmark script for evaluating recall conditions.
- Added model and shape command-line arguments along with pricing and shape configurations.
- Updated default model variants and added an unknown billing family to shape resolution.
- Updated shape resolution and model resolution tests to verify the new defaults.
- Added Standard Schema V1 interop via `~standard` property to enable synchronous validation across tools like tRPC and @t3-oss/env.
- Added `fromJsonSchema()` function to rebuild callable schemas from JSON Schema documents with recursive reference support.
- Added comprehensive unit test suites covering Standard Schema validation and JSON Schema round-tripping.
Moved the direct DeepSeek enabled toggle into the thinking-only compat variant and normalized stale cached compat metadata before request encoding.
Fixes#7559
- Added an any-cutoff guard to InferDef/InferDefIn so permissive instantiation
terminates instead of recursing through spread/index members without bound.
- Boxed spread and index-signature recursion behind an interface member and
flattened primitive keyword lookup plus member-inference fallback chains.
- Gave BaseType (type.raw results) the fluent composition surface so .array()
and friends type-check.
- Preserved escaped control characters for the downstream reinterpretation safety decision.
- Covered the backslash-escaped git inline shell-alias bypass.
Fixes#7552
- Treated double-quoted shell-control chars like single-quoted ones so a -c/-e reinterpretation option still gates them.
- Covered the double-quoted git inline shell-alias bypass.
Fixes#7552
- Added `compileAllows` and specialized `.allows()` caching for boolean validation.
- Optimized parser performance with helper methods for whitespace scans and object definitions.
- Cloned path arrays in error handling to prevent internal mutation bugs.
- Updated benchmarks and added unit tests covering nested and optional property validation.
- Replaced the raw character guard with quote-aware scanning while retaining command substitution and unquoted shell-control protections.
- Added regression coverage for the reported Cargo benchmark filter.
Fixes#7552
- Introduce `@oh-my-pi/omptype` as a new ArkType-compatible schema validation package featuring a lazy JIT runtime, JSON Schema emission, and compatibility adapters.
- Replace `arktype` across workspace packages and test utilities with `@oh-my-pi/omptype`.
- Add benchmark suites, tests, and documentation for the new validation engine and adapters.
- Update workspace build, test runner, and release configurations to include the new package.
install_binary downloaded the release binary, chmod'd it, and printed
"✓ Installed omp" with exit 0 without ever running it. Bun's musl-target
binaries link libstdc++/libgcc dynamically, which stock Alpine/musl systems
lack, so the binary exits 127 with relocation errors while the installer
still claimed success.
Smoke-run `omp --version` after install; on failure print the captured
error, add the `apk add libstdc++ libgcc` remediation for musl targets,
and exit non-zero. Document the Alpine/musl runtime requirement in the
README install section.
Fixes#7545
- Split the Python bridge signal: the raw abort reaches tools (so
subagents die with the turn) while a shielded signal governs how long
the host waits, so a cancel can no longer settle a cell on top of a
still-running isolation merge.
- Mirrored the contract in the JS runtime: abort in-flight tool calls
immediately, then drain any deferExternalAbort phase before killing
the worker, and refuse new bridge calls once cancelled.
- Held a finished worker result until the run's tool calls drain. A
floated agent() previously settled the cell at once, dropping the
run's abort listener and leaving the subagent running with nothing
able to cancel it.
- Added regression coverage for all three, each verified to fail
without its fix.
- Corrected the mapping of the "state" specifier to PsField::State in the ps format parser.
- Added a test to verify that the ps builtin successfully accepts tpgid and other job control columns.
- Handled broken pipe errors across tail output and follow paths by translating them to a silent SIGPIPE exit code.
- Prevented stderr noise when downstream pipeline readers exit early, matching native tail behavior.
Load project Codex MCP entries before user entries so a disabled project server claims its dedupe key before a same-named user server can survive.
Added regression coverage for project-over-user disable precedence.
Fixes#7538
- Added support for extended ps format specifiers including tpgid, ruid, rgid, egid, pri, flags, min_flt, maj_flt, times, sz, s, ruser, rgroup, and tgid.
- Implemented group name resolution via `getgrgid_r` on Unix platforms.
- Suppressed broken pipe diagnostic output in the tail builtin to match standard tail behavior on downstream closure.
Carry enabled = false through discovery so loadAllMCPConfigs' suppress
path can claim the dedupe key (keeping a same-named lower-priority
source disabled) and honor the user force-enable allowlist. Dropping the
entry outright defeated both.
Fixes#7538
- Warned when a K3 turn completed without thinking blocks so the source turn is visible before degraded replay.
- Reported one-based assistant-turn positions on first degraded replay and deduplicated subsequent warnings for the same messages.
- Covered completion and replay warning behavior.
Fixes#7516
shouldSendServiceTier/applyOpenAIServiceTier began forwarding every tier —
including `auto` — for openai/openai-codex after PR #7376. Legacy/default
sessions resolve to {openai:"auto"}, so Codex (ChatGPT OAuth) requests now
carry service_tier:"auto", which that endpoint rejects with a 400, breaking
every turn at default settings.
Never send `auto`: it is OpenAI's implicit default, so omitting service_tier
is identical where accepted and required where the tier is rejected. Explicit
default/flex/scale/priority are unchanged.
Fixes#7517
assertCursorKimiK3HistoryReplayable threw for any assistant turn lacking a
non-empty thinking block, including same-model kimi-k3 turns whose stream
carried no thinkingDelta events. Such a turn is persisted with only
text/toolCall blocks, so every subsequent turn failed locally before any
request, permanently bricking the session.
Split the two failure modes: foreign history still hard-errors (another
model's turns cannot replay K3 reasoning), but a same-model turn missing
thinking now degrades to a one-time warning and replays without the
reasoning part via buildCursorAssistantContent, which already omits it.
Fixes#7516