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
157 changes: 157 additions & 0 deletions docs/ai/design/2026-08-23-feature-claude-provider-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
---
phase: design
title: Claude Provider Refactor Design
description: Provider-local Claude module boundary with public package exports
---

# Claude Provider Refactor Design

## Architecture Overview

The refactor introduces a Claude provider-local implementation area while preserving current package-root adapter and durable exports.

```mermaid
graph TD
PublicIndex["src/index.ts"] --> ClaudeAdapter["src/providers/claude/ClaudeCodeAdapter.ts"]
AdapterIndex["src/adapters/index.ts"] --> ClaudeAdapter

ClaudeAdapter --> Locator["ClaudeSessionLocator"]
ClaudeAdapter --> Parser["ClaudeSessionParser"]
ClaudeAdapter --> Mapper["ClaudeAgentMapper"]
ClaudeAdapter --> SharedProcess["utils/process"]
ClaudeAdapter --> SharedMatching["utils/matching"]

PublicIndex --> ClaudeDurable["src/providers/claude/durable/*"]
ClaudeDurable --> Database["database + DurableAgentRepository contracts"]
ClaudeDurable --> ClaudeCli["Claude CLI"]
```

The public package shape remains stable. The internal shape changes from feature/top-level scattered Claude files to provider-local ownership:

```text
packages/agent-manager/src/
providers/
claude/
ClaudeCodeAdapter.ts
ClaudeSessionLocator.ts
ClaudeSessionParser.ts
ClaudeAgentMapper.ts
durable/
ClaudeCliProbe.ts
ClaudePrintRunner.ts
ClaudePrintAgentService.ts
```

## Data Models

No persisted schema changes are introduced.

Provider-local transient types:

- `ClaudePidFileEntry`: parsed shape of `~/.claude/sessions/<pid>.json`.
- `ClaudeDirectMatch`: process, session file, optional live status, optional waiting reason.
- `ClaudeLocatedSessionFile`: existing `SessionFile` plus Claude-resolved cwd semantics.
- `ClaudeAgentMappingInput`: parsed Claude session, process, located session file, optional live info.

Existing public models remain unchanged:

- `AgentInfo`
- `ProcessInfo`
- `ConversationMessage`
- `SessionSummary`
- `DurableAgent`
- `CapacityReport`

## API Design

### Public API

No public package-root API change.

Existing exports stay valid:

```ts
export { ClaudeCodeAdapter } from './providers/claude/ClaudeCodeAdapter.js';
export { ClaudePrintAgentService } from './providers/claude/durable/ClaudePrintAgentService.js';
```

The implementation exports high-level public provider entry points directly from `src/providers/claude/...` through `src/index.ts` and `src/adapters/index.ts`. Lower-level Claude print probe/runner classes stay provider-local; thin path-level wrapper files were removed because they added no behavior or contract value.

### Internal Interfaces

The first implementation should prefer small concrete classes/functions over broad interfaces:

```ts
class ClaudeSessionLocator {
matchRunningProcesses(processes: ProcessInfo[]): ClaudeMatchSet;
discoverHistoricalSessionFiles(): Array<{ filePath: string; defaultCwd: string }>;
getProjectDir(cwd: string): string;
}

class ClaudeAgentMapper {
mapSessionToAgent(input: ClaudeAgentMappingInput): AgentInfo;
mapProcessOnlyAgent(processInfo: ProcessInfo): AgentInfo;
}
```

Avoid introducing a cross-provider `Provider` or `CapabilityProvider` public abstraction in this feature. If needed later, it should be based on multiple real provider capability implementations.

## Component Breakdown

### `providers/claude/ClaudeCodeAdapter.ts`

Keeps the `AgentAdapter` implementation and orchestrates the flow:

1. Capture/filter Claude processes.
2. Ask `ClaudeSessionLocator` for direct and legacy matches.
3. Parse matched session files with `ClaudeSessionParser`.
4. Map sessions/processes to `AgentInfo` with `ClaudeAgentMapper`.
5. Delegate conversation and historical session listing.

### `providers/claude/ClaudeSessionLocator.ts`

Owns Claude filesystem/session location rules:

- Claude project path encoding.
- `claude --resume <uuid>` extraction.
- PID-file read and stale guard.
- PID-file live status mapping.
- Direct match construction.
- Legacy CWD + birthtime discovery setup.
- Historical session candidate walking.

It may still call shared utilities such as `batchGetSessionFileBirthtimes`, `safeStat`, `safeReaddir`, `listJsonl`, and `matchProcessesToSessions`.

### `providers/claude/ClaudeSessionParser.ts`

Moves from `utils/` without logic changes. It remains responsible for Claude JSONL parsing, conversation extraction, noise filtering, and JSONL-derived status.

