pantheon-opencode 1.5.2 → 1.6.0-beta.10

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 (146) hide show
  1. package/.pantheon/code-mode/README.md +4 -2
  2. package/.pantheon/code-mode/checkpoint_session.py +138 -102
  3. package/.pantheon/code-mode/compress-inline.py +102 -57
  4. package/.pantheon/code-mode/manifest.json +2 -8
  5. package/AGENTS.global.md +182 -0
  6. package/AGENTS.md +10 -891
  7. package/CHANGELOG.md +343 -0
  8. package/README.md +577 -79
  9. package/README.pt-BR.md +345 -60
  10. package/bin/pantheon-init.mjs +26 -3
  11. package/commands/pantheon-audit.md +7 -1
  12. package/commands/pantheon-consolidate.md +1 -1
  13. package/commands/pantheon-deepwork.md +14 -3
  14. package/commands/pantheon-focus.md +17 -0
  15. package/commands/pantheon-optimize.md +2 -2
  16. package/commands/pantheon-vision.md +61 -12
  17. package/package.json +30 -11
  18. package/plugin.json +2 -2
  19. package/pyproject.toml +11 -16
  20. package/scripts/build-agents-md.mjs +376 -58
  21. package/scripts/changelog-merge.mjs +161 -0
  22. package/scripts/check-plugin-v2-coverage.mjs +213 -0
  23. package/scripts/ci-validate-yaml.py +7 -5
  24. package/scripts/{code_mode_server.py → code_mode.py} +119 -27
  25. package/scripts/cost.mjs +244 -41
  26. package/scripts/doctor.mjs +236 -29
  27. package/scripts/install/agents-md.mjs +4 -4
  28. package/scripts/install/cli-ui.mjs +1 -1
  29. package/scripts/install/config-migration.mjs +319 -6
  30. package/scripts/install/health-check.mjs +26 -37
  31. package/scripts/install/interactive.mjs +7 -7
  32. package/scripts/install/migrate.mjs +1 -1
  33. package/scripts/install/opencode-version.mjs +246 -4
  34. package/scripts/install/opencode.mjs +627 -179
  35. package/scripts/install/plugin.mjs +43 -9
  36. package/scripts/install/shared.mjs +120 -12
  37. package/scripts/install/vision-prompt.mjs +161 -0
  38. package/scripts/install-mcp.mjs +28 -9
  39. package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +392 -78
  40. package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +2 -2
  41. package/scripts/{memory_mcp_server.py → memory_mcp.py} +372 -198
  42. package/scripts/postinstall.mjs +0 -7
  43. package/scripts/probe-context-rehydrate.mjs +36 -13
  44. package/scripts/probe-pantheon-cost.mjs +71 -15
  45. package/scripts/prune.mjs +2 -2
  46. package/scripts/run-node-tests.mjs +189 -0
  47. package/scripts/sync-artifacts.mjs +26 -13
  48. package/scripts/sync-tui.mjs +24 -3
  49. package/scripts/test-opencode-v2-sandbox.sh +1913 -0
  50. package/scripts/validate-routing.mjs +43 -3
  51. package/scripts/validate-sandbox-install.mjs +138 -0
  52. package/scripts/versioning.mjs +13 -1
  53. package/scripts/vision-status.mjs +682 -0
  54. package/skills-lock.json +15 -16
  55. package/src/agents/aphrodite.md +20 -37
  56. package/src/agents/apollo.md +7 -3
  57. package/src/agents/athena.md +63 -35
  58. package/src/agents/demeter.md +8 -28
  59. package/src/agents/gaia.md +1 -1
  60. package/src/agents/hephaestus.md +10 -21
  61. package/src/agents/hermes.md +15 -38
  62. package/src/agents/iris.md +1 -1
  63. package/src/agents/mnemosyne.md +23 -60
  64. package/src/agents/nyx.md +1 -1
  65. package/src/agents/prometheus.md +16 -20
  66. package/src/agents/talos.md +10 -2
  67. package/src/agents/themis.md +5 -5
  68. package/src/agents/zeus.md +99 -130
  69. package/src/instructions/agent-return-format.instructions.md +18 -3
  70. package/src/instructions/backend-standards.instructions.md +2 -0
  71. package/src/instructions/frontend-standards.instructions.md +3 -1
  72. package/src/instructions/memory-protocol.instructions.md +11 -110
  73. package/src/instructions/zeus-anti-stall.instructions.md +14 -61
  74. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  75. package/src/instructions/zeus-council-synthesis.instructions.md +32 -260
  76. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  77. package/src/instructions/zeus-timeout-retry.instructions.md +40 -87
  78. package/src/mcp/{code_mode_server.py → code_mode.py} +119 -27
  79. package/src/mcp/eval_store.py +2 -2
  80. package/src/mcp/mcp_codemap_module.py +559 -129
  81. package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +392 -78
  82. package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +2 -2
  83. package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +373 -250
  84. package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +396 -40
  85. package/src/mcp/requirements-mcp.txt +10 -6
  86. package/src/mcp/requirements-vision.txt +4 -2
  87. package/src/pantheon/cost-command.ts +399 -101
  88. package/src/pantheon/delegation-enforce.ts +10 -1
  89. package/src/pantheon/model-command.ts +18 -7
  90. package/src/pantheon/presets.d.mts +0 -8
  91. package/src/pantheon/presets.mjs +5 -32
  92. package/src/pantheon/todo-enforcer.ts +1 -1
  93. package/src/pantheon/v2-bounded-read.ts +640 -0
  94. package/src/pantheon/v2-delegation-enforce.ts +214 -0
  95. package/src/pantheon/v2-execute-after.ts +186 -0
  96. package/src/pantheon/v2-tools.ts +429 -0
  97. package/src/pantheon/v2-unsupported.d.mts +11 -0
  98. package/src/pantheon/v2-unsupported.mjs +90 -0
  99. package/src/pantheon/v2-vision.ts +622 -0
  100. package/src/pantheon/vision-local.ts +531 -0
  101. package/src/pantheon/vision.ts +1161 -116
  102. package/src/plugin-v2.ts +1244 -288
  103. package/src/plugin.ts +12 -9
  104. package/src/plugins/tui/dist/server.d.ts +1 -2
  105. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  106. package/src/plugins/tui/dist/tui-v2.d.ts +154 -0
  107. package/src/plugins/tui/dist/tui-v2.d.ts.map +1 -0
  108. package/src/plugins/tui/dist/tui-v2.js +659 -0
  109. package/src/plugins/tui/dist/tui-v2.js.map +1 -0
  110. package/src/plugins/tui/dist/tui.d.ts +85 -82
  111. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  112. package/src/plugins/tui/dist/tui.js +72 -59
  113. package/src/plugins/tui/index-v2.ts +6 -0
  114. package/src/plugins/tui/package-lock.json +5504 -1341
  115. package/src/plugins/tui/package.json +25 -15
  116. package/src/plugins/tui/src/index-v2.tsx +734 -0
  117. package/src/plugins/tui/src/index.tsx +106 -85
  118. package/src/plugins/tui/src/opencode-v2.d.ts +13 -0
  119. package/src/plugins/tui/tsconfig.build.json +5 -0
  120. package/src/plugins/tui/tsconfig.typecheck.json +5 -0
  121. package/src/plugins/tui/tsdown.config.ts +22 -2
  122. package/src/plugins/tui/tui-v2.ts +2 -0
  123. package/src/plugins/tui/tui.ts +3 -0
  124. package/src/routing.yml +11 -22
  125. package/src/skills/README.md +34 -39
  126. package/src/skills/agent-coordination/SKILL.md +7 -2
  127. package/src/skills/artifact-management/SKILL.md +12 -5
  128. package/src/skills/auto-continue/SKILL.md +54 -95
  129. package/src/skills/code-review-checklist/SKILL.md +5 -5
  130. package/src/skills/context-compression/SKILL.md +26 -879
  131. package/src/skills/session-goal/SKILL.md +14 -5
  132. package/src/skills/spec-driven-development/SKILL.md +3 -1
  133. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  134. package/.pantheon/code-mode/eval-llm-judge.py +0 -255
  135. package/.pantheon/code-mode/eval-monte-carlo.py +0 -368
  136. package/.pantheon/code-mode/eval-run.py +0 -197
  137. package/.pantheon/code-mode/eval-static.py +0 -321
  138. package/.pantheon/code-mode/session-end-save.py +0 -186
  139. package/.pantheon/code-mode/session-end-save.sh +0 -18
  140. package/opencode.json +0 -58
  141. package/scripts/recover-zenodo-deposition.mjs +0 -146
  142. package/scripts/test-opencode-v1-v2-sandbox.sh +0 -862
  143. package/scripts/validate-zenodo-release.mjs +0 -154
  144. package/scripts/zenodo-artifact.mjs +0 -94
  145. package/scripts/zenodo-release-state.mjs +0 -53
  146. package/src/skills/orchestration-workflow/SKILL.md +0 -311
