Skip to content

fix(harness): correct pi config paths, provider schema, and bridge layout#78

Merged
nhuelstng merged 1 commit into
support-pi-harnessfrom
fix/pi-harness-review-fixes
Jul 15, 2026
Merged

fix(harness): correct pi config paths, provider schema, and bridge layout#78
nhuelstng merged 1 commit into
support-pi-harnessfrom
fix/pi-harness-review-fixes

Conversation

@nhuelstng

Copy link
Copy Markdown
Contributor

Summary

Structural fixes on top of #73, found via review and verified live against a real pi 0.80.6 install and the real SKAINET gateway. Each item below was reproduced concretely, not just inferred from docs.

  • Bridge extension hang (severe). .pi/extensions/omac-bridge/index.ts (subdirectory + index.ts) reproducibly hung pi indefinitely 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 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.
  • UserConfigHome was .pi; pi's real config home is ~/.pi/agent. Confirmed from pi's own docs and a live install: models.json, sessions/, skills/, and extensions/ all live under ~/.pi/agent/, not directly under ~/.pi/. This silently broke GlobalSkillsDir() — omac's auto-provisioned built-in skill was landing at ~/.pi/skills, which pi's own loader never reads — and GlobalBridgeDir(). The existing piSessionsRoot() had already worked around this by manually appending "agent", which is the tell that this was an oversight, not a deliberate choice. Fixed UserConfigHome to .pi/agent and removed the now-redundant manual append in piSessionsRoot().
  • Missing PI_CODING_AGENT_DIR env override — pi documents this as its config-home override; added as HomeEnv.
  • e2e provider config didn't match pi's real schema, and was missing a required flag. ProviderSetup wrote ~/.pi/agent/auth.json + settings.json, a schema pi's provider loader doesn't recognize. RunArgs also omitted --provider (pi defaults to --provider google without it). Live-tested: this exact combination hangs indefinitely against the real gateway, while the same --model flag 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, a providers map) plus --provider model in RunArgs; verified live (real 200s, real completions) against SKAINET.
  • Fabricated e2e version pin. @earendil-works/pi-coding-agent@2026.7.7 doesn't exist on npm (checked via npm view ... versions — 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 never got pi added to matrix.harness. Added.
  • Also dropped the unconfirmed ~/.cache/pi SandboxDirs entry — 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.
  • Live, outside any test harness: omac start pi under 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/pi and TestE2ESecurityAudit/pi against the live SKAINET gateway: both pass, every sandbox-boundary assertion holds (secrets, fs read/write, network, sidecar, env passthrough).

Test plan

  • Unit tests pass (go test ./...)
  • TestE2EEchoRest/pi passes against live SKAINET
  • TestE2ESecurityAudit/pi passes against live SKAINET
  • Manual omac start pi verified end-to-end under the real sandbox

🤖 Generated with Claude Code

…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 nhuelstng requested a review from anotherthomas July 14, 2026 09:24
@nhuelstng nhuelstng merged commit 6ee264e into support-pi-harness Jul 15, 2026
10 checks passed
@nhuelstng nhuelstng deleted the fix/pi-harness-review-fixes branch July 15, 2026 07:04
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>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant