pantheon-opencode 1.0.0 → 1.0.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -109
- package/bin/pantheon-init.mjs +57 -136
- package/commands/pantheon-audit.md +1 -1
- package/commands/pantheon-deepwork.md +32 -81
- package/commands/pantheon-reflect.md +16 -0
- package/commands/pantheon-status.md +1 -1
- package/commands/pantheon-verify.md +17 -0
- package/opencode.json +25 -0
- package/package.json +24 -13
- package/scripts/ci-validate-yaml.py +19 -0
- package/scripts/doctor.mjs +10 -65
- package/scripts/install/opencode.mjs +69 -6
- package/scripts/install/shared.mjs +39 -13
- package/scripts/manifest.mjs +5 -30
- package/scripts/postinstall.mjs +47 -0
- package/scripts/release-bundle.mjs +2 -2
- package/scripts/uninstall.mjs +5 -5
- package/scripts/validate-routing.mjs +19 -16
- package/scripts/versioning.mjs +12 -1
- package/skills-lock.json +9 -2
- package/src/agents/aphrodite.md +15 -57
- package/src/agents/apollo.md +9 -48
- package/src/agents/athena.md +17 -54
- package/src/agents/demeter.md +10 -47
- package/src/agents/gaia.md +7 -40
- package/src/agents/hephaestus.md +9 -52
- package/src/agents/hermes.md +17 -52
- package/src/agents/iris.md +8 -45
- package/src/agents/mnemosyne.md +12 -47
- package/src/agents/nyx.md +8 -45
- package/src/agents/prometheus.md +11 -49
- package/src/agents/talos.md +6 -45
- package/src/agents/themis.md +10 -35
- package/src/agents/zeus.md +5 -7
- package/src/mcp/mcp_resources_server.py +2 -0
- package/src/plugins/tui/dist/tui.tsx +203 -93
- package/src/plugins/tui/src/index.tsx +203 -93
- package/src/routing.yml +33 -93
- package/src/skills/clonedeps/SKILL.md +45 -0
- package/src/skills/codemap/SKILL.md +47 -0
- package/src/skills/loop-engineering/SKILL.md +51 -0
- package/src/skills/reflect/SKILL.md +49 -0
- package/src/skills/simplify/SKILL.md +39 -0
- package/src/skills/verification-planning/SKILL.md +52 -0
- package/src/skills/worktrees/SKILL.md +43 -0
- package/commands/pantheon-bg.md +0 -10
- package/commands/pantheon-consolidate.md +0 -11
- package/commands/pantheon-doc.md +0 -10
- package/commands/pantheon-hash.md +0 -11
- package/commands/pantheon-todo.md +0 -11
- package/docs/AGENT-MCP.md +0 -194
- package/docs/ARCHITECTURE.md +0 -384
- package/docs/BRANCH-PROTECTION.md +0 -142
- package/docs/INDEX.md +0 -81
- package/docs/INSTALLATION.md +0 -217
- package/docs/MCP.md +0 -238
- package/docs/MEMORY.md +0 -471
- package/docs/MIGRATION-MEMORY-BANK.md +0 -139
- package/docs/PLATFORMS.md +0 -5
- package/docs/QUICKSTART.md +0 -49
- package/docs/README.md +0 -18
- package/docs/RELEASING.md +0 -256
- package/docs/SETUP.md +0 -5
- package/docs/UPGRADING.md +0 -41
- package/docs/mcp-recommendations.md +0 -439
- package/docs/mcp-tools.md +0 -156
- package/docs/mcp-user-guide.md +0 -204
- package/docs/persistence-mcp.md +0 -111
- package/scripts/init-pantheon-mcp.sh +0 -118
- package/scripts/install.mjs +0 -26
- package/src/instructions/documentation-standards.instructions.md +0 -53
- package/src/mcp/init-pantheon-mcp.sh +0 -118
|
@@ -1,128 +1,79 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Start a heavy multi-phase task with persisted checkpoints, phased specialist dispatch, and Themis review gates. Progress saved to .pantheon/deepwork/ for resumability.
|
|
2
|
+
description: "Start a heavy multi-phase task with persisted checkpoints, phased specialist dispatch, and Themis review gates. Progress saved to .pantheon/deepwork/ for resumability."
|
|
3
3
|
agent: "zeus"
|
|
4
4
|
---
|
|
5
5
|
# /pantheon-deepwork — Heavy Task Workflow
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
Structured, checkpointed workflow for complex multi-step tasks spanning multiple agents and sessions. Progress persisted to `.pantheon/deepwork/<task-slug>/`. Each phase gated by Themis.
|
|
8
8
|
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
- Anything where losing context mid-way would be costly
|
|
15
|
-
|
|
16
|
-
## When NOT to Use
|
|
17
|
-
|
|
18
|
-
- Simple fixes (use @talos)
|
|
19
|
-
- Single-file changes (use /subtask)
|
|
20
|
-
- Tasks completable in < 5 turns (use normal delegation)
|
|
9
|
+
| Use When | Don't Use When |
|
|
10
|
+
|---|---|
|
|
11
|
+
| 10+ turns or multi-session | Simple fixes (→ @talos) |
|
|
12
|
+
| Multi-agent dependencies | Single-file changes (→ /subtask) |
|
|
13
|
+
| Costly context loss | < 5 turns (→ normal delegation) |
|
|
21
14
|
|
|
22
15
|
## Workflow
|
|
23
16
|
|
|
24
17
|
```
|
|
25
18
|
Phase 0: SCOPING
|
|
26
|
-
└─ Zeus + Athena define
|
|
27
|
-
└─ Output: .pantheon/deepwork/<slug>/PLAN.md
|
|
19
|
+
└─ Zeus + Athena define scope, phases, acceptance criteria → PLAN.md
|
|
28
20
|
|
|
29
21
|
Phase 1: DISCOVERY
|
|
30
|
-
└─ @apollo maps relevant codebase areas
|
|
31
|
-
└─ Output: .pantheon/deepwork/<slug>/DISCOVERY.md
|
|
22
|
+
└─ @apollo maps relevant codebase areas → DISCOVERY.md
|
|
32
23
|
|
|
33
24
|
Phase 2-N: IMPLEMENTATION (parallel per phase)
|
|
34
|
-
└─ @hermes
|
|
35
|
-
└─ Output:
|
|
25
|
+
└─ @hermes, @aphrodite, @demeter, @hephaestus, @prometheus
|
|
26
|
+
└─ Output: IMPL-phase-<N>-<agent>.md
|
|
36
27
|
|
|
37
28
|
GATE after each phase:
|
|
38
|
-
└─ @themis reviews
|
|
39
|
-
└─ FAIL → fix and re-submit
|
|
40
|
-
└─ PASS → continue to next phase
|
|
29
|
+
└─ @themis reviews output → FAIL (fix + resubmit) or PASS (continue)
|
|
41
30
|
|
|
42
31
|
Phase FINAL: VERIFICATION
|
|
43
|
-
└─ @themis full integration review
|
|
32
|
+
└─ @themis full integration review → REVIEW.md
|
|
44
33
|
└─ All tests pass, coverage >80%
|
|
45
|
-
└─ Output: .pantheon/deepwork/<slug>/REVIEW.md
|
|
46
34
|
```
|
|
47
35
|
|
|
48
|
-
##
|
|
49
|
-
|
|
50
|
-
Each phase writes a checkpoint file. If work is interrupted:
|
|
36
|
+
## Checkpoints
|
|
51
37
|
|
|
52
38
|
```
|
|
53
|
-
|
|
54
|
-
/pantheon-deepwork --status <slug> # Show current progress
|
|
55
|
-
/pantheon-deepwork --list # List all deepwork tasks
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
Checkpoint files:
|
|
39
|
+
Usage: --resume <slug> | --status <slug> | --list
|
|
59
40
|
|
|
60
|
-
```
|
|
61
41
|
.pantheon/deepwork/<slug>/
|
|
62
|
-
├── PLAN.md
|
|
63
|
-
├── DISCOVERY.md # Codebase map
|
|
64
|
-
├── phase-1-hermes.md # Phase 1 backend work
|
|
65
|
-
├── phase-1-aphrodite.md # Phase 1 frontend work
|
|
66
|
-
├── phase-1-review.md # Phase 1 Themis review
|
|
67
|
-
├── phase-2-*.md # Subsequent phases
|
|
68
|
-
├── REVIEW.md # Final Themis review
|
|
69
|
-
└── STATUS.md # Current state (phase, progress, blockers)
|
|
42
|
+
├── PLAN.md DISCOVERY.md IMPL-phase-*-*.md phase-*-review.md REVIEW.md STATUS.md
|
|
70
43
|
```
|
|
71
44
|
|
|
72
|
-
##
|
|
73
|
-
|
|
74
|
-
> ⚠️ **WARNING:** This bypasses human review gates. Only for experienced operators. Tier 1 gates (plan, commit, deploy) still require human approval.
|
|
45
|
+
## Full-Auto Mode (`--full-auto`)
|
|
75
46
|
|
|
76
|
-
|
|
47
|
+
> ⚠️ Bypasses human review gates. Tier 1 gates (plan, commit, deploy) still require approval.
|
|
77
48
|
|
|
78
|
-
|
|
79
|
-
- Only stops if Themis returns a **BLOCKING** verdict
|
|
80
|
-
- Equivalent to the "ultrawork" paradigm from OMO (one-minute-optimization)
|
|
81
|
-
- Checkpoints still saved at every phase boundary
|
|
82
|
-
- Use for: high-confidence tasks, batch processing, experienced operators
|
|
49
|
+
**Themis auto-approves non-blocking reviews** — only stops on **BLOCKING** verdict. No waiting between phases. Checkpoints saved at every boundary.
|
|
83
50
|
|
|
84
51
|
```
|
|
85
|
-
/pantheon-deepwork --full-auto "Refactor auth service to use JWT"
|
|
86
|
-
/pantheon-deepwork --full-auto --resume auth-jwt
|
|
52
|
+
/pantheon-deepwork --full-auto "Refactor auth service to use JWT"
|
|
53
|
+
/pantheon-deepwork --full-auto --resume auth-jwt
|
|
87
54
|
```
|
|
88
55
|
|
|
89
|
-
## Anti-Stall
|
|
56
|
+
## Anti-Stall
|
|
90
57
|
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
- **Stall Detection Protocol** — 3 turns no progress → escalate
|
|
94
|
-
- **Phase Reminder** — after each dispatch, continue only independent work
|
|
58
|
+
- **Stall Detection** — 3 turns no progress → escalate
|
|
59
|
+
- **Phase Reminder** — continue only independent work after dispatch
|
|
95
60
|
- **Progress Checkpoint** — every 5 turns, summarize completed vs remaining
|
|
96
|
-
- **Delegate Retry** —
|
|
97
|
-
|
|
98
|
-
If a phase stalls:
|
|
99
|
-
|
|
100
|
-
1. Checkpoint current progress
|
|
101
|
-
2. Report to user: "Phase [N] stalled. Progress saved. Options: (a) retry with different approach, (b) simplify scope, (c) skip phase and revisit."
|
|
61
|
+
- **Delegate Retry** — failures retried once with rephrased prompt
|
|
102
62
|
|
|
103
63
|
## Usage
|
|
104
64
|
|
|
105
65
|
```
|
|
106
|
-
/pantheon-deepwork "Add user authentication with OAuth2"
|
|
107
|
-
/pantheon-deepwork --resume auth-oauth2
|
|
108
|
-
/pantheon-deepwork --status auth-oauth2
|
|
109
|
-
/pantheon-deepwork --list
|
|
110
|
-
/pantheon-deepwork --
|
|
111
|
-
/pantheon-deepwork --full-auto
|
|
112
|
-
/pantheon-deepwork --full-auto --resume auth-refactor # Resume full-auto session
|
|
66
|
+
/pantheon-deepwork "Add user authentication with OAuth2" # Start new session
|
|
67
|
+
/pantheon-deepwork --resume auth-oauth2 # Resume interrupted
|
|
68
|
+
/pantheon-deepwork --status auth-oauth2 # Show progress
|
|
69
|
+
/pantheon-deepwork --list /pantheon-deepwork --archive <slug> # List / archive
|
|
70
|
+
/pantheon-deepwork --full-auto "Refactor auth" # Themis auto-approve
|
|
71
|
+
/pantheon-deepwork --full-auto --resume auth-refactor # Resume full-auto
|
|
113
72
|
```
|
|
114
73
|
|
|
115
74
|
## Safety
|
|
116
75
|
|
|
117
76
|
- All progress persisted — work is never lost
|
|
118
77
|
- Each phase gated by Themis — quality enforced at every step
|
|
119
|
-
- Explicit resume required —
|
|
78
|
+
- Explicit resume required — no auto-continue without intent (unless `--full-auto`)
|
|
120
79
|
- `.pantheon/deepwork/` is gitignored — no accidental commits
|
|
121
|
-
|
|
122
|
-
---
|
|
123
|
-
|
|
124
|
-
## Related: `/pantheon-praxis` (merged)
|
|
125
|
-
|
|
126
|
-
`/pantheon-praxis` was merged into `/pantheon-deepwork` in v4.0. Use `/pantheon-deepwork` for all multi-phase execution.
|
|
127
|
-
|
|
128
|
-
For ad-hoc single-phase execution, use normal agent delegation (`@hermes`, `@aphrodite`, etc.) directly.
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Reflect on workflow friction and create improvement action items"
|
|
3
|
+
agent: zeus
|
|
4
|
+
---
|
|
5
|
+
# /pantheon-reflect — Workflow Reflection
|
|
6
|
+
|
|
7
|
+
**What:** After completing a task, reflect on what could be improved. Turns repeated friction into reusable skills, agents, or config improvements.
|
|
8
|
+
**Usage:** `/pantheon-reflect [session-or-task]`
|
|
9
|
+
**Returns:** Structured reflection with action items
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
- After completing a complex feature
|
|
13
|
+
- When you notice the same manual steps repeating
|
|
14
|
+
- At end of work session
|
|
15
|
+
|
|
16
|
+
Delegates to @mnemosyne with `skill: reflect`.
|
|
@@ -42,7 +42,7 @@ Produce EXACTLY this structure:
|
|
|
42
42
|
|
|
43
43
|
### Commands Available
|
|
44
44
|
|
|
45
|
-
`/pantheon` `/pantheon-status` `/audit` `/focus` `/deepwork` `/optimize` `/sketch`
|
|
45
|
+
`/pantheon` `/pantheon-status` `/audit` `/focus` `/deepwork` `/optimize` `/sketch` `/` `/` `/` `/pantheon-remember` `/pantheon-search` `/` `/pantheon-forget`
|
|
46
46
|
|
|
47
47
|
### Health
|
|
48
48
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
---
|
|
2
|
+
description: "Create verification plan before non-trivial changes"
|
|
3
|
+
agent: zeus
|
|
4
|
+
---
|
|
5
|
+
# /pantheon-verify — Verification Planning
|
|
6
|
+
|
|
7
|
+
**What:** Plans an evidence path before non-trivial changes, defining how to verify correctness.
|
|
8
|
+
**Usage:** `/pantheon-verify <change-description>`
|
|
9
|
+
**Returns:** Verification plan with strategy, rollback, and acceptance criteria
|
|
10
|
+
|
|
11
|
+
## When to Use
|
|
12
|
+
- Before changes touching 3+ files
|
|
13
|
+
- Before DB migrations or schema changes
|
|
14
|
+
- Before API contract changes
|
|
15
|
+
- Before dependency upgrades
|
|
16
|
+
|
|
17
|
+
Delegates to @themis + @athena with `skill: verification-planning`.
|
package/opencode.json
ADDED
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
{
|
|
2
|
+
"$schema": "https://opencode.ai/config.json",
|
|
3
|
+
"default_agent": "zeus",
|
|
4
|
+
"subagent_depth": 2,
|
|
5
|
+
"agent": {},
|
|
6
|
+
"permission": {
|
|
7
|
+
"skill": {
|
|
8
|
+
"*": "allow"
|
|
9
|
+
},
|
|
10
|
+
"bash": {
|
|
11
|
+
"git *": "allow",
|
|
12
|
+
"npm *": "allow",
|
|
13
|
+
"npx *": "allow",
|
|
14
|
+
"pytest *": "allow",
|
|
15
|
+
"ruff *": "allow",
|
|
16
|
+
"pip *": "allow"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"instructions": [
|
|
20
|
+
"AGENTS.md",
|
|
21
|
+
"src/instructions/*.instructions.md"
|
|
22
|
+
],
|
|
23
|
+
"plugin": [],
|
|
24
|
+
"mcp": {}
|
|
25
|
+
}
|
package/package.json
CHANGED
|
@@ -1,21 +1,33 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pantheon-opencode",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "Multi-agent orchestration for OpenCode
|
|
3
|
+
"version": "1.0.6",
|
|
4
|
+
"description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public",
|
|
7
7
|
"registry": "https://registry.npmjs.org/"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
|
-
"
|
|
11
|
-
"
|
|
10
|
+
"postinstall": "node scripts/postinstall.mjs",
|
|
11
|
+
"setup": "node bin/pantheon-init.mjs init",
|
|
12
|
+
"setup:lite": "node bin/pantheon-init.mjs init --clean --components agents,skills,instructions",
|
|
12
13
|
"doctor": "node scripts/doctor.mjs",
|
|
13
|
-
"init": "
|
|
14
|
+
"init": "node bin/pantheon-init.mjs init",
|
|
14
15
|
"opencode": "OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode",
|
|
15
|
-
"start": "OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode"
|
|
16
|
+
"start": "OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true opencode",
|
|
17
|
+
"prepublishOnly": "node scripts/validate-routing.mjs",
|
|
18
|
+
"postpublish": "node -e \"console.log('✅ Published pantheon-opencode v' + require('./package.json').version + ' to npm')\"",
|
|
19
|
+
"version:status": "node scripts/versioning.mjs status",
|
|
20
|
+
"version:apply": "node scripts/versioning.mjs apply",
|
|
21
|
+
"release:dry-run": "node scripts/versioning.mjs status && npm pack --dry-run",
|
|
22
|
+
"publish:next": "npm publish --tag next --access public",
|
|
23
|
+
"lint": "npx biome ci .",
|
|
24
|
+
"typecheck": "npx tsc --noEmit",
|
|
25
|
+
"audit": "npm audit --audit-level=high",
|
|
26
|
+
"test": "python3 -m pytest tests/ -q 2>&1 || echo \"No tests found\"",
|
|
27
|
+
"test:ci": "python3 -m pytest tests/ -q --tb=short 2>&1 || true"
|
|
16
28
|
},
|
|
17
29
|
"bin": {
|
|
18
|
-
"pantheon-
|
|
30
|
+
"pantheon-opencode": "bin/pantheon-init.mjs"
|
|
19
31
|
},
|
|
20
32
|
"files": [
|
|
21
33
|
"LICENSE",
|
|
@@ -25,23 +37,22 @@
|
|
|
25
37
|
"README.md",
|
|
26
38
|
"src/mcp/*.txt",
|
|
27
39
|
"commands/*.md",
|
|
28
|
-
"src/skills/**/*.txt",
|
|
29
|
-
"src/skills/**/*.md",
|
|
30
40
|
"pantheon.schema.json",
|
|
31
41
|
"skills-lock.json",
|
|
32
42
|
"scripts/*.sh",
|
|
33
43
|
"src/agents/*.md",
|
|
34
44
|
"bin/*.mjs",
|
|
35
45
|
"AGENTS.md",
|
|
46
|
+
"opencode.json",
|
|
36
47
|
"src/mcp/*.py",
|
|
37
48
|
"src/instructions/*.instructions.md",
|
|
38
49
|
"src/mcp/*.mjs",
|
|
39
50
|
"scripts/*.mjs",
|
|
40
51
|
"src/plugins/tui/**",
|
|
41
|
-
"docs/*.md",
|
|
42
52
|
"src/mcp/*.sh",
|
|
43
53
|
"src/routing.yml",
|
|
44
|
-
"src/mcp/requirements*"
|
|
54
|
+
"src/mcp/requirements*",
|
|
55
|
+
"src/skills/**"
|
|
45
56
|
],
|
|
46
57
|
"dependencies": {
|
|
47
58
|
"js-yaml": "^4.3.0"
|
|
@@ -53,7 +64,7 @@
|
|
|
53
64
|
},
|
|
54
65
|
"repository": {
|
|
55
66
|
"type": "git",
|
|
56
|
-
"url": "https://github.com/ils15/pantheon.git"
|
|
67
|
+
"url": "https://github.com/ils15/pantheon-opencode.git"
|
|
57
68
|
},
|
|
58
69
|
"keywords": [
|
|
59
70
|
"github",
|
|
@@ -69,4 +80,4 @@
|
|
|
69
80
|
"node": ">=18"
|
|
70
81
|
},
|
|
71
82
|
"preferGlobal": true
|
|
72
|
-
}
|
|
83
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""Validate agent YAML frontmatter in CI."""
|
|
3
|
+
import os, re, yaml, sys
|
|
4
|
+
|
|
5
|
+
errors = 0
|
|
6
|
+
for f in sorted(os.listdir('src/agents')):
|
|
7
|
+
if not f.endswith('.md'):
|
|
8
|
+
continue
|
|
9
|
+
content = open(f'src/agents/{f}').read()
|
|
10
|
+
match = re.match(r'^---\n(.*?)\n---', content, re.DOTALL)
|
|
11
|
+
if match:
|
|
12
|
+
try:
|
|
13
|
+
yaml.safe_load(match.group(1))
|
|
14
|
+
except yaml.YAMLError as e:
|
|
15
|
+
print(f'FAIL: {f}: {e}')
|
|
16
|
+
errors += 1
|
|
17
|
+
|
|
18
|
+
print(f'{sum(1 for _ in os.listdir("src/agents") if _.endswith(".md")) - errors}/{sum(1 for _ in os.listdir("src/agents") if _.endswith(".md"))} agents valid')
|
|
19
|
+
sys.exit(errors)
|
package/scripts/doctor.mjs
CHANGED
|
@@ -35,20 +35,16 @@ import { fileURLToPath } from 'node:url'
|
|
|
35
35
|
|
|
36
36
|
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
37
37
|
const ROOT = join(__dirname, '..')
|
|
38
|
-
const AGENTS_DIR = join(ROOT,
|
|
38
|
+
const AGENTS_DIR = join(ROOT, "src", "agents")
|
|
39
39
|
const PLATFORM_DIR = join(ROOT, 'platform')
|
|
40
40
|
|
|
41
41
|
// All known platforms (must match platform/ subdirectories with adapter.json)
|
|
42
|
-
const _ALL_PLATFORMS = ['opencode'
|
|
42
|
+
const _ALL_PLATFORMS = ['opencode']
|
|
43
43
|
|
|
44
44
|
const PLATFORM_LABELS = {
|
|
45
45
|
opencode: 'OpenCode',
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
windsurf: 'Windsurf',
|
|
49
|
-
copilot: 'VS Code / Copilot',
|
|
50
|
-
continue: 'Continue.dev',
|
|
51
|
-
cline: 'Cline',
|
|
46
|
+
}
|
|
47
|
+
opencode: 'OpenCode',
|
|
52
48
|
}
|
|
53
49
|
|
|
54
50
|
// ---------------------------------------------------------------------------
|
|
@@ -183,13 +179,13 @@ function showHelp() {
|
|
|
183
179
|
// ---------------------------------------------------------------------------
|
|
184
180
|
|
|
185
181
|
/**
|
|
186
|
-
* Collect canonical agent names from agents/*.
|
|
182
|
+
* Collect canonical agent names from agents/*.md
|
|
187
183
|
* @returns {string[]} sorted list of agent names (without extension)
|
|
188
184
|
*/
|
|
189
185
|
function getCanonicalAgentNames() {
|
|
190
186
|
if (!existsSync(AGENTS_DIR)) return []
|
|
191
187
|
return readdirSync(AGENTS_DIR)
|
|
192
|
-
.filter((f) => f.endsWith('.
|
|
188
|
+
.filter((f) => f.endsWith('.md'))
|
|
193
189
|
.map((f) => f.replace(/\.agent\.md$/, ''))
|
|
194
190
|
.sort()
|
|
195
191
|
}
|
|
@@ -421,7 +417,7 @@ function checkMcpConfig(args) {
|
|
|
421
417
|
* Cross-reference agent mcpServers references with opencode.json MCP config entries.
|
|
422
418
|
*/
|
|
423
419
|
function checkAgentMcpReferences(cfg) {
|
|
424
|
-
const agentFiles = readdirSync(AGENTS_DIR).filter((f) => f.endsWith('.
|
|
420
|
+
const agentFiles = readdirSync(AGENTS_DIR).filter((f) => f.endsWith('.md'))
|
|
425
421
|
const mcpNames = new Set(Object.keys(cfg.data.mcp ?? {}))
|
|
426
422
|
const referencedNames = new Set()
|
|
427
423
|
|
|
@@ -519,7 +515,7 @@ function checkPermissionMismatches(args) {
|
|
|
519
515
|
let bodyIssues = 0
|
|
520
516
|
|
|
521
517
|
for (const agent of canonical) {
|
|
522
|
-
const filePath = join(AGENTS_DIR, `${agent}.
|
|
518
|
+
const filePath = join(AGENTS_DIR, `${agent}.md`)
|
|
523
519
|
if (!existsSync(filePath)) continue
|
|
524
520
|
|
|
525
521
|
const content = readFileSync(filePath, 'utf8')
|
|
@@ -561,59 +557,8 @@ function checkPermissionMismatches(args) {
|
|
|
561
557
|
function checkSyncStatus(args) {
|
|
562
558
|
section('D. Sync Status')
|
|
563
559
|
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
warn('sync-platforms.mjs not found')
|
|
567
|
-
return
|
|
568
|
-
}
|
|
569
|
-
|
|
570
|
-
// Use the validate-sync approach: dry-run with clean
|
|
571
|
-
const result = spawn(process.execPath, [syncScript, '--dry-run', '--clean'])
|
|
572
|
-
// sync-platforms exits 1 when there are changes in dry-run mode
|
|
573
|
-
|
|
574
|
-
if (result.status === 0) {
|
|
575
|
-
pass('All platforms are in sync with canonical agents')
|
|
576
|
-
} else if (result.status === 1) {
|
|
577
|
-
// Parse output to determine what would change
|
|
578
|
-
const lines = (result.stdout || '').split('\n').filter(Boolean)
|
|
579
|
-
const updateLines = lines.filter((l) => l.includes('would update') || l.includes('~'))
|
|
580
|
-
const staleLines = lines.filter((l) => l.includes('stale'))
|
|
581
|
-
|
|
582
|
-
const updateCount = updateLines.length
|
|
583
|
-
const staleCount = staleLines.length
|
|
584
|
-
|
|
585
|
-
warn(
|
|
586
|
-
`Platforms are out of sync (${updateCount} file(s) would change${staleCount > 0 ? `, ${staleCount} stale` : ''})`,
|
|
587
|
-
)
|
|
588
|
-
if (args.verbose || updateCount + staleCount < 20) {
|
|
589
|
-
for (const line of updateLines) {
|
|
590
|
-
console.log(` ${line}`)
|
|
591
|
-
}
|
|
592
|
-
for (const line of staleLines) {
|
|
593
|
-
console.log(` ${line}`)
|
|
594
|
-
}
|
|
595
|
-
}
|
|
596
|
-
|
|
597
|
-
if (args.fix) {
|
|
598
|
-
info('Attempting --fix: running npm run sync...')
|
|
599
|
-
const syncResult = spawn('npm', ['run', 'sync'])
|
|
600
|
-
if (syncResult.status === 0) {
|
|
601
|
-
pass('Sync completed successfully')
|
|
602
|
-
} else {
|
|
603
|
-
error(`Sync failed (exit ${syncResult.status})`)
|
|
604
|
-
if (syncResult.stderr) {
|
|
605
|
-
console.log(` ${syncResult.stderr}`)
|
|
606
|
-
}
|
|
607
|
-
}
|
|
608
|
-
} else {
|
|
609
|
-
info('Use --fix to run "npm run sync" automatically')
|
|
610
|
-
}
|
|
611
|
-
} else {
|
|
612
|
-
error(`Sync dry-run failed (exit ${result.status})`)
|
|
613
|
-
if (result.stderr) {
|
|
614
|
-
console.log(` ${result.stderr}`)
|
|
615
|
-
}
|
|
616
|
-
}
|
|
560
|
+
// Platform sync removed in v1.0 (OpenCode-only)
|
|
561
|
+
info('Sync check skipped — platform sync was removed in v1.0')
|
|
617
562
|
}
|
|
618
563
|
|
|
619
564
|
// ---------------------------------------------------------------------------
|
|
@@ -72,10 +72,15 @@ function isGlobalConfigDir(target) {
|
|
|
72
72
|
|
|
73
73
|
export function installOpenCode(
|
|
74
74
|
target,
|
|
75
|
-
dryRun,
|
|
75
|
+
dryRun = false,
|
|
76
76
|
clean = false,
|
|
77
77
|
components = ['agents', 'skills', 'instructions', 'commands', 'plugins', 'runtime'],
|
|
78
78
|
) {
|
|
79
|
+
// Default target if not provided (global ~/.config/opencode)
|
|
80
|
+
if (!target) {
|
|
81
|
+
target = join(homedir(), '.config', 'opencode')
|
|
82
|
+
}
|
|
83
|
+
|
|
79
84
|
const componentSet = new Set(components)
|
|
80
85
|
const stats = summary.opencode
|
|
81
86
|
|
|
@@ -117,6 +122,18 @@ export function installOpenCode(
|
|
|
117
122
|
}
|
|
118
123
|
}
|
|
119
124
|
|
|
125
|
+
// -----------------------------------------------------------------------
|
|
126
|
+
// 1.5 Install routing.yml (routing configuration)
|
|
127
|
+
// -----------------------------------------------------------------------
|
|
128
|
+
if (componentSet.has('agents')) {
|
|
129
|
+
const srcRouting = join(ROOT, 'src', 'routing.yml')
|
|
130
|
+
const dstRouting = join(target, 'routing.yml')
|
|
131
|
+
if (existsSync(srcRouting)) {
|
|
132
|
+
writeIfChanged(dstRouting, readFileSync(srcRouting, 'utf8'), dryRun)
|
|
133
|
+
stats.created++
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
|
|
120
137
|
// -----------------------------------------------------------------------
|
|
121
138
|
// 2. Install skills (--components skills)
|
|
122
139
|
// -----------------------------------------------------------------------
|
|
@@ -193,10 +210,30 @@ export function installOpenCode(
|
|
|
193
210
|
}
|
|
194
211
|
|
|
195
212
|
// -----------------------------------------------------------------------
|
|
213
|
+
// -----------------------------------------------------------------------
|
|
214
|
+
// 2.7 Ensure subagent_depth in opencode.json
|
|
215
|
+
// -----------------------------------------------------------------------
|
|
216
|
+
if (componentSet.has('agents')) {
|
|
217
|
+
const cfgPath = join(target, 'opencode.json')
|
|
218
|
+
if (existsSync(cfgPath)) {
|
|
219
|
+
try {
|
|
220
|
+
const cfg = JSON.parse(readFileSync(cfgPath, 'utf8'))
|
|
221
|
+
let changed = false
|
|
222
|
+
if (cfg.subagent_depth === undefined) { cfg.subagent_depth = 2; changed = true }
|
|
223
|
+
if (changed && !dryRun) {
|
|
224
|
+
writeFileSync(cfgPath, JSON.stringify(cfg, null, 2) + '\n')
|
|
225
|
+
console.log(' ✅ subagent_depth: 2 added to opencode.json')
|
|
226
|
+
}
|
|
227
|
+
} catch (e) {
|
|
228
|
+
console.warn(` ⚠️ Could not update opencode.json: ${e.message}`)
|
|
229
|
+
}
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
|
|
196
233
|
// 2.8 Install TUI plugins (--components plugins)
|
|
197
234
|
// -----------------------------------------------------------------------
|
|
198
235
|
if (componentSet.has('plugins')) {
|
|
199
|
-
const srcPluginDir = join(
|
|
236
|
+
const srcPluginDir = join(ROOT, 'src', 'plugins', 'tui')
|
|
200
237
|
const dstPluginDir = isGlobal
|
|
201
238
|
? join(target, 'plugins', 'pantheon-tui')
|
|
202
239
|
: join(target, '.opencode', 'plugins', 'pantheon-tui')
|
|
@@ -205,9 +242,29 @@ export function installOpenCode(
|
|
|
205
242
|
rmSync(dstPluginDir, { recursive: true, force: true })
|
|
206
243
|
mkdirSync(dstPluginDir, { recursive: true })
|
|
207
244
|
}
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
245
|
+
if (!dryRun) mkdirSync(join(dstPluginDir, "dist"), { recursive: true })
|
|
246
|
+
// Copy src/index.tsx -> index.tsx
|
|
247
|
+
const srcIdx = join(srcPluginDir, "src", "index.tsx")
|
|
248
|
+
if (existsSync(srcIdx)) {
|
|
249
|
+
writeIfChanged(join(dstPluginDir, "index.tsx"), readFileSync(srcIdx, "utf8"), dryRun)
|
|
250
|
+
stats.created++
|
|
251
|
+
}
|
|
252
|
+
// Copy dist files
|
|
253
|
+
const distSrc = join(srcPluginDir, "dist")
|
|
254
|
+
if (existsSync(distSrc)) {
|
|
255
|
+
for (const f of readdirSync(distSrc)) {
|
|
256
|
+
const c = readFileSync(join(distSrc, f), "utf8")
|
|
257
|
+
writeIfChanged(join(dstPluginDir, "dist", f), c, dryRun)
|
|
258
|
+
stats.created++
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
// Copy package.json
|
|
262
|
+
const pkgSrc = join(srcPluginDir, "package.json")
|
|
263
|
+
if (existsSync(pkgSrc)) {
|
|
264
|
+
writeIfChanged(join(dstPluginDir, "package.json"), readFileSync(pkgSrc, "utf8"), dryRun)
|
|
265
|
+
stats.created++
|
|
266
|
+
}
|
|
267
|
+
|
|
211
268
|
}
|
|
212
269
|
|
|
213
270
|
// -----------------------------------------------------------------------
|
|
@@ -227,8 +284,14 @@ export function installOpenCode(
|
|
|
227
284
|
if (!Array.isArray(tuiConfig.plugin)) {
|
|
228
285
|
tuiConfig.plugin = []
|
|
229
286
|
}
|
|
287
|
+
// Remove stale plugin refs (old dist/tui.tsx path)
|
|
288
|
+
const staleRefs = ["plugins/pantheon-tui/dist/tui.tsx", "plugins/pantheon-tui/dist/tui.js"]
|
|
289
|
+
for (const stale of staleRefs) {
|
|
290
|
+
const idx = tuiConfig.plugin.indexOf(stale)
|
|
291
|
+
if (idx !== -1) tuiConfig.plugin.splice(idx, 1)
|
|
292
|
+
}
|
|
230
293
|
// Add our plugin if not already present
|
|
231
|
-
const pluginRef = 'plugins/pantheon-tui
|
|
294
|
+
const pluginRef = 'plugins/pantheon-tui'
|
|
232
295
|
if (!tuiConfig.plugin.includes(pluginRef)) {
|
|
233
296
|
tuiConfig.plugin.push(pluginRef)
|
|
234
297
|
}
|