Skip to content

Pi agent support β€” multi-harness framework with harness-agnostic .agents/ directory#66

Merged
striderZA merged 34 commits into
masterfrom
feat/pi-agent-support
Jun 21, 2026
Merged

Pi agent support β€” multi-harness framework with harness-agnostic .agents/ directory#66
striderZA merged 34 commits into
masterfrom
feat/pi-agent-support

Conversation

@striderZA

Copy link
Copy Markdown
Owner

Summary

Ports OpenCode Game Studios to the Pi coding agent harness alongside OpenCode, using a harness-agnostic canonical content directory (.agents/). All 51 agents, 77 skills, 54 commands, and 11 rules now live in .agents/ and are consumed natively by each harness.

Key Changes

Architecture

  • .agents/ β€” New canonical content directory (harness-agnostic). All agents, skills, commands, rules, and modules live here.
  • .opencode/ β€” Now only OpenCode-specific plugins, config, and symlinks to .agents/
  • .pi/ β€” Pi-specific extensions and settings
  • Agent frontmatter made harness-neutral (no model:, mode:, permission:)

Pi Extensions (7 extensions)

  • ocgs-core β€” Barrel extension for .agents/ content discovery
  • ocgs-delegation β€” Task tool (vertical delegation) + /consult (peer review)
  • ocgs-question β€” Structured decision capture with TUI picker
  • ocgs-path-guard β€” Dynamic path-scoped rule injection
  • ocgs-audit β€” Byte-identical audit logging
  • ocgs-drift-detector β€” Real-time structural drift detection
  • ocgs-changelog β€” Conventional-commit changelog generation with TUI modal
  • ocgs-validate β€” Content validation on startup and post-write

Docs

  • Added docs/pi-compatibility.md, docs/pi-extensions.md, docs/pi-workflow.md
  • Updated all docs to reference .agents/ paths
  • Fixed stale agent/command/skill counts across WORKFLOW-GUIDE, AGENTS.md, README.md

Testing

  • E2E parity tests for Pi extensions
  • Extension-specific unit tests

Migration

Existing users: run node tools/migrate-to-agents.mjs --dry-run to preview migration from .opencode/ to .agents/. Both harnesses work side by side β€” no breaking changes to OpenCode workflows.

striderZA added 30 commits June 21, 2026 17:00
… detailed report to production/session-logs/ocgs-validation-report.md
…ut in WORKFLOW-GUIDE

- 48→51 agents, 68→54 commands, 12 hooks→3 plugins
- Add Pi users info callout referencing pi-workflow.md and pi-compatibility.md
- Fix Appendix B header: 66β†’54 Commands by Category
…GENTS.md

- 49β†’51 coordinated OpenCode agents
- 50β†’54 commands in the available commands section
- Add pi-extensions.md and pi-workflow.md to directory tree
- 49β†’51 coordinated agents, 51β†’54 slash commands in Motivation
- 76β†’77 skills, 51β†’54 commands in Quick Start
- Redesign directory tree to show .agents/ as canonical source
  with .opencode/ symlinks to .agents/ counterparts
- 49-agent roster β†’ 51-agent roster
- 49-agent framework β†’ 51-agent framework
@github-actions

Copy link
Copy Markdown
Contributor

I have enough context now. Here is my full PR review.


PR Review: Pi Agent Support β€” Multi-Harness Framework

Overall Assessment

The architectural direction is sound β€” a harness-agnostic .agents/ directory is the right approach for supporting both OpenCode and Pi. The Pi extensions are well-structured with clear separation of concerns. However, there are several critical issues that must be resolved before merge.


Critical Issues

1. Missing symlinks break OpenCode entirely (BLOCKER)
AGENTS.md:31-34 and CHANGELOG.md:28 claim that .opencode/{agents,skills,commands,rules} are symlinks to .agents/, but these directories do not exist in the working tree. OpenCode will find zero agents, skills, commands, or rules.

Fix: Create the symlinks:

ln -s ../.agents/agents .opencode/agents
ln -s ../.agents/skills .opencode/skills
ln -s ../.agents/commands .opencode/commands
ln -s ../.agents/rules .opencode/rules

2. installed.json references stale .opencode/ paths (BLOCKER)
Both .agents/modules/installed.json and .opencode/modules/installed.json record file paths like .opencode/agents/art-director.md, .opencode/skills/art-bible/SKILL.md, etc. None of these paths resolve anymore. The module system (install.mjs) is completely broken.

Fix: Update all file references in both installed.json files from .opencode/ to .agents/.

3. drift-detector.ts hardcodes .opencode/ paths (BLOCKER)
All path-matching logic in .opencode/plugins/drift-detector.ts (lines 57, 142, 218, 296, 306, 317, 350, 352, 354) checks for .opencode/agents/, .opencode/skills/, etc. After the migration, writes go to .agents/, so the plugin silently stops working.