### `providers/claude/ClaudeAgentMapper.ts`

Owns conversion from Claude provider data to `AgentInfo`:

- live PID status precedence;
- waiting reason summary decoration;
- process-only fallback representation;
- generated agent names;
- project path and session file path assignment.

### `providers/claude/durable/*`

Provider-local home for Claude print-mode execution mechanics. Existing `src/durable/*` files should stay as compatibility exports unless planning decides the move is too broad for the first implementation pass.

## Design Decisions

- **Provider-local first, generic later.** The chosen structure improves locality without inventing abstractions before there are multiple implementations.
- **Compatibility exports stay.** Public and existing internal import paths are kept stable while implementation files move.
- **Move/extract before behavior change.** The initial implementation should avoid modifying matching/status/listing behavior.
- **Capacity and durable are capabilities.** Their current top-level facades can remain public, but provider-specific implementation should live with the provider over time.
- **Claude first.** Codex capacity, Pi sessions, Gemini sessions, and other providers are explicitly deferred.

## Non-Functional Requirements

- **Reliability:** All existing Claude interactive and durable behavior must remain covered by tests.
- **Performance:** Session discovery should preserve existing batching behavior and should not add broad directory scans to `detectAgents()`.
- **Security:** Prompt content, provider output, and credentials handling remain unchanged. Durable prompt stdin behavior and bounded result sanitization remain intact.
- **Maintainability:** New modules should have one clear responsibility and avoid one-file directories unless they are compatibility wrappers.
- **Deletion cost:** Compatibility wrappers should be easy to remove in a future breaking cleanup, but they must stay for this feature.
119 changes: 119 additions & 0 deletions docs/ai/implementation/2026-08-23-feature-claude-provider-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,119 @@
---
phase: implementation
title: Claude Provider Refactor Implementation Notes
description: Technical notes and evidence for behavior-preserving Claude provider extraction
---

# Claude Provider Refactor Implementation Notes

## Development Setup

- Active worktree: `.worktrees/feature-claude-provider-refactor`
- Branch: `feature-claude-provider-refactor`
- Dependency bootstrap: `npm ci` completed.
- Lifecycle lint: `npx ai-devkit@latest lint --feature claude-provider-refactor` passes.

## Code Structure

Target internal structure:

```text
packages/agent-manager/src/providers/claude/
ClaudeCodeAdapter.ts
ClaudeSessionLocator.ts
ClaudeSessionParser.ts
ClaudeAgentMapper.ts
types.ts
durable/
```

Package-root exports remain the compatibility surface. Thin path-level wrappers under `src/adapters`, `src/utils`, and `src/durable` were removed after review because they only re-exported provider-local modules.

## Implementation Notes

### Core Features

- Move files first, then extract logic.
- Keep `ClaudeCodeAdapter` as the public `AgentAdapter` implementation.
- Keep parser behavior unchanged.
- Keep live PID-file status precedence unchanged.
- Keep legacy CWD + birthtime matching fallback unchanged.
- Keep durable Claude print-mode behavior unchanged.

### Patterns & Best Practices

- Preserve public package exports while avoiding no-value path-level re-export files.
- Keep provider-local concrete classes small and focused.
- Avoid a generic provider/capability framework in this feature.
- Add comments only where extraction makes responsibility boundaries clearer.
- Prefer existing utilities from `utils/session`, `utils/matching`, and `utils/process`.

## Integration Points

- `src/index.ts` and `src/adapters/index.ts` continue exporting `ClaudeCodeAdapter` directly from the Claude provider.
- `AgentManager` continues working through `AgentAdapter`.
- `ClaudeCodeAdapter` continues using shared process snapshot filtering.
- Durable service continues using `DurableAgentRepository`, provider-local `ClaudeCliProbe`, and provider-local `ClaudePrintRunner` contracts.

## Error Handling

- PID-file read, malformed JSON, stale metadata, and missing JSONL errors remain swallowed and routed to fallback behavior.
- Session JSONL read errors continue returning `null` or empty conversations as before.
- Durable provider errors and sanitization remain unchanged.

## Performance Considerations

- Live detection must remain process-scoped and avoid scanning all Claude project directories.
- Historical `listSessions()` may continue walking every Claude project directory by design.
- `batchGetSessionFileBirthtimes()` remains the shared stat batching utility for legacy live matching.

## Security Notes

- No new provider command execution behavior is introduced.
- Prompt handling and durable stdin behavior remain unchanged.
- Provider-reported metadata is not promoted to persisted state by this refactor.
- Public exports must not duplicate or alter durable persistence behavior.

## Implementation Log

