pantheon-opencode 1.6.0-beta.1 → 1.6.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (120) hide show
  1. package/AGENTS.global.md +182 -0
  2. package/AGENTS.md +10 -891
  3. package/CHANGELOG.md +326 -0
  4. package/README.md +496 -32
  5. package/README.pt-BR.md +285 -20
  6. package/bin/pantheon-init.mjs +26 -3
  7. package/commands/pantheon-audit.md +7 -1
  8. package/commands/pantheon-consolidate.md +1 -1
  9. package/commands/pantheon-deepwork.md +14 -3
  10. package/commands/pantheon-focus.md +17 -0
  11. package/commands/pantheon-vision.md +61 -12
  12. package/package.json +21 -14
  13. package/plugin.json +2 -2
  14. package/pyproject.toml +8 -6
  15. package/scripts/build-agents-md.mjs +374 -56
  16. package/scripts/changelog-merge.mjs +161 -0
  17. package/scripts/{code_mode_server.py → code_mode.py} +3 -3
  18. package/scripts/cost.mjs +244 -41
  19. package/scripts/doctor.mjs +151 -1
  20. package/scripts/install/agents-md.mjs +4 -4
  21. package/scripts/install/config-migration.mjs +317 -4
  22. package/scripts/install/health-check.mjs +21 -19
  23. package/scripts/install/interactive.mjs +1 -1
  24. package/scripts/install/opencode-version.mjs +246 -4
  25. package/scripts/install/opencode.mjs +627 -179
  26. package/scripts/install/plugin.mjs +43 -9
  27. package/scripts/install/shared.mjs +120 -12
  28. package/scripts/install/vision-prompt.mjs +161 -0
  29. package/scripts/install-mcp.mjs +28 -9
  30. package/scripts/{mcp_persistence_server.py → mcp_persistence.py} +2 -2
  31. package/{src/mcp/mcp_resources_server.py → scripts/mcp_resources.py} +2 -2
  32. package/scripts/{memory_mcp_server.py → memory_mcp.py} +2 -2
  33. package/scripts/probe-context-rehydrate.mjs +8 -2
  34. package/scripts/probe-pantheon-cost.mjs +71 -15
  35. package/scripts/run-node-tests.mjs +189 -0
  36. package/scripts/sync-artifacts.mjs +26 -13
  37. package/scripts/sync-tui.mjs +24 -3
  38. package/scripts/test-opencode-v2-sandbox.sh +180 -26
  39. package/scripts/validate-routing.mjs +3 -3
  40. package/scripts/validate-sandbox-install.mjs +138 -0
  41. package/scripts/versioning.mjs +13 -1
  42. package/scripts/vision-status.mjs +682 -0
  43. package/skills-lock.json +8 -8
  44. package/src/agents/aphrodite.md +20 -37
  45. package/src/agents/apollo.md +7 -3
  46. package/src/agents/athena.md +63 -35
  47. package/src/agents/demeter.md +8 -28
  48. package/src/agents/gaia.md +1 -1
  49. package/src/agents/hephaestus.md +10 -21
  50. package/src/agents/hermes.md +15 -38
  51. package/src/agents/iris.md +1 -1
  52. package/src/agents/mnemosyne.md +18 -54
  53. package/src/agents/nyx.md +1 -1
  54. package/src/agents/prometheus.md +16 -20
  55. package/src/agents/talos.md +10 -2
  56. package/src/agents/themis.md +5 -5
  57. package/src/agents/zeus.md +99 -129
  58. package/src/instructions/agent-return-format.instructions.md +18 -3
  59. package/src/instructions/backend-standards.instructions.md +2 -0
  60. package/src/instructions/frontend-standards.instructions.md +3 -1
  61. package/src/instructions/memory-protocol.instructions.md +11 -110
  62. package/src/instructions/zeus-anti-stall.instructions.md +14 -61
  63. package/src/instructions/zeus-communication-rules.instructions.md +0 -1
  64. package/src/instructions/zeus-council-synthesis.instructions.md +32 -260
  65. package/src/instructions/zeus-memory-operations.instructions.md +26 -0
  66. package/src/instructions/zeus-timeout-retry.instructions.md +40 -87
  67. package/src/mcp/{code_mode_server.py → code_mode.py} +3 -3
  68. package/src/mcp/eval_store.py +2 -2
  69. package/src/mcp/{mcp_persistence_server.py → mcp_persistence.py} +2 -2
  70. package/{scripts/mcp_resources_server.py → src/mcp/mcp_resources.py} +2 -2
  71. package/src/mcp/{memory_mcp_server.py → memory_mcp.py} +2 -2
  72. package/src/mcp/{pantheon_vision_server.py → pantheon_vision.py} +286 -42
  73. package/src/mcp/requirements-mcp.txt +6 -4
  74. package/src/mcp/requirements-vision.txt +2 -2
  75. package/src/pantheon/cost-command.ts +399 -101
  76. package/src/pantheon/delegation-enforce.ts +10 -1
  77. package/src/pantheon/presets.d.mts +0 -8
  78. package/src/pantheon/presets.mjs +5 -32
  79. package/src/pantheon/v2-bounded-read.ts +640 -0
  80. package/src/pantheon/v2-delegation-enforce.ts +214 -0
  81. package/src/pantheon/v2-execute-after.ts +186 -0
  82. package/src/pantheon/v2-tools.ts +429 -0
  83. package/src/pantheon/v2-unsupported.d.mts +11 -0
  84. package/src/pantheon/v2-unsupported.mjs +90 -0
  85. package/src/pantheon/v2-vision.ts +622 -0
  86. package/src/pantheon/vision-local.ts +531 -0
  87. package/src/pantheon/vision.ts +1160 -115
  88. package/src/plugin-v2.ts +1145 -219
  89. package/src/plugin.ts +12 -9
  90. package/src/plugins/tui/dist/server.d.ts +1 -2
  91. package/src/plugins/tui/dist/server.d.ts.map +1 -1
  92. package/src/plugins/tui/dist/tui-v2.d.ts +154 -0
  93. package/src/plugins/tui/dist/tui-v2.d.ts.map +1 -0
  94. package/src/plugins/tui/dist/tui-v2.js +659 -0
  95. package/src/plugins/tui/dist/tui-v2.js.map +1 -0
  96. package/src/plugins/tui/dist/tui.d.ts +85 -82
  97. package/src/plugins/tui/dist/tui.d.ts.map +1 -1
  98. package/src/plugins/tui/dist/tui.js +72 -59
  99. package/src/plugins/tui/index-v2.ts +6 -0
  100. package/src/plugins/tui/package-lock.json +5516 -1353
  101. package/src/plugins/tui/package.json +22 -12
  102. package/src/plugins/tui/src/index-v2.tsx +734 -0
  103. package/src/plugins/tui/src/index.tsx +106 -85
  104. package/src/plugins/tui/src/opencode-v2.d.ts +13 -0
  105. package/src/plugins/tui/tsconfig.build.json +5 -0
  106. package/src/plugins/tui/tsconfig.typecheck.json +5 -0
  107. package/src/plugins/tui/tsdown.config.ts +22 -2
  108. package/src/plugins/tui/tui-v2.ts +2 -0
  109. package/src/plugins/tui/tui.ts +3 -0
  110. package/src/routing.yml +11 -21
  111. package/src/skills/README.md +3 -3
  112. package/src/skills/agent-coordination/SKILL.md +7 -2
  113. package/src/skills/artifact-management/SKILL.md +12 -5
  114. package/src/skills/auto-continue/SKILL.md +39 -30
  115. package/src/skills/code-review-checklist/SKILL.md +5 -5
  116. package/src/skills/context-compression/SKILL.md +26 -879
  117. package/src/skills/session-goal/SKILL.md +14 -5
  118. package/src/skills/spec-driven-development/SKILL.md +3 -1
  119. package/src/skills/tdd-with-agents/SKILL.md +18 -10
  120. package/opencode.json +0 -58
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
@@ -50,6 +52,11 @@ opencode
50
52
  The installer guides you through the available setup. For optional MCP servers,
51
53
  project-local installation, or non-interactive setup, see the
52
54
  [installation guide](docs/INSTALLATION.md).
55
+ The bundled Python MCP servers use the pinned MCP SDK 2.2.0 and standalone
56
+ FastMCP 4.0.10 runtime; see the [MCP guide](docs/MCP.md).
57
+ The installer also turns each agent's `mcp_tools` allowlist into native
58
+ per-agent permissions for OpenCode V1 and V2; see the
59
+ [agent MCP reference](docs/AGENT-MCP.md).
53
60
 
54
61
  ## A simple example
55
62
 
@@ -60,6 +67,10 @@ Once OpenCode is running, describe the outcome you want:
60
67
  ```
61
68
 
62
69
  Pantheon helps turn that request into a plan and a sequence of reviewed steps.
70
+ When you ask for a plan or start `/pantheon-deepwork`, Athena returns the full
71
+ plan to Zeus, who displays it in the main conversation before asking for
72
+ approval. The approval prompt will not point to a plan hidden in a child-agent
73
+ conversation.
63
74
 
64
75
  ## Who is it for?
65
76
 
@@ -76,13 +87,100 @@ clear handoff between stages of work.
76
87
  - Project memory that helps preserve relevant context between sessions.
77
88
  - Optional integrations for common development tasks.
78
89
 
90
+ Memory is used selectively: the coordinator searches once only when project
91
+ history could affect a task, then passes relevant results to specialists. Store
92
+ one concise, reusable outcome at task completion when it will matter later;
93
+ routine child summaries and phase updates stay in the current handoff. The
94
+ session-checkpoint tools are separate, optional persistence APIs and are not
95
+ called automatically by compaction hooks. See [Memory usage](docs/MEMORY.md).
96
+
79
97
  ## Status
80
98
 
81
- Operational checkout version: **v1.6.0-beta.1** (first beta compatible with
82
- OpenCode 2; publication is not asserted here). Pantheon is designed for OpenCode and depends on the
83
- availability and configuration of OpenCode and any optional services you choose
84
- to use. Check the [releases](https://github.com/ils15/pantheon-opencode/releases)
85
- and [changelog](CHANGELOG.md) for the latest published changes.
99
+ Candidate version: the manifests in this checkout express the version being
100
+ prepared, not a confirmed publication. A beta is published only after the
101
+ Release workflow completes successfully. To check which version is actually
102
+ published, consult the npm `beta` dist-tag. Pantheon is designed for OpenCode
103
+ and depends on the availability and configuration of OpenCode and any optional
104
+ services you choose to use. Check the
105
+ [releases](https://github.com/ils15/pantheon-opencode/releases) and
106
+ [changelog](CHANGELOG.md) for the latest published changes.
107
+
108
+ ## Compatibility and support policy
109
+
110
+ > ### ⚠️ 1.6.x is the LAST line that supports OpenCode 1.X
111
+ >
112
+ > **OpenCode 1.X support ends after the 1.6 line.** From **1.7 onward, every
113
+ > release is a breaking change targeting OpenCode 2.** A 1.6.x install is the
114
+ > last one that runs on an OpenCode 1.X host; do not plan an upgrade across the
115
+ > 1.6 → 1.7 boundary while your host is still on OpenCode 1.X.
116
+
117
+ | Pantheon line | OpenCode 1.X host | OpenCode 2 host |
118
+ |---|---|---|
119
+ | **1.6.x** (current line) | **Supported.** V1 plugin contract | Supported, reduced surface — V2 contract |
120
+ | **1.7 and later** | **Not supported.** Breaking change | Target of the 1.7+ work |
121
+
122
+ Both columns of the 1.6.x row are real, and they are not the same claim. Read
123
+ [the plugin contract](#opencode-v1v2--dual-version-160-beta1) for what each
124
+ generation actually registers.
125
+
126
+ ### What "supported on OpenCode 1.X" concretely means
127
+
128
+ On the 1.6 line, an OpenCode 1.X host gets the **V1 plugin**:
129
+ `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts`, registered under the
130
+ singular `plugin` config key. That surface registers 6 tools
131
+ (`hashline_edit`, the 3 `pantheon_goal_*` tools, `pantheon_cost`,
132
+ `pantheon_model`), the BackgroundJobBoard lifecycle, the V1 event/tool hooks and
133
+ the V1 compaction path. It is selected automatically: the generation gate
134
+ (`--opencode-version`, else `OPENCODE_VERSION`, else a `OPENCODE_BIN` basename of
135
+ `opencode2`, else a `--version` probe where major ≥ 2 selects V2) resolves a 1.X
136
+ host to V1.
137
+
138
+ The two generations are exclusive. The installer strips Pantheon references from
139
+ both config shapes and registers only the selected one, so a 1.X host never
140
+ loads the V2 plugin and a V2 host never loads the V1 plugin. Forcing V2 on a 1.X
141
+ host is an unsupported mixed/wrong-generation configuration, not a supported mode.
142
+
143
+ ### What the OpenCode 2 path is — and is not
144
+
145
+ **Not inert.** The V2 path (`src/plugin-v2`, registered as a directory because
146
+ the V2 loader rejects bare file paths) registers real tools with real
147
+ `input`/`output` schemas via `ctx.tool.transform()`, 5 event subscriptions,
148
+ session hooks and tool/permission hooks that enforce read-only sessions and the
149
+ caller→target delegation matrix. The matrix applies only to Pantheon-managed
150
+ targets: Zeus may delegate to any registered agent; Athena and Hermes may target
151
+ Apollo only; other Pantheon callers and unknown callers are denied. Child
152
+ sessions cannot delegate to Pantheon agents. Calls between native/custom agents
153
+ remain under host permissions. The V2 path never adds an allow grant or
154
+ overrides an explicit host deny; missing or mismatched identity fails closed
155
+ for the attempted Pantheon delegation. The 3 goal tools remain unsupported and
156
+ are reported as `goal-tools`.
157
+
158
+ When the host successfully registers V2's permission hook, Pantheon does not
159
+ trust `permission.evaluate.agent` by itself for a Pantheon target. It matches
160
+ the permission source's session, message and tool-call IDs to a short-lived
161
+ record from the host's `tool.execute.before` event, then requires the host
162
+ session to have no `parentID` before applying the matrix. This admits valid
163
+ root dispatches and denies child-session dispatches; missing, stale, replayed
164
+ or mismatched origins are denied. OpenCode v2.0.29 runtime evidence is in
165
+ [`bench/results/f4a-v229-admission-identity-2026-10-14.md`](bench/results/f4a-v229-admission-identity-2026-10-14.md).
166
+
167
+ **Partial, with the exercised host version made explicit.** The V2 tool canary
168
+ started against `opencode 2.0.22`, a version that no npm channel publishes.
169
+ The current F4A rerun now uses the installable **OpenCode v2.0.29** binary and
170
+ passes 18/18 checks with permission probes: the real plugin registers and runs
171
+ its tools, admits the valid Zeus→Apollo root dispatch, rejects an invalid edge
172
+ before child creation, and rejects a matrix-valid dispatch from a child. The
173
+ remaining V2 surface still has unsupported goal tools and registration-only
174
+ session/compaction hooks, so the 1.6 line is not full V2 feature parity.
175
+
176
+ ### Verified against which OpenCode versions
177
+
178
+ | What | Verified against | How |
179
+ |---|---|---|
180
+ | 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 |
181
+ | V2 plugin tool surface | OpenCode v2.0.29 | `tests/canary/plugin-v2-tool-canary.test.mjs`, driving the real plugin through `opencode serve`; F4A permission canary passes 18/18 |
182
+ | V2 native subagent admission | OpenCode v2.0.29 | `tests/canary/run-v2-permission-proof.sh`; identity, root/child checks and permission-before-child ordering are recorded in [`bench/results/f4a-v229-admission-identity-2026-10-14.md`](bench/results/f4a-v229-admission-identity-2026-10-14.md) |
183
+ | 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 | — |
86
184
 
87
185
  ## Delegation (native `task()`)
88
186
 
@@ -93,6 +191,28 @@ there is no Pantheon-specific delegation tool surface to configure. See
93
191
  [ADR-0011](.pantheon/memory-bank/adr/0011-delegation-engine-contract.md) for the
94
192
  historical engine contract.
95
193
 
194
+ This beta.8 candidate combines native per-agent MCP permissions for OpenCode V1
195
+ and V2, V2 delegation-permission alignment, simpler memory/compression
196
+ instructions, and a sandbox check that proves the installed package matches
197
+ this checkout instead of silently accepting stale npm-cached code. The isolated
198
+ sandbox launcher also pins the OpenCode background service to its dedicated
199
+ loopback port, rather than colliding with another OpenCode installation. The Zeus
200
+ prompt reuses one task-start memory-search result for context and routing;
201
+ runtime call counts and latency have not been measured. A beta.7 V2 dispatch
202
+ failed because the permission hook passed a bare string to `ctx.session.get`
203
+ instead of the V2 input object `{ sessionID }`; beta.8 corrects the call and
204
+ adds contract tests for the success and failure cases. The user subsequently
205
+ reported a successful Hermes liveness delegation in the active session, but
206
+ freshly restarting and testing the beta.8 sandbox remains the end-to-end gate.
207
+ The original report also included a separate `GET /api/session/{id}/permission`
208
+ 404; the session ID exists in the beta7-candidate database but not the default
209
+ global database. Both OpenCode services were running, so the 404 in the global
210
+ log may come from the other instance; this remains an end-to-end verification
211
+ item.
212
+
213
+ Delegated tasks get at most one retry after an initial timeout or failure. If
214
+ that retry fails, the configured fallback or escalation chain applies.
215
+
96
216
  ## Cost tool backend
97
217
 
98
218
  `pantheon_cost` prefers a read-only `node:sqlite` backend against the selected
@@ -183,16 +303,128 @@ per installation; V1 and V2 Pantheon plugins must never be registered together.
183
303
  |---|---|---|
184
304
  | OpenCode config key | singular `plugin` | plural `plugins` |
185
305
  | Pantheon registration | `src/plugin.ts` plus `src/plugins/pantheon-hooks.ts` | `<installed>/src/plugin-v2` directory (`index.ts` re-exports `src/plugin-v2.ts`) |
186
- | 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 |
306
+ | 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 orchestration tools plus `vision_describe` when the model catalog is available, 5 event subscriptions, session hooks (`prompt`, `context`), a read-only-enforcing tool `execute.before` hook, plus configuration transforms |
187
307
  | V1 APIs | Registered | Own tool definitions via `ctx.tool.transform()` — not the V1 plugin path |
188
308
 
189
- The V2 plugin provides 6 orchestration tools (`hashline_edit`,
190
- `pantheon_goal_create`, `pantheon_goal_get`, `pantheon_goal_update`,
191
- `pantheon_cost`, `pantheon_model`), 4 event subscriptions (`session.created`,
192
- `session.idle`, `session.error`, `session.compacted`), session hooks (`prompt`,
193
- `context`), and tool hooks (`execute.before`, `execute.after`). Unsupported V2
194
- features are `legacy-hooks` (the V1-specific hook surface), `catalog-transform`,
195
- `integration-transform`, and `skill-transform`.
309
+ The V2 plugin provides 3 orchestration tools (`hashline_edit`, `pantheon_cost`,
310
+ `pantheon_model`), 5 event subscriptions (`session.created`, `session.idle`,
311
+ `session.deleted`, `session.error`, `session.compacted`), session hooks
312
+ (`prompt`, `context`),
313
+ and a tool `execute.before` hook that enforces read-only sessions. The 3 goal
314
+ tools are **not**
315
+ registered on V2: the goal loop needs a `GoalStore`, a `GoalLoopClient` and a
316
+ `BackgroundJobBoard`, none of which the V2 `PluginContext` exposes, so the gap
317
+ is reported as the `goal-tools` unsupported-feature marker. Use the V1
318
+ contract if you need the goal loop.
319
+
320
+ V2 also registers `vision_describe` when `ctx.model.list()` is available. It
321
+ checks the live catalog for image input, prefers the paid OpenCode Go
322
+ `opencode-go/mimo-v2.6-flash` model (free-tier models are excluded from automatic
323
+ selection — the direct gateway rejects them with HTTP 403, they only work from
324
+ inside OpenCode; an explicit `PANTHEON_VISION_MODEL`/config/preset pin is still
325
+ honored, so its 403 surfaces as an actionable error rather than a silent
326
+ substitution), and
327
+ sends the image directly to the authenticated OpenCode Zen endpoint. The request
328
+ carries the live session id as the Zen-only `x-opencode-session` header the
329
+ gateway requires (never sent to a non-Zen provider, and never logged). OpenCode
330
+ credentials come from
331
+ `opencode auth login` or `PANTHEON_OPENCODE_API_KEY`; if no supported model or
332
+ credentials are available, the tool returns an explicit error instead of a
333
+ fabricated description. This path works without the optional V1 bridge.
334
+ The V2 prompt hook also preserves image attachment references and tells Zeus
335
+ to inspect relevant visual context and pass the reference plus concise findings
336
+ to Aphrodite. Inline image bytes are not copied into persisted prompt text, and
337
+ an image does not authorize deleting or reverting unrelated work.
338
+
339
+ The chat-turn native path picks its vision model in a fixed precedence: the
340
+ `PANTHEON_VISION_MODEL` env var, then `visionModel` in `opencode-vision.json`,
341
+ then the active preset's `vision.model`, then automatic discovery in the host
342
+ provider catalog (`GET /config/providers`), then the built-in default. Discovery
343
+ is conservative and paid-only: it keeps only image-capable entries
344
+ (`capabilities.input.image`) whose provider is a trusted Zen provider or whose
345
+ `npm` package is OpenAI-compatible (`@ai-sdk/openai-compatible` /
346
+ `@ai-sdk/openai`), EXCLUDES free-tier entries (`-free` id or `cost.input <= 0`
347
+ — the direct gateway rejects them with HTTP 403), picks the cheapest remaining
348
+ entry, and caches the catalog for 60
349
+ seconds per process; an incompatible model simply falls through to the vision
350
+ MCP tool. The base URL comes from the catalog entry's `api.url`, and the legacy
351
+ Zen endpoints remain the no-catalog fallback. Credentials follow the endpoint:
352
+ for a Zen endpoint the shared `PANTHEON_OPENCODE_API_KEY` / `OPENCODE_API_KEY`
353
+ env keys are tried first, then the OpenCode auth store (the resolved provider
354
+ first, then the legacy `opencode-go` / `opencode` entries); for a non-Zen
355
+ endpoint only that provider's own auth-store entry is used — the shared env keys
356
+ and the legacy Zen entries are never attached to a non-Zen base URL. An
357
+ explicitly configured, qualifying vision model always wins over discovery — a
358
+ pin that does not qualify (non-Zen, text-only, or absent from the catalog) is
359
+ discarded and the automatic selection takes over. `pantheon-opencode init`
360
+ offers an optional vision step in interactive TTY sessions — automatic discovery
361
+ is the default and writes nothing; pinning merges `visionModel` into the global
362
+ `opencode-vision.json`; non-interactive runs never prompt and never write.
363
+ The `/pantheon-vision` command adds a model picker: `vision-status.mjs --list`
364
+ enumerates image-capable candidates — labelling whether the source is the live
365
+ host catalog or an offline `opencode models` heuristic, plus `free`/`paid` and
366
+ credential presence per provider (never the token) — and `--set` pins the chosen
367
+ `provider/model` with the same atomic merge.
368
+
369
+ The user's question is injected into the vision prompt on both the native and V2
370
+ paths, trimmed and capped at 2000 characters; the same image asked a different
371
+ question gets a fresh description, while an identical re-ask inside the cache
372
+ TTL reuses the stored text. Native describes are robust by design: the timeout
373
+ scales from a 20-second base at roughly 10 seconds per MB of payload up to a
374
+ 300-second ceiling, and a zero-dependency EXIF-orientation check (JPEG) adds a
375
+ textual hint so the vision model describes a rotated or mirrored image upright —
376
+ detection only, pixels are never rewritten, and the orientation is folded into
377
+ the cache key.
378
+
379
+ Vision degrades through an explicit chain — native → vision MCP tool → local.
380
+ When native is unavailable and the vision MCP tool is absent, the image is
381
+ replaced by deterministic local extraction: dimensions, format and size from the
382
+ PNG/JPEG/GIF/WebP header, dominant colors for RGB/RGBA PNG, and OCR only when a
383
+ `tesseract` binary is on `PATH`. It never fabricates content — the degradation is
384
+ stated explicitly. The `vision_describe` and `vision_ocr` MCP tools degrade to
385
+ that local mode when no gateway credential is configured, with no new
386
+ dependencies. (`vision_analyze` requires a gateway credential and returns an
387
+ explicit error instead.)
388
+ Deliberate trade-offs, recorded so they are not reversed by accident: Pantheon
389
+ describes each image once and keeps the text in history (council 2026-08-03)
390
+ rather than preserving the original image for per-turn re-observation;
391
+ describe-always favors zero added latency over an on-demand `describe_image`
392
+ tool. Multi-turn sanitization (`experimental.chat.messages.transform`) is a
393
+ mandatory invariant — it guarantees `image_url` / `FilePart` payloads never
394
+ reach a text-only provider and is not configurable. Bifrost stays opt-in and
395
+ never the default, per the credential incident in [SECURITY.md](SECURITY.md).
396
+
397
+ The V2 `execute.before` hook is the read-only enforcement point for that
398
+ surface: the host includes the active agent on the event, a read-only agent
399
+ (`apollo`, `gaia`) registers its session, and the shared
400
+ `createEnforcementGuard` throws to deny `edit`, `write`, `bash`, `task`,
401
+ `hashline_edit` and `pantheon_model`. It does **not** rely on the V1
402
+ `tool.execute.before` hook, which lives in `src/plugin.ts` and is not loaded
403
+ when only `plugin-v2` is configured. When the host registers the
404
+ `permission.evaluate` hook, it enforces the V2 caller/target matrix for
405
+ Pantheon-managed native `subagent` requests. If hook registration is
406
+ unavailable, the matrix is unavailable and the host remains in control.
407
+ Native-only resources pass through unchanged to OpenCode's permission policy;
408
+ mixed native/Pantheon and multi-target requests are denied. Pantheon matches
409
+ the permission source's session, message and tool-call IDs to a short-lived
410
+ record from `tool.execute.before`, cross-checks the captured host caller against
411
+ `permission.evaluate.agent`, and confirms the session has no `parentID`.
412
+ `permission.evaluate.agent` alone is not trusted because
413
+ `ctx.permission.assert` accepts a caller-supplied agent. Missing, stale,
414
+ replayed or mismatched origins fail closed, and explicit host denies remain
415
+ final. On OpenCode v2.0.29, a runtime canary admits Zeus→Apollo from a root,
416
+ denies a matrix-valid Athena→Apollo call from a child and rejects an invalid
417
+ edge before child creation; see the
418
+ [`F4A evidence`](bench/results/f4a-v229-admission-identity-2026-10-14.md).
419
+ V2 `execute.after` runs the completed-result chain:
420
+ `task-result-guard` → `context-sandbox` → `read-enhancer`.
421
+
422
+ Every V2 tool declares an `output` schema. OpenCode 2.0.x requires the
423
+ declaration and the resolved result to agree in both directions, so an
424
+ undeclared tool — or one that returns `output` without declaring it — fails on
425
+ every call. Unsupported V2 features are `legacy-hooks` (the V1-specific hook
426
+ surface), `catalog-transform`, `integration-transform`, `skill-transform` and
427
+ `goal-tools`.
196
428
 
197
429
  The package exposes both contracts as importable exports: `pantheon-opencode/plugin`
198
430
  (V1), `pantheon-opencode/plugin-v2` (V2) and `pantheon-opencode/v2-bridge`
@@ -211,28 +443,75 @@ npx pantheon-opencode init --opencode-version v2
211
443
  npx pantheon-opencode init --opencode-version auto
212
444
  ```
213
445
 
214
- `--version v1|v2|auto` is accepted as the older selector spelling when used
215
- after `init`. `auto` is conservative, not general platform autodetection:
216
- `OPENCODE_VERSION=v1|v2` wins; otherwise an `OPENCODE_BIN` ending in
217
- `opencode2` selects V2; every other case selects V1. The installer removes
218
- Pantheon references from both config shapes before writing only the selected
219
- Pantheon registration. Third-party entries are not converted or claimed by
220
- this rule.
221
-
222
- The V1-only `pantheon_cost` report can select its database with
223
- `PANTHEON_OPENCODE_VERSION=v1` or `v2` (`opencode.db` or `opencode-v2.db`).
224
- `PANTHEON_COST_DB=/absolute/path/to/opencode.db` takes precedence over the
225
- version selector, and an explicit `dbPath` supplied by the tool caller takes
226
- precedence over both. The resolver never probes the other version's database
227
- and reports an actionable error when the selected DB is missing or has an
228
- incompatible schema.
446
+ `auto` is the default. `--version v1|v2|auto` is accepted as the older
447
+ selector spelling when used after `init`. `auto` resolves the generation from
448
+ the host in this order: an explicit `OPENCODE_VERSION=v1|v2` wins; otherwise an
449
+ `OPENCODE_BIN` path ending in `opencode2` selects V2; otherwise the host
450
+ binary is asked for its `--version` and a major of 2 or more selects V2. Every
451
+ other case — an unreadable probe, an unparseable banner, or a banner whose
452
+ version-like tokens contradict each other with no tool name to break the tie —
453
+ warns once and falls back to V1, because a plural `plugins` directory entry on
454
+ an unknown 1.x host loses the plugin entirely.
455
+
456
+ The probe prefers the token that follows the tool name, so a runtime token
457
+ ahead of it (`node v22.1.0 (opencode 1.18.33)`) or a trailing build date
458
+ (`opencode v1.18.33 built 2026.10.04`) cannot flip the generation. The
459
+ installer removes Pantheon references from both config shapes before writing
460
+ only the selected Pantheon registration. Third-party entries are not converted
461
+ or claimed by this rule.
462
+
463
+ The `pantheon_cost` report resolves its database by PATH, in this order: an
464
+ explicit `dbPath` supplied by the tool caller, then
465
+ `PANTHEON_COST_DB=/absolute/path/to/opencode.db`, then `OPENCODE_DB`, then the
466
+ XDG default `opencode.db`. There is no per-version filename in that chain:
467
+ `opencode-v2.db` is not a host 2.x database — it is the name a sandbox gives
468
+ its own state database through `OPENCODE_DB`.
469
+
470
+ The v1/v2 distinction is the DETECTED SCHEMA, not the file name. The report
471
+ looks for the `message` and `session_message` tables and reads whichever the
472
+ open database actually holds, because a migrated database carries both
473
+ families at once. `PANTHEON_OPENCODE_VERSION=v1|v2` selects no file: it only
474
+ narrows an already-detected set to one table family, and fails fast when the
475
+ value is neither `v1` nor `v2` or when the requested family is not there. Left
476
+ unset, every detected family is read. A database carrying neither table comes
477
+ back as an actionable error (`CORRUPT_DATA`), and a ledger that exists but
478
+ yields no readable tokens as `UNSUPPORTED` — never as a successful empty
479
+ report.
229
480
 
230
481
  The installer still writes the compatibility settings required by the selected
231
482
  OpenCode host, such as `experimental.subagent_depth`; this does not convert a
232
483
  V1 plugin into V2 or provide V2 with V1 hooks.
233
484
 
485
+ Pantheon does not set a step ceiling on agents. On OpenCode 2 the `steps`
486
+ field is optional and has no default: absent means the host applies no native
487
+ limit. A config written before this change still carries the old value, and the
488
+ V2 install path strips it from every agent Pantheon manages — an agent you
489
+ define yourself is never touched, and the retiring V1 singular `agent` block
490
+ is left alone. Run the installer once to clear a stale value from an existing
491
+ config:
492
+
493
+ ```bash
494
+ npx pantheon-opencode init --opencode-version=v2
495
+ ```
496
+
497
+ Context control is not a Pantheon setting. Whatever budget an agent runs
498
+ against comes from the compaction settings of the OpenCode host you are
499
+ running, and Pantheon does not define them.
500
+
501
+ When a V1 `agent` block and a V2 `agents` block are both present — which is
502
+ what an installed `opencode.json` carries — the V1→V2 conversion merges them
503
+ instead of letting one replace the other. The V2 block is the base, the
504
+ framework-managed fields from the V1 block overwrite, and your own fields are
505
+ preserved, matching the precedence the installer already applies elsewhere.
506
+ Key order does not matter.
507
+
234
508
  ## Updating between releases (beta.5+)
235
509
 
510
+ > **Read [Compatibility and support policy](#compatibility-and-support-policy)
511
+ > before upgrading across a line boundary.** 1.6.x is the last line that
512
+ > supports an OpenCode 1.X host; 1.7+ is breaking-change territory targeting
513
+ > OpenCode 2. Within the 1.6 line, `update` is the supported path.
514
+
236
515
  One command keeps an existing installation current:
237
516
 
238
517
  ```bash
@@ -253,7 +532,14 @@ Two freshness guarantees back it up:
253
532
  - **Postinstall artifact sync** — after any `npm install`, copy-only artifacts
254
533
  (agents, skills, AGENTS.md, commands, MCP scripts, code-mode payload) are
255
534
  refreshed into the existing config dir automatically; you never have to
256
- re-run `init` just for file copies.
535
+ re-run `init` just for file copies. The global config dir receives the
536
+ repo-agnostic **global artifact** (`AGENTS.global.md`: agent table + shared
537
+ rules), while each project's own `AGENTS.md` carries only project-specific
538
+ setup — the two are carved to be disjoint (beta-10 latency work), so no rule
539
+ is paid for twice per session. Installs are conservative: content outside
540
+ the generated managed region (user house rules) is preserved verbatim, a
541
+ legacy fully-generated `AGENTS.md` upgrades in place, and any merge is
542
+ reported with a warning.
257
543
  - **Drift detection** — the installer stamps the installed version in
258
544
  `.pantheon/install-state.json` and `doctor` warns when the package is newer
259
545
  than the last sync, pointing at `update`. `doctor` also detects **plugin
@@ -315,6 +601,10 @@ pushes, merges, and tags never publish anything, and every validation gate is
315
601
  fail-closed: only an explicit PASS authorizes release evidence. See
316
602
  [docs/RELEASING.md](docs/RELEASING.md) for validation and recovery details.
317
603
 
604
+ For a candidate whose release section already exists, maintain its notes with
605
+ `node scripts/versioning.mjs changelog <version>`; this merges `[Unreleased]`
606
+ into that version without advancing the package version.
607
+
318
608
  Release validation keeps each manifest with its lockfile: the root
319
609
  `package.json` + `package-lock.json` and the TUI
320
610
  `src/plugins/tui/package.json` + `src/plugins/tui/package-lock.json`. Both use
@@ -323,6 +613,12 @@ Release validation keeps each manifest with its lockfile: the root
323
613
  SHA-256 of that same artifact, and binds the tarball and GitHub release to the
324
614
  full `TARGET_SHA`; a second pack is not interchangeable.
325
615
 
616
+ CI also rebuilds the TUI with `npm run build --prefix src/plugins/tui` and
617
+ checks every packaged `dist` artifact byte-for-byte against its checked-in
618
+ version, including final newlines. The build includes separate V1 and native
619
+ OpenCode V2 TUI entrypoints; `init` selects the entrypoint and sidebar slot API
620
+ for the host generation in use.
621
+
326
622
  ## Sandbox validation (V2)
327
623
 
328
624
  `scripts/test-opencode-v2-sandbox.sh` validates the globally installed
@@ -334,6 +630,11 @@ agent delegation. The gate is fail-closed: every required check must return an
334
630
  explicit PASS; timeouts, auth/network/provider failures and missing
335
631
  prerequisites block the run.
336
632
 
633
+ The runner defaults to the current stable `@opencode/cli` package and its
634
+ `opencode2` alias; set `OPENCODE_V2_SPEC` only when a test needs a different
635
+ host build. This keeps Pantheon beta testing separate from the OpenCode CLI
636
+ release channel.
637
+
337
638
  "V2" here refers only to the hook canary observed against an OpenCode v2.0.18
338
639
  host, where at least one tested hook callback fired; it does not establish
339
640
  compatibility with the stable `@opencode/plugin@2.0.18` SDK or full 2.x
@@ -345,6 +646,7 @@ single leg.
345
646
 
346
647
  ```bash
347
648
  scripts/test-opencode-v2-sandbox.sh --prepare # tarball + install + init in the sandbox
649
+ ~/pantheon-sandbox/start-pantheon.sh # interactive TUI in that isolated beta sandbox
348
650
  scripts/test-opencode-v2-sandbox.sh --run v2 # base validation only
349
651
  scripts/test-opencode-v2-sandbox.sh --prompts # base validation + prompt battery
350
652
  scripts/test-opencode-v2-sandbox.sh --rehydrate # offline context rehydration/session-summary probe
@@ -369,6 +671,142 @@ repository from a sibling directory.
369
671
  This validates the prepared isolated sandbox only. A PASS is not proof of
370
672
  support for every real host or for host configurations that were not exercised.
371
673
 
674
+ ## Latency benchmark (bench/)
675
+
676
+ `bench/` measures end-to-end session latency of the installed `opencode` CLI
677
+ with the repo's V2 plugin — the baseline every performance change in a release
678
+ must be compared against. It runs two scenarios N times each, interleaved
679
+ (non-interactive, one fresh sandbox directory per run), collects per-run
680
+ metrics from `opencode.db` in READ-ONLY mode (tokens root + child sessions
681
+ without double counting, tool calls per name, child-session count) and hook
682
+ timings from the `[bench]` lines the plugin appends to `hooks.log`:
683
+
684
+ ```bash
685
+ node bench/bin/bench.mjs # 5 runs per scenario (A and B), ~1h
686
+ BENCH_MODEL=opencode-go/glm-5.3-flash node bench/bin/bench.mjs # pin a model
687
+ node bench/bin/bench.mjs --runs 1 # smoke: one run per scenario
688
+ ```
689
+
690
+ Results land in `bench/results/<label>-<git-sha>.json` (median + p80 +
691
+ failures per scenario); the label defaults to `baseline` and the harness
692
+ refuses to overwrite an existing result, so the run identity lives in the file
693
+ name. Scenario A performs real web research, so its variance is
694
+ network-dependent and recorded per run.
695
+
696
+ ### Measurement profiles (explicit, never inferred)
697
+
698
+ Instructions are injected from two surfaces: the global config dir and the
699
+ project directory. The harness states which one it exercises, because a
700
+ result only means anything in the profile where the change acts:
701
+
702
+ | `--profile` | Global `AGENTS.md` | Project `AGENTS.md` | Use |
703
+ |---|---|---|---|
704
+ | `host` (default) | host config dir (or `--global-agents`) | none — run dirs stay empty | the host's real, unmodified injection |
705
+ | `double-injection` | host config dir (or `--global-agents`) | `--project-agents`, written into every run dir | the in-repo profile where global+project overlap |
706
+
707
+ The default measures scenarios A and B. Use `--scenarios B` to isolate the F1
708
+ one-shot claim; the selected scenario still runs N times (`--runs 5` by
709
+ default).
710
+
711
+ ```bash
712
+ # candidate arm: the carved global artifact + the carved project artifact
713
+ node bench/bin/bench.mjs --runs 5 --scenarios B --profile double-injection \
714
+ --global-agents AGENTS.global.md --project-agents AGENTS.md --label f1-candidate
715
+ ```
716
+
717
+ Each arm records, per run and read from the db, the identity (path, bytes,
718
+ sha256) of every instruction file the session actually loaded
719
+ (`instruction_state` + `instruction_blob`) — the fidelity proof that what was
720
+ measured is what was generated. A claim may only rest on a run whose
721
+ provenance shows the intended global **and** project artifacts were loaded.
722
+
723
+ ### Signal vs noise
724
+
725
+ Wall time is a lead, not a criterion: same-day spread reaches ~8× in scenario
726
+ A and ~13× in B. An effect is **confirmed** only when it exceeds the same-day
727
+ spread (or demands a larger N); otherwise it is recorded as **inconclusive**.
728
+ Prefer token medians, which are far more stable. Scenario A's wall is not a
729
+ claim metric — it performs real web research, so network variance dominates.
730
+
731
+ ### First-request proxy and F1 evidence
732
+
733
+ The injected instruction payload only lands on the first request, so the
734
+ tree-total `tokens.input` (summed over every turn) is dominated by
735
+ session-length variance. Each run also records `firstRequest` — the first
736
+ assistant row's `tokens.input` + `tokens.cache.read` — the proxy that isolates
737
+ the payload.
738
+
739
+ An interleaved OpenCode v2.0.29 run (C1/K1…C5/K5, N=5/arm) measured
740
+ first-request context at 17555 tokens for control and 15489 for candidate
741
+ (**−2066, −11.8%**; within-arm spread 14 tokens in each arm). D4 confirmed
742
+ 22350 B loaded for control and 13400 B for candidate (−8950 B, −40.0%); the
743
+ pre-registered correctness oracle passed 5/5 in both arms. Themis accepted F1
744
+ with **PASS_WITH_NOTES**. The first-request effect is confirmed against
745
+ within-arm spread. Tree-total input fell from a median 47594 to 38253
746
+ tokens, but ranges overlap and the ≤30k hypothesis was not met. Wall medians
747
+ were 30.078 s and 24.130 s, with high spread; tree-total input and wall remain
748
+ **inconclusive**. No wall-time or monetary-cost gain is claimed. Details and
749
+ per-run records: `bench/results/f1-di-v229-interleaved-2026-10-14.md`.
750
+ The earlier sequential pair remains supporting-only in
751
+ `bench/results/f1-di-v229-clean-2026-10-14.md`. Earlier exploratory runs are
752
+ retained separately in `bench/results/f1-double-injection.md` and
753
+ `bench/results/f1-di-v229-preliminary-2026-10-14.md`.
754
+
755
+ ### Explicit root specialist result (F3a)
756
+
757
+ For the bounded one-shot scenario B, explicitly starting Talos as the root
758
+ produced the oracle-passing artifact in 5/5 runs with no child session or
759
+ `subagent` call. In the same-day paired sample, Talos used 16,171 median input
760
+ tokens per run versus 33,301 for Zeus (−51.4%); this is a descriptive result
761
+ for this task, model, and configuration, not a general routing or monetary
762
+ savings claim. Wall time is inconclusive: medians were 30.347 s and 31.893 s,
763
+ the ranges overlap widely, and Talos had the higher p80. No automatic
764
+ LLM-selected root routing is introduced by this result.
765
+
766
+ A final integration check after F4A/F3b initially completed 4/5 Talos artifacts.
767
+ Talos's prompt now says to finish named files with native `write`/`edit` tools
768
+ and not confuse MCP tool discovery with the host's native tool catalog. The
769
+ failure remains recorded in
770
+ [`beta10-final-integration-2026-10-15.md`](bench/results/beta10-final-integration-2026-10-15.md).
771
+ A new pre-registered cohort on that prompt passed the artifact oracle in 5/5
772
+ Talos runs with zero children or `subagent` calls. Its first-request context
773
+ proxy was 9,675 tokens versus 13,009 for Zeus (−25.6%, confirmed against the
774
+ same-arm spread). Tree-total input is descriptive, and wall time remains
775
+ inconclusive. See the [follow-up report](bench/results/beta10-final-integration-followup-2026-10-15.md)
776
+ and [raw run record](bench/results/beta10-final-integration-followup-20261015.json).
777
+
778
+ The v2.0.29 harness requires explicit agent and fixture selection, and proves
779
+ global plus project instruction provenance for each run:
780
+
781
+ ```bash
782
+ BENCH_MODEL=opencode-go/glm-5.3-flash node bench/bin/bench.mjs \
783
+ --scenario B --runs 5 --profile double-injection \
784
+ --global-agents AGENTS.global.md --project-agents AGENTS.md \
785
+ --agents-dir src/agents --skills-dir src/skills \
786
+ --root-agent talos --control-root-agent zeus --paired \
787
+ --out bench/results/phase3-root-paired-20261014.json
788
+ ```
789
+
790
+ Themis reviewed the harness and evidence (**PASS_WITH_NOTES**). Full method,
791
+ oracle audit, limitations, and per-run data are in
792
+ `bench/results/f3a-root-paired-2026-10-14.md` and
793
+ `bench/results/phase3-root-paired-20261014.json`.
794
+
795
+ ### Bounded workspace reads (F3b)
796
+
797
+ On OpenCode v2.0.29, the V2 plugin can expose `pantheon_bounded_read` when the
798
+ host provides its native permission and session APIs. Only a root Zeus session
799
+ can use it. Each call asks the host for `read` permission to one exact
800
+ workspace-relative file, with an empty save scope; content is read only after
801
+ approval and is scanned by the existing fail-closed secret scanner. Limits are
802
+ two calls and two distinct files, 400 lines and 32 KiB per assistant message.
803
+ Traversal, symlinks, directories, sensitive scopes, recognized binary/media
804
+ formats, and scanner failures are rejected. This is scoped to a local workspace
805
+ without concurrent writers; it does not claim adversarial filesystem isolation
806
+ or whole-file binary classification. The host-backed evidence is in
807
+ [`bench/results/f3b-v229-bounded-read-2026-10-15.md`](bench/results/f3b-v229-bounded-read-2026-10-15.md).
808
+
809
+
372
810
  ## Plugin V2 TypeScript coverage
373
811
 
374
812
  `npm run coverage:plugin-v2` runs the `tests/pantheon/*.test.ts` suite with
@@ -383,7 +821,7 @@ Env overrides:
383
821
  |----------|---------|---------|
384
822
  | `PANTHEON_SANDBOX_ROOT` | `~/pantheon-sandbox` | Sandbox root (refused if unsafe for `--reset`) |
385
823
  | `OPENCODE_V1_SPEC` | `opencode-ai@1.18.18` | Configures the V1 plugin only; the V2-only sandbox runner does not consume or support it |
386
- | `OPENCODE_V2_SPEC` | `@opencode-ai/cli@beta` | npm spec providing the `opencode2` binary |
824
+ | `OPENCODE_V2_SPEC` | `@opencode/cli@latest` | npm spec providing the `opencode2` binary |
387
825
  | `PANTHEON_SANDBOX_MODEL` | `opencode-go/mimo-v2.5` | Model used by init and prompts |
388
826
  | `PANTHEON_PROMPT_TIMEOUT` | `300` | Per-prompt timeout in seconds |
389
827
 
@@ -392,7 +830,7 @@ in the sandbox root) · `2` usage error · `3` sandbox not prepared.
392
830
 
