feat(hosts): add Pi coding agent host adapter - #25
Conversation
Add Pi (pi.dev / @earendil-works/pi-coding-agent) as an analysis-capable source-local host, following the Qwen Code host template: - Distribution shell: `pi` manifest in package.json plus a /better-harness prompt template, so `pi install <repo>` discovers the canonical skills/ root and registers the slash command; add the pi-package keyword and ship prompts/ in the npm package while keeping it out of the Qoder runtime bundle. - Configured assets: scripts/agent-customize/providers/pi.mjs inventories settings-declared pi packages (npm/git/local), extensions, skills (including shared .agents/skills), prompt templates, and AGENTS.md context rules for user and project scopes. - Session evidence: scripts/session-analysis/platforms/pi.mjs reads workspace-matching JSONL v3 transcripts under ~/.pi/agent/sessions/--<cwd-slug>--/, honors PI_CODING_AGENT_DIR and PI_CODING_AGENT_SESSION_DIR, verifies the session-header cwd, and normalizes user/assistant/toolResult messages, toolCall blocks, and usage into provider-labelled events. - Register the pi platform across session-analysis, evidence-bundle, asset-baseline/integrity, task-loop, report-run, and agent-lint surfaces with --pi-home threading. - Sync the host adapter matrix, site docs (en/zh), references (platforms/pi.md, routing, sessions diagnostics), and READMEs; add provider, inventory, baseline, and evidence-bundle tests with fixtures matching the real Pi v3 session format. Validated with npm run check (874 tests, pack verification) and against real local Pi data: session discovery, agent-customize inventory, and a complete pi evidence bundle; Pi's own package resolver discovers the skill and prompt template from this repo.
There was a problem hiding this comment.
Pull request overview
Adds first-class support for the Pi coding-agent host (pi.dev, @earendil-works/pi-coding-agent) by introducing a new Pi session-analysis adapter, a Pi agent-customize inventory provider, and the pi-package discovery surfaces (manifest + /better-harness prompt template). This aligns with the repo’s host-boundary approach where host differences live in the adapter matrix, configured-asset providers, session adapters, and output modes.
Changes:
- Add Pi session evidence adapter (
--platform pi) with JSONL v3 parsing and workspace scoping. - Add Pi configured-asset inventory provider and wire
piinto harness/evidence-bundle/task-loop/report CLI surfaces. - Ship a
pimanifest +prompts/template in the npm package; update docs/README/changelog and add tests.
Reviewed changes
Copilot reviewed 49 out of 49 changed files in this pull request and generated 2 comments.
Show a summary per file
| File | Description |
|---|---|
| test/session-analysis-providers.test.mjs | Adds Pi analyzer coverage and Pi transcript fixtures. |
| test/scripts-refactor-contract.test.mjs | Updates frozen CLI output hashes after new platform. |
| test/plugin-manifests.test.mjs | Verifies package.json.pi and prompts/ packaging rules. |
| test/fixtures/scripts-refactor-contract/session-help.txt | Updates help fixture to include pi. |
| test/fixtures/scripts-refactor-contract/root-help.txt | Updates root help fixture to mention Pi. |
| test/coding-agent-platform-notes.test.mjs | Ensures sessions diagnostics notes include Pi paths. |
| test/better-harness-evidence-bundle.test.mjs | Adds Pi agentCustomize lane routing test. |
| test/agent-customize.test.mjs | Adds Pi inventory/provider tests and fixtures. |
| test/agent-customize-architecture.test.mjs | Updates architecture doc expectations for “six metadata roots”. |
| test/agent-asset-baseline.test.mjs | Adds Pi asset baseline fixture test. |
| scripts/session-analysis/usage-summary.mjs | Extends --platform usage to include pi. |
| scripts/session-analysis/selection-profile.mjs | Extends --platform usage to include pi. |
| scripts/session-analysis/platforms/pi.mjs | Implements Pi session discovery + normalization (new). |
| scripts/session-analysis/lifecycle-demand-signals.mjs | Allows pi in host-safe normalization. |
| scripts/session-analysis/analyzer.mjs | Wires Pi platform loader + help strings. |
| scripts/session-analysis.mjs | Wires Pi platform loader + help strings (shim). |
| scripts/npm-package/verify-pack.mjs | Requires prompt template in package and forbids it in runtime bundle. |
| scripts/harness-analysis/task-loop-source.mjs | Accepts pi platform; threads pi-home through evidence collection. |
| scripts/harness-analysis/task-loop-report.mjs | Recognizes pi in platform selection. |
| scripts/harness-analysis/report-run.mjs | Accepts pi and --pi-home for report runs. |
| scripts/harness-analysis/report-quality.mjs | Adds Pi to session-scope detection patterns. |
| scripts/harness-analysis/evidence-bundle/contract.mjs | Adds pi to allowed providers. |
| scripts/harness-analysis/evidence-bundle/cli.mjs | Accepts --pi-home and pi platform. |
| scripts/harness-analysis/evidence-bundle/agent-customize.mjs | Enables Pi for agentCustomize lane. |
| scripts/coding-agent-practices/inventory.mjs | Accepts pi and includes piHome in scope. |
| scripts/coding-agent-practices/asset-integrity.mjs | Accepts pi provider. |
| scripts/coding-agent-practices/asset-baseline.mjs | Accepts pi provider. |
| scripts/better-harness-cli/registry.mjs | Updates session-analysis command summary to include Pi. |
| scripts/agent-lint/cli.mjs | Allows `--provider ... |
| scripts/agent-customize/providers/pi.mjs | Implements Pi configured-asset inventory (new). |
| scripts/agent-customize/providers/index.mjs | Registers Pi provider collector. |
| scripts/agent-customize/cli.mjs | Threads --pi-home through CLI. |
| references/session-evidence/sessions-diagnostics.md | Adds Pi platform notes for session evidence diagnostics. |
| references/agent-customize/routing.md | Adds Pi asset routing guidance. |
| references/agent-customize/README.md | Adds Pi platform notes link. |
| references/agent-customize/platforms/pi.md | Adds Pi operating-practice reference (new). |
| README.zh-CN.md | Documents Pi installation and report usage (zh-CN). |
| README.md | Documents Pi installation and report usage (en). |
| prompts/better-harness.md | Adds /better-harness prompt template (new). |
| package.json | Adds pi manifest + pi-package keyword + ships prompts/. |
| docs/i18n/zh-Hans/docusaurus-plugin-content-docs/current/hosts/adapter-matrix.md | Adds Pi to host adapter matrix (zh-Hans). |
| docs/glossary.md | Updates session-analysis + host shell glossary entries for Pi. |
| docs/docs/hosts/adapter-matrix.md | Adds Pi to host adapter matrix (en docs site). |
| docs/concepts.md | Updates session-evidence concept to include Pi. |
| docs/community.md | Updates “host shell and packaging” to include Pi manifest. |
| docs/ARCHITECTURE.md | Updates “five” → “six” plugin metadata roots wording. |
| docs/adrs/directory-structure.md | Updates platform adapter list and packaging roots count. |
| docs/adapters/README.md | Adds Pi row and discovery/evidence notes. |
| CHANGELOG.md | Records Pi host support under Unreleased. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| async discoverSourceRoots(scope) { | ||
| const roots = [ | ||
| { | ||
| id: "pi-sessions", | ||
| kind: "pi-session-jsonl", | ||
| role: "session-transcript", | ||
| path: path.join(scope.sessionsDir, scope._workspaceDirVariants.exact), | ||
| paths: [scope.sessionsDir], | ||
| optional: false, | ||
| enabled: true, | ||
| workspaceScoped: true, | ||
| coverage: "primary", | ||
| }, | ||
| ]; | ||
| return Promise.all(roots.map(async (root) => ({ | ||
| ...root, | ||
| exists: await pathExists(root.path) || await pathExists(root.paths[0]), | ||
| }))); | ||
| } |
|
|
||
| User request: | ||
|
|
||
| ${@:-review this project's AI coding workflow and generate a report} |
There was a problem hiding this comment.
Verified against an isolated install of @earendil-works/pi-coding-agent@0.83.0: Pi's prompt-templates API and runtime substituteArgs() explicitly support ${@:-default}. The no-argument case expanded to the fallback, and ["one", "two"] expanded to one two.
So line 19 is valid and should not be changed just for this concern. I suggest documenting the default-value form in the Pi platform notes and adding an expansion smoke test so the supported syntax is visible in-repo.
phodal
left a comment
There was a problem hiding this comment.
I ran an isolated native smoke with @earendil-works/pi-coding-agent@0.83.0 and compared Pi's own resolver/session behavior with this adapter.
What already works:
pi install/pi listaccepts this package.- Pi's
DefaultPackageManagerresolves exactly the canonicalbetter-harnessSkill and prompt from the package manifest. npm run checkpasses locally: 874/874 tests plus pack verification.
There are still native-contract blockers in the inline comments below. In addition, please update the branch before merge:
- Rebase onto current
main, which now includes PR #22 and PR #23. At this head,git merge-treereports 37 content conflicts. Resolve host registries as a union so Copilot support is retained while Pi is added. - Add a dated Pi host spec under
docs/specs/with stable acceptance IDs, and link the new Coding Agent contribution guide. The guide links PR #6 and PR #22 as reviewed examples. - Amend the commit with the required single
Co-authored-byline. - Re-run CI after updating the head. The current run is
action_requiredwith no jobs, so it is not green CI.
One environment note: the local suite ran under Node 26, outside the repository's declared Node range. The passing local suite is useful evidence but should not replace CI on a supported runtime.
| options.home ?? options.piHome ?? options["pi-home"] ?? process.env.PI_CODING_AGENT_DIR ?? "~/.pi/agent", | ||
| )); | ||
| const sessionsDir = path.resolve(expandHome( | ||
| options.sessionsDir ?? options["sessions-dir"] ?? process.env.PI_CODING_AGENT_SESSION_DIR ?? path.join(home, "sessions"), |
There was a problem hiding this comment.
Blocking native-contract mismatch: Pi 0.83 treats --session-dir, PI_CODING_AGENT_SESSION_DIR, and settings.json sessionDir as the exact directory containing JSONL files. It does not treat a custom directory as a root containing --<cwd-slug>-- children.
I reproduced this with Pi's SessionManager.create(workspace, customDir): native SessionManager.list(workspace, customDir) found 1 session, while this adapter found 0. SettingsManager.getSessionDir() also returned the configured directory, but resolveScope() fell back to <piHome>/sessions.
Please distinguish the default cwd-keyed tree from a custom flat session directory, honor CLI > env > settings > default, qualify custom-directory files by the session-header cwd, and add positive/foreign-workspace tests for env and settings overrides. This should also address the existing source-root warning thread, because a parent directory alone is not proof of a workspace evidence root.
| installSource: scope, | ||
| installMatch: `pi-settings-${record.sourceKind}`, | ||
| installType: record.sourceKind, | ||
| enabled: true, |
There was a problem hiding this comment.
Blocking effective-state issue: object-form package settings are reduced to source, then every installed package and its resources are reported as enabled: true.
With packages: [{ source, autoload: false, skills: [], prompts: [] }], Pi's native DefaultPackageManager resolves zero package Skills and prompts, while this provider still reports both better-harness resources as enabled. Declaring filters unsupported does not make it safe to publish disabled resources as effective configured assets.
Please apply Pi's manifest/settings filters and negative selectors, or fail closed without publishing those child resources as enabled. Add fixtures for autoload: false, explicit allowlists, and negative overrides.
| function piUserHomeBase(piHome) { | ||
| // The default agent dir is <home>/.pi/agent; derive the owning home so the | ||
| // shared ~/.agents/skills surface stays bound to the inspected pi home. | ||
| return path.dirname(path.dirname(piHome)); |
There was a problem hiding this comment.
PI_CODING_AGENT_DIR relocates Pi's agent/config directory, but native Pi still discovers the Agent Skills standard directory from the real user home at ~/.agents/skills. Deriving the user home by taking two parents of an arbitrary piHome changes that contract.
In an isolated PI_CODING_AGENT_DIR smoke, Pi's resolver still found the real ~/.agents/skills, while this provider missed them. Please model piHome and user home separately (or use os.homedir() for the native global surface), preserve the includeUserHome privacy boundary, and add a custom-agent-dir fixture.
| cacheCreationInputTokens: usage.cacheWrite ?? usage.cacheCreationInputTokens, | ||
| }; | ||
| return Object.values(fields).some((value) => value !== undefined) | ||
| ? Object.fromEntries(Object.entries(fields).map(([key, value]) => [key, Number.isFinite(Number(value)) ? Number(value) : 0])) |
There was a problem hiding this comment.
Missing usage fields should remain unobserved, not be converted to zero. Once any one usage field exists, this mapping turns every absent or malformed sibling field into 0.
Current main and the PR #22 evidence contract keep partial usage explicit. Please emit only finite fields actually observed, preserve missing input/cache fields as absent, and add partial plus malformed usage fixtures.
Summary
Pi (pi.dev,
@earendil-works/pi-coding-agent) can now run/better-harnessas a first-class host:pi install <repo>discovers the skill and a/better-harnessprompt template, and reviews on Pi gain real configured-asset and session evidence instead ofunobservedlanes.Why
Traceability and Scope
docs/adapters/README.mdhost-boundary contract (host differences enter only the matrix, configured-asset providers, session adapters, and output modes).--platform piaccepted across session-analysis, evidence-bundle, asset-baseline/integrity, task-loop, report-run, and agent-lint;pi install/pi -ediscovery works from the repository root.scripts/agent-customize/providers/pi.mjsandscripts/session-analysis/platforms/pi.mjs(new), platform registration lists acrossscripts/,package.json(pimanifest,prompts/packaging),prompts/better-harness.md,references/agent-customize/platforms/pi.md, adapter-matrix docs (en/zh), READMEs, CHANGELOG.docs/adapters/pi.mdsplit (no split trigger met), no change to the Qoder runtime bundle contents.Change Type
Test and Review Evidence
npm testnpm run pack:verifypackage/prompts/better-harness.md; runtime zip 338 entries withprompts/correctly excludednode scripts/session-analysis.mjs sources --platform pi --workspace /private/tmp(real local Pi data)node scripts/session-analysis.mjs facts --platform pi ...session-core-factswith 2 candidates; no session-id or home-path leakage in outputbetter-harness agent-customize inventory --provider pi(real~/.pi/agent)AGENTS.mdrulesbetter-harness harness evidence-bundle --platform pi --workspace <repo>status: complete; sessionEvidence/projectHarness/agentCustomize + lead all availableDefaultPackageManager.resolveExtensionSources(<repo>)in an isolated agent dirbetter-harness) and 1 prompt template (better-harness.md) from thepimanifestManual or visual evidence: session-format fixtures were derived from real Pi v3 JSONL transcripts and pi 0.83.0 source (
session-manager.jsslug rule,config.jsenv overrides), not from documentation alone.Risk and Recovery
\and:replacement) are covered by unit tests.pimanifest key,pi-packagekeyword, andprompts/;verify-packenforces the new required entry and forbidsprompts/from the Qoder runtime bundle. No schema changes./better-harnessreport run inside an interactive Pi session (model-driven) was not exercised; discovery, evidence collection, and bundle assembly were verified directly. Pi package manifest glob filters and per-resource enable state are declared unsupported rather than inventoried.AI Involvement
Checklist
AGENTS.md,CONTRIBUTING.md, and the relevant canonical-owner guidance.CHANGELOG.md.