- Baseline validation before source changes:
- `npm run nx -- test agent-manager` passed with 28 test files and 568 tests.
- `npm run lint` in `packages/agent-manager` passed.
- `npm run typecheck` in `packages/agent-manager` passed.
- `npm run build` in `packages/agent-manager` passed.
- Moved `ClaudeSessionParser` to `packages/agent-manager/src/providers/claude/ClaudeSessionParser.ts`.
- Focused parser validation passed with 19 tests.
- Moved `ClaudeCodeAdapter` implementation to `packages/agent-manager/src/providers/claude/ClaudeCodeAdapter.ts`.
- Focused adapter validation passed with 87 tests.
- Added `packages/agent-manager/src/providers/claude/ClaudeAgentMapper.ts`.
- Extracted session-backed and process-only `AgentInfo` mapping from the adapter.
- Added focused mapper tests covering live status precedence, waiting summaries, and process-only fallback.
- Added `packages/agent-manager/src/providers/claude/ClaudeSessionLocator.ts`.
- Extracted resume matching, PID-file matching, legacy live discovery, project-dir encoding, and historical session discovery from the adapter.
- Added focused locator test covering resume matching plus live PID status metadata.
- Moved the adapter's locator-facing tests onto `ClaudeSessionLocator` so no compatibility proxies remain on the adapter.
- Moved Claude durable execution implementations under `packages/agent-manager/src/providers/claude/durable/`.
- Claude print-mode focused validation passed with 4 test files and 8 tests.
- Removed no-value wrapper files after review:
- `packages/agent-manager/src/adapters/ClaudeCodeAdapter.ts`
- `packages/agent-manager/src/utils/ClaudeSessionParser.ts`
- `packages/agent-manager/src/durable/ClaudeCliProbe.ts`
- `packages/agent-manager/src/durable/ClaudePrintRunner.ts`
- `packages/agent-manager/src/durable/ClaudePrintAgentService.ts`
- Updated `src/index.ts`, `src/adapters/index.ts`, and focused tests to import provider-local modules directly.
- Cleaned package-root exports after review:
- Removed process-helper exports: `getProcessTty`, `captureProcessSnapshot`, `executableBasename`, and `filterByProcessNames`.
- Removed root export of `AgentSortKey`; `ListAgentsOptions` remains exported as the public options contract.
- Removed root export of `LocalProcessInspector`; `ProcessInspector` remains exported as the injectable contract.
- Kept `ClaudePrintAgentService` public and moved `ClaudeCliProbe`/`ClaudePrintRunner` tests to provider-local imports.
- Final validation after source changes:
- `npm run nx -- test agent-manager` passed with 30 test files and 571 tests.
- `npm run lint` in `packages/agent-manager` passed.
- `npm run typecheck` in `packages/agent-manager` passed.
- `npm run build` in `packages/agent-manager` passed.
- `npx ai-devkit@latest lint --feature claude-provider-refactor` passed.

## Design Deviations

- `providers/claude/types.ts` was not created. The extracted modules did not need a shared provider-local type barrel, and skipping it avoids a thin abstraction.
- Adapter private compatibility proxies for `discoverSessions`, `tryPidFileMatching`, and `getProjectDir` were removed after review. The 19 tests that drove them moved to `__tests__/providers/claude/ClaudeSessionLocator.test.ts` and now target `ClaudeSessionLocator` directly, so `tryPidFileMatching` and `getProjectDir` are private on the locator again.
108 changes: 108 additions & 0 deletions docs/ai/planning/2026-08-23-feature-claude-provider-refactor.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
---
phase: planning
title: Claude Provider Refactor Plan
description: Ordered behavior-preserving extraction plan for Claude provider code
---

# Claude Provider Refactor Plan

## Milestones

- [x] Milestone 1: Requirements, design, and testing strategy created.
- [x] Milestone 2: Baseline validation recorded before source changes.
- [x] Milestone 3: Claude parser and adapter implementation moved into provider-local modules.
- [x] Milestone 4: Claude session locator and agent mapper extracted with focused tests.
- [x] Milestone 5: Claude durable implementation moved into provider-local modules.
- [x] Milestone 6: Final validation, implementation check, testing update, and review complete.

## Task Breakdown

### Phase 1: Baseline and Compatibility Shell

- [x] Task 1.1: Run baseline `agent-manager` test, typecheck, lint, and build commands.
- Outcome: pre-refactor pass/fail evidence is recorded.
- Validation: task evidence includes command, exit code, and summary.
- Testing scenarios: baseline reporting in testing doc.
- [x] Task 1.2: Create `src/providers/claude/` and move `ClaudeSessionParser` to the provider-local path.
- Outcome: parser tests import the provider-local module directly.
- Validation: `ClaudeSessionParser` tests pass.
- Testing scenarios: parser compatibility.
- [x] Task 1.3: Move `ClaudeCodeAdapter` implementation to the provider-local path.
- Outcome: public and adapter barrel exports remain valid without a path-level wrapper.
- Validation: `ClaudeCodeAdapter` tests compile and pass.
- Testing scenarios: adapter export compatibility.

