Skip to content
Open
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
71 changes: 71 additions & 0 deletions docs/ai/design/2026-08-17-feature-pi-print-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
phase: design
title: Pi Print Mode Design
description: Architecture for durable Pi JSON-mode agents
---

# Pi Print Mode Design

## Architecture Overview

```mermaid
flowchart LR
CLI[agent start/send/list/detail] --> Dispatch[provider dispatch]
Dispatch --> Service[PiPrintAgentService]
Service --> Probe[PiCliProbe]
Service --> Repository[DurableAgentRepository]
Service --> Runner[PiPrintRunner]
Runner -->|pi --mode json --session-id/--session UUID| Pi[Pi CLI]
Pi -->|session header + events| Runner
Repository --> Registry[(agents.db durable_agents)]
Registry --> Console[agent list / detail]
```

Pi follows the merged Claude durable service/runner boundary. The open Codex design is used only as a read-only consistency reference.

## Data Models

- `DurableProvider`: `claude | pi`.
- `DurableAgent`: shared identity, durable mode, cwd binding, state, timestamps, active-run identity, and last result.
- `DurableAgentRepository` assigns a provider session UUID at creation and persists rows in SQLite migration 003.

## API Design

- `PiCliProbe.validate()` runs `pi --version` and `pi --help`, requiring `--mode`, `json`, `--session-id`, and `--session`.
- `PiPrintRunner.run(request)` uses `--session-id <uuid>` for a first run and `--session <uuid>` for resume; prompt is sent on stdin.
- `onSpawn(ProcessIdentity)` persists process ownership; the emitted session UUID must match the repository-assigned UUID.
- `PiPrintAgentService.create()` probes then creates with provider `pi`.
- `PiPrintAgentService.send()` resolves, locks, checks provider, runs, records success/failure, and always releases through `completeRun`.
- CLI creates and dispatches services by stored provider rather than assuming Claude.

## Component Breakdown

- `DurableAgent.ts`: provider union and Pi errors.
- `DurableAgentRepository.ts`: SQLite persistence, provider creation, and CAS run ownership.
- `PiCliProbe.ts`: sanitized capability validation.
- `PiPrintRunner.ts`: bounded JSONL parser, identity validation, lifecycle/result extraction, subprocess safety.
- `PiPrintAgentService.ts`: orchestration and state transitions.
- `agent.ts`: start validation, provider-aware send, labels, and detail output.
- Tests mock process and store boundaries following Claude print patterns.

## Protocol Rules

- Accept exactly one valid leading/session identity event; duplicate or invalid session identity is a protocol error.
- Verify every run emits the stored UUID.
- Collect non-empty assistant text from completed assistant messages; return the last complete assistant text.
- Require clean line-delimited JSON, a zero exit code, a session identity, `agent_end`, and at least one assistant result.
- Reject oversized lines and incomplete trailing JSON; drain stderr without echoing potentially sensitive provider content.

## Design Decisions

- Selected JSON mode over plain print mode for durable session identity.
- Use Pi's `--session-id` support so the durable repository remains the UUID authority.
- Extend only the shared provider union and create input; no migration or legacy import is needed.
- Keep synchronous send behavior and SQLite CAS ownership; no daemon or streaming transport.

## Non-Functional Requirements

- Security: `shell: false`, stdin prompts, canonical non-symlink cwd, bounded JSON lines, sanitized summaries, no stderr reflection.
- Reliability: atomic SQLite mutations, provider/session uniqueness, CAS ownership, mismatch degradation, stale-run reconciliation.
- Performance: streaming JSONL parsing with a 1 MiB default line bound; no whole-output buffering.
- Compatibility: no dependencies and no behavioral changes to interactive Pi or Claude print invocations.
54 changes: 54 additions & 0 deletions docs/ai/implementation/2026-08-17-feature-pi-print-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
---
phase: implementation
title: Pi Print Mode Implementation
description: Living implementation record for durable Pi print agents
---

# Pi Print Mode Implementation

## Development Setup

- Worktree: `feature-pi-print-mode`, rebased onto the durable-agents architecture on `origin/main`.
- References: merged Claude implementation under `packages/agent-manager/src/durable/`; read-only Codex worktree at `../feature-codex-print-mode`.
- Pi ground truth: installed package README, `docs/json.md`, and CLI capability probe.
- Tests run with repository Vitest/Nx scripts; no new dependencies.

