Managed Provider Process Implementation Plan
For Claude: REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task.
Goal: Replace the Unix-shaped process-group helper with a provider-process abstraction that provider adapters can use without knowing platform-specific process-tree cleanup details.
Architecture: Provider adapters should ask for a managed provider process and receive a child process plus lifecycle helpers. POSIX cleanup uses detached process groups and negative-pid signaling. Windows provider-process cleanup is intentionally unsupported until there is a tested implementation; the managed boundary should fail clearly on Windows rather than claim unverified process-tree ownership.
Tech Stack: TypeScript, Node child_process, Vitest, existing harness provider adapters.
Task 1: Introduce Managed Provider Process Boundary#
Files:
- Create:
src/process/managed-child.ts - Modify:
src/process/index.ts - Test:
test/managed-child.test.ts
Step 1: Write managed-child tests
Cover:
- spawning a fixture child and grandchild through the managed helper
terminate()kills both processes on POSIX- termination escalates when graceful termination is ignored
attachAbort()terminates the child tree when an abort signal fires
Use existing fixture helpers from test/helpers.ts.
Step 2: Run focused test and verify it fails
Run:
npm test -- test/managed-child.test.tsExpected: fail because src/process/managed-child.ts does not exist.
Step 3: Implement the managed boundary
Create a wrapper interface:
export interface ManagedChildProcess {
child: ChildProcess;
readonly treeId?: number;
terminate(options?: TerminateManagedChildOptions): Promise<void>;
attachAbort(signal: AbortSignal, options?: TerminateManagedChildOptions): () => void;
}Expose:
export function spawnManagedChildProcess(
command: string,
args: readonly string[],
options: SpawnOptions,
): ManagedChildProcessImplementation rules:
- POSIX: use
detached: true, record child pid astreeId, signal-treeId, wait, then escalate. - Windows: throw a clear unsupported-platform error before spawning. Do not add
taskkill, Job Object, or child-only cleanup until it can be tested. - Do not monkey-patch
child.kill. - Treat
ESRCHas unavailable. Do not treatEPERMas dead.
Step 4: Run tests
Run:
npm test -- test/managed-child.test.tsExpected: pass.
Step 5: Commit
git add src/process/managed-child.ts src/process/index.ts test/managed-child.test.ts
git commit -m "feat: add managed provider process abstraction"Task 2: Move Providers Onto Managed Process Boundary#
Files:
- Modify:
src/harness/providers/claude.ts - Modify:
src/harness/providers/codex/app-server.ts - Modify:
src/harness/providers/codex/exec.ts - Test:
test/claude-harness-provider.test.ts - Test:
test/codex-harness-provider.test.ts
Step 1: Update Claude SDK spawn hook
Replace direct spawnInProcessGroup() use with spawnManagedChildProcess().
The SDK-facing object should delegate kill() to managed.terminate({ signal }).
Step 2: Update Codex app-server
Replace direct process-group spawning and termination with the managed process wrapper. Keep existing timeout and signal behavior.
Step 3: Update Codex exec
Move legacy Codex exec to the managed process helper too. This keeps every CLI-backed provider runtime under the same cleanup contract even if app-server is the normal Codex path.
Step 4: Run focused provider tests
Run:
npm test -- test/claude-harness-provider.test.ts test/codex-harness-provider.test.tsExpected: pass.
Step 5: Commit
git add src/harness/providers/claude.ts src/harness/providers/codex/app-server.ts src/harness/providers/codex/exec.ts test/claude-harness-provider.test.ts test/codex-harness-provider.test.ts
git commit -m "refactor: use managed provider processes"Task 3: Remove Old Process-Group Surface#
Files:
- Delete:
src/process/process-group.ts - Delete or rename:
test/process-group.test.ts - Modify imports in source and tests.
Step 1: Search for old names
Run:
rg -n "process-group|spawnInProcessGroup|terminateProcessGroup|attachAbortSignalToProcessGroup|ProcessGroupChild" src testExpected: only old files before cleanup.
Step 2: Remove old files and exports
Use apply_patch to delete old files or move the remaining useful tests into test/managed-child.test.ts.
Step 3: Run focused process/provider tests
Run:
npm test -- test/managed-child.test.ts test/claude-harness-provider.test.ts test/codex-harness-provider.test.tsExpected: pass.
Step 4: Commit
git add -A src/process test
git commit -m "refactor: remove process-group provider surface"Task 4: Update Wiki Decision Log#
Files:
- Modify:
.almanac/pages/process-manager-runs.md - Modify:
.almanac/pages/harness-providers.md - Modify:
.almanac/pages/capture-automation.mdif needed.
Step 1: Update prose
Record:
- provider process ownership is a harness/provider execution concern
- managed child process is the abstraction
- POSIX process groups are implementation detail
- Windows provider-process cleanup is explicitly unsupported until tested
Step 2: Run wiki health
Run:
almanac healthExpected: all categories ok.
Step 3: Commit
git add .almanac/pages/process-manager-runs.md .almanac/pages/harness-providers.md .almanac/pages/capture-automation.md
git commit -m "almanac: record managed provider process boundary"Task 5: Review, Verify, Squash, Merge#
Step 1: Request code review
Review the full branch against origin/dev, focusing on abstraction placement, process cleanup correctness, platform behavior, and test coverage.
Step 2: Fix review findings
Commit review fixes separately.
Step 3: Full verification
Run:
npm run lint
npm run build
npm test
almanac healthExpected: all pass.
Step 4: Squash branch
Squash branch commits into one implementation commit before merging to dev.
Step 5: Merge and push
Fast-forward or merge the squashed commit into dev, then push origin dev.