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.
Files changed (49) hide show
  1. package/AGENTS.md +58 -15
  2. package/CHANGELOG.md +37 -100
  3. package/README.md +78 -102
  4. package/README.pt-BR.md +19 -37
  5. package/package.json +1 -2
  6. package/plugin.json +2 -2
  7. package/pyproject.toml +1 -1
  8. package/scripts/build-agents-md.mjs +2 -3
  9. package/scripts/doctor.mjs +22 -104
  10. package/scripts/hooks/scan-secrets.sh +97 -0
  11. package/scripts/install/config-migration.mjs +9 -42
  12. package/scripts/install/interactive.mjs +1 -1
  13. package/scripts/install/opencode.mjs +114 -43
  14. package/scripts/install/strings.mjs +0 -8
  15. package/scripts/probe-pantheon-cost.mjs +3 -16
  16. package/scripts/test-opencode-v2-sandbox.sh +203 -786
  17. package/scripts/validate-sandbox-install.mjs +138 -0
  18. package/skills-lock.json +3 -4
  19. package/src/agents/aphrodite.md +2 -9
  20. package/src/agents/demeter.md +0 -9
  21. package/src/agents/gaia.md +1 -0
  22. package/src/agents/hephaestus.md +0 -9
  23. package/src/agents/hermes.md +2 -9
  24. package/src/agents/mnemosyne.md +14 -42
  25. package/src/agents/prometheus.md +0 -9
  26. package/src/agents/themis.md +0 -1
  27. package/src/agents/zeus.md +180 -19
  28. package/src/instructions/agent-return-format.instructions.md +48 -3
  29. package/src/instructions/memory-protocol.instructions.md +8 -9
  30. package/src/instructions/zeus-anti-stall.instructions.md +54 -6
  31. package/src/instructions/zeus-council-synthesis.instructions.md +71 -0
  32. package/src/instructions/zeus-memory-operations.instructions.md +4 -4
  33. package/src/instructions/zeus-timeout-retry.instructions.md +81 -7
  34. package/src/pantheon/v2-delegation-enforce.ts +2 -1
  35. package/src/plugin-v2.ts +251 -168
  36. package/src/plugins/pantheon-hooks.ts +35 -82
  37. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  38. package/src/plugins/tui/dist/tui.js +26 -50
  39. package/src/plugins/tui/package-lock.json +2 -2
  40. package/src/plugins/tui/package.json +1 -1
  41. package/src/plugins/tui/src/index.tsx +25 -60
  42. package/src/routing.yml +4 -2
  43. package/src/skills/README.md +7 -12
  44. package/src/skills/agent-coordination/SKILL.md +83 -13
  45. package/src/skills/auto-continue/SKILL.md +13 -14
  46. package/src/skills/context-compression/SKILL.md +26 -879
  47. package/src/pantheon/secret-scanner.ts +0 -489
  48. package/src/plugins/tui/README.md +0 -14
  49. 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": "cedeaf001d70abbb526a61bcd0feaaca10b9898ac8e983dae573511f6b34ca34",
2
+ "src/skills/agent-coordination/SKILL.md": "cfd040ef29e3dd0fd5e0e67773874facf7c06e3284898afe1fddba4456c3f1aa",
3
3
  "src/skills/artifact-management/SKILL.md": "91d68c8f2d1b642725adfc6df11e55865a8491aca690dc27d02ea7c778d49d41",
4
- "src/skills/auto-continue/SKILL.md": "5ab932a5f48db30d955da579bebe85eeda9985284ed1fda6705104a6f62d84d2",
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/council-synthesis/SKILL.md": "ef479ba6f6d15c84b2129620733dc2733e62778cfeb6ba83febf5b0af21371a7",
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",
@@ -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`
@@ -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`
@@ -22,6 +22,7 @@ mcp_tools:
22
22
  pantheon-resources: all
23
23
  pantheon-memory: [memory_recall]
24
24
  pantheon-code-mode: []
