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 +90 -0
- package/README.md +28 -8
- package/README.pt-BR.md +26 -6
- package/package.json +2 -1
- package/plugin.json +1 -1
- package/pyproject.toml +1 -1
- package/src/pantheon/delegation-enforce.ts +10 -1
- package/src/pantheon/v2-tools.ts +426 -0
- package/src/plugin-v2.ts +344 -134
- package/src/plugins/tui/dist/tui.js +1 -1
- package/src/plugins/tui/package-lock.json +2 -2
- package/src/plugins/tui/package.json +1 -1
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:
|
|
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
|
|
193
|
-
`
|
|
194
|
-
`
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
`
|
|
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:
|
|
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
|
|
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
|
|
133
|
-
|
|
134
|
-
`
|
|
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.
|
|
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.
|
|
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
|
@@ -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 ──────────────────────────────────────────────────
|