package/README.pt-BR.md CHANGED
@@ -10,7 +10,7 @@ e equipes que querem mais estrutura sem perder o controle do próprio código.
10
10
 
11
11
  [![Versão](https://img.shields.io/github/v/release/ils15/pantheon-opencode?label=versão)](https://github.com/ils15/pantheon-opencode/releases/latest)
12
12
  [![CI](https://img.shields.io/github/actions/workflow/status/ils15/pantheon-opencode/ci.yml?branch=main&label=CI)](https://github.com/ils15/pantheon-opencode/actions)
13
- [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.22306637.svg)](https://doi.org/10.5281/zenodo.22306637)
13
+ [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.22650136.svg)](https://doi.org/10.5281/zenodo.22650136)
14
14
 
15
15
  ## O que é?
16
16
 
@@ -31,7 +31,7 @@ de planejar o trabalho, avançar, conferir resultados e preservar o contexto
31
31
 
32
32
  ## Comece em 2 minutos
33
33
 
34
- Requisitos: [OpenCode 1.18.4+](https://opencode.ai/docs/) e Node.js 22+.
34
+ Requisitos: [OpenCode 1.18.4+](https://opencode.ai/docs/) e Node.js `^22.22.2 || ^24.15.0 || >=26.0.0`.
35
35
 
36
36
  No projeto em que você quer usar o Pantheon:
37
37
 
@@ -53,6 +53,10 @@ Com o OpenCode em execução, descreva o resultado que você quer:
53
53
  ```
54
54
 
55
55
  O Pantheon ajuda a transformar esse pedido em um plano e em etapas revisadas.
56
+ Quando você pede um plano ou inicia `/pantheon-deepwork`, Athena devolve o plano
57
+ completo para Zeus, que o apresenta na conversa principal antes de pedir
58
+ aprovação. O pedido de aprovação não ficará separado de um plano escondido na
59
+ conversa de um subagente.
56
60
 
57
61
  ## Para quem é?
58
62
 
@@ -71,8 +75,8 @@ verificações repetíveis e passagens claras entre etapas do trabalho.
71
75
 
72
76
  ## Status
73
77
 
74
- Versão operacional neste checkout: **v1.5.0-beta.2** (candidata; esta página
75
- não afirma publicação). O Pantheon foi feito para OpenCode e depende da
78
+ Versão operacional neste checkout: **v1.6.0-beta.1** (primeira beta compatível
79
+ com OpenCode 2; esta página não afirma publicação). O Pantheon foi feito para OpenCode e depende da
76
80
  disponibilidade e da configuração do OpenCode e dos serviços opcionais que você
77
81
  escolher. Veja as [releases](https://github.com/ils15/pantheon-opencode/releases)
78
82
  e o [changelog](CHANGELOG.md) para acompanhar as mudanças publicadas.
@@ -103,25 +107,17 @@ falha fechado, sem fallback silencioso. O `doctor` valida o manifest e o
103
107
  SHA-256 de cada script sem regenerá-lo.
104
108
 
105
109
 
106
- ## Novidades da 1.5.0-beta.2
110
+ ## Novidades da 1.6.0-beta.1
107
111
 
108
- - Instalador exclusivo para OpenCode: guias de plataformas consolidados em um
109
- único [guia OpenCode](docs/platforms/opencode.md).
110
- - Novo CLI `uninstall` com escopos project/global e checagem de ownership:
111
- `node scripts/uninstall.mjs --project|--global [--dry-run] [--force]`.
112
- - Recursos MCP endurecidos: correção do `pantheon://agents` e proteção contra
113
- symlink/traversal nos caminhos de recursos.
114
- - Compatibilidade com OpenCode V2: merge de configuração `plugins` /
115
- `mcp.servers.enabled` e launch stdio MCP com PWD correto.
116
- - `doctor` e health checks de instalação expandidos.
117
- - Validador de sandbox para instalações globais
118
- (`scripts/test-opencode-v1-v2-sandbox.sh`) cobrindo OpenCode V1/V2 lado a
119
- lado — veja [Validação em sandbox](#validação-em-sandbox-v1v2).
120
- - A flag `--prompts` do instalador está planejada para uma release futura.
112
+ - Primeira beta compatível com o contrato de plugin do OpenCode 2.
113
+ - Remoção do pipeline legado de vector-memory, preservando a busca por palavras-
114
+ chave SQLite FTS5/BM25 e as ferramentas de codemap `code_*`.
115
+ - Validações de CI e release fail-closed; `doctor` e o sandbox exclusivo V2
116
+ cobrem o caminho de instalação do OpenCode 2.
121
117
 
122
- ## OpenCode V1/V2 — Versão dupla (1.5.0-beta.2)
118
+ ## OpenCode V1/V2 — Versão dupla (1.6.0-beta.1)
123
119
 
124
- O Pantheon tem dois contratos de plugin OpenCode **exclusivos**. A configuração
120
+ Esta é a primeira beta compatível com o OpenCode 2. O Pantheon tem dois contratos de plugin OpenCode **exclusivos**. A configuração
125
121
  comum do OpenCode pode ser compartilhada, mas o registro do plugin Pantheon é
126
122
  selecionado por instalação; os plugins Pantheon V1 e V2 nunca devem ser
127
123
  registrados juntos.
@@ -130,15 +126,137 @@ registrados juntos.
130
126
  |---|---|---|
131
127
  | Chave de config do OpenCode | `plugin` singular | `plugins` plural |
132
128
  | Registro Pantheon | `src/plugin.ts` mais `src/plugins/pantheon-hooks.ts` | `pantheon-opencode/plugin-v2` (`src/plugin-v2.ts`) |
133
- | Contrato de runtime | Plugin Pantheon V1: 6 ferramentas (`hashline_edit`, as 3 ferramentas de goal, `pantheon_cost`, `pantheon_model`), hooks de evento/ferramenta e tratamento de compactação V1 | Plugin V2 completo: 6 ferramentas de orquestração, 4 assinaturas de eventos, session hooks (`prompt`, `context`), tool hooks (`execute.before`/`after`), além de transforms de configuração |
129
+ | Contrato de runtime | Plugin Pantheon V1: 6 ferramentas (`hashline_edit`, as 3 ferramentas de goal, `pantheon_cost`, `pantheon_model`), hooks de evento/ferramenta e tratamento de compactação V1 | Plugin V2 completo: 3 ferramentas de orquestração mais `vision_describe` quando o catálogo de modelos está disponível, 5 assinaturas de eventos, session hooks (`prompt`, `context`), um hook `execute.before` que impõe sessões somente-leitura, além de transforms de configuração |
134
130
  | APIs V1 | Registradas | Definições próprias de ferramentas via `ctx.tool.transform()` — não pelo caminho do plugin V1 |
135
131
 
136
- O plugin V2 fornece 6 ferramentas de orquestração (`hashline_edit`,
137
- `pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
132
+ O plugin V2 fornece 3 ferramentas de orquestração (`hashline_edit`,
138
133
  `pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos (`session.created`,
139
134
  `session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
140
- `context`) e tool hooks (`execute.before`, `execute.after`). O único recurso V2
141
- sem suporte é `legacy-hooks` (a superfície de hooks específica do V1).
135
+ `context`) e um hook de ferramenta `execute.before` que impõe sessões
136
+ somente-leitura. As 3 ferramentas de goal **não** são
137
+ registradas no V2: o goal loop precisa de um `GoalStore`, de um
138
+ `GoalLoopClient` e de um `BackgroundJobBoard`, nenhum dos quais o
139
+ `PluginContext` do V2 expõe, então a lacuna é reportada como o marcador de
140
+ recurso sem suporte `goal-tools`. Use o contrato V1 se precisar do goal loop.
141
+
142
+ O V2 também registra `vision_describe` quando `ctx.model.list()` está
143
+ disponível. A ferramenta verifica a entrada de imagem no catálogo atual,
144
+ prioriza o modelo pago `opencode-go/mimo-v2.6-flash` (modelos free-tier são
145
+ excluídos da seleção automática — o gateway direto os rejeita com HTTP 403, só
146
+ funcionam de dentro do OpenCode; um pin explícito em
147
+ `PANTHEON_VISION_MODEL`/config/preset continua sendo honrado, então seu 403 vira
148
+ um erro acionável em vez de uma troca silenciosa) e envia a imagem
149
+ diretamente ao endpoint autenticado do OpenCode Zen. A requisição carrega o
150
+ session id vivo no header Zen-only `x-opencode-session` exigido pelo gateway
151
+ (nunca enviado a um provider não-Zen, e nunca logado). As credenciais vêm de
152
+ `opencode auth login` ou `PANTHEON_OPENCODE_API_KEY`; sem modelo compatível ou
153
+ credenciais, a ferramenta retorna um erro explícito em vez de inventar uma
154
+ descrição. Esse caminho funciona sem a ponte V1 opcional.
155
+ O hook de prompt V2 também preserva as referências dos anexos e orienta Zeus a
156
+ inspecionar imagens relevantes e repassar a referência e observações concisas a
157
+ Aphrodite. Bytes inline não são copiados para o texto persistido do prompt, e a
158
+ imagem não autoriza apagar nem reverter alterações fora do escopo.
159
+
160
+ O caminho nativo do turno de chat escolhe o modelo de visão numa precedência
161
+ fixa: a variável `PANTHEON_VISION_MODEL`, depois `visionModel` em
162
+ `opencode-vision.json`, depois `vision.model` do preset ativo, depois descoberta
163
+ automática no catálogo de providers do host (`GET /config/providers`) e, por
164
+ fim, o padrão embutido. A descoberta é conservadora e somente paga: mantém
165
+ apenas entradas com imagem (`capabilities.input.image`) cujo provider é Zen
166
+ confiável ou cujo pacote `npm` é OpenAI-compatível (`@ai-sdk/openai-compatible` /
167
+ `@ai-sdk/openai`), EXCLUI entradas free-tier (`-free` ou `cost.input <= 0` — o
168
+ gateway direto as rejeita com HTTP 403), escolhe a entrada mais barata restante
169
+ e faz cache do catálogo por 60
170
+ segundos por processo; um modelo incompatível simplesmente cai no fallback da
171
+ tool MCP de visão. A base URL vem do `api.url` da entrada do catálogo, e os
172
+ endpoints Zen legados permanecem como fallback quando não há catálogo. As
173
+ credenciais seguem o endpoint: para um endpoint Zen, as variáveis compartilhadas
174
+ `PANTHEON_OPENCODE_API_KEY` / `OPENCODE_API_KEY` são tentadas primeiro e depois o
175
+ auth store do OpenCode (o provider resolvido primeiro, depois as entradas legadas
176
+ `opencode-go` / `opencode`); para um endpoint não-Zen, apenas a entrada do próprio
177
+ provider no auth store é usada — as variáveis compartilhadas e as entradas Zen
178
+ legadas nunca são anexadas a uma base URL não-Zen. Um modelo de visão
179
+ configurado explicitamente e qualificado sempre vence a descoberta — um pin que
180
+ não qualifica (não-Zen, text-only ou fora do catálogo) é descartado e a seleção
181
+ automática assume. O `pantheon-opencode init` oferece um
182
+ passo opcional de vision em sessões TTY interativas — a descoberta automática é
183
+ o default e não grava nada; pinar faz merge de `visionModel` no
184
+ `opencode-vision.json` global; fluxos não-interativos nunca perguntam nem gravam.
185
+
186
+ A pergunta do usuário é injetada no prompt de visão nos caminhos nativo e V2,
187
+ aparada e limitada a 2000 caracteres; a mesma imagem com uma pergunta diferente
188
+ gera nova descrição, enquanto uma repetição idêntica dentro do TTL de cache
189
+ reutiliza o texto guardado. O describe nativo é robusto por construção: o
190
+ timeout escala de uma base de 20 segundos a cerca de 10 segundos por MB de
191
+ payload até um teto de 300 segundos, e uma checagem de orientação EXIF sem
192
+ dependências (JPEG) adiciona uma dica textual para o vision model descrever a
193
+ imagem rotacionada ou espelhada na posição correta — só detecção, os pixels
194
+ nunca são reescritos, e a orientação entra na chave do cache.
195
+
196
+ A visão degrada numa cadeia explícita — nativa → tool MCP de visão → local.
197
+ Quando a nativa está indisponível e a tool MCP de visão não está presente, a
198
+ imagem é substituída por extração local determinística: dimensões, formato e
199
+ tamanho do header PNG/JPEG/GIF/WebP, cores dominantes para PNG RGB/RGBA e OCR
200
+ somente quando o binário `tesseract` está no `PATH`. Nunca fabrica conteúdo — a
201
+ degradação é declarada explicitamente. As tools `vision_describe` e `vision_ocr`
202
+ do MCP degradam para esse modo local quando não há credencial de gateway, sem
203
+ dependências novas. (A `vision_analyze` exige credencial de gateway e retorna um
204
+ erro explícito.) Trade-offs deliberados, registrados para não serem
205
+ revertidos por acidente: o Pantheon descreve cada imagem uma vez e mantém o
206
+ texto no histórico (council 2026-08-03) em vez de preservar a imagem original
207
+ para re-observação a cada turno; o describe-always prioriza latência zero em vez
208
+ de uma tool `describe_image` sob demanda. A sanitização multi-turno
209
+ (`experimental.chat.messages.transform`) é invariante obrigatória — garante que
210
+ `image_url` / `FilePart` nunca cheguem a um provider textual e não é
211
+ configurável. O Bifrost permanece opt-in, nunca padrão, conforme o incidente de
212
+ credencial em [SECURITY.md](SECURITY.md).
213
+
214
+ O hook `execute.before` do V2 é o ponto de imposição de sessões somente-leitura
215
+ dessa superfície: o host inclui o agente ativo no evento, um agente somente-leitura
216
+ (`apollo`, `gaia`) registra sua sessão, e o `createEnforcementGuard`
217
+ compartilhado lança para negar `edit`, `write`, `bash`, `task`,
218
+ `hashline_edit` e `pantheon_model`. Ele **não** depende do hook
219
+ `tool.execute.before` do V1, que vive em `src/plugin.ts` e não é carregado
220
+ quando apenas `plugin-v2` está configurado. Quando o host registra o hook
221
+ `permission.evaluate`, ele aplica no V2 a matriz caller/target a todos os itens
222
+ do array `resources` do host para destinos gerenciados pelo Pantheon. Sem o
223
+ registro do hook, a matriz não fica disponível e o host mantém o controle.
224
+ Recursos exclusivamente nativos são repassados sem alteração à política de
225
+ permissões do OpenCode; pedidos mistos (nativos/Pantheon) ou com vários destinos
226
+ são negados.
227
+ Para destinos Pantheon, a política exige uma chamada nativa `subagent` cujo
228
+ session ID, message ID e tool-call ID no `source` coincidam com o evento do host
229
+ `tool.execute.before`; também confirma que a sessão não tem `parentID`. O campo
230
+ `permission.evaluate.agent`, sozinho, não identifica o chamador. Origins
231
+ ausentes, expirados, repetidos ou incompatíveis são negados. A canary no
232
+ OpenCode v2.0.29 admite Zeus→Apollo na raiz e nega dispatches inválidos ou
233
+ originados em uma filha; veja o [relatório de F4A](bench/results/f4a-v229-admission-identity-2026-10-14.md).
234
+ Uma negação explícita do host é final, e dados de recursos ausentes ou
235
+ desconhecidos são negados por padrão. O `execute.after` do
236
+ V2 executa a cadeia de resultados concluídos `task-result-guard` →
237
+ `context-sandbox` → `read-enhancer`; eventos de erro permanecem inalterados.
238
+
239
+ #### Leitura bounded do workspace (F3b)
240
+
241
+ No OpenCode v2.0.29, o plugin V2 pode registrar `pantheon_bounded_read` quando
242
+ o host oferece as APIs nativas de permissão e sessão. Só uma sessão root do
243
+ Zeus pode usá-la. Cada chamada pede ao host permissão `read` para um arquivo
244
+ relativo exato do workspace, com escopo de persistência vazio; o conteúdo só é
245
+ lido após aprovação e passa pelo scanner de segredos fail-closed existente.
246
+ Os limites são duas chamadas e dois arquivos distintos, 400 linhas e 32 KiB
247
+ por mensagem do assistant. Travessia de diretórios, symlinks, diretórios,
248
+ escopos sensíveis, formatos binários/mídia reconhecidos e falhas do scanner são
249
+ negados. O escopo suportado é um workspace local sem escritores concorrentes;
250
+ isso não promete isolamento contra filesystem adversarial nem classificação
251
+ binária do arquivo inteiro. Evidência host-backed:
252
+ [`bench/results/f3b-v229-bounded-read-2026-10-15.md`](bench/results/f3b-v229-bounded-read-2026-10-15.md).
253
+
254
+ Toda ferramenta V2 declara um schema `output`. O OpenCode 2.0.x exige que a
255
+ declaração e o resultado resolvido concordem nos dois sentidos, então uma
256
+ ferramenta sem declaração — ou que retorne `output` sem declará-lo — falha em
257
+ toda chamada. Os recursos V2 sem suporte são `legacy-hooks` (a superfície de
258
+ hooks específica do V1), `catalog-transform`, `integration-transform`,
259
+ `skill-transform` e `goal-tools`.
142
260
 
143
261
  O pacote expõe os dois contratos como exports importáveis:
144
262
  `pantheon-opencode/plugin` (V1), `pantheon-opencode/plugin-v2` (V2) e
@@ -158,26 +276,68 @@ npx pantheon-opencode init --opencode-version v2
158
276
  npx pantheon-opencode init --opencode-version auto
159
277
  ```
160
278
 
161
- `--version v1|v2|auto` é aceito como a grafia antiga do seletor quando usado
162
- depois de `init`. `auto` é conservador, não uma autodetecção geral de
163
- plataforma: `OPENCODE_VERSION=v1|v2` vence; caso contrário, um `OPENCODE_BIN`
164
- terminando em `opencode2` seleciona V2; qualquer outro caso seleciona V1. O
165
- instalador remove referências Pantheon das duas formas de config antes de
279
+ `auto` é o padrão. `--version v1|v2|auto` é aceito como a grafia antiga do seletor
280
+ quando usado depois de `init`. `auto` resolve a geração a partir do host nesta
281
+ ordem: um `OPENCODE_VERSION=v1|v2` explícito vence; caso contrário, um
282
+ `OPENCODE_BIN` terminando em `opencode2` seleciona V2; caso contrário o binário
283
+ do host é consultado com `--version` e uma major >= 2 seleciona V2. Qualquer
284
+ outro caso — uma sonda ilegível, um banner não interpretável, ou um banner
285
+ cujos tokens de versão se contradizem sem um nome de ferramenta que desfaça o
286
+ empate — avisa uma vez e volta para V1, porque uma entrada de diretório em
287
+ `plugins` plural em um host 1.x desconhecido perde o plugin inteiro.
288
+
289
+ A sonda prefere o token que vem logo após o nome da ferramenta, então um token
290
+ de runtime antes dele (`node v22.1.0 (opencode 1.18.33)`) ou uma data de build
291
+ no final (`opencode v1.18.33 built 2026.10.04`) não conseguem virar a geração.
292
+ O instalador remove referências Pantheon das duas formas de config antes de
166
293
  gravar apenas o registro Pantheon selecionado. Entradas de terceiros não são
167
294
  convertidas nem reivindicadas por essa regra.
168
295
 
169
- O relatório `pantheon_cost`, disponível nos plugins V1 e V2, pode selecionar o banco com
170
- `PANTHEON_OPENCODE_VERSION=v1` ou `v2` (`opencode.db` ou `opencode-v2.db`).
171
- `PANTHEON_COST_DB=/caminho/absoluto/para/opencode.db` tem precedência sobre o
172
- seletor de versão, e um `dbPath` explícito fornecido pelo chamador da
173
- ferramenta tem precedência sobre ambos. O resolver nunca consulta o banco da
174
- outra versão e reporta um erro acionável quando o banco selecionado está
175
- ausente ou com schema incompatível.
296
+ O relatório `pantheon_cost`, disponível nos plugins V1 e V2, resolve o banco por
297
+ CAMINHO, nesta ordem: um `dbPath` explícito fornecido pelo chamador da
298
+ ferramenta, depois `PANTHEON_COST_DB=/caminho/absoluto/para/opencode.db`,
299
+ depois `OPENCODE_DB`, e por fim o padrão do XDG `opencode.db`. Não há nome de
300
+ arquivo por versão nessa cadeia: `opencode-v2.db` não é um banco de um host 2.x
301
+ — é o nome que um sandbox dá ao próprio banco de estado via `OPENCODE_DB`.
302
+
303
+ A distinção v1/v2 é o SCHEMA DETECTADO, não o nome do arquivo. O relatório
304
+ procura as tabelas `message` e `session_message` e lê aquele que o banco aberto
305
+ realmente tiver, porque um banco migrado carrega as duas famílias ao mesmo
306
+ tempo. `PANTHEON_OPENCODE_VERSION=v1|v2` não seleciona arquivo nenhum: apenas
307
+ estreita um conjunto já detectado para uma família de tabelas, e falha rápido
308
+ quando o valor não é `v1` nem `v2` ou quando a família pedida não existe lá.
309
+ Sem a variável, todas as famílias detectadas são lidas. Um banco sem nenhuma
310
+ das duas tabelas volta como erro acionável (`CORRUPT_DATA`), e um ledger que
311
+ existe mas não produz tokens legíveis como `UNSUPPORTED` — nunca como um
312
+ relatório vazio com sucesso.
176
313
 
177
314
  O instalador continua gravando as configurações de compatibilidade exigidas
178
315
  pelo host OpenCode selecionado, como `experimental.subagent_depth`; isso não
179
316
  converte um plugin V1 em V2 nem dá hooks V1 ao V2.
180
317
 
318
+ O Pantheon não define mais um teto de passos para os agentes. No OpenCode 2 o
319
+ campo `steps` é opcional e não tem default: ausente significa que o host não
320
+ aplica nenhum limite nativo. Uma config escrita antes dessa mudança ainda
321
+ carrega o valor antigo, e o caminho de instalação v2 o remove de todos os
322
+ agentes que o Pantheon gerencia — um agente definido por você nunca é tocado,
323
+ e o bloco V1 singular `agent`, em retirada, é deixado intacto. Rode o
324
+ instalador uma vez para limpar um valor antigo de uma config existente:
325
+
326
+ ```bash
327
+ npx pantheon-opencode init --opencode-version=v2
328
+ ```
329
+
330
+ O controle de contexto não é uma configuração do Pantheon. Qualquer orçamento
331
+ que um agente terá vem das settings de compactação do próprio host OpenCode,
332
+ e o Pantheon não as define.
333
+
334
+ Quando um bloco V1 `agent` e um bloco V2 `agents` coexistem — o que acontece
335
+ em qualquer `opencode.json` já instalado — a conversão V1→V2 mescla os dois em
336
+ vez de deixar um substituir o outro. O bloco V2 é a base, os campos
337
+ gerenciados que vêm do V1 sobrescrevem, e os seus próprios campos são
338
+ preservados, com a mesma precedência que o instalador já aplica em outros
339
+ pontos. A ordem das chaves não muda o resultado.
340
+
181
341
  ## Atualizando entre releases (beta.5+)
182
342
 
183
343
  Um comando mantém uma instalação existente em dia:
@@ -200,7 +360,15 @@ pacote. Duas garantias de freshness sustentam isso:
200
360
  - **Sync de artifacts no postinstall** — depois de qualquer `npm install`, os
201
361
  artefatos de cópia (agents, skills, AGENTS.md, commands, scripts MCP,
202
362
  payload code-mode) são atualizados automaticamente no config dir existente;
203
- você nunca precisa re-rodar `init` só para atualizar arquivos.
363
+ você nunca precisa re-rodar `init` só para atualizar arquivos. O config dir
364
+ global recebe o **artefato global** agnóstico de repositório
365
+ (`AGENTS.global.md`: tabela de agentes + regras compartilhadas), enquanto o
366
+ `AGENTS.md` de cada projeto carrega apenas o setup específico do projeto —
367
+ os dois são esculpidos para serem disjuntos (trabalho de latência beta-10),
368
+ então nenhuma regra é paga duas vezes por sessão. A instalação é
369
+ conservadora: conteúdo fora da região gerenciada (regras próprias do
370
+ usuário) é preservado verbatim, um `AGENTS.md` legado totalmente gerado é
371
+ atualizado in place, e qualquer merge é reportado com um aviso.
204
372
  - **Detecção de drift** — o instalador grava a versão instalada em
205
373
  `.pantheon/install-state.json` e o `doctor` avisa quando o pacote é mais
206
374
  novo que o último sync, apontando para o `update`.
@@ -220,6 +388,10 @@ de PR, push, merge e tag nunca publicam nada, e todos os gates de validação s
220
388
  fail-closed: somente um PASS explícito autoriza release evidence. Consulte
221
389
  [docs/RELEASING.md](docs/RELEASING.md) para detalhes de validação e recuperação.
222
390
 
391
+ Se a seção de uma versão candidata já existir, atualize as notas com
392
+ `node scripts/versioning.mjs changelog <versão>`; o comando mescla `[Unreleased]`
393
+ na versão indicada sem avançar o número do pacote.
394
+
223
395
  A validação mantém cada manifest junto do seu lockfile: o root
224
396
  `package.json` + `package-lock.json` e o TUI
225
397
  `src/plugins/tui/package.json` + `src/plugins/tui/package-lock.json`. Ambos usam
@@ -228,39 +400,152 @@ fallback para `npm install`. Uma release carrega um único tarball `.tgz`, calcu
228
400
  o SHA-256 desse mesmo artefato e vincula o tarball e o GitHub Release ao
229
401
  `TARGET_SHA` completo; um segundo pack não é intercambiável.
230
402
 
231
- ## Validação em sandbox (V1/V2)
403
+ ## Validação em sandbox (V2)
232
404
 
233
- O `scripts/test-opencode-v1-v2-sandbox.sh` valida o pacote instalado
405
+ O `scripts/test-opencode-v2-sandbox.sh` valida o pacote instalado
234
406
  globalmente como um usuário real dentro de um sandbox isolado (com `HOME`,
235
407
  prefix npm e venv próprios) — nunca o ambiente de desenvolvimento. Ele verifica
236
- OpenCode V1 (`opencode`) e V2 (`opencode2`) lado a lado: binários, conectividade
237
- MCP, `doctor` e — com `--prompts` — uma bateria de prompts cobrindo o recurso
238
- `pantheon://agents`, memory store/recall, escrita no filesystem e delegação de
239
- agente. O gate é fail-closed: todo check obrigatório precisa terminar em PASS
240
- explícito; timeout, falha de auth/rede/provider e pré-requisitos ausentes
241
- bloqueiam a execução.
408
+ a perna OpenCode V2: o binário, conectividade MCP, `doctor` e — com
409
+ `--prompts` — uma bateria de prompts cobrindo o recurso `pantheon://agents`,
410
+ memory store/recall, escrita no filesystem e delegação de agente. O gate é
411
+ fail-closed: todo check obrigatório precisa terminar em PASS explícito;
412
+ timeout, falha de auth/rede/provider e pré-requisitos ausentes bloqueiam a
413
+ execução.
414
+
415
+ "V2" aqui se refere somente ao canário de hooks observado em um host OpenCode
416
+ v2.0.18, no qual ao menos um callback testado foi disparado; isso não
417
+ estabelece compatibilidade com o SDK estável `@opencode/plugin@2.0.18` nem com
418
+ o contrato 2.x completo. Esta branch ainda fixa a dependência transitória
419
+ `@opencode-ai/plugin@1.18.30`. Em hosts com `opencode` e `opencode2`, este
420
+ último costuma ser um shim que executa o mesmo binário; a comparação lado a
421
+ lado anterior, portanto, não provava nada sobre o binário em si. O projeto é
422
+ exclusivo V2, portanto há uma única perna.
242
423
 
243
424
  ```bash
244
- scripts/test-opencode-v1-v2-sandbox.sh --prepare # tarball + install + init no sandbox
245
- scripts/test-opencode-v1-v2-sandbox.sh --run v1 --prompts # validação base + bateria de prompts (V1)
246
- scripts/test-opencode-v1-v2-sandbox.sh --run v2 # apenas validação base (V2)
247
- scripts/test-opencode-v1-v2-sandbox.sh --prompts # bateria de prompts para as duas versões
248
- scripts/test-opencode-v1-v2-sandbox.sh --reset # limpa a raiz do sandbox
425
+ scripts/test-opencode-v2-sandbox.sh --prepare # tarball + install + init no sandbox
426
+ scripts/test-opencode-v2-sandbox.sh --run v2 # apenas validação base
427
+ scripts/test-opencode-v2-sandbox.sh --prompts # validação base + bateria de prompts
428
+ scripts/test-opencode-v2-sandbox.sh --rehydrate # sondas offline de rehydration/summary de sessão
429
+ scripts/test-opencode-v2-sandbox.sh --hooks # canário de callbacks de hooks V2
430
+ scripts/test-opencode-v2-sandbox.sh --rehydrate --hooks # executa os dois canários
431
+ scripts/test-opencode-v2-sandbox.sh --reset # limpa a raiz do sandbox
249
432
  ```
250
433
 
251
- Os modos são combináveis (ex.: `--prepare --run v1 --prompts`). Os binários são
252
- resolvidos estritamente dentro do prefix npm do sandbox — um sandbox não
253
- preparado falha rápido em vez de testar silenciosamente a instalação do host.
434
+ Os modos são combináveis (ex.: `--prepare --run v2 --prompts`). `--rehydrate`
435
+ executa sondas offline de `context_rehydrate` e `context_session_summary`.
436
+ `--hooks` executa um canário de hooks V2 com o binário do sandbox para verificar
437
+ se os callbacks de hooks são disparados; ele não testa os efeitos dos callbacks
438
+ de transform nem comprova o enforcement de segurança `execute.before` do
439
+ Pantheon. Com o par de sondas `--rehydrate --hooks` (sem `--run`, `--prompts` ou
440
+ `--cost`), o canário de hooks ainda é executado se a rehydration falhar, e o
441
+ comando retorna falha em seguida. Esses canários de teste/sandbox não são prova
442
+ de enforcement de segurança do Pantheon. Os binários são resolvidos estritamente
443
+ dentro do prefix npm do sandbox — um sandbox não preparado falha rápido em vez
444
+ de testar silenciosamente a instalação do host.
254
445
 
255
446
  Isso valida somente o sandbox isolado e preparado. Um PASS não prova suporte
256
447
  para todo host real nem para configurações de host que não foram exercitadas.
257
448
 
449
+ ## Benchmark de latência (bench/)
450
+
451
+ O `bench/` mede a latência de sessão de ponta a ponta do CLI `opencode`
452
+ instalado com o plugin V2 do repositório — o baseline contra o qual toda
453
+ mudança de performance de uma release deve ser comparada. Executa dois
454
+ cenários N vezes cada, intercalados (não-interativo, um diretório de sandbox
455
+ novo por run), coleta métricas por run do `opencode.db` em modo READ-ONLY
456
+ (tokens root + sessões filhas sem dupla contagem, tool calls por nome, número
457
+ de sessões filhas) e tempos de hook das linhas `[bench]` que o plugin anexa ao
458
+ `hooks.log`:
459
+
460
+ ```bash
461
+ node bench/bin/bench.mjs # 5 runs por cenário (A e B), ~1h
462
+ BENCH_MODEL=opencode-go/glm-5.3-flash node bench/bin/bench.mjs # fixar modelo
463
+ node bench/bin/bench.mjs --runs 1 # smoke: um run por cenário
464
+ ```
465
+
466
+ Os resultados vão para `bench/results/<label>-<git-sha>.json` (mediana +
467
+ p80 + falhas por cenário); o label padrão é `baseline` e o harness recusa
468
+ sobrescrever um resultado existente, então a identidade do run fica no nome do
469
+ arquivo. O cenário A faz pesquisa web real, então a variância de rede é
470
+ registrada por run.
471
+
472
+ ### Perfis de medição (explícitos, nunca inferidos)
473
+
474
+ As instruções são injetadas por duas superfícies: o diretório de config global
475
+ e o diretório do projeto. O harness declara qual delas exercita, porque um
476
+ resultado só significa algo no perfil onde a mudança atua:
477
+
478
+ | `--profile` | `AGENTS.md` global | `AGENTS.md` de projeto | Uso |
479
+ |---|---|---|---|
480
+ | `host` (padrão) | diretório de config do host (ou `--global-agents`) | nenhum — run dirs ficam vazios | a injeção real do host, sem alteração |
481
+ | `double-injection` | diretório de config do host (ou `--global-agents`) | `--project-agents`, escrito em cada run dir | o perfil no repo onde global+projeto se sobrepõem |
482
+
483
+ O padrão mede os cenários A e B. Use `--scenarios B` para isolar o claim
484
+ one-shot de F1; o cenário selecionado ainda roda N vezes (`--runs 5` por
485
+ padrão).
486
+
487
+ ```bash
488
+ # braço candidato: artefato global carveado + artefato de projeto carveado
489
+ node bench/bin/bench.mjs --runs 5 --scenarios B --profile double-injection \
490
+ --global-agents AGENTS.global.md --project-agents AGENTS.md --label f1-candidate
491
+ ```
492
+
493
+ Cada braço registra, por run e lido do banco, a identidade (caminho, bytes,
494
+ sha256) de cada arquivo de instrução que a sessão de fato carregou
495
+ (`instruction_state` + `instruction_blob`) — a prova de fidelidade de que o
496
+ que foi medido é o que foi gerado. Um claim só pode se apoiar num run cuja
497
+ provenance mostre que os artefatos global **e** de projeto pretendidos foram
498
+ carregados.
499
+
500
+ ### Sinal vs ruído
501
+
502
+ Wall time é pista, não critério: o spread same-day chega a ~8× no cenário A e
503
+ ~13× no B. Um efeito só é **confirmado** quando excede o spread same-day (ou
504
+ exige N maior); caso contrário é registrado como **inconclusivo**. Prefira
505
+ medianas de tokens, bem mais estáveis. O wall do cenário A não é métrica de
506
+ claim — ele faz pesquisa web real, então a variância de rede domina.
507
+
508
+ ### Proxy do 1º request e evidência de F1
509
+
510
+ O payload de instruções injetado só incide no primeiro request, então o
511
+ `tokens.input` total da árvore (somado em todo turno) é dominado pela variância
512
+ de duração da sessão. Cada run também registra `firstRequest` — o
513
+ `tokens.input` + `tokens.cache.read` da primeira linha assistant — o proxy que
514
+ isola o payload.
515
+
516
+ Uma rodada intercalada no OpenCode v2.0.29 (C1/K1…C5/K5, N=5/braço) mediu o
517
+ contexto do 1º request em 17555 tokens no controle e 15489 na candidata
518
+ (**−2066, −11,8%**; spread intra-braço de 14 tokens em cada braço). D4 confirmou
519
+ 22350 B carregados no controle e 13400 B na candidata (−8950 B, −40,0%); o
520
+ oráculo pré-registrado passou em 5/5 nos dois braços. O efeito no primeiro
521
+ request está confirmado contra o spread intra-braço; a aceitação final de F1
522
+ aguarda revisão do Themis. O input total da árvore caiu da mediana de 47594 para
523
+ 38253 tokens, mas os ranges se sobrepõem e a hipótese de ≤30k não foi atingida.
524
+ As medianas de wall foram 30,078 s e 24,130 s, com spread alto; input total e
525
+ wall permanecem **inconclusivos**. Não há claim de ganho de wall ou custo
526
+ monetário. Detalhes e artefatos por run:
527
+ `bench/results/f1-di-v229-interleaved-2026-10-14.md`. O par sequencial anterior
528
+ permanece somente como evidência de apoio em
529
+ `bench/results/f1-di-v229-clean-2026-10-14.md`. As rodadas exploratórias
530
+ anteriores foram preservadas separadamente em
531
+ `bench/results/f1-double-injection.md` e
532
+ `bench/results/f1-di-v229-preliminary-2026-10-14.md`.
533
+
534
+
535
+ ## Cobertura TypeScript do Plugin V2
536
+
537
+ `npm run coverage:plugin-v2` executa a suíte `tests/pantheon/*.test.ts` com a
538
+ cobertura nativa do Node habilitada para source maps e exige pelo menos 80% de
539
+ cobertura de linhas somente para `src/plugin-v2.ts`. Requer Node `v24.15.0`;
540
+ coberturas de branches e funções são informativas, não gates. Isso não é uma
541
+ alegação de cobertura do repositório inteiro.
542
+
258
543
  Variáveis de ambiente:
259
544
 
260
545
  | Variável | Padrão | Finalidade |
261
546
  |----------|---------|---------|
262
547
  | `PANTHEON_SANDBOX_ROOT` | `~/pantheon-sandbox` | Raiz do sandbox (recusada se insegura para `--reset`) |
263
- | `OPENCODE_V1_SPEC` | `opencode-ai@1.18.18` | Spec npm que fornece o binário `opencode` |
548
+ | `OPENCODE_V1_SPEC` | `opencode-ai@1.18.18` | Configura somente o plugin V1; o runner de sandbox exclusivo V2 não consome nem oferece suporte a essa variável |
264
549
  | `OPENCODE_V2_SPEC` | `@opencode-ai/cli@beta` | Spec npm que fornece o binário `opencode2` |
265
550
  | `PANTHEON_SANDBOX_MODEL` | `opencode-go/mimo-v2.5` | Modelo usado pelo init e pelos prompts |
266
551
  | `PANTHEON_PROMPT_TIMEOUT` | `300` | Timeout por prompt em segundos |
@@ -271,7 +556,7 @@ preparado.
271
556
 
272
557
  ### Divergência intencional do memory MCP
273
558
 
274
- `scripts/memory_mcp_server.py` e `src/mcp/memory_mcp_server.py` são
559
+ `scripts/memory_mcp.py` e `src/mcp/memory_mcp.py` são
275
560
  intencionalmente diferentes. A cópia independente em `scripts/` mantém o
276
561
  contrato leve de `memory_*`; a cópia instalada em `src/mcp/` também expõe o
277
562
  schema opcional de codemap e `code_index`, `code_query` e `code_neighbors`. As
@@ -295,10 +580,10 @@ uma issue ou pull request.
295
580
 
296
581
  ## Citação e DOI
297
582
 
298
- O Pantheon é distribuído sob a [Licença MIT](LICENSE). Para o registro histórico
299
- publicado da v1.4.3 apenas, use o [DOI do Zenodo](https://doi.org/10.5281/zenodo.22306637);
300
- essa não é a versão operacional atual. Os metadados de citação também estão em
301
- [CITATION.cff](CITATION.cff).
583
+ O Pantheon é distribuído sob a [Licença MIT](LICENSE). Cite o
584
+ [DOI conceitual do Zenodo](https://doi.org/10.5281/zenodo.22650136), que sempre
585
+ resolve para a última release arquivada; cada release também tem seu próprio
586
+ version DOI. Os metadados de citação também estão em [CITATION.cff](CITATION.cff).
302
587
 
303
588
  Repositório canônico: <https://github.com/ils15/pantheon-opencode>
304
589
 
@@ -8,8 +8,10 @@
8
8
  * installOpenCode() from scripts/install/opencode.mjs.
9
9
  *
10
10
  * Dual-version install (Phase 3): the generated config is V1-shaped and valid
11
- * under BOTH OpenCode V1 (`opencode` 1.18.x) and V2 (`opencode2`
12
- * v0.0.0-next-17444). V2 reads the same config locations and normalizes V1
11
+ * under BOTH OpenCode V1 (`opencode` 1.18.x) and V2 (`opencode2`, OpenCode 2.x —
12
+ * `opencode2 --version` prints "opencode v2.0.22"; an early 2.x prerelease
13
+ * printed "0.0.0-next-17444", which is history and not a host observation).
14
+ * V2 reads the same config locations and normalizes V1
13
15
  * fields in memory — no native V2 conversion. `--version v2` labels the
14
16
  * install for the operator; state isolation is a runtime concern
15
17
  * (OPENCODE_DB ~/.local/share/opencode/opencode-v2.db, service port 49375).
@@ -54,6 +56,9 @@ function printUsage() {
54
56
  console.log(' npx pantheon-opencode init --components agents,skills,instructions')
55
57
  console.log(' npx pantheon-opencode init --opencode-version v1|v2|auto')
56
58
  console.log(' npx pantheon-opencode init --preset <name> # Install and activate model preset')
59
+ console.log(
60
+ ' npx pantheon-opencode init --merge-dev-config <path> # Merge a dev config (off by default)',
61
+ )
57
62
  console.log(' npx pantheon-opencode set-tier <name> # Set active model preset (global)')
58
63
  console.log(
59
64
  ' npx pantheon-opencode update [--stable] # Update package + re-run init (default: beta channel)',
@@ -287,6 +292,7 @@ async function main() {
287
292
  '--version',
288
293
  '--opencode-version',
289
294
  '--components',
295
+ '--merge-dev-config',
290
296
  ])
291
297
  for (let i = 1; i < args.length; i++) {
292
298
  const arg = args[i]
@@ -368,6 +374,22 @@ async function main() {
368
374
  }
369
375
  }
370
376
 
377
+ // --merge-dev-config <path> opts IN to merging a contributor's personal
378
+ // OpenCode config into the generated one. Only third-party plugin/provider/
379
+ // compaction entries are merged; Pantheon-owned entries are always stripped.
380
+ // Absent this flag no repository-root config is read (product defaults come
381
+ // from the installer code, never from a dev checkout).
382
+ const mergeDevConfigIndex = args.indexOf('--merge-dev-config')
383
+ const inlineMergeDevConfig = args.find((arg) => arg.startsWith('--merge-dev-config='))
384
+ const mergeDevConfigOpt =
385
+ mergeDevConfigIndex >= 0
386
+ ? (args[mergeDevConfigIndex + 1] ?? null)
387
+ : (inlineMergeDevConfig?.split('=', 2)[1] ?? null)
388
+ if (mergeDevConfigIndex >= 0 && mergeDevConfigOpt === null) {
389
+ console.error('❌ --merge-dev-config requires a file path')
390
+ process.exit(1)
391
+ }
392
+
371
393
  const components = requestedComponents ?? [
372
394
  'agents',
373
395
  'skills',
@@ -402,7 +424,8 @@ async function main() {
402
424
  model: modelOpt,
403
425
  smallModel: smallModelOpt,
404
426
  preset: presetOpt,
405
- version: versionOpt ?? 'v1',
427
+ version: versionOpt ?? 'auto',
428
+ mergeDevConfig: mergeDevConfigOpt,
406
429
  })
407
430
  } catch (err) {
408
431
  if (err?.message === 'Canceled') {
@@ -15,7 +15,13 @@ agent: "zeus"
15
15
  ## Layers
16
16
 
17
17
  ### Layer 1 — Heuristic Scan
18
- `python3 scripts/themis_heuristic_scan.py [--path=<dir>]`
18
+ Resolve the installed helper first (do not assume the current project contains
19
+ Pantheon source). Check, in order: `$OPENCODE_CONFIG_DIR/.opencode/scripts/`,
20
+ `$OPENCODE_CONFIG_DIR/scripts/`, `${XDG_CONFIG_HOME:-$HOME/.config}/opencode/scripts/`,
21
+ `$HOME/.opencode/scripts/`, `.opencode/scripts/`, then
22
+ `$(npm root -g)/pantheon-opencode/scripts/`. Resolve the first existing file to
23
+ an absolute path and run `python3 "$helper" --path="$PWD"`; if none exists,
24
+ report the helper as missing and stop Layer 1 rather than claiming it passed.
19
25
  Zero tokens, <2s. Checks: ruff, biome, anti-pattern slop, anti-overengineering (YAGNI), hash-anchored edits. Returns score 0-100 + APPROVED/BLOCKING.
20
26
 
21
27
  ### Layer 2 — Themis Deep Review
@@ -1,6 +1,6 @@
1
1
  ---
2
2
  description: "Merge and consolidate memory entries"
3
- agent: zeus
3
+ agent: mnemosyne
4
4
  ---
5
5
 
6
6
  Merge related memory entries and consolidate duplicates:
@@ -15,8 +15,15 @@ Structured, checkpointed workflow for complex multi-step tasks spanning multiple
15
15
  ## Workflow
16
16
 
17
17
  ```
18
- Phase 0: SCOPING
19
- └─ Zeus + Athena define scope, phases, acceptance criteria → PLAN.md
18
+ Phase 0: PLAN AND APPROVAL
19
+ └─ @athena returns the complete, detailed Markdown plan to Zeus
20
+ └─ Zeus publishes the full plan as a normal message in the main conversation (not only in the child-agent transcript)
21
+ └─ GATE 1: open the approval UI only after that plan message is visible; never bundle or reverse the two
22
+ └─ If the runtime cannot guarantee that order, ask for approval in plain text after the plan and wait
23
+ └─ Wait for explicit approval or requested changes
24
+ └─ For requested changes, redisplay the entire revised plan and repeat Gate 1
25
+ └─ Do not start discovery or implementation before approval
26
+ └─ After approval, persist the approved plan as PLAN.md through the artifact workflow
20
27
 
21
28
  Phase 1: DISCOVERY
22
29
  └─ @apollo maps relevant codebase areas → DISCOVERY.md
@@ -44,7 +51,11 @@ Usage: --resume <slug> | --status <slug> | --list
44
51
 
45
52
  ## Full-Auto Mode (`--full-auto`)
46
53
 
47
- > ⚠️ Bypasses human review gates. Tier 1 gates (plan, commit, deploy) still require approval.
54
+ > ⚠️ Automates only eligible review gates. Gate 1 and commit/deploy gates still require approval.
55
+
56
+ `--full-auto` does not hide the plan or skip Gate 1: Zeus still displays the
57
+ complete plan in the main conversation and waits for explicit approval before
58
+ discovery or implementation. It only affects the later gates described below.
48
59
 
49
60
  **Themis auto-approves non-blocking reviews** — only stops on **BLOCKING** verdict. No waiting between phases. Checkpoints saved at every boundary.
50
61