## Code Structure

Pi provider modules live beside the Claude modules under `src/durable/`. Shared changes are limited to the provider union, repository create input, exports, and CLI dispatch.

## Implementation Notes

### Core Features

- Complete: Pi support in the shared SQLite `DurableAgentRepository`; no legacy import or Pi-specific migration is needed.
- Complete: Pi capability probe, bounded JSONL runner, repository-assigned session UUID via `--session-id`, exact resume args, and service state orchestration.
- Complete: provider-aware CLI creation/send dispatch, Pi labels, and shared durable list/detail integration.
- Complete: user-facing creation uses `--mode durable`; the retired `--mode print` spelling is rejected consistently.
- Complete: pure `PiPrintProtocol` helpers make argument, session-identity, and assistant-text mapping independently testable at 100% coverage.

### Patterns & Best Practices

- Red-green-refactor for each planning task.
- Mock child processes and store boundaries; validate public behavior.
- Preserve Claude defaults for callers that omit provider.

## Integration Points

`agent start` creates through the provider service; `agent send` resolves the persisted record then dispatches by provider; list/detail/console use the shared durable repository.

## Error Handling

Provider-specific probe/protocol/process errors are sanitized. The service maps identity mismatches to `sessionHealth: mismatch` and other failures to `unknown`, then records completion to release ownership.

## Performance Considerations

Parse stdout incrementally with a 1 MiB line limit. Store only the final bounded result summary.

## Security Notes

No shell, prompt via stdin, canonical cwd, no stderr reflection, UUID validation, and SQLite CAS run ownership.

## Deviations and Follow-ups

The original file-store generalization was dropped because main now supplies SQLite persistence and CAS concurrency. Pi uses the repository-assigned UUID directly, avoiding late session binding. Provider files are isolated under `src/durable/`; shared edits remain additive.
49 changes: 49 additions & 0 deletions docs/ai/planning/2026-08-17-feature-pi-print-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
---
phase: planning
title: Pi Print Mode Plan
description: TDD implementation plan for durable Pi print agents
---

# Pi Print Mode Plan

## Milestones

- [x] Requirements and Pi CLI investigation
- [x] Architecture and test strategy
- [x] Provider-aware durable storage
- [x] Pi probe, runner, and service
- [x] CLI integration and lifecycle verification

## Task Breakdown

### Phase 1: Storage Foundation

- [x] T1: Rebase onto the SQLite durable-agent repository and add a failing test for Pi creation/provider validation. No legacy import is required.
- [x] T2: Extend the provider union and repository create input additively while retaining Claude defaults and CAS behavior.

### Phase 2: Pi Provider

- [x] T3: Add failing probe tests for supported, missing, unsupported, and sanitized failure cases; implement `PiCliProbe`. Depends on T2. Evidence: probe suite and coverage. Scenarios: S6-S8.
- [x] T4: Add failing runner tests for first/resume args, stdin, event parsing, identity mismatch, malformed/oversized/incomplete output, process failures, and callbacks; implement `PiPrintRunner`. Depends on T2. Evidence: runner suite and coverage. Scenarios: S9-S18.
- [x] T5: Add failing mocked-service integration tests for create/send success, resume, ambiguity/provider mismatch, binding failure, and state recording; implement `PiPrintAgentService`. Depends on T3-T4. Evidence: service suite. Scenarios: S19-S24.

### Phase 3: CLI Integration

- [x] T6: Add failing CLI tests for Pi print start, provider-aware send/list/detail/console representation, validation, and Claude regression; implement dispatch wiring and exports. Depends on T5. Evidence: CLI targeted suite. Scenarios: S25-S30.
- [x] T7: Update implementation/testing docs, run full relevant tests, coverage, lint, typecheck/build, and lifecycle review. Depends on all tasks. Evidence: fresh command outputs and feature lint.

## Dependencies

Storage generalization precedes provider code; runner and probe precede service; service precedes CLI. No new external dependencies. The Codex worktree is read-only reference material, never a branch dependency.

## Risks & Mitigation

- Pi protocol drift: capability probe plus strict protocol tests and explicit errors.
- Store migration regression: version-1 fixtures and full Claude print regression suite.
- Session cross-binding: ownership checks and per-provider uniqueness.
- Sensitive output leakage: stderr drain and bounded sanitized summaries.
- CLI ambiguity: dispatch from persisted provider and preserve existing exact-ID rules.

