Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
36 changes: 36 additions & 0 deletions devlog/_plan/261004_claude_request_preservation/000_plan.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Claude request preservation replacement roadmap

Native Claude requests need consistent OAuth tool names, client compatibility and pool dispatch without losing caller content. This unit separates those runtime contracts from the preference that selects them. It refines public sources #6533, #6534 and #6547 into a manual PR chain; source closure remains coordinator-owned.

## Loop specification
Comment thread
lidge-jun marked this conversation as resolved.

- Shape/trigger: satisfy-spec, assigned next-release Claude lane.
- Goal: focused published replacement PRs with complete source behavior accounting and real-author attribution.
- Non-goals: merges, release/version changes, installed runtime writes, account/credential changes, live upstream traffic, source closure, native stacks, unrelated work.
- Verification: focused Bun behavior tests, typecheck, structure/privacy/layout/ratchet gates; GUI tests and observed render for preference; docs build for docs changes. Full/changed local suites excluded by explicit concurrent-release resource contract; wider coverage belongs to current-head hosted CI.
- Stop: all replacement PRs published, independent review addressed, current-head CI inspected, residual native/live gaps honestly draft-bound.
- Artifacts: this numbered unit; ignored `.tmp/claude-lane/` stores source snapshots, verification logs and non-public security reasoning.
- Outcomes: DONE = publication and complete accounting; unresolved evidence stays explicit/draft; blocked capability is reported without invented success.
- Escalation: scope/authorization change or unavailable indispensable capability. Existing scoped commits/push/PR creation are authorized.
- Tool/credential scope: repository filesystem, GitHub repository reads and scoped branch/PR writes, fake/local test endpoints. No real provider credentials or paid upstream calls.
- Token/cost/wall-clock bounds: no user numeric budget supplied; do not invent one. Managed short-yield commands and bounded leaf tasks; keep work within the requested scope.

## Baseline and topology

Base `0818ea1812a028e1c14cd0b0511b44863407bc52` from refreshed dev. Sources: #6533 `8e5c78912222b1616709d664c23de254dd71b7c9`; #6534 `829b203b3e65530a4cdaaa121f2da15484c2c9b7`; #6547 `5f3cf4ed0b4a63604133863442002fb9ac824b16`. Original author: Claire Novotny <claire@novotny.org>. Inherited tool/pool commits are consumed once, never blindly cherry-picked cumulatively.

| Cycle | Output | Dependency |
| --- | --- | --- |
| wp0 | Docs-only reviewed roadmap | none |
| wp1 | B1 typed references and inline tools | roadmap |
| wp2 | B2/B3 client compatibility and pooled native dispatch | B1 |
| wp3 | B4 preference, defaults, API, GUI | B2/B3 |

Existing owners: `src/adapters/anthropic/` shapes the wire; `src/oauth/anthropic-routing.ts` owns pool selection/health; native server modules own physical dispatch; `src/protocols/settings.ts` owns policy resolution; pool settings capability and management routes own validated writes; the existing Anthropic pool component owns UI. Reuse these paths and existing tests. No alternate pool or retry engine.

## Consultation

Read-only architect proposal/reflection and independent audit recorded before implementation. Every later P revalidates its decade document against current parent tip. Leaves are scoped to disjoint files and never branch or run goals/FSM.

Architect handle: 01a10493-1a9a-73d2-96f9-86ef0df9518d. Main accepts CL-A01/A05/A08; amends CL-A02 duplicate carries, CL-A03 session priority, CL-A04 lease-before-charge, CL-A06 malformed protocol salvage, CL-A07 CSS sibling and CL-G01–G04 route race/raw malformed/help/preview coverage. Reflection requested on amended roadmap.
Architect reflection on amended roadmap: ALIGNED; all CL-A02/A03/A04/A06/A07 and CL-G01–G04 resolved. Independent audit remains required. No implementation evidence claimed.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# B1 — Typed tool references and inline declarations

Depends on the roadmap only. Branch `codex/next-release-261004-claude-tools`, PR base dev. Carry #6533 in full and the inline-tool portion of #6534/#6547. Identity/beta/preamble and pooling remain later layers.

## Exact change map

