pantheon-opencode 1.6.0-beta.5 → 1.6.0-beta.7

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 (62) hide show
  1. package/AGENTS.md +27 -820
  2. package/CHANGELOG.md +130 -0
  3. package/README.md +205 -30
  4. package/README.pt-BR.md +47 -23
  5. package/package.json +10 -5
  6. package/plugin.json +1 -1
  7. package/pyproject.toml +3 -1
  8. package/scripts/build-agents-md.mjs +162 -28
  9. package/scripts/doctor.mjs +104 -22
  10. package/scripts/install/agents-md.mjs +2 -2
  11. package/scripts/install/config-migration.mjs +154 -7
  12. package/scripts/install/opencode.mjs +202 -40
  13. package/scripts/install/shared.mjs +115 -7
  14. package/scripts/install/strings.mjs +8 -0
  15. package/scripts/probe-pantheon-cost.mjs +16 -3
  16. package/scripts/run-node-tests.mjs +189 -0
  17. package/scripts/sync-artifacts.mjs +2 -2
  18. package/scripts/test-opencode-v2-sandbox.sh +820 -86
  19. package/skills-lock.json +6 -5
  20. package/src/agents/aphrodite.md +17 -28
  21. package/src/agents/athena.md +1 -0
  22. package/src/agents/demeter.md +8 -18
  23. package/src/agents/hephaestus.md +10 -11
  24. package/src/agents/hermes.md +15 -30
  25. package/src/agents/iris.md +1 -0
  26. package/src/agents/nyx.md +1 -0
  27. package/src/agents/prometheus.md +16 -10
  28. package/src/agents/talos.md +4 -1
  29. package/src/agents/themis.md +5 -3
  30. package/src/agents/zeus.md +17 -280
  31. package/src/instructions/agent-return-format.instructions.md +4 -50
  32. package/src/instructions/backend-standards.instructions.md +2 -0
  33. package/src/instructions/frontend-standards.instructions.md +3 -1
  34. package/src/instructions/memory-protocol.instructions.md +12 -121
  35. package/src/instructions/zeus-anti-stall.instructions.md +8 -111
  36. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  37. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  38. package/src/instructions/zeus-timeout-retry.instructions.md +9 -130
  39. package/src/pantheon/secret-scanner.ts +489 -0
  40. package/src/pantheon/v2-delegation-enforce.ts +86 -0
  41. package/src/pantheon/v2-execute-after.ts +186 -0
  42. package/src/pantheon/v2-unsupported.mjs +0 -23
  43. package/src/plugin-v2.ts +254 -102
  44. package/src/plugins/pantheon-hooks.ts +82 -35
  45. package/src/plugins/tui/README.md +14 -0
  46. package/src/plugins/tui/dist/tui.d.ts +11 -8
  47. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  48. package/src/plugins/tui/dist/tui.js +102 -62
  49. package/src/plugins/tui/package-lock.json +30 -33
  50. package/src/plugins/tui/package.json +5 -1
  51. package/src/plugins/tui/src/index.tsx +163 -107
  52. package/src/plugins/tui/tsdown.config.ts +17 -0
  53. package/src/routing.yml +12 -9
  54. package/src/skills/README.md +9 -4
  55. package/src/skills/agent-coordination/SKILL.md +13 -83
  56. package/src/skills/artifact-management/SKILL.md +12 -5
  57. package/src/skills/auto-continue/SKILL.md +38 -28
  58. package/src/skills/code-review-checklist/SKILL.md +5 -5
  59. package/src/skills/council-synthesis/SKILL.md +29 -0
  60. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  61. package/scripts/hooks/scan-secrets.sh +0 -97
  62. package/src/instructions/zeus-council-synthesis.instructions.md +0 -299
package/CHANGELOG.md CHANGED
@@ -18,6 +18,136 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/).
18
18
 
19
19
  ## ✅ Closed Issues
20
20
 