Fix: Update all path checks to .agents/.

4. opencode.json references stale path (BLOCKER)
Line 6: "template": "Run the hybrid-prototype skill: load .opencode/skills/hybrid-prototype/SKILL.md..." β€” this file is now at .agents/skills/hybrid-prototype/SKILL.md.

Fix: Update to .agents/skills/hybrid-prototype/SKILL.md.


Bugs

5. docs/pi-extensions.md changelog code example mismatch
Lines 207-208 show pi.registerCommand("changelog" but the actual implementation at .pi/extensions/ocgs-changelog/index.ts:83 registers "generate-changelog". The docs code is wrong.

6. .gitignore misconfigured
Lines 27-30 ignore .opencode/{agents,skills,commands,rules}/. These are now tracked symlinks (or should be), so they should not be in .gitignore.


Code Quality Issues

7. Duplicate installed.json with identical content
Both .agents/modules/installed.json and .opencode/modules/installed.json are byte-identical. This creates ambiguity β€” which is canonical? After migration, .agents/ should be canonical and .opencode/ should symlink or there should be one source of truth.

8. ocgs-path-guard: Mutating event parameter

return {
  systemPrompt: event.systemPrompt + "\n\n## Active OCGS Path-Scoped Rules\n\n" + augmentation,
};

This mutates the input event by relying on the return value being merged. If the event system clones the object, the augmentation never takes effect. Should return a new copy of event with the modified systemPrompt, or use a documented API contract.

9. ocgs-validate: No type guard on event.input.path
Line 132: event.input.path as string β€” no null check. If path is undefined, the cast silently passes "undefined" to validateFile.

10. ocgs-delegation: Loads all agent prompts eagerly at startup
loadAgentNames() and loadSystemPrompt() are called at import time, not lazily. For 51 agents each with large system prompts, this will slow startup with unnecessary I/O.


Suggestions

11. Missing .pi/extensions/ package.json files for type resolution
Only ocgs-validate has a package.json. The imports from @earendil-works/pi-coding-agent, @earendil-works/pi-ai, and typebox won't resolve for the other extensions without proper project setup. Each extension that imports from these packages needs either its own package.json or these should be hoisted.

12. Migration script improvement
tools/migrate-to-agents.mjs correctly strips harness-specific frontmatter but doesn't update internal .opencode/ references inside the content being migrated (e.g., skill files that reference .opencode/ paths in their instructions). Post-migration, skills/doc references need updating too.

13. No validation tests for .agents/ content
tests/extensions/ has only 3 test files covering audit format and path-guard. Missing tests for ocgs-core, ocgs-delegation, ocgs-question, ocgs-drift-detector, ocgs-changelog, and ocgs-validate. The test-parity.test.ts file is referenced in CHANGELOG.md:23 but doesn't exist on disk.


Summary

Severity Count
Blocker 4
Bug 2
Quality 4
Suggestion 3

Verdict: Needs significant revisions. The architectural direction is correct, but the missing symlinks and stale .opencode/ paths in installed.json, drift-detector.ts, and opencode.json mean that neither OpenCode nor the module system will work after this merge.

New%20session%20-%202026-06-21T17%3A55%3A30.811Z
opencode sessionΒ Β |Β Β github run

… extension bugs

Critical fixes for CI and module system:

- Remove .gitignore entries for .opencode/ symlinks (now tracked as git symlinks)
- Add relative symlinks .opencode/{agents,skills,commands,rules} -> ../.agents/*
- Update drift-detector.ts: replace 13 hardcoded .opencode/ checks with .agents/
- Fix opencode.json: update template path .opencode/skills/ -> .agents/skills/
- Update CHANGELOG.md and docs/pi-workflow.md for symlink tracking

Pi extension quality fixes:

- ocgs-delegation: lazy-load agent names; defer readdirSync to first use
- ocgs-path-guard: spread ...event before returning modified systemPrompt
- ocgs-validate: replace bare 'as string' cast with proper typeof guard

Review: #66
@github-actions

Copy link
Copy Markdown
Contributor

Here's my review of the current state of the PR (after commit b4597d2 which already resolved the original review's blocker issues):


PR Review: Pi Agent Support (Current State)

Most of the critical issues flagged earlier have been addressed β€” symlinks are tracked, drift-detector.ts, opencode.json, and ocgs-validate paths are corrected, and ocgs-delegation now uses lazy caching. What remains:

Bugs

1. docs/pi-extensions.md:208 β€” stale command name in code example
The docs show pi.registerCommand("changelog" but the actual implementation at .pi/extensions/ocgs-changelog/index.ts:83 registers "generate-changelog". The code example is wrong.

Code Quality

2. Duplicate installed.json β€” two sources of truth
.agents/modules/installed.json and .opencode/modules/installed.json are byte-identical (both still reference .opencode/ paths). Since .agents/ is now canonical, drop the .opencode/modules/ copy or make it a relative-symlink to .agents/modules/. Also, ~half the module entries still use .opencode/... paths instead of relative agents/... paths β€” these won't resolve from .agents/.

3. ocgs-path-guard β€” fragile path extraction from bash commands
Line 171: event.input.command.match(/(?:^|\s)([a-z_][\w\-./]+)/) β€” this extracts the first word-like token from a bash command as a "file path". This will produce false positives (e.g., git status β†’ matches git) and miss actual paths passed as arguments. Consider checking for common file/directory patterns instead.

Suggestions

4. Missing package.json for type resolution
Only ocgs-validate has a package.json. The other 7 extensions import from @earendil-works/pi-coding-agent, @earendil-works/pi-ai, and typebox without local resolution config. Either hoist deps or add per-extension package.json files.

5. Migration script doesn't update internal references
tools/migrate-to-agents.mjs strips frontmatter fields but doesn't update .opencode/ β†’ .agents/ references within migrated file bodies. Skill instructions, doc references, and command templates that reference .opencode/ paths will silently break post-migration.

6. test-parity.test.ts is a skeleton
tests/e2e/test-parity.test.ts exists (fixing the original issue) but runOpencodeScenario() and runPiScenario() are stubs that return hardcoded paths without actually spawning either harness. No tests exercise the Pi extensions themselves β€” only ocgs-audit and ocgs-path-guard have unit tests.

7. ocgs-core implicitly depends on extension load order
It dynamically imports all other extensions via import(), but there's no error handling if one extension fails to load. A single broken extension will prevent all subsequent ones from loading.


Verdict: The architecture is solid and the major blockers are fixed. The remaining issues are docs bugs (1), config cleanup (2), and test/error-handling polish (4-7). Recommend addressing items 1 and 2 before merge; items 3-7 can be follow-up issues.

New%20session%20-%202026-06-21T18%3A37%3A07.396Z
opencode sessionΒ Β |Β Β github run

- Fix R1: team-release skill no longer references /generate-changelog
  as a command (uses /changelog instead, Pi name in plain text)
- Fix I5: AGENTS.md non-agent names (ocgs-delegation, ocgs-question,
  question) no longer backtick-quoted to avoid false agent refs
@github-actions

Copy link
Copy Markdown
Contributor

Here is my review of the current PR state.


PR Review: Pi Agent Support (Current State)

Most critical issues from the original review have been resolved β€” symlinks are tracked, drift-detector.ts (active copy), opencode.json, ocgs-validate type guard, ocgs-path-guard event mutation, and ocgs-delegation lazy loading are all fixed.

Remaining Issues

1. docs/pi-extensions.md:208 β€” stale command name (Bug)
The code example shows pi.registerCommand("changelog", { but the actual implementation at .pi/extensions/ocgs-changelog/index.ts registers "generate-changelog". Fix the docs to match.

2. installed.json β€” stale .opencode/ paths (Bug)
Both .agents/modules/installed.json and .opencode/modules/installed.json contain ~155 paths prefixed with .opencode/ (e.g., ".opencode/agents/lead-programmer.md"). These won't resolve from .agents/ or without the symlink context. Newer modules use bare paths ("agents/..."). Need a consistent scheme β€” either all .agents/-prefixed or all bare relative paths.

3. Module template drift-detector.ts still has stale paths (Bug)
.opencode/modules/core/plugins/drift-detector.ts still hardcodes 13 .opencode/ references (lines 57, 142, 218, 251, 292+). The active copy at .opencode/plugins/drift-detector.ts was fixed, but the module template wasn't. Re-installing the core module would produce broken code.

4. Duplicate installed.json files (Quality)
.agents/modules/installed.json and .opencode/modules/installed.json are byte-identical. Since .agents/ is canonical, drop the .opencode/modules/ copy or replace it with a symlink.

5. Missing package.json for type resolution (Quality)
Only ocgs-validate has a package.json. The other 7 extensions import from @earendil-works/pi-coding-agent, @earendil-works/pi-ai, and typebox without local resolution config.

6. test-parity.test.ts is a skeleton (Quality)
tests/e2e/test-parity.test.ts has runOpencodeScenario() and runPiScenario() stubs returning hardcoded paths. No actual harness spawning.

7. ocgs-core imports extensions without error handling (Quality)
The barrel extension dynamically imports all others via import() but has no error handling β€” one broken extension silently blocks all subsequent ones.

Severity Count
Bug 3
Quality 4

Verdict: Address items 1-3 before merge (docs fix + installed.json normalization + module template fix). Items 4-7 can be follow-up issues.

New%20session%20-%202026-06-21T18%3A40%3A18.829Z
opencode sessionΒ Β |Β Β github run

- Fix docs/pi-extensions.md: registerCommand name changed from
  'changelog' to 'generate-changelog' to match implementation
- Fix installed.json: normalize 177 .opencode/ prefixed paths to
  bare relative paths (agents/foo.md) for module system compatibility
- Fix module template: update module copy of drift-detector.ts
  (13 .opencode -> .agents path references)
@striderZA striderZA merged commit c5a3e40 into master Jun 21, 2026
@github-actions

Copy link
Copy Markdown
Contributor

PR Review: Pi Agent Support (Final State @ b4597d2)

The previous blocker issues (missing symlinks, stale .opencode/ paths in drift-detector.ts, opencode.json, installed.json) have all been resolved. Here's what remains:

Bugs

1. ocgs-changelog widget references wrong command name β€” .pi/extensions/ocgs-changelog/index.ts:76

"Run /changelog to generate the full entry."

The command is registered as generate-changelog (line 83), not changelog. The widget text at line 76 gives users a non-existent command.

2. ocgs-path-guard regex over-matches bash commands β€” .pi/extensions/ocgs-path-guard/index.ts:171

const match = event.input.command.match(/(?:^|\s)([a-z_][\w\-./]+)/);

This treats any first word in a bash command as a potential file path (e.g., git, npm, npx, ls, cd, python, node). This will generate false positives on nearly every bash call, bloating the tracked paths list with irrelevant tokens. Consider filtering against known shell builtins/commands, or only capturing arguments that look like paths (containing . or /).

Code Quality

3. Duplicate installed.json β€” .agents/modules/installed.json and .opencode/modules/installed.json are byte-identical. Since .opencode/modules/ is a real directory (not a symlink to .agents/modules/), these will diverge over time. Recommend replacing .opencode/modules/installed.json with a symlink to ../.agents/modules/installed.json.

4. Drift-detector plugin duplicated across two trees β€” .opencode/plugins/drift-detector.ts and .opencode/modules/core/plugins/drift-detector.ts are byte-identical copies. The module template copy is dead code unless the module system explicitly copies it to the active plugins directory on install. One source of truth needed.

5. Unregistered plugins in opencode.json β€” .opencode/plugins/drift-detector.ts and .opencode/plugins/changelog-generator.ts exist on disk but are not listed in opencode.json's "plugin" array (only ccgs-hooks.ts is). These plugins are never loaded by OpenCode. Either register them or remove them.

6. ocgs-drift-detector docs don't match implementation β€” docs/pi-extensions.md:182 says the scan checks for description and maxTurns frontmatter fields, but the actual code at .pi/extensions/ocgs-drift-detector/index.ts:8-11 checks for markdown sections (**name**, **description**, ## name, etc.), not YAML frontmatter. The docs are misleading.

7. Missing package.json for type resolution β€” Only 1/8 Pi extensions (ocgs-validate) has a package.json. The other 7 import from @earendil-works/pi-coding-agent, @earendil-works/pi-ai, and typebox without local resolution config. If Pi doesn't provide ambient types, these break in strict TypeScript environments.

8. ocgs-core barrel docs vs code mismatch β€” docs/pi-extensions.md:21 says the barrel "Dynamically imports and registers" 7 child extensions, but the actual implementation at .pi/extensions/ocgs-core/index.ts is only a resources_discover handler β€” it doesn't import anything. Either the docs are wrong about dynamic importing, or the barrel is missing the import logic.

Suggestions

9. Migration script doesn't update internal references β€” tools/migrate-to-agents.mjs strips harness-specific frontmatter but doesn't rewrite .opencode/ β†’ .agents/ references within migrated file bodies. Post-migration, skill instructions and doc references to old paths will silently break.

10. Parity tests are stubs β€” tests/e2e/test-parity.test.ts has runOpencodeScenario() and runPiScenario() returning hardcoded paths without spawning either harness. The test infrastructure is placeholder-only.

Summary

Severity Count Key Items
Bug 2 Wrong command name in widget (#1), regex over-match (#2)
Quality 6 Duplicate installed.json (#3), duplicate drift-detector (#4), unregistered plugins (#5), stale docs (#6), missing package.json (#7), barrel docs mismatch (#8)
Suggestion 2 Migration script incompleteness (#9), stub parity tests (#10)

These are all non-blocking polish items. Recommend addressing #1 (wrong command name) and #3 (duplicate installed.json β†’ symlink) before closing.

New%20session%20-%202026-06-21T18%3A52%3A01.616Z
opencode sessionΒ Β |Β Β github run

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