The build host can validate and update stable provider compatibility manually. Codex changes reach installed gateways through the normal verified gateway release. Claude and Copilot use private verified installations on that host; new processes select the current installation and running sessions keep theirs.
Official stable releases
↓
Private candidate checkout and CLI installations
↓
Gateway tests + CLI handshakes + patched Codex build and actual gateway mock turn
↓ pass ↓ fail
Generated pins and CLI paths Last verified source and CLI paths stay
↓
Normal gateway release and idle activation
| Provider | Discovery | Compatibility gate |
|---|---|---|
| Codex gateway SDK | Official stable GitHub release, tag resolved to its immutable commit | Archive SHA-256, sequential gateway patches, locked Rust build, all 34 identity/compaction/queue/client-tool/role-context/cache/background-completion regressions, release executable |
| Claude Code | Official npm latest stable release and exact-version metadata |
SHA-512 archive integrity, private native installation, version, required public flags, actual stream-json control initialization using the gateway's complete CLI arguments, request shapes through the candidate's Messages parser |
| GitHub Copilot | Official npm latest stable release and exact-version metadata |
SHA-512 archive integrity, private installation, version, required public flags, actual gateway RPC framing and protocol 3 handshake |
| API-only providers | No local provider executable | Existing translation and transport tests; caller models, endpoints and credentials stay unchanged |
Claude and Copilot have no manually maintained version whitelist. Their validation
record in provider-compatibility.json documents tested versions. On promotion,
private immutable installations go under
~/.local/share/harness-gateway/provider-tools/<integration-contract>/installs, and an atomic
current.json selects both versions. The gateway verifies the whole dependency
tree before selecting a new process. A changed managed installation fails closed.
An installation without a managed entry continues to use PATH.
The job never replaces global CLIs or redistributes their packages. Official package installers run inside the private candidate prefix and HOME, without inherited provider credentials or Node injection variables. Provider licenses stay with those private installations. Runtime authentication keeps each account's existing directory; validation homes are never reused for real requests. CLI self-updates are disabled in gateway-owned launches, including sign-in. The integration contract derives from the gateway's CLI adapter source files. Older gateway releases retain their own verified installations when those adapters change; testing an unreleased adapter cannot change their selected tools.
The signed app engine and native relay are separate compatibility boundaries. This job updates the gateway's patched Codex SDK. It does not replace or re-sign the app's native executable, or automatically expand native sharing and relay allowlists. Those depend on signature, ownership and transport checks described in architecture and native remote.
Commands
Run npm ci and npm run build on the Apple Silicon build host first. Rust and
the usual release build tools must already be available.
npm run providers:check
npm run providers:update
npm run providers:update -- --commit
npm run providers:schedule -- status
npm run providers:schedule -- uninstall
providers:check prepares and validates a candidate. providers:update also
promotes the five generated files and managed CLI installations when source HEAD
is unchanged and the checkout is still clean. --commit uses committer with
those explicit source paths.
It never pushes, merges, publishes a release, dispatches hosted CI or restarts
a gateway. A dirty checkout refuses automatic promotion.
The former standalone daily developer LaunchAgent is retired. install refuses
to create it, preserving the single signed app-owned background item. Provider
compatibility builds remain manual; model-family discovery still runs
automatically inside the app service. Manual maintenance leaves a dirty checkout
or a different branch alone and uses the private-file lock. It creates no GitHub
Actions trigger. See the CI cost policy.
The fixed outcome and phase are in .state/provider-maintenance/latest.json;
the schedule prints only safe outcomes in schedule.log. A failed validator also
records bounded structured facts when available:
| Field | Saved information |
|---|---|
failureReason |
nonzero_exit, timeout, output_limit, spawn_error, or cancelled; the first cause is retained. |
exitCode, signal |
Numeric exit status and an allowed operating-system signal name. |
failureFiles, failureLocations |
Existing candidate-relative test files and their line numbers, with optional columns. |
failureTypes, compilerCodes |
Allowed Node test failure classes and Rust or TypeScript compiler codes. |
testTotals |
Numeric TAP or spec-reporter summary counts. |
Locations are restricted to the candidate's dist/tests/*.test.js and
scripts/tests/provider-*.test.mjs files. Absolute paths and file URLs are reduced
to relative paths only after containment checks. Arrays, paths, line buffers, and
counts are bounded. Metadata is validated again before it reaches the report,
including errors supplied by test doubles.
Raw messages, test titles, assertion values, stack traces, command arguments,
environment values, and provider output are not retained. Failed candidates stay
under that directory for inspection. Validation
uses no subscription inference or copied authentication. Handshakes prove CLI
interfaces, not model behavior or billing.
Maintenance limits the source suite to four concurrent fixture files to avoid
host-load-dependent lease and startup failures. The ordinary runner keeps its
eight-file cap; GATEWAY_TEST_CONCURRENCY can lower it to any value from 1 to 8.
An upstream incompatibility is a blocked update, not permission to weaken
permissions or remove tests. The job retains the existing pins and retries on the
next run. Compatible releases need no manual version or hash edits. A breaking
patch, protocol, schema or safety change still requires implementation work.
SDK builds retain immutable source paths through the updater's --build-root
selection, while still verifying the archive, complete tree and build outputs.
A private build lock serializes their temporary compaction-test isolation.
After an interruption, only the authenticated original or reduced aggregator can
be recovered automatically; other changes remain a blocked update.
Claude Code request shapes
The stream-json check proves the CLI the gateway launches. It does not prove what
Claude Code sends when it is the client, and the Messages parser accepts only the
fields it knows. So the candidate also runs real Claude Code against a synthetic
local backend that answers through the candidate's own parser, routing rules and
error envelope. Each accepted request then runs through the real Chat Completions,
Anthropic and Responses adapters against a local stub, on a route that offers only
low, medium and xhigh. A refusal there reaches the client just as it would
from Gateway, so a default effort a route rejects fails the check. No provider,
account or paid inference is involved.
| Scenario | What it proves |
|---|---|
opaque_alias |
A gateway alias finishes, and the declared context window is applied. |
recognized_model |
A Claude model ID finishes; these IDs get different beta values. |
mcp_tools |
A large MCP catalog finishes. |
tool_round_trip |
A real tool call and result pass the parser. |
subagent |
A real subagent keeps its own conversation key. |
auto_review |
The classifier keeps the exact shape Gateway reviews natively, and the reviewed action then runs. A changed shape is refused, which blocks the update. |
The check also needs Claude Code's session UUID and request-class header on each accepted request, because live sessions and hint handling depend on them.
A rejection counts as known only when removing a field from the list in Messages makes the request valid. Any other rejection blocks the candidate, even when Claude Code recovers, because a retry can turn a feature off without telling anyone. A client that cannot finish also blocks it. The last verified CLI stays selected until Gateway is updated.
The candidate's request-shape.json report and the requestShape field in
provider-compatibility.json hold field names, beta values and counts, never
prompts or tool content. Comparing requestShape between versions shows what
changed. To test any installed CLI by hand, build first and then run:
node scripts/claude-request-shape.mjs --claude /absolute/path/to/claude \
--package "$PWD" --root "$(mktemp -d /tmp/claude-request-shape.XXXXXX)"
The exit code is non-zero when the shape changed. This proves request shapes only. It does not prove model behavior, cache use or long sessions.
Generated SDK inputs
src/gateway-sdk-pin.json is the single upstream identity used by build scripts
and the compiled runtime. The candidate derives workspace lock repairs and test
aggregator hashes from the selected immutable source. A changed test boundary
blocks the candidate; it never silently skips the regression suite.
src/gateway-feature-schema-data.json derives strict feature tables and nested
fields from upstream config.schema.json. Unsupported schema shapes block the
candidate. Network limits retain their existing fail-closed handling.
src/gateway-sdk-build-pins.ts contains derived source and patch hashes; generate
it with npm run sdk:pins and check it with:
node scripts/sync-gateway-sdk-pins.mjs --check
npm run providers:test
The other generated files are the adapter integration contract and
provider-compatibility.json. A cached successful
candidate is valid only for the same source revision, releases, generated bytes,
SDK receipt/binary and CLI dependency trees. Corrupt caches trigger validation
again. A durable source-promotion journal recovers interrupted writes while
preserving any intervening user edit. Source promotion never overwrites other work. Installation and
runtime receipt checks still require exact versions, digests and gateway patch
capabilities for the selected release.