Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
22 commits
Select commit Hold shift + click to select a range
73766c8
fix(custody): key scoped main quota by the roster primary account
iceteaSA Sep 24, 2026
a456ebd
fix(custody): poll main quota under scoped custody
iceteaSA Sep 24, 2026
0677fd0
fix(custody): fence scoped main quota identity and bound header-only …
iceteaSA Sep 24, 2026
dc6e69e
fix(pi): port transcript replay so Oh My Pi can load the extension
iceteaSA Sep 24, 2026
1e00466
fix(pi): check every host import clause in the dist import guard
iceteaSA Sep 24, 2026
733e19b
fix(custody): bind the main poll-attempt bound to its account
iceteaSA Sep 24, 2026
ee0bdb5
feat(custody): log scoped 401 retry decisions and delivered reports
iceteaSA Sep 24, 2026
e9d775a
fix(pi): parse the dist import guard's input instead of matching its …
iceteaSA Sep 24, 2026
0dda779
fix(custody): count only physical usage polls toward the header-only …
iceteaSA Sep 24, 2026
9a1a490
feat(custody): log Pi scoped 401 decisions and why a retry was skipped
iceteaSA Sep 24, 2026
540eb11
fix(custody): record reauthorize-failed at the CacheKeep 401 retry sites
iceteaSA Sep 24, 2026
eed5804
build(core): upgrade Claustrum client to 0.4.0
ualtinok Sep 24, 2026
847cecb
Review merge PR #259 scoped main quota
ualtinok Sep 24, 2026
739ccaa
Review merge PR #260 OMP transcript portability
ualtinok Sep 24, 2026
f1c9be8
Review merge PR #261 scoped 401 diagnostics
ualtinok Sep 24, 2026
af39724
ci(pi): guard all emitted host imports in release gates
ualtinok Sep 24, 2026
13ec401
ci(test): raise Core and OpenCode floors from clean CI
ualtinok Sep 24, 2026
ca62426
docs(release): prepare v2.0.0 migration notes and install examples
ualtinok Sep 24, 2026
52a69b5
test(opencode): isolate host paths before Core imports
ualtinok Sep 25, 2026
eae6591
fix(models): reject unsupported Opus fast and forced tool modes
ualtinok Sep 25, 2026
c005241
docs: record v2 Opus request and test isolation fixes
ualtinok Sep 25, 2026
b504bc8
ci: ratchet v2 test floors to clean-runner counts
ualtinok Sep 25, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions .ci/test-count-floors.json
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
{
"floors": {
"core": 290,
"opencode": 1677,
"pi": 140
"core": 302,
"opencode": 1700,
"pi": 145
},
"measurement": {
"head": "e86aa0b79fa5e5fae164ddb47fddcf6e74f4802b",
"head": "c0052410b5a58dc1116b1b53512f0ddacea4306e",
"dirtyPaths": 0
},
"evidence": {
"_note": "Pinned Bun 1.3.14 runner totals after the scoped-only cutover. The measurement head precedes this floor-file update and was clean. Runner counts, not source declaration counts, are the authority at the gate.",
"core": "290 passing on clean CI run 35985845771 at commit e86aa0b7",
"opencode": "1677 passing on clean CI run 35985845771 at commit e86aa0b7",
"pi": "140 passing on clean CI run 35985845771 at commit e86aa0b7"
"core": "302 passing on clean CI run 36175474561 at commit c0052410",
"opencode": "1700 passing on clean CI run 36175474561 at commit c0052410",
"pi": "145 passing on clean CI run 36175474561 at commit c0052410"
}
}
2 changes: 2 additions & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ jobs:
- run: bun run check:workspace-lock
- run: bun run types
- run: bun run build
- run: bun test scripts/check-pi-dist-imports.test.ts
- run: bun run check:pi-dist-imports
- run: bun run check:claustrum-golden
env:
GITHUB_TOKEN: ${{ github.token }}
Expand Down
6 changes: 6 additions & 0 deletions .github/workflows/release.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,12 @@ jobs:
- name: Build
run: bun run build

- name: Pi host-import guard tests
run: bun test scripts/check-pi-dist-imports.test.ts

- name: Pi host-import guard
run: bun run check:pi-dist-imports