25
+ pantheon-vision: [vision_describe, vision_ocr, vision_analyze]
25
26
  ---
26
27
 
27
28
  ## Core Capabilities
@@ -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.
@@ -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`
@@ -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. **Auto-index memory**: Store the new entries with the `memory_store` MCP tool (namespace `memory-bank`) so `memory_search` can find them. Search is FTS5 (BM25) keyword retrieval — there is no embedding step to run or report on.
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 summary: "Compressed. 2 CRITICAL, 1 HIGH, 3 STANDARD. Budget: 15/20 lines. Cross-refs: +2 entities, +1 decision. Indexed X new, skipped Y duplicates."
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
- After each `compress_context` run, store the new entries with `memory_store`:
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, before wiping .tmp/:
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 any agent for artifact creation
156
+ - Called by another agent only when an artifact/memory task is explicitly requested
161
157
 
162
- ## Quick-Index Handler (Tier 1 — Background Agent Results)
158
+ ## Explicit Memory Store
163
159
 
164
- Called automatically by Zeus when any agent returns a subtask_summary
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
- **Trigger patterns:**
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 Quick-index <subtask_summary_json>`
164
+ **Command:** `@mnemosyne Store <concise reusable result>`
174
165
 
175
166
  **What it does:**
176
- 1. Calls `memory_store` with the summary fields
177
- 2. Stores under a `type/agent` namespace and a `<type>:<agent>:<date>` key
178
- 3. Reports: "Indexed: {type} from @{agent} (namespace {namespace})"
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
- - Auto-continue through memory initialization and Quick-index operations
202
- - No checkpoint needed (all operations are idempotent)
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
@@ -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`
@@ -16,7 +16,6 @@ skills:
16
16
  - code-review-checklist
17
17
  - security-hardening
18
18
  - tdd-with-agents
19
- - context-compression
20
19
  mcp_tools:
21
20
  pantheon-resources: all
22
21
  pantheon-memory: [memory_search]
@@ -1,5 +1,5 @@
1
1
  ---
2
- description: "Orquestrador central; delega conforme escopo e risco, sem implementar."
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
- - memory_recall
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
- - council-synthesis
23
+ - incremental-implementation
26
24
 
27
25
  ---
28
26
 
29
27
  ## Golden Rule
30
28
 
31
- **Coordenador apenas. Zeus não lê nem edita código-fonte.** O especialista que implementa inspeciona os arquivos relevantes; chame @apollo à parte só para discovery amplo/independente ou investigação read-only.
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
- ## Fluxo proporcional
32
+ ## 🔒 Fusion-Style Enforcement
35
33
 
36
- Zeus não edita arquivos nem executa shell; essas restrições são impostas pelas permissões do agente. Encaminhe apenas o trabalho que realmente exige um especialista. Use as descrições dos agentes para rotas óbvias; consulte `pantheon://routing` só quando o destino ou os limites de delegação não estiverem claros.
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
- - Pergunta ou explicação sem mudança no repositório: responda diretamente, sem delegar.
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
- Full-auto só continua trabalho reversível já autorizado; nunca libera os gates acima. Commit, push, merge e release não são automáticos.
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
- ## Roteamento
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
- Nunca use `general` ou `explore`. Escolha o especialista mais específico; se nenhum for adequado, pergunte ao usuário. Mnemosyne atua apenas em `.pantheon/memory-bank/`; documentação do projeto vai ao especialista de implementação ou a @iris para release.
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
- ## Delegação paralela
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
- Use `background=true` somente se `OPENCODE_EXPERIMENTAL_BACKGROUND_SUBAGENTS=true` e houver pelo menos duas tarefas independentes. Envie os dispatches juntos e aguarde os IDs conhecidos com `task_status(wait=true)`; sem paralelismo real, prefira uma chamada síncrona. Limite a orquestração a Zeus → especialista → no máximo um especialista auxiliar, quando a configuração permitir. Não use KV compartilhado para contar profundidade: ele é estado global, sujeito a corrida entre tarefas.
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.