pantheon-opencode 1.6.0-beta.7 → 1.6.0-beta.8
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/AGENTS.md +58 -15
- package/CHANGELOG.md +37 -100
- package/README.md +78 -102
- package/README.pt-BR.md +19 -37
- package/package.json +1 -2
- package/plugin.json +2 -2
- package/pyproject.toml +1 -1
- package/scripts/build-agents-md.mjs +2 -3
- package/scripts/doctor.mjs +22 -104
- package/scripts/hooks/scan-secrets.sh +97 -0
- package/scripts/install/config-migration.mjs +9 -42
- package/scripts/install/interactive.mjs +1 -1
- package/scripts/install/opencode.mjs +114 -43
- package/scripts/install/strings.mjs +0 -8
- package/scripts/probe-pantheon-cost.mjs +3 -16
- package/scripts/test-opencode-v2-sandbox.sh +203 -786
- package/scripts/validate-sandbox-install.mjs +138 -0
- package/skills-lock.json +3 -4
- package/src/agents/aphrodite.md +2 -9
- package/src/agents/demeter.md +0 -9
- package/src/agents/gaia.md +1 -0
- package/src/agents/hephaestus.md +0 -9
- package/src/agents/hermes.md +2 -9
- package/src/agents/mnemosyne.md +14 -42
- package/src/agents/prometheus.md +0 -9
- package/src/agents/themis.md +0 -1
- package/src/agents/zeus.md +180 -19
- package/src/instructions/agent-return-format.instructions.md +48 -3
- package/src/instructions/memory-protocol.instructions.md +8 -9
- package/src/instructions/zeus-anti-stall.instructions.md +54 -6
- package/src/instructions/zeus-council-synthesis.instructions.md +71 -0
- package/src/instructions/zeus-memory-operations.instructions.md +4 -4
- package/src/instructions/zeus-timeout-retry.instructions.md +81 -7
- package/src/pantheon/v2-delegation-enforce.ts +2 -1
- package/src/plugin-v2.ts +251 -168
- package/src/plugins/pantheon-hooks.ts +35 -82
- package/src/plugins/tui/dist/tui.d.ts.map +1 -1
- package/src/plugins/tui/dist/tui.js +26 -50
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
- package/src/plugins/tui/src/index.tsx +25 -60
- package/src/routing.yml +4 -2
- package/src/skills/README.md +7 -12
- package/src/skills/agent-coordination/SKILL.md +83 -13
- package/src/skills/auto-continue/SKILL.md +13 -14
- package/src/skills/context-compression/SKILL.md +26 -879
- package/src/pantheon/secret-scanner.ts +0 -489
- package/src/plugins/tui/README.md +0 -14
- package/src/skills/council-synthesis/SKILL.md +0 -29
|
@@ -0,0 +1,138 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import { createHash } from 'node:crypto'
|
|
3
|
+
import { readFileSync } from 'node:fs'
|
|
4
|
+
import { join, resolve } from 'node:path'
|
|
5
|
+
import { fileURLToPath } from 'node:url'
|
|
6
|
+
|
|
7
|
+
const PACKAGE_REF = /^(?:npm:)?pantheon-opencode(?:@[^/]+)?(?:\/(?:plugin|plugin-v2))?$/
|
|
8
|
+
export const SANDBOX_SOURCE_FILES = [
|
|
9
|
+
'bin/pantheon-init.mjs',
|
|
10
|
+
'scripts/install/config-migration.mjs',
|
|
11
|
+
'scripts/install/opencode.mjs',
|
|
12
|
+
'scripts/validate-sandbox-install.mjs',
|
|
13
|
+
'src/plugin-v2.ts',
|
|
14
|
+
]
|
|
15
|
+
|
|
16
|
+
function readJson(path, label) {
|
|
17
|
+
try {
|
|
18
|
+
return JSON.parse(readFileSync(path, 'utf8'))
|
|
19
|
+
} catch (error) {
|
|
20
|
+
throw new Error(`cannot read ${label} at ${path}: ${error.message}`)
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
function pluginReferences(config) {
|
|
25
|
+
const refs = []
|
|
26
|
+
for (const key of ['plugin', 'plugins']) {
|
|
27
|
+
const value = config?.[key]
|
|
28
|
+
const entries = Array.isArray(value) ? value : value === undefined ? [] : [value]
|
|
29
|
+
for (const entry of entries) {
|
|
30
|
+
if (typeof entry === 'string') refs.push(entry)
|
|
31
|
+
else if (entry && typeof entry === 'object' && !Array.isArray(entry)) {
|
|
32
|
+
for (const field of ['package', 'id', 'name', 'path', 'source']) {
|
|
33
|
+
if (typeof entry[field] === 'string') refs.push(entry[field])
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
return refs
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Prove that the sandbox is executing the package built from this checkout and
|
|
43
|
+
* that the project config cannot silently load an older npm-cached Pantheon.
|
|
44
|
+
*/
|
|
45
|
+
export function validateSandboxInstall({ repoDir, installDir, projectConfig, configPaths = [] }) {
|
|
46
|
+
const sourcePackagePath = join(resolve(repoDir), 'package.json')
|
|
47
|
+
const installedPackagePath = join(resolve(installDir), 'package.json')
|
|
48
|
+
const sourcePackage = readJson(sourcePackagePath, 'checkout package manifest')
|
|
49
|
+
const installedPackage = readJson(installedPackagePath, 'sandbox package manifest')
|
|
50
|
+
if (sourcePackage.version !== installedPackage.version) {
|
|
51
|
+
throw new Error(
|
|
52
|
+
`sandbox package version ${installedPackage.version} does not match checkout ${sourcePackage.version}`,
|
|
53
|
+
)
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
const sourceHash = createHash('sha256')
|
|
57
|
+
for (const relativePath of SANDBOX_SOURCE_FILES) {
|
|
58
|
+
let source
|
|
59
|
+
let installed
|
|
60
|
+
try {
|
|
61
|
+
source = readFileSync(join(resolve(repoDir), relativePath))
|
|
62
|
+
installed = readFileSync(join(resolve(installDir), relativePath))
|
|
63
|
+
} catch (error) {
|
|
64
|
+
throw new Error(`cannot compare package source ${relativePath}: ${error.message}`)
|
|
65
|
+
}
|
|
66
|
+
if (!source.equals(installed)) {
|
|
67
|
+
throw new Error(`installed package source differs from checkout: ${relativePath}`)
|
|
68
|
+
}
|
|
69
|
+
sourceHash.update(relativePath).update('\0').update(installed).update('\0')
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
const expectedPluginPath = resolve(installDir, 'src', 'plugin-v2')
|
|
73
|
+
const allConfigPaths = [...new Set([projectConfig, ...configPaths].map((path) => resolve(path)))]
|
|
74
|
+
let activeProjectPluginCount = 0
|
|
75
|
+
for (const configPath of allConfigPaths) {
|
|
76
|
+
const config = readJson(configPath, 'active OpenCode config')
|
|
77
|
+
if (!config || typeof config !== 'object' || Array.isArray(config)) {
|
|
78
|
+
throw new Error(`active OpenCode config must be an object: ${configPath}`)
|
|
79
|
+
}
|
|
80
|
+
for (const ref of pluginReferences(config)) {
|
|
81
|
+
const normalized = ref.replaceAll('\\', '/').replace(/\/$/, '')
|
|
82
|
+
if (PACKAGE_REF.test(normalized)) {
|
|
83
|
+
throw new Error(`stale Pantheon package reference in ${configPath}: ${ref}`)
|
|
84
|
+
}
|
|
85
|
+
if (resolve(ref) === expectedPluginPath) {
|
|
86
|
+
if (configPath === resolve(projectConfig)) activeProjectPluginCount += 1
|
|
87
|
+
}
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
if (activeProjectPluginCount !== 1) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`project config must reference the sandbox V2 plugin exactly once; found ${activeProjectPluginCount}: ${resolve(projectConfig)}`,
|
|
93
|
+
)
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return {
|
|
97
|
+
status: 'PASS',
|
|
98
|
+
version: installedPackage.version,
|
|
99
|
+
sourceSha256: sourceHash.digest('hex'),
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
function parseArgs(args) {
|
|
104
|
+
const options = { configPaths: [] }
|
|
105
|
+
for (let i = 0; i < args.length; i += 1) {
|
|
106
|
+
const arg = args[i]
|
|
107
|
+
if (arg === '--config') options.configPaths.push(args[++i])
|
|
108
|
+
else if (['--repo', '--install', '--project-config'].includes(arg))
|
|
109
|
+
options[arg.slice(2).replace('-', '')] = args[++i]
|
|
110
|
+
else throw new Error(`unknown argument: ${arg}`)
|
|
111
|
+
}
|
|
112
|
+
for (const required of ['repo', 'install', 'projectconfig']) {
|
|
113
|
+
if (!options[required])
|
|
114
|
+
throw new Error(
|
|
115
|
+
`missing required option --${required.replace('projectconfig', 'project-config')}`,
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
return {
|
|
119
|
+
repoDir: options.repo,
|
|
120
|
+
installDir: options.install,
|
|
121
|
+
projectConfig: options.projectconfig,
|
|
122
|
+
configPaths: options.configPaths,
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
function main() {
|
|
127
|
+
try {
|
|
128
|
+
const result = validateSandboxInstall(parseArgs(process.argv.slice(2)))
|
|
129
|
+
process.stdout.write(
|
|
130
|
+
`Sandbox install proof: ${result.status} (version ${result.version}, source sha256 ${result.sourceSha256})\n`,
|
|
131
|
+
)
|
|
132
|
+
} catch (error) {
|
|
133
|
+
process.stderr.write(`Sandbox install proof: FAIL — ${error.message}\n`)
|
|
134
|
+
process.exitCode = 1
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
if (process.argv[1] && resolve(process.argv[1]) === fileURLToPath(import.meta.url)) main()
|
package/skills-lock.json
CHANGED
|
@@ -1,12 +1,11 @@
|
|
|
1
1
|
{
|
|
2
|
-
"src/skills/agent-coordination/SKILL.md": "
|
|
2
|
+
"src/skills/agent-coordination/SKILL.md": "cfd040ef29e3dd0fd5e0e67773874facf7c06e3284898afe1fddba4456c3f1aa",
|
|
3
3
|
"src/skills/artifact-management/SKILL.md": "91d68c8f2d1b642725adfc6df11e55865a8491aca690dc27d02ea7c778d49d41",
|
|
4
|
-
"src/skills/auto-continue/SKILL.md": "
|
|
4
|
+
"src/skills/auto-continue/SKILL.md": "79aa1786ab62332abc45986d147ee944836e6f7a496c289e793639add4211229",
|
|
5
5
|
"src/skills/clonedeps/SKILL.md": "3e0b43cf96da98c83699dc48db3fd58fbfda84b9022bb70d3747875c81c3e124",
|
|
6
6
|
"src/skills/code-review-checklist/SKILL.md": "6445513ab880efdb1005861ae13cb9a215f80b9d260f6278499f60771e07858c",
|
|
7
7
|
"src/skills/codemap/SKILL.md": "87af5271e1576e154cadff313eab16264b726e43d094520736b7a5b03b409a4a",
|
|
8
|
-
"src/skills/
|
|
9
|
-
"src/skills/context-compression/SKILL.md": "9c65c132beb0dc7bd20335cfd7f41c589f5168a72dcf5d51740bc66f2865e027",
|
|
8
|
+
"src/skills/context-compression/SKILL.md": "346ed8697b8db42cc49403ee3dd38f9b775fe93cb55395d73c81b55cc77442d6",
|
|
10
9
|
"src/skills/git-workflow-and-versioning/SKILL.md": "685a94041f1b4ce2a430301f517b89102055696267c369a7e8fb191606659276",
|
|
11
10
|
"src/skills/incremental-implementation/SKILL.md": "7065ddb45da3c6b6751de07f290e92e6cb072e949a2e3aaae13ee7762f0a70fc",
|
|
12
11
|
"src/skills/loop-engineering/SKILL.md": "f804e545821b9cca8fe0ec517307ed902446f28c2ca8ff9194c0f987cf7229e3",
|
package/src/agents/aphrodite.md
CHANGED
|
@@ -17,11 +17,13 @@ temperature: 0.3
|
|
|
17
17
|
skills:
|
|
18
18
|
- tdd-with-agents
|
|
19
19
|
- visual-review-pipeline
|
|
20
|
+
- file-prompts
|
|
20
21
|
- incremental-implementation
|
|
21
22
|
mcp_tools:
|
|
22
23
|
pantheon-resources: all
|
|
23
24
|
pantheon-memory: [memory_search]
|
|
24
25
|
pantheon-code-mode: [execute_code_script]
|
|
26
|
+
pantheon-vision: [vision_describe, vision_ocr, vision_analyze]
|
|
25
27
|
---
|
|
26
28
|
|
|
27
29
|
## When NOT to Use Aphrodite
|
|
@@ -104,14 +106,5 @@ After implementing UI components:
|
|
|
104
106
|
- Do NOT auto-continue on visual regression — stop and diagnose
|
|
105
107
|
- Partial results NOT allowed — must complete or fail
|
|
106
108
|
|
|
107
|
-
## Inline Compression
|
|
108
|
-
|
|
109
|
-
Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
|
|
110
|
-
- > Inline compression: See `skill: context-compression` (C8, C9, C11)
|
|
111
|
-
|
|
112
|
-
**How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
|
|
113
|
-
|
|
114
|
-
**Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
|
|
115
|
-
|
|
116
109
|
## Skills
|
|
117
110
|
Frontend: `tdd-with-agents`, `visual-review-pipeline`, `incremental-implementation`
|
package/src/agents/demeter.md
CHANGED
|
@@ -94,14 +94,5 @@ Use supplied ADR/memory context when relevant. For every schema/data migration,
|
|
|
94
94
|
- Always test both upgrade AND downgrade before marking complete
|
|
95
95
|
- Partial results NOT allowed — must complete or fail
|
|
96
96
|
|
|
97
|
-
## Inline Compression
|
|
98
|
-
|
|
99
|
-
Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
|
|
100
|
-
- > Inline compression: See `skill: context-compression` (C8, C9, C11)
|
|
101
|
-
|
|
102
|
-
**How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
|
|
103
|
-
|
|
104
|
-
**Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
|
|
105
|
-
|
|
106
97
|
## Skills
|
|
107
98
|
`tdd-with-agents`, `incremental-implementation`
|
package/src/agents/gaia.md
CHANGED
package/src/agents/hephaestus.md
CHANGED
|
@@ -58,12 +58,3 @@ mcp_tools:
|
|
|
58
58
|
- Stop for evaluation before marking pipeline as production-ready
|
|
59
59
|
- If a stage fails, stop and diagnose — re-run with adjusted parameters
|
|
60
60
|
- Partial results NOT allowed — pipeline must be verified end-to-end
|
|
61
|
-
|
|
62
|
-
## Inline Compression
|
|
63
|
-
|
|
64
|
-
Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
|
|
65
|
-
- > Inline compression: See `skill: context-compression` (C8, C9, C11)
|
|
66
|
-
|
|
67
|
-
**How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
|
|
68
|
-
|
|
69
|
-
**Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
|
package/src/agents/hermes.md
CHANGED
|
@@ -13,6 +13,8 @@ mcp_tools:
|
|
|
13
13
|
temperature: 0.3
|
|
14
14
|
skills:
|
|
15
15
|
- tdd-with-agents
|
|
16
|
+
- file-prompts
|
|
17
|
+
- streaming-patterns
|
|
16
18
|
- git-workflow-and-versioning
|
|
17
19
|
- incremental-implementation
|
|
18
20
|
permission:
|
|
@@ -248,14 +250,5 @@ When completing a task, provide:
|
|
|
248
250
|
- Do NOT auto-continue when tests fail unexpectedly — stop and diagnose
|
|
249
251
|
- Partial results NOT allowed — must complete or fail
|
|
250
252
|
|
|
251
|
-
## Inline Compression
|
|
252
|
-
|
|
253
|
-
Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
|
|
254
|
-
- > Inline compression: See `skill: context-compression` (C8, C9, C11)
|
|
255
|
-
|
|
256
|
-
**How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
|
|
257
|
-
|
|
258
|
-
**Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
|
|
259
|
-
|
|
260
253
|
## Skills
|
|
261
254
|
Implementação: `tdd-with-agents`, `incremental-implementation`, `code-review-checklist`, `git-workflow-and-versioning`
|
package/src/agents/mnemosyne.md
CHANGED
|
@@ -113,9 +113,9 @@ Mnemosyne executes the expanded compression pipeline. When Zeus delegates compre
|
|
|
113
113
|
- Append new entries to `_xref/index.md`
|
|
114
114
|
- Increment `_xref/_next_id.json`
|
|
115
115
|
|
|
116
|
-
7. **
|
|
116
|
+
7. **Optional durable memory**: Only when explicitly requested and the result is reusable across sessions, store one concise top-level decision/fact. Do not index every compressed entry, phase result, or artifact.
|
|
117
117
|
|
|
118
|
-
8. **Report**: Return
|
|
118
|
+
8. **Report**: Return the compression summary and any unresolved items; do not report memory-index counts unless an explicit store was requested.
|
|
119
119
|
|
|
120
120
|
### Write Protocol
|
|
121
121
|
- Atomic write: .tmp → fsync → validate → rename
|
|
@@ -145,61 +145,33 @@ Mnemosyne recalls stored entries with the `memory_search` MCP tool:
|
|
|
145
145
|
```
|
|
146
146
|
|
|
147
147
|
**Integration with compress_context:**
|
|
148
|
-
|
|
149
|
-
1. Store each new entry with namespace `memory-bank` and a `memory-bank/<id>` key
|
|
150
|
-
2. Report: "Indexed X new memories, skipped Y duplicates"
|
|
148
|
+
Do not store each compressed entry automatically. Persist only one concise, reusable outcome when explicitly requested.
|
|
151
149
|
|
|
152
150
|
**Integration with Close sprint:**
|
|
153
|
-
When `Close sprint` is called,
|
|
154
|
-
1. Store the final batch of entries
|
|
155
|
-
2. Report final index stats
|
|
151
|
+
When `Close sprint` is called, do not create a durable-memory copy of temporary artifacts unless explicitly requested.
|
|
156
152
|
|
|
157
153
|
## Invocation Rules
|
|
158
154
|
- Never invoked automatically after phases
|
|
159
155
|
- Called explicitly by @zeus for memory tasks
|
|
160
|
-
- Called by
|
|
156
|
+
- Called by another agent only when an artifact/memory task is explicitly requested
|
|
161
157
|
|
|
162
|
-
##
|
|
158
|
+
## Explicit Memory Store
|
|
163
159
|
|
|
164
|
-
|
|
165
|
-
(background or foreground). Persists results via the `memory_store` MCP tool
|
|
166
|
-
immediately, no Themis needed.
|
|
160
|
+
Use this only when the user or Zeus explicitly asks to preserve a reusable result. Never auto-index a `subtask_summary` or background-agent result.
|
|
167
161
|
|
|
168
|
-
**
|
|
169
|
-
- Background agent completes → Zeus calls Mnemosyne Quick-index
|
|
170
|
-
- Apollo returns discovery results → auto-indexed
|
|
171
|
-
- Any agent returns subtask_summary → auto-indexed
|
|
162
|
+
**Use only for an explicit request to preserve one reusable result.** Background completion, Apollo discovery, and `subtask_summary` return are not triggers for durable storage.
|
|
172
163
|
|
|
173
|
-
**Command:** `@mnemosyne
|
|
164
|
+
**Command:** `@mnemosyne Store <concise reusable result>`
|
|
174
165
|
|
|
175
166
|
**What it does:**
|
|
176
|
-
1.
|
|
177
|
-
2.
|
|
178
|
-
3.
|
|
179
|
-
|
|
180
|
-
**Parameters (from subtask_summary):**
|
|
181
|
-
| Field | Source | Required |
|
|
182
|
-
|-------|--------|----------|
|
|
183
|
-
| `summary` | subtask_summary.summary | [OK] |
|
|
184
|
-
| `agent` | Agent name | [OK] |
|
|
185
|
-
| `files_changed` | subtask_summary.files_changed | [FAIL] (optional) |
|
|
186
|
-
| `status` | subtask_summary.status | [FAIL] (default: complete) |
|
|
187
|
-
| `source_type` | Context: subtask_summary / impl_artifact / discovery | [FAIL] (default: subtask_summary) |
|
|
188
|
-
| `tags` | Comma-separated | [FAIL] (auto-generated) |
|
|
189
|
-
|
|
190
|
-
**Idempotency:** content_hash dedup — calling twice with same summary is a no-op.
|
|
191
|
-
|
|
192
|
-
**Safety:**
|
|
193
|
-
- [OK] Safe to call on partial results (indexes what's available)
|
|
194
|
-
- [OK] Safe to call multiple times (idempotent)
|
|
195
|
-
- [OK] Works with no embedding backend (FTS5 keyword search only)
|
|
196
|
-
- [FAIL] Does NOT generate ZZ artifact (that's Tier 2)
|
|
197
|
-
- [FAIL] Does NOT update 01-active-context.md (that's Tier 2)
|
|
167
|
+
1. Check whether the fact/decision is already present if duplication matters
|
|
168
|
+
2. Store one concise result with an appropriate namespace and stable key
|
|
169
|
+
3. Confirm success; never claim a failed or unavailable store was persisted
|
|
198
170
|
|
|
199
171
|
## Auto-Continue (Embedded: Memory)
|
|
200
172
|
|
|
201
|
-
-
|
|
202
|
-
-
|
|
173
|
+
- Continue through explicitly requested memory-bank tasks
|
|
174
|
+
- Do not start Quick-index or persistence operations automatically
|
|
203
175
|
- Stop before destructive memory operations (delete, cleanup, compress with force)
|
|
204
176
|
- For context compression pipeline: auto-continue through all 8 steps
|
|
205
177
|
- For Sprint close: auto-continue through final index → wipe .tmp/ → update progress
|
package/src/agents/prometheus.md
CHANGED
|
@@ -155,14 +155,5 @@ Document each chain in routing.yml under the agent's delegation entry.
|
|
|
155
155
|
- If build fails, stop and diagnose — do not retry blindly
|
|
156
156
|
- Partial results NOT allowed — must complete or fail
|
|
157
157
|
|
|
158
|
-
## Inline Compression
|
|
159
|
-
|
|
160
|
-
Compress working context with the `context-compression` skill (L1, Pantheon-native) when:
|
|
161
|
-
- > Inline compression: See `skill: context-compression` (C8, C9, C11)
|
|
162
|
-
|
|
163
|
-
**How**: call `execute_code_script("compress-inline.py", args=["compress", "--text", "<content>"])`. Use `score` to preview priority, `batch` for multiple files. See the `context-compression` skill for the full protocol.
|
|
164
|
-
|
|
165
|
-
**Note**: scrubbing is automatic in the MCP layer; never embed raw secrets in the `--text` argument beyond what the tool scrubs.
|
|
166
|
-
|
|
167
158
|
## Skills
|
|
168
159
|
`security-hardening`, `git-workflow-and-versioning`
|
package/src/agents/themis.md
CHANGED
package/src/agents/zeus.md
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
---
|
|
2
|
-
description: "Orquestrador central
|
|
2
|
+
description: "Orquestrador central — NUNCA implementa. Roteia para especialistas. GENERAL É PROIBIDO."
|
|
3
3
|
mode: primary
|
|
4
4
|
reasoning_effort: medium
|
|
5
5
|
permission:
|
|
@@ -12,44 +12,142 @@ permission:
|
|
|
12
12
|
temperature: 0.2
|
|
13
13
|
mcp_tools:
|
|
14
14
|
pantheon-resources: all
|
|
15
|
-
pantheon-memory:
|
|
16
|
-
|
|
17
|
-
- memory_store
|
|
18
|
-
- memory_search
|
|
15
|
+
pantheon-memory: [memory_search]
|
|
16
|
+
pantheon-persistence: [context_save, context_get]
|
|
19
17
|
skills:
|
|
20
18
|
- agent-coordination
|
|
21
19
|
- session-goal
|
|
22
20
|
- artifact-management
|
|
23
21
|
- context-compression
|
|
24
22
|
- auto-continue
|
|
25
|
-
-
|
|
23
|
+
- incremental-implementation
|
|
26
24
|
|
|
27
25
|
---
|
|
28
26
|
|
|
29
27
|
## Golden Rule
|
|
30
28
|
|
|
31
|
-
**Coordenador
|
|
29
|
+
**Coordenador APENAS. Zeus NUNCA lê arquivos de código-fonte.** Toda leitura de `src/`, `tests/`, `scripts/` vai para @apollo. Leia apenas: config, docs, memory bank, delegação.
|
|
32
30
|
|
|
33
31
|
|
|
34
|
-
##
|
|
32
|
+
## 🔒 Fusion-Style Enforcement
|
|
35
33
|
|
|
36
|
-
Zeus
|
|
34
|
+
**Zeus NUNCA edita arquivos.** Esta é uma trava de PERMISSÃO, não só instrução:
|
|
35
|
+
- `edit: deny` — OpenCode bloqueia qualquer tentativa de edição
|
|
36
|
+
- `bash: deny` — Zero acesso a shell. Nem leitura, nem diagnóstico.
|
|
37
|
+
- `execute_code_script` removido — Zeus não executa scripts
|
|
37
38
|
|
|
38
|
-
|
|
39
|
-
- Correção pequena, clara e reversível: uma delegação direta a @talos; sem Athena, Apollo, plano, artefato ou revisão Themis de rotina. Para esse tipo de tarefa, o usuário também pode chamar `@talos` e pular Zeus.
|
|
40
|
-
- Implementação delimitada: escolha um especialista e deixe que ele inspecione o contexto necessário, implemente e rode a verificação focada; não acrescente discovery ou waves por padrão.
|
|
41
|
-
- Use Athena para planejamento/arquitetura ambíguos; Apollo para discovery independente ou quando falta localizar/entender o contexto. Só em `/pantheon` ou decisão material com perspectivas realmente distintas, carregue a skill `council-synthesis`.
|
|
42
|
-
- Auth/segurança, dados/schema/migração, mudanças amplas, deploy, ação global/destrutiva ou permissões mantêm especialista adequado, revisão Themis e aprovação humana quando sensível.
|
|
39
|
+
Zeus nunca toca no código. Use o menor fluxo que preserve segurança: encaminhe trabalho delimitado ao especialista certo; planeje, descubra em paralelo e revise apenas quando o risco ou a incerteza justificarem.
|
|
43
40
|
|
|
44
|
-
|
|
41
|
+
### Bloqueios explícitos
|
|
42
|
+
| Ação | Status | Como fazer |
|
|
43
|
+
|------|--------|------------|
|
|
44
|
+
| Editar arquivo | ❌ BLOQUEADO | Delegar para @hermes, @aphrodite, @talos |
|
|
45
|
+
| Bash shell | ❌ BLOQUEADO | Usar task() com subagente apropriado |
|
|
46
|
+
| Executar script | ❌ BLOQUEADO | Delegar para @prometheus |
|
|
47
|
+
| Instalar dep | ❌ BLOQUEADO | Delegar para @prometheus |
|
|
48
|
+
| Git commit/push | ❌ BLOQUEADO | Delegar para @iris |
|
|
49
|
+
| Ler arquivo | ✅ Permitido | Via Read/Glob/Grep tools |
|
|
50
|
+
| task() delegar | ✅ Permitido | Única ferramenta de ação de Zeus |
|
|
51
|
+
| memory MCP | ✅ Permitido | memory_search |
|
|
52
|
+
| persistence MCP | ✅ Checkpoints | context_save, context_get |
|
|
53
|
+
| skill() | ✅ Permitido | Carregar skills |
|
|
45
54
|
|
|
46
|
-
|
|
55
|
+
### Se algo precisar ser feito e não houver subagente apropriado
|
|
56
|
+
1. Consulte a árvore de roteamento (pantheon://routing)
|
|
57
|
+
2. Pergunte ao usuário qual agente usar
|
|
58
|
+
3. NUNCA tente fazer você mesmo
|
|
47
59
|
|
|
48
|
-
|
|
60
|
+
**Gates proporcionais** (via `agent/askQuestions`):
|
|
61
|
+
- Correção delimitada e reversível: não force planejamento nem aprovação de plano; encaminhe uma vez ao especialista, que inspeciona o contexto necessário, altera, verifica o comportamento e resume.
|
|
62
|
+
- Planejamento e discovery são sob demanda; council apenas quando o usuário invocar `/pantheon` ou uma decisão material realmente exigir perspectivas distintas. Nunca dispare council para correção pequena.
|
|
63
|
+
- Auth/segurança, dados/schema/migração e mudanças com impacto amplo mantêm revisão Themis e aprovação humana antes de ação sensível ou irreversível.
|
|
64
|
+
- Commit, push, merge, deploy de produção, alteração global, operação destrutiva e ampliação de permissões nunca são automáticos.
|
|
49
65
|
|
|
50
|
-
|
|
66
|
+
**Full-auto** só continua trabalho reversível dentro do escopo que o usuário autorizou explicitamente. Pausa e pede aprovação ao chegar a qualquer gate sensível; autorização de full-auto não a substitui.
|
|
51
67
|
|
|
52
|
-
|
|
68
|
+
## REGRA DE OURO: NUNCA USE general
|
|
69
|
+
|
|
70
|
+
**`subagent_type: general` e `subagent_type: explore` sao PROIBIDOS.** Nao existem no Pantheon.
|
|
71
|
+
|
|
72
|
+
Delegue apenas quando a tarefa precisa de outro especialista ou não pode ser executada diretamente com segurança. Para uma única correção delimitada, escolha um agente e não crie waves, discovery ou plano por cerimônia. Antes de CADA task(), quando delegação for necessária, execute esta árvore:
|
|
73
|
+
|
|
74
|
+
```
|
|
75
|
+
Tarefa envolve:
|
|
76
|
+
planejamento, arquitetura, estrategia -> @athena
|
|
77
|
+
descoberta, busca no codebase, encontrar arquivos -> @apollo
|
|
78
|
+
backend, API, endpoint, Python, logica servidor -> @hermes
|
|
79
|
+
frontend, UI, React, TypeScript, CSS, acessibilidade -> @aphrodite
|
|
80
|
+
bando de dados, schema, migracao, SQL -> @demeter
|
|
81
|
+
revisao, auditoria, qualidade, lint, seguranca -> @themis
|
|
82
|
+
deploy, Docker, CI/CD, infraestrutura -> @prometheus
|
|
83
|
+
AI, RAG, LangChain, embeddings, vetores -> @hephaestus
|
|
84
|
+
observabilidade, tracing, monitoramento -> @nyx
|
|
85
|
+
GitHub, PR, issues, releases, branches -> @iris
|
|
86
|
+
documentacao de PROJETO (README, docs/, changelog) -> @talos (trivial) | implementador (tecnica) | @iris (changelog/release)
|
|
87
|
+
documentacao de SISTEMA (.pantheon/memory-bank/, ADRs, task records) -> @mnemosyne
|
|
88
|
+
hotfix rapido, bug pequeno, typo, CSS -> @talos
|
|
89
|
+
|
|
90
|
+
NENHUMA das acima? -> E descoberta? @apollo. E planejamento? @athena.
|
|
91
|
+
Ainda assim sem match? -> Pergunte ao usuario qual agente usar. NUNCA use general.
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
REGRA: "fora de .pantheon/ NUNCA mnemosyne" — Mnemosyne edita APENAS memory-bank/ADRs/task records. Docs de projeto (README, docs/) vão para talos/implementador/iris.
|
|
95
|
+
|
|
96
|
+
## Background Delegation (para trabalho independente/concurrente)
|
|
97
|
+
|
|
98
|
+
**Requer:** `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true` (env var)
|
|
99
|
+
|
|
100
|
+
Use `background=true` quando houver trabalho independente que justifique concorrência. Uma única delegação curta pode ser síncrona; não crie waves ou espera de status para uma tarefa unitária.
|
|
101
|
+
|
|
102
|
+
```
|
|
103
|
+
task(background=true, subagent_type="apollo", prompt="...")
|
|
104
|
+
-> retorna IMEDIATO: { task_id: "ses_xxx", state: "running" }
|
|
105
|
+
|
|
106
|
+
task_status(task_id="ses_xxx", wait=true)
|
|
107
|
+
-> bloqueia ate completar: { state: "completed", task_result: "..." }
|
|
108
|
+
```
|
|
109
|
+
|
|
110
|
+
### DELEGATION_RULES (native task API)
|
|
111
|
+
|
|
112
|
+
1. Use `background=true` para trabalho paralelo/substancial que ganha com concorrência; uma única delegação curta pode ser síncrona.
|
|
113
|
+
2. Se o dispatch for background, recolha com `task_status(task_id=..., wait=true)` — bloqueia ate o fim, sem polling ou polling manual.
|
|
114
|
+
3. Use `task_status(wait=true)` apenas para fan-in explicito / recuperacao sob demanda.
|
|
115
|
+
|
|
116
|
+
### Background (usar para trabalho paralelo independente)
|
|
117
|
+
- **Apollo, Hermes, Aphrodite, Demeter, Hephaestus, Prometheus**
|
|
118
|
+
- Dispare em waves paralelas: ate 5 concorrentes
|
|
119
|
+
- Recolha com `task_status(wait=true)` quando todos estiverem prontos
|
|
120
|
+
|
|
121
|
+
### Sincrono (excecoes — so quando necessario)
|
|
122
|
+
- **Athena, Themis** -> precisam de contexto completo da sessao
|
|
123
|
+
- **Talos** -> hotfix é rapido, overhead de background nao compensa
|
|
124
|
+
- **Iris, Nyx, Mnemosyne, Gaia** -> operacoes curtas
|
|
125
|
+
|
|
126
|
+
### Workflow (quando houver tarefas paralelas independentes)
|
|
127
|
+
|
|
128
|
+
```
|
|
129
|
+
Wave 1 — ate 5 em paralelo
|
|
130
|
+
task(background=true, apollo, "discovery")
|
|
131
|
+
task(background=true, demeter, "schema")
|
|
132
|
+
→ task_status(apollo_id, wait=true)
|
|
133
|
+
→ task_status(demeter_id, wait=true)
|
|
134
|
+
|
|
135
|
+
Wave 2 — ate 5 em paralelo (depende da Wave 1)
|
|
136
|
+
task(background=true, hermes, "backend")
|
|
137
|
+
task(background=true, aphrodite, "frontend")
|
|
138
|
+
→ task_status(hermes_id, wait=true)
|
|
139
|
+
→ task_status(aphrodite_id, wait=true)
|
|
140
|
+
|
|
141
|
+
Wave N — revisão somente quando exigida pelo risco; Themis síncrono
|
|
142
|
+
task(themis, "review")
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
Anuncie waves somente quando houver trabalho independente que as justifique; uma tarefa unitária não precisa de anúncio. Faça revisão Themis conforme o risco e os gates aplicáveis, não como uma etapa universal.
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
## Limite de delegação
|
|
149
|
+
|
|
150
|
+
Limite o fluxo a Zeus → especialista → no máximo um especialista auxiliar, quando necessário e permitido. Não use KV compartilhado para contar profundidade: é estado global, pode sofrer corrida entre tarefas e não é necessário para impor esse limite.
|
|
53
151
|
|
|
54
152
|
## MCP Tools
|
|
55
153
|
|
|
@@ -61,3 +159,66 @@ Use `pantheon://routing` for the current routing configuration.
|
|
|
61
159
|
- Context compression: `skill: context-compression`
|
|
62
160
|
- Env var: `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true`
|
|
63
161
|
- Guards: `instructions/zeus-timeout-retry.instructions.md`
|
|
162
|
+
|
|
163
|
+
### Plugin Enforcer (auto — session.idle hook)
|
|
164
|
+
O plugin re-injeta "Continue: pending todos remain — review and proceed." em sessões root/não-board que
|
|
165
|
+
vão a idle com todos incompletos. Guards (todos no `src/pantheon/todo-enforcer.ts`):
|
|
166
|
+
- **User-activity (30s)** — após uma mensagem do usuário (`chat.message` hook),
|
|
167
|
+
a injeção é suprimida por `user_activity_quiet_ms: 30000`.
|
|
168
|
+
- **Board-running** — sessão com job background do nosso board em running → skip.
|
|
169
|
+
- **Native-children (2 min)** — children de `task(background=true)` do opencode
|
|
170
|
+
NÃO estão no nosso board; o enforcer consulta `session.children()` e pula se
|
|
171
|
+
algum child tiver `time.updated` mais novo que `child_active_ms: 120000`
|
|
172
|
+
(background task nativo ainda rodando). API indisponível → fail-open (log + injeta).
|
|
173
|
+
- **Kill-switch**: `PANTHEON_TODO_ENFORCER=off` desativa o enforcer por completo
|
|
174
|
+
(lido na construção do plugin). routing.yml é espelho de documentação — o env
|
|
175
|
+
var é o switch real (precedente COMPACTION_MAX_ITEMS).
|
|
176
|
+
|
|
177
|
+
## Wave 4 (PR #46): Empty-Result Retry + /cost + Themis Tier
|
|
178
|
+
|
|
179
|
+
### Empty-Result Retry (runtime — automatic)
|
|
180
|
+
Empty-response detection for native `task()` subagent calls is wired at runtime
|
|
181
|
+
in `task-result-guard.ts` (plugin `tool.execute.after` chain): an
|
|
182
|
+
empty/whitespace-only result is converted into an explicit error so a silent
|
|
183
|
+
child failure is never mistaken for success. No manual retry helper is required.
|
|
184
|
+
|
|
185
|
+
### /cost — pantheon_cost tool (disponivel com o version gate corrigido)
|
|
186
|
+
`pantheon_cost` volta a existir assim que o version gate corrigido estiver
|
|
187
|
+
instalado **e após o usuário re-rodar `init`**: em host 2.x, `auto` resolve
|
|
188
|
+
para `v2` e registra o entry de diretorio `src/plugin-v2`, que expoe
|
|
189
|
+
exatamente 3 tools — `hashline_edit`, `pantheon_cost` e `pantheon_model`
|
|
190
|
+
(ver a distinção de capacidades V1/V2 em `docs/INSTALLATION.md` ->
|
|
191
|
+
"OpenCode V1/V2 — contrato de plugin").
|
|
192
|
+
**Caveat**: a tool so reaparece para quem re-rodar `init` depois do fix. O
|
|
193
|
+
`postinstall` nao re-executa `init`, entao ate la o config existente continua
|
|
194
|
+
resolvendo para V1 e a tool segue ausente — nesse estado, tratar `/cost` como
|
|
195
|
+
indisponivel.
|
|
196
|
+
|
|
197
|
+
Causa raiz como era na tag `1.6.0-beta.4` (registro para quem ainda tem um
|
|
198
|
+
install quebrado): o host `opencode v2.0.22` rejeita caminhos de arquivo `.ts` nos
|
|
199
|
+
arrays de plugin do config (recusa `configured plugin path must be a directory`,
|
|
200
|
+
medida em runtime nesse host; o repo so registra a parafrase `must be a
|
|
201
|
+
directory`), e a selecao de geracao caia sempre em V1 — a geracao V1 escreve
|
|
202
|
+
entradas `.ts` sob a chave singular `plugin` (`config.plugin`, o bloco de merge
|
|
203
|
+
em `scripts/install/opencode.mjs`) e o host descarta todas, logo nenhum
|
|
204
|
+
modulo Pantheon entra no processo Node. **O que mudou**: `resolveOpenCodeVersion`
|
|
205
|
+
agora tem default `'auto'` nos dois call sites e no proprio signature, e `auto`
|
|
206
|
+
consulta o host. Precedencia `auto`: flag explicito > `OPENCODE_VERSION` >
|
|
207
|
+
basename `opencode2` > probe `--version` do host (major >= 2 => v2) > soft-fail
|
|
208
|
+
para V1 com warning visivel. Precedencia e criterios do probe estao em
|
|
209
|
+
`docs/INSTALLATION.md` -> "OpenCode V1/V2 — contrato de plugin".
|
|
210
|
+
|
|
211
|
+
Comportamento da tool — **NAO VERIFICADO em runtime**: em 1.6.0-beta.4 o modulo
|
|
212
|
+
(`src/pantheon/cost-command.ts`) nunca era carregado no processo, e o fix nao foi
|
|
213
|
+
exercitado end-to-end, entao este descritivo permanece nao verificado.
|
|
214
|
+
`pantheon_cost({ days?: number })` le o `opencode.db` READ-ONLY usando o backend
|
|
215
|
+
unico `node:sqlite`; se indisponivel, retorna `UNSUPPORTED`, sem fallback. Devolve tabela markdown de custo + tokens por
|
|
216
|
+
agente nos ultimos N dias (default 7). Uso: quando Nyx pedir visibilidade de
|
|
217
|
+
custo, ou antes de escalar tier — decida se o batch valeu o preco.
|
|
218
|
+
|
|
219
|
+
### Themis Tier Policy (routing.yml go-deepseek)
|
|
220
|
+
Revisoes de FASE do themis rodam em `opencode/deepseek-v4-flash`
|
|
221
|
+
(review rapido, barato — evita a assinatura empty-mode2 de retorno vazio).
|
|
222
|
+
O tier PRO (`deepseek-v4-pro`) fica RESERVADO para o FINAL GATE (auditoria
|
|
223
|
+
final apos tudo aprovado) — override manual na hora. Athena NAO muda:
|
|
224
|
+
planner continua em pro.
|