- MODIFY `src/adapters/anthropic/passthrough.ts`: within `anthropicOAuthWireBody`, replace top-level tool-use-only mapping with copy-on-write typed block traversal. Carry #6533 diff plus the inline-name hunks of public commit `e3eefbaedf5e0ba598c5d443ce16e21d94a9f378`. Collect inline `tool_addition.tool.type=tool_definition` client definitions before mapping so preceding references resolve. Rewrite declared custom tool `tool_use.name`, `tool_reference.tool_name`, inline addition/removal `tool.type=tool_reference` names, and inline client definition names. Traverse only message content and typed tool-result content. Preserve arbitrary schemas, arguments, cache markers and unknown blocks. Reject ambiguous wire-name collisions, including typed versus client declarations.
- MODIFY `tests/adapters/anthropic/anthropic-messages-passthrough-oauth.test.ts`: preserve six existing regressions; carry nested-reference and inline-declaration source cases; add targeted ordering, typed collision and opaque-container negatives within ratchet headroom, otherwise register a sibling domain file in both layout maps.
- MODIFY `structure/data-planes/protocol-paths.md`: native OAuth paragraph documents typed reference/inline naming, exact opaque preservation and copy-on-write behavior.
- MODIFY `docs-site/src/content/docs/guides/claude-code.md`: small native tool compatibility note, without claiming pool/default behavior before later layers.

## Observable acceptance

Declared lookup in nested tool-result content becomes custom_lookup; undeclared and typed builtins stay unchanged. Inline declaration after an earlier reference still prefixes consistently. Inline removal names match declaration. Source body JSON is unchanged; opaque tool input/schema and text/cache TTL/scope remain identical. A collision is refused before dispatch. Key auth gets no OAuth shaping. Tests fail against original behavior then pass with the patch. No network request.

## Verification

`bun test tests/adapters/anthropic/anthropic-messages-passthrough-oauth.test.ts` reads the target directly; baseline six tests pass after frozen dependency installation. `bun run typecheck`, `bun run structure:check`, `bun run privacy:scan`, `bun test tests/test-layout.test.ts tests/test-layout-tooling.test.ts tests/ci-workflows/file-size-ratchet.test.ts`; docs build per docs-site instructions. Source/public patch anchors are fixed above. Human semantic review proves prose scope, not a phrase-presence test.

## Source accounting

`#6533` all behavior carried. #6534/#6547 inline naming carried here; client compatibility, pool and preferences remain unresolved until their own layers. Include `Co-authored-by: Claire Novotny <claire@novotny.org>` in commit and PR body.

## B1 focused source review dispositions

Accept independent tool review: collect both top-level and inline typed names before any rename; reject original-name ambiguity and typed wire-name collisions independent of declaration order. Register all client declarations in the prefix collision map before walking uses. Follow only the same typed content containers in both collection and mapping so nested inline definitions cannot silently escape while their neighbors are rewritten; this is conservative structural support, not a claim that upstream accepts nested inline definitions. Add cross-message ordering, inline choice/use, undeclared/typed references, and schema/input/unknown-container opacity regressions. These are bounded refinements within B1's existing collision and typed-container contract.
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
# B2/B3 — Native client compatibility and pooled dispatch

Depends on B1. Publish `codex/next-release-261004-claude-native` as manual child of tools. Combining client compatibility and dispatch is intentional: selecting native for a real pooled client without preserving its identity/preamble/betas would admit a request the replacement cannot faithfully send. No preference/default changes in this layer.

## Exact change map

Use the complete public #6534 diff at `829b203b3e65530a4cdaaa121f2da15484c2c9b7`, excluding B1 hunks already carried, The equivalent #6547 commits `c46145193613d54574c779806192e8ff4f19ace5` (dispose refusal before rebind) and `5f3cf4ed0b4a63604133863442002fb9ac824b16` (blank session fallback) corroborate behavior already in the pinned #6534 head and are not applied again. Adapt to current routing/refusal owners, never restore obsolete ownership from a source patch.