21
+ ## [v1.6.0-beta.7] - 2026-10-10
22
+
23
+ <!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
24
+ move this section to a versioned entry and reset the template below. -->
25
+
26
+ ## 🆕 What's New
27
+
28
+ - **Simpler agent dispatch:** answer no-change questions directly, send bounded
29
+ fixes to one specialist, load council instructions on demand, and remove
30
+ routine per-task KV/cache routing. No token, cost, or latency savings are
31
+ claimed without live measurements.
32
+ - **V2 install and permissions:** use a versioned package-root plugin pin and
33
+ migrate V1 `task`/`write` permissions to V2 `subagent`/`edit`, retaining the
34
+ stricter effect when rules collide.
35
+ - **Release and runtime hardening:** bounded in-process secret scanning,
36
+ fail-closed V2 registration, TUI timer disposal, truthful doctor reporting,
37
+ and guarded V2 sandbox prepare/reset.
38
+
39
+ ## 🐞 Fixed
40
+
41
+ - TUI usage polling now starts only after its optional slot registers and all
42
+ refresh timers are disposed on shutdown.
43
+ - Doctor detects version drift in string and object V2 package pins, including
44
+ prerelease versions; checkout installs warn when their exact npm pin is not
45
+ published yet.
46
+ - V2 permission migration maps `task → subagent` and `write → edit` and
47
+ preserves the stricter conflicting rule.
48
+
49
+ ## ⚠️ Known Issues
50
+
51
+ - Live provider E2E is blocked by HTTP 403; an interactive model-backed V2 TUI
52
+ turn remains unverified.
53
+ - The V2 tool canary targets OpenCode 2.0.22 while the installable CLI differs
54
+ (issue #216); V1 host end-to-end validation is also deferred.
55
+ - The observed P0-4 tool-catalog oscillation has no reproduced cause; its
56
+ reproduction harness remains follow-up work.
57
+ - V2 `init` from an unpublished source checkout writes a versioned npm pin that
58
+ cannot resolve until that version is published; the installer warns.
59
+ ## [v1.6.0] - 2026-10-10
60
+
61
+ This stable candidate consolidates the beta.1–beta.6 changes. The original beta
62
+ entries remain below as historical records so release detail is not discarded.
63
+
64
+ ## 🆕 What's New
65
+
66
+ - **OpenCode V2 plugin and installer path:** generation detection, V2 plugin
67
+ registration, three functional V2 tools, read-only enforcement, and explicit
68
+ reporting of the smaller V2 feature surface. The V1 API path remains in the
69
+ package, but no V1 host has been exercised end-to-end in this release.
70
+ - **Sandbox validation and release hardening:** fail-closed checks, V2 MCP and
71
+ hook probes, package/version inventory validation, and reproducible package
72
+ evidence. The sandbox now generates its runner, isolated TUI launcher, and
73
+ README during `--prepare`.
74
+ - **Dependency and TUI maintenance:** synchronized release manifests, updated
75
+ dependency/security overrides, and TUI/runtime consistency checks.
76
+ - **Simpler agent dispatch path:** no-change questions can be answered directly;
77
+ bounded fixes route to one specialist; council guidance is loaded on demand;
78
+ and default routing no longer makes per-task KV/cache lookups. Synthetic
79
+ timeout/session behavior unsupported by the host was removed. These changes
80
+ simplify the prompt and dispatch path; this release makes no measured token,
81
+ cost, or latency improvement claim.
82
+
83
+ ## 🐞 Fixed
84
+
85
+ - `PANTHEON_V2_MCP_LIST_TIMEOUT` now defaults to 15 seconds in both the harness
86
+ and generated `run-test.sh`, including under `set -u`; the default does not
87
+ depend on an exported environment variable.
88
+ - `PANTHEON_REPO` is resolved consistently for prepare, generated tests, and
89
+ reset guards. Relative, dangling, missing, or non-Pantheon paths fail before
90
+ packaging; `.repo-dir` is atomically written and validated before use.
91
+ - Sandbox prepare/reset reject roots overlapping a checkout or the user's
92
+ `HOME`. `PANTHEON_V2_PORT` defaults to 49376, is range-checked, and refuses an
93
+ occupied port without reusing or stopping the existing service.
94
+ - Sandbox `tmp/` is not blanket-deleted: prepare only expires hash-named Node
95
+ compile-cache files owned by the current user and older than 30 days. Runtime
96
+ state, unknown entries, and handoff/evidence files remain untouched.
97
+ - **V2 plugin registration is stable across install locations.** `init` now
98
+ writes the exact `pantheon-opencode@<version>` npm entry and the package root
99
+ exports the V2 plugin. This replaces absolute paths into a global prefix or
100
+ transient `npx` cache; `doctor` recognizes the pinned package and reports
101
+ version drift. A clean production-only package consumer test covers the root
102
+ export.
103
+ - **V1-to-V2 permissions preserve their intended actions.** Migration maps
104
+ `task` to V2 `subagent` and `write` to the `edit` action that also governs
105
+ `write`/`patch`. If V1 `edit` and `write` rules collide on one resource, the
106
+ more restrictive effect wins. Tests cover global and nested agent rules.
107
+ - **`doctor` distinguishes SQLite readiness from tool registration.** The
108
+ `node:sqlite` check now says it verifies only the backend prerequisite, not
109
+ whether `pantheon_cost` registered on the active host.
110
+ - **Release documentation was reconciled with current code.** The V2 caller /
111
+ target matrix is enforced by `permission.evaluate`; the bridge export is an
112
+ importable utility but is not wired into production; the V2 event count and
113
+ package registration format are corrected in both READMEs and the install /
114
+ upgrade guides.
115
+
116
+ ## ⚠️ Known Issues
117
+
118
+ - **V1 host canary is deferred.** The tested package dependency pair is
119
+ `@opencode-ai/plugin@1.18.33` + `@opencode-ai/sdk@1.18.33`; this is not an
120
+ end-to-end V1 host compatibility claim. No OpenCode `1.18.35` host support is
121
+ asserted.
122
+ - **V2 support remains partial.** The tool canary was authored against
123
+ `opencode 2.0.22`; the installable CLI has drifted from that canary contract
124
+ (tracked in issue #216). See the README compatibility table for the measured
125
+ evidence and limitations.
126
+ - **Release validation is not complete.** Live provider E2E returned HTTP 403,
127
+ the interactive V2 TUI/model-backed turn has not been verified, and the
128
+ previously observed within-session tool-catalog oscillation (P0-4) still has
129
+ no reproduced cause. This candidate must not be published until the host
130
+ validation gates are resolved or explicitly waived.
131
+ - **V2 init from an unpublished source checkout cannot bootstrap its own npm
132
+ pin.** It writes the exact package version and emits a warning; OpenCode
133
+ cannot resolve that version until it is published. This is limited to
134
+ running the installer from the repository checkout. After publication, use
135
+ the npm-installed or `npx` installer for the supported consumer path.
136
+
137
+ ## [v1.6.0-beta.6] - 2026-10-05
138
+
139
+ &lt;!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
140
+ move this section to a versioned entry and reset the template below. --&gt;
141
+
142
+ ## 🆕 What's New
143
+
144
+ - **Política de suporte documentada: a linha 1.6.x é a ÚLTIMA compatível com OpenCode 1.X.** A partir de **1.7, toda release é breaking change com alvo em OpenCode 2.** O limite está escrito no `README.md` (seção "Compatibility and support policy", com matriz de suporte) e em `docs/INSTALLATION.md` (seção "OpenCode V1/V2 — contrato de plugin"), não duplicado em um documento novo: os dois arquivos já eram o ponto de entrada do contrato de plugin, e um terceiro documento seria um terceiro lugar para divergir. O texto distingue as duas células da linha 1.6.x — a célula 1.X é o contrato V1 (6 tools, lifecycle do board, hooks V1, compaction V1) e a célula OpenCode 2 é o contrato V2, que é real porém **menor**: 3 tools, sem as `pantheon_goal_*` e sem a matriz de delegação caller→target. **O suporte a OpenCode 2 na linha 1.6 é documentado como parcial, e não como completo**, por duas razões verificadas: (a) o canário de ferramentas V2 foi escrito contra `opencode 2.0.22`, host que não é publicado em nenhum canal npm — contra o `@opencode-ai/cli` instalável o mesmo canário falha 12/12, porque `/api/experimental/session/{id}/wait` foi promovido para `/api/session/{id}/wait` (404 no caminho antigo) e `ctx.tool.list` não existe mais; corrigindo apenas a rota, 10/12 passam no mesmo host, o que caracteriza descasamento canário/host e não regressão medida do plugin (issue #216, PR #213); (b) não existe perna V1 de validação end-to-end — `scripts/test-opencode-v2-sandbox.sh` é V2-only e rejeita `--run v1` — portanto a versão exata de host 1.X exercitada end-to-end pela linha 1.6 fica registrada como **não verificada**, e o caminho 1.X é sustentado pelo pin de dependência (`@opencode-ai/plugin` / `@opencode-ai/sdk` `1.18.33`), pelos testes unitários do gate de geração e pelos testes end-to-end do installer sobre a config emitida.
145
+
146
+ ## 🐞 Fixed
147
+
148
+ - **Os exemplos de chamada MCP nos arquivos de prompt ensinavam um contrato que não existe no schema real.** Um `pantheon-persistence.kv_get` ao vivo foi rejeitado com `namespace: Missing key`; a linha que o produziu foi `src/agents/zeus.md:189` (`depth = kv_get("deleg:depth") ?? 0`), cuja cópia instalada em `~/.config/opencode/agents/zeus.md` é a que executou. A causa não era o servidor MCP: os arquivos de agente e de instrução ensinavam chamadas posicionais sem `namespace`, enquanto o schema real é `kv_get({ namespace /* obrigatório, sem default */, key, scope? })` — `kv_store.namespace` é igualmente obrigatório e `kv_store.value` é `str`. **A correção está nos docs, e não em adicionar um `namespace` default:** um default escreveria estado de coordenação no namespace errado silenciosamente, então *obrigatório* é o desenho correto. A mesma classe de defeito foi corrigida em `context_save` (posicional, com um helper `json()` inexistente e sem o `session_id` obrigatório → forma por palavra-chave com `content=JSON.stringify(...)`), em `memory_store` (`value` precisa ser uma string JSON codificada → agora iguala o padrão já correto de `metadata`, o que resolveu uma aut contradição no mesmo arquivo), na aritmética de profundidade (envolvida em `String(...)`, porque `kv_store.value` é `str` e não `int`) e em `memory_search(query, ...)` → `query=` em todas as instâncias. `AGENTS.md` é artefato gerado e foi reconstruído, nunca editado à mão.
149
+ - **Um bypass de permissão vivo: `edit: deny` não cobria `hashline_edit`.** A regra `edit: deny` é avaliada por nome de ferramenta, e `hashline_edit` não é `edit` — então os agentes restritos a `edit: deny` (`zeus`, `athena`, `iris`, `nyx`, `themis`) podiam editar arquivos assim mesmo, escrevendo no disco por um caminho que a negação não cobria. `hashline_edit: deny` foi adicionado a esses cinco agentes. **Não era uma condição de corrida nem um erro de configuração: era uma tabela de permissões incompleta**, o que significa que a negação nunca esteve de fato aplicada a quem só deveria ler.
150
+ - **`test:node` reportava sucesso tendo coletado zero testes.** `node --test <glob>` sai com 0 quando o glob não expande (Node >= 22), e foi exatamente o que aconteceu: um glob que nunca expandiu produziu um gate verde que não executou nada. Pior, `tests/` estava ausente da allow-list `files` do pacote, então um consumidor que rodasse `npm test` recebia esse verde. Agora os scripts de teste falham em voz alta quando a coleta é zero, e a guarda tem teste próprio (`tests/run-node-tests.test.mjs`) que a dirige como subprocesso — o contrato é o código de saída, então testá-la em processo não provaria nada.
21
151
  ## [v1.6.0-beta.5] - 2026-10-05
22
152
 
23
153
  &lt;!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
package/README.md CHANGED
@@ -31,7 +31,9 @@ way to plan work, make progress, check results, and keep useful project context.
31
31
  ## Start in 2 minutes
32
32
 
33
33
  Requirements: [OpenCode 1.18.4+](https://opencode.ai/docs/) and Node.js
34
- 22.22.2+ (or 24.15.0+ / 26+).
34
+ 22.22.2+ (or 24.15.0+ / 26+). For which OpenCode generation each Pantheon
35
+ release line supports, see
36
+ [Compatibility and support policy](#compatibility-and-support-policy).
35
37
 
36
38
  Pantheon declares `engines.node` as `^22.22.2 || ^24.15.0 || >=26.0.0`. The
37
39
  floor reflects what the dependency tree actually needs — the transitive
@@ -62,6 +64,13 @@ Once OpenCode is running, describe the outcome you want:
62
64
  ```
63
65
 
64
66
  Pantheon helps turn that request into a plan and a sequence of reviewed steps.
67
+ For questions that do not require repository changes, Zeus answers directly;
68
+ small, reversible fixes use one specialist dispatch. Discovery, planning,
69
+ parallel work, and council review are reserved for tasks that benefit from them.
70
+
71
+ For a tiny, bounded repair, invoke `@talos` directly (for example,
72
+ `@talos fix this typo`). That skips the Zeus orchestration call; use `/pantheon`
73
+ for planning, delegation, multi-file work, or quality gates.
65
74
 
66
75
  ## Who is it for?
67
76
 
@@ -80,15 +89,96 @@ clear handoff between stages of work.
80
89
 
81
90
  ## Status
82
91
 
83
- Candidate version: the manifests in this checkout express the version being
84
- prepared, not a confirmed publication. A beta is published only after the
85
- Release workflow completes successfully. To check which version is actually
86
- published, consult the npm `beta` dist-tag. Pantheon is designed for OpenCode
92
+ Candidate version: **1.6.0-beta.7**. The manifests in this checkout express a
93
+ beta candidate, not a confirmed publication; beta publication happens only
94
+ after the explicit Release workflow completes successfully. To check the
95
+ published beta, consult the npm `beta` dist-tag. Pantheon is designed for OpenCode
87
96
  and depends on the availability and configuration of OpenCode and any optional
88
97
  services you choose to use. Check the
89
98
  [releases](https://github.com/ils15/pantheon-opencode/releases) and
90
99
  [changelog](CHANGELOG.md) for the latest published changes.
91
100
 
101
+ ## Compatibility and support policy
102
+
103
+ > ### ⚠️ 1.6.x is the LAST line that supports OpenCode 1.X
104
+ >
105
+ > **OpenCode 1.X support ends after the 1.6 line.** From **1.7 onward, every
106
+ > release is a breaking change targeting OpenCode 2.** A 1.6.x install is the
107
+ > last one that runs on an OpenCode 1.X host; do not plan an upgrade across the
108
+ > 1.6 → 1.7 boundary while your host is still on OpenCode 1.X.
109
+
110
+ | Pantheon line | OpenCode 1.X host | OpenCode 2 host |
111
+ |---|---|---|
112
+ | **1.6.x** (current line) | **Supported.** V1 plugin contract | Supported, reduced surface — V2 contract |
113
+ | **1.7 and later** | **Not supported.** Breaking change | Target of the 1.7+ work |
114
+
115
+ Both columns of the 1.6.x row are real, and they are not the same claim. Read
116
+ [the plugin contract](#opencode-v1v2--dual-version-160-beta1) for what each
117
+ generation actually registers.
118
+
119
+ ### What "supported on OpenCode 1.X" concretely means
120
+
121
+ On the 1.6 line, an OpenCode 1.X host gets the **V1 plugin**:
122
+ `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts`, registered under the
123
+ singular `plugin` config key. That surface registers 6 tools
124
+ (`hashline_edit`, the 3 `pantheon_goal_*` tools, `pantheon_cost`,
125
+ `pantheon_model`), the BackgroundJobBoard lifecycle, the V1 event/tool hooks and
126
+ the V1 compaction path. It is selected automatically: the generation gate
127
+ (`--opencode-version`, else `OPENCODE_VERSION`, else a `OPENCODE_BIN` basename of
128
+ `opencode2`, else a `--version` probe where major ≥ 2 selects V2) resolves a 1.X
129
+ host to V1.
130
+
131
+ The two generations are exclusive. The installer strips Pantheon references from
132
+ both config shapes and registers only the selected one, so a 1.X host never
133
+ loads the V2 plugin and a V2 host never loads the V1 plugin. Forcing V2 on a 1.X
134
+ host is an unsupported mixed/wrong-generation configuration, not a supported mode.
135
+
136
+ ### What the OpenCode 2 path is — and is not
137
+
138
+ **Not inert.** V2 registers the version-pinned npm package
139
+ `pantheon-opencode@<version>` (pinned to the installed Pantheon version); its
140
+ package-root export points to `src/plugin-v2.ts`.
141
+ It registers real tools with `input`/`output` schemas via
142
+ `ctx.tool.transform()`, five event subscriptions, session hooks, and tool/
143
+ permission hooks for read-only enforcement and the Pantheon caller→target
144
+ delegation matrix. For Pantheon-managed targets, Zeus may delegate to any
145
+ registered agent; Athena and Hermes may target Apollo only; other Pantheon
146
+ callers and unknown callers are denied. Child sessions cannot delegate to
147
+ Pantheon agents. Native/custom targets remain under host permissions. V2 never
148
+ adds an allow grant or overrides an explicit host deny; missing or mismatched
149
+ identity fails closed for a Pantheon delegation. The three goal tools remain
150
+ unsupported and are reported as `goal-tools`.
151
+
152
+ **Not complete either, and the V2 support claim is currently narrowed.** Two
153
+ facts, both recorded in this repository rather than smoothed over:
154
+
155
+ - **The host-backed V2 gate is red on the installable OpenCode CLI.** The V2 tool
156
+ canary (`tests/canary/plugin-v2-tool-canary.test.mjs`) was written against
157
+ `opencode 2.0.22`, which no npm channel publishes. Against the installable
158
+ `@opencode-ai/cli` host, `/api/experimental/session/{id}/wait` has been
159
+ promoted to `/api/session/{id}/wait` (the old path 404s) and `ctx.tool.list`
160
+ is absent, so the canary fails 12/12 there. That is a canary/host-generation
161
+ mismatch, not a measured plugin regression — with only the route renamed, 10/12
162
+ pass on the same host, including the edit being applied and the mutant still
163
+ caught. Tracked as [issue
164
+ #216](https://github.com/ils15/pantheon-opencode/issues/216); the fail-closed
165
+ CI change is [PR #213](https://github.com/ils15/pantheon-opencode/pull/213).
166
+ - **The 2.x host claims in `src/plugin-v2.ts` are measured against `2.0.22`
167
+ specifically**, not against the current installable CLI. Re-measurement
168
+ against the current host is outstanding and is tracked in the same issue.
169
+
170
+ Treat the 1.6 line's OpenCode 2 support as **real but partial**, and do not read
171
+ the 1.6.x row as "OpenCode 2 is finished".
172
+
173
+ ### Verified dependency and host evidence
174
+
175
+ | What | Verified against | How |
176
+ |---|---|---|
177
+ | V1 plugin API/generation checks | The dependency pair pinned by this release: `@opencode-ai/plugin@1.18.33` + `@opencode-ai/sdk@1.18.33` | `package.json`; generation-gate unit tests over injected host banners; installer end-to-end tests asserting the emitted `opencode.json` shape. This is not a claim that a V1 host was exercised end-to-end. |
178
+ | V2 plugin tool surface | `opencode 2.0.22` (the host the canary was written against) | `tests/canary/plugin-v2-tool-canary.test.mjs`, driving `hashline_edit` through a real `opencode serve` |
179
+ | V2 against the current installable CLI | **Not verified.** Canary fails 12/12; see issue #216 | — |
180
+ | Exact 1.X host version exercised end-to-end | **Unverified; V1 host canary deferred.** The sandbox runner is V2-only and `--run v1` is rejected | — |
181
+
92
182
  ## Delegation (native `task()`)
93
183
 
94
184
  Pantheon delegates exclusively through OpenCode's native `task()` child-session
@@ -98,6 +188,18 @@ there is no Pantheon-specific delegation tool surface to configure. See
98
188
  [ADR-0011](.pantheon/memory-bank/adr/0011-delegation-engine-contract.md) for the
99
189
  historical engine contract.
100
190
 
191
+ This 1.6.0-beta.7 candidate consolidates the final beta.6 follow-ups: safer
192
+ V2 installation and permission migration, bounded in-process secret scanning,
193
+ sandbox hardening, TUI lifecycle fixes, and a simpler agent dispatch path.
194
+ Zeus answers no-change questions directly and routes bounded fixes once; the
195
+ council procedure is loaded only for a council, without per-task KV/cache
196
+ lookups. Runtime call counts and latency have not been measured. Live provider
197
+ E2E and a model-backed interactive V2 TUI turn remain unverified.
198
+
199
+ Transient delegation dispatch failures get at most one retry. A refusal or
200
+ failed check is not repeated; after the retry fails, the configured fallback
201
+ chain applies once or Zeus escalates.
202
+
101
203
  ## Cost tool backend
102
204
 
103
205
  `pantheon_cost` prefers a read-only `node:sqlite` backend against the selected
@@ -187,8 +289,8 @@ per installation; V1 and V2 Pantheon plugins must never be registered together.
187
289
  | | V1 | V2 |
188
290
  |---|---|---|
189
291
  | OpenCode config key | singular `plugin` | plural `plugins` |
190
- | Pantheon registration | `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts` | `<installed>/src/plugin-v2` directory (`index.ts` re-exports `src/plugin-v2.ts`) |
191
- | Runtime contract | Pantheon V1 plugin: 6 tools (`hashline_edit`, the 3 goal tools, `pantheon_cost`, `pantheon_model`), event/tool hooks and V1 compaction handling | Full V2 plugin: 3 tools (`hashline_edit`, `pantheon_cost`, `pantheon_model`), 5 event subscriptions, session hooks (`prompt`, `context`), a read-only-enforcing tool `execute.before` hook, plus configuration transforms |
292
+ | Pantheon registration | `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts` | Version-pinned npm package `pantheon-opencode@<version>` (root export loads V2) |
293
+ | Runtime contract | Pantheon V1 plugin: 6 tools (`hashline_edit`, the 3 goal tools, `pantheon_cost`, `pantheon_model`), event/tool hooks and V1 compaction handling | V2 plugin: 3 Pantheon tools when required enforcement registers, 5 event subscriptions, session hooks (`prompt`, `context`), a read-only and secret-scanning `execute.before` hook, plus configuration transforms |
192
294
  | V1 APIs | Registered | Own tool definitions via `ctx.tool.transform()` — not the V1 plugin path |
193
295
 
194
296
  The V2 plugin provides 3 orchestration tools (`hashline_edit`, `pantheon_cost`,
@@ -208,10 +310,16 @@ surface: the host includes the active agent on the event, a read-only agent
208
310
  `createEnforcementGuard` throws to deny `edit`, `write`, `bash`, `task`,
209
311
  `hashline_edit` and `pantheon_model`. It does **not** rely on the V1
210
312
  `tool.execute.before` hook, which lives in `src/plugin.ts` and is not loaded
211
- when only `plugin-v2` is configured. The companion `execute.after` hook and the
212
- `permission.evaluate` hook are registration points with no V2-side behaviour,
213
- and the V1 caller/target delegation matrix for native `task()` is not enforced
214
- on V2.
313
+ when only `plugin-v2` is configured. The `permission.evaluate` hook enforces
314
+ the V2 caller/target matrix for Pantheon-managed targets across every entry in
315
+ the host's `resources` array. Native-only resources pass through unchanged to
316
+ OpenCode's permission policy; mixed native/Pantheon requests and multi-target
317
+ requests are denied unless every Pantheon target is explicitly allowed for the
318
+ authoritative caller. Explicit host denies remain final, and missing or
319
+ unknown resource data fails closed. If a denied evaluation has no mutable host
320
+ output argument, the hook throws to fail closed rather than silently omitting
321
+ the denial. V2 `execute.after` runs the completed-result chain:
322
+ `task-result-guard` → `context-sandbox` → `read-enhancer`.
215
323
 
216
324
  Every V2 tool declares an `output` schema. OpenCode 2.0.x requires the
217
325
  declaration and the resolved result to agree in both directions, so an
@@ -220,14 +328,41 @@ every call. Unsupported V2 features are `legacy-hooks` (the V1-specific hook
220
328
  surface), `catalog-transform`, `integration-transform`, `skill-transform` and
221
329
  `goal-tools`.
222
330
 
223
- The package exposes both contracts as importable exports: `pantheon-opencode/plugin`
224
- (V1), `pantheon-opencode/plugin-v2` (V2) and `pantheon-opencode/v2-bridge`
225
- (optional interop), so a host can load either contract explicitly.
226
-
227
- The V1→V2 bridge (`src/pantheon/v2-bridge.ts`) enables optional interop:
228
- V1 infrastructure singletons (BackgroundJobBoard, GoalStore,
229
- TodoEnforcer, VisionHandler) are passed through V2 `ctx.options`. The bridge is
230
- optional — V2 works standalone with graceful degradation.
331
+ When `init --opencode-version v2` migrates a V1-shaped permission config, it
332
+ translates `task` to the V2 `subagent` action and `write` to `edit` (which also
333
+ covers host `write`/`patch`). If legacy `edit` and `write` rules collide on a
334
+ resource, migration keeps the stricter effect. Hand-edited V2 configs should
335
+ use the native top-level `permissions` array and action/resource/effect form.
336
+
337
+ ### Runtime secret-scanning limit
338
+
339
+ V1 and V2 use the same in-process scanner on their tool `execute.before` paths.
340
+ The scanner accepts up to **5 MiB (5,242,880 UTF-8 bytes) of serialized hook
341
+ payload**. Larger or malformed payloads are denied fail-closed; the rejected
342
+ payload is not written to the scanner log. This bound applies to the complete
343
+ serialized hook payload, not just one argument field. Before calling
344
+ `JSON.stringify`, the scanner iteratively preflights compact JSON byte size,
345
+ including UTF-8 and JSON escapes, and stops as soon as the limit is exceeded.
346
+ It rejects cycles, enumerable accessors and `toJSON` hooks, proxies, excessive
347
+ nesting, and non-JSON values without serializing or logging them.
348
+
349
+ V2 registers its required enforcement hook before registering Pantheon tools.
350
+ If the host rejects that hook, startup reports `secret-scan-hook` and
351
+ `pantheon-tools-disabled`, and Pantheon V2 tools are not registered. This does
352
+ not disable or claim scanner coverage for native host built-in tools; those may
353
+ remain available under the host's own policies. The opt-in timing harness is
354
+ reproducible with `npx tsx scripts/bench-secret-scanner.ts`: it runs 3 warmups
355
+ and 15 measured calls per size, reporting median timings for the current
356
+ `scanSecretText` implementation on safe ASCII strings only. It excludes payload
357
+ preflight/serialization and host-hook overhead, is not a historical or
358
+ Bash-versus-TypeScript comparison, and makes no speedup claim. It does not print
359
+ scan input.
360
+
361
+ The package exposes both contracts as importable exports: the package root and
362
+ `pantheon-opencode/plugin-v2` load V2; `pantheon-opencode/plugin` loads V1.
363
+ `pantheon-opencode/v2-bridge` is currently an importable utility only:
364
+ production setup does not wire it into the V2 plugin, so it does not provide
365
+ runtime interoperability or restore V1 goal/board features.
231
366
 
232
367
  Select the contract explicitly when installing:
233
368
 
@@ -244,8 +379,8 @@ the host in this order: an explicit `OPENCODE_VERSION=v1|v2` wins; otherwise an
244
379
  binary is asked for its `--version` and a major of 2 or more selects V2. Every
245
380
  other case — an unreadable probe, an unparseable banner, or a banner whose
246
381
  version-like tokens contradict each other with no tool name to break the tie —
247
- warns once and falls back to V1, because a plural `plugins` directory entry on
248
- an unknown 1.x host loses the plugin entirely.
382
+ warns once and falls back to V1, because the V2-only package export is not a
383
+ valid V1 runtime contract on an unknown 1.x host.
249
384
 
250
385
  The probe prefers the token that follows the tool name, so a runtime token
251
386
  ahead of it (`node v22.1.0 (opencode 1.18.33)`) or a trailing build date
@@ -301,11 +436,17 @@ Key order does not matter.
301
436
 
302
437
  ## Updating between releases (beta.5+)
303
438
 
439
+ > **Read [Compatibility and support policy](#compatibility-and-support-policy)
440
+ > before upgrading across a line boundary.** 1.6.x is the last line that
441
+ > supports an OpenCode 1.X host; 1.7+ is breaking-change territory targeting
442
+ > OpenCode 2. Within the 1.6 line, `update` is the supported path.
443
+
304
444
  One command keeps an existing installation current:
305
445
 
306
446
  ```bash
307
- # Without a global install, ALWAYS pin the dist-tag — plain `npx
308
- # pantheon-opencode` resolves `latest`, which is the stable release (1.4.3):
447
+ # Without a global install, pin the intended npm dist-tag. The `latest` tag
448
+ # reflects the most recently published stable release, not an unpublished
449
+ # release candidate:
309
450
  npx pantheon-opencode@beta update # npm beta channel + config refresh
310
451
  npx pantheon-opencode@beta update --stable # stable channel instead
311
452
 
@@ -391,6 +532,10 @@ Release validation keeps each manifest with its lockfile: the root
391
532
  SHA-256 of that same artifact, and binds the tarball and GitHub release to the
392
533
  full `TARGET_SHA`; a second pack is not interchangeable.
393
534
 
535
+ CI also rebuilds the TUI with `npm run build --prefix src/plugins/tui` and
536
+ checks every packaged `dist` artifact byte-for-byte against its checked-in
537
+ version, including final newlines.
538
+
394
539
  ## Sandbox validation (V2)
395
540
 
396
541
  `scripts/test-opencode-v2-sandbox.sh` validates the globally installed
@@ -402,10 +547,12 @@ agent delegation. The gate is fail-closed: every required check must return an
402
547
  explicit PASS; timeouts, auth/network/provider failures and missing
403
548
  prerequisites block the run.
404
549
 
405
- "V2" here refers only to the hook canary observed against an OpenCode v2.0.18
406
- host, where at least one tested hook callback fired; it does not establish
407
- compatibility with the stable `@opencode/plugin@2.0.18` SDK or full 2.x
408
- contract. This branch still pins transitional `@opencode-ai/plugin@1.18.30`.
550
+ The historical hook canary observed at least one callback on an OpenCode
551
+ v2.0.18 host; the tool canary was written against v2.0.22. Those observations
552
+ do not establish compatibility with the current installable `@opencode-ai/cli@beta`,
553
+ an SDK contract for all of 2.x, or a V1 host. This release pins the V1 plugin
554
+ dependency pair at `@opencode-ai/plugin@1.18.33` and `@opencode-ai/sdk@1.18.33`;
555
+ the V1 host canary remains deferred.
409
556
  On hosts where both `opencode` and `opencode2` exist, the latter is typically
410
557
  a shim that execs the same binary, so an older side-by-side comparison proved
411
558
  nothing about the binary itself. The project is V2-exclusive, so there is a
@@ -418,7 +565,7 @@ scripts/test-opencode-v2-sandbox.sh --prompts # base validation + prompt bat
418
565
  scripts/test-opencode-v2-sandbox.sh --rehydrate # offline context rehydration/session-summary probe
419
566
  scripts/test-opencode-v2-sandbox.sh --hooks # V2 hook callback canary
420
567
  scripts/test-opencode-v2-sandbox.sh --rehydrate --hooks # run both canaries
421
- scripts/test-opencode-v2-sandbox.sh --reset # wipe the sandbox root
568
+ scripts/test-opencode-v2-sandbox.sh --reset # guarded reset of the sandbox root
422
569
  ```
423
570
 
424
571
  Modes are combinable (e.g. `--prepare --run v2 --prompts`). `--rehydrate` runs
@@ -431,8 +578,20 @@ rehydration fails, and the command returns a failing status afterward. These
431
578
  are test/sandbox canaries, not proof of Pantheon security enforcement. Binaries
432
579
  are resolved strictly inside the sandbox npm prefix — a non-prepared sandbox
433
580
  fails fast instead of silently testing the host installation. The sandbox is
434
- always built from the checkout this script lives in; it never infers a
435
- repository from a sibling directory.
581
+ always built from the checkout this script lives in unless `PANTHEON_REPO` is
582
+ set to an absolute path for an existing `pantheon-opencode` checkout. The same
583
+ resolved checkout is used by prepare and the generated `run-test.sh`; dangling,
584
+ relative, and non-Pantheon paths fail before packaging. `--prepare` generates
585
+ `run-test.sh`, `start-pantheon.sh`, and a sandbox-local `README.md`.
586
+
587
+ `PANTHEON_V2_PORT` selects the dedicated loopback port (default `49376`). The
588
+ harness validates the port and refuses an occupied listener without reusing or
589
+ stopping it. `PANTHEON_V2_HOST` defaults to `127.0.0.1` and rejects non-loopback
590
+ addresses. `PANTHEON_V2_MCP_LIST_TIMEOUT` controls each `mcp list` call
591
+ (default `15` seconds). On prepare, only hash-named Node compile-cache files
592
+ owned by the current user and older than 30 days may expire under
593
+ `tmp/node-compile-cache`; runtime state and unrecognized files (including
594
+ handoff evidence) are preserved.
436
595
 
437
596
  This validates the prepared isolated sandbox only. A PASS is not proof of
438
597
  support for every real host or for host configurations that were not exercised.
@@ -509,6 +668,22 @@ Ideas, bug reports, documentation improvements, and code contributions are
509
668
  welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening an issue
510
669
  or pull request.
511
670
 
671
+ ### Reproducible benchmark evidence
672
+
673
+ The beta2 benchmark records reported token usage separately from its
674
+ character-based fallback estimate; source bytes and logical line counts remain
675
+ provenance data and are never converted into tokens. Cross-report comparisons
676
+ require matching model/config provenance and reported OpenCode usage. Offline
677
+ fixture responses are mocked: their reported values are labeled separately,
678
+ excluded from `actual` usage, and blocked from comparative metrics and GEPA.
679
+ Fixture quality outcomes test the offline contract; they are not evaluation
680
+ evidence.
681
+ Reproduce the
682
+ checked-in AGENTS.md history manifest with
683
+ `python3 -m benchmarks.beta2.provenance --output benchmarks/beta2/fixtures/agent-baseline-provenance.json`.
684
+ For OpenCode benchmark runs, provide `--model` and `--config-sha256` so reports
685
+ can be compared safely.
686
+
512
687
  ### Project-level `opencode.json`
513
688
 
514
689
  The published package carries no `opencode.json` template. `init` still writes
package/README.pt-BR.md CHANGED
@@ -53,6 +53,19 @@ 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
+ Perguntas sem mudança no repositório são respondidas diretamente; correções
57
+ pequenas usam uma única delegação. Discovery, planejamento, paralelismo e
58
+ revisão em council ficam para quando o escopo ou o risco justificarem.
59
+
60
+ Para uma correção pequena e bem delimitada, chame `@talos` diretamente (por
61
+ exemplo, `@talos corrija este typo`). Assim você pula a chamada de orquestração
62
+ do Zeus; use `/pantheon` para planejamento, delegação, mudanças em vários
63
+ arquivos ou gates de qualidade.
64
+
65
+ O procedimento completo de council só é carregado em `/pantheon` ou quando uma
66
+ decisão material realmente exige perspectivas distintas. Falhas de dispatch
67
+ podem ser tentadas novamente uma vez; testes reprovados e recusas não são
68
+ repetidos automaticamente.
56
69
 
57
70
  ## Para quem é?
58
71
 
@@ -71,11 +84,13 @@ verificações repetíveis e passagens claras entre etapas do trabalho.
71
84
 
72
85
  ## Status
73
86
 
74
- Versão operacional neste checkout: **v1.6.0-beta.1** (primeira beta compatível
75
- com OpenCode 2; esta página não afirma publicação). O Pantheon foi feito para OpenCode e depende da
76
- disponibilidade e da configuração do OpenCode e dos serviços opcionais que você
77
- escolher. Veja as [releases](https://github.com/ils15/pantheon-opencode/releases)
78
- e o [changelog](CHANGELOG.md) para acompanhar as mudanças publicadas.
87
+ Versão candidata neste checkout: **v1.6.0-beta.7** (manifestos preparados;
88
+ publicação ainda não confirmada). Para verificar a beta publicada, consulte a
89
+ dist-tag `beta` do npm. O histórico permanece no [changelog](CHANGELOG.md). O
90
+ Pantheon foi feito para OpenCode e depende da disponibilidade e da configuração
91
+ do OpenCode e dos serviços opcionais que você escolher. Veja as
92
+ [releases](https://github.com/ils15/pantheon-opencode/releases) e o
93
+ [changelog](CHANGELOG.md) para acompanhar as mudanças publicadas.
79
94
 
80
95
 
81
96
  ## Execução code-mode (opt-in explícito)
@@ -121,13 +136,13 @@ registrados juntos.
121
136
  | | V1 | V2 |
122
137
  |---|---|---|
123
138
  | Chave de config do OpenCode | `plugin` singular | `plugins` plural |
124
- | Registro Pantheon | `src/plugin.ts` mais `src/plugins/pantheon-hooks.ts` | `pantheon-opencode/plugin-v2` (`src/plugin-v2.ts`) |
125
- | 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 (`hashline_edit`, `pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos, session hooks (`prompt`, `context`), um hook de ferramenta `execute.before` que impõe sessões somente-leitura, além de transforms de configuração |
139
+ | Registro Pantheon | `src/plugin.ts` mais `src/plugins/pantheon-hooks.ts` | pacote npm `pantheon-opencode@<versão>` fixado à versão instalada (export raiz aponta para `src/plugin-v2.ts`) |
140
+ | 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: 3 ferramentas (`hashline_edit`, `pantheon_cost`, `pantheon_model`), 5 assinaturas de eventos, session hooks (`prompt`, `context`), hooks de execução/permissão e transforms de configuração |
126
141
  | APIs V1 | Registradas | Definições próprias de ferramentas via `ctx.tool.transform()` — não pelo caminho do plugin V1 |
127
142
 
128
143
  O plugin V2 fornece 3 ferramentas de orquestração (`hashline_edit`,
129
- `pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos (`session.created`,
130
- `session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
144
+ `pantheon_cost`, `pantheon_model`), 5 assinaturas de eventos (`session.created`,
145
+ `session.idle`, `session.deleted`, `session.error`, `session.compacted`), session hooks (`prompt`,
131
146
  `context`) e um hook de ferramenta `execute.before` que impõe sessões
132
147
  somente-leitura. As 3 ferramentas de goal **não** são
133
148
  registradas no V2: o goal loop precisa de um `GoalStore`, de um
@@ -141,10 +156,16 @@ dessa superfície: o host inclui o agente ativo no evento, um agente somente-lei
141
156
  compartilhado lança para negar `edit`, `write`, `bash`, `task`,
142
157
  `hashline_edit` e `pantheon_model`. Ele **não** depende do hook
143
158
  `tool.execute.before` do V1, que vive em `src/plugin.ts` e não é carregado
144
- quando apenas `plugin-v2` está configurado. Os hooks companheiros
145
- `execute.after` e `permission.evaluate` são pontos de registro sem comportamento
146
- do lado V2, e a matriz de delegação caller/target da V1 para o `task()` nativo
147
- não é imposta no V2.
159
+ quando apenas `plugin-v2` está configurado. O hook `permission.evaluate`
160
+ aplica no V2 a matriz caller/target para destinos gerenciados pelo Pantheon,
161
+ considerando todos os itens do array `resources` do host. Recursos
162
+ exclusivamente nativos são repassados sem alteração à política de permissões do
163
+ OpenCode; pedidos mistos (nativos/Pantheon) e com vários destinos são negados,
164
+ a menos que todos os destinos Pantheon sejam explicitamente permitidos para o
165
+ chamador autoritativo. Uma negação explícita do host é final, e dados de
166
+ recursos ausentes ou desconhecidos são negados por padrão. O `execute.after` do
167
+ V2 executa a cadeia de resultados concluídos `task-result-guard` →
168
+ `context-sandbox` → `read-enhancer`; eventos de erro permanecem inalterados.
148
169
 
149
170
  Toda ferramenta V2 declara um schema `output`. O OpenCode 2.0.x exige que a
150
171
  declaração e o resultado resolvido concordem nos dois sentidos, então uma
@@ -153,15 +174,18 @@ toda chamada. Os recursos V2 sem suporte são `legacy-hooks` (a superfície de
153
174
  hooks específica do V1), `catalog-transform`, `integration-transform`,
154
175
  `skill-transform` e `goal-tools`.
155
176
 
156
- O pacote expõe os dois contratos como exports importáveis:
157
- `pantheon-opencode/plugin` (V1), `pantheon-opencode/plugin-v2` (V2) e
158
- `pantheon-opencode/v2-bridge` (interop opcional), para que o host carregue
159
- explicitamente o contrato desejado.
177
+ Ao migrar uma config V1 com `init --opencode-version v2`, o instalador traduz
178
+ `task` para a ação V2 `subagent` e `write` para `edit` (que também cobre as
179
+ tools host `write`/`patch`). Se regras legadas `edit` e `write` colidirem no
180
+ mesmo recurso, a migração preserva o efeito mais restritivo. Configs V2
181
+ editadas manualmente devem usar o array nativo `permissions` com
182
+ `action`/`resource`/`effect`.
160
183
 
161
- A ponte V1→V2 (`src/pantheon/v2-bridge.ts`) habilita interop opcional:
162
- singletons de infraestrutura V1 (BackgroundJobBoard,
163
- GoalStore, TodoEnforcer, VisionHandler) são repassados via `ctx.options` do V2.
164
- A ponte é opcional — o V2 funciona standalone com degradação graciosa.
184
+ O pacote expõe os dois contratos: a raiz e `pantheon-opencode/plugin-v2`
185
+ carregam V2; `pantheon-opencode/plugin` carrega V1. `pantheon-opencode/v2-bridge`
186
+ é atualmente apenas uma utility importável: o setup de produção não a conecta
187
+ ao plugin V2, então ela não fornece interoperabilidade em runtime nem restaura
188
+ as ferramentas de goal/board do V1.
165
189
 
166
190
  Selecione o contrato explicitamente na instalação:
167
191
 
@@ -238,8 +262,8 @@ pontos. A ordem das chaves não muda o resultado.
238
262
  Um comando mantém uma instalação existente em dia:
239
263
 
240
264
  ```bash
241
- # Sem instalação global, SEMPRE fixe o dist-tag — `npx pantheon-opencode`
242
- # puro resolve a tag `latest`, que é o release estável (1.4.3):
265
+ # Sem instalação global, fixe o dist-tag desejado. `latest` aponta para a
266
+ # release estável publicada mais recente, não para um candidato não publicado:
243
267
  npx pantheon-opencode@beta update # canal beta do npm + refresh do config
244
268
  npx pantheon-opencode@beta update --stable # canal estável
245
269