fix(harness): correct pi config paths, provider schema, and bridge layout#78
Merged
Merged
Conversation
…yout Structural fixes to the pi harness registration in #73, found and verified live against the real SKAINET gateway and a real pi 0.80.6 install: - internal/config/harness.go: UserConfigHome was ".pi"; pi's actual config home is ~/.pi/agent (confirmed from pi's docs and a live install: models.json/sessions/skills/extensions all live there, not directly under ~/.pi). This silently broke GlobalSkillsDir() (built-in skills provisioned to ~/.pi/skills, which pi's own loader never reads) and GlobalBridgeDir(). Also add the documented PI_CODING_AGENT_DIR HomeEnv override, and drop the unconfirmed ~/.cache/pi SandboxDirs entry (not observed in a live install; pi's caches nest under ~/.pi/agent/{git,npm}). - internal/session/session.go: piSessionsRoot no longer appends "agent" manually now that ConfigHome() already includes it (was about to double up to ~/.pi/agent/agent/sessions once UserConfigHome was fixed). - .pi/extensions/omac-bridge/index.ts -> .pi/extensions/omac-bridge.ts: the subdirectory+index.ts layout reproducibly hung `pi` indefinitely on every launch (confirmed by loading the identical file content both ways against a real pi install — flat file loads instantly, the subdirectory form hangs with zero output). Pi's docs only document flat-file auto-discovery under .pi/extensions/*.ts. Also hardened before_agent_start to return {systemPrompt} per the documented hook contract, in addition to the existing messages.unshift, since it wasn't independently confirmed which application mechanism pi's runtime actually uses. - internal/e2e/harnesses.go: ProviderSetup wrote ~/.pi/agent/auth.json + settings.json, a schema pi's provider loader doesn't recognize; RunArgs omitted the required --provider flag (pi defaults to "google" without it). Together these caused every real pi e2e invocation to hang instead of failing fast. Replaced with the models.json custom-provider schema (verified live: real 200s and real completions against SKAINET) and RunArgs "--provider model --model <id>". - internal/e2e/versions.go: the pinned version "@earendil-works/pi-coding-agent@2026.7.7" does not exist on npm (only semver releases up to 0.80.6 are published) and would 404 in CI. Pinned to the real latest, 0.80.6. - .github/workflows/e2e.yml: pi was never added to matrix.harness. Verified live end-to-end after each fix: omac start pi under the real bwrap sandbox against SKAINET (built-in skill correctly provisioned to ~/.pi/agent/skills, real model response), and both TestE2EEchoRest/pi and TestE2ESecurityAudit/pi passing against the live gateway (every sandbox-boundary assertion: secrets, fs read/write, network, sidecar, env passthrough). Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com> Signed-off-by: Niclas Hülsmann <niclas.huelsmann@tngtech.com>
nhuelstng
added a commit
that referenced
this pull request
Jul 15, 2026
* feat: add pi (pi.dev) as supported harness Add Pi coding agent (pi.dev) as the fifth supported inner harness in omac, following the same declarative pattern as the codex-copilot change. - Register pi harness descriptor in harnessRegistry() (inner command pi, SkillsBase pi, TypeScript extension bridge, JSONL session listing) - Add SessionListPi enum value + listPi() function that walks JSONL files under ~/.pi/agent/sessions/ with filename-fallback ID extraction - Extend list() function signature with piRoot parameter, update all 8 existing test call sites - Ship TypeScript extension bridge at .pi/extensions/omac-bridge/index.ts (session_start/before_agent_start lifecycle events, reads OMAC_SANDBOX_BRIEFING, inert when OMAC_CONTROL_BASE unset) - Add piConfig() e2e test config + pinned version in versions.go - Add unit tests for harness lookup, session listing, and bridge files - Update README, CREATING_A_SKILL, MULTI_DIR_DESKTOP documentation - Create openspec change proposal (proposal.md + tasks.md) Signed-off-by: Thomas Fenzl <thomas.fenzl@tngtech.com> * fix(harness): correct pi config paths, provider schema, and bridge layout (#78) Structural fixes to the pi harness registration in #73, found and verified live against the real SKAINET gateway and a real pi 0.80.6 install: - internal/config/harness.go: UserConfigHome was ".pi"; pi's actual config home is ~/.pi/agent (confirmed from pi's docs and a live install: models.json/sessions/skills/extensions all live there, not directly under ~/.pi). This silently broke GlobalSkillsDir() (built-in skills provisioned to ~/.pi/skills, which pi's own loader never reads) and GlobalBridgeDir(). Also add the documented PI_CODING_AGENT_DIR HomeEnv override, and drop the unconfirmed ~/.cache/pi SandboxDirs entry (not observed in a live install; pi's caches nest under ~/.pi/agent/{git,npm}). - internal/session/session.go: piSessionsRoot no longer appends "agent" manually now that ConfigHome() already includes it (was about to double up to ~/.pi/agent/agent/sessions once UserConfigHome was fixed). - .pi/extensions/omac-bridge/index.ts -> .pi/extensions/omac-bridge.ts: the subdirectory+index.ts layout reproducibly hung `pi` indefinitely on every launch (confirmed by loading the identical file content both ways against a real pi install — flat file loads instantly, the subdirectory form hangs with zero output). Pi's docs only document flat-file auto-discovery under .pi/extensions/*.ts. Also hardened before_agent_start to return {systemPrompt} per the documented hook contract, in addition to the existing messages.unshift, since it wasn't independently confirmed which application mechanism pi's runtime actually uses. - internal/e2e/harnesses.go: ProviderSetup wrote ~/.pi/agent/auth.json + settings.json, a schema pi's provider loader doesn't recognize; RunArgs omitted the required --provider flag (pi defaults to "google" without it). Together these caused every real pi e2e invocation to hang instead of failing fast. Replaced with the models.json custom-provider schema (verified live: real 200s and real completions against SKAINET) and RunArgs "--provider model --model <id>". - internal/e2e/versions.go: the pinned version "@earendil-works/pi-coding-agent@2026.7.7" does not exist on npm (only semver releases up to 0.80.6 are published) and would 404 in CI. Pinned to the real latest, 0.80.6. - .github/workflows/e2e.yml: pi was never added to matrix.harness. Verified live end-to-end after each fix: omac start pi under the real bwrap sandbox against SKAINET (built-in skill correctly provisioned to ~/.pi/agent/skills, real model response), and both TestE2EEchoRest/pi and TestE2ESecurityAudit/pi passing against the live gateway (every sandbox-boundary assertion: secrets, fs read/write, network, sidecar, env passthrough). Signed-off-by: Niclas Hülsmann <niclas.huelsmann@tngtech.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com> --------- Signed-off-by: Thomas Fenzl <thomas.fenzl@tngtech.com> Signed-off-by: Niclas Hülsmann <niclas.huelsmann@tngtech.com> Co-authored-by: Niclas Hülsmann <niclas.huelsmann@tngtech.com> Co-authored-by: Claude Sonnet 5 <noreply@anthropic.com>
nhuelstng
added a commit
that referenced
this pull request
Jul 15, 2026
pi was added to matrix.harness and harnessVersions (#73/#78), but the workflow_dispatch pi_version input, its E2E_VERSION_PI env var, the cache key, and the versionEnvVar map entry were never added — so pi's version, unlike every other harness, couldn't be overridden for a single manual run without editing internal/e2e/versions.go. Add pi_version input (default matching versions.go's current pin), E2E_VERSION_PI env var, fold it into the install-cache key, and add the versionEnvVar["pi"] mapping so pinnedPackage() picks it up. Also add TestVersionEnvVarCompleteness, asserting every harness in allHarnesses() has both a harnessVersions and versionEnvVar entry, so a future harness addition can't silently ship without a working version override the way pi did. Signed-off-by: Niclas Hülsmann <niclas.huelsmann@tngtech.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Structural fixes on top of #73, found via review and verified live against a real
pi0.80.6 install and the real SKAINET gateway. Each item below was reproduced concretely, not just inferred from docs..pi/extensions/omac-bridge/index.ts(subdirectory +index.ts) reproducibly hungpiindefinitely on every launch. Confirmed by loading the identical file content both ways: flat file loads instantly, subdirectory form hangs with zero output even with--verbose. Pi's docs only document flat-file auto-discovery under.pi/extensions/*.ts. Fixed by flattening to.pi/extensions/omac-bridge.ts. Also hardenedbefore_agent_startto return{systemPrompt}per the documented hook contract, in addition to the existingmessages.unshift, since it wasn't independently confirmed which application mechanism pi's runtime actually uses.UserConfigHomewas.pi; pi's real config home is~/.pi/agent. Confirmed from pi's own docs and a live install:models.json,sessions/,skills/, andextensions/all live under~/.pi/agent/, not directly under~/.pi/. This silently brokeGlobalSkillsDir()— omac's auto-provisioned built-in skill was landing at~/.pi/skills, which pi's own loader never reads — andGlobalBridgeDir(). The existingpiSessionsRoot()had already worked around this by manually appending"agent", which is the tell that this was an oversight, not a deliberate choice. FixedUserConfigHometo.pi/agentand removed the now-redundant manual append inpiSessionsRoot().PI_CODING_AGENT_DIRenv override — pi documents this as its config-home override; added asHomeEnv.ProviderSetupwrote~/.pi/agent/auth.json+settings.json, a schema pi's provider loader doesn't recognize.RunArgsalso omitted--provider(pi defaults to--provider googlewithout it). Live-tested: this exact combination hangs indefinitely against the real gateway, while the same--modelflag with zero provider config fails fast and cleanly instead — confirming the hang is tied to the unrecognized config being present. Replaced with pi's actual documented custom-provider schema (~/.pi/agent/models.json, aprovidersmap) plus--provider modelinRunArgs; verified live (real 200s, real completions) against SKAINET.@earendil-works/pi-coding-agent@2026.7.7doesn't exist on npm (checked vianpm view ... versions— only semver releases up to0.80.6are published) and would 404 in CI. Pinned to the real latest,0.80.6..github/workflows/e2e.ymlnever gotpiadded tomatrix.harness. Added.~/.cache/piSandboxDirsentry — not observed in a live install (pi's caches nest under~/.pi/agent/{git,npm}).Verification
go build,go vet,staticcheck,go test ./...(incl.-race) all clean.omac start piunder the real bwrap sandbox against SKAINET — built-in skill correctly provisioned to~/.pi/agent/skills, real model response received.go test -tags=e2e -run TestE2EEchoRest/piandTestE2ESecurityAudit/piagainst the live SKAINET gateway: both pass, every sandbox-boundary assertion holds (secrets, fs read/write, network, sidecar, env passthrough).Test plan
go test ./...)TestE2EEchoRest/pipasses against live SKAINETTestE2ESecurityAudit/pipasses against live SKAINETomac start piverified end-to-end under the real sandbox🤖 Generated with Claude Code