Skip to content

Commit e68c0d1

Browse files
revised plan
1 parent f4ce551 commit e68c0d1

File tree

1 file changed

+49
-46
lines changed

1 file changed

+49
-46
lines changed

.plans/17-claude-code.md

Lines changed: 49 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -15,12 +15,12 @@ Claude integration must plug into this path instead of reintroducing legacy prov
1515

1616
---
1717

18-
## Current constraints to design around
18+
## Current constraints to design around (post-Stage 1)
1919

2020
1. Provider runtime ingestion expects canonical `ProviderRuntimeEvent` shapes, not provider-native payloads.
21-
2. `ProviderService.startSession` currently defaults to `provider: "codex"` unless explicitly provided.
22-
3. `thread.turn.start` has no provider field today, so first-turn provider selection cannot be explicitly requested.
23-
4. `ProviderService` requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
21+
2. Start input now uses typed `providerOptions` and generic `resumeCursor`; top-level provider-specific fields were removed.
22+
3. `resumeCursor` is intentionally opaque outside adapters and must never be synthesized from `providerThreadId`.
23+
4. `ProviderService` still requires adapter `startSession()` to return a `ProviderSession` with `threadId`.
2424
5. Checkpoint revert currently calls `providerService.rollbackConversation()`, so Claude adapter needs a rollback strategy compatible with current reactor behavior.
2525
6. Web currently marks Claude as unavailable (`"Claude Code (soon)"`) and model picker is Codex-only.
2626

@@ -61,21 +61,24 @@ Update `packages/contracts/src/orchestration.ts`:
6161

6262
This removes the implicit “Codex unless session already exists” behavior as the only path.
6363

64-
### 1.3 Provider session start input for Claude runtime knobs
64+
### 1.3 Provider session start input for Claude runtime knobs (completed)
6565

6666
Update `packages/contracts/src/provider.ts`:
6767

68-
1. Extend `ProviderSessionStartInput` with optional Claude-specific fields (for example `claudeBinaryPath`, `permissionMode`, `maxThinkingTokens`).
69-
2. Keep fields optional so current call sites remain valid.
70-
3. Continue using generic `resumeThreadId` + `resumeCursor` as the cross-provider recovery mechanism.
68+
1. Move provider-specific start fields into typed `providerOptions`:
69+
- `providerOptions.codex`
70+
- `providerOptions.claudeCode`
71+
2. Keep `resumeCursor` as the single cross-provider resume input in `ProviderSessionStartInput`.
72+
3. Deprecate/remove `resumeThreadId` from the generic start contract.
73+
4. Treat `resumeCursor` as adapter-owned opaque state.
7174

72-
### 1.4 Contract tests
75+
### 1.4 Contract tests (completed)
7376

7477
Update/add tests in `packages/contracts/src/*.test.ts` for:
7578

7679
1. New command payload shape.
7780
2. Provider-aware model resolution behavior.
78-
3. Backward compatibility of existing command/schema decoding.
81+
3. Breaking-change expectations for removed top-level provider fields.
7982

8083
---
8184

@@ -100,9 +103,9 @@ Baseline adapter options to support from day one:
100103

101104
1. `cwd`
102105
2. `model`
103-
3. `pathToClaudeCodeExecutable` (from `claudeBinaryPath`)
104-
4. `permissionMode`
105-
5. `maxThinkingTokens`
106+
3. `pathToClaudeCodeExecutable` (from `providerOptions.claudeCode.binaryPath`)
107+
4. `permissionMode` (from `providerOptions.claudeCode.permissionMode`)
108+
5. `maxThinkingTokens` (from `providerOptions.claudeCode.maxThinkingTokens`)
106109
6. `resume`
107110
7. `resumeSessionAt`
108111
8. `includePartialMessages`
@@ -120,7 +123,7 @@ Required capabilities:
120123
2. Multi-turn input queue.
121124
3. Interrupt support.
122125
4. Approval request/response bridge.
123-
5. Resume support via `resumeThreadId` / `resumeCursor`.
126+
5. Resume support via opaque `resumeCursor` (parsed inside Claude adapter only).
124127

125128
#### 2.2.a Agent SDK details to preserve
126129

@@ -129,7 +132,7 @@ The adapter should explicitly rely on these SDK capabilities:
129132
1. `query()` returns an async iterable message stream and control methods (`interrupt`, `setModel`, `setPermissionMode`, `setMaxThinkingTokens`, account/status helpers).
130133
2. Multi-turn input is supported via async-iterable prompt input.
131134
3. Tool approval decisions are provided via `canUseTool`.
132-
4. Resume support uses `resume` and optional `resumeSessionAt`.
135+
4. Resume support uses `resume` and optional `resumeSessionAt`, both derived by parsing adapter-owned `resumeCursor`.
133136
5. Hooks can be used for lifecycle signals (`Stop`, `PostToolUse`, etc.) when we need adapter-originated checkpoint/runtime events.
134137