- name: Packed TUI smoke test
run: bun run --cwd packages/opencode smoke:tui
env:
Expand Down
10 changes: 6 additions & 4 deletions ARCHITECTURE.md

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions AUDITOR.md
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ Guidance for future audits of intentional tradeoffs in this repository.
- **CCH/signing and cache rewrites parse/stringify request bodies.** This is expected because signing must cover the final serialized body and cache markers are JSON-structural. Optimizations should preserve exact wire-body semantics and be backed by benchmarks.
- **Relay patch creation is linear in body size.** This is currently acceptable relative to JSON serialization/signing and network upload costs. Replacing it should be justified by measurements and must preserve hash-gated reconstruction.
- **Total loss of Fable 5.1 effort markers and the current-user anchor remains fail-closed (#237/#242).** A resolved request-plan header alone cannot prove that the retained wire history is an exact suffix; a retained earlier user/assistant pair with all marker text stripped is a concrete counterexample. An anchored full prefix trim already folds safely. Missing-all refusals log only bounded shape and hashed plan metadata, never prompt text or marker bytes; accepting an unanchored trim needs independent proof of the surviving boundary, not a count check.
- **Opus 5.5 structured output cannot be forced with `tool_choice: any/tool`.** Anthropic rejects those values on Opus 5.5, including OpenCode's `required` setting for JSON-schema output. The request keeps the StructuredOutput tool and system instruction but removes only the unsupported forced choice; OpenCode validates a returned tool call against the schema and reports `StructuredOutputError` when the model completes without it. This avoids a universal 400 without claiming that every request is guaranteed to produce structured output. A real isolated OpenCode tool round-trip and plain-text negative test cover both outcomes.

## Quota and fallback policy

Expand Down
9 changes: 9 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,12 +4,21 @@ This repo is a CortexKit-maintained Anthropic auth monorepo for OpenCode and Pi.

## Unreleased

## 2.0.0

### Breaking Changes

- Remove the handle-based Claustrum serving path, manifest bindings and per-account gates. OpenCode and Pi now require enrolled, zero-bind scoped custody; an older Claustrum configuration without a scoped roster refuses serving until `setup` completes. Remove Core's process-shared enrollment-registry export; host path resolution remains available through the Core enrollment module. Local OAuth and API-key routes are unaffected.

### Patch Changes

- Stop sending `speed: "fast"` to Opus 4.7, where it returns 400, and Opus 4.6, where it has no effect. Fast mode now applies only to Opus 4.8, Opus 5, and Opus 5.5 in OpenCode and Pi (#267).
- Remove Opus 5.5's unsupported forced `tool_choice` for OpenCode structured-output requests while retaining the schema tool. OpenCode still records validated structured output and reports an error if the model does not call it. Keep named `tool_choice` references aligned with prefixed tool definitions on other models (#268).
- Isolate OpenCode tests from live account files, sidebar state, CacheKeep leases, RPC directories, and Claustrum sockets even when a test clears a feature-specific override. Setup detection now uses the supplied environment for its connection file (#264, #265).
- Persist scoped main quota under the discovered primary account rather than the local host slot, and let `/claude-quota` poll with a freshly authorized scoped credential. A header-only main quota remains due for its first usage poll; failed polls are spaced by account without treating usage 403 as rate-limit backoff or counting requests that lose the cross-process refresh lock.
- Load the Pi extension through Oh My Pi's legacy SDK compatibility layer by keeping transcript system-prompt and tool replay in the extension instead of importing helpers absent from the host. Check built Pi imports with a syntax-aware allowlist in CI and release workflows.
- Add debug diagnostics for scoped 401 retry decisions and delivered failure reports across OpenCode and Pi, recording served and current record versions and a non-secret decision reason without logging bearer material.
- Update the shared Claustrum client to 0.4.0 (with Subc client 0.16.x) for scoped custody. The client no longer reconnects on a terminal `unknown_module` response from a daemon without the Claustrum module.
- Show an approved Claustrum enrollment as active in `/claude-account` and the account modal when the main account is vault-served; stop telling already configured users to rerun setup or request a grant. Clarify that `enrollment-reset` only clears terminal state.
- Fix packed OpenCode CLI startup under Node: keep `jsonc-parser` external so its CommonJS `./impl/*` modules resolve from the installed dependency, and run the packed CLI's `--help` path alongside the TUI smoke gate (#257).
- Stop unsolicited Claustrum enrollment on OpenCode boot and account-status views: only explicit offline setup proposes and polls, while `/claude-account enrollment-reset` clears terminal state under lock without starting another request. Setup resumes crash-persisted secrets and replaces one daemon-confirmed dead request; all producer-permanent refusal codes stop polling even when older client transports mislabel them retryable. This removes the per-process enrollment poll loop (#255) without changing scoped account-discovery polling.
Expand Down
10 changes: 5 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ This repo is a Bun workspace monorepo with two user-facing integrations and one
- **Cache keepalive**: use `/claude-cachekeep always` or `/claude-cachekeep HH-HH` to pre-warm hybrid cache anchors for active sessions before the 1-hour TTL expires.
- **Quota window priming**: opt in with `/claude-prime on` to start each 5-hour quota window about one minute after it resets instead of waiting for the next normal prompt.
- **Lane start (OpenCode only)**: use `/claude-start` to fire one synthetic, one-token turn through the current session's normal model, agent, variant, quota, routing, cache, and request pipeline.
- **Fast mode toggle**: use `/claude-fast on|off` to request Anthropic fast mode for supported Opus models (`claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`).
- **Fast mode toggle**: use `/claude-fast on|off` to request Anthropic fast mode for supported Opus models (`claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`).
- **Adaptive reasoning visibility**: request summarized adaptive thinking for Claude Fable 5/5.1, Mythos 5/5.1, Opus 5, and Opus 5.5. OpenCode exposes native `low`, `medium`, `high`, `xhigh`, and `max` effort variants for Fable 5.1, Opus 5, and Opus 5.5. On Opus 5.5, thinking is always on (adaptive summarized) per the model specification. OAuth Fable 5.1 sessions can change effort between turns without rewriting the cached prefix.
- **Fable/Opus 5 and 5.5 safety fallback (OpenCode)**: eligible OAuth requests try Anthropic's server-side safety fallback first. The plugin preserves Anthropic's fallback conversation boundary across OpenCode history and automatically starts its deterministic 10-response Opus 4.8 recovery if the response still ends in refusal. The TUI sidebar and OpenCode Desktop report the active target model and restoration. Set `OPENCODE_ANTHROPIC_AUTH_FALLBACK_MODE=legacy` to bypass the server policy and use client-side recovery exclusively.
- **Live quota visibility**: use `/claude-quota` to see main and fallback quota state, reset times, and refresh errors.
Expand Down Expand Up @@ -88,7 +88,7 @@ Pinning is strongly recommended for any OpenCode plugin:

```json
{
"plugin": ["@cortexkit/opencode-anthropic-auth@1.0.0"]
"plugin": ["@cortexkit/opencode-anthropic-auth@2.0.0"]
}
```

Expand All @@ -102,7 +102,7 @@ After changing plugin config, restart OpenCode.
Install the Pi package with Pi's package manager:

```bash
pi install npm:@cortexkit/pi-anthropic-auth@1.0.0
pi install npm:@cortexkit/pi-anthropic-auth@2.0.0
```

For an unpinned install:
Expand Down Expand Up @@ -380,7 +380,7 @@ Pinning is recommended, matching the main plugin entry:

```json
{
"plugin": ["@cortexkit/opencode-anthropic-auth@1.0.0"]
"plugin": ["@cortexkit/opencode-anthropic-auth@2.0.0"]
}
```

Expand Down Expand Up @@ -587,7 +587,7 @@ Both OpenCode and Pi packages can persistently request Anthropic fast mode for s
/claude-fast off
```

When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic currently documents fast mode for `claude-opus-4-6`, `claude-opus-4-7`, `claude-opus-4-8`, and `claude-opus-5`; Claude Fable and Mythos 5/5.1 are not fast-mode models.
When enabled, supported requests add `speed: "fast"` to the Anthropic JSON body and include the `fast-mode-2026-02-01` beta header. Unsupported models are left at standard speed. Anthropic supports fast mode for `claude-opus-4-8`, `claude-opus-5`, and `claude-opus-5-5`. Opus 4.7 rejects `speed: "fast"`, while Opus 4.6 runs at standard speed; Claude Fable and Mythos 5/5.1 are not fast-mode models.

Fast and standard speeds do not share prompt-cache prefixes, so switching this setting can cause cache misses.

Expand Down
9 changes: 5 additions & 4 deletions STRUCTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -60,15 +60,15 @@ anthropic-auth/
**`packages/pi/src/`:**
- Purpose: Pi extension — registers CortexKit Anthropic provider override
- Contains: Extension entry point, command registration, request building, streaming provider
- Key files: `index.ts` (provider and model-catalog registration), `stream.ts` (streaming request handling including redacted-thinking preservation), `commands.ts` (slash command registration), `convert.ts` (Claude Code-compatible request conversion, bounded process-local billing-suffix pinning, origin-aware thinking-signature filtering, configurable Fable 5.1 prefix behavior, mid-conversation effort markers, redacted-thinking replay, Pi documentation-prompt relocation, and cache breakpoint placement), `effort-history.ts` (compaction-aware Pi thinking-level timeline), `paths.ts` (Pi-specific path resolution)
- Key files: `index.ts` (provider and model-catalog registration), `stream.ts` (streaming request handling including redacted-thinking preservation), `commands.ts` (slash command registration), `convert.ts` (Claude Code-compatible request conversion, bounded process-local billing-suffix pinning, origin-aware thinking-signature filtering, configurable Fable 5.1 prefix behavior, mid-conversation effort markers, redacted-thinking replay, Pi documentation-prompt relocation, and cache breakpoint placement), `transcript.ts` (host-independent system-prompt and tool replay for Pi and Oh My Pi), `effort-history.ts` (compaction-aware Pi thinking-level timeline), `paths.ts` (Pi-specific path resolution)

**`packages/e2e-tests/`:**
- Purpose: Integration tests with mock Anthropic, relay, and Claustrum servers
- Contains: Test harness, mock server implementations, process runner with temp dir hygiene, end-to-end integration tests (tool prefix, quota header relay, temp directory hygiene, custody mode, mock claustrum)

**`scripts/`:**
- Purpose: Development, release, and analysis utilities
- Contains: `dev.ts` / `dev-clean.ts` (local dev workflow with symlinks), `release.sh` / `wait-release.sh` (tag-driven npm release), `analyze-cache-usage.mjs` (OpenCode SQLite cache analyzer), `check-claustrum-golden.ts` (pins canonical Claustrum tombstone ancestry and exact fixture bytes), `check-pi-tool-mapping.ts` (runs an isolated real Pi host tool round-trip against deterministic SSE), `check-test-count-floors.ts` (runs unit suites once; compares floors against the merge target in PR CI and the previous version tag at release), `extract-system-prompt.ts` (prompt capture extraction), `capture-with-mitmproxy.sh` (HTTPS capture setup), `version-sync.mjs` / `workspace-lock.mjs` (cross-package versions, surgical Bun lockfile synchronization, and manifest-to-lock validation)
- Contains: `dev.ts` / `dev-clean.ts` (local dev workflow with symlinks), `release.sh` / `wait-release.sh` (tag-driven npm release), `analyze-cache-usage.mjs` (OpenCode SQLite cache analyzer), `check-claustrum-golden.ts` (pins canonical Claustrum tombstone ancestry and exact fixture bytes), `check-pi-tool-mapping.ts` (runs an isolated real Pi host tool round-trip against deterministic SSE), `check-pi-dist-imports.ts` (AST-validates emitted Pi host-SDK imports, rejecting unsupported or unverifiable dynamic imports in CI and release), `check-test-count-floors.ts` (runs unit suites once; compares floors against the merge target in PR CI and the previous version tag at release), `extract-system-prompt.ts` (prompt capture extraction), `capture-with-mitmproxy.sh` (HTTPS capture setup), `version-sync.mjs` / `workspace-lock.mjs` (cross-package versions, surgical Bun lockfile synchronization, and manifest-to-lock validation)

## Key File Locations

Expand Down Expand Up @@ -148,14 +148,15 @@ anthropic-auth/
- `packages/pi/src/commands.ts`: Pi slash command registration (`/claude-*`) and persistent setting handlers
- `packages/pi/src/paths.ts`: Pi-specific storage and config path resolution
- `packages/pi/src/convert.ts`: Pi-to-Anthropic request conversion, including ordered system prompt block flattening, session-stable Claude Code billing suffixes, same-origin thinking-signature replay, configurable Fable 5.1 compaction behavior, mid-conversation effort markers, redacted_thinking mapping, Pi documentation-prompt relocation, and four-slot cache breakpoint placement
- `packages/pi/src/transcript.ts`: Locally replays host system messages and tool changes rather than importing helpers absent from Oh My Pi's legacy SDK shim
- `packages/pi/src/effort-history.ts`: Rebuilds Fable 5.1 effort transitions from Pi's active branch and compaction-aware context entries (locally derived when buildContextEntries is absent)
- `packages/pi/src/stream.ts`: Pi provider streaming implementation, including preservation of Anthropic redacted-thinking blocks for later replay, request-resolved host tool names for SSE tool-call mapping, API-key route versioned URL composition, and safe custom header application

**Tests:**
- `packages/core/src/tests/`: Core-only unit tests (dump, killswitch, models, prime, quota surfaces, accounts persistence, custom headers, model remap, claustrum)
- `packages/opencode/src/tests/`: One test file per module (50+ test files covering core + opencode), including Claustrum client/custody, credential-handle blindness, billing lineage tracking, and fail-closed network-guard suites
- `packages/opencode/src/tests/`: OpenCode unit and integration tests, including scoped Claustrum custody, billing lineage, a fail-closed network guard, and test-host filesystem/daemon isolation. `preload-sandbox.ts` initializes a disposable sandbox before `setup.ts` imports Core (whose logger/dump defaults are fixed at module load), then `setup.ts` restores account, sidebar, cache, RPC, dump, and daemon paths before/after tests so clearing a feature override cannot reach live state.
- `packages/pi/src/tests/`: Pi-specific tests (commands, convert, effort-history, index, stream)
- `packages/e2e-tests/tests/`: Integration tests (tool prefix, quota header relay, temp directory hygiene, custody mode, mock claustrum)
- `packages/e2e-tests/tests/`: Process integration tests (tool prefix, quota header relay, temp directory hygiene, scoped custody, and Opus 5.5 structured output with and without the schema tool call)

## Naming Conventions

Expand Down
7 changes: 4 additions & 3 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading
Loading