### Phase 2: Provider-Local Extraction

- [x] Task 2.1: Extract Claude session locating/matching logic into `providers/claude/ClaudeSessionLocator.ts`.
- Outcome: resume matching, PID-file matching, legacy discovery, and historical discovery are isolated from adapter orchestration.
- Dependencies: Task 1.3.
- Validation: existing adapter tests pass; add focused locator tests if exposed behavior is easier to assert directly.
- Testing scenarios: resume direct match, stale PID fallback, missing JSONL fallback, historical discovery.
- [x] Task 2.2: Extract Claude `AgentInfo` mapping into `providers/claude/ClaudeAgentMapper.ts`.
- Outcome: live status precedence, waiting summary decoration, and process-only fallback are isolated.
- Dependencies: Task 2.1.
- Validation: adapter tests pass; focused mapper tests cover status/summary/path behavior.
- Testing scenarios: mapper unit scenarios.
- [x] Task 2.3: Add provider-local `types.ts` only for shared Claude internal types that are used by more than one provider-local module.
- Outcome: not needed. Shared internal types stayed local to `ClaudeAgentMapper` and `ClaudeSessionLocator`, avoiding a thin unused file.
- Dependencies: Task 2.1 or 2.2 if duplication appears.
- Validation: typecheck.

### Phase 3: Durable Provider Locality

- [x] Task 3.1: Move Claude durable execution files under `providers/claude/durable/`, if the move is low-risk after Phase 2.
- Outcome: `ClaudeCliProbe`, `ClaudePrintRunner`, and `ClaudePrintAgentService` are provider-local while the package root keeps the high-level durable service public.
- Dependencies: Phase 2 complete and green.
- Validation: durable print tests pass.
- Testing scenarios: existing durable tests through compatibility exports.
- [x] Task 3.2: If durable relocation creates disproportionate churn, defer it explicitly in implementation notes and keep the interactive Claude extraction complete.
- Outcome: durable relocation completed; no deferral was required.
- Outcome: scope remains safe and documented.
- Dependencies: Phase 2 outcome.
- Validation: docs record deferral rationale.

### Phase 4: Final Checks

- [x] Task 4.1: Update implementation and testing docs with changed files, decisions, deviations, and command evidence.
- [x] Task 4.2: Run final package validation: tests, typecheck, lint, build, and feature lint.
- [x] Task 4.3: Run implementation alignment check against requirements/design.
- [x] Task 4.4: Run final review and close task if no blocking findings remain.

## Dependencies

- Existing public exports in `src/index.ts` and `src/adapters/index.ts` must remain compatible throughout.
- Task 1.1 must complete before source edits.
- Parser and adapter moves should happen before extraction to minimize import churn.
- Durable relocation depends on interactive provider extraction being stable.

## Timeline & Estimates

- Baseline and compatibility shell: small.
- Locator and mapper extraction: medium, highest regression risk because tests currently exercise private adapter behavior indirectly.
- Durable relocation: small to medium, but can be deferred if it adds unrelated blast radius.
- Final validation/review: medium because full `agent-manager` tests and build must run.

## Risks & Mitigation

- **Risk:** Provider-local exports break declaration output or package barrels.
- Mitigation: run typecheck/build after moves and inspect public exports.
- **Risk:** Private-method tests become brittle after extraction.
- Mitigation: move assertions to provider-local module tests where behavior is now first-class.
- **Risk:** Locator extraction accidentally changes fallback ordering.
- Mitigation: preserve existing test coverage and move code mechanically before simplifying.
- **Risk:** Durable relocation pulls in broader repository import churn.
- Mitigation: keep old durable files as re-exports; defer relocation if it becomes disproportionate.
- **Risk:** Lint rules reject re-export-only compatibility files.
- Mitigation: use existing barrel export style and validate early.

## Resources Needed

- Existing `agent-manager` Vitest suites.
- Existing Claude adapter/parser/durable fixtures and fake Claude executable.
- `npx ai-devkit@latest lint --feature claude-provider-refactor` for lifecycle validation.
- Task tracing under `claude-provider-refactor`.

## Progress Summary

Implementation completed. Claude interactive detection, parsing, mapping, session locating, and durable print-mode execution now live under `src/providers/claude/`. Package-root and adapter-barrel exports are preserved for high-level public entry points, while no-value path-level wrappers and lower-level root exports were removed. The planned `types.ts` file was intentionally skipped because extracted modules did not need a shared provider-local type barrel.
Loading
Loading