Skip to content

test: hermetic e2e suite for Altimate Base (registration, catalog, inference, rate-limit/budget, error surfacing) - #1248

Merged
anandgupta42 merged 2 commits into
codex/altimate-base-release-finalfrom
test/altimate-base-e2e
Sep 7, 2026
Merged

test: hermetic e2e suite for Altimate Base (registration, catalog, inference, rate-limit/budget, error surfacing)#1248
anandgupta42 merged 2 commits into
codex/altimate-base-release-finalfrom
test/altimate-base-e2e

Conversation

@anandgupta42

@anandgupta42 anandgupta42 commented Sep 4, 2026

Copy link
Copy Markdown
Contributor

Issue for this PR

Closes #1247

Type of change

  • New feature
  • Bug fix
  • Refactor / code improvement
  • Documentation

What does this PR do?

Adds 53 hermetic e2e tests across 5 suites for Altimate Base's free-tier client (src/altimate/free/*), consolidated onto the shared _fixtures/altimate-base-harness.ts + _fixtures/fake-gateway.ts harness already on this branch:

  • altimate-base-registration-gaps.test.ts (11) — HTTP 4xx/5xx/network/malformed-JSON register failure mapping onto RegistrationError, the exact request payload (hashed install secret, cli_version), and retry idempotency.
  • altimate-base-catalog.test.ts (9) — model catalog / provider isolation (Provider.list() / Provider.defaultModel() / Provider.sort()) against a credential minted through the real consent + register path.
  • altimate-base-inference-e2e.test.ts (5) — full register → provider-list → authorizedFetch round trip, plus the placeholder-vs-real-key and credential-storage isolation properties.
  • altimate-base-rate-limit-messages.test.ts (21) — every describeRateLimit / describeRequestTooLarge branch: per-minute token throttle, burst throttle, wallet/global/unknown budget, request-too-large byte math, and the malformed/unrecognized fallback paths.
  • altimate-base-error-surfacing.test.ts (7) — non-rate-limit inference-time failures reach authorizedFetch's caller cleanly: 5xx pass-through, timeout/abort propagation, raw connection failure, malformed JSON body, and chat-time 401.

