pantheon-opencode 1.6.0-beta.4 → 1.6.0-beta.6
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/AGENTS.md +42 -23
- package/CHANGELOG.md +41 -0
- package/README.md +114 -12
- package/README.pt-BR.md +15 -6
- package/bin/pantheon-init.mjs +26 -3
- package/package.json +5 -6
- package/plugin.json +1 -1
- package/pyproject.toml +6 -6
- package/scripts/{code_mode_server.py → code_mode.py} +2 -2
- package/scripts/doctor.mjs +151 -1
- package/scripts/install/config-migration.mjs +80 -2
- package/scripts/install/health-check.mjs +12 -17
- package/scripts/install/opencode-version.mjs +246 -4
- package/scripts/install/opencode.mjs +250 -119
- package/scripts/install-mcp.mjs +28 -9
- package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +1 -1
- package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +1 -1
- package/scripts/{memory_mcp_server.py → memory_mcp.py} +1 -1
- package/scripts/probe-context-rehydrate.mjs +2 -2
- package/scripts/run-node-tests.mjs +189 -0
- package/scripts/sync-artifacts.mjs +5 -5
- package/scripts/test-opencode-v2-sandbox.sh +21 -21
- package/skills-lock.json +2 -2
- package/src/agents/aphrodite.md +1 -1
- package/src/agents/apollo.md +7 -2
- package/src/agents/athena.md +1 -0
- package/src/agents/demeter.md +1 -1
- package/src/agents/hephaestus.md +1 -1
- package/src/agents/hermes.md +1 -1
- package/src/agents/iris.md +1 -0
- package/src/agents/nyx.md +1 -0
- package/src/agents/themis.md +1 -0
- package/src/agents/zeus.md +39 -10
- package/src/instructions/memory-protocol.instructions.md +21 -10
- package/src/instructions/zeus-anti-stall.instructions.md +19 -11
- package/src/instructions/zeus-council-synthesis.instructions.md +2 -2
- package/src/mcp/{code_mode_server.py → code_mode.py} +2 -2
- package/src/mcp/eval_store.py +2 -2
- package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +1 -1
- package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +1 -1
- package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +1 -1
- package/src/pantheon/v2-unsupported.d.mts +11 -0
- package/src/pantheon/v2-unsupported.mjs +113 -0
- package/src/plugin-v2.ts +149 -53
- 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/src/skills/auto-continue/SKILL.md +4 -4
- package/src/skills/context-compression/SKILL.md +1 -1
- package/opencode.json +0 -58
- /package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +0 -0
package/AGENTS.md
CHANGED
|
@@ -271,15 +271,21 @@ Each agent file defines overrides in its `## 🧠 Memory Protocol` section:
|
|
|
271
271
|
|
|
272
272
|
Para otimizar decisoes de delegacao e reduzir gasto de tokens:
|
|
273
273
|
|
|
274
|
-
1. **memory_search(task_prompt, top_k=2)** antes de aplicar a arvore de roteamento
|
|
274
|
+
1. **memory_search(query=task_prompt, top_k=2)** antes de aplicar a arvore de roteamento
|
|
275
275
|
2. Se score > 0.85 → reutiliza agente + background_mode do cache
|
|
276
276
|
3. Se score ≤ 0.85 → aplica regras estaticas e memory_store() com:
|
|
277
277
|
- key: deleg:<task_type>
|
|
278
|
-
- value: {agent, background, pattern}
|
|
279
|
-
- metadata: {type: "decision", score: N}
|
|
278
|
+
- value: JSON.stringify({agent, background, pattern})
|
|
279
|
+
- metadata: JSON.stringify({type: "decision", score: N})
|
|
280
280
|
|
|
281
|
-
|
|
282
|
-
|
|
281
|
+
`value` E `metadata` sao JSON-encoded strings — o runtime exige que o
|
|
282
|
+
chamador serialize os dois. Objeto cru em `metadata` e rejeitado pelo
|
|
283
|
+
`BeforeValidator` do servidor com `metadata must be a JSON object encoded
|
|
284
|
+
as a string (got object). json.dumps it first. Example: metadata='{"type":
|
|
285
|
+
"decision", "score": 0.9}'`.
|
|
286
|
+
|
|
287
|
+
4. **kv_store(namespace="deleg", key="deleg:<pattern>", value=...)** para padroes recorrentes de delegacao
|
|
288
|
+
5. **kv_get(namespace="deleg", key="deleg:<pattern>")** para reusar decisoes ja tomadas
|
|
283
289
|
|
|
284
290
|
Isso elimina ~300 tokens de reasoning por delegacao quando o cache acerta.
|
|
285
291
|
|
|
@@ -293,7 +299,7 @@ After every `/pantheon` council synthesis completes, Zeus stores:
|
|
|
293
299
|
memory_store({
|
|
294
300
|
namespace: "council_decisions",
|
|
295
301
|
key: "council:<yyyy-mm-dd>:<slug>",
|
|
296
|
-
value: {
|
|
302
|
+
value: JSON.stringify({
|
|
297
303
|
question: "original question",
|
|
298
304
|
specialists: ["@agent1", "@agent2"],
|
|
299
305
|
recommendation: "final recommendation",
|
|
@@ -304,20 +310,25 @@ memory_store({
|
|
|
304
310
|
themis_audit: "approved|issues",
|
|
305
311
|
precedent_used: false,
|
|
306
312
|
timestamp: "<ISO-8601>"
|
|
307
|
-
},
|
|
308
|
-
metadata: {
|
|
313
|
+
}),
|
|
314
|
+
metadata: JSON.stringify({
|
|
309
315
|
type: "council_decision",
|
|
310
316
|
specialist_count: N,
|
|
311
317
|
model_tier_used: "premium|default|fast"
|
|
312
|
-
}
|
|
318
|
+
})
|
|
313
319
|
})
|
|
314
320
|
```
|
|
315
321
|
`value` is JSON-serialized before storing (the MCP `memory_store.value` argument is a string).
|
|
322
|
+
`metadata` works the same way — it is a JSON object encoded as a **string**, so pass
|
|
323
|
+
`JSON.stringify({...})`. A raw object is rejected with `metadata must be a JSON object
|
|
324
|
+
encoded as a string (got object). json.dumps it first. Example: metadata='{"type":
|
|
325
|
+
"decision", "score": 0.9}'` (enforced by a `BeforeValidator` in
|
|
326
|
+
`memory_mcp.py`). **Both `value` and `metadata` must be serialized by the caller.**
|
|
316
327
|
|
|
317
328
|
### Read Path (Precedent Fast-Path)
|
|
318
329
|
Before dispatching a new council, Zeus runs:
|
|
319
330
|
```
|
|
320
|
-
memory_search(question, top_k=2, namespace="council_decisions")
|
|
331
|
+
memory_search(query=question, top_k=2, namespace="council_decisions")
|
|
321
332
|
```
|
|
322
333
|
|
|
323
334
|
Result interpretation:
|
|
@@ -415,19 +426,27 @@ All session state lives in **pantheon-persistence** (namespace `checkpoint:<slug
|
|
|
415
426
|
No file I/O, no checkpoint_session.py — TTL (4h) handles cleanup automatically.
|
|
416
427
|
|
|
417
428
|
### Heartbeat Check
|
|
418
|
-
- If `context_get(slug, "heartbeat")` returns a checkin older than 300s, log a stall warning and resume
|
|
429
|
+
- If `context_get(slug=slug, key="heartbeat", session_id=SESSION_ID)` returns a checkin older than 300s, log a stall warning and resume
|
|
419
430
|
- Write heartbeat after every anti-stall recovery action:
|
|
420
431
|
```
|
|
421
|
-
context_save(slug, "heartbeat",
|
|
432
|
+
context_save(slug=slug, key="heartbeat", content=JSON.stringify({"status": "alive", "last_action": "...", "turn_count": N}), session_id=SESSION_ID)
|
|
422
433
|
```
|
|
423
434
|
|
|
424
435
|
### Checkpoint Auto-Save (Pré-Compactação)
|
|
425
436
|
Before ANY delegate dispatch, save a checkpoint:
|
|
426
437
|
```
|
|
427
|
-
context_save(slug, "phase:N",
|
|
428
|
-
"phase":
|
|
438
|
+
context_save(slug=slug, key="phase:N", content=JSON.stringify({
|
|
439
|
+
"phase": {"current": N, "total": M, "name": "..."},
|
|
440
|
+
"turn_count": N, "agent": "...", "summary": "..."
|
|
429
441
|
}), session_id=SESSION_ID)
|
|
430
442
|
```
|
|
443
|
+
**`content.phase` must be an OBJECT, not a bare number.** `{"phase": 1}` is rejected with
|
|
444
|
+
`context_save: content.phase must be an object (got number)`. The server reads `current`
|
|
445
|
+
and `total` (non-negative ints) and `name` (string, max 256 **bytes** — the guard
|
|
446
|
+
measures `len(value.encode())`, so multi-byte characters count as more than one). That
|
|
447
|
+
set is not closed: any other key inside `phase` is accepted and ignored, never an
|
|
448
|
+
error. The `"phase:N"` slot KEY above is unrelated to `content.phase` and stays a plain
|
|
449
|
+
string.
|
|
431
450
|
All checkpoints auto-expire after 4h (TTL=14400).
|
|
432
451
|
|
|
433
452
|
### Gatilho de Pré-Compactação (Anti-perda de estado)
|
|
@@ -437,15 +456,15 @@ o Zeus DEVE salvar o estado atual:
|
|
|
437
456
|
2. Salve heartbeat + phase atual + tarefas pendentes
|
|
438
457
|
3. Só então permita que a compactação prossiga
|
|
439
458
|
```
|
|
440
|
-
# Ao iniciar sessão:
|
|
441
|
-
result = context_save(slug, "init", session_state)
|
|
459
|
+
# Ao iniciar sessão (session_id é REQUIRED — use o id da sessão corrente):
|
|
460
|
+
result = context_save(slug=slug, key="init", content=JSON.stringify(session_state), session_id=SESSION_ID)
|
|
442
461
|
SESSION_ID = result.session_id # ← guarde para toda a sessão
|
|
443
462
|
|
|
444
463
|
# Antes de CADA delegação:
|
|
445
|
-
context_save(slug, f"pre:{agent}", current_state, session_id=SESSION_ID)
|
|
464
|
+
context_save(slug=slug, key=f"pre:{agent}", content=JSON.stringify(current_state), session_id=SESSION_ID)
|
|
446
465
|
|
|
447
466
|
# Após retorno do agente:
|
|
448
|
-
context_save(slug, f"post:{agent}", result_state, session_id=SESSION_ID)
|
|
467
|
+
context_save(slug=slug, key=f"post:{agent}", content=JSON.stringify(result_state), session_id=SESSION_ID)
|
|
449
468
|
```
|
|
450
469
|
Isso garante que o estado sobreviva à compactação — o "latest" pointer
|
|
451
470
|
sempre aponta para o checkpoint mais recente, mesmo após compactação.
|
|
@@ -454,9 +473,9 @@ sempre aponta para o checkpoint mais recente, mesmo após compactação.
|
|
|
454
473
|
### Context Retrieval
|
|
455
474
|
Next-phase agents retrieve previous context via:
|
|
456
475
|
```
|
|
457
|
-
context_get(slug,
|
|
458
|
-
context_get(slug, "phase:3")
|
|
459
|
-
context_list(slug)
|
|
476
|
+
context_get(slug=slug, session_id=SESSION_ID) # most recent checkpoint ("latest" is the default key)
|
|
477
|
+
context_get(slug=slug, key="phase:3", session_id=SESSION_ID) # specific phase
|
|
478
|
+
context_list(slug=slug, session_id=SESSION_ID) # all checkpoints
|
|
460
479
|
```
|
|
461
480
|
|
|
462
481
|
### Long-Session Progress
|
|
@@ -516,7 +535,7 @@ sequenceDiagram
|
|
|
516
535
|
participant T as Themis (Audit + Moderator)
|
|
517
536
|
|
|
518
537
|
U->>Z: /pantheon [--research] question
|
|
519
|
-
Z->>M: memory_search(council_decisions)
|
|
538
|
+
Z->>M: memory_search(query, namespace="council_decisions")
|
|
520
539
|
alt Precedent found (score > 0.85)
|
|
521
540
|
M-->>Z: ⚠️ Cached decision
|
|
522
541
|
Z->>U: Fast-path precedent
|
|
@@ -565,7 +584,7 @@ sequenceDiagram
|
|
|
565
584
|
## Dispatch Sequence (9-Step Protocol)
|
|
566
585
|
|
|
567
586
|
### Step 0 — Precedent Fast-Path (Fase 1)
|
|
568
|
-
Run the precedent read path defined in `## Memory Protocol > Council Decisions Namespace` (`memory_search(query, top_k=2, namespace="council_decisions")`). If no precedent applies, proceed to Step 0b.
|
|
587
|
+
Run the precedent read path defined in `## Memory Protocol > Council Decisions Namespace` (`memory_search(query=question, top_k=2, namespace="council_decisions")`). If no precedent applies, proceed to Step 0b.
|
|
569
588
|
|
|
570
589
|
### Step 0b — Apollo Pre-Scan (Fase 2, --research flag)
|
|
571
590
|
If `/pantheon --research <question>`: dispatch @apollo with 30s timeout. Inject findings as `shared_context` into ALL specialist prompts. Skip if flag absent.
|
package/CHANGELOG.md
CHANGED
|
@@ -18,6 +18,47 @@ 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.6] - 2026-10-05
|
|
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
|
+
- **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.
|
|
29
|
+
|
|
30
|
+
## 🐞 Fixed
|
|
31
|
+
|
|
32
|
+
- **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.
|
|
33
|
+
- **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.
|
|
34
|
+
- **`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.
|
|
35
|
+
## [v1.6.0-beta.5] - 2026-10-05
|
|
36
|
+
|
|
37
|
+
<!-- Add new changes here. Running `node scripts/versioning.mjs apply` will
|
|
38
|
+
move this section to a versioned entry and reset the template below. -->
|
|
39
|
+
|
|
40
|
+
## 🆕 What's New
|
|
41
|
+
|
|
42
|
+
- **O gate de geração do plugin passa a ler a versão do host — e a superfície de ferramentas deixa de desaparecer num host OpenCode 2.x.** O seletor de geração tinha três defaults `'v1'` (`bin/pantheon-init.mjs`, `scripts/install/opencode.mjs` e a assinatura do resolver em `scripts/install/opencode-version.mjs`). Nesse ramo, o installer grava caminhos de arquivo `.ts` na chave singular `plugin`; um host 2.x rejeita caminhos de arquivo ali (`configured plugin path must be a directory`), **descarta** as entradas e, ao fazer isso, **remove** a entrada de diretório V2 que já estava registrada e funcionando. O sintoma era um host aparentemente saudável — a frota MCP subia normalmente — com um único WARN no log e **nenhuma** ferramenta do plugin no catálogo: sem `pantheon_cost`, sem `hashline_edit`, sem `pantheon_model`, sem BackgroundJobBoard e sem hooks. Os três defaults passam a `'auto'`, e `auto` consulta a versão do host. Precedência: flag explícita > `OPENCODE_VERSION` > basename `opencode2` > probe de `--version` > aviso e fallback `v1`. Isto restaura as **3** ferramentas que o contrato V2 registra (`hashline_edit`, `pantheon_cost`, `pantheon_model`); não é paridade com o V1 — ver **Issues Conhecidas**.
|
|
43
|
+
- **Uma instalação na geração V2 e o `doctor` agora declaram a superfície reduzida em vez de deixá-la ser descoberta.** A lista de recursos não suportados no V2 (`getUnsupportedFeatures()`) não tinha nenhum consumidor em produção — só testes a liam. O installer passa a imprimi-la ao lado do aviso de destino V2, e o `doctor` a reporta como um achado próprio, sem alterar o código de saída (uma instalação V2 é uma configuração suportada, não quebrada). A V2 registra 3 ferramentas, não 6, e não tem BackgroundJobBoard; as 3 ferramentas de goal não são registradas na V2 por desenho. O texto agora é único, vindo de `src/pantheon/v2-unsupported.mjs`.
|
|
44
|
+
- **Renomeação dos entrypoints MCP (issue #198).** Os cinco entrypoints Python deixaram de compartilhar o token `server.py`, então um `pkill -f server.py` amplo não derruba mais a frota inteira como efeito colateral. Inclui uma migração em tempo de instalação para que as instalações existentes não fiquem órfãs.
|
|
45
|
+
- **O pacote npm deixou de versionar e distribuir a configuração pessoal de desenvolvimento do OpenCode.** `opencode.json` e `.opencode/` (comandos, plugins e skills) saíram do controle de versão: a config carregava um endpoint MCP privado e overrides de permissão por desenvolvedor, e o harness V1 de comandos/plugins foi substituído por `src/plugin-v2.ts`. O `init` continua gerando a config do projeto do usuário, então instalações não são afetadas; para contribuidores, um `opencode.json` pessoal deve ir em `.git/info/exclude`.
|
|
46
|
+
- **Documentação: `ROADMAP.md` reescrito e um novo documento de fronteira.** O roadmap foi reescrito com as causas-raiz verificadas, e um novo documento — `docs/PERMISSIONS-QUALITY-DELEGATION.md` — mapeia os gates de qualidade, as quatro camadas de permissão e a delegação num só lugar, marcando explicitamente o que ainda não foi verificado.
|
|
47
|
+
|
|
48
|
+
## 🐞 Fixed
|
|
49
|
+
|
|
50
|
+
- **A leitura do banner de versão do host era quadrática.** Um banner longo custava **11,1 s** para ser interpretado, contra o timeout de **5 s** do spawn de `--version`; o timeout guarda o processo, não a leitura, então um host verboso conseguia estourá-lo. A interpretação passou a ser **linear**.
|
|
51
|
+
- **O `readOnlyRegistry` do V2 não era podado no `session.deleted`.** O registro é global ao processo e nunca era limpo quando uma sessão do V2 terminava, então entradas de sessões encerradas acumulavam. O `session.deleted` do V2 passa a podar o registro, como a V1 já fazia.
|
|
52
|
+
|
|
53
|
+
## ⚠️ Known Issues
|
|
54
|
+
|
|
55
|
+
- **Ação necessária: re-executar o `init` numa instalação afetada.** O `postinstall` **não** roda o `init`. Quem teve a configuração corrompida por uma instalação `v1` anterior **não** é auto-corrigido apenas por atualizar o pacote — é preciso rodar o installer de novo (`npx pantheon-opencode init`). Uma escolha correta de geração **auto-corrige** a configuração (o ramo V2 já remove as referências `.ts` do V1), mas só quando o installer roda. O mesmo vale para a renomeação dos entrypoints: instalações existentes continuam funcionando porque os arquivos antigos são mantidos, mas os caminhos só são corrigidos numa nova execução do installer; até lá, esses usuários permanecem nos entrypoints antigos e sujeitos ao efeito colateral do `server.py`.
|
|
56
|
+
- **A superfície V2 é menor que a V1 por desenho.** A V2 registra 3 ferramentas (`hashline_edit`, `pantheon_cost`, `pantheon_model`), não 6, e não tem BackgroundJobBoard; as 3 `pantheon_goal_*` são V1-only e a matriz de delegação caller→target não é replicada. O installer e o `doctor` agora **dizem** isso (ver What's New), mas a funcionalidade ausente não é restaurada.
|
|
57
|
+
- **O fallback continua a ser `v1`.** Quando o probe do host falha, não consegue ser interpretado, ou traz versões contraditórias, o resolver avisa **uma vez** e cai para `v1`, em vez de arriscar um host 1.x com uma entrada `plugins` que ele ignoraria. É um erro alto e visível, mas ainda é uma queda para a configuração V1.
|
|
58
|
+
|
|
59
|
+
## ✅ Closed Issues
|
|
60
|
+
|
|
61
|
+
- **A justificativa da matriz de delegação V1→V2 foi corrigida.** O texto dizia que o V2 "não expõe esse caminho de semeadura"; os tipos do SDK refutam isso. A causa real da matriz não replicada não é a ausência de um caminho de semeadura (`session.created` do V2 traz `properties.info: Session` com `parentID?`, o mesmo campo que a V1 semeia), mas a *segunda* fonte da V1 — o seed de `client.session.list()` para sessões anteriores ao carregamento do plugin — porque o `PluginContext` do V2 não expõe `client`. Se um host 2.0.22 ao vivo popula `info.parentID` nesse evento continua **não verificado** (nenhum canário lê payload de evento). A linha publicada em `v1.6.0-beta.4` fica como registro.
|
|
21
62
|
## [v1.6.0-beta.4] - 2026-10-03
|
|
22
63
|
|
|
23
64
|
<!-- 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
|
|
@@ -89,6 +91,81 @@ services you choose to use. Check the
|
|
|
89
91
|
[releases](https://github.com/ils15/pantheon-opencode/releases) and
|
|
90
92
|
[changelog](CHANGELOG.md) for the latest published changes.
|
|
91
93
|
|
|
94
|
+
## Compatibility and support policy
|
|
95
|
+
|
|
96
|
+
> ### ⚠️ 1.6.x is the LAST line that supports OpenCode 1.X
|
|
97
|
+
>
|
|
98
|
+
> **OpenCode 1.X support ends after the 1.6 line.** From **1.7 onward, every
|
|
99
|
+
> release is a breaking change targeting OpenCode 2.** A 1.6.x install is the
|
|
100
|
+
> last one that runs on an OpenCode 1.X host; do not plan an upgrade across the
|
|
101
|
+
> 1.6 → 1.7 boundary while your host is still on OpenCode 1.X.
|
|
102
|
+
|
|
103
|
+
| Pantheon line | OpenCode 1.X host | OpenCode 2 host |
|
|
104
|
+
|---|---|---|
|
|
105
|
+
| **1.6.x** (current line) | **Supported.** V1 plugin contract | Supported, reduced surface — V2 contract |
|
|
106
|
+
| **1.7 and later** | **Not supported.** Breaking change | Target of the 1.7+ work |
|
|
107
|
+
|
|
108
|
+
Both columns of the 1.6.x row are real, and they are not the same claim. Read
|
|
109
|
+
[the plugin contract](#opencode-v1v2--dual-version-160-beta1) for what each
|
|
110
|
+
generation actually registers.
|
|
111
|
+
|
|
112
|
+
### What "supported on OpenCode 1.X" concretely means
|
|
113
|
+
|
|
114
|
+
On the 1.6 line, an OpenCode 1.X host gets the **V1 plugin**:
|
|
115
|
+
`src/plugin.ts` plus `src/plugins/pantheon-hooks.ts`, registered under the
|
|
116
|
+
singular `plugin` config key. That surface registers 6 tools
|
|
117
|
+
(`hashline_edit`, the 3 `pantheon_goal_*` tools, `pantheon_cost`,
|
|
118
|
+
`pantheon_model`), the BackgroundJobBoard lifecycle, the V1 event/tool hooks and
|
|
119
|
+
the V1 compaction path. It is selected automatically: the generation gate
|
|
120
|
+
(`--opencode-version`, else `OPENCODE_VERSION`, else a `OPENCODE_BIN` basename of
|
|
121
|
+
`opencode2`, else a `--version` probe where major ≥ 2 selects V2) resolves a 1.X
|
|
122
|
+
host to V1.
|
|
123
|
+
|
|
124
|
+
The two generations are exclusive. The installer strips Pantheon references from
|
|
125
|
+
both config shapes and registers only the selected one, so a 1.X host never
|
|
126
|
+
loads the V2 plugin and a V2 host never loads the V1 plugin. Forcing V2 on a 1.X
|
|
127
|
+
host is an unsupported mixed/wrong-generation configuration, not a supported mode.
|
|
128
|
+
|
|
129
|
+
### What the OpenCode 2 path is — and is not
|
|
130
|
+
|
|
131
|
+
**Not inert.** The V2 path (`src/plugin-v2`, registered as a directory because
|
|
132
|
+
the V2 loader rejects bare file paths) registers real tools with real
|
|
133
|
+
`input`/`output` schemas via `ctx.tool.transform()`, 5 event subscriptions,
|
|
134
|
+
session hooks and a tool `execute.before` hook that enforces read-only sessions.
|
|
135
|
+
It is a smaller surface than V1 by design, not a stub: the 3 goal tools and the
|
|
136
|
+
V1 caller→target delegation matrix are absent, and `getUnsupportedFeatures()`
|
|
137
|
+
reports that as `goal-tools` and `delegation-matrix`.
|
|
138
|
+
|
|
139
|
+
**Not complete either, and the V2 support claim is currently narrowed.** Two
|
|
140
|
+
facts, both recorded in this repository rather than smoothed over:
|
|
141
|
+
|
|
142
|
+
- **The host-backed V2 gate is red on the installable OpenCode CLI.** The V2 tool
|
|
143
|
+
canary (`tests/canary/plugin-v2-tool-canary.test.mjs`) was written against
|
|
144
|
+
`opencode 2.0.22`, which no npm channel publishes. Against the installable
|
|
145
|
+
`@opencode-ai/cli` host, `/api/experimental/session/{id}/wait` has been
|
|
146
|
+
promoted to `/api/session/{id}/wait` (the old path 404s) and `ctx.tool.list`
|
|
147
|
+
is absent, so the canary fails 12/12 there. That is a canary/host-generation
|
|
148
|
+
mismatch, not a measured plugin regression — with only the route renamed, 10/12
|
|
149
|
+
pass on the same host, including the edit being applied and the mutant still
|
|
150
|
+
caught. Tracked as [issue
|
|
151
|
+
#216](https://github.com/ils15/pantheon-opencode/issues/216); the fail-closed
|
|
152
|
+
CI change is [PR #213](https://github.com/ils15/pantheon-opencode/pull/213).
|
|
153
|
+
- **The 2.x host claims in `src/plugin-v2.ts` are measured against `2.0.22`
|
|
154
|
+
specifically**, not against the current installable CLI. Re-measurement
|
|
155
|
+
against the current host is outstanding and is tracked in the same issue.
|
|
156
|
+
|
|
157
|
+
Treat the 1.6 line's OpenCode 2 support as **real but partial**, and do not read
|
|
158
|
+
the 1.6.x row as "OpenCode 2 is finished".
|
|
159
|
+
|
|
160
|
+
### Verified against which OpenCode versions
|
|
161
|
+
|
|
162
|
+
| What | Verified against | How |
|
|
163
|
+
|---|---|---|
|
|
164
|
+
| V1 plugin + generation gate | The OpenCode 1.18.x line. This package pins `@opencode-ai/plugin` and `@opencode-ai/sdk` to `1.18.33`; the highest published `opencode-ai` host package (the one shipping the `opencode` binary) is `1.18.34` | Dependency pin (`package.json`); generation-gate unit tests over injected host banners; installer end-to-end tests asserting the emitted `opencode.json` shape |
|
|
165
|
+
| 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` |
|
|
166
|
+
| V2 against the current installable CLI | **Not verified.** Canary fails 12/12; see issue #216 | — |
|
|
167
|
+
| Exact 1.X host version the 1.6 line is exercised against end-to-end | **Unverified.** No V1 host leg exists: the sandbox runner is V2-only and `--run v1` is rejected | — |
|
|
168
|
+
|
|
92
169
|
## Delegation (native `task()`)
|
|
93
170
|
|
|
94
171
|
Pantheon delegates exclusively through OpenCode's native `task()` child-session
|
|
@@ -188,12 +265,13 @@ per installation; V1 and V2 Pantheon plugins must never be registered together.
|
|
|
188
265
|
|---|---|---|
|
|
189
266
|
| OpenCode config key | singular `plugin` | plural `plugins` |
|
|
190
267
|
| 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`),
|
|
268
|
+
| 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 |
|
|
192
269
|
| V1 APIs | Registered | Own tool definitions via `ctx.tool.transform()` — not the V1 plugin path |
|
|
193
270
|
|
|
194
271
|
The V2 plugin provides 3 orchestration tools (`hashline_edit`, `pantheon_cost`,
|
|
195
|
-
`pantheon_model`),
|
|
196
|
-
`session.error`, `session.compacted`), session hooks
|
|
272
|
+
`pantheon_model`), 5 event subscriptions (`session.created`, `session.idle`,
|
|
273
|
+
`session.deleted`, `session.error`, `session.compacted`), session hooks
|
|
274
|
+
(`prompt`, `context`),
|
|
197
275
|
and a tool `execute.before` hook that enforces read-only sessions. The 3 goal
|
|
198
276
|
tools are **not**
|
|
199
277
|
registered on V2: the goal loop needs a `GoalStore`, a `GoalLoopClient` and a
|
|
@@ -236,13 +314,22 @@ npx pantheon-opencode init --opencode-version v2
|
|
|
236
314
|
npx pantheon-opencode init --opencode-version auto
|
|
237
315
|
```
|
|
238
316
|
|
|
239
|
-
`--version v1|v2|auto` is accepted as the older
|
|
240
|
-
after `init`. `auto`
|
|
241
|
-
`OPENCODE_VERSION=v1|v2` wins; otherwise an
|
|
242
|
-
`
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
317
|
+
`auto` is the default. `--version v1|v2|auto` is accepted as the older
|
|
318
|
+
selector spelling when used after `init`. `auto` resolves the generation from
|
|
319
|
+
the host in this order: an explicit `OPENCODE_VERSION=v1|v2` wins; otherwise an
|
|
320
|
+
`OPENCODE_BIN` path ending in `opencode2` selects V2; otherwise the host
|
|
321
|
+
binary is asked for its `--version` and a major of 2 or more selects V2. Every
|
|
322
|
+
other case — an unreadable probe, an unparseable banner, or a banner whose
|
|
323
|
+
version-like tokens contradict each other with no tool name to break the tie —
|
|
324
|
+
warns once and falls back to V1, because a plural `plugins` directory entry on
|
|
325
|
+
an unknown 1.x host loses the plugin entirely.
|
|
326
|
+
|
|
327
|
+
The probe prefers the token that follows the tool name, so a runtime token
|
|
328
|
+
ahead of it (`node v22.1.0 (opencode 1.18.33)`) or a trailing build date
|
|
329
|
+
(`opencode v1.18.33 built 2026.10.04`) cannot flip the generation. The
|
|
330
|
+
installer removes Pantheon references from both config shapes before writing
|
|
331
|
+
only the selected Pantheon registration. Third-party entries are not converted
|
|
332
|
+
or claimed by this rule.
|
|
246
333
|
|
|
247
334
|
The `pantheon_cost` report resolves its database by PATH, in this order: an
|
|
248
335
|
explicit `dbPath` supplied by the tool caller, then
|
|
@@ -291,6 +378,11 @@ Key order does not matter.
|
|
|
291
378
|
|
|
292
379
|
## Updating between releases (beta.5+)
|
|
293
380
|
|
|
381
|
+
> **Read [Compatibility and support policy](#compatibility-and-support-policy)
|
|
382
|
+
> before upgrading across a line boundary.** 1.6.x is the last line that
|
|
383
|
+
> supports an OpenCode 1.X host; 1.7+ is breaking-change territory targeting
|
|
384
|
+
> OpenCode 2. Within the 1.6 line, `update` is the supported path.
|
|
385
|
+
|
|
294
386
|
One command keeps an existing installation current:
|
|
295
387
|
|
|
296
388
|
```bash
|
|
@@ -450,7 +542,7 @@ in the sandbox root) · `2` usage error · `3` sandbox not prepared.
|
|
|
450
542
|
|
|
451
543
|
### Intentional memory MCP divergence
|
|
452
544
|
|
|
453
|
-
`scripts/
|
|
545
|
+
`scripts/memory_mcp.py` and `src/mcp/memory_mcp.py` are
|
|
454
546
|
intentionally different. The standalone `scripts/` copy keeps the lightweight
|
|
455
547
|
`memory_*` contract; the installed `src/mcp/` copy additionally exposes the
|
|
456
548
|
optional codemap schema and `code_index`, `code_query`, and `code_neighbors`.
|
|
@@ -499,6 +591,16 @@ Ideas, bug reports, documentation improvements, and code contributions are
|
|
|
499
591
|
welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening an issue
|
|
500
592
|
or pull request.
|
|
501
593
|
|
|
594
|
+
### Project-level `opencode.json`
|
|
595
|
+
|
|
596
|
+
The published package carries no `opencode.json` template. `init` still writes
|
|
597
|
+
your project's `opencode.json` itself, and the few product defaults an install
|
|
598
|
+
seeds — `default_agent: zeus` and `permission.skill` — come from the installer
|
|
599
|
+
code, not from a packaged file. Contributors who keep a project-level
|
|
600
|
+
`opencode.json` for their own OpenCode sessions should leave it untracked —
|
|
601
|
+
`.git/info/exclude` per clone, or a shared `.gitignore` decision — rather than
|
|
602
|
+
versioning it.
|
|
603
|
+
|
|
502
604
|
## Citation and DOI
|
|
503
605
|
|
|
504
606
|
Pantheon is released under the [MIT License](LICENSE). Cite the
|
package/README.pt-BR.md
CHANGED
|
@@ -171,11 +171,20 @@ npx pantheon-opencode init --opencode-version v2
|
|
|
171
171
|
npx pantheon-opencode init --opencode-version auto
|
|
172
172
|
```
|
|
173
173
|
|
|
174
|
-
`--version v1|v2|auto` é aceito como a grafia antiga do seletor
|
|
175
|
-
depois de `init`. `auto`
|
|
176
|
-
|
|
177
|
-
terminando em `opencode2` seleciona V2;
|
|
178
|
-
|
|
174
|
+
`auto` é o padrão. `--version v1|v2|auto` é aceito como a grafia antiga do seletor
|
|
175
|
+
quando usado depois de `init`. `auto` resolve a geração a partir do host nesta
|
|
176
|
+
ordem: um `OPENCODE_VERSION=v1|v2` explícito vence; caso contrário, um
|
|
177
|
+
`OPENCODE_BIN` terminando em `opencode2` seleciona V2; caso contrário o binário
|
|
178
|
+
do host é consultado com `--version` e uma major >= 2 seleciona V2. Qualquer
|
|
179
|
+
outro caso — uma sonda ilegível, um banner não interpretável, ou um banner
|
|
180
|
+
cujos tokens de versão se contradizem sem um nome de ferramenta que desfaça o
|
|
181
|
+
empate — avisa uma vez e volta para V1, porque uma entrada de diretório em
|
|
182
|
+
`plugins` plural em um host 1.x desconhecido perde o plugin inteiro.
|
|
183
|
+
|
|
184
|
+
A sonda prefere o token que vem logo após o nome da ferramenta, então um token
|
|
185
|
+
de runtime antes dele (`node v22.1.0 (opencode 1.18.33)`) ou uma data de build
|
|
186
|
+
no final (`opencode v1.18.33 built 2026.10.04`) não conseguem virar a geração.
|
|
187
|
+
O instalador remove referências Pantheon das duas formas de config antes de
|
|
179
188
|
gravar apenas o registro Pantheon selecionado. Entradas de terceiros não são
|
|
180
189
|
convertidas nem reivindicadas por essa regra.
|
|
181
190
|
|
|
@@ -344,7 +353,7 @@ preparado.
|
|
|
344
353
|
|
|
345
354
|
### Divergência intencional do memory MCP
|
|
346
355
|
|
|
347
|
-
`scripts/
|
|
356
|
+
`scripts/memory_mcp.py` e `src/mcp/memory_mcp.py` são
|
|
348
357
|
intencionalmente diferentes. A cópia independente em `scripts/` mantém o
|
|
349
358
|
contrato leve de `memory_*`; a cópia instalada em `src/mcp/` também expõe o
|
|
350
359
|
schema opcional de codemap e `code_index`, `code_query` e `code_neighbors`. As
|
package/bin/pantheon-init.mjs
CHANGED
|
@@ -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
|
-
*
|
|
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 ?? '
|
|
427
|
+
version: versionOpt ?? 'auto',
|
|
428
|
+
mergeDevConfig: mergeDevConfigOpt,
|
|
406
429
|
})
|
|
407
430
|
} catch (err) {
|
|
408
431
|
if (err?.message === 'Canceled') {
|
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.6",
|
|
4
4
|
"description": "Multi-agent orchestration for OpenCode — 14 specialized agents, TDD, Themis review gates.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"workspaces": [
|
|
@@ -41,12 +41,12 @@
|
|
|
41
41
|
"hooks:install": "pre-commit install",
|
|
42
42
|
"hooks:update": "pre-commit autoupdate",
|
|
43
43
|
"test:security": "npm run secret-scan",
|
|
44
|
-
"test:node": "node --test tests/*.mjs tests/pantheon/*.mjs",
|
|
45
|
-
"coverage": "echo 'Node coverage (report-only, NO threshold is enforced).' && echo 'Covers: the .mjs/.js modules under scripts/, src/ and bin/ that test:node exercises.' && echo 'Does NOT cover: test:ts (hand-rolled tsx loop, no node --test runner) and test:ci (pytest).' && echo ' TypeScript under src/ (41 files) is therefore entirely unmeasured here.' && echo '' && node --
|
|
44
|
+
"test:node": "node scripts/run-node-tests.mjs --label 'test:node' 'tests/*.mjs' 'tests/pantheon/*.mjs'",
|
|
45
|
+
"coverage": "echo 'Node coverage (report-only, NO threshold is enforced).' && echo 'Covers: the .mjs/.js modules under scripts/, src/ and bin/ that test:node exercises.' && echo 'Does NOT cover: test:ts (hand-rolled tsx loop, no node --test runner) and test:ci (pytest).' && echo ' TypeScript under src/ (41 files) is therefore entirely unmeasured here.' && echo '' && node scripts/run-node-tests.mjs --label 'coverage' -- --experimental-test-coverage --test-coverage-include='scripts/**/*.mjs' --test-coverage-include='src/**/*.mjs' --test-coverage-include='src/**/*.js' --test-coverage-include='bin/**/*.mjs' 'tests/*.mjs' 'tests/pantheon/*.mjs'",
|
|
46
46
|
"coverage:plugin-v2": "node scripts/check-plugin-v2-coverage.mjs",
|
|
47
47
|
"test:ts": "for f in tests/pantheon/*.test.ts; do if [ \"$f\" = tests/pantheon/plugin-v2-contract.test.ts ]; then NODE_OPTIONS=--conditions=import tsx \"$f\"; else tsx \"$f\"; fi || exit 1; done",
|
|
48
|
-
"test:hooks": "node --test tests/pantheon/plugin-v2-hook-canary.test.mjs",
|
|
49
|
-
"test:tool-canary": "node --test tests/canary/plugin-v2-tool-canary.test.mjs",
|
|
48
|
+
"test:hooks": "node scripts/run-node-tests.mjs --label 'test:hooks' 'tests/pantheon/plugin-v2-hook-canary.test.mjs'",
|
|
49
|
+
"test:tool-canary": "node scripts/run-node-tests.mjs --label 'test:tool-canary' 'tests/canary/plugin-v2-tool-canary.test.mjs'",
|
|
50
50
|
"test:all": "npm run test:ci && npm run test:node && npm run test:ts",
|
|
51
51
|
"test": "npm run test:all",
|
|
52
52
|
"test:ci": "python3 -m pytest -q --tb=short 2>&1"
|
|
@@ -76,7 +76,6 @@
|
|
|
76
76
|
"bin/*.mjs",
|
|
77
77
|
"AGENTS.md",
|
|
78
78
|
"CHANGELOG.md",
|
|
79
|
-
"opencode.json",
|
|
80
79
|
"src/mcp/*.py",
|
|
81
80
|
"src/instructions/*.instructions.md",
|
|
82
81
|
"src/mcp/*.mjs",
|
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.6",
|
|
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.
|
|
7
|
+
version = "1.6.0-beta.6"
|
|
8
8
|
description = "Multi-agent orchestration framework"
|
|
9
9
|
requires-python = ">=3.11"
|
|
10
10
|
dependencies = []
|
|
@@ -39,11 +39,11 @@ select = ["E", "F", "W", "I", "N", "UP", "B", "SIM", "PL", "RUF", "C901"]
|
|
|
39
39
|
"tests/test_memory_mcp_server.py" = ["PLC0415", "PLR2004"]
|
|
40
40
|
# Existing public APIs and test fixtures are intentionally broad/simple; refactoring
|
|
41
41
|
# them would be behavior-affecting rather than a mechanical lint correction.
|
|
42
|
-
"scripts/
|
|
43
|
-
"src/mcp/
|
|
44
|
-
"scripts/
|
|
45
|
-
"src/mcp/
|
|
46
|
-
"scripts/
|
|
42
|
+
"scripts/code_mode.py" = ["PLR0913", "PLR0917"]
|
|
43
|
+
"src/mcp/code_mode.py" = ["PLR0913", "PLR0917"]
|
|
44
|
+
"scripts/mcp_persistence.py" = ["PLR0913", "PLR0917"]
|
|
45
|
+
"src/mcp/mcp_persistence.py" = ["PLR0913", "PLR0917"]
|
|
46
|
+
"scripts/memory_mcp.py" = ["C901"]
|
|
47
47
|
"src/mcp/eval_store.py" = ["PLR2004"]
|
|
48
48
|
"tests/test_code_mode_frontmatter.py" = ["PLR2004"]
|
|
49
49
|
"tests/test_eval.py" = ["PLR2004"]
|
|
@@ -5,12 +5,12 @@ Provides a confined execution environment for orchestration scripts
|
|
|
5
5
|
via MCP tools and resources.
|
|
6
6
|
|
|
7
7
|
Usage:
|
|
8
|
-
python scripts/
|
|
8
|
+
python scripts/code_mode.py
|
|
9
9
|
|
|
10
10
|
Or via MCP client (stdio transport):
|
|
11
11
|
pantheon-code-mode:
|
|
12
12
|
command: python
|
|
13
|
-
args: ["scripts/
|
|
13
|
+
args: ["scripts/code_mode.py"]
|
|
14
14
|
"""
|
|
15
15
|
|
|
16
16
|
from __future__ import annotations
|