- MODIFY `src/adapters/anthropic/client-identity.ts`: recognize bounded observed CLI/Desktop Code compatibility bundles; keep WeakMap-backed opaque handles, header exclusion, first-party-only forwarding and operator header precedence. Expose observed-identity predicate for native preamble/beta consumers.
- NEW `src/adapters/anthropic/native-client-preamble.ts`: carry the public source helper that recognizes leading billing plus Claude identity preambles only with an observed native client identity. Preserve source block objects and cache markers; otherwise existing synthetic prefix remains.
- MODIFY `src/adapters/anthropic/beta-allowlist.ts`: add only source-listed feature betas for recognized first-party native clients; retain compatible-host and unrecognized-client deny behavior.
- MODIFY `src/adapters/anthropic/passthrough.ts`: add request-local clientIdentity option to native wire-body builder and OAuth shaping; feed identity predicate to beta allowlist; B1 names remain unchanged.
- MODIFY `src/oauth/anthropic-routing.ts`: reuse shared session-key construction for native ingress, with existing priority: nonblank metadata conversation ID, then session header (`session_id`, then Claude session header), then thread header, then eligible cache-key fallback. Preserve bounded hashing and no raw identifiers in logs.
- MODIFY `src/server/claude-messages.ts`: capture native request session key and client identity at ingress; pass to native dispatch and token counting. Keep existing route/feature guards and caller-forward behavior.
- MODIFY `src/server/messages-native-eligibility.ts`: remove pool/quorum-only declines behind explicit native rollout. Keep provider, destination, tools/proxy processing and feature eligibility guards.
- MODIFY `src/server/messages-native-oauth.ts`: resolve binding with model/session/tried-account scope through existing account-routing and commit owners. Preserve selected UUID plus generation, pause/health eligibility and concurrent-selection fences. Remove obsolete pool-decline-only guard; do not invent separate selection/failover policy.
- MODIFY `src/server/messages-native.ts`: carry bounded pre-output shared refusal classification/recovery for OAuth; cancel rejected response before refresh/rebind; rebuild from original caller body with replacement exact UUID/generation; preserve physical-send budgets and cancellation. Acquire family revalidation lease before spend/send accounting; release on budget refusal, abort and transport failure. Add denied-lease test proving no send charge/record. Re-evaluate model-route policy if it changes while binding is asynchronous. No replay after output. Capture account identity before recording refusal, so a race cannot blame the replacement. Propagate route/session into every binding check.
- MODIFY `tests/adapters/anthropic/anthropic-account-pool.test.ts`, `anthropic-beta-allowlist.test.ts`, `anthropic-client-identity.test.ts`, `anthropic-messages-passthrough-oauth.test.ts`: carry source compatibility/session cases without duplicating B1.
- MODIFY `tests/claude-integration/messages-native-oauth.test.ts`, `tests/responses/messages-native-oauth-eligibility.test.ts`: carry all source loopback dispatch/recovery/identity tests; strengthen model-route exclusion, pause/generation races and post-output no-replay where missing.
- MODIFY `structure/data-planes/protocol-paths.md`, `structure/providers/anthropic-account-pool.md`, `docs-site/src/content/docs/guides/claude-code.md`: replace obsolete pool exclusion with explicit-rollout native contract; no default-on claim yet.

## Acceptance and verification

Real local fake endpoints exercise two usable accounts, sticky session, model route, eligible shared-quota 429 and classified account 403 before output, bounded attempt exhaustion, refusal cancellation before rebind, and partial-output termination without another physical send. Manual selection, pause, generation or UUID change during async preparation must not emit stale binding. Opaque content/cache markers are equal across rebuild except declared tool/account metadata fields. CLI/Desktop preamble and beta cases use fabricated compatibility headers only. Token counting and preview select same body/lane as runtime without refreshing or selecting credentials.

Run focused test files above plus existing native bridge/opaque-state tests, `bun run typecheck`, structure/privacy/layout/ratchet gates and docs build. Use fake isolated OAuth homes; no credential or live-provider access. Source regressions may need sibling test modules to respect downward ratchets, registered in both layout inventories. Security review is independent; unshipped discoveries stay ignored scratch.
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# B4 — Pool native preference, API and UI

Depends on B2/B3. Publish `codex/next-release-261004-claude-settings` as a manual child of native. This layer carries #6547 settings behavior while correcting precedence: an explicit operator false rollout remains false. Source tests asserting false becomes true are deliberately replaced by precedence regressions.

## Field chain and exact changes

The new optional `anthropicAccountPool.nativeMessages` boolean is created by API/UI, serialized by existing config persistence, parsed by schema/config diagnostics, resolved by protocol settings and consumed by eligibility, preview, count_tokens and runtime. DTO/UI normalization must preserve false.