## Progress Summary

The obsolete file-store generalization commit was dropped during rebase. Pi provider and CLI adaptation now target `DurableAgentRepository`; fresh post-rebase validation is required before completion.
65 changes: 65 additions & 0 deletions docs/ai/requirements/2026-08-17-feature-pi-print-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
---
phase: requirements
title: Pi Print Mode Requirements
description: Durable non-interactive Pi coding agents managed by AI DevKit
---

# Pi Print Mode Requirements

## Problem Statement

AI DevKit can start Pi only as an interactive terminal process. Automation needs a durable, non-interactive Pi agent that can be registered once, addressed by AI DevKit ID or name, resumed across invocations, inspected alongside other agents, and reconciled after an interrupted run.

## Goals & Objectives

- Support `ai-devkit agent start --type pi --mode durable --name <name> --cwd <dir>`.
- Run Pi non-interactively through its structured JSON event mode.
- Persist the Pi session UUID after the first run and resume it with `--session <id>`.
- Reuse Claude print-agent identity, locking, lifecycle, listing, detail, and pruning semantics.
- Keep Claude print agents backward compatible and align storage with the Codex print-mode generalization in PR #148.
- Add no runtime dependencies.

Non-goals:

- Changing existing interactive Pi behavior.
- Streaming partial Pi output or live heartbeats to the console.
- Supporting Pi's interactive session picker (`--resume`) or forking.
- Merging or depending on the open Codex print branch.

## User Stories & Use Cases

- As an automation user, I can register a named Pi print agent without opening a terminal UI.
- As a user, I can send multiple prompts to that agent and retain Pi conversation context.
- As a user, I can see Pi print agents in `agent list` and `agent console`, and inspect their provider session ID.
- As a user, I receive a clear failure when Pi is missing, lacks required flags, emits invalid JSON, changes session identity, or exits unsuccessfully.
- As a user, an interrupted provider process is reconciled using existing print-agent run-lock behavior.

## Success Criteria

- `--type pi --mode durable` creates a persisted `provider: "pi"` agent with a repository-assigned provider session UUID.
- First send invokes `pi --mode json`, extracts and stores the session header UUID, and returns the final assistant text.
- Later sends invoke `pi --mode json --session <uuid>` and reject a different emitted UUID.
- Pi agents participate in existing list/detail/send/console flows and provider-specific dispatch.
- Claude store data remains readable and Claude tests remain green.
- New probe, protocol parsing, and argument mapping branches have 100% statement, branch, function, and line coverage.
- Agent-manager and CLI tests, typechecks/builds, and feature-doc lint pass.

## Constraints & Assumptions

- Ground truth is the installed `@earendil-works/pi-coding-agent`: `--mode json` is non-interactive, emits a leading `{type:"session", id}` JSON line, auto-saves sessions, and accepts `--session <path|id>`.
- Pi has no Claude-style caller-assigned session ID; the store must bind the provider-emitted UUID during the first run.
- Pi JSON mode emits lifecycle events rather than one terminal result object; the runner derives the result from completed assistant messages and requires `agent_end`.
- Prompts are written to stdin to avoid shell interpolation and command-line disclosure; subprocesses use `shell: false`.
- Existing print-agent storage must migrate safely without losing Claude agents.
- The globally installed lifecycle skills satisfy execution even though project-local built-in installation fails at `.agents/skills`; optional task tracing is unavailable (`unknown command 'task'`).

## Alternatives Considered

- `pi -p`: simple text output but does not expose the new session UUID reliably; rejected.
- Discover the session file after execution: races with other Pi processes and couples to filesystem layout; rejected.
- `pi --mode rpc`: designed for a long-lived controller and adds unnecessary lifecycle complexity; rejected.
- `pi --mode json --session-id <uuid>`: deterministic structured identity using the repository-assigned UUID; selected.

## Questions & Open Items

No material open items. Pi's documented session identity and resume surface resolves the durability question.
94 changes: 94 additions & 0 deletions docs/ai/testing/2026-08-17-feature-pi-print-mode.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,94 @@
---
phase: testing
title: Pi Print Mode Testing Strategy
description: Unit, integration, CLI, and regression coverage for Pi print agents
---

