@osovv/vv-opencode 1.3.4 → 1.3.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,14 @@
1
+ ## <small>1.3.5 (2026-08-21)</small>
2
+
3
+ ### Summary
4
+
5
+ Release 1.3.5 clarifies what vv-opencode offers and makes plan documents easier to work with by hand. The docs are restructured around an outcome-first pitch that reframes the package as an opinionated agentic development layer for OpenCode, adds a "You just talk to OpenCode normally" section showing how vv-controller picks the lightest trajectory for each request while explicit spec, plan, and execute skills take over only when the work needs them, and surfaces provider-neutral web tools in a new Why section. On the functional side, plan tasks and waves now carry their identity in unique element names (`<TASK-T-NNN>` and `<WAVE-N>`) instead of generic tags with child id/num elements, so long task blocks stay addressable and grep/sed extraction used by vv-plan and vv-execute remains exact without a separate query language; the plan template, skill format rules, plan-validation checks, and README grep examples are updated to match.
6
+
7
+ * docs(readme): reframe pitch as agentic layer and add natural-trajectory section ([d197955](https://github.com/osovv/vv-opencode/commit/d197955))
8
+ * docs(readme): restructure around outcome-first pitch and runtime value ([9e6910b](https://github.com/osovv/vv-opencode/commit/9e6910b))
9
+ * docs(readme): surface provider-neutral web tools in the Why section ([c90ecf0](https://github.com/osovv/vv-opencode/commit/c90ecf0))
10
+ * feat(skills): give plan tasks and waves unique element-name boundaries ([8f52f0c](https://github.com/osovv/vv-opencode/commit/8f52f0c))
11
+
1
12
  ## <small>1.3.4 (2026-08-19)</small>
2
13
 
3
14
  ### Summary
package/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @osovv/vv-opencode
2
2
 
3
- **Curated, opinionated OpenCode plugin set** for spec-first, review-driven, safer agentic development — with managed agents, skills, safety plugins, and the `vvoc` CLI.
3
+ **An opinionated agentic development layer for OpenCode** — spec-first when it matters, review-driven execution, portable model roles, safer tools, and long-run safety. Under the hood it ships as a set of OpenCode plugins, managed agents, skills, and the `vvoc` CLI.
4
4
 
5
5
  <p>
6
6
  <a href="https://www.npmjs.com/package/@osovv/vv-opencode"><img src="https://img.shields.io/npm/v/%40osovv%2Fvv-opencode?style=flat&label=npm&color=blue" alt="npm"></a>
@@ -11,49 +11,87 @@
11
11
  <a href="LICENSE"><img src="https://img.shields.io/github/license/osovv/vv-opencode?style=flat&color=green" alt="MIT"></a>
12
12
  </p>
13
13
 
14
+ OpenCode owns the mechanics: streaming, model invocation, sandboxing, permissions. The development *process* — when to clarify, when to plan, when to review, how to survive long runs — it leaves up to you.
15
+
16
+ vv-opencode adds that process layer. It is a hand-picked workflow crystallized from a year and a half of daily agentic development: you run `vvoc install`, learn three skills (`vv-spec`, `vv-plan`, `vv-execute`), and get a disciplined spec-to-code pipeline with review gates, portable model roles, and long-run safety — without needing to know how any of it works inside.
17
+
18
+ The spec pipeline is the most visible part, but it is only one layer. Everything underneath runs on every session whether or not you ever write a spec: each model edits files through the tool it knows best, routine permissions are approved without interrupting your run, secrets never reach the model, and multi-agent work is held together by an explicit state machine instead of prompt luck. If you already have your own spec tooling, keep it — the runtime layers below apply anyway.
19
+
20
+ ---
21
+
22
+ ## Why vv-opencode?
23
+
24
+ OpenCode is a strong, flexible base, but it intentionally leaves the development process up to you. Left to itself, agentic work tends to drift: requirements get skipped, one agent silently implements and "reviews" itself, multi-agent loops churn through "one more final review", long runs stall on permission prompts, and model choices are hardcoded everywhere.
25
+
26
+ vv-opencode addresses each of these:
27
+
28
+ - **Formalized trajectories** — small changes stay direct, unclear bugs start with investigation, large changes go through spec and plan, risky implementation uses review loops.
29
+ - **Spec-first by default** — broad requests become explicit specs, plans, and review gates before implementation, and every artifact is saved as grep-able XML.
30
+ - **Review-driven execution** — implementation, spec review, and code review are separate steps with bounded retries, not one agent silently doing everything.
31
+ - **A state machine for multi-agent work** — explicit work items, required reviewers, round limits, and hard stops instead of free-form subagent loops.
32
+ - **Portable model choices** — agents reference roles like `vv-role:smart` and `vv-role:fast`; you map roles to concrete models per machine or project and switch stacks with one preset command.
33
+ - **Per-model editing** — each model edits through the tool it knows best: DeepSeek gets its `str_replace_editor` contract, GLM/Qwen/Kimi get exact-match replace, and GPT keeps the host editing path. Routing is resolved dynamically per session, and every edit is anchored to a fresh file read — fewer wrong-line and stale-context errors.
34
+ - **Provider-neutral web tools** — agents get one canonical `web_search` and `web_fetch` contract backed by Exa, Brave, Z.AI, native retrieval, or Spider, instead of provider-specific search and reader schemas leaking into your prompts.
35
+ - **Long-run safety** — Guardian auto-approves routine low-risk permissions (risky ones stay in OpenCode's manual approval flow), and secrets are redacted before they reach the model.
36
+ - **Reproducible setup** — `vvoc install` / `vvoc sync` recreate the same workflow on any machine or project.
37
+
38
+ ---
39
+
40
+ ## You just talk to OpenCode normally
41
+
42
+ You don't need to learn a command surface first. Ask for what you want — `vv-controller` picks the lightest appropriate trajectory, and explicit skills take over only when the work needs them:
43
+
44
+ ```text
45
+ > Rename this field and update its tests.
46
+ → handled directly
47
+
48
+ > Why does auth occasionally return 401 after a token refresh?
49
+ → root-cause investigation first → targeted fix → verification
50
+
51
+ > Add organizations with role-based access.
52
+ → vv-spec → approval → vv-plan → approval → vv-execute
53
+ ├─ implement
54
+ ├─ spec review
55
+ └─ code review
56
+ ```
57
+
58
+ Every managed skill can also be invoked explicitly when you want to drive the process yourself.
59
+
14
60
  ---
15
61
 
16
- ## Quick Start
62
+ ## Quick start
17
63
 
18
64
  ```bash
19
- bun add -g opencode-ai@1.18.2
65
+ bun add -g opencode-ai
20
66
  bun add -g @osovv/vv-opencode
21
67
  vvoc install
22
68
  ```
23
69
 
24
- That's it. `vvoc install` pins the server plugin, registers the same pinned package for OpenCode to load its `/context` TUI export, scaffolds managed agents and skills, writes canonical config, and sets `vv-controller` as your default OpenCode agent with auto-triggered spec, planning, review, reflection, and handoff skills. The TUI integration requires OpenCode `1.18.2` or newer; `vvoc status` and `vvoc doctor` report the installed host version and fail compatibility checks for older releases.
70
+ `vvoc install` does four things:
71
+
72
+ - pins `@osovv/vv-opencode` as an OpenCode runtime plugin and registers the same pinned package as the OpenCode TUI plugin;
73
+ - scaffolds the managed agents and skills;
74
+ - writes the canonical `vvoc.json` config;
75
+ - sets `vv-controller` as your default OpenCode agent, with the spec, planning, review, reflection, and handoff skills auto-triggered by request type.
25
76
 
26
- To scope everything to the current project instead of the global OpenCode config:
77
+ The TUI integration requires OpenCode `1.18.2` or newer; `vvoc status` and `vvoc doctor` report the installed host version and fail compatibility checks for older releases.
78
+
79
+ **Want to try it without touching your global setup?** Scope everything to one project:
27
80
 
28
81
  ```bash
29
82
  vvoc install --scope project
30
83
  vvoc launch --scope project
31
84
  ```
32
85
 
33
- Project scope writes only to `./.opencode/` and `./.vvoc/`. A normal `opencode` launch may still apply OpenCode's native config discovery and merge behavior; `vvoc launch --scope project` is the hard sandbox path and starts OpenCode with `OPENCODE_CONFIG`, `OPENCODE_TUI_CONFIG`, and `VVOC_CONFIG` pinned to the selected local files, so you can smoke-test vv-opencode in one repository without mutating your primary global setup.
86
+ Project scope writes only to `./.opencode/` and `./.vvoc/`. A plain `opencode` launch may still apply OpenCode's native config discovery and merge behavior; `vvoc launch --scope project` is the hard sandbox path — it starts OpenCode with `OPENCODE_CONFIG`, `OPENCODE_TUI_CONFIG`, and `VVOC_CONFIG` pinned to the selected local files, so you can smoke-test vv-opencode in one repository without mutating your primary global setup.
34
87
 
35
88
  > **Already installed?** Run `vvoc sync` anytime to refresh plugins, prompts, skills, and presets.
36
89
 
37
90
  ---
38
91
 
39
- ## 1.0 Stability Posture
40
-
41
- `vv-opencode` 1.0 marks the workflow as a daily-driver baseline: a hand-picked, curated OpenCode setup that packages the agent routing, managed skills, model-role indirection, safer editing, review loops, and release discipline used in real projects.
42
-
43
- The stable user-facing surface is intentionally practical:
92
+ ## How it works: spec → plan → execute
44
93
 
45
- - `vvoc install` / `vvoc sync` / `vvoc launch` remain the primary setup and refresh path.
46
- - `vv-spec`, `vv-plan`, and `vv-execute` remain the canonical spec-to-code path for larger work.
47
- - `vv-review`, `vv-reflect`, and `vv-handoff` remain the auxiliary review, durable-learning, and session-continuity workflows.
48
- - The published package exports, CLI command names, canonical vvoc schema v3, and date-prefixed `.vvoc/specs/YYYY-MM-DD-<slug>/` artifact layout are treated as compatibility surfaces.
49
-
50
- The project still prefers conservative, explicit changes over hidden migration magic: user-owned config is not silently clobbered, invalid current config fails loudly, and breaking workflow or config changes must be documented in release notes.
51
-
52
- ---
53
-
54
- ## Spec-to-Code Pipeline
55
-
56
- vvoc keeps larger agentic work from jumping straight into edits. The process turns a request into explicit artifacts first, then executes the approved plan with bounded implementation and review loops.
94
+ vvoc keeps larger agentic work from jumping straight into edits. A request first becomes explicit artifacts; only the approved plan gets executed, with bounded implementation and review loops. This trajectory is opt-in per request: small changes never go through it, and if you already run your own spec workflow, you can keep it — nothing else in vv-opencode depends on these skills.
57
95
 
58
96
  ```
59
97
  Request / idea
@@ -77,7 +115,7 @@ vv-execute
77
115
  Verified result
78
116
  ```
79
117
 
80
- Inside `vv-execute`:
118
+ Inside `vv-execute`, each plan task goes through a tracked loop:
81
119
 
82
120
  ```text
83
121
  Each plan task
@@ -106,84 +144,243 @@ All artifacts for one feature live together:
106
144
  plan.xml # how to implement and verify it
107
145
  ```
108
146
 
109
- New `vv-spec` packages use a date-prefixed id (`YYYY-MM-DD-<slug>`, for example `2026-06-24-cache-store`) so active packages sort by creation date. The prefix is date-only; it must not include hours, minutes, seconds, timezone, or a full ISO timestamp.
147
+ Package ids are date-prefixed (`YYYY-MM-DD-<slug>`, for example `2026-06-24-cache-store`) so active packages sort by creation date; the prefix is date-only, never a full timestamp. Spec and plan lifecycle runs through a top-level status: `draft` while being written, `approved` after explicit user approval, `applied` after successful execution. `vv-execute` archives applied packages by moving the whole directory to `.vvoc/specs/archive/YYYY-MM-DD-<slug>-<timestamp>/`.
110
148
 
111
- Specs and plans use a top-level lifecycle status: `draft` while being written, `approved` after explicit user approval, and `applied` after successful execution. `vv-execute` archives applied artifact packages by moving the entire spec package directory `.vvoc/specs/YYYY-MM-DD-<slug>/` to `.vvoc/specs/archive/YYYY-MM-DD-<slug>-<timestamp>/`.
149
+ Specs and plans are XML, so requirements, tasks, acceptance criteria, and dependencies stay grep-able. Task and wave identity lives in unique element names (`<TASK-T-001>…</TASK-T-001>`, `<WAVE-1>…</WAVE-1>`), so grep/sed extraction stays exact without a separate query language:
112
150
 
113
- ### XML grep
151
+ ```bash
152
+ grep '<TASK-T-' .vvoc/specs/*/plan.xml # task ids
153
+ grep '<criterion>' .vvoc/specs/*/plan.xml # acceptance criteria
154
+ grep '<task_id>' .vvoc/specs/*/plan.xml # dependency graph
155
+ ```
114
156
 
115
- Plans and specs are XML documents, making every element grep-able:
157
+ `vv-controller` explicitly routes `vv-spec`, `vv-plan`, and `vv-review`; `vv-execute`, `vv-reflect`, and `vv-handoff` are available as managed skills for plan execution, durable repository memory, and end-of-session handoff notes.
116
158
 
117
- ```bash
118
- # Extract tasks from plan
119
- grep '<id>T-' .vvoc/specs/*/plan.xml
159
+ ---
120
160
 
121
- # Extract all acceptance criteria
122
- grep '<criterion>' .vvoc/specs/*/plan.xml
161
+ ## What's inside
123
162
 
124
- # Extract dependency graph
125
- grep '<task_id>' .vvoc/specs/*/plan.xml
163
+ ### The ten plugins
126
164
 
127
- # Extract method signatures
128
- grep '/\*\*' .vvoc/specs/*/plan.xml
165
+ | Plugin | What it does |
166
+ |---|---|
167
+ | **WorkflowPlugin** | A state machine over multi-agent work: explicit work items, required reviewers, bounded implementation/review rounds, and hard stops when more context is needed. |
168
+ | **ModelRolesPlugin** | Semantic model roles (`vv-role:smart`, `vv-role:fast`, …) instead of hardcoded model IDs in agents, subagents, and commands — resolved per machine or project at startup. |
169
+ | **GuardianPlugin** | Keeps long or AFK runs moving by auto-approving routine low-risk permission requests; anything risky stays in OpenCode's normal manual approval flow. |
170
+ | **HashlineEditPlugin** | Routes each model to the edit tool it knows best (DeepSeek `str_replace_editor`, exact replace for GLM/Qwen/Kimi, host path for GPT) and ties every edit to a fresh `read`, reducing wrong-line and stale-context edits. |
171
+ | **SystemContextInjectionPlugin** | Injects the work policy selected by the orchestration profile into vv-controller at startup, plus skill discovery; subagents stay unpolluted. |
172
+ | **SecretsRedactionPlugin** | Redacts tokens, keys, emails, and other sensitive values before messages reach the model, restoring them only where local execution needs the originals. |
173
+ | **WebToolsPlugin** | Two provider-neutral tools — `web_search` and `web_fetch` — over Exa, Brave, Z.AI, native retrieval, or Spider, with permission checks and normalized output. |
174
+ | **ToolHistoryCompactionPlugin** | Shrinks the context replayed to the model by compacting old tool outputs non-destructively, without touching on-disk history. |
175
+ | **AnalyticsPlugin** | Local-only token and cache telemetry per model step, a live `cache NN%` indicator in the TUI, and `vvoc analytics cache-hit-rate` for retrospective comparison. |
176
+ | **ContextTuiPlugin** | The `/context` inspector: an honest, scrollable TUI dialog showing context-window usage by category, tool, and MCP server. |
177
+
178
+ ### Managed agents
129
179
 
130
- # Extract all modules from architecture
131
- grep '<name>' .vvoc/specs/*/plan.xml
132
- ```
180
+ All prompt files are scaffolded by `vvoc install` / `vvoc sync`:
133
181
 
134
- Managed skills are installed by `vvoc`. `vv-controller` explicitly routes `vv-spec`, `vv-plan`, and `vv-review`; `vv-execute`, `vv-reflect`, and `vv-handoff` are available as managed skills for plan execution, durable repository memory, and end-of-session handoff notes.
182
+ | Agent | When it helps |
183
+ |---|---|
184
+ | `vv-controller` | Primary agent that follows the concrete work policy selected for the session by the orchestration profile |
185
+ | `enhancer` | Improves rough requests before execution when a clearer prompt would help |
186
+ | `vv-implementer` | Applies a focused approved change and verifies it before reporting completion |
187
+ | `vv-spec-reviewer` | Checks whether implementation matches the requested spec and acceptance criteria |
188
+ | `vv-code-reviewer` | Looks for bugs, regressions, maintainability risks, and missing tests |
189
+ | `investigator` | Finds the root cause first when behavior is unclear or a failure needs diagnosis |
190
+ | `guardian` | Supports GuardianPlugin by reviewing permission requests and auto-approving only routine low-risk ones |
191
+
192
+ ### Managed skills
193
+
194
+ Two families: `vv-*` skills guide the work protocol, while `vvoc-*` skills operate and observe the vvoc/OpenCode tooling itself.
195
+
196
+ | Skill | When to use it | What it gives you |
197
+ |---|---|---|
198
+ | `vv-spec` | You have a feature or creative request and no agreed contract yet | A guided interview, recommended options, and a saved spec in `.vvoc/specs/YYYY-MM-DD-<slug>/spec.xml` |
199
+ | `vv-plan` | A spec is approved and ready to implement | A task-level implementation plan with file targets, contracts, dependencies, and acceptance criteria |
200
+ | `vv-execute` | A plan is approved and you want it applied step by step | Ordered execution with verification, an explicit inline-or-classic mode choice, and applied spec/plan archival |
201
+ | `vv-review` | You want findings, not fixes | A review-only workflow that reports spec/code issues and stops before implementation |
202
+ | `vv-reflect` | A long development, debugging, ops, or investigation session produced reusable knowledge | Durable notes in existing docs or `.vvoc/lessons` / `.vvoc/runbooks` for future agents |
203
+ | `vv-handoff` | You are ending a session and want the visible context preserved | A redacted XML note at `.vvoc/handoff/YYYY-MM-DD-<session-slug>/handoff.xml`, written from already-visible context only |
204
+ | `vvoc-usage-analytics` | You ask about token usage, cache hit rate, costs, or caching regressions | Read-only analysis across `vvoc analytics`, the analytics JSONL, and historical `opencode.db` data |
205
+
206
+ Skills are loaded by OpenCode at session start through `config.skills.paths` (registered by SystemContextInjectionPlugin); the `vv-controller` agent's skill-trigger rules invoke them automatically when a request matches their conditions.
135
207
 
136
208
  ---
137
209
 
138
- ## Why vv-opencode?
210
+ ## CLI at a glance
139
211
 
140
- OpenCode is a strong, flexible base for agentic coding, but it intentionally leaves the development process mostly up to you: when to clarify requirements, when to plan, when to investigate first, when to review, and how to keep longer runs safe. That flexibility is powerful, but it can also make agent work feel loose and inconsistent.
212
+ | Command | Purpose |
213
+ |---|---|
214
+ | `vvoc init` | Interactive bootstrap flow |
215
+ | `vvoc install` | Non-interactive setup and scaffolding |
216
+ | `vvoc sync` | Refresh runtime/TUI plugin entries, agents, prompts, skills, config |
217
+ | `vvoc launch` | Launch OpenCode with deterministic runtime, TUI, and vvoc config sources |
218
+ | `vvoc status` | Show current installation state, including OpenCode version compatibility and TUI registration |
219
+ | `vvoc doctor` | Diagnose OpenCode version/runtime/TUI/vvoc setup problems (exits non-zero on issues) |
220
+ | `vvoc config validate` | Validate canonical `vvoc.json` |
221
+ | `vvoc role list\|set\|unset` | Manage model role assignments |
222
+ | `vvoc preset list\|show\|<name>` | Inspect or apply named presets |
223
+ | `vvoc guardian config` | Print or write the guardian section |
224
+ | `vvoc plugin list` | List OpenCode plugin entries |
225
+ | `vvoc plugin enable\|disable` | Toggle a vvoc-managed plugin on or off |
226
+ | `vvoc orchestration show\|set` | Show or set the vv-controller orchestration profile |
227
+ | `vvoc patch-provider stepfun-ai\|codex\|deepseek\|kimi\|alibaba\|all` | Patch OpenCode providers; `codex` adds subscription-safe OpenAI aliases (also accepts `openai`), `deepseek`/`kimi`/`alibaba` add vv- reasoning-effort aliases, `all` patches every provider at once |
228
+ | `vvoc completion` | Install shell completions |
229
+ | `vvoc upgrade` | Upgrade the global package and run follow-up sync; sync failure is reported as a partial upgrade |
230
+ | `vvoc analytics cache-hit-rate` | Aggregate persisted cache hit rate by day, week, month, session, model, provider, project, vvoc version, or OpenCode version |
231
+ | `vvoc version` | Print installed version |
141
232
 
142
- **vv-opencode adds a curated process layer on top of OpenCode:**
233
+ Guardian duration overrides use positive whole milliseconds. Both `--timeout-ms` and `--review-toast-duration-ms` reject zero, negative, fractional, missing, or malformed values:
143
234
 
144
- - **Formalized trajectories** — small changes stay direct, unclear bugs start with investigation, large changes go through spec and plan, and risky implementation uses review loops
145
- - **Spec-first by default** — turn broad requests into explicit specs, plans, and review gates before implementation
146
- - **Review-driven execution** — keep implementation, spec review, and code review as separate steps instead of one agent silently doing everything
147
- - **Portable model choices** — use roles like `vv-role:smart` and `vv-role:fast` in shared agents, then map those roles per machine or project
148
- - **Long-run safety** — Guardian auto-approves routine low-risk permission requests, leaves risky ones to OpenCode's manual approval flow, and secrets redaction reduces accidental leakage
149
- - **Safer edits** — per-model edit routing gives each model its native editing tool: hashline-anchored edits, exact oldString/newString replace, or the DeepSeek `str_replace_editor`, all tied to fresh `read` output so agents rarely write against stale content
235
+ ```bash
236
+ vvoc guardian config --print --timeout-ms 30000 --review-toast-duration-ms 5000
237
+ ```
150
238
 
151
239
  ---
152
240
 
153
- ## Features
241
+ ## Configuration
154
242
 
155
- | Area | What you get |
156
- |---|---|
157
- | **Plugins** | A curated set of OpenCode plugins that make agentic work more structured, portable, and safer without hand-wiring each piece yourself |
158
- | **Agent System** | A default controller (vv-controller) that follows the concrete work policy selected by the orchestration profile |
159
- | **Skills** | Guided workflows for turning ideas into specs, specs into plans, plans into execution, reviews into findings, and long sessions into reusable memory |
160
- | **Spec-to-Code Pipeline** | A repeatable path from request → spec → plan → implementation → review, so agents do not silently skip requirements or acceptance criteria |
161
- | **One-Click Setup** | Recreate the same opinionated workflow on a new machine or project with `vvoc install` / `vvoc sync` |
162
- | **CLI Tooling** | Operate and diagnose the setup from one CLI: install, sync, launch, status, doctor, roles, presets, orchestration profiles, plugin toggles, completion, and upgrade |
163
- | **Long-Run Safety** | Guardian keeps safe long/AFK runs moving by auto-approving routine low-risk permissions, while risky actions stay in OpenCode's manual approval flow; secrets redaction reduces accidental leakage |
164
- | **Model Roles** | Put roles like `vv-role:smart` or `vv-role:fast` in shared agents and skills instead of hardcoded model IDs, then choose provider/model mappings per environment |
165
- | **Orchestration Profiles** | Select a concrete work policy — single-session, balanced, or orchestrated — to control how vv-controller delegates. Built-in presets pick a sensible default and status reports the effective profile. |
166
- | **Workflow Tracking** | Replace free-form multi-agent chaos with explicit work items, bounded review rounds, reviewer result collection, and hard stops when more context is needed |
167
- | **Unified Web Tools** | Replace provider-specific search and reader schemas with the canonical `web_search` and `web_fetch` tools, configurable for Exa, Brave, native retrieval, or Spider extraction |
168
- | **Context Inspector** | Run `/context` in an active OpenCode TUI session for Overview, Tools, and MCP tabs with provider-reported usage, approximate context-window percentages, active post-compaction tool history, and deterministic source attribution |
169
- | **Cache Analytics** | Watch a live per-session `cache NN%` indicator in the TUI and compare cache hit rates across vvoc releases, OpenCode versions, models, and projects with `vvoc analytics cache-hit-rate` |
243
+ Mutating commands default to global scope for backward compatibility; add `--scope project` to write a project-local layer. Read and diagnostic commands accept `--scope global|project|effective`, where `effective` resolves in this order:
244
+
245
+ 1. explicit env override (`VVOC_CONFIG` / `OPENCODE_CONFIG` / `OPENCODE_TUI_CONFIG`)
246
+ 2. nearest project layer
247
+ 3. global layer
248
+ 4. built-in defaults when the command/runtime permits defaults
249
+
250
+ Canonical project-local paths:
251
+
252
+ ```text
253
+ OpenCode config → ./.opencode/opencode.json(c)
254
+ OpenCode TUI config → ./.opencode/tui.json(c)
255
+ vvoc config → ./.vvoc/vvoc.json
256
+ Managed agent prompts → ./.vvoc/agents/*.md
257
+ Managed skills → ./.vvoc/skills/*/SKILL.md
258
+ Spec package directory → ./.vvoc/specs/YYYY-MM-DD-<slug>/
259
+ Handoff notes → ./.vvoc/handoff/YYYY-MM-DD-<session-slug>/handoff.xml
260
+ Repository memory → ./.vvoc/lessons/*.xml, ./.vvoc/runbooks/*.xml
261
+ ```
262
+
263
+ Legacy root-level `./opencode.json` and `./opencode.jsonc` are intentionally not used as vvoc project layers.
264
+
265
+ Global paths:
266
+
267
+ ```text
268
+ OpenCode config → $XDG_CONFIG_HOME/opencode/opencode.json
269
+ OpenCode TUI config → $XDG_CONFIG_HOME/opencode/tui.json(c)
270
+ vvoc config → $XDG_CONFIG_HOME/vvoc/vvoc.json
271
+ Managed agent prompts → $XDG_CONFIG_HOME/vvoc/agents/*.md
272
+ Managed skills → $XDG_CONFIG_HOME/vvoc/skills/*/SKILL.md
273
+ Persisted data → $XDG_DATA_HOME/vvoc/
274
+ Usage analytics → $XDG_DATA_HOME/vvoc/analytics/usage-YYYY-MM.jsonl
275
+ ```
276
+
277
+ ### Two config surfaces, one pinned package
278
+
279
+ OpenCode keeps server/runtime plugins and native TUI plugins in separate configuration surfaces. `opencode.json(c)` is loaded by the core/server plugin runtime and activates vvoc features such as model roles, Guardian, workflow, hashline edit, redaction, and web tools. `tui.json(c)` is loaded by the terminal UI process and activates the package's `./tui` module (the `/context` inspector). The same pinned package version appears in both files, but OpenCode selects a different public export for each process; headless/server launches therefore never load the UI module.
280
+
281
+ `vvoc install`, `vvoc init`, and `vvoc sync` conservatively add the pinned base package specifier (for example `@osovv/vv-opencode@X.Y.Z`) to `tui.json(c)`; sync also migrates the broken legacy `@osovv/vv-opencode/tui` form and older managed pins. Existing comments, unrelated settings, unrelated plugin entries, and `[specifier, options]` tuples are preserved; malformed plugin entries fail without rewrite.
282
+
283
+ Runtime plugins load the effective `vvoc.json` once during OpenCode startup and share one immutable config snapshot for the lifetime of the process. There is no live reload: restart OpenCode after changing `vvoc.json` or `tui.json(c)`.
284
+
285
+ ### Strict schema, loud failures
286
+
287
+ The config contract is versioned and published with the package — source of truth at `schemas/vvoc/v3.json`. `vvoc.json` must be canonical version 3 and include required sections such as `plugins`. Existing v1/v2/pre-role, incomplete, malformed, or otherwise invalid config files fail instead of being migrated or repaired. `vvoc install` and `vvoc sync` may create a fresh canonical config when no config exists, but they refuse to rewrite an invalid existing `vvoc.json`; fix the file manually and rerun `vvoc sync`.
288
+
289
+ The optional schema-v3 `web` section follows the same layer precedence and is omitted from generated defaults — see [Web tools](#web-tools) for provider selection:
290
+
291
+ ```json
292
+ "web": {
293
+ "search": { "provider": "exa", "apiKey": "optional-exa-key" },
294
+ "fetch": { "provider": "native" }
295
+ }
296
+ ```
297
+
298
+ ### Diagnostics never mutate
299
+
300
+ `vvoc status` and `vvoc doctor` report the installed OpenCode version, the `1.18.2` TUI minimum, selected runtime/TUI/vvoc config paths, and validation problems without normalizing or rewriting files. `vvoc upgrade` can still finish the package installation when the follow-up `vvoc sync` fails; it then reports a partial upgrade, leaves config unchanged, and tells you to fix the invalid config before rerunning `vvoc sync`.
301
+
302
+ Runtime compatibility is current-only: Guardian permission replies use the current OpenCode permission reply path (with the current HTTP reply fallback), hashline edit refs must use current hash/context anchors, and sync writes current managed agents without deleting old pre-rename user or command entries.
303
+
304
+ ### Stability and compatibility
305
+
306
+ Since 1.0, vv-opencode treats the daily-driver surface as stable. The compatibility surfaces are: `vvoc install` / `vvoc sync` / `vvoc launch`, the managed skill names (`vv-spec`, `vv-plan`, `vv-execute`, `vv-review`, `vv-reflect`, `vv-handoff`), the published package exports, canonical vvoc schema v3, and the date-prefixed `.vvoc/specs/YYYY-MM-DD-<slug>/` artifact layout. Breaking workflow or config changes are documented in release notes. The project still prefers conservative, explicit changes over hidden migration magic: user-owned config is never silently clobbered, and invalid current config fails loudly.
307
+
308
+ ### Deterministic local launch
309
+
310
+ Use `vvoc launch` when the vvoc-selected config files should be the only files OpenCode sees for this run:
311
+
312
+ ```bash
313
+ vvoc install --scope project
314
+ vvoc launch --scope project -- run "hello"
315
+ ```
316
+
317
+ `vvoc launch --scope project` is strict and non-mutating: if `.opencode/opencode.json` or `.vvoc/vvoc.json` is missing, it fails with a hint to run `vvoc install --scope project`. When the selected `.opencode/tui.json(c)` exists, launch also sets `OPENCODE_TUI_CONFIG`; a missing TUI file is not synthesized. `--scope effective` follows the layered lookup order, and `--scope global` uses the global config paths.
170
318
 
171
319
  ---
172
320
 
173
- ## The Ten Plugins
321
+ ## Deep dives
322
+
323
+ ### Model roles & presets
324
+
325
+ ```bash
326
+ # View current assignments
327
+ vvoc role list
328
+ vvoc role list --scope effective
329
+
330
+ # Assign models to roles
331
+ vvoc role set default deepseek/deepseek-v4-flash
332
+ vvoc role set smart openai/vv-codex-gpt-5.6-sol-xhigh
333
+ vvoc role set fast openai/vv-codex-gpt-5.6-luna-low
334
+ vvoc role set reviewer zai-coding-plan/glm-5.2 --scope project
335
+
336
+ # Switch provider presets
337
+ vvoc preset vv-codex
338
+ vvoc preset vv-zai
339
+ vvoc preset vv-deepseek
340
+ vvoc preset vv-kimi
341
+ vvoc preset vv-alibaba
342
+ vvoc preset vv-osovv-sol
343
+ vvoc preset vv-osovv-flash
344
+ vvoc preset vv-osovv-kimi
345
+ vvoc preset vv-osovv-qwen
346
+ ```
347
+
348
+ Built-in role IDs: `default`, `smart`, `fast`, `reviewer`, plus any custom lowercase-hyphenated IDs. Presets are partial — applying one only changes the roles it defines. Managed built-in presets (`vv-*`) are refreshed on every `vvoc install`/`vvoc sync`; user-defined presets are preserved as-is.
349
+
350
+ ### Orchestration profiles
351
+
352
+ Three concrete policies control how vv-controller delegates work at runtime:
353
+
354
+ - `single-session` — vv-controller performs exploration, investigation, planning, implementation, and verification directly. Independent reviewer subagents remain available when the user explicitly requests review or when a materially risky completed change benefits from independent cross-model evaluation.
355
+ - `balanced` — vv-controller keeps architecture, critical reading, and final synthesis in the primary session and may selectively delegate bounded search, investigation, mechanical implementation, or review when that is the lightest safe route. Delegation is optional, not mechanically mandatory.
356
+ - `orchestrated` — vv-controller uses the full tracked implementer/reviewer workflow with explicit work items, required reviewers, bounded rounds, and hard stops.
357
+
358
+ Pick a profile explicitly or let a built-in preset select one:
359
+
360
+ ```bash
361
+ vvoc orchestration show --scope effective
362
+ vvoc orchestration set single-session --scope project
363
+ ```
174
364
 
175
- | Plugin | What it helps you do |
365
+ Built-in presets declare an orchestration mapping:
366
+
367
+ | Preset | Profile |
176
368
  |---|---|
177
- | **WorkflowPlugin** | Keep multi-agent work structured with explicit work items, bounded implementation/review loops, reviewer result collection, and safe stops when more context is needed. |
178
- | **ModelRolesPlugin** | Use semantic model roles instead of hardcoded model IDs in OpenCode agents, subagents, and command configs — e.g. `vv-role:smart`, `vv-role:fast` — then map those roles per machine or project. |
179
- | **GuardianPlugin** | Keep long or AFK agent runs moving by auto-approving routine low-risk permission requests. If something looks risky, Guardian does not auto-approve it and leaves the decision to OpenCode's normal manual approval flow. |
180
- | **HashlineEditPlugin** | Route each model to its native editing tool (hashline anchors, exact replace, or DeepSeek `str_replace_editor`), tying changes to fresh `read` output to reduce wrong-line and stale-context edits. |
181
- | **SystemContextInjectionPlugin** | Inject universal primary guidance plus one startup-resolved orchestration policy into vv-controller, with skill discovery and subagent-only explore worker prompts. |
182
- | **SecretsRedactionPlugin** | Reduce accidental secret leakage by redacting tokens, keys, emails, and other sensitive values before messages are sent to the model. |
183
- | **WebToolsPlugin** | Register the provider-neutral `web_search` and `web_fetch` tools, return direct image/PDF attachments, and hide OpenCode's built-in web tools at runtime unless the user explicitly configured their permissions. |
184
- | **ContextTuiPlugin** | Add a native scrollable `/context` dialog with measured usage plus detailed observable per-tool and per-MCP schema/history estimates, explicitly marking data that OpenCode does not expose. |
185
- | **ToolHistoryCompactionPlugin** | Shrink the replayed conversation context non-destructively by compacting old tool outputs in the model replay (old reads to `[Read <file>, lines X-Y]`, over-budget ephemeral outputs pruned), while retaining web/search/skill knowledge results. |
186
- | **AnalyticsPlugin** | Persist per-step token and cache telemetry with vvoc/OpenCode version attribution, show a live `cache NN%` indicator next to the session prompt plus a combined OpenCode/vvoc version line in the sidebar footer, and answer "did my cache optimizations help?" via `vvoc analytics cache-hit-rate`. |
369
+ | `vv-codex` | single-session |
370
+ | `vv-kimi` | single-session |
371
+ | `vv-alibaba` | single-session |
372
+ | `vv-osovv-sol` | single-session |
373
+ | `vv-osovv-flash` | single-session |
374
+ | `vv-osovv-kimi` | single-session |
375
+ | `vv-osovv-qwen` | single-session |
376
+ | `vv-zai` | balanced |
377
+ | `vv-deepseek` | balanced |
378
+
379
+ Applying a built-in preset changes both model roles and the root orchestration profile atomically. A custom user-defined preset without an orchestration section preserves the current root profile. `vvoc status` reports the profile resolved from the selected vvoc source; effective status with no config files reports `balanced`.
380
+
381
+ Profiles are enforced through the concrete policy injected into vv-controller at startup — the model only receives its active work instructions and never sees inactive profile alternatives. The first version does not disable tools, change permissions, or block subagent types; the policy is prompt-driven, and asynchronous vv-execute classic mode remains available through that skill's explicit inline/classic selection. Profile changes take effect after an OpenCode restart, like all vvoc config changes.
382
+
383
+ ### Workflow work items
187
384
 
188
385
  Workflow work items are opened with explicit intent. For implementation loops, controllers use:
189
386
 
@@ -202,7 +399,7 @@ Workflow work items are opened with explicit intent. For implementation loops, c
202
399
 
203
400
  For review-only reports, use `"mode": "review_only"`. In review-only mode, reviewer `FAIL` is a completed finding result: required reviewers are collected independently, parallel `spec` and `code` reviewers may both return `FAIL`, and the item does not route to `vv-implementer` unless the user explicitly requests fixes.
204
401
 
205
- ### Edit Format Routing
402
+ ### Edit format routing
206
403
 
207
404
  `HashlineEditPlugin` resolves an edit mode per session model and exposes only the matching edit tool to that model:
208
405
 
@@ -213,9 +410,7 @@ For review-only reports, use `"mode": "review_only"`. In review-only mode, revie
213
410
 
214
411
  The default routing table sends `deepseek` to `str_replace_editor`, `kimi`, `qwen`, and `glm` to `replace`, and `gpt`/`codex` to `passthrough`; everything else stays on `hashline`. Patterns match case-insensitively against the session `providerID` first, then `modelID`; the first matching rule wins.
215
412
 
216
- `vvoc sync` and `vvoc init` write this default table into `vvoc.json` so it is visible and editable. Materialization is conservative: a routing value you have changed is never overwritten; the table is only filled in where it is missing.
217
-
218
- Override routing in `vvoc.json` (schema v3). The `plugins["hashline-edit"]` entry accepts a boolean or an object:
413
+ `vvoc sync` and `vvoc init` write this default table into `vvoc.json` so it is visible and editable. Materialization is conservative: a routing value you have changed is never overwritten; the table is only filled in where it is missing. Override routing in `vvoc.json` (schema v3) — the `plugins["hashline-edit"]` entry accepts a boolean or an object:
219
414
 
220
415
  ```json
221
416
  "plugins": {
@@ -228,21 +423,22 @@ Override routing in `vvoc.json` (schema v3). The `plugins["hashline-edit"]` entr
228
423
  }
229
424
  }
230
425
  ```
426
+
231
427
  Routing changes require an OpenCode restart, like other runtime plugin settings.
232
428
 
233
- ### Tool History Compaction
429
+ ### Tool history compaction
234
430
 
235
431
  `ToolHistoryCompactionPlugin` shrinks the context replayed to the model on every turn without touching on-disk storage. It rewrites only the in-memory message copy through the `experimental.chat.messages.transform` hook, and only the `output` of old completed tool parts — `input` and part structure (callID/type/order) are never changed, so provider tool_use/tool_result stitching stays intact.
236
432
 
237
- The **recent working context is never touched**: the newest message and the last `protectRecentMessages` messages (default 8, measured by message recency time with array-order fallback) are always replayed verbatim, regardless of call count, output size, tool class, or parallel batching. Compaction only applies to messages older than that window.
433
+ The recent working context is never touched: the newest message and the last `protectRecentMessages` messages (default 8, measured by message recency time with array-order fallback) are always replayed verbatim, regardless of call count, output size, tool class, or parallel batching. Compaction only applies to messages older than that window.
238
434
 
239
435
  Compaction is tool-classified, not blanket:
240
436
 
241
437
  - **Retained (never compacted):** results that stay relevant for the whole session — `webfetch`/`web_fetch`/web readers, web/search tools, `skill`, and subagent (`task`/`agent`) outputs. Retained tools also never consume the per-call protection budget.
242
438
  - **Old reads** collapse to `[Read <file>, lines X-Y]` (range recovered from the line-numbered output; missing file or range falls back to head/tail pruning, never a fabricated summary).
243
- - **Other ephemeral outputs** (`bash`, `grep`, `glob`, …) past `outputMaxChars` are pruned to `headChars` + a fixed marker + `tailChars`, DeepSeek-Harness style. With `savePrunedOutput` (default on), the full output is written once to `$XDG_DATA_HOME/vvoc/tool-output/tool-<callID>.txt` and the marker embeds `Full output saved to: <path>`, so the model can re-read the full content instead of reconstructing it from fragments.
439
+ - **Other ephemeral outputs** (`bash`, `grep`, `glob`, …) past `outputMaxChars` are pruned to `headChars` + a fixed marker + `tailChars`. With `savePrunedOutput` (default on), the full output is written once to `$XDG_DATA_HOME/vvoc/tool-output/tool-<callID>.txt` and the marker embeds `Full output saved to: <path>`, so the model can re-read the full content instead of reconstructing it from fragments.
244
440
 
245
- Outside the window, the last `protectLastCalls` completed calls are also protected; error parts and parts already compacted by OpenCode are skipped. Rewrites are deterministic and idempotent (each part is rewritten at most once, and the saved path is deterministic per callID), and a `minSavingsChars` guard skips rewrites that would churn the prompt cache for a tiny gain.
441
+ Outside the recent window, the last `protectLastCalls` completed calls are also protected; error parts and parts already compacted by OpenCode are skipped. Rewrites are deterministic and idempotent (each part is rewritten at most once, and the saved path is deterministic per callID), and a `minSavingsChars` guard skips rewrites that would churn the prompt cache for a tiny gain.
246
442
 
247
443
  Config lives in `vvoc.json` under `plugins["tool-history-compaction"]` (boolean or object) and is conservatively materialized by `vvoc sync`/`init`:
248
444
 
@@ -265,11 +461,11 @@ Config lives in `vvoc.json` under `plugins["tool-history-compaction"]` (boolean
265
461
 
266
462
  Set `outputMaxChars` to `0` to disable pruning, `protectRecentMessages` to `0` to disable the message window (only the newest message stays protected), `savePrunedOutput` to `false` to skip disk persistence, or `"enabled": false` to disable the plugin entirely. Changes require an OpenCode restart.
267
463
 
268
- ### Cache Hit Rate Analytics
464
+ ### Cache hit rate analytics
269
465
 
270
466
  `AnalyticsPlugin` records one line per completed model step — fresh input, cache read, cache write, output, reasoning, recorded cost — to `$XDG_DATA_HOME/vvoc/analytics/usage-YYYY-MM.jsonl`, attributed with the vvoc version, the OpenCode version (from session telemetry), project, provider, model, and agent. Telemetry never leaves the machine; disable collection with `"plugins": { "analytics": false }` and delete old monthly files freely.
271
467
 
272
- In the TUI you get a live `cache NN%` indicator next to the session prompt (green at 80%+, yellow at 50%+, red below, muted `n/a` before the first cache-eligible step) and a combined footer line `• OpenCode <version> · vvoc vX.Y.Z` in the sidebar (the stock version line, extended with the vvoc version). The indicator is per-session and computed in memory.
468
+ In the TUI you get a live `cache NN%` indicator next to the session prompt (green at 80%+, yellow at 50%+, red below, muted `n/a` before the first cache-eligible step) and a combined footer line `• OpenCode <version> · vvoc vX.Y.Z` in the sidebar. The indicator is per-session and computed in memory.
273
469
 
274
470
  Retrospective analysis lives in the CLI:
275
471
 
@@ -281,20 +477,18 @@ vvoc analytics cache-hit-rate --group-by session|model|provider|project|week|mon
281
477
  vvoc analytics cache-hit-rate --project my-repo --order hit-rate --limit 10 --json
282
478
  ```
283
479
 
284
- The hit rate is token-weighted: `cacheRead / (cacheRead + cacheWrite + input)` over cache-eligible steps; `COVERAGE` shows the share of steps whose provider reported cache tokens at all, so providers without prompt caching read as `n/a` instead of a misleading `0%`. `--since`/`--until` accept `Nd`/`Nw`/`Nm` or `YYYY-MM-DD`.
480
+ The hit rate is token-weighted: `cacheRead / (cacheRead + cacheWrite + input)` over cache-eligible steps; `COVERAGE` shows the share of steps whose provider reported cache tokens at all, so providers without prompt caching read as `n/a` instead of a misleading `0%`. `--since`/`--until` accept `Nd`/`Nw`/`Nm` or `YYYY-MM-DD`; `--order` accepts `date`, `steps`, or `hit-rate`.
285
481
 
286
- Agents can run this analysis conversationally too: the managed `vvoc-usage-analytics` skill answers usage, cache, and cost questions inside a session — including historical comparisons from `opencode.db` that predate the analytics plugin (see Managed Skills).
482
+ Agents can run this analysis conversationally too: the managed `vvoc-usage-analytics` skill answers usage, cache, and cost questions inside a session — including historical comparisons from `opencode.db` that predate the analytics plugin.
287
483
 
288
- ### Web Tools
484
+ ### Web tools
289
485
 
290
486
  `WebToolsPlugin` exposes exactly two canonical model-facing tools:
291
487
 
292
488
  - `web_search` requests the `web_search` permission and returns ranked titles, URLs, snippets, and publication dates. Search uses Exa by default, Brave when configured, or the direct Z.AI/Zhipu Tool API for an explicitly selected region.
293
489
  - `web_fetch` requests the `web_fetch` permission and retrieves a known HTTP or HTTPS URL as Markdown, text, raw HTML, or a direct JPEG, PNG, GIF, WebP, or PDF attachment. Fetch uses local native retrieval by default, Spider for configured textual extraction, or the direct Z.AI/Zhipu Reader Tool API.
294
490
 
295
- The `web-tools` vvoc plugin toggle is enabled by default.
296
-
297
- Provider selection belongs to `vvoc.json`, not to individual model calls. Add this optional property fragment to an otherwise valid canonical schema-v3 config:
491
+ The `web-tools` vvoc plugin toggle is enabled by default. Provider selection belongs to `vvoc.json`, not to individual model calls:
298
492
 
299
493
  ```json
300
494
  "web": {
@@ -305,7 +499,7 @@ Provider selection belongs to `vvoc.json`, not to individual model calls. Add th
305
499
 
306
500
  Supported search providers are `exa` (default), `brave`, and `zai`. Supported fetch providers are `native` (default, no credential required), `spider`, and `zai`. A `zai` section must set `region` to either `international` or `china`; the plugin never guesses or falls back to another region.
307
501
 
308
- Direct Z.AI endpoint routing is:
502
+ Direct Z.AI endpoint routing:
309
503
 
310
504
  | Region | Search | Reader | Search engine |
311
505
  |---|---|---|---|
@@ -319,7 +513,7 @@ Credentials resolve in this order:
319
513
  1. `EXA_API_KEY`, `BRAVE_API_KEY`, `SPIDER_API_KEY`, or `ZAI_API_KEY` for the selected provider
320
514
  2. `web.search.apiKey` or `web.fetch.apiKey` in the effective `vvoc.json`
321
515
 
322
- Environment variables win when both sources exist. Config changes take effect after restarting OpenCode. Configured `apiKey` values become exact-match SecretsRedactionPlugin rules for provider-bound message flows, and WebToolsPlugin diagnostics report only the credential source (`env` or `config`), never the value. If a project-layer `.vvoc/vvoc.json` containing an `apiKey` is tracked by Git, startup logs warn with the file name only. Prefer environment variables or the global vvoc layer; do not commit credentials.
516
+ Environment variables win when both sources exist; config changes take effect after restarting OpenCode. Configured `apiKey` values become exact-match SecretsRedactionPlugin rules for provider-bound message flows, and WebToolsPlugin diagnostics report only the credential source (`env` or `config`), never the value. If a project-layer `.vvoc/vvoc.json` containing an `apiKey` is tracked by Git, startup logs warn with the file name only. Prefer environment variables or the global vvoc layer; do not commit credentials.
323
517
 
324
518
  While `web-tools` is enabled, its runtime config hook denies the built-in `webfetch` and `websearch` permission ids in memory, leaving only `web_fetch` and `web_search` in the normal tool surface. It does not rewrite OpenCode files or remove MCP servers. An explicit user permission entry for `webfetch` or `websearch` is respected and may intentionally keep that built-in visible. Disable the plugin and restart to restore stock behavior:
325
519
 
@@ -329,15 +523,15 @@ vvoc plugin disable web-tools
329
523
 
330
524
  Unrelated MCP search or reader tools are not removed automatically; disable those separately if you want only the two canonical tools visible.
331
525
 
332
- ### `/context` accuracy
526
+ ### `/context` inspector
333
527
 
334
- Run `/context` inside an active session. Its bounded host-owned dialog has three tabs: **Overview**, **Tools**, and **MCP**. Use left/right arrows or `1`, `2`, and `3` to switch tabs and up/down to scroll long detail. The measured header remains visible on every tab. Top-line used/remaining values come from the latest assistant turn's provider-reported input, cache-read, and output token counts when OpenCode exposes them.
528
+ Run `/context` inside an active session. Its bounded host-owned dialog has three tabs: **Overview**, **Tools**, and **MCP**. Use left/right arrows or `1`, `2`, and `3` to switch tabs and up/down to scroll long detail; the measured header remains visible on every tab. Top-line used/remaining values come from the latest assistant turn's provider-reported input, cache-read, and output token counts when OpenCode exposes them.
335
529
 
336
- Overview category rows remain provider-neutral estimates derived from observable TUI/SDK state: system instructions, skill catalog, loaded skills, tool schemas, user and assistant messages, tool calls and results, files, and the latest compaction summary. Percentages are always `estimated tokens / current model contextLimit`; if OpenCode does not expose a positive current limit, the percentage is shown as an em dash rather than using another denominator. Numeric percentages may exceed 100% when estimates drift, while visual bars clamp only their fill at 100%.
530
+ Overview category rows are provider-neutral estimates derived from observable TUI/SDK state: system instructions, skill catalog, loaded skills, tool schemas, user and assistant messages, tool calls and results, files, and the latest compaction summary. Percentages are always `estimated tokens / current model contextLimit`; if OpenCode does not expose a positive current limit, the percentage is shown as an em dash rather than using another denominator. Numeric percentages may exceed 100% when estimates drift, while visual bars clamp only their fill at 100%.
337
531
 
338
- The Tools tab separates each observable current tool's persistent **schema** estimate from its active **history** estimate, call count, combined total, source, and percentages. When a schema catalog is unavailable, the row says `schema unavailable` and labels the history-only subtotal as `known total` rather than presenting a false zero. History includes only tool parts in the active context: the latest compaction summary and subsequent turns. Pending and running calls include observable input; completed calls include output and failed calls include errors. The `skill` tool remains visible in detail, but its history continues to belong to Overview's `Loaded skill results` category so it is not double-counted as `Tool calls and results`.
532
+ The Tools tab separates each observable current tool's persistent **schema** estimate from its active **history** estimate, call count, combined total, source, and percentages. When a schema catalog is unavailable, the row says `schema unavailable` and labels the history-only subtotal as `known total` rather than presenting a false zero. History includes only tool parts in the active context: the latest compaction summary and subsequent turns. The `skill` tool remains visible in detail, but its history belongs to Overview's `Loaded skill results` category so it is not double-counted.
339
533
 
340
- The MCP tab aggregates observable current schema and retained active history by server and nests the attributed tools. OpenCode 1.18.x does not expose connected MCP tool definitions through its public TUI/SDK tool catalog, so connected servers show `current tools unavailable` and `schema unavailable`; their `known total` includes retained history only, while the unexposed schema overhead remains in `Unknown/provider-only`. `disabled`, `failed`, `needs_auth`, and `needs_client_registration` servers have a known zero current schema, while matching call history can remain visible until compaction removes it. Attribution follows OpenCode's sanitized `<server>_<tool>` naming contract with unique longest-prefix matching. Sanitized collisions or other ambiguous ownership fail closed under **Other external/plugin** with a bounded warning instead of being guessed.
534
+ The MCP tab aggregates observable current schema and retained active history by server and nests the attributed tools. OpenCode 1.18.x does not expose connected MCP tool definitions through its public TUI/SDK tool catalog, so connected servers show `current tools unavailable` and `schema unavailable`; their `known total` includes retained history only, while the unexposed schema overhead remains in `Unknown/provider-only`. Attribution follows OpenCode's sanitized `<server>_<tool>` naming contract with unique longest-prefix matching; sanitized collisions or other ambiguous ownership fail closed under **Other external/plugin** with a bounded warning instead of being guessed.
341
535
 
342
536
  The plugin does **not** claim to reconstruct the exact final provider request or provide provider-exact tokenization. Hidden provider transformations, plugin-added data, or otherwise unattributable content appears as `Unknown/provider-only`; when visible estimates exceed provider usage, the dialog reports estimation drift instead of forcing totals to match. Collection reuses OpenCode's existing tool catalog, active parts, model metadata, and MCP status snapshot without issuing extra MCP requests.
343
537
 
@@ -345,206 +539,27 @@ The `context` vvoc plugin toggle defaults to enabled. Disable it with `vvoc plug
345
539
 
346
540
  ---
347
541
 
348
- ## CLI at a Glance
349
-
350
- | Command | Purpose |
351
- |---|---|
352
- | `vvoc init` | Interactive bootstrap flow |
353
- | `vvoc install` | Non-interactive setup and scaffolding |
354
- | `vvoc sync` | Refresh runtime/TUI plugin entries, agents, prompts, skills, config |
355
- | `vvoc launch` | Launch OpenCode with deterministic runtime, TUI, and vvoc config sources |
356
- | `vvoc status` | Show current installation state, including OpenCode version compatibility and TUI registration |
357
- | `vvoc doctor` | Diagnose OpenCode version/runtime/TUI/vvoc setup problems (exits non-zero on issues) |
358
- | `vvoc config validate` | Validate canonical `vvoc.json` |
359
- | `vvoc role list\|set\|unset` | Manage model role assignments |
360
- | `vvoc preset list\|show\|<name>` | Inspect or apply named presets |
361
- | `vvoc guardian config` | Print or write guardian section |
362
- | `vvoc plugin list` | List OpenCode plugin entries |
363
- | `vvoc plugin enable\|disable` | Toggle a vvoc-managed plugin on or off |
364
- | `vvoc orchestration show\|set` | Show or set the vv-controller orchestration profile |
365
- | `vvoc patch-provider stepfun-ai\|codex\|deepseek\|kimi\|alibaba\|all` | Patch OpenCode providers; `codex` adds subscription-safe OpenAI aliases (also accepts `openai`), `deepseek`/`kimi`/`alibaba` add vv- reasoning-effort aliases, `all` patches every provider at once |
366
- | `vvoc completion` | Install shell completions |
367
- | `vvoc upgrade` | Upgrade global package and run follow-up sync; sync failure is reported as a partial upgrade |
368
- | `vvoc analytics cache-hit-rate` | Aggregate persisted cache hit rate by day, week, month, session, model, provider, project, vvoc version, or OpenCode version |
369
- | `vvoc version` | Print installed version |
370
-
371
- Guardian duration overrides use positive whole milliseconds. Both `--timeout-ms` and
372
- `--review-toast-duration-ms` reject zero, negative, fractional, missing, or malformed values:
373
-
374
- ```bash
375
- vvoc guardian config --print --timeout-ms 30000 --review-toast-duration-ms 5000
376
- ```
377
-
378
- ---
379
- ---
380
-
381
- ## Orchestration Profiles
382
-
383
- Three concrete policies control how vv-controller delegates work at runtime:
384
-
385
- - `single-session`: vv-controller performs exploration, investigation, planning, implementation,
386
- and verification directly. Independent reviewer subagents remain available when the user
387
- explicitly requests review or when a materially risky completed change benefits from independent
388
- cross-model evaluation.
389
- - `balanced`: vv-controller keeps architecture, critical reading, and final synthesis in the
390
- primary session and may selectively delegate bounded search, investigation, mechanical
391
- implementation, or review when that is the lightest safe route. Delegation is optional, not
392
- mechanically mandatory.
393
- - `orchestrated`: vv-controller uses the full tracked implementer/reviewer workflow with
394
- explicit work items, required reviewers, bounded rounds, and hard stops.
395
-
396
- Pick a profile explicitly or let a built-in preset select one:
397
-
398
- ```bash
399
- vvoc orchestration show --scope effective
400
- vvoc orchestration set single-session --scope project
401
- ```
402
-
403
- Built-in presets declare an orchestration mapping:
404
-
405
- | Preset | Profile |
406
- |---|---|
407
- | `vv-codex` | single-session |
408
- | `vv-kimi` | single-session |
409
- | `vv-alibaba` | single-session |
410
- | `vv-osovv-sol` | single-session |
411
- | `vv-osovv-flash` | single-session |
412
- | `vv-osovv-kimi` | single-session |
413
- | `vv-osovv-qwen` | single-session |
414
- | `vv-zai` | balanced |
415
- | `vv-deepseek` | balanced |
416
-
417
- Applying a built-in preset changes both model roles and the root orchestration profile
418
- atomically. A custom user-defined preset without an orchestration section preserves the current
419
- root profile. `vvoc status` reports the profile resolved from the selected vvoc source; effective
420
- status with no config files reports `balanced`.
421
-
422
- ### Prompt-only first version
423
-
424
- Profiles are enforced through the concrete policy injected into vv-controller at startup —
425
- the model only receives its active work instructions and does not see inactive profile alternatives.
426
- The first version does not disable tools, change permissions, or block subagent types; the policy
427
- is prompt-driven and asynchronous vv-execute classic mode remains available through that skill's
428
- explicit inline/classic selection.
429
-
430
- ### Restart requirement
431
-
432
- Config changes to the orchestration profile take effect after an OpenCode restart. Runtime plugins
433
- resolve the profile once from the startup vvoc config snapshot and do not live-reload.
434
-
435
- ## Model Roles & Presets
542
+ ## Local development
436
543
 
437
544
  ```bash
438
- # View current assignments
439
- vvoc role list
440
- vvoc role list --scope effective
441
-
442
- # Assign models to roles
443
- vvoc role set default openai/gpt-5.6-terra
444
- vvoc role set team-review anthropic/claude-sonnet-4-5 --scope project
445
- vvoc role set smart openai/vv-codex-gpt-5.6-sol-xhigh
446
- vvoc role set fast openai/gpt-5.6-luna
447
-
448
- # Switch provider presets
449
- vvoc preset vv-codex
450
- vvoc preset vv-zai
451
- vvoc preset vv-deepseek
452
- vvoc preset vv-kimi
453
- vvoc preset vv-alibaba
454
- vvoc preset vv-osovv-sol
455
- vvoc preset vv-osovv-flash
456
- vvoc preset vv-osovv-kimi
457
- vvoc preset vv-osovv-qwen
458
- ```
459
-
460
- Built-in role IDs: `default`, `smart`, `fast`, `reviewer` + any custom lowercase-hyphenated IDs.
461
-
462
- Presets are partial — applying one only changes the roles it defines. Managed built-in presets (`vv-*`) are refreshed on every `vvoc install`/`vvoc sync`; user-defined presets are preserved as-is.
463
-
464
- ---
465
-
466
- ## Config & Data Layout
467
-
468
- Mutating commands default to global for backward compatibility. Add `--scope project` to write a project-local layer. Read/diagnostic commands accept `--scope global|project|effective`, where `effective` resolves in this order:
469
-
470
- 1. explicit env override (`VVOC_CONFIG` / `OPENCODE_CONFIG` / `OPENCODE_TUI_CONFIG`)
471
- 2. nearest project layer
472
- 3. global layer
473
- 4. built-in defaults when the command/runtime permits defaults
474
-
475
- Canonical project-local paths:
476
-
477
- ```text
478
- OpenCode config → ./.opencode/opencode.json(c)
479
- OpenCode TUI config → ./.opencode/tui.json(c)
480
- vvoc config → ./.vvoc/vvoc.json
481
- Managed agent prompts → ./.vvoc/agents/*.md
482
- Managed skills → ./.vvoc/skills/*/SKILL.md
483
- Spec package directory → ./.vvoc/specs/YYYY-MM-DD-<slug>/
484
- spec.xml # normative spec document (required)
485
- design-context.xml # curated design memory (optional)
486
- plan.xml # implementation plan (created by vv-plan)
487
- Handoff notes → ./.vvoc/handoff/YYYY-MM-DD-<session-slug>/handoff.xml
488
-
489
- ```
490
-
491
- Legacy root-level `./opencode.json` and `./opencode.jsonc` are intentionally not used as vvoc project layers.
492
-
493
- ```
494
- Global OpenCode config → $XDG_CONFIG_HOME/opencode/opencode.json
495
- Global OpenCode TUI → $XDG_CONFIG_HOME/opencode/tui.json(c)
496
- Global vvoc config → $XDG_CONFIG_HOME/vvoc/vvoc.json
497
- Managed agent prompts → $XDG_CONFIG_HOME/vvoc/agents/*.md (global)
498
- ./.vvoc/agents/*.md (project)
499
- Managed skills → $XDG_CONFIG_HOME/vvoc/skills/*/SKILL.md (global)
500
- ./.vvoc/skills/*/SKILL.md (project)
501
- Spec documents → ./.vvoc/specs/YYYY-MM-DD-<slug>/spec.xml
502
- Optional design context → ./.vvoc/specs/YYYY-MM-DD-<slug>/design-context.xml
503
- Implementation plans → ./.vvoc/specs/YYYY-MM-DD-<slug>/plan.xml
504
- Persisted data → $XDG_DATA_HOME/vvoc/
505
- Usage analytics → $XDG_DATA_HOME/vvoc/analytics/usage-YYYY-MM.jsonl (local-only cache telemetry)
506
- Repository memory → ./.vvoc/lessons/*.xml (lazy vv-reflect fallback)
507
- ./.vvoc/runbooks/*.xml (lazy vv-reflect fallback)
508
- Session handoff notes → ./.vvoc/handoff/YYYY-MM-DD-<session-slug>/handoff.xml
509
- ```
510
-
511
- Schema is versioned and published with the package — source of truth at `schemas/vvoc/v3.json`. The current config contract is strict: `vvoc.json` must be canonical version 3 and include required sections such as `plugins`. Existing v1/v2/pre-role, incomplete, malformed, or otherwise invalid config files fail instead of being migrated or repaired. `vvoc install` and `vvoc sync` may create a fresh canonical config when no config exists, but they refuse to rewrite an invalid existing `vvoc.json`; fix the file manually and rerun `vvoc sync`.
512
-
513
- The optional schema-v3 `web` section follows the same layer precedence as the rest of `vvoc.json` and is omitted from generated defaults:
514
-
515
- ```json
516
- "web": {
517
- "search": { "provider": "exa", "apiKey": "optional-exa-key" },
518
- "fetch": { "provider": "native" }
519
- }
545
+ bun install # Install dependencies
546
+ bun run check # Typecheck + lint + format check + GRACE markup check + test
547
+ bun run fmt # Auto-format source files
548
+ bun run release:check # Verify package/schema release consistency
520
549
  ```
521
550
 
522
- Use `brave` instead of `exa` for Brave Web Search, or `spider` instead of `native` for Spider textual extraction. The matching environment variable takes precedence over `apiKey` fields.
523
-
524
- OpenCode intentionally keeps server/runtime plugins and native terminal UI plugins in separate configuration surfaces. `opencode.json(c)` is loaded by the core/server plugin runtime and activates vvoc features such as model roles, Guardian, workflow, hashline edit, redaction, and web tools. `tui.json(c)` is loaded by the terminal UI process and activates the package's `./tui` module, currently the `/context` inspector. The same pinned package version appears in both files, but OpenCode selects a different public export for each process; headless/server launches therefore do not need to load the Solid/OpenTUI UI module.
525
-
526
- `vvoc install`, `vvoc init`, and `vvoc sync` conservatively add the pinned base package specifier (for example `@osovv/vv-opencode@X.Y.Z`) to dedicated `tui.json(c)`; OpenCode then selects the package's public `./tui` export. Sync migrates the broken legacy `@osovv/vv-opencode/tui` form and older managed pins. Existing comments, unrelated settings, unrelated plugin entries, and `[specifier, options]` tuples are preserved; malformed plugin entries fail without rewrite.
527
-
528
- `vvoc status` and `vvoc doctor` are diagnostic exceptions: they report the installed OpenCode version, the `1.18.2` TUI minimum, selected runtime/TUI/vvoc config paths, and validation problems without normalizing or rewriting the files. `vvoc upgrade` can still finish the package installation when the follow-up `vvoc sync` fails; in that case it reports a partial upgrade, leaves config unchanged, and tells you to fix the invalid config manually before rerunning `vvoc sync`.
551
+ Git hooks are managed via `lefthook`.
529
552
 
530
- Runtime compatibility is current-only. Guardian permission replies use the current OpenCode permission reply path (with the current HTTP reply fallback), Hashline edit refs must use current hash/context anchors, and sync writes current managed agents without deleting old pre-rename user or command entries.
531
-
532
- Runtime plugins load the effective `vvoc.json` once during OpenCode startup and share the same immutable config snapshot for the lifetime of the process. There is no live reload; restart OpenCode after changing `vvoc.json` or `tui.json(c)`.
533
-
534
- ### Deterministic local launch
535
-
536
- Use `vvoc launch` when you want the vvoc-selected config files to be the only files OpenCode sees for this run:
553
+ Smoke-test the built CLI against an isolated config home:
537
554
 
538
555
  ```bash
539
- vvoc install --scope project
540
- vvoc launch --scope project -- run "hello"
556
+ tmpdir="$(mktemp -d)"
557
+ bun run build
558
+ bun dist/cli.js install --config-dir "$tmpdir"
559
+ bun dist/cli.js status --config-dir "$tmpdir"
541
560
  ```
542
561
 
543
- `vvoc launch --scope project` is strict and non-mutating: if `.opencode/opencode.json` or `.vvoc/vvoc.json` is missing, it fails with a hint to run `vvoc install --scope project`. When the selected `.opencode/tui.json(c)` exists, launch also sets `OPENCODE_TUI_CONFIG`; a missing TUI file is not synthesized during launch. `--scope effective` follows the layered lookup order, and `--scope global` uses the global config paths.
544
-
545
- ### Test the local TUI before release
546
-
547
- From this repository, launch OpenCode against the freshly built local `dist/tui.js` without publishing or rewriting your selected configs:
562
+ Test the local TUI against a freshly built `dist/tui.js` without publishing or rewriting your selected configs:
548
563
 
549
564
  ```bash
550
565
  bun run tui:local
@@ -554,69 +569,7 @@ bun run tui:local -- --scope project
554
569
 
555
570
  The command defaults to `effective` config resolution. It builds the package, copies the selected `tui.json(c)` into a temporary isolated config home, replaces only the managed vv-opencode TUI entry with a local `file://` URL, preserves unrelated TUI settings and tuple options, and forwards remaining arguments to OpenCode. The original OpenCode, TUI, and vvoc config files are not modified, and the temporary config is removed after OpenCode exits. Restart the command after source changes because runtime plugins do not live reload.
556
571
 
557
- ---
558
-
559
- ## Managed Agents
560
-
561
- All prompt files are scaffolded by `vvoc install` / `vvoc sync`:
562
-
563
- | Agent | When it helps |
564
- |---|---|
565
- | `vv-controller` | Primary agent that follows the concrete work policy selected for the session by the orchestration profile |
566
- | `enhancer` | Improves rough requests before execution when a clearer prompt would help |
567
- | `vv-implementer` | Applies a focused approved change and verifies it before reporting completion |
568
- | `vv-spec-reviewer` | Checks whether implementation matches the requested spec and acceptance criteria |
569
- | `vv-code-reviewer` | Looks for bugs, regressions, maintainability risks, and missing tests |
570
- | `investigator` | Finds the root cause first when behavior is unclear or a failure needs diagnosis |
571
- | `guardian` | Supports GuardianPlugin by auto-approving routine low-risk permission requests and leaving risky ones for manual approval |
572
-
573
- ---
574
-
575
- ## Managed Skills
576
-
577
- Managed skills come in two families: `vv-*` skills guide the work protocol (spec, plan, execute, review, reflect, handoff), while `vvoc-*` skills operate and observe the vvoc/OpenCode tooling itself. Seven skills are scaffolded alongside agents:
578
-
579
- | Skill | When to use it | What it gives you |
580
- |---|---|---|
581
- | `vv-spec` | You have a feature or creative request and no agreed contract yet | A guided interview, recommended options, and a saved spec in `.vvoc/specs/YYYY-MM-DD-<slug>/spec.xml` |
582
- | `vv-plan` | A spec is approved and ready to implement | A task-level implementation plan with file targets, contracts, dependencies, and acceptance criteria |
583
- | `vv-execute` | A plan is approved and you want it applied step by step | Ordered execution with verification, explicit inline-or-classic mode choice, and applied spec/plan archival |
584
- | `vv-review` | You want findings, not fixes | A review-only workflow that reports spec/code issues and stops before implementation |
585
- | `vv-reflect` | A long development, debugging, ops, or investigation session produced reusable knowledge | Durable notes in existing docs or `.vvoc/lessons` / `.vvoc/runbooks` for future agents |
586
- | `vv-handoff` | You are ending a session and want the visible context preserved for a future session | A redacted XML note at `.vvoc/handoff/YYYY-MM-DD-<session-slug>/handoff.xml`, without running new checks or collecting fresh context |
587
- | `vvoc-usage-analytics` | You ask about token usage, cache hit rate, costs, or whether a vvoc/OpenCode upgrade changed caching | An agent-run read-only analysis across `vvoc analytics`, the analytics JSONL, and historical `opencode.db` data (validated SQL snippets included) |
588
-
589
- Spec and plan artifacts stay XML so requirements, tasks, acceptance criteria, and dependencies remain easy to grep and review.
590
-
591
- `vv-reflect` creates `.vvoc/lessons` and `.vvoc/runbooks` lazily only after approved fallback writes. It prefers an existing repository documentation convention when there is a high-confidence match.
592
-
593
- `vv-handoff` writes only the project-local XML handoff artifact from context already visible in the session. It records missing git, diff, or verification evidence as not collected in the current session instead of running commands.
594
-
595
- Skills are loaded by OpenCode at session start through `config.skills.paths` (registered by the SystemContextInjectionPlugin). The `vv-controller` agent's `<skill_trigger_rule>` ensures they are invoked automatically when the user's request matches their trigger conditions.
596
-
597
- ---
598
-
599
- ## Local Development
600
-
601
- ```bash
602
- bun install # Install dependencies
603
- bun run check # Typecheck + lint + format check + test
604
- bun run fmt # Auto-format source files
605
- bun run release:check # Verify package/schema release consistency
606
- ```
607
-
608
- Git hooks managed via `lefthook`.
609
-
610
- ### Smoke-test the built CLI
611
-
612
- ```bash
613
- tmpdir="$(mktemp -d)"
614
- bun run build
615
- bun dist/cli.js install --config-dir "$tmpdir"
616
- bun dist/cli.js status --config-dir "$tmpdir"
617
- ```
618
-
619
- ### Full release verification
572
+ Full release verification:
620
573
 
621
574
  ```bash
622
575
  bun run release:check
@@ -625,17 +578,17 @@ bun run pack:check
625
578
  ```
626
579
 
627
580
  ---
581
+
628
582
  ## Publishing
629
583
 
630
584
  The release flow is automated via a local wrapper and an exact-commit, CI-gated GitHub Actions workflow.
631
585
 
632
- ### Local bump
633
-
634
586
  ```bash
635
587
  bun run release:bump patch # or minor, major, prerelease, or explicit semver
636
588
  ```
637
589
 
638
590
  This will:
591
+
639
592
  1. Reject if the worktree is dirty
640
593
  2. Bump `package.json` via `npm version --no-git-tag-version`
641
594
  3. Generate a required AI release summary with `opencode --pure run`
@@ -649,38 +602,19 @@ This will:
649
602
  11. Retry npm metadata propagation, then verify that npm reports the exact release commit as the published `gitHead`
650
603
  12. Create and push the annotated tag locally, then create the GitHub Release through `gh`
651
604
 
652
- Required local release prerequisite:
653
- - `opencode` must be available from `PATH`.
654
- - `gh` must be installed and authenticated with permission to dispatch/watch workflows and create releases in the repository.
655
- - `gh run watch` does not support fine-grained PAT authentication; use a supported `gh` login such as OAuth or a classic token.
656
- - The summary model defaults to `deepseek/deepseek-v4-flash`.
657
- - Override with `VVOC_RELEASE_SUMMARY_MODEL=provider/model`.
658
- - Override the per-attempt timeout with `VVOC_RELEASE_SUMMARY_TIMEOUT_MS=120000`.
659
- Run `release:bump` from a checked-out branch with branch and tag push access to `origin`. A normal branch push never publishes by itself; the wrapper explicitly dispatches the workflow for the exact pushed commit.
660
-
661
- The GitHub Actions workflow checks out the requested commit SHA, verifies that its
662
- `package.json` version matches the dispatch input, and runs full validation
663
- (typecheck, lint, fmt check, tests, build, pack check, and `release:check`). Only
664
- after every gate passes does it publish to npm with provenance. The local wrapper
665
- waits for that CI result, retries registry metadata propagation, verifies npm
666
- `gitHead`, and only then uses the maintainer's authenticated `git` and `gh` clients
667
- to create the annotated `vX.Y.Z` tag and GitHub Release. This avoids GitHub App
668
- token restrictions on tagging commits that contain workflow changes while preserving
669
- verification-before-tagging.
670
-
671
- ### Checking consistency manually
605
+ Local prerequisites:
672
606
 
673
- ```bash
674
- bun run release:check
675
- ```
676
-
677
- This verifies that `package.json` name, version, and `schemas/vvoc/v3.json` `$id` and
678
- config format version are all consistent. Run it independently anytime.
607
+ - `opencode` must be available from `PATH`.
608
+ - `gh` must be installed and authenticated with permission to dispatch/watch workflows and create releases in the repository. `gh run watch` does not support fine-grained PAT authentication; use a supported `gh` login such as OAuth or a classic token.
609
+ - The summary model defaults to `deepseek/deepseek-v4-flash`; override with `VVOC_RELEASE_SUMMARY_MODEL=provider/model` and the per-attempt timeout with `VVOC_RELEASE_SUMMARY_TIMEOUT_MS=120000`.
610
+ - Run `release:bump` from a checked-out branch with branch and tag push access to `origin`. A normal branch push never publishes by itself; the wrapper explicitly dispatches the workflow for the exact pushed commit.
679
611
 
680
- ### CI publish workflow
612
+ The GitHub Actions workflow checks out the requested commit SHA, verifies that its `package.json` version matches the dispatch input, and runs full validation (typecheck, lint, fmt check, tests, build, pack check, and `release:check`). Only after every gate passes does it publish to npm with provenance. The local wrapper waits for that CI result, retries registry metadata propagation, verifies npm `gitHead`, and only then uses the maintainer's authenticated `git` and `gh` clients to create the annotated `vX.Y.Z` tag and GitHub Release. This avoids GitHub App token restrictions on tagging commits that contain workflow changes while preserving verification-before-tagging.
681
613
 
682
614
  The workflow uses npm provenance/trusted publishing (`id-token: write`) and read-only repository contents access. It can only publish through an explicit `workflow_dispatch` request; normal branch and tag pushes do not publish. Tag and GitHub Release creation happen locally only after the workflow succeeds. Configure npm trusted publishing for this GitHub repository/package, or adapt the publish step to use an `NPM_TOKEN` secret if token-based publishing is required.
683
615
 
616
+ `bun run release:check` verifies independently that `package.json` name, version, and `schemas/vvoc/v3.json` `$id` and config format version are all consistent; run it anytime.
617
+
684
618
  ---
685
619
 
686
620
  ## License
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@osovv/vv-opencode",
3
- "version": "1.3.4",
4
- "description": "A curated, opinionated set of OpenCode plugins for spec-first, review-driven, safer agentic development.",
3
+ "version": "1.3.5",
4
+ "description": "An opinionated agentic development layer for OpenCode — spec-first when it matters, review-driven execution, portable model roles, safer tools, and long-run safety.",
5
5
  "type": "module",
6
6
  "main": "./dist/index.js",
7
7
  "types": "./dist/index.d.ts",
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
- "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.4/schemas/vvoc/v3.json",
3
+ "$id": "https://cdn.jsdelivr.net/npm/@osovv/vv-opencode@1.3.5/schemas/vvoc/v3.json",
4
4
  "title": "vvoc config",
5
5
  "description": "Canonical vvoc configuration document.",
6
6
  "type": "object",
@@ -45,27 +45,27 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
45
45
  <purpose>List all module names</purpose>
46
46
  </helper>
47
47
  <helper name="list-tasks">
48
- <command>grep '&lt;id&gt;T-' PLAN_PATH</command>
48
+ <command>grep '&lt;TASK-T-' PLAN_PATH</command>
49
49
  <purpose>List all task IDs in document order</purpose>
50
50
  </helper>
51
51
  <helper name="extract-task">
52
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH</command>
53
- <purpose>Extract one full task by ID (replace T-NNN with actual ID like T-001)</purpose>
52
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH</command>
53
+ <purpose>Extract one full task by ID (replace T-NNN in the TASK-T-NNN element name with the actual ID, e.g. TASK-T-001)</purpose>
54
54
  </helper>
55
55
  <helper name="extract-snippet">
56
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | sed -n '/&lt;snippet&gt;/,/&lt;\/snippet&gt;/p'</command>
56
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | sed -n '/&lt;snippet&gt;/,/&lt;\/snippet&gt;/p'</command>
57
57
  <purpose>Extract only the code snippet for a specific task</purpose>
58
58
  </helper>
59
59
  <helper name="extract-acceptance">
60
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | sed -n '/&lt;acceptance&gt;/,/&lt;\/acceptance&gt;/p'</command>
60
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | sed -n '/&lt;acceptance&gt;/,/&lt;\/acceptance&gt;/p'</command>
61
61
  <purpose>Extract all acceptance criteria for a specific task</purpose>
62
62
  </helper>
63
63
  <helper name="task-file">
64
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;file&gt;'</command>
64
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;file&gt;'</command>
65
65
  <purpose>Get the target file for a specific task</purpose>
66
66
  </helper>
67
67
  <helper name="task-status">
68
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;status&gt;'</command>
68
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;status&gt;'</command>
69
69
  <purpose>Get current status of a specific task</purpose>
70
70
  </helper>
71
71
  <helper name="dependency-graph">
@@ -73,11 +73,11 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
73
73
  <purpose>Show all task dependencies</purpose>
74
74
  </helper>
75
75
  <helper name="task-deps">
76
- <command>sed -n '/&lt;id&gt;T-NNN&lt;\/id&gt;/,/&lt;\/task&gt;/p' PLAN_PATH | grep '&lt;task_id&gt;'</command>
76
+ <command>sed -n '/&lt;TASK-T-NNN&gt;/,/&lt;\/TASK-T-NNN&gt;/p' PLAN_PATH | grep '&lt;task_id&gt;'</command>
77
77
  <purpose>List dependencies for a specific task</purpose>
78
78
  </helper>
79
79
  <helper name="count-tasks">
80
- <command>grep -c '&lt;id&gt;T-' PLAN_PATH</command>
80
+ <command>grep -c '&lt;TASK-T-' PLAN_PATH</command>
81
81
  <purpose>Count total tasks in the plan</purpose>
82
82
  </helper>
83
83
  <helper name="all-files">
@@ -103,8 +103,8 @@ Do not mutate files until the execution mode is explicit. In classic mode, deleg
103
103
  <check>Plan contains a non-empty &lt;spec&gt; path pointing to a readable active spec file at .vvoc/specs/&lt;id&gt;/spec.xml. Stop and report if the spec path is under archive/.</check>
104
104
  <check>The linked spec's top-level &lt;status&gt; is approved</check>
105
105
  <check>If the linked spec status is draft, applied, missing, or invalid, stop and report that vv-execute requires an approved active spec.</check>
106
- <check>Plan contains &lt;tasks&gt; section with at least one &lt;task&gt;</check>
107
- <check>Each task has non-empty &lt;id&gt;, &lt;title&gt;, and &lt;file&gt;</check>
106
+ <check>Plan contains &lt;tasks&gt; section with at least one &lt;TASK-T-NNN&gt; element grouped under &lt;WAVE-N&gt; elements</check>
107
+ <check>Each task element name matches the TASK-T-NNN pattern and the task has non-empty &lt;title&gt; and &lt;file&gt;. There is no child id element — identity lives in the element name.</check>
108
108
  <check>Each task has &lt;snippet&gt; (may be empty but must exist)</check>
109
109
  <check>Each task has &lt;acceptance&gt; with at least one &lt;criterion&gt;</check>
110
110
  <action>If any check fails, stop and report the issue with line numbers. Do not proceed with broken plan.</action>
@@ -36,8 +36,9 @@ You are the vv-plan skill. Your job is to take an approved spec and write an imp
36
36
  <rule>When first saving the plan, set the top-level status to &lt;status&gt;draft&lt;/status&gt;. Only change it to approved after the user explicitly reads/reviews and approves the final plan. Never set the top-level status to applied yourself; applied is reserved for vv-execute after successful execution.</rule>
37
37
  <rule>The plan contains two major sections: architecture (modules, contracts, dependencies) and tasks (implementation steps with code snippets).</rule>
38
38
  <rule>Architecture section uses child tags: module, name, purpose, file (path, role), contract, depends_on (module).</rule>
39
- <rule>Tasks use child tags: id (T-NNN pattern), title, file, status, description, depends_on (task_id), snippet (CDATA), acceptance (criterion), verification (command). Task-level &lt;status&gt; values are separate from the top-level plan lifecycle status and may remain pending until execution updates them.</rule>
40
- <rule>Every XML element is named for grep extraction. Use: `grep '&lt;id&gt;T-' plan.xml` to list tasks, `grep '&lt;criterion&gt;' plan.xml` for all criteria, `grep '&lt;task_id&gt;' plan.xml` for dependency graph.</rule>
39
+ <rule>Tasks are grouped into wave elements whose identity is the element name: &lt;WAVE-1&gt;, &lt;WAVE-2&gt;, … Each wave contains a &lt;goal&gt; and its tasks.</rule>
40
+ <rule>A task's identity is its element name in the TASK-T-NNN pattern: &lt;TASK-T-001&gt;…&lt;/TASK-T-001&gt;. The identity repeats on both boundaries so long blocks stay addressable. Tasks use child tags: title, file, status, description, depends_on (task_id), snippet (CDATA), acceptance (criterion), verification (command). Do NOT add a child id element — the element name is the single authoritative identity. Task-level &lt;status&gt; values are separate from the top-level plan lifecycle status and may remain pending until execution updates them.</rule>
41
+ <rule>Every XML element is named for grep extraction. Use: `grep '&lt;TASK-T-' plan.xml` to list tasks, `grep '&lt;criterion&gt;' plan.xml` for all criteria, `grep '&lt;task_id&gt;' plan.xml` for dependency graph.</rule>
41
42
  <rule>Populate the &lt;spec&gt; element with the path to the spec.xml this plan implements.</rule>
42
43
  <rule>If a design-context.xml was found and read as explanatory context, populate the &lt;design-context&gt; element with the path to design-context.xml so execution tools and reviewers can locate it.</rule>
43
44
  <location>Save plan.xml as a sibling of spec.xml in the same spec package directory: .vvoc/specs/&lt;id&gt;/plan.xml</location>
@@ -61,10 +62,9 @@ You are the vv-plan skill. Your job is to take an approved spec and write an imp
61
62
  </acceptance_criteria_format>
62
63
 
63
64
  <example>
64
- <rule>Here is a concrete example of one task in the new format. Every &lt;snippet&gt; uses CDATA, and every &lt;criterion&gt; is testable:</rule>
65
+ <rule>Here is a concrete example of one task. The task identity is the element name, repeated on both boundaries; every &lt;snippet&gt; uses CDATA, and every &lt;criterion&gt; is testable:</rule>
65
66
  <sample-fragment>
66
- &lt;task&gt;
67
- &lt;id&gt;T-001&lt;/id&gt;
67
+ &lt;TASK-T-001&gt;
68
68
  &lt;title&gt;LRU Cache Store&lt;/title&gt;
69
69
  &lt;file&gt;src/lib/cache-store.ts&lt;/file&gt;
70
70
  &lt;status&gt;pending&lt;/status&gt;
@@ -111,9 +111,9 @@ export type CacheStoreOptions = {
111
111
  &lt;verification&gt;
112
112
  &lt;command&gt;bun test src/lib/cache-store.test.ts&lt;/command&gt;
113
113
  &lt;/verification&gt;
114
- &lt;/task&gt;
114
+ &lt;/TASK-T-001&gt;
115
115
  </sample-fragment>
116
- <rule>Notice: the snippet uses CDATA wrapping (mandatory). Every element is a child tag (no attributes). The task has id, title, file, status, description, snippet, acceptance, and verification — all as child elements.</rule>
116
+ <rule>Notice: the task identity TASK-T-001 appears in the opening and closing element names. The snippet uses CDATA wrapping (mandatory). Every field is a child tag (no attributes): title, file, status, description, snippet, acceptance, and verification.</rule>
117
117
  </example>
118
118
 
119
119
  <file_structure>
@@ -142,6 +142,7 @@ export type CacheStoreOptions = {
142
142
  <forbidden>XML attributes in any tag — use child elements only</forbidden>
143
143
  <forbidden>Code outside CDATA — all snippets must be wrapped in CDATA sections</forbidden>
144
144
  <forbidden>Numbered criterion tags — use plain &lt;criterion&gt;, not numbered variants</forbidden>
145
+ <forbidden>Generic &lt;task&gt; or &lt;wave&gt; elements with child id/num elements — identity belongs in the element name: &lt;TASK-T-NNN&gt;, &lt;WAVE-N&gt;</forbidden>
145
146
  </no_placeholders>
146
147
 
147
148
  <self_review>
@@ -150,7 +151,7 @@ export type CacheStoreOptions = {
150
151
  <check>Acceptance criteria quality: Is every criterion testable? Could a reviewer or implementer write a failing test for it?</check>
151
152
  <check>Type consistency: Do types, signatures, and property names match across tasks? A function called `clearLayers()` in Task 3 but `clearFullLayers()` in Task 7 is a bug.</check>
152
153
  <rule>Fix issues inline as you find them. No second review pass needed — just fix and continue.</rule>
153
- <check>Format compliance: Are there zero XML attributes? Is every snippet in CDATA? Are tasks using id child tags instead of task-N numbering?</check>
154
+ <check>Format compliance: Are there zero XML attributes? Is every snippet in CDATA? Is every task a &lt;TASK-T-NNN&gt; element with identity in the element name and no child id element?</check>
154
155
  <check>Architecture presence: Does the plan have an architecture section with modules, contracts, and dependency graph?</check>
155
156
  </self_review>
156
157
 
@@ -28,11 +28,9 @@
28
28
  </architecture>
29
29
 
30
30
  <tasks>
31
- <wave>
32
- <num>1</num>
31
+ <WAVE-1>
33
32
  <goal></goal>
34
- <task>
35
- <id>T-001</id>
33
+ <TASK-T-001>
36
34
  <title></title>
37
35
  <file></file>
38
36
  <status>pending</status>
@@ -49,7 +47,7 @@
49
47
  <verification>
50
48
  <command></command>
51
49
  </verification>
52
- </task>
53
- </wave>
50
+ </TASK-T-001>
51
+ </WAVE-1>
54
52
  </tasks>
55
53
  </plan>