- MODIFY `src/types/config.ts`: add optional nativeMessages boolean to existing Anthropic pool type.
- MODIFY `src/config/schema/config-schema.ts` and `src/config/diagnostics.ts`: source #6547 conservative malformed-field salvage and strict validated-write diagnostics; malformed field becomes false without dropping providers or sibling pool settings. Preserve explicit native false when a malformed sibling would otherwise drop the entire protocols object; file-load-to-resolver regressions must prove this. Malformed protocol containers retain a conservative disabled native policy after salvage.
- MODIFY `src/protocols/settings.ts`: extend accepted config projection and optional provider scope. An enabled Anthropic pool supplies true only for absent native rollout values; explicit false or malformed present rollout is off. Pool nativeMessages=false disables pooled native selection. Pool-off keeps explicit legacy rollout behavior; another provider never inherits Anthropic default. Invalid protocols/rollout containers fail closed. Native OAuth cannot be true when managed native is false. Include effective/default/provider inputs in policy revision so preview becomes stale after a relevant change.
- MODIFY `src/protocols/plan-snapshot.ts`, `src/server/messages-native-eligibility.ts`, `src/server/claude-messages.ts`: pass settled provider consistently into policy resolver at preview/count/runtime ingress; keep admission and source identity behavior from parent.
- MODIFY `src/oauth/pool-settings-capability.ts`: add Anthropic-only writable capability and nullable DTO field; other providers expose null. Resolve absent preference true but malformed false consistently with config boundary.
- MODIFY `src/server/management/oauth-account-routes.ts`: both unified and legacy routes accept boolean nativeMessages only for Anthropic; reject malformed/provider-inapplicable writes before mutation. Patch latest persisted config through existing atomic mutation owner, preserve unrelated concurrent changes, update live config only after save succeeds. Preserve legacy validation/default/routes null-clear behavior. Return useful non-sensitive save failures.
- MODIFY `gui/src/pool-settings.ts`: request/response type, Anthropic-only normalization, false-preserving 204 fallback and request construction.
- MODIFY `gui/src/components/provider-workspace/AnthropicAccountPoolSettings.tsx`: source #6547 checkbox inside existing details, accurate help that explicit rollout opt-outs still apply, shared save payload across every pool control, persisted opt-out on reload, visible save failure and revert behavior. Disabled while loading/saving as existing controls require.
- NEW `gui/src/styles/anthropic-native-messages.css`: source checkbox/copy alignment using existing tokens; import from component. Main stylesheet has only two lines of ratchet headroom.
- MODIFY `gui/src/i18n/{de,en,fr,ja,ko,pt,ru,tr,vi,zh-TW,zh}.ts`: source strings, amended as needed so explicit rollout overrides are not misrepresented.
- MODIFY `gui/tests/account-pool-strategy.test.tsx`, `gui/tests/anthropic-pool-conditions.test.tsx`, `gui/tests/anthropic-pool-quota-window.test.tsx`: DTO/default/204 tests, opt-out save/reload, failed save visible, controls retain native preference.
- MODIFY `tests/config/config-load-degrade.test.ts`, `tests/config/protocol-settings.test.ts`, `tests/responses/messages-native-eligibility.test.ts`, `tests/server/account-pool-management-api.test.ts`, `tests/responses/protocol-plan-snapshot.test.ts`: source malformed salvage/atomic write tests and corrected precedence truth table, provider scope, revision/preview/count/runtime agreement.
- MODIFY `docs-site/src/content/docs/guides/claude-code.md`, `reference/configuration/providers.md`, `reference/configuration/server.md`, `structure/providers/anthropic-account-pool.md` and affected protocol contract: default only when no explicit opt-out; pool-off rules; cache remains account-specific. Review translated pages and amend contradictory statements.

## Activation matrix

Pool absent/disabled + flags absent -> off. Pool enabled + flags absent + preference absent/true -> eligible Anthropic native on. Each explicit false flag wins; malformed flag or container fails closed. Preference false wins over explicit true flags for pooled routes. Other providers retain their own rollout. Invalid native preference -> false without losing providers. Raw malformed preference/rollout input is tested in resolver and DTO, not only parsed-file tests. Both API routes reject wrong provider/nonboolean; persistence failure leaves live config unchanged and UI shows error; concurrent unrelated disk edit survives. 204 false write remains false. Preview revision changes when effective policy changes; count sends no requests. GUI checkbox toggles and reload reflects actual saved choice.

## Verification and publication

Focused backend/GUI tests, root typecheck and GUI lint/typecheck, structure/privacy/layout/ratchet; docs build. Observe local rendered checkbox and first state change with mocked endpoints and fake account data; capture screenshot outside PR branch and publish via pr-assets (or reuse source image only if accurate). Every source hunk is carried/amended/dropped explicitly; all three layers carry Claire Novotny attribution. Current-head hosted checks inspected, broad/native/live missing evidence remains draft-bound. No merge or source closure.
6 changes: 6 additions & 0 deletions docs-site/src/content/docs/guides/claude-code.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,12 @@ Operational contract when enabled:

See [Configuration](/reference/configuration/providers/#anthropicaccountpool-experimental).

For managed native OAuth requests, declared custom tools use consistent names across deferred
references and inline additions or removals. Tool arguments, schemas and cache markers are retained.
Ambiguous tool declarations are rejected before sending a request. For inline tool changes in
system messages, send the required `inline-tools-2026-09-15` beta; the first-party native builder
preserves that requested header with the typed blocks. See [Claude’s inline tool contract](https://platform.claude.com/docs/en/build-with-claude/mid-conversation-system-messages).

Comment thread
coderabbitai[bot] marked this conversation as resolved.
## Quickstart

```bash
Expand Down
Loading
Loading