135138
#### 2.2.b Effect-native session lifecycle skeleton
@@ -142,21 +145,23 @@ const acquireSession = (input: ProviderSessionStartInput) =>
142145
Effect.acquireRelease(
143146
Effect.tryPromise({
144147
try: async () => {
148+
const claudeOptions = input.providerOptions?.claudeCode;
149+
const resumeState = readClaudeResumeState(input.resumeCursor);
145150
const abortController = new AbortController();
146151
const result = query({
147-
prompt: makePromptAsyncIterable(input.sessionId),
152+
prompt: makePromptAsyncIterable(),
148153
options: {
149154
cwd: input.cwd,
150155
model: input.model,
151-
permissionMode: input.permissionMode,
152-
maxThinkingTokens: input.maxThinkingTokens,
153-
pathToClaudeCodeExecutable: input.claudeBinaryPath,
154-
resume: input.resumeThreadId,
155-
resumeSessionAt: readResumeCursor(input.resumeCursor),
156+
permissionMode: claudeOptions?.permissionMode,
157+
maxThinkingTokens: claudeOptions?.maxThinkingTokens,
158+
pathToClaudeCodeExecutable: claudeOptions?.binaryPath,
159+
resume: resumeState?.threadId,
160+
resumeSessionAt: resumeState?.sessionAt,
156161
signal: abortController.signal,
157162
includePartialMessages: true,
158-
canUseTool: makeCanUseTool(input.sessionId),
159-
hooks: makeClaudeHooks(input.sessionId),
163+
canUseTool: makeCanUseTool(),
164+
hooks: makeClaudeHooks(),
160165
},
161166
});
162167
return { abortController, result };
@@ -345,7 +350,8 @@ Define explicit adapter semantics:
345350

346351
1. `sessionId`: adapter-owned stable session id.
347352
2. `threadId`: Claude conversation/session identifier returned as `ProviderThreadId`.
348-
3. `resumeCursor`: provider-specific cursor (for example message id) needed for precise recovery/rollback.
353+
3. `resumeCursor`: provider-specific cursor (for example thread id + message cursor) needed for precise recovery/rollback.
354+
4. Orchestration/shared services persist and forward `resumeCursor` unchanged without provider-specific parsing.
349355

350356
### 2.5 Rollback/read strategy
351357

@@ -402,11 +408,12 @@ Update integration tests to ensure:
402408

403409
## Phase 4: Orchestration command/reactor updates
404410

405-
### 4.1 Decider propagation
411+
### 4.1 Decider propagation (completed)
406412

407413
Update `apps/server/src/orchestration/decider.ts`:
408414

409415
1. Carry optional `provider` from `thread.turn.start` command into `thread.turn-start-requested` event payload.
416+
2. Keep this behavior provider-agnostic (no provider-specific runtime fields in the event payload).
410417

411418
### 4.2 ProviderCommandReactor provider selection
412419

@@ -415,6 +422,7 @@ Update `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`:
415422
1. Prefer provider from turn-start event payload when starting a new session.
416423
2. Fallback to existing thread session provider when payload omitted.
417424
3. Fallback to default provider only when neither is present.
425+
4. On restart/rebind, forward the runtime session's persisted `resumeCursor` as-is (no reconstruction from `providerThreadId`).
418426

419427
Switch behavior policy (explicit in implementation):
420428

@@ -516,31 +524,26 @@ Confirm both native and canonical provider logs remain useful with multi-adapter
516524

517525
## File checklist
518526

519-
Likely files to touch:
520-
521-
1. `packages/contracts/src/model.ts`
522-
2. `packages/contracts/src/orchestration.ts`
523-
3. `packages/contracts/src/provider.ts`
524-
4. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
525-
5. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
526-
6. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
527-
7. `apps/server/src/serverLayers.ts`
528-
8. `apps/server/src/orchestration/decider.ts`
529-
9. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
530-
10. `apps/web/src/session-logic.ts`
531-
11. `apps/web/src/components/ChatView.tsx`
532-
12. Related tests under `packages/contracts/src`, `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
527+
Likely remaining files to touch:
528+
529+
1. `apps/server/src/provider/Services/ClaudeCodeAdapter.ts` (new)
530+
2. `apps/server/src/provider/Layers/ClaudeCodeAdapter.ts` (new)
531+
3. `apps/server/src/provider/Layers/ProviderAdapterRegistry.ts`
532+
4. `apps/server/src/serverLayers.ts`
533+
5. `apps/server/src/orchestration/Layers/ProviderCommandReactor.ts`
534+
6. `apps/web/src/session-logic.ts`
535+
7. `apps/web/src/components/ChatView.tsx`
536+
8. Related tests under `apps/server/src/provider/Layers`, `apps/server/src/orchestration/Layers`, `apps/server/integration`, and `apps/web/src`.
533537

534538
---
535539

536540
## Delivery order
537541

538-
1. Contracts for provider selection + models.
539-
2. Claude adapter + unit tests.
540-
3. Registry/layer wiring.
541-
4. Reactor updates for provider-aware session start.
542-
5. Web provider picker + provider-aware models.
543-
6. Checkpoint/revert compatibility.
544-
7. End-to-end integration tests and stabilization.
542+
1. Claude adapter + unit tests on top of the new `providerOptions`/opaque-cursor contracts.
543+
2. Registry/layer wiring.
544+
3. Remaining reactor updates for provider-aware session selection/switching invariants.
545+
4. Web provider picker + provider-aware models.
546+
5. Checkpoint/revert compatibility.
547+
6. End-to-end integration tests and stabilization.
545548

546549
This order keeps risk isolated and maintains a working orchestrated path at each stage.

0 commit comments

Comments
 (0)