All suites are fully hermetic — fetch is injected via the shared FakeGateway fixture (spyOn(globalThis, "fetch")), so there is no live gateway, no credentials, and no network access anywhere in this PR. Each suite runs in its own isolated XDG/home tree (isolateAltimateBaseHome) so credential stores, config, and cache never collide across files or touch a real user directory. This is picked up by CI automatically via the existing test/altimate/** path filters — no workflow change needed.

The centralized-arming fix (the load-bearing change in this PR): FreeTierCapability.issueArmer() is a process-global capability that throws on a second call in the same process (by design — it's the security property that makes Altimate Base's consent gate unforgeable, see src/altimate/free/capability.ts). Every one of these 5 new suites, plus the two pre-existing files (altimate-base.test.ts, altimate-base-harness-smoke.test.ts), independently called issueArmer() at module scope. bun test test/altimate/ loads multiple test files into one worker process, so this throws "Altimate Base consent armer already issued for this process" as soon as a second armer-calling file loads — reproducible with just the two pre-existing files, before any of these suites existed.

Fixed by adding a consented() helper to the shared harness (_fixtures/altimate-base-harness.ts) that lazily claims issueArmer() exactly once per process and caches the returned armer in a module-level singleton. Because bun caches modules per process, every suite file that imports consented() — regardless of load order or how many files load it — shares that one cached armer. All 7 armer-calling files (5 new + 2 existing) now go through this shared helper instead of claiming their own armer. This adds no way to reset, re-claim, or otherwise weaken the one-shot guarantee issueArmer() already enforces; it is purely a cache in front of the single legitimate call, so the underlying security property (only one in-process caller can ever obtain the ability to arm the production consent authority) is unchanged — the existing "unforgeable consent" test in altimate-base.test.ts (which asserts a second issueArmer()/issueRedeemer() call throws) still passes unmodified.

Live-prod smoke testing against a real gateway is intentionally out of scope here and tracked separately / non-blocking for this PR — everything in this PR is fetch-injected and hermetic.

This PR stacks on #1199 (Altimate Base hosted model release) — the base is codex/altimate-base-release-final so the diff here shows only the harness + tests, not #1199's feature changes. It should be retargeted to main once #1199 merges.

How did you verify your code works?

Ran the full test/altimate/ directory in one bun test invocation, matching CI's own invocation and timeout (bun test --timeout 90000, from packages/opencode, per .github/workflows/ci.yml's typescript job):

bun test --timeout 90000 test/altimate/
 5103 pass
 653 skip
 0 fail
Ran 5756 tests across 186 files. [~75s]

Zero "consent armer already issued" errors — this is the actual acceptance bar, not file-by-file green (each file was also independently confirmed green: 11 + 9 + 5 + 21 + 7 = 53 new tests, all passing).

Also verified:

  • bun run typecheck (bun turbo typecheck) — clean, 13/13 tasks successful.
  • bun run script/upstream/analyze.ts --markers --base origin/main --strict — clean, no unmarked upstream-shared changes.
  • bunx prettier --check on all changed files — clean.

Screenshots / recordings

N/A — test-only change, no UI.

Checklist

  • I have tested my changes locally
  • I have not included unrelated changes in this PR

Note

Low Risk
Test-only changes with no runtime behavior modifications; the shared consented() helper preserves the one-shot issueArmer() security model while fixing multi-file test loading.

Overview
Adds a hermetic Altimate Base e2e test layer built on shared _fixtures/altimate-base-harness.ts (isolated XDG home, gateway env reset) and _fixtures/fake-gateway.ts (spyOn(globalThis, "fetch") for /register and chat completions with scripted error modes). Five new suites cover registration failure gaps, provider catalog/defaultModel() behavior, register→Provider.list()authorizedFetch inference, full describeRateLimit / describeRequestTooLarge branches, and inference-time 5xx/timeout/network/malformed-JSON/401 surfacing; a small harness smoke file exercises the fixtures.

Load-bearing harness fix: all suites (and the existing altimate-base.test.ts) now mint consent via shared consented(), which lazily claims FreeTierCapability.issueArmer() once per process so bun test test/altimate/ does not crash when multiple files load in one worker.

Also adds docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md as the design contract. The planned context-clamp suite is not in this diff (still flagged in the doc). No production source changes; tests only, no CI workflow edits.

Reviewed by Cursor Bugbot for commit d2973f4. Bugbot is set up for automated code reviews on this repo. Configure here.


Summary by cubic

Adds 53 hermetic e2e tests across 5 suites for Altimate Base's free-tier client (closes #1247), and centralizes the process-global issueArmer() capability behind a shared consented() helper so all test files run together in one worker process without the "consent armer already issued" crash.

Coverage

  • New suites cover registration-failure mapping, catalog/provider isolation, register-to-inference round trips, rate-limit/budget message mapping, and inference-time error surfacing.
  • All tests inject fetch via the shared FakeGateway fixture with isolated XDG/home trees — no network, credentials, or live gateway.
  • Verified in one bun test invocation at CI's timeout (5103 pass, 0 fail), and the diff is test-only since it stacks on feat: release Altimate Base hosted model #1199 — retarget to main once that merges.

Consent armer

  • issueArmer() throws on a second in-process call by design; 7 files each claiming it at module scope crashed under bun's single-worker test loading.
  • consented() lazily claims the armer once per process and caches it, so all 7 files share it — the unforgeable-consent guarantee is unchanged and still covered by an existing test.

Written for commit d2973f4. Summary will update on new commits.

Review in cubic

anandgupta42 and others added 2 commits September 4, 2026 12:10
Foundation for a 6-suite parallel Altimate Base e2e test partition (see the
design doc). Adds `test/altimate/_fixtures/fake-gateway.ts` (a `FakeGateway`
that intercepts `fetch` via `spyOn(globalThis, "fetch")` — the repo's
existing proven pattern, not a real HTTP server — implementing `/register`
and `/v1/chat/completions` with controllable knobs for every failure mode
the suites need: per-minute token rate-limit, both `budget_exceeded`
variants, request-too-large, 401, 5xx, timeout, malformed JSON, and success)
and `test/altimate/_fixtures/altimate-base-harness.ts` (isolated XDG/home
bootstrap + gateway-env reset helpers, extracted from
`altimate-base.test.ts`'s existing pattern so every suite shares one
implementation).

Adds `altimate-base-harness-smoke.test.ts` proving the harness works in
both directions: a register -> `authorizedFetch` happy-path round trip, and
one scripted failure knob (per-minute token rate-limit ->
`describeRateLimit`'s non-retryable message).

Does not add any of the 6 planned suite files themselves — those are a
separate, parallel follow-up. Copies the design doc
(`docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md`) into the
branch so it travels with the PR.

Stacked on `codex/altimate-base-release-final` (#1199) since the harness
targets that branch's 131072/65536 limits and Altimate Base code.
…rming

Brings together 5 independently-written hermetic e2e suites for Altimate
Base onto the shared harness branch (53 tests):
- `altimate-base-registration-gaps.test.ts` (11) — HTTP/network/malformed
  register failure mapping, payload shape, retry idempotency
- `altimate-base-catalog.test.ts` (9) — model catalog / provider isolation
- `altimate-base-inference-e2e.test.ts` (5) — register -> list -> fetch
  round trip, placeholder-vs-real-key isolation
- `altimate-base-rate-limit-messages.test.ts` (21) — throttle/budget/
  request-too-large message mapping
- `altimate-base-error-surfacing.test.ts` (7) — 5xx/timeout/abort/
  malformed-body/401 pass-through at the inference layer

All 5 (plus the two pre-existing files, `altimate-base.test.ts` and
`altimate-base-harness-smoke.test.ts`) independently called
`FreeTierCapability.issueArmer()` at module scope. That capability is
process-global and throws on a second call, so running the directory in
one `bun test` invocation — as CI does — threw "Altimate Base consent
armer already issued for this process" once a second armer-calling file
loaded into the same worker process (reproducible with just the two
pre-existing files, before any of these suites existed).

Fix: centralize arming in the shared harness
(`_fixtures/altimate-base-harness.ts`) behind a new `consented()` helper
that lazily calls `issueArmer()` exactly once per process and caches the
returned armer in a module-level singleton. Because bun caches modules
per process, every suite file that imports `consented()` shares that one
cached armer regardless of load order or file count. This adds no way to
reset, re-claim, or otherwise weaken the one-shot guarantee
`issueArmer()` already enforces — it is a cache in front of the single
legitimate call, not a new capability. All 7 armer-calling files now
import and use the shared helper instead of claiming their own.

Verified with `bun test --timeout 90000 test/altimate/` (the directory
CI covers, at CI's timeout) from `packages/opencode`: 5103 pass, 0 fail,
zero armer-collision errors, in one process invocation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqnuBDGkh1ZT65Ti7e6DHZ

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.

Tip: disable this comment in your organization's Code Review settings.

@cursor

cursor Bot commented Sep 4, 2026

Copy link
Copy Markdown

Bugbot couldn't run - usage limit reached

Bugbot is counted against Cursor usage for this user or team, and this run hit a usage or spend limit.

A user or team admin can review and increase usage limits in the Cursor dashboard.

(requestId: serverGenReqId_e9e0cb77-cc9e-4751-b90e-c28b01e5b412)

@coderabbitai

coderabbitai Bot commented Sep 4, 2026

Copy link
Copy Markdown

Important

Review skipped

Auto reviews are disabled on base/target branches other than the default branch.

Please check the settings in the CodeRabbit UI or the .coderabbit.yaml file in this repository. To trigger a single review, invoke the @coderabbitai review command.

⚙️ Run configuration

Configuration used: Repository UI

Review profile: CHILL

Plan: Team

Run ID: 584ad642-1ad6-45c8-b003-d337a1cf84f6

You can disable this status message by setting the reviews.review_status to false in the CodeRabbit configuration file.

Use the checkbox below for a quick retry:

  • 🔍 Trigger review

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 4, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-04T19:52:41.643544Z d2973f4 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

Thanks for your contribution!

This PR doesn't have a linked issue. All PRs must reference an existing issue.

Please:

  1. Open an issue describing the bug/feature (if one doesn't exist)
  2. Add Fixes #<number> or Closes #<number> to this PR description

See CONTRIBUTING.md for details.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown
- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
            3 sessions behind this PR             

builder · claude-sonnet-5...............≥ $19.0480
  session slice: turns 1–234 of 270
builder · claude-sonnet-5................≥ $2.6255
  session slice: turns 212–230 of 278
builder · claude-sonnet-5................≥ $1.2645
  session slice: turns 1–28 of 30
--------------------------------------------------
TOTAL priced............................≥ $22.9380
  standard API-equivalent floor; not an invoice
  counted: 3 sessions
  cache served 99% of input tokens
  full receipts + session ids: section below
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -
full receipts (3 sessions)
session id scope turns time tokens in / out cached
builder a7b26059 turns 1–234 of 270 234 40m 468 / 12k 99%
builder a322d28e turns 212–230 of 278 19 9m 38 / 268 94%
builder a1b6d225 turns 1–28 of 30 28 3m 56 / 1.5k 97%

builder · a7b26059

- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
 “Address the 8 unresolved review threads (seve…” 
 Claude Code · Sep 04 2026 01:47:05 UTC · 40m 58s 
               claude-sonnet-5 100%               
         cache served 99% of input tokens         

pre-edit: 10% of priced floor (45/234 turns)
  (share before the first named edit tool)

Bash.......................≥ $10.9728  (132 calls)
Read.........................≥ $4.4082  (56 calls)
Edit.........................≥ $3.1686  (38 calls)
ToolSearch....................≥ $0.1670  (3 calls)
Monitor........................≥ $0.1196  (1 call)
Write..........................≥ $0.1056  (1 call)
EnterWorktree.................≥ $0.0761  (2 calls)
ExitWorktree...................≥ $0.0297  (1 call)
--------------------------------------------------
TOTAL...................................≥ $19.0476
standard API-equivalent floor; not an invoice
same tokens on claude-haiku-4-5..........≥ $6.3493
  (67% lower observable floor)
  (arithmetic, not a prediction)
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -

builder · a322d28e

- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
 “Run a real end-to-end test of the Altimate Ba…” 
 Claude Code · Sep 04 2026 17:49:29 UTC · 9m 58s  
               claude-sonnet-5 100%               
         cache served 94% of input tokens         

pre-edit: no named edit tool observed
  (share before the first named edit tool)

Bash.........................≥ $2.4480  (17 calls)
(thinking/reply)...............≥ $0.0930  (1 turn)
Read...........................≥ $0.0843  (1 call)

≈ re-priced eligible trivial spans.......≈ $0.0310
  (1 tiny turns, priced at claude-haiku-4-5)
--------------------------------------------------
TOTAL....................................≥ $2.6253
standard API-equivalent floor; not an invoice
same tokens on claude-haiku-4-5..........≥ $0.8751
  (67% lower observable floor)
  (arithmetic, not a prediction)
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -

builder · a1b6d225

- - - - - - - - - - - - - - - - - - - - - - - - -
                    AIRECEIPTS                    
 “Foundation step for the Altimate Base e2e tes…” 
 Claude Code · Sep 04 2026 19:05:28 UTC · 3m 36s  
               claude-sonnet-5 100%               
         cache served 97% of input tokens         

pre-edit: 45% of priced floor (10/28 turns)
  (share before the first named edit tool)

Bash.........................≥ $0.8397  (21 calls)
Read..........................≥ $0.2605  (3 calls)
Write.........................≥ $0.1163  (3 calls)
Edit...........................≥ $0.0479  (1 call)
--------------------------------------------------
TOTAL....................................≥ $1.2644
standard API-equivalent floor; not an invoice
same tokens on claude-haiku-4-5..........≥ $0.4215
  (67% lower observable floor)
  (arithmetic, not a prediction)
- - - - - - - - - - - - - - - - - - - - - - - - -
                npx aireceipts-cli                
         github.com/anandgupta42/receipts         
- - - - - - - - - - - - - - - - - - - - - - - - -
handoff — flagged pattern cost ≈ 280,013 tok
FLAGGED PATTERN COST.................≈ 280,013 tok
  heuristic pattern subtotal · not proven savings

≈ re-priced eligible trivial spans.......≈ $0.0310
  (1 tiny turns, priced at claude-haiku-4-5)
  → route short replies to a cheaper model

covers: 3 sessions · 281 turns · 1 flagged-pattern line

Generated by aireceipts

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

2 similar comments
@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@github-actions

github-actions Bot commented Sep 4, 2026

Copy link
Copy Markdown

👋 This PR was automatically closed by our quality checks.

Common reasons:

  • New GitHub account with limited contribution history
  • PR description doesn't meet our guidelines
  • Contribution appears to be AI-generated without meaningful review

If you believe this was a mistake, please open an issue explaining your intended contribution and a maintainer will help you.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d2973f4ec9

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

// kicking off the call could fire before the fake gateway's `timeout` branch has attached its
// `abort` listener. `AbortSignal.timeout` schedules the abort on a real timer instead, so it
// always fires after the listener is attached.
const promise = FreeTier.authorizedFetch(url, { ...init, signal: AbortSignal.timeout(50) })

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Wait for fake-gateway readiness before aborting

On a slow CI filesystem, credentialsForLoad() can take longer than 50 ms, so this signal may abort before FakeGateway.handleChat() installs its abort listener. The fake does not check signal.aborted when entering timeout mode, leaving its promise pending until Bun's 30-second test timeout. Publish gateway readiness and abort afterward, or make the fake immediately reject an already-aborted signal.

AGENTS.md reference: packages/opencode/test/AGENTS.md:L165-L169

Useful? React with 👍 / 👎.

Comment on lines +81 to +83
function armer(): (token: string) => void {
if (!cachedArmer) cachedArmer = FreeTierCapability.issueArmer()
return cachedArmer

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Claim the consent armer before filtered tests run

Because the shared armer is now claimed lazily, running only the existing unforgeable consent: no in-process caller can mint an independent authority test means no earlier call to consented() has occurred. Its direct FreeTierCapability.issueArmer() call therefore succeeds even though the test expects it to throw, so common bun test -t ... workflows fail. Claim the armer during module setup or explicitly initialize it in that test before checking the second-claim behavior.

Useful? React with 👍 / 👎.

Comment on lines +84 to +87
const response = await FreeTier.authorizedFetch(`${GATEWAY_URL}/v1/chat/completions`, chatRequestInit())

expect(response.status).toBe(200)
const body = (await response.json()) as { choices: [{ message: { content: string } }] }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Exercise inference through the configured provider model

This purported inference E2E path calls FreeTier.authorizedFetch directly and manually parses the response, so it never constructs the @ai-sdk/openai-compatible model or exercises Provider.getModel/Provider.getLanguage, request serialization, model selection, and SDK response decoding. A regression that leaves the fetch function present in provider options but makes the configured model unusable would therefore pass the entire new suite; drive a generation through the provider model, as other provider E2E tests do, instead of invoking the transport seam directly.

Useful? React with 👍 / 👎.

Comment on lines +81 to +84
const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url
if (url.endsWith("/register")) return this.handleRegister(url, init)
if (url.includes("/v1/chat/completions")) return this.handleChat(url, init)
throw new Error(`FakeGateway: unhandled URL ${url}`)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate HTTP methods and exact routes in the fake gateway

The fake dispatches only by URL suffix/substring and never checks init.method, so it accepts requests that the real gateway rejects—for example, a registration accidentally changed from POST to GET, or a chat request sent to /v1/chat/completions-invalid. Because replacing global fetch also bypasses native rejection of a GET request with a body, the registration contract tests can remain green while the shipped client fails before reaching the gateway. Match the exact pathname and require POST for both routes.

Useful? React with 👍 / 👎.

import fs from "node:fs"
import os from "node:os"
import path from "node:path"
import { consented } from "./_fixtures/altimate-base-harness"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Redundant environment-isolation code — consolidate onto the shared helper.

This file still hand-rolls the XDG/home isolation (isolatedEnvironment, originalEnvironment, temporaryHome, and the afterAll cleanup at lines 8-21 and 68-75), duplicating what isolateAltimateBaseHome() in _fixtures/altimate-base-harness.ts now provides. The harness plan (docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md) explicitly intended altimate-base.test.ts to import the shared bootstrap so there is "exactly one isolated-environment implementation", but only consented() was migrated. Replace the inline block with isolateAltimateBaseHome("altimate-base").


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

claimable exactly once **per process**, not per file. `bun test` runs each test file in its own
worker process by default (confirmed by the existing suite's comment at `altimate-base.test.ts:76-82`
treating this as safe), so each suite file gets its own fresh module instances and can safely call
`FreeTierCapability.issueArmer()` at module scope, exactly like the existing file does. **Do not**

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: This guidance contradicts the shipped fix and would reintroduce the crash.

This section instructs each suite to call FreeTierCapability.issueArmer() at module scope on the premise that "bun test runs each test file in its own worker process." The actual fix in this PR (consented() in _fixtures/altimate-base-harness.ts) exists precisely because multiple suite files load into one worker, where a second module-scope issueArmer() throws. A future implementer following this section (or the example test later in this file that calls issueArmer() directly) would reintroduce the "consent armer already issued" crash. Update this section to direct suites to use consented() instead.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Sep 4, 2026

Copy link
Copy Markdown

Code Review Summary

Status: 2 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 0
WARNING 0
SUGGESTION 2
Issue Details (click to expand)

SUGGESTION

File Line Issue
packages/opencode/test/altimate/altimate-base.test.ts 6 Redundant inline XDG/home-isolation block duplicates the new isolateAltimateBaseHome helper; only consented() was consolidated
docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md 232 "Cross-file consent isolation" guidance (each file calls issueArmer() at module scope) contradicts the shipped consented() fix
Files Reviewed (10 files)
  • docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md - 1 issue
  • packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts
  • packages/opencode/test/altimate/_fixtures/fake-gateway.ts
  • packages/opencode/test/altimate/altimate-base-catalog.test.ts
  • packages/opencode/test/altimate/altimate-base-error-surfacing.test.ts
  • packages/opencode/test/altimate/altimate-base-harness-smoke.test.ts
  • packages/opencode/test/altimate/altimate-base-inference-e2e.test.ts
  • packages/opencode/test/altimate/altimate-base-rate-limit-messages.test.ts
  • packages/opencode/test/altimate/altimate-base-registration-gaps.test.ts
  • packages/opencode/test/altimate/altimate-base.test.ts - 1 issue

Fix these issues in Kilo Cloud


Reviewed by deepseek-v4-pro · Input: 96.3K · Output: 32.8K · Cached: 1.3M

Review guidance: REVIEW.md from base branch codex/altimate-base-release-final

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

8 issues found across 10 files

Prompt for AI agents (unresolved issues)

Check if these issues are valid — if so, understand the root cause of each and fix them. If appropriate, use sub-agents to investigate and fix each issue separately.


<file name="packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts">

<violation number="1" location="packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts:59">
P3: resetGatewayEnv() permanently mutates process env: it deletes ALTIMATE_FREE_GATEWAY_URL and sets ALTIMATE_BASE_GATEWAY_URL to the fake gateway URL, but no teardown restores the prior values. isolateAltimateBaseHome()'s afterAll only restores the ISOLATED_ENV keys, so in a shared `bun test` worker the fake gateway URL stays set and the legacy var stays deleted after the suite. Follow the file's own restoration pattern: capture the original values once (e.g., alongside the ISOLATED_ENV snapshot in isolateAltimateBaseHome) and restore them in the afterAll.</violation>

<violation number="2" location="packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts:79">
P2: When the unforgeable-consent test runs alone with `bun test -t`, `cachedArmer` is still unset, so its direct `issueArmer()` call succeeds instead of throwing. Claim the shared armer during module setup so filtered tests still exercise a second claim.</violation>
</file>

<file name="docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md">

<violation number="1" location="docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md:3">
P3: The doc's status header says "Not yet implemented" and describes itself as the contract for implementer agents, but every suite and fixture it specifies is implemented and shipped in this same PR. Its Deliverable 2 example and "Cross-file consent isolation" section also instruct each file to claim `issueArmer()` once at module scope, whereas the shipped harness uses a shared `consented()` singleton that claims the process's single armer — the exact collision this PR was built to fix. Update the status to reflect that the design is implemented and that the consent helper is a per-process `consented()` shared across files, not a per-file `issueArmer()`, so a future reader doesn't follow the stale design.</violation>

<violation number="2" location="docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md:360">
P2: The fake gateway accepts invalid methods and paths, allowing contract tests to pass for requests the real gateway rejects. Dispatch only when the exact pathname is paired with `POST` for both routes.</violation>
</file>

<file name="packages/opencode/test/altimate/_fixtures/fake-gateway.ts">

<violation number="1" location="packages/opencode/test/altimate/_fixtures/fake-gateway.ts:151">
P3: The `timeout` chat mode never settles when the request has no AbortSignal, and also hangs if the signal is already aborted before the listener attaches. Check the signal and reject immediately in those cases so a mis-scripted test degrades to a clear rejection instead of a hang until Bun's global timeout.</violation>
</file>

<file name="packages/opencode/test/altimate/altimate-base-registration-gaps.test.ts">

<violation number="1" location="packages/opencode/test/altimate/altimate-base-registration-gaps.test.ts:143">
P3: The primary assertion in the cli_version test is a tautology: `sentVersion` is computed by the client as exactly `sanitizeCliVersion(Installation.VERSION)`, so comparing it to the same re-called function can never fail independently and gives false confidence that the sanitizer contract is being exercised. The only meaningful check is the following regex. Make the assertion self-contained by hardcoding an expected value, or rely on the regex alone and drop the self-comparison.</violation>
</file>

<file name="packages/opencode/test/altimate/altimate-base.test.ts">

<violation number="1" location="packages/opencode/test/altimate/altimate-base.test.ts:6">
P3: Use `isolateAltimateBaseHome("altimate-base")` here and remove the inline environment setup so this file has the same single isolation implementation as the new suites.</violation>
</file>

<file name="packages/opencode/test/altimate/altimate-base-inference-e2e.test.ts">

<violation number="1" location="packages/opencode/test/altimate/altimate-base-inference-e2e.test.ts:84">
P2: This test bypasses the configured `@ai-sdk/openai-compatible` model, so it cannot catch broken model construction, provider model selection, request serialization, or SDK response decoding. Drive a generation through the provider model instead.</violation>
</file>

Tip: cubic can generate docs of your entire codebase and keep them up to date. Try it here.

Re-trigger cubic

// otherwise bypass that one-shot guarantee. It is purely a shared cache in front of the single
// legitimate call, so the underlying security property (only one in-process caller can ever obtain
// the ability to arm the production consent authority) is unchanged.
let cachedArmer: ((token: string) => void) | undefined

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: When the unforgeable-consent test runs alone with bun test -t, cachedArmer is still unset, so its direct issueArmer() call succeeds instead of throwing. Claim the shared armer during module setup so filtered tests still exercise a second claim.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts, line 79:

<comment>When the unforgeable-consent test runs alone with `bun test -t`, `cachedArmer` is still unset, so its direct `issueArmer()` call succeeds instead of throwing. Claim the shared armer during module setup so filtered tests still exercise a second claim.</comment>

<file context>
@@ -0,0 +1,95 @@
+// otherwise bypass that one-shot guarantee. It is purely a shared cache in front of the single
+// legitimate call, so the underlying security property (only one in-process caller can ever obtain
+// the ability to arm the production consent authority) is unchanged.
+let cachedArmer: ((token: string) => void) | undefined
+
+function armer(): (token: string) => void {
</file context>

Comment on lines +360 to +361
if (url.endsWith("/register")) return this.handleRegister(url, init)
if (url.includes("/v1/chat/completions")) return this.handleChat(url, init)

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: The fake gateway accepts invalid methods and paths, allowing contract tests to pass for requests the real gateway rejects. Dispatch only when the exact pathname is paired with POST for both routes.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md, line 360:

<comment>The fake gateway accepts invalid methods and paths, allowing contract tests to pass for requests the real gateway rejects. Dispatch only when the exact pathname is paired with `POST` for both routes.</comment>

<file context>
@@ -0,0 +1,672 @@
+    this.spy = spyOn(globalThis, "fetch").mockImplementation(
+      (async (input: RequestInfo | URL, init?: RequestInit) => {
+        const url = typeof input === "string" ? input : input instanceof URL ? input.href : input.url
+        if (url.endsWith("/register")) return this.handleRegister(url, init)
+        if (url.includes("/v1/chat/completions")) return this.handleChat(url, init)
+        throw new Error(`FakeGateway: unhandled URL ${url}`)
</file context>
Suggested change
if (url.endsWith("/register")) return this.handleRegister(url, init)
if (url.includes("/v1/chat/completions")) return this.handleChat(url, init)
const request = new URL(url)
if (request.pathname === "/register" && init?.method === "POST") return this.handleRegister(url, init)
if (request.pathname === "/v1/chat/completions" && init?.method === "POST") return this.handleChat(url, init)

await registerWithGateway()

gateway.chatNext({ kind: "ok", content: "the answer is 42" })
const response = await FreeTier.authorizedFetch(`${GATEWAY_URL}/v1/chat/completions`, chatRequestInit())

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2: This test bypasses the configured @ai-sdk/openai-compatible model, so it cannot catch broken model construction, provider model selection, request serialization, or SDK response decoding. Drive a generation through the provider model instead.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/altimate-base-inference-e2e.test.ts, line 84:

<comment>This test bypasses the configured `@ai-sdk/openai-compatible` model, so it cannot catch broken model construction, provider model selection, request serialization, or SDK response decoding. Drive a generation through the provider model instead.</comment>

<file context>
@@ -0,0 +1,185 @@
+    await registerWithGateway()
+
+    gateway.chatNext({ kind: "ok", content: "the answer is 42" })
+    const response = await FreeTier.authorizedFetch(`${GATEWAY_URL}/v1/chat/completions`, chatRequestInit())
+
+    expect(response.status).toBe(200)
</file context>

export function resetGatewayEnv(gatewayUrl: string): void {
delete process.env.ALTIMATE_BASE_GATEWAY_URL
delete process.env.ALTIMATE_FREE_GATEWAY_URL
process.env.ALTIMATE_BASE_GATEWAY_URL = gatewayUrl

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: resetGatewayEnv() permanently mutates process env: it deletes ALTIMATE_FREE_GATEWAY_URL and sets ALTIMATE_BASE_GATEWAY_URL to the fake gateway URL, but no teardown restores the prior values. isolateAltimateBaseHome()'s afterAll only restores the ISOLATED_ENV keys, so in a shared bun test worker the fake gateway URL stays set and the legacy var stays deleted after the suite. Follow the file's own restoration pattern: capture the original values once (e.g., alongside the ISOLATED_ENV snapshot in isolateAltimateBaseHome) and restore them in the afterAll.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/_fixtures/altimate-base-harness.ts, line 59:

<comment>resetGatewayEnv() permanently mutates process env: it deletes ALTIMATE_FREE_GATEWAY_URL and sets ALTIMATE_BASE_GATEWAY_URL to the fake gateway URL, but no teardown restores the prior values. isolateAltimateBaseHome()'s afterAll only restores the ISOLATED_ENV keys, so in a shared `bun test` worker the fake gateway URL stays set and the legacy var stays deleted after the suite. Follow the file's own restoration pattern: capture the original values once (e.g., alongside the ISOLATED_ENV snapshot in isolateAltimateBaseHome) and restore them in the afterAll.</comment>

<file context>
@@ -0,0 +1,95 @@
+export function resetGatewayEnv(gatewayUrl: string): void {
+  delete process.env.ALTIMATE_BASE_GATEWAY_URL
+  delete process.env.ALTIMATE_FREE_GATEWAY_URL
+  process.env.ALTIMATE_BASE_GATEWAY_URL = gatewayUrl
+}
+
</file context>

@@ -0,0 +1,672 @@
# Altimate Base — E2E Test Suite: Spec, Harness Design, Parallel Partition

Status: Phase 1 (research + design) complete. Not yet implemented.

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The doc's status header says "Not yet implemented" and describes itself as the contract for implementer agents, but every suite and fixture it specifies is implemented and shipped in this same PR. Its Deliverable 2 example and "Cross-file consent isolation" section also instruct each file to claim issueArmer() once at module scope, whereas the shipped harness uses a shared consented() singleton that claims the process's single armer — the exact collision this PR was built to fix. Update the status to reflect that the design is implemented and that the consent helper is a per-process consented() shared across files, not a per-file issueArmer(), so a future reader doesn't follow the stale design.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md, line 3:

<comment>The doc's status header says "Not yet implemented" and describes itself as the contract for implementer agents, but every suite and fixture it specifies is implemented and shipped in this same PR. Its Deliverable 2 example and "Cross-file consent isolation" section also instruct each file to claim `issueArmer()` once at module scope, whereas the shipped harness uses a shared `consented()` singleton that claims the process's single armer — the exact collision this PR was built to fix. Update the status to reflect that the design is implemented and that the consent helper is a per-process `consented()` shared across files, not a per-file `issueArmer()`, so a future reader doesn't follow the stale design.</comment>

<file context>
@@ -0,0 +1,672 @@
+# Altimate Base — E2E Test Suite: Spec, Harness Design, Parallel Partition
+
+Status: Phase 1 (research + design) complete. Not yet implemented.
+Scope: PR #1199, branch `codex/altimate-base-release-final`.
+Author: research/design pass, 2026-09-04. No test code was written by this pass — this
</file context>

return new Response("", { status: 401 })
case "server-error":
return new Response("upstream error", { status: mode.status ?? 500 })
case "timeout":

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The timeout chat mode never settles when the request has no AbortSignal, and also hangs if the signal is already aborted before the listener attaches. Check the signal and reject immediately in those cases so a mis-scripted test degrades to a clear rejection instead of a hang until Bun's global timeout.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/_fixtures/fake-gateway.ts, line 151:

<comment>The `timeout` chat mode never settles when the request has no AbortSignal, and also hangs if the signal is already aborted before the listener attaches. Check the signal and reject immediately in those cases so a mis-scripted test degrades to a clear rejection instead of a hang until Bun's global timeout.</comment>

<file context>
@@ -0,0 +1,174 @@
+        return new Response("", { status: 401 })
+      case "server-error":
+        return new Response("upstream error", { status: mode.status ?? 500 })
+      case "timeout":
+        return new Promise<Response>((_resolve, reject) => {
+          init?.signal?.addEventListener("abort", () => reject(init.signal?.reason), { once: true })
</file context>
Suggested change
case "timeout":
case "timeout": {
const signal = init?.signal
if (signal?.aborted) return Promise.reject(signal.reason)
return new Promise<Response>((_resolve, reject) => {
signal?.addEventListener("abort", () => reject(signal.reason), { once: true })
})
}


expect(gateway.registerCalls).toHaveLength(1)
const sentVersion = gateway.registerCalls[0]!.cliVersion
expect(sentVersion).toBe(FreeTier.sanitizeCliVersion(Installation.VERSION))

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: The primary assertion in the cli_version test is a tautology: sentVersion is computed by the client as exactly sanitizeCliVersion(Installation.VERSION), so comparing it to the same re-called function can never fail independently and gives false confidence that the sanitizer contract is being exercised. The only meaningful check is the following regex. Make the assertion self-contained by hardcoding an expected value, or rely on the regex alone and drop the self-comparison.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/altimate-base-registration-gaps.test.ts, line 143:

<comment>The primary assertion in the cli_version test is a tautology: `sentVersion` is computed by the client as exactly `sanitizeCliVersion(Installation.VERSION)`, so comparing it to the same re-called function can never fail independently and gives false confidence that the sanitizer contract is being exercised. The only meaningful check is the following regex. Make the assertion self-contained by hardcoding an expected value, or rely on the regex alone and drop the self-comparison.</comment>

<file context>
@@ -0,0 +1,176 @@
+
+    expect(gateway.registerCalls).toHaveLength(1)
+    const sentVersion = gateway.registerCalls[0]!.cliVersion
+    expect(sentVersion).toBe(FreeTier.sanitizeCliVersion(Installation.VERSION))
+    // sanitizeCliVersion's contract: only these characters survive, capped at 32 chars, never empty.
+    expect(sentVersion).toMatch(/^[A-Za-z0-9._+-]{1,32}$/)
</file context>

import fs from "node:fs"
import os from "node:os"
import path from "node:path"
import { consented } from "./_fixtures/altimate-base-harness"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P3: Use isolateAltimateBaseHome("altimate-base") here and remove the inline environment setup so this file has the same single isolation implementation as the new suites.

Prompt for AI agents
Check if this issue is valid — if so, understand the root cause and fix it. At packages/opencode/test/altimate/altimate-base.test.ts, line 6:

<comment>Use `isolateAltimateBaseHome("altimate-base")` here and remove the inline environment setup so this file has the same single isolation implementation as the new suites.</comment>

<file context>
@@ -3,6 +3,7 @@ import { createHash, randomBytes } from "node:crypto"
 import fs from "node:fs"
 import os from "node:os"
 import path from "node:path"
+import { consented } from "./_fixtures/altimate-base-harness"
 
 const isolatedEnvironment = [
</file context>

@anandgupta42
anandgupta42 merged commit 5cadd14 into codex/altimate-base-release-final Sep 7, 2026
32 checks passed
anandgupta42 added a commit that referenced this pull request Sep 7, 2026
* feat: release Altimate Base hosted model

Rebase of PR #1199 (codex/altimate-base-release-final) onto current
origin/main. Squash-merged the 37 PR commits against main and resolved
the single content conflict in packages/opencode/src/session/llm.ts:
main's canonical `requestHeaders` (from mergeRequestHeaders, also used
by the output-token budget estimator) is now wrapped with
withManagedSessionHeaders() so Altimate Base (altimate-free provider)
requests still get the session-scoped X-Session-Id header, instead of
the PR's redundant inline header-object reconstruction.

No other files had real conflicts; ci.yml/release.yml picked up both
this branch's ALTIMATE_BASE_GATEWAY_URL env additions and main's
unrelated changes cleanly via auto-merge.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqnuBDGkh1ZT65Ti7e6DHZ

* fix: address PR #1199 review threads — unforgeable consent gate + model-precedence fixes

Rebased onto current origin/main (clean, no conflicts). Addresses all 8 unresolved
review threads on the Altimate Base release PR.

Security (P1, cubic + codex duplicate threads): the exported `ConsentCapabilityStore`
let any in-process caller construct their own store, arm it with a fabricated token, and
pass it straight to `registerAfterConsent()`, bypassing the disclosure gate entirely.
Redesigned so `registerAfterConsent` takes a bare token and checks it against a private,
module-scoped authority in `capability.ts` that is never exported. The only way to arm or
redeem that authority is `issueArmer()`/`issueRedeemer()`, each claimable exactly once per
process — claimed once by the TUI worker's consent gate at boot and once by `client.ts`
at module load. A caller can still construct their own `ConsentCapabilityStore` (kept
exported for direct unit tests of its TTL/eviction mechanics), but it is inert: a
self-armed store only ever validates against itself, never against what
`registerAfterConsent` actually checks. New tests prove both that a forged token is
rejected and that no in-process caller can obtain a second armer/redeemer.

Also fixes, per review:
- Namespace projection: all consumers (`client.ts`, `worker.ts`, tests) now import
  `FreeTierCapability` via `export * as` and reference members through it, per
  AGENTS.md's flat-export convention (superseded by the security redesign above).
- ACP default-model resolution (`acp/service.ts`): a project that sets
  `model: "altimate-free/altimate-base"` alongside any `provider` allowlist got a
  `defaultModel` resolved against the unfiltered provider map, even though the same
  allowlist had just excluded Altimate Base from the advertised snapshot — so ACP still
  selected and routed to it. Now resolves against the same filtered `snapshotProviders`
  used for the catalogue.
- Preserve an explicit Big Pickle re-selection (`tui/context/local.tsx`,
  `tui/app.tsx`): a user who registers Altimate Base and later deliberately picks Big
  Pickle through `/model` had that choice silently overwritten on the next launch,
  because it persisted through the same fields the retired implicit default used. Adds
  a separate `explicitDefault` marker, set only by an interactive picker, that legacy
  migration now checks before treating a persisted Big Pickle selection as the old
  implicit default.
- First-run picker race (`tui/app.tsx`, P2): the first-run picker effect was missing
  the `local.model.ready` gate its sibling migration effect already has, so it could
  misclassify a returning Big Pickle user as a fresh install if provider sync settled
  before `model.json`'s async read finished.
- 401-counter reset (`altimate/free/client.ts`, P2): a non-401 response that also
  wasn't a 2xx (429/503/etc.) left the consecutive-401 counter untouched instead of
  resetting it, so an unrelated rate-limit/outage response between two real 401s could
  still push a healthy credential past the persistence threshold.
- Wrong logout command in the disclosure (`tui/component/altimate-onboarding.tsx` +
  two docs pages): `/providers logout` is not a TUI slash command — only `/logout`
  exists, and it signs out of the paid gateway, not Altimate Base. Points to the actual
  CLI command, `altimate providers logout altimate-base`.

Verification: typecheck clean across all 15 workspace packages; upstream marker check
clean (`--base origin/main --strict`); altimate/free + acp + provider suites green
(6542 tests, 0 fail); full tui package suite green (285 tests, 0 fail).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqnuBDGkh1ZT65Ti7e6DHZ

* fix: align altimate-base static limits to the gateway's served 131072/65536

`provider.ts`: update the altimate-base static model definition's declared
`limit` from `{context: 65_536, output: 4_096}` to `{context: 131_072,
output: 65_536}` to match what the gateway actually serves and advertises
(Qwen3.8-27B natively supports 262144, so 131072 needs no YaRN scaling on
the gateway side).

This is the client's offline/fallback value only — the gateway is the
source of truth for what it actually serves. Keep the two in sync so they
never disagree. Output is a clean half of the context window rather than
the model's theoretical max because this is a reasoning+coding model
(reasoning tokens count toward output) and 65536 keeps a real free-tier
cost guardrail while guaranteeing ample input room.

Updates the matching assertion in provider.test.ts.

This addresses the root cause of "Context budget exceeded" on Altimate
Base's first message: the CLI's default agent prompt (~77-78K tokens)
never fit inside the old declared 65,536-token window. This client-side
change alone is not sufficient — the gateway must also actually serve
context 131072 / output 65536 for the launch blocker to resolve end to
end; that change is being made separately on the gateway side. The
gateway endpoint embedded into release builds still comes only from the
ALTIMATE_BASE_GATEWAY_URL build-time repo variable, never from source.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqnuBDGkh1ZT65Ti7e6DHZ

* feat: retire Big Pickle, default free slot to Altimate Base; accurate data-handling disclosure + docs; scrub model-name references

- Remove Big Pickle as a NEW selectable option from the full model catalog
  (`dialog-model.tsx`); the migration path for users already on Big Pickle
  (detection + Altimate Base consent gate) is untouched.
- Change the migration decline label to `No — pick something else` for both
  origins, and update the model-picker note to `free · no signup · rate
  limited` everywhere it appears (welcome picker, full catalog, `/connect`).
- Replace the `ALTIMATE_BASE_DISCLOSURE` consent-gate text with an accurate,
  shorter disclosure (secrets are masked but shouldn't be relied on; usage is
  rate limited); the fuller per-install-identifier detail moves to the docs.
- Rewrite the Altimate Base section of `providers.md` with an explicit
  Data handling note (logged/used to improve products including the model,
  secrets masked, pseudonymous not anonymous per the security FAQ, rate
  limited) and a contrast sentence pointing to the Altimate LLM Gateway for
  stronger data-handling guarantees.
- Scrub the served model's name from public docs and source comments
  (`quickstart.md`, `provider.ts`), replacing it with generic phrasing.
- Update `dialog-altimate-base.test.tsx` for the new disclosure text and the
  retired Big Pickle catalog entry.

* chore: [AI] scrub model-family metadata from Altimate Base entry

- `family: "qwen"` -> `family: "altimate"` on the Altimate Base catalog
  entry in `provider.ts`. Verified no behavior change: this model's
  providerID is `altimate-free`, so it never reaches the
  `providerID === "altimate-backend"` family-vendor switch in
  `session/system.ts` (prompt selection falls through to the `api.id`
  check instead), and `familyVendor()` does not map "qwen" to any vendor
  either way.
- Update the test and fixture that pinned the old value:
  `provider.test.ts` (assertion + test title) and
  `dialog-altimate-base.test.tsx` (mock fixture).

* test: hermetic e2e suite for Altimate Base (registration, catalog, inference, rate-limit/budget, error surfacing) (#1248)

* test: add shared hermetic harness for Altimate Base e2e suites

Foundation for a 6-suite parallel Altimate Base e2e test partition (see the
design doc). Adds `test/altimate/_fixtures/fake-gateway.ts` (a `FakeGateway`
that intercepts `fetch` via `spyOn(globalThis, "fetch")` — the repo's
existing proven pattern, not a real HTTP server — implementing `/register`
and `/v1/chat/completions` with controllable knobs for every failure mode
the suites need: per-minute token rate-limit, both `budget_exceeded`
variants, request-too-large, 401, 5xx, timeout, malformed JSON, and success)
and `test/altimate/_fixtures/altimate-base-harness.ts` (isolated XDG/home
bootstrap + gateway-env reset helpers, extracted from
`altimate-base.test.ts`'s existing pattern so every suite shares one
implementation).

Adds `altimate-base-harness-smoke.test.ts` proving the harness works in
both directions: a register -> `authorizedFetch` happy-path round trip, and
one scripted failure knob (per-minute token rate-limit ->
`describeRateLimit`'s non-retryable message).

Does not add any of the 6 planned suite files themselves — those are a
separate, parallel follow-up. Copies the design doc
(`docs/internal/2026-09-04-altimate-base-e2e-harness-plan.md`) into the
branch so it travels with the PR.

Stacked on `codex/altimate-base-release-final` (#1199) since the harness
targets that branch's 131072/65536 limits and Altimate Base code.

* test: consolidate Altimate Base e2e suite + centralize test consent-arming

Brings together 5 independently-written hermetic e2e suites for Altimate
Base onto the shared harness branch (53 tests):
- `altimate-base-registration-gaps.test.ts` (11) — HTTP/network/malformed
  register failure mapping, payload shape, retry idempotency
- `altimate-base-catalog.test.ts` (9) — model catalog / provider isolation
- `altimate-base-inference-e2e.test.ts` (5) — register -> list -> fetch
  round trip, placeholder-vs-real-key isolation
- `altimate-base-rate-limit-messages.test.ts` (21) — throttle/budget/
  request-too-large message mapping
- `altimate-base-error-surfacing.test.ts` (7) — 5xx/timeout/abort/
  malformed-body/401 pass-through at the inference layer

All 5 (plus the two pre-existing files, `altimate-base.test.ts` and
`altimate-base-harness-smoke.test.ts`) independently called
`FreeTierCapability.issueArmer()` at module scope. That capability is
process-global and throws on a second call, so running the directory in
one `bun test` invocation — as CI does — threw "Altimate Base consent
armer already issued for this process" once a second armer-calling file
loaded into the same worker process (reproducible with just the two
pre-existing files, before any of these suites existed).

Fix: centralize arming in the shared harness
(`_fixtures/altimate-base-harness.ts`) behind a new `consented()` helper
that lazily calls `issueArmer()` exactly once per process and caches the
returned armer in a module-level singleton. Because bun caches modules
per process, every suite file that imports `consented()` shares that one
cached armer regardless of load order or file count. This adds no way to
reset, re-claim, or otherwise weaken the one-shot guarantee
`issueArmer()` already enforces — it is a cache in front of the single
legitimate call, not a new capability. All 7 armer-calling files now
import and use the shared helper instead of claiming their own.

Verified with `bun test --timeout 90000 test/altimate/` (the directory
CI covers, at CI's timeout) from `packages/opencode`: 5103 pass, 0 fail,
zero armer-collision errors, in one process invocation.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01VqnuBDGkh1ZT65Ti7e6DHZ

---------

Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

* fix: [AI] preserve explicit Big Pickle picks, apply provider policy to TUI fallback, and fix migration-decline routing

Addresses four remaining unresolved review threads on the Altimate Base release
PR (several sibling threads on the same functions were already fixed in an
earlier pass):

- `tui/context/local.tsx` `cycleFavorite()`: a deliberate favorite-cycle pick of
  Big Pickle after registering Altimate Base persisted through the same
  `model`/`recent` fields the retired implicit default uses, but bypassed the
  `explicitDefault` marker that `/model` already sets. Legacy migration then
  silently overwrote it on the next launch. Routes the pick through the shared
  `selectModel(..., { recent: true, explicit: true })` path instead of writing
  the store fields directly, so it is marked explicit like every other
  picker-driven selection.
- `tui/context/local.tsx` `fallbackModel`: did not apply the managed-provider
  policy `Provider.defaultModel()` already enforces server-side, so a project
  `provider` block that excludes Altimate Base (e.g. `{ "openai": {} }`) could
  still have the TUI fall back to it through a persisted recent entry or the
  first-live-provider selection. Both paths now skip the managed model when
  `allowsManagedBaseDefault()` says the project has narrowed the allowlist.
- `tui/component/altimate-onboarding.tsx`: `no()` for the migration-declined
  origin only cleared the dialog, leaving the user on the retired Big Pickle
  model with no way to pick anything else — even though the label read "No —
  pick something else". Routes a migration decline to the same curated picker
  a welcome-origin decline already uses (after persisting the refusal via
  `onDecline`), and collapses the now-identical ternary into a plain label.
  Updates the one existing test that encoded the old close-and-strand
  behavior.
- `altimate/free/client.ts` `authorizedFetch`: after retrying with a
  concurrently rotated credential, a non-401 retry response never reset that
  credential's consecutive-401 counter (only the initial response's non-401
  path did). A stale 401 recorded against it elsewhere could then survive a
  successful retry and later cross the rejection threshold on its own. Mirrors
  the initial response's reset for the retry response too.

Verification: `bun run typecheck` clean; `@opencode-ai/tui`'s onboarding/local/
dialog-model-welcome suites (21 tests) and `@altimateai/altimate-code`'s
altimate-base/acp/provider suites (218 tests, 1 pre-existing unrelated failure
in altimate-base-catalog.test.ts's model-family assertion, tracked by a
separate unresolved review thread) green; marker check clean
(`--base origin/main --strict`).

* fix: [AI] restore disclosure linkability line, isolate Altimate Base consent from public SDK context

Two previously human-held decisions are now approved:

- `packages/tui/src/component/altimate-onboarding.tsx` (`ALTIMATE_BASE_DISCLOSURE`): the on-screen
  consent text a user actually accepts before any registration request must itself disclose that
  requests are linkable across launches, not defer that to docs a user never sees before accepting.
  Restores "Logs are linked to a persistent per-installation identifier." before "Usage is rate
  limited."
- Consent-gated registration is no longer reachable through the public SDK context. Previously
  `sdk.altimateBaseRegistration()` (the callback that arms consent and calls `/altimate/base/register`)
  was a plain property on the shared `useSDK()` context, exported as
  `@opencode-ai/tui/context/sdk` — any in-process consumer of that hook, including a
  plugin-rendered component, could call it directly and mint a Base install identifier / enable
  request logging without the disclosure dialog ever being shown or accepted.

  Moves the operation into a new `context/altimate-base-consent.tsx`, deliberately NOT listed in
  `package.json`'s `exports` map, so `@opencode-ai/tui/context/altimate-base-consent` cannot be
  resolved from outside this package at all (Node's exports field rejects unlisted subpaths).
  `app.tsx` still receives the host-injected operation on `TuiInput` and now provides it through
  this dedicated context instead of through `SDKProvider`. The two legitimate in-package readers —
  the consent dialog (which calls it, only after acceptance) and the provider picker (which only
  checks whether it exists, to decide whether to advertise Base setup) — read it from there.
  `useSDK()` itself no longer carries any property related to this operation.

  Adds `test/context/altimate-base-consent.test.tsx`, proving the public SDK context object has no
  such property (forged or otherwise) while the dedicated context does expose it and the legitimate
  accept flow can still call it; updates the one existing test harness that previously wired the
  registration callback through `SDKProvider`.

Verification: `bun run typecheck` clean; full `@opencode-ai/tui` suite green (286 pass, 1 pre-existing
skip, 0 fail, across 57 files, including the new isolation test and the updated onboarding harness).

* chore: [AI] wrap the new dialog-provider availability check in altimate_change markers

Marker Guard flagged `useAltimateBaseConsent()` in `createDialogProviderOptions()`
as unmarked new code in this upstream-shared file. No behavior change.

* fix: [AI] close two gaps automated review found in the prior fallback/migration fixes

Two automated review findings on the just-pushed fixes, addressed immediately:

- `tui/context/local.tsx` `fallbackModel`: the last-resort provider selection only
  excluded Altimate Base when a project provider allowlist disallowed it, but did not
  apply the allowlist to any OTHER provider — so it could still land on a connected
  provider the project never named either. Now filters every fallback candidate by the
  configured provider keys (mirroring `Provider.defaultModel()`'s `providerAllowed`),
  in addition to the existing Base-specific check. The `recent` scan is intentionally
  left as-is: matching `Provider.defaultModel()`'s own comment, a recent entry is the
  user's own past explicit pick and stays honored for every provider except the
  managed one, regardless of a later-narrowed allowlist.
- `tui/component/altimate-onboarding.tsx` `yes()`: after a successful registration,
  `migrateLegacyDefault()` re-checks eligibility and can return `false` if a project
  allowlist or explicit model change landed while the request was in flight — but the
  success path ignored that result and unconditionally called `markSetupComplete()`,
  marking a user still on the retired Big Pickle model as ready. Now routes to the
  curated picker instead of marking setup complete when migration did not happen.

Verification: `bun run typecheck` clean; full `@opencode-ai/tui` suite green (286 pass,
1 pre-existing skip, 0 fail).

* fix: [AI] tune altimate-base sampling params to match the served model's family

The gateway's sampling-tuning by model id in `ProviderTransform` never matched
`altimate-base` (the id under which the hosted free model is registered), so it
ran with default sampling instead of the values this family already gets
elsewhere in the same file — the gateway itself does not force these on
requests it doesn't recognize as needing them.

- `temperature()`: altimate-base now returns 0.55, matching the row above it.
- `topP()`: altimate-base now returns 1, matching the row above it.
- `variants()`: altimate-base is now excluded from the reasoning-effort
  variant list, alongside the other ids already excluded there (matching
  behavior, not renamed logic).

Matched on the literal model id (`id.includes("altimate-base")`) rather than
importing a constant from `altimate/free/client.ts`, to keep this
foundational, widely-imported file free of any new cross-domain dependency —
not because of a confirmed import cycle (checked: `client.ts` and its
transitive deps have no path back to `provider/`), but because a wrong call
on a file this central is worse than the small duplication.

Audited every other id-string check and adjacent reasoning/thinking-token
handling in `packages/opencode/src` for the same gap; only these three needed
a matching addition. Notably NOT touched: the `alibaba-cn`-specific
`enable_thinking` body param (gated on that provider's specific transport
quirk, not on any id string — extending it to a different, unverified gateway
stack would be a guess) and the static `interleaved` capability on the
altimate-base catalog entry (also provider/host-specific per the models
registry, not inferrable from an id check, and changing it without confirming
the actual gateway behavior risks a correctness regression in multi-turn
reasoning replay).

Also fixes the one now-in-scope pre-existing test failure: the catalog
assertion pinned `model.family` to a value the production catalog no longer
sets (scrubbed in bec2ae3); updated to match.

Verification: `bun run typecheck` clean; full altimate-base + transform +
provider + acp suites green (555 pass, 9 pre-existing skip, 0 fail).

* chore: [AI] wrap the new altimate-base sampling checks in altimate_change markers

Marker Guard flagged the temperature()/topP() additions as unmarked new code
in this upstream-shared file (the variants() addition was already inside an
existing marked block). No behavior change.

* fix: [AI] make the Altimate Base consent test hermetic against cross-file credential leakage

Root-caused the intermittent CI "TypeScript" job failure: `provider HttpApi >
advertises Altimate Base for consent without marking it connected`. Pulled the
actual failed CI run's log directly — the literal failure is
`expect(isRecord(body) && Array.isArray(body.connected) &&
body.connected.includes("altimate-free")).toBe(false)` -> `Expected: false,
Received: true`. Pre-existing since the test was added in `431a3b489b`, well
before this branch's other work; confirmed by isolating the single test
(passes) vs. running it alongside `test/altimate/*.test.ts` files that
perform a REAL `FreeTier.registerAfterConsent()` (fails when they run first
in the same `bun test` process).

Mechanism: `FreeTierStore.credentialPath()` resolves through the
process-wide, non-Instance-scoped `Global.Path.data` — not this test's own
isolated `TestInstance` directory. A real registration performed by an
earlier Altimate Base suite in the same shared Bun process writes a live
credential there; this test never registers anything and reads
`FreeTier.credentialsForLoad()` for real (no mock), so it picks up that
leftover credential and the custom provider loader marks `altimate-free`
`autoload: true`, landing it in `connected` depending on test-file execution
order.

Not a real production secret leak: `options.apiKey` for `altimate-free` is
always `FreeTier.MANAGED_API_KEY_PLACEHOLDER`, never the real credential,
regardless of this ordering issue — kept the `not.toContain("sk-")` guard in
the test unchanged, since it is a real assertion worth having.

Fix: clear any leftover `FreeTierStore` credential (`FreeTierStore.remove()`)
at the top of this specific test, before it makes its request — a minimal,
targeted isolation fix scoped to the one test that depends on a clean-slate
credential store, rather than touching the shared `Global.Path` module (an
earlier attempt at a deeper fix there — converting its module-level path
consts to lazy getters — broke the eager one-time directory creation many
unrelated tests depend on, causing 91 failures across the suite; reverted).

Verification: `bun test packages/opencode/test/server/httpapi-provider.test.ts`
— 6 pass, 0 fail; run alongside `test/altimate/altimate-base.test.ts` (which
performs real registrations) — 40 pass, 0 fail, confirming the isolation now
holds regardless of file order; `bun test packages/opencode/test/server/` —
only two unrelated pre-existing local-sandbox failures (real ambient MCP
config on this machine bleeding into `httpapi-mcp.test.ts`/experimental
HttpApi tests, absent in CI); `bun run typecheck` clean.

---------

Co-authored-by: Claude Opus 4.8 <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant