sortie-dogs 0.1.11 → 0.2.2

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/README.md CHANGED
@@ -1,283 +1,348 @@
1
- # Sortie-dogs
2
-
3
- **Give OpenCode a task; get a bounded, validated implementation loop instead of an open-ended agent run.**
4
-
5
- > **Project status: Experimental / unsupported.** No stability, compatibility,
6
- > or support guarantees are provided. Mk2A2 remains the canonical internal workflow.
7
-
8
- [![npm](https://img.shields.io/npm/v/sortie-dogs)](https://www.npmjs.com/package/sortie-dogs)
9
- [![license](https://img.shields.io/npm/l/sortie-dogs)](LICENSE)
10
- [![Node.js](https://img.shields.io/node/v/sortie-dogs)](https://www.npmjs.com/package/sortie-dogs)
11
-
12
- ![Sortie-dogs coordinating a bounded implementation workflow](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-workflow.gif)
13
-
14
- Sortie-dogs is an opt-in OpenCode orchestration plugin. It turns a task into a
15
- scoped plan, parallel investigation, dedicated implementation, canonical
16
- validation, and evidence-backed completion—while preserving standard OpenCode
17
- agents and settings.
18
-
19
- Requirements: Node.js 22.6 or newer, npm, and OpenCode.
20
-
21
- Guides: [日本語](docs/guide-ja.md) · [简体中文](docs/guide-zh-CN.md)
22
-
23
- ## Quick start
24
-
25
- Install the public npm package in the project and generate the project-local
26
- OpenCode runtime files:
27
-
28
- ```sh
29
- npm install --save-dev sortie-dogs
30
- npx sortie-dogs init .
31
- ```
32
-
33
- Alternatively, install the CLI globally and initialize OpenCode's global
34
- configuration:
35
-
36
- ```sh
37
- npm install --global sortie-dogs
38
- sortie-dogs init --global
39
- ```
40
-
41
- This installs the canonical runtime assets in OpenCode's global configuration,
42
- so `dog-coordinator` can be selected from other projects without project-local
43
- initialization. Global initialization and project-local initialization are
44
- separate: `sortie-dogs init .` still writes runtime files only into that
45
- project. Project-local configuration and the plugin bridge below remain
46
- available when a project needs its own settings or dependency.
47
-
48
- `dog-coordinator` and `dog-scout` default to `openai/gpt-5.6-luna`. To use a
49
- different model for both roles, save this as `.opencode/sortie-dogs.json`:
50
-
51
- ```json
52
- {
53
- "modelRouting": {
54
- "dog-coordinator": {
55
- "preferred": { "model": "provider/model" }
56
- },
57
- "dog-scout": {
58
- "preferred": { "model": "provider/model" }
59
- }
60
- },
61
- "modelCatalog": {
62
- "project": [{ "model": "provider/model" }]
63
- }
64
- }
65
- ```
66
-
67
- Replace `provider/model` with a model available to you. Then create
68
- `.opencode/plugins/sortie-dogs.ts` as the OpenCode plugin bridge:
69
-
70
- ```ts
71
- export { SortieDogsPlugin } from "sortie-dogs/plugin";
72
- ```
73
-
74
- OpenCode discovers the bridge automatically; no `plugin` entry in
75
- `opencode.json` is required. Restart OpenCode, then start a task:
76
-
77
- ```text
78
- /sortie <task>
79
- ```
80
-
81
- Selecting `dog-coordinator` directly also activates the workflow.
82
-
83
- ## The write gate
84
-
85
- The write gate is opt-in per project. Without `operation-manifest.json` in the
86
- project root, the plugin stays passive and never denies a tool call. Creating
87
- that file is how a project opts in, so the coordinator can always create it.
88
-
89
- ```json
90
- {
91
- "version": "0.1.0",
92
- "task_id": "add-requested-behavior",
93
- "read": ["src/feature.ts", "test/feature.test.ts"],
94
- "write": ["src/feature.ts", "test/feature.test.ts"],
95
- "validation": ["npm test"]
96
- }
97
- ```
98
-
99
- - `write` lists the only paths a bound worker may change. A listed directory
100
- covers the files under it; every other entry is an exact path.
101
- - `validation` lists the exact commands a bound worker may run. Build and test
102
- commands cannot be classified by path, so a command is allowed only when it
103
- matches a declared entry exactly. Anything else is denied as unclassified.
104
- - `read` documents the intended reading scope; reads are never blocked.
105
-
106
- `dog-coordinator` owns this file. A worker binds to it once per candidate with
107
- `sortie_bind_write_gate`, and only after the coordinator's handoff has been
108
- inspected. Coordinator sessions are never gated.
109
-
110
- Optional settings in `.opencode/sortie-dogs.json`:
111
-
112
- ```json
113
- {
114
- "operationManifestPath": "operation-manifest.json",
115
- "handoffPaths": ["handoff.json"],
116
- "readOnlyTools": ["my_mcp_search"],
117
- "dedicatedWorkerModel": { "model": "provider/model", "variant": "deep" }
118
- }
119
- ```
120
-
121
- - `operationManifestPath` moves the manifest; the path is project-relative.
122
- - `handoffPaths` lists the handoff files the plugin inspects. A worker can only
123
- bind after one of these files passes inspection, so an empty list disables
124
- binding entirely.
125
- - `readOnlyTools` adds host-specific tool names that never change files, such as
126
- MCP tools. Unknown tools are denied for a bound session by default.
127
- - `dedicatedWorkerModel` selects the single model every worker role resolves to.
128
- It defaults to `openai/gpt-5.6-sol` with variant `xhigh`; declare your own when
129
- that model is unavailable. Worker roles always resolve to this one target and
130
- cannot be routed per role.
131
-
132
- ## Why Sortie-dogs
133
-
134
- - **Focused when invited, invisible otherwise.** Activate it with `/sortie` or
135
- select `dog-coordinator`; ordinary OpenCode sessions remain unchanged.
136
- - **Parallel context without uncontrolled fan-out.** Every worker handoff uses
137
- exactly three bounded scouts before implementation begins.
138
- - **Writes stay inside the assignment.** Exact source or operation manifests
139
- gate edits and handoffs.
140
- - **One accountable implementation path.** A dedicated Sol worker handles
141
- implementation, remediation, and blocker resolution.
142
- - **Evidence before completion.** Canonical validation, risk-based review, and
143
- terminal evidence gate coordinator-owned completion and commits.
144
- - **Long work can recover.** Restart recovery and bounded compaction continue
145
- from retained handoff context rather than silently starting over.
146
-
147
- ## Example run
148
-
149
- An illustrative low-risk run stays bounded and reports its gates:
150
-
151
- ```text
152
- You: /sortie Add the requested behavior
153
- dog-coordinator: manifest confirmed
154
- dog-scout ×3: investigation complete
155
- dog-worker: implementation complete
156
- validation: npm test PASS
157
- review: skipped low risk
158
- dog-coordinator: completion evidence accepted
159
- ```
160
-
161
- ## The workflow
162
-
163
- 1. **Brief and plan** — `dog-coordinator` turns the request into acceptance
164
- criteria, a write manifest, and validation requirements.
165
- 2. **Exactly three scouts** bounded, read-only investigation collects
166
- complementary evidence without expanding the write scope.
167
- 3. **Dedicated worker** the Sol worker implements only the approved manifest
168
- and also owns scoped remediation or blocker resolution.
169
- 4. **Canonical validation** the declared test or build command must produce
170
- acceptable evidence.
171
- 5. **Risk-based review** high-risk candidates receive independent review;
172
- low-risk candidates can skip that extra pass after validation.
173
- 6. **Coordinator completion** — only the coordinator closes the loop and owns
174
- any commit after manifest, validation, review, and evidence gates pass.
175
- 7. **Bounded continuation** — restart recovery and compaction handoffs preserve
176
- progress; repeated batches remain bounded rather than becoming endless
177
- delegation.
178
-
179
- ## A visual walkthrough
180
-
181
- ### Control complexity
182
-
183
- ![Bounded roles and gates containing orchestration complexity](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-complexity.png)
184
-
185
- The coordinator keeps investigation, implementation, validation, and review in
186
- separate roles. Manifest gates keep their writes bounded even as the project
187
- gets more complex.
188
-
189
- ### Finish with evidence
190
-
191
- ![Validated work reaching coordinator-owned completion](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-complete.png)
192
-
193
- Validation and risk-based review happen before coordinator-owned completion, so
194
- the result returns with a concise record of what changed and how it was checked.
195
-
196
- ## Scope and session guarantees
197
-
198
- The plugin is passive by default. It activates a session only when a message
199
- uses `/sortie` or the selected agent is `dog-coordinator`. It validates exact
200
- write scope through source or operation manifests and rejects invalid worker
201
- handoffs. Standard OpenCode agents, roles, settings, and unrelated sessions are
202
- preserved.
203
-
204
- On `session.idle`, the final handoff is checked and the session is released. A
205
- `session.deleted` event also releases it. A later request must activate the
206
- workflow again.
207
-
208
- ## Model routing
209
-
210
- `dog-coordinator` and `dog-scout` default to `openai/gpt-5.6-luna` with the
211
- `xhigh` variant. This is the recommended balance: bounded prompts, concise
212
- scout evidence, and fewer unnecessary context or tool turns can reduce token
213
- use while preserving quality. Project-local routing can override either
214
- default.
215
-
216
- The `implementation`, `remediation`, `blocker-resolution`, and `dog-advisor`
217
- roles always use dedicated Sol `xhigh`; user configuration cannot replace those
218
- routes. For other explicitly routed roles, resolution is deterministic: Sortie-dogs tries
219
- the preferred target, then ordered fallbacks. Roles without either a built-in
220
- default or an explicit route keep OpenCode's already selected model.
221
-
222
- ```json
223
- {
224
- "modelRouting": {
225
- "dog-coordinator": {
226
- "preferred": { "model": "openai/gpt-5.6-luna", "variant": "xhigh" }
227
- },
228
- "dog-scout": {
229
- "preferred": { "model": "openai/gpt-5.6-luna", "variant": "xhigh" }
230
- },
231
- "dog-advisor": {
232
- "preferred": { "model": "openai/gpt-5.6-sol", "variant": "xhigh" }
233
- },
234
- "dog-reviewer": {
235
- "preferred": { "model": "fable/opus", "variant": "thinking" },
236
- "fallback": [{ "model": "provider/general" }]
237
- }
238
- },
239
- "modelCatalog": {
240
- "project": [
241
- { "model": "openai/gpt-5.6-sol", "variants": ["xhigh"] },
242
- { "model": "openai/gpt-5.6-luna", "variants": ["xhigh"] },
243
- { "model": "fable/opus", "variants": ["thinking"] },
244
- { "model": "provider/general" }
245
- ]
246
- }
247
- }
248
- ```
249
-
250
- Save project configuration as `.opencode/sortie-dogs.json`. The `dog-advisor`
251
- entry above shows the built-in effective route and is not user-overridable.
252
- `modelCatalog`
253
- declares provider models and named variants that are actually available;
254
- Sortie-dogs does not invent, probe, or translate variants. Resolution tries the
255
- preferred target and then its fallbacks, rejecting an explicitly routed role
256
- when no candidate appears in the catalog. The advisor route is authoritative; the
257
- reviewer route remains an optional secondary example.
258
-
259
- `dog-advisor` accepts bounded Strategy or SourceReview consultation from the
260
- coordinator. `dog-reviewer` independently checks high-risk candidates after
261
- canonical validation. Neither role implements, stages, commits, or acts as a
262
- user-facing worker.
263
-
264
- ## Updates and migration
265
-
266
- After replacing the dependency with a newer release asset, run:
267
-
268
- ```sh
269
- npx sortie-dogs init .
270
- ```
271
-
272
- `init` is idempotent. It updates files owned by Sortie-dogs, migrates recognized
273
- older runtime files, and records the installed version in
274
- `.opencode/sortie-dogs.version`. Conflicting or unrecognized files remain
275
- untouched and initialization stops safely. User-owned configuration—including
276
- `.opencode/sortie-dogs.json`—and standard OpenCode files are preserved.
277
-
278
- ## Safe manual removal
279
-
280
- There is no supported Sortie-dogs uninstall command. Remove the npm dependency
281
- separately, then follow the [safe manual removal guide](docs/uninstall.md) to
282
- delete only Sortie-dogs-owned runtime files without affecting user files or
283
- standard OpenCode agents.
1
+ # Sortie-dogs
2
+
3
+ **Give OpenCode a task; get a bounded, validated implementation loop instead of an open-ended agent run.**
4
+
5
+ > **Project status: Experimental / unsupported.** No stability, compatibility,
6
+ > or support guarantees are provided. Mk2A2 remains the canonical internal workflow.
7
+
8
+ [![npm](https://img.shields.io/npm/v/sortie-dogs)](https://www.npmjs.com/package/sortie-dogs)
9
+ [![license](https://img.shields.io/npm/l/sortie-dogs)](LICENSE)
10
+ [![Node.js](https://img.shields.io/node/v/sortie-dogs)](https://www.npmjs.com/package/sortie-dogs)
11
+
12
+ ![Sortie-dogs coordinating a bounded implementation workflow](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-workflow.gif)
13
+
14
+ Sortie-dogs is an opt-in OpenCode orchestration plugin. It turns a task into a
15
+ scoped plan, parallel investigation, dedicated implementation, canonical
16
+ validation, and evidence-backed completion—while preserving standard OpenCode
17
+ agents and settings.
18
+
19
+ Requirements: Node.js 22.6 or newer, npm, and OpenCode.
20
+
21
+ Guides: [日本語](docs/guide-ja.md) · [简体中文](docs/guide-zh-CN.md)
22
+
23
+ ## Quick start
24
+
25
+ Install the public npm package in the project and generate the project-local
26
+ OpenCode runtime files:
27
+
28
+ ```sh
29
+ npm install --save-dev sortie-dogs
30
+ npx sortie-dogs init .
31
+ ```
32
+
33
+ Alternatively, install the CLI globally and initialize OpenCode's global
34
+ configuration:
35
+
36
+ ```sh
37
+ npm install --global sortie-dogs
38
+ sortie-dogs init --global
39
+ ```
40
+
41
+ This installs the canonical runtime assets in OpenCode's global configuration,
42
+ so `dog-coordinator` can be selected from other projects without project-local
43
+ initialization. Global initialization and project-local initialization are
44
+ separate: `sortie-dogs init .` still writes runtime files only into that
45
+ project. Project-local configuration and the plugin bridge below remain
46
+ available when a project needs its own settings or dependency.
47
+
48
+ Installing the runtime assets does not load the plugin, and without the plugin
49
+ every role runs on whichever model the caller happened to use. Add the package
50
+ to the `plugin` array of the OpenCode configuration the agents run under —
51
+ `~/.config/opencode/opencode.json` for the global assets, or the project's
52
+ `.opencode/opencode.json`:
53
+
54
+ ```json
55
+ {
56
+ "plugin": ["sortie-dogs"]
57
+ }
58
+ ```
59
+
60
+ Restart OpenCode afterwards. A `plugin` entry must name the package, not a
61
+ subpath: `sortie-dogs/plugin` is an import specifier, not a plugin specifier.
62
+
63
+ `dog-coordinator` and `dog-scout` default to `openai/gpt-5.6-luna`. To use a
64
+ different model for both roles, save this as `.opencode/sortie-dogs.json`:
65
+
66
+ ```json
67
+ {
68
+ "modelRouting": {
69
+ "dog-coordinator": {
70
+ "preferred": { "model": "provider/model" }
71
+ },
72
+ "dog-scout": {
73
+ "preferred": { "model": "provider/model" }
74
+ }
75
+ },
76
+ "modelCatalog": {
77
+ "project": [{ "model": "provider/model" }]
78
+ }
79
+ }
80
+ ```
81
+
82
+ Replace `provider/model` with a model available to you.
83
+
84
+ A project that depends on the package can load it from
85
+ `.opencode/plugins/sortie-dogs.ts` instead of the `plugin` array:
86
+
87
+ ```ts
88
+ export { SortieDogsPlugin } from "sortie-dogs/plugin";
89
+ ```
90
+
91
+ OpenCode discovers that file automatically. Export the plugin and nothing else:
92
+ OpenCode calls every runtime export of a plugin module as a plugin factory, so
93
+ one extra export disables the whole module. Restart OpenCode, then start a task:
94
+
95
+ ```text
96
+ /sortie <task>
97
+ ```
98
+
99
+ Selecting `dog-coordinator` directly also activates the workflow.
100
+
101
+ ## The write gate
102
+
103
+ The write gate is opt-in per project. Without `operation-manifest.json` in the
104
+ project root, the plugin stays passive and never denies a tool call. Creating
105
+ that file is how a project opts in, so the coordinator can always create it.
106
+
107
+ ```json
108
+ {
109
+ "version": "0.1.0",
110
+ "task_id": "add-requested-behavior",
111
+ "read": ["src/feature.ts", "test/feature.test.ts"],
112
+ "write": ["src/feature.ts", "test/feature.test.ts"],
113
+ "validation": ["npm test"]
114
+ }
115
+ ```
116
+
117
+ - `write` lists the only paths a bound worker may change. A listed directory
118
+ covers the files under it; every other entry is an exact path.
119
+ - `validation` lists the exact commands a bound worker may run. Build and test
120
+ commands cannot be classified by path, so a command is allowed only when it
121
+ matches a declared entry exactly. Anything else is denied as unclassified.
122
+ - `read` documents the intended reading scope; reads are never blocked.
123
+
124
+ `dog-coordinator` owns this file. A worker binds to it once per candidate with
125
+ `sortie_bind_write_gate`, and only after the coordinator's handoff has been
126
+ inspected. Coordinator sessions are never gated.
127
+
128
+ Both documents are schema-checked before inspection and binding, and every object
129
+ rejects unknown properties. A rejection always names the failing document, the
130
+ exact JSON pointer, and the failing rule, for example
131
+ `Defects: handoff /state/blocked/0 schema_type`, so the coordinator repairs that
132
+ pointer instead of resending an unchanged document. Check a handoff before
133
+ dispatch with the read-only `sortie_check_contract` tool, which reports the same
134
+ defects without inspecting or binding, or with `sortie-dogs lint <handoff.json>
135
+ --manifest <operation-manifest.json>`. The two most common defects are a
136
+ `state.blocked` list of strings instead of `{ reason, needed }` objects, and an
137
+ operation manifest that declares anything other than `version`, `task_id`,
138
+ `read`, `write`, and `validation`.
139
+
140
+ Optional settings in `.opencode/sortie-dogs.json`:
141
+
142
+ ```json
143
+ {
144
+ "operationManifestPath": "operation-manifest.json",
145
+ "handoffPaths": ["handoff.json"],
146
+ "readOnlyTools": ["my_mcp_search"],
147
+ "dedicatedWorkerModel": { "model": "provider/model", "variant": "deep" },
148
+ "continuation": { "enabled": true, "maxAutoContinues": 3 }
149
+ }
150
+ ```
151
+
152
+ - `operationManifestPath` moves the manifest; the path is project-relative.
153
+ - `handoffPaths` lists the handoff files the plugin inspects. A worker can only
154
+ bind after one of these files passes inspection, so an empty list disables
155
+ binding entirely. Relative entries are also candidate-relative in a nested
156
+ repository: a child candidate may use its own `handoff.json` while OpenCode is
157
+ opened at the parent workspace. For operational work the coordinator creates
158
+ that valid handoff before dispatch and sends its exact absolute path; the
159
+ binding child must use the built-in Read tool on it immediately before bind.
160
+ - `readOnlyTools` adds host-specific tool names that never change files, such as
161
+ MCP tools. Unknown tools are denied for a bound session by default.
162
+ - `dedicatedWorkerModel` selects the single model every worker role resolves to.
163
+ It defaults to `openai/gpt-5.6-sol` with variant `medium`; declare your own when
164
+ that model is unavailable or when you want a different worker effort. Worker
165
+ roles always resolve to this one target and cannot be routed per role.
166
+ - `continuation` bounds the batch loop. After a terminal unit and its checkpoint,
167
+ `dog-coordinator` calls `sortie_compact_and_continue`, which compacts the run
168
+ and resumes the same root session on the next independent unit. Only a root
169
+ `dog-coordinator` session is ever resumed: a child session is never promoted and
170
+ another coordinator is never adopted. Set `enabled` to `false` to keep every
171
+ batch manual, raise or lower `maxAutoContinues` (default `3`, maximum `10`) to
172
+ change the ceiling, and set `summarizeModel` to pin the compaction model when
173
+ the host default is unsuitable.
174
+
175
+ ## Why Sortie-dogs
176
+
177
+ - **Focused when invited, invisible otherwise.** Activate it with `/sortie` or
178
+ select `dog-coordinator`; ordinary OpenCode sessions remain unchanged.
179
+ - **Parallel context without uncontrolled fan-out.** Every worker handoff uses
180
+ exactly three bounded scouts before implementation begins.
181
+ - **Writes stay inside the assignment.** Exact source or operation manifests
182
+ gate edits and handoffs.
183
+ - **One accountable implementation path.** A dedicated Sol worker handles
184
+ implementation, remediation, and blocker resolution.
185
+ - **Evidence before completion.** Canonical validation, risk-based review, and
186
+ terminal evidence gate coordinator-owned completion and commits.
187
+ - **Long work can recover.** Restart recovery and bounded compaction continue
188
+ from retained handoff context rather than silently starting over.
189
+
190
+ ## Example run
191
+
192
+ An illustrative low-risk run stays bounded and reports its gates:
193
+
194
+ ```text
195
+ You: /sortie Add the requested behavior
196
+ dog-coordinator: manifest confirmed
197
+ dog-scout ×3: investigation complete
198
+ dog-worker: implementation complete
199
+ validation: npm test PASS
200
+ review: skipped low risk
201
+ dog-coordinator: completion evidence accepted
202
+ ```
203
+
204
+ ## The workflow
205
+
206
+ 1. **Brief and plan** — `dog-coordinator` turns the request into acceptance
207
+ criteria, a write manifest, and validation requirements.
208
+ 2. **Exactly three scouts** — bounded, read-only investigation collects
209
+ complementary evidence without expanding the write scope.
210
+ 3. **Dedicated worker** the Sol worker implements only the approved manifest
211
+ and also owns scoped remediation or blocker resolution.
212
+ 4. **Canonical validation** the declared test or build command must produce
213
+ acceptable evidence.
214
+ 5. **Risk-based review** — high-risk candidates receive independent review;
215
+ low-risk candidates can skip that extra pass after validation.
216
+ 6. **Coordinator completion** only the coordinator closes the loop and owns
217
+ any commit after manifest, validation, review, and evidence gates pass.
218
+ 7. **Bounded continuation** restart recovery and compaction handoffs preserve
219
+ progress; repeated batches remain bounded rather than becoming endless
220
+ delegation.
221
+
222
+ ## A visual walkthrough
223
+
224
+ ### Control complexity
225
+
226
+ ![Bounded roles and gates containing orchestration complexity](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-complexity.png)
227
+
228
+ The coordinator keeps investigation, implementation, validation, and review in
229
+ separate roles. Manifest gates keep their writes bounded even as the project
230
+ gets more complex.
231
+
232
+ ### Finish with evidence
233
+
234
+ ![Validated work reaching coordinator-owned completion](https://raw.githubusercontent.com/zufall-upon/Sortie-dogs/main/docs/assets/sortie-complete.png)
235
+
236
+ Validation and risk-based review happen before coordinator-owned completion, so
237
+ the result returns with a concise record of what changed and how it was checked.
238
+
239
+ ## Scope and session guarantees
240
+
241
+ The plugin is passive by default. It activates a session only when a message
242
+ uses `/sortie` or the selected agent is `dog-coordinator`. It validates exact
243
+ write scope through source or operation manifests and rejects invalid worker
244
+ handoffs. Standard OpenCode agents, roles, settings, and unrelated sessions are
245
+ preserved.
246
+
247
+ On `session.idle`, the final handoff is checked and the session is released. A
248
+ `session.deleted` event also releases it. A later request must activate the
249
+ workflow again.
250
+
251
+ One host defect is repaired in place. A subagent result is built from the last
252
+ text part of the child's final message, so a reasoning model that closes its
253
+ turn with an empty text part returns an empty result and the coordinator
254
+ re-dispatches work the worker already finished. When a completed `task` result
255
+ is empty, Sortie-dogs restores the last real assistant text from that child
256
+ session. Non-empty results, other tools, and unreadable child sessions are left
257
+ untouched.
258
+
259
+ ## Model routing
260
+
261
+ `dog-coordinator` and `dog-scout` default to `openai/gpt-5.6-luna` with the
262
+ `xhigh` variant. This is the recommended balance: bounded prompts, concise
263
+ scout evidence, and fewer unnecessary context or tool turns can reduce token
264
+ use while preserving quality. Project-local routing can override either
265
+ default.
266
+
267
+ The `implementation`, `remediation`, `blocker-resolution`, and `dog-worker`
268
+ roles always use the dedicated worker target, `openai/gpt-5.6-sol` with the
269
+ `medium` variant. Worker effort is deliberately below review effort: source
270
+ review is mandatory for risky candidates and returns findings the worker must
271
+ remediate, so the loop already re-runs weak implementation work and top-of-range
272
+ first-attempt effort mostly buys accuracy the reviewer supplies anyway. Raise
273
+ `dedicatedWorkerModel` when you would rather pay for it up front. `modelRouting`
274
+ cannot replace those routes, and only `dedicatedWorkerModel` moves them. For other explicitly
275
+ routed roles, resolution is deterministic: Sortie-dogs tries the preferred
276
+ target, then ordered fallbacks. Roles without either a built-in default or an
277
+ explicit route keep OpenCode's already selected model.
278
+
279
+ `dog-reviewer` and `dog-advisor` must never inherit the caller's model, because
280
+ review and strategy lose their value when they run on the model that produced
281
+ the candidate. Both default to `anthropic/claude-opus-5` when the catalog
282
+ declares it, and otherwise fall back to `openai/gpt-5.6-sol` with the `xhigh`
283
+ variant, one effort step above the worker target. A host that redeclares
284
+ `dedicatedWorkerModel` keeps that target as its first fallback, since such a
285
+ host may not serve the shipped model at all. Nothing here requires a particular
286
+ vendor: both roles stay fully configurable, so declare whichever model you can
287
+ actually serve.
288
+
289
+ ```json
290
+ {
291
+ "modelRouting": {
292
+ "dog-coordinator": {
293
+ "preferred": { "model": "openai/gpt-5.6-luna", "variant": "xhigh" }
294
+ },
295
+ "dog-scout": {
296
+ "preferred": { "model": "openai/gpt-5.6-luna", "variant": "xhigh" }
297
+ },
298
+ "dog-reviewer": {
299
+ "preferred": { "model": "anthropic/claude-opus-5" },
300
+ "fallback": [{ "model": "openai/gpt-5.6-sol", "variant": "xhigh" }]
301
+ },
302
+ "dog-advisor": {
303
+ "preferred": { "model": "openai/gpt-5.6-sol", "variant": "xhigh" }
304
+ }
305
+ },
306
+ "modelCatalog": {
307
+ "project": [
308
+ { "model": "openai/gpt-5.6-sol", "variants": ["medium", "xhigh"] },
309
+ { "model": "openai/gpt-5.6-luna", "variants": ["xhigh"] },
310
+ { "model": "anthropic/claude-opus-5" }
311
+ ]
312
+ }
313
+ }
314
+ ```
315
+
316
+ Save project configuration as `.opencode/sortie-dogs.json`. `modelCatalog`
317
+ declares provider models and named variants that are actually available;
318
+ Sortie-dogs does not invent, probe, or translate variants. The built-in catalog
319
+ intentionally omits `anthropic/claude-opus-5`, so the preferred consultation
320
+ model applies only after you declare it. Resolution tries the preferred target
321
+ and then its fallbacks, rejecting an explicitly routed role when no candidate
322
+ appears in the catalog.
323
+
324
+ `dog-advisor` accepts bounded Strategy or SourceReview consultation from the
325
+ coordinator. `dog-reviewer` independently checks high-risk candidates after
326
+ canonical validation. Neither role implements, stages, commits, or acts as a
327
+ user-facing worker.
328
+
329
+ ## Updates and migration
330
+
331
+ After replacing the dependency with a newer release asset, run:
332
+
333
+ ```sh
334
+ npx sortie-dogs init .
335
+ ```
336
+
337
+ `init` is idempotent. It updates files owned by Sortie-dogs, migrates recognized
338
+ older runtime files, and records the installed version in
339
+ `.opencode/sortie-dogs.version`. Conflicting or unrecognized files remain
340
+ untouched and initialization stops safely. User-owned configuration—including
341
+ `.opencode/sortie-dogs.json`—and standard OpenCode files are preserved.
342
+
343
+ ## Safe manual removal
344
+
345
+ There is no supported Sortie-dogs uninstall command. Remove the npm dependency
346
+ separately, then follow the [safe manual removal guide](docs/uninstall.md) to
347
+ delete only Sortie-dogs-owned runtime files without affecting user files or
348
+ standard OpenCode agents.