feat(trace): add Pi provider support
Merged
WA
1d ago+1819+1819+0123456789012345678901234567890123456789-123-123-012345678901234567890123456789
Summary
Completes Pi support for Chainloop Trace under issue #3520 and its approved spec:
- registers Pi in the shared provider registry and init wizard;
- adds
trace init --piandtrace run --piwhile preserving Claude Code as the no-flag default and existing multi-provider behavior; - owns the project-local
.pi/extensions/chainloop-trace.tslifecycle, including safe upgrades, collision and symlink checks, uninstall, rollback, and trace-run restoration; - bridges Pi session, prompt, tree,
write,edit, andbashevents into the existing Trace hook pipeline; - maps Pi
toolCallIdto the existingtool_use_idcorrelation key for concurrent file snapshots; - bounds direct child processes with per-stream output caps, timeout, SIGTERM grace, SIGKILL fallback, and failure absorption;
- completes the Pi E2E adapter, generated CLI reference, provider guide, compatibility matrix, and project-trust guidance; and
- supports the approved Pi 0.80.10 JSONL v3 baseline in both TUI and JSON-headless operation.
Together with merged provider/parser PR #3547, this covers R-001 through R-009. This PR directly implements R-001, R-002, R-003, R-004, R-008, and R-009, plus the extension-side transcript-path behavior in R-005.
Compatibility and safety
- Claude Code remains the default provider when no provider flag is selected.
- Existing Claude Code, Cursor, and OpenCode behavior is unchanged except for the approved shared file-snapshot correlation change when a provider supplies
ToolUseID; events without one retain the existing fallback key. - Pi project trust is not bypassed. Interactive Pi asks before loading project files, and non-interactive Pi needs saved trust or
--approve. - The extension executes
chainloopdirectly, never through a shell, and runs each child fromctx.cwd. - Spawn errors, malformed responses, output overflow, timeouts, and non-zero exits are absorbed without blocking Pi tools or corrupting stdout.
- No control-plane API, protobuf, evidence schema, or attestation schema changes are included.
- The merged behavior from #3547 keeps the last usable private Pi transcript when a refresh fails. That accepted behavior differs from the stale invalidation wording in R-005 and is preserved here.
Verification
go test -race ./cmd ./internal/trace/providers ./internal/trace/e2e ./internal/trace/pi ./pkg/actionwithCHAINLOOP_TOKENandCODEX_HOMEunset- full
make -C app/cli testpasses every package except the current-main Codex storage-root tests; the identicaltranscript outside Codex storagefailure was reproduced on untouched upstream72bc01d9in the same environment go build ./...andgo vet ./...fromapp/cligolangci-lint v2.14.0 run --new-from-rev upstream/main: 0 issuesgo generate ./documentation, with no stale generated CLI reference- LSP diagnostics: no errors in the changed command, provider, Pi, or E2E packages
- compiled CLI/manual QA: init/run help, default selection, multi-provider selection, install, repeat init, uninstall, and trust guidance
- Pi 1.3.0 live E2E matrix with
openrouter/anthropic/claude-haiku-5.5: 25 checks passed; unsupported and control-plane-only cells remainNoorUnknown - Pi 0.80.10 targeted TUI and JSON-headless smokes: session start,
write,edit,bash, commit attribution, and session shutdown all observed; TUI banner observed git merge-tree --write-tree HEAD upstream/main: clean- final immutable gate review: APPROVE
Pi 1.3.0 matrix result: /tmp/pr3704-postmerge-pi-e2e-results/runs/20261023T135451Z.json.
Provider checklist
Provider package (app/cli/internal/trace/pi/)
-
Nameconstant andvar _ trace.Provider = (*Provider)(nil). -
InstallHooks: a second call changes nothing and user files stay intact. -
InstallHooksForTraceRun: all hooks except session end. -
SettingsFile: returns the installed extension path. -
UninstallHooks: removes only the marked Chainloop extension. -
HooksInstalled: true only for the marked Chainloop extension. - Hook events: session start, user prompt, selected session shutdown reasons, and session-tree changes.
- Hook events: before and after Pi
write,edit, andbash; Pi skills tracking is intentionally unsupported and documented. -
ReadHookInput: typed, size-limited input with absolute paths, cwd, transcript path, tool-use ID, command, version, and model fields where available. -
IsFileWritingToolandIsCommandTool: Go slices generate the extension tool lists. - Snapshot attribution strategy implemented and cleaned up.
- Shell tool sends paired hooks with the same
ToolUseID. -
CopySessionData: repeatable, path-checked, atomic, and non-blocking for missing sessions. -
ParseSession: reads only the Trace-owned copy. - Copy and parse paths require no control plane or network.
- Trace state flows only through
*state.Store, includingtrace run --localoutside a repository. - Evidence includes agent identity, session timing, model/provider, and models used.
- Evidence includes input, output, total, cache-read, and cache-write tokens.
- Evidence uses Pi's persisted cost.
- Evidence includes tools, conversation counts, and documented root-session-only behavior.
-
RawSession["main"]is non-nil and contains JSON objects. - Invalid or missing optional data produces sanitized warnings.
- Session-start, prompt-submit, and post-tool channels emit one document or no output.
-
Supports*methods match Pi UI and headless behavior. -
AnnounceToUseruses Pi UI or stderr as appropriate. - Optional skill, spec-copy, and pasted-image interfaces were evaluated; unsupported features are documented as
No. - Unit coverage includes hooks, parsing, messages, copies, concurrency, failure bounds, and legacy recovery.
CLI wiring
- Registered in
providers/registry.go. -
traceProviderFlagsfield,any(), andnames(). -
--piintrace init, wizard/help, andtrace run. - Existing
chainloop trace hook pi ...subcommands retainskipActionOptsInit. - Pi pre-tool handlers always return
undefinedand never block tools. -
providers/capabilities_test.goupdated. - Init provider, default, multiple-provider, next-step, and local-mode tests updated.
- Generated CLI reference refreshed.
End-to-end tests and documentation
-
e2e/pi.goimplementse2e.Harness. - Pi is registered in the E2E harness map.
- Pi 1.3.0 and its OpenRouter model are pinned in
e2e/config.yaml. - The Pi column was run and its results reviewed.
-
README.mdhas a Pi cell in every feature table with measured values. - Every non-
YesPi cell has an explanation. - The hook table and provider list include Pi.
- The approved spec is present and requirement IDs are cited here.
- Changed source files retain the 2026 license header.
- Changed-code lint, affected race tests, build, vet, generated docs, manual QA, and live E2E pass; the full CLI suite's only failure is the identical pre-existing Codex storage-root failure reproduced on current main.
Refs #3520
AI assistance
Vibhav's Pi assisted with implementation, testing, and review. Every affected commit carries Assisted-by: Vibhav's Pi and a DCO sign-off, and is GPG-signed.