# Pi Print Mode Testing Strategy

## Test Coverage Goals

- 100% statements, branches, functions, and lines for new pure probe/protocol/argument-mapping logic.
- Mocked subprocess tests; no model credentials or network calls.
- Mocked-store service integration tests for every state transition.
- CLI command tests for critical creation and dispatch flows.
- Full Claude print regression coverage and package typecheck/build.

## Unit Tests

### Store and Types

- [ ] S1 Pi agents start with a null provider session while Claude retains an assigned UUID.
- [ ] S2 version-1 Claude stores load and migrate to version 2 on mutation.
- [ ] S3 an owned Pi run binds one valid UUID idempotently.
- [ ] S4 binding rejects invalid UUIDs, ownership changes, non-Pi agents, mismatches, and duplicate provider bindings.
- [ ] S5 malformed provider-discriminated records are rejected.

### Pi CLI Probe

- [x] S6 supported Pi help/version returns sanitized metadata.
- [x] S7 missing flags produce an unsupported-capability error.
- [x] S8 execution failures produce a sanitized unavailable error.

### Pi JSON Runner

- [x] S9 first-run args are `--mode json`; resume adds `--session <uuid>`; prompt uses stdin and shell is disabled.
- [x] S10 provider process identity and session callbacks run.
- [x] S11 the session header and completed assistant message yield the final result.
- [x] S12 multiple assistant completions return the last complete message.
- [x] S13 missing/invalid/duplicate/mismatched session identity is rejected.
- [x] S14 malformed, non-object, oversized, or incomplete JSON is rejected.
- [x] S15 missing `agent_end` or assistant output is rejected.
- [x] S16 spawn identity/start errors and callback failures terminate safely.
- [x] S17 non-zero/signal exits become process errors.
- [x] S18 stderr is drained without inclusion in results.

## Integration Tests

- [x] S19 service create probes and persists provider `pi`.
- [x] S20 first send records process/session, success, health, and sanitized summary.
- [x] S21 resumed send preserves the bound session.
- [x] S22 missing/ambiguous/wrong-provider references fail clearly.
- [x] S23 protocol/store session mismatches record mismatch health.
- [x] S24 other failures record unknown health and release the run.

## CLI and End-to-End Tests

- [x] S25 `agent start --type pi --mode durable` creates without interactive launch.
- [x] S26 unsupported durable providers and the retired `print` mode name remain rejected.
- [x] S27 `agent send` dispatches Pi records to the Pi service and reports provider `pi`.
- [x] S28 list/detail output identifies durable Pi agents and their repository-assigned sessions.
- [x] S29 console receives the combined interactive/durable registry.
- [x] S30 Claude print start/send/list/detail behavior remains green.

## Test Data

Use temporary store/cwd fixtures, deterministic clocks/process identities, valid UUID fixtures, mocked child-process streams, and mocked probe/runner/store boundaries. Never invoke a live model.

## Test Reporting & Coverage

- Targeted: `npx vitest run <changed test files>` in relevant packages.
- Coverage: package Vitest coverage scoped to Pi pure-logic files with 100% thresholds.
- Regression: `npm test --workspace @ai-devkit/agent-manager` and CLI equivalent.
- Static: package lint/typecheck/build and `npx ai-devkit@latest lint --feature pi-print-mode`.

Final evidence (2026-08-17):

- Agent manager: 28 files, 552 tests passed.
- CLI: 82 files, 986 tests passed.
- Pi focused suites: 4 files, 23 tests passed.
- Pure Pi protocol: 100% statements (26/26), branches (38/38), functions (4/4), and lines (20/20), enforced with `--coverage.thresholds.100=true`.
- Agent-manager and CLI package builds passed; package lints passed (CLI retains five unrelated baseline warnings and zero errors).
- Feature-doc lint passed all base, feature, branch, and worktree checks.

## Manual Testing

No credentialed Pi model run is required. `pi --help` and installed docs provide CLI-surface evidence; subprocess behavior is deterministic under mocks.

## Performance and Security Testing

Oversized-line tests exercise the memory bound. Spawn assertions cover `shell: false`, cwd binding, stdin prompt delivery, stderr draining, and provider-output sanitization.

## Bug Tracking

Any failing scenario returns to its implementation task, is added as a regression test first, and is documented in implementation notes.
Loading
Loading