pantheon-opencode 1.6.0-beta.2 → 1.6.0-beta.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -18,6 +18,96 @@ 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.3] - 2026-10-03
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
+ - **Três ferramentas V2 agora executam de verdade**: `hashline_edit`,
28
+ `pantheon_cost` e `pantheon_model` rodam no host `opencode v2.0.x`. Antes
29
+ eram placeholders que declaravam sucesso sem fazer nada.
30
+ - **Enforcement de sessão read-only no caminho V2**: `apollo` e `gaia` voltam
31
+ a ter escrita bloqueada, com o guard registrado no próprio plugin V2 — sem
32
+ depender de uma ponte que a instalação V2 não monta.
33
+ - **Varredura de segredos de alta confiança no caminho V2**: o único hard block
34
+ de segurança que a V1 tinha, e que estava inerte por viver num plugin que a
35
+ instalação V2 não carrega, passa a rodar.
36
+
37
+ ## 🐞 Fixed
38
+ - **As 6 ferramentas de plugin do V2 falhavam em 100% das chamadas**:
39
+ `hashline_edit`, `pantheon_cost` e `pantheon_model` lançavam
40
+ `Tool result declared output without an output schema` em toda invocação. A
41
+ causa era assimetria local — `draft.add()` não declarava `output` enquanto o
42
+ `execute` resolvia `{ output: string }`. O host exige simetria nos dois
43
+ sentidos: resultado com `output` e nenhuma declaração lança, assim como
44
+ declaração sem `output` no resultado. `output` passou a ser **obrigatório** na
45
+ interface `V2ToolDef`, então o compilador exige a declaração daqui em diante.
46
+ - **A suíte exigia o defeito**: `tests/pantheon/plugin-v2-contract.test.ts`
47
+ afirmava que o resultado carregava `.output` string — literalmente a condição
48
+ de falha, contra um mock que não reproduzia a exigência do host. O teste foi
49
+ reescrito para o invariante de simetria, contra um mock que constrói o
50
+ `outputSchema` a partir de `def.output` como o host faz
51
+ (`output: I.outputSchema ?? {}`), cobrindo as duas direções do bicondicional.
52
+ - **A imposição read-only não existia na superfície V2**: `createEnforcementGuard`
53
+ só era instanciado em `src/plugin.ts`, que o `opencode.json` da release não
54
+ declara — V2 nunca carrega V1. Com `hashline_edit` funcional, uma sessão
55
+ somente-leitura podia escrever arquivos. O guard passou a ser registrado no
56
+ hook `execute.before` do V2, e `pantheon_model` — que escreve
57
+ `active-preset.json` em escopo project e global — foi acrescentado a
58
+ `DEFAULT_BLOCKED_TOOLS`, o que corrige também a V1. `pantheon_cost` ficou de
59
+ fora de propósito: só lê `opencode.db`.
60
+ - **O único hard block de segurança da V1 estava inerte**: o scan de segredos de
61
+ alta confiança vivia em `src/plugins/pantheon-hooks.ts`, um plugin que a
62
+ instalação V2 não carrega — inerte por construção, não por má configuração.
63
+ Passou a rodar dentro do `execute.before` do V2
64
+ (`scripts/hooks/scan-secrets.sh`; exit 2 bloqueia, exit 1 é advisory e só
65
+ registra). O caminho do script foi verificado a partir do tarball instalado,
66
+ não só do repo.
67
+ - **Cinco comentários afirmavam cobertura que não existe** ("wired through the
68
+ V1…"). Corrigidos — é o defeito "anunciado como vivo, morto no caminho", a
69
+ mesma classe do bug original, transferida do tool para o controle de segurança.
70
+
71
+ ## ⚠️ Known Issues
72
+ - **A release entrega 3 ferramentas V2 funcionais, não 6**:
73
+ `pantheon_goal_create`, `pantheon_goal_get` e `pantheon_goal_update` foram
74
+ **removidos** da superfície V2. `GoalLoopDeps` exige `store`, `client` e
75
+ `board`, que não existem no `PluginContext` V2, e a bridge V1 resolve para
76
+ `null` fora da V1. Registrá-las como placeholders não funcionais seria pior
77
+ que a ausência: anunciá-las seria mentira silenciosa. Marcador `goal-tools`
78
+ em `V2_UNSUPPORTED_FEATURES`. **Breaking** para quem usava esses tools no
79
+ host V2 — o contrato V1 permanece disponível para o goal loop.
80
+ - **A matriz de delegação nativa da V1 não é replicada na V2**: o guard V2 cobre
81
+ a lista de ferramentas bloqueadas, mas não a matriz caller→target nem a negação
82
+ de `task` em sessão filha. A matriz precisa de uma hierarquia de sessões
83
+ semeada a partir dos metadados de sessão, e o V2 não expõe esse caminho de
84
+ semeadura — `SessionHierarchyRegistry.isRoot` reporta `true` para sessões
85
+ desconhecidas enquanto não semeada, então semeá-la pela metade negaria todo
86
+ `task()`. O branch é pulado em vez de negado indiscriminadamente. Marcador
87
+ `delegation-matrix`. `task` continua negada em sessão somente-leitura pela
88
+ lista de ferramentas bloqueadas, então a profundidade 2 se sustenta; o que
89
+ não existe é a matriz. Coberto por `experimental.subagent_depth` nesta
90
+ configuração, mas a garantia do plugin não existe.
91
+ - **O log do scan de segredos escreve só em `.pantheon/logs/hooks.log`**: o
92
+ `PluginContext` V2 não expõe `client` nem `directory`, então os canais de log
93
+ estruturado e de toast da V1 não existem nessa superfície. É menos
94
+ observabilidade, não menos bloqueio.
95
+ - **Falha de infraestrutura do scanner é fail-open por decisão**: script ausente
96
+ ou timeout não bloqueiam. `runHook` nunca rejeita e um erro de infraestrutura
97
+ não deve negar chamadas não relacionadas. Ausência do script não bloqueia.
98
+
99
+ ## ✅ Closed Issues
100
+ - **Drift de documentação no `README.pt-BR.md`**: a tabela de contrato de
101
+ runtime e o parágrafo de superfície listavam 6 ferramentas V2 e as 3 de goal,
102
+ que não estão registradas. Corrigido para 3 ferramentas, com a razão da
103
+ ausência e o ponto de imposição read-only.
104
+ - **Cinco comentários de falsa cobertura** sobre a imposição read-only e o scan
105
+ de segredos.
106
+ - **Shim do loader JSON do ajv elevado a bootstrap de módulo**: o patch de
107
+ `Module._extensions['.json']` era aplicado de dentro de `loadAjv()` e ficava
108
+ vivo durante todo o run, podendo vazar entre arquivos de teste e se manifestar
109
+ longe da causa. Agora instala, carrega e restaura em nível de módulo, antes de
110
+ qualquer corpo de teste, com `finally`.
21
111
  ## [v1.6.0-beta.2] - 2026-10-02
22
112
 
23
113
  ## 🆕 What's New
package/README.md CHANGED
@@ -186,16 +186,36 @@ per installation; V1 and V2 Pantheon plugins must never be registered together.
186
186
  |---|---|---|
187
187
  | OpenCode config key | singular `plugin` | plural `plugins` |
188
188
  | Pantheon registration | `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts` | `<installed>/src/plugin-v2` directory (`index.ts` re-exports `src/plugin-v2.ts`) |
189
- | 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: 6 orchestration tools, 4 event subscriptions, session hooks (`prompt`, `context`), tool hooks (`execute.before`/`after`), plus configuration transforms |
189
+ | 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`), 4 event subscriptions, session hooks (`prompt`, `context`), a read-only-enforcing tool `execute.before` hook, plus configuration transforms |
190
190
  | V1 APIs | Registered | Own tool definitions via `ctx.tool.transform()` — not the V1 plugin path |
191
191
 
192
- The V2 plugin provides 6 orchestration tools (`hashline_edit`,
193
- `pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
194
- `pantheon_cost`, `pantheon_model`), 4 event subscriptions (`session.created`,
195
- `session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
196
- `context`), and tool hooks (`execute.before`, `execute.after`). Unsupported V2
197
- features are `legacy-hooks` (the V1-specific hook surface), `catalog-transform`,
198
- `integration-transform`, and `skill-transform`.
192
+ The V2 plugin provides 3 orchestration tools (`hashline_edit`, `pantheon_cost`,
193
+ `pantheon_model`), 4 event subscriptions (`session.created`, `session.idle`,
194
+ `session.error`, `session.compacted`), session hooks (`prompt`, `context`),
195
+ and a tool `execute.before` hook that enforces read-only sessions. The 3 goal
196
+ tools are **not**
197
+ registered on V2: the goal loop needs a `GoalStore`, a `GoalLoopClient` and a
198
+ `BackgroundJobBoard`, none of which the V2 `PluginContext` exposes, so the gap
199
+ is reported as the `goal-tools` unsupported-feature marker. Use the V1
200
+ contract if you need the goal loop.
201
+
202
+ The V2 `execute.before` hook is the read-only enforcement point for that
203
+ surface: the host includes the active agent on the event, a read-only agent
204
+ (`apollo`, `gaia`) registers its session, and the shared
205
+ `createEnforcementGuard` throws to deny `edit`, `write`, `bash`, `task`,
206
+ `hashline_edit` and `pantheon_model`. It does **not** rely on the V1
207
+ `tool.execute.before` hook, which lives in `src/plugin.ts` and is not loaded
208
+ when only `plugin-v2` is configured. The companion `execute.after` hook and the
209
+ `permission.evaluate` hook are registration points with no V2-side behaviour,
210
+ and the V1 caller/target delegation matrix for native `task()` is not enforced
211
+ on V2.
212
+
213
+ Every V2 tool declares an `output` schema. OpenCode 2.0.x requires the
214
+ declaration and the resolved result to agree in both directions, so an
215
+ undeclared tool — or one that returns `output` without declaring it — fails on
216
+ every call. Unsupported V2 features are `legacy-hooks` (the V1-specific hook
217
+ surface), `catalog-transform`, `integration-transform`, `skill-transform` and
218
+ `goal-tools`.
199
219
 
200
220
  The package exposes both contracts as importable exports: `pantheon-opencode/plugin`
201
221
  (V1), `pantheon-opencode/plugin-v2` (V2) and `pantheon-opencode/v2-bridge`
package/README.pt-BR.md CHANGED
@@ -122,16 +122,36 @@ registrados juntos.
122
122
  |---|---|---|
123
123
  | Chave de config do OpenCode | `plugin` singular | `plugins` plural |
124
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: 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 |
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 |
126
126
  | APIs V1 | Registradas | Definições próprias de ferramentas via `ctx.tool.transform()` — não pelo caminho do plugin V1 |
127
127
 
128
- O plugin V2 fornece 6 ferramentas de orquestração (`hashline_edit`,
129
- `pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
128
+ O plugin V2 fornece 3 ferramentas de orquestração (`hashline_edit`,
130
129
  `pantheon_cost`, `pantheon_model`), 4 assinaturas de eventos (`session.created`,
131
130
  `session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
132
- `context`) e tool hooks (`execute.before`, `execute.after`). Os recursos V2 sem
133
- suporte são `legacy-hooks` (a superfície de hooks específica do V1),
134
- `catalog-transform`, `integration-transform` e `skill-transform`.
131
+ `context`) e um hook de ferramenta `execute.before` que impõe sessões
132
+ somente-leitura. As 3 ferramentas de goal **não** são
133
+ registradas no V2: o goal loop precisa de um `GoalStore`, de um
134
+ `GoalLoopClient` e de um `BackgroundJobBoard`, nenhum dos quais o
135
+ `PluginContext` do V2 expõe, então a lacuna é reportada como o marcador de
136
+ recurso sem suporte `goal-tools`. Use o contrato V1 se precisar do goal loop.
137
+
138
+ O hook `execute.before` do V2 é o ponto de imposição de sessões somente-leitura
139
+ dessa superfície: o host inclui o agente ativo no evento, um agente somente-leitura
140
+ (`apollo`, `gaia`) registra sua sessão, e o `createEnforcementGuard`
141
+ compartilhado lança para negar `edit`, `write`, `bash`, `task`,
142
+ `hashline_edit` e `pantheon_model`. Ele **não** depende do hook
143
+ `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.
148
+
149
+ Toda ferramenta V2 declara um schema `output`. O OpenCode 2.0.x exige que a
150
+ declaração e o resultado resolvido concordem nos dois sentidos, então uma
151
+ ferramenta sem declaração — ou que retorne `output` sem declará-lo — falha em
152
+ toda chamada. Os recursos V2 sem suporte são `legacy-hooks` (a superfície de
153
+ hooks específica do V1), `catalog-transform`, `integration-transform`,
154
+ `skill-transform` e `goal-tools`.
135
155
 
136
156
  O pacote expõe os dois contratos como exports importáveis:
137
157
  `pantheon-opencode/plugin` (V1), `pantheon-opencode/plugin-v2` (V2) e
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pantheon-opencode",
3
- "version": "1.6.0-beta.2",
3
+ "version": "1.6.0-beta.3",
4
4
  "description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
5
5
  "type": "module",
6
6
  "workspaces": [
@@ -105,6 +105,7 @@
105
105
  "@biomejs/biome": "2.5.13",
106
106
  "@commitlint/cli": "21.2.2",
107
107
  "@commitlint/config-conventional": "21.2.2",
108
+ "ajv": "8.20.0",
108
109
  "husky": "^9.1.7",
109
110
  "tsx": "4.23.13",
110
111
  "typescript": "6.0.3"
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "pantheon",
3
3
  "publisher": "ils15",
4
- "version": "1.6.0-beta.2",
4
+ "version": "1.6.0-beta.3",
5
5
  "displayName": "Pantheon",
6
6
  "description": "Conductor-Delegate orchestration platform with 14 specialized agents, 21 skills, and OpenCode support.",
7
7
  "agents": "./src/agents",
package/pyproject.toml CHANGED
@@ -4,7 +4,7 @@ build-backend = "setuptools.backends._legacy:_Backend"
4
4
 
5
5
  [project]
6
6
  name = "pantheon"
7
- version = "1.6.0-beta.2"
7
+ version = "1.6.0-beta.3"
8
8
  description = "Multi-agent orchestration framework"
9
9
  requires-python = ">=3.11"
10
10
  dependencies = []
@@ -9,12 +9,14 @@
9
9
  * module never needs the opencode SDK — the handler is a structural closure
10
10
  * wired from plugin.ts.
11
11
  *
12
- * Blocked tools (edit, write, bash, task, hashline_edit):
12
+ * Blocked tools (edit, write, bash, task, hashline_edit, pantheon_model):
13
13
  * - edit/write/bash are the mutating surface — read-only agents (apollo,
14
14
  * gaia) must stay investigation-only.
15
15
  * - `hashline_edit` is the Wave 2 (PR #46) tag-anchored edit tool — it is a
16
16
  * write surface too, so read-only agents must not bypass enforcement via
17
17
  * it.
18
+ * - `pantheon_model` writes active-preset.json in project and global scope —
19
+ * a config write a read-only session must not perform.
18
20
  * - `task` is blocked too, which hard-enforces depth-2: a read-only agent
19
21
  * cannot spawn its own subagents.
20
22
  *
@@ -182,6 +184,13 @@ export const DEFAULT_BLOCKED_TOOLS: ReadonlySet<string> = new Set([
182
184
  'bash',
183
185
  'task',
184
186
  'hashline_edit',
187
+ // `pantheon_model` writes active-preset.json in BOTH the project and the
188
+ // global scope, so it is a write surface with the same blast radius as
189
+ // `write`. Read-only agents have no reason to change agent models, and a
190
+ // global override from an investigation-only session is unrecoverable from
191
+ // inside that session. `pantheon_cost` is deliberately absent: it only reads
192
+ // opencode.db.
193
+ 'pantheon_model',
185
194
  ])
186
195
 
187
196
  // ─── Zeus Read Guard ──────────────────────────────────────────────────