393
831
  ### Intentional memory MCP divergence
394
832
 
395
- `scripts/memory_mcp_server.py` and `src/mcp/memory_mcp_server.py` are
833
+ `scripts/memory_mcp.py` and `src/mcp/memory_mcp.py` are
396
834
  intentionally different. The standalone `scripts/` copy keeps the lightweight
397
835
  `memory_*` contract; the installed `src/mcp/` copy additionally exposes the
398
836
  optional codemap schema and `code_index`, `code_query`, and `code_neighbors`.
@@ -441,6 +879,32 @@ Ideas, bug reports, documentation improvements, and code contributions are
441
879
  welcome. Please read [CONTRIBUTING.md](CONTRIBUTING.md) before opening an issue
442
880
  or pull request.
443
881
 
882
+ ### Reproducible benchmark evidence
883
+
884
+ The beta2 benchmark records reported token usage separately from its
885
+ character-based fallback estimate; source bytes and logical line counts remain
886
+ provenance data and are never converted into tokens. Cross-report comparisons
887
+ require matching model/config provenance and reported OpenCode usage. Offline
888
+ fixture responses are mocked: their reported values are labeled separately,
889
+ excluded from `actual` usage, and blocked from comparative metrics and GEPA.
890
+ Fixture quality outcomes test the offline contract; they are not evaluation
891
+ evidence.
892
+ Reproduce the
893
+ checked-in AGENTS.md history manifest with
894
+ `python3 -m benchmarks.beta2.provenance --output benchmarks/beta2/fixtures/agent-baseline-provenance.json`.
895
+ For OpenCode benchmark runs, provide `--model` and `--config-sha256` so reports
896
+ can be compared safely.
897
+
898
+ ### Project-level `opencode.json`
899
+
900
+ The published package carries no `opencode.json` template. `init` still writes
901
+ your project's `opencode.json` itself, and the few product defaults an install
902
+ seeds — `default_agent: zeus` and `permission.skill` — come from the installer
903
+ code, not from a packaged file. Contributors who keep a project-level
904
+ `opencode.json` for their own OpenCode sessions should leave it untracked —
905
+ `.git/info/exclude` per clone, or a shared `.gitignore` decision — rather than
906
+ versioning it.
907
+
444
908
  ## Citation and DOI
445
909
 
446
910
  Pantheon is released under the [MIT License](LICENSE). Cite the