@kontextmind/kxm 0.7.184 → 0.7.186

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/.claude-plugin/marketplace.json +1 -1
  2. package/.kxm/README.md +1 -1
  3. package/.kxm/roles/reviewer-cli.yaml +5 -2
  4. package/.kxm/roles/writer.yaml +1 -1
  5. package/CHANGELOG.md +18 -0
  6. package/docs/contributing/assignment-runner.md +3 -3
  7. package/docs/contributing/ci-and-release.md +1 -1
  8. package/docs/contributing/harness-routing-internals.md +21 -19
  9. package/docs/glossary.md +1 -1
  10. package/docs/guides/governed-skills.md +1 -1
  11. package/docs/guides/pi-workers.md +2 -2
  12. package/docs/guides/provenance-gates.md +1 -1
  13. package/docs/operations/troubleshooting.md +1 -1
  14. package/docs/reference/cli-reference.md +14 -12
  15. package/docs/reference/config-reference.md +21 -13
  16. package/docs/reference/configuration.md +2 -2
  17. package/docs/reference/harness-routing.md +24 -20
  18. package/docs/templates/review.md +1 -1
  19. package/package.json +1 -1
  20. package/packages/core/tui/dist/index.js +1 -1
  21. package/packages/core/tui/src/tui/optimizer.ts +1 -1
  22. package/plugins/kxm/.claude-plugin/plugin.json +1 -1
  23. package/plugins/kxm/dist/cli.js +17 -12
  24. package/plugins/kxm/dist/mcp-server.js +1 -1
  25. package/plugins/kxm/dist/runtime-supervisor.js +7 -2
  26. package/plugins/kxm/dist/runtime.js +8 -3
  27. package/plugins/kxm/dist/server.js +1 -1
  28. package/plugins/kxm/package.json +1 -1
  29. package/plugins/kxm/src/cli/system.ts +1 -1
  30. package/plugins/kxm/src/init-guide-setup.ts +9 -9
  31. package/plugins/kxm/src/mcp-server.ts +1 -1
  32. package/plugins/kxm/src/oneshot-producer.ts +2 -2
  33. package/plugins/kxm/src/pi-producer.ts +1 -1
  34. package/plugins/kxm/src/subagent-control.ts +1 -1
  35. package/plugins/kxm/src/workforce-names.mjs +13 -4
  36. package/scripts/assignment-run.mjs +1 -1
  37. package/scripts/harness-run.d.mts +1 -1
  38. package/scripts/harness-run.mjs +3 -3
@@ -11,7 +11,7 @@
11
11
  "name": "kxm",
12
12
  "source": "./plugins/kxm",
13
13
  "description": "Durable workflows, peer agents, and kxm tui",
14
- "version": "0.7.184",
14
+ "version": "0.7.186",
15
15
  "category": "development",
16
16
  "tags": ["kxm", "multi-agent", "workflows", "mcp"]
17
17
  }
package/.kxm/README.md CHANGED
@@ -37,7 +37,7 @@ Ids in this checkout follow one convention per kind:
37
37
  |---|---|---|
38
38
  | Role | The purpose: `planner`, `writer`, `reviewer-arch`, `reviewer-cli` | Unchanged |
39
39
  | Agent | The same id as its `role` | `planner`, `writer`, `reviewer-arch`, `reviewer-cli` |
40
- | Route | `<harness>-<model-slug>[-<provider>]`, with `.` written as `-` | `grok-grok-4-7`, `claude-fable`, `pi-qwen3-coder-plus-openrouter` |
40
+ | Route | `<harness>-<model-slug>[-<provider>]`, with `.` written as `-` | `grok-grok-4-7`, `claude-fable`, `pi-qwen3-7-plus-openrouter` |
41
41
  | Workflow | `default`, `land`, or `<role>-only` | `default`, `land`, `writer-only`, `reviewer-arch-only`, `reviewer-cli-only` |
42
42
  | Agent step | The agent's role id | `writer`, `reviewer-arch`, `reviewer-cli` |
43
43
 
@@ -3,9 +3,12 @@ id: reviewer-cli
3
3
  purpose: reviewer-cli
4
4
  permission: read-only
5
5
  description: Independent CLI and docs critic.
6
- # codex-gpt-5-6-sol is the required cli critic. The Pi fallback is a different vendor.
6
+ # codex-gpt-6-1-sol is the required cli critic. The Pi fallback is a different vendor.
7
+ # codex-gpt-5-6-sol stays admitted as the last fallback.
7
8
  roster:
8
- - route: codex-gpt-5-6-sol
9
+ - route: codex-gpt-6-1-sol
9
10
  effort: low
10
11
  - route: pi-qwen3-8-flash-openrouter
11
12
  effort: low
13
+ - route: codex-gpt-5-6-sol
14
+ effort: low
@@ -10,7 +10,7 @@ description: Primary implementation agent.
10
10
  roster:
11
11
  - route: grok-grok-4-7
12
12
  effort: medium
13
- - route: pi-qwen3-coder-plus-openrouter
13
+ - route: pi-qwen3-7-plus-openrouter
14
14
  effort: medium
15
15
  - route: agy-gemini-4-argon-high
16
16
  effort: medium
package/CHANGELOG.md CHANGED
@@ -216,6 +216,24 @@ All notable user-facing changes are documented here. The project follows [Semant
216
216
 
217
217
  ### Changed
218
218
 
219
+ - **Writer #2 is OpenRouter Qwen3.7 Plus.** `pi-qwen3-7-plus-openrouter`
220
+ (`openrouter/qwen/qwen3.7-plus`) replaces `pi-qwen3-coder-plus-openrouter`.
221
+ OpenRouter no longer lists `qwen/qwen3-coder-plus`. The live catalog on
222
+ 2026-10-17 prices Qwen3.7 Plus at $0.32 input and $1.28 output per 1M
223
+ tokens, with a 1,000,000-token context and tool support. The old model
224
+ file stays `status: retired`, off every roster, and `qwen-openrouter-pi`
225
+ no longer resolves. `.kxm/prices.yaml` keeps the last Coder Plus row and
226
+ adds the Qwen3.7 Plus base tier. The dev helper's only Pi writer is
227
+ `openrouter/qwen/qwen3.7-plus`.
228
+ - **The CLI critic is Codex GPT-6.1 Sol.** `codex-gpt-6-1-sol` is the
229
+ `reviewer-cli` primary (`codex` / `gpt-6.1-sol`, effort `low`).
230
+ `pi-qwen3-8-flash-openrouter` stays the other-vendor fallback, and
231
+ `codex-gpt-5-6-sol` stays admitted as the last fallback. Architecture
232
+ review stays `claude-fable`, then `pi-glm-5-3-flash-openrouter`. Pro is
233
+ the same model with reasoning mode `pro`, not a separate route. List
234
+ price is $2 / $10 per 1M tokens through 272,000 prompt tokens ($0.10
235
+ cached input, $2.50 cache write), then $4 / $15.
236
+
219
237
  - **The writer rotation's agy routes are Gemini 4 Argon.** `agy-gemini-4-argon-high`
220
238
  (alias `gemini-agy`) and `agy-gemini-4-argon-medium` are writer #3 and #4.
221
239
  `agy-gemini-3-8-flash-medium` stays #5 because Argon needs a paid Google AI
@@ -34,10 +34,10 @@ admits each route for specific roles and permissions:
34
34
 
35
35
  | Role | Admitted route (harness / model) | Vendor | Permission |
36
36
  |---|---|---|---|
37
- | `writer` | `grok` / `grok-4.7`; relief: `pi` / `openrouter/qwen/qwen3-coder-plus`; `agy` / `gemini-4-argon-high`, then `gemini-4-argon-medium`, then `gemini-3.8-flash-medium`, then `gemini-3.8-flash-high` | `xai`; `alibaba`; `google` | `edit` |
37
+ | `writer` | `grok` / `grok-4.7`; relief: `pi` / `openrouter/qwen/qwen3.7-plus`; `agy` / `gemini-4-argon-high`, then `gemini-4-argon-medium`, then `gemini-3.8-flash-medium`, then `gemini-3.8-flash-high` | `xai`; `alibaba`; `google` | `edit` |
38
38
  | `planner` | `claude` / `fable` | `anthropic` | `read-only` |
39
39
  | `reviewer-arch` | `claude` / `fable` | `anthropic` | `read-only` |
40
- | `reviewer-cli` | `codex` / `gpt-5.6-sol` | `openai` | `read-only` |
40
+ | `reviewer-cli` | `codex` / `gpt-6.1-sol`; fallback `pi` / `openrouter/qwen/qwen3.8-flash`, then `codex` / `gpt-5.6-sol` | `openai`; `alibaba`; `openai` | `read-only` |
41
41
 
42
42
  The policy itself enforces three rules. Critics are read-only. The two
43
43
  designated critics have different vendors. No admitted writer shares a vendor
@@ -347,7 +347,7 @@ and exits with status 2. It refuses when:
347
347
  segment must not be a braked native vendor (`x-ai`, `moonshotai` and
348
348
  `google-ai` count as `xai`, `moonshot` and `google`);
349
349
  - a Pi `edit` request comes from a role other than `experiment` or `writer`, or
350
- a Pi writer asks for anything but `openrouter/qwen/qwen3-coder-plus` with
350
+ a Pi writer asks for anything but `openrouter/qwen/qwen3.7-plus` with
351
351
  `edit`;
352
352
  - the request asks for hooks or skills, sets `max_cost_usd` for a harness other
353
353
  than Claude, or sets `max_turns` for a harness other than Grok;
@@ -269,7 +269,7 @@ The real Pi smoke calls paid models, so it never runs by default. Its workflow,
269
269
  `KXM_SMOKE_RUNNER` names a runner with Pi credentials. Both smoke models run as
270
270
  long-lived Pi workers, so each must pass the Pi native-vendor brake: pick two
271
271
  non-native routes such as
272
- `openrouter/qwen/qwen3-coder-plus,openrouter/z-ai/glm-5.3-flash`, never `xai/…`
272
+ `openrouter/qwen/qwen3.7-plus,openrouter/z-ai/glm-5.3-flash`, never `xai/…`
273
273
  or `anthropic/…`. The container smoke needs
274
274
  Docker, a `pass-cli` session and a local Pi model store. It keeps secrets in a
275
275
  mode-600 file inside a temporary directory; set `KXM_SMOKE_VAULT` to read keys
@@ -9,7 +9,7 @@ This page records how the KXM repository applies [harness routing](../reference/
9
9
 
10
10
  The files use one id shape per kind. A route id is `<harness>-<model-slug>[-<provider>]`, with `.` written as `-`. An agent id equals its role. A workflow id is `default`, `land`, or `<role>-only`. An agent step id equals that role.
11
11
 
12
- This checkout's routes are `grok-grok-4-7`, `pi-qwen3-coder-plus-openrouter`, `agy-gemini-4-argon-high`, `agy-gemini-4-argon-medium`, `agy-gemini-3-8-flash-medium`, `agy-gemini-3-8-flash-high`, `claude-fable`, `codex-gpt-5-6-sol`, `pi-qwen3-8-flash-openrouter`, and `pi-glm-5-3-flash-openrouter`. Agents are `planner`, `writer`, `reviewer-arch`, and `reviewer-cli`. `opus-claude` was removed because `opus` is not an admitted selector. `qwen-token-plan/*` and `zai-coding-cn/*` left the admitted list because those harnesses are not allowlisted; their `prices.yaml` rows stay. Old ids resolve as aliases. Every roster entry names an effort. `reviewer-arch` dispatches `claude-fable`. #343's architecture critic ran on opus because the justfile recipe review-arch hardcoded that model; the role file on that commit listed only `fable-claude`. The helper now refuses `opus`.
12
+ This checkout's admitted routes are `grok-grok-4-7`, `pi-qwen3-7-plus-openrouter`, `agy-gemini-4-argon-high`, `agy-gemini-4-argon-medium`, `agy-gemini-3-8-flash-medium`, `agy-gemini-3-8-flash-high`, `claude-fable`, `codex-gpt-6-1-sol`, `codex-gpt-5-6-sol`, `pi-qwen3-8-flash-openrouter`, and `pi-glm-5-3-flash-openrouter`. `pi-qwen3-coder-plus-openrouter` stays on disk with `status: retired` because OpenRouter removed `qwen/qwen3-coder-plus` (catalog 404); it is not admitted and not on a roster, and `qwen-openrouter-pi` does not resolve. Agents are `planner`, `writer`, `reviewer-arch`, and `reviewer-cli`. `opus-claude` was removed because `opus` is not an admitted selector. `qwen-token-plan/*` and `zai-coding-cn/*` left the admitted list because those harnesses are not allowlisted; their `prices.yaml` rows stay. Other old ids resolve as aliases. Every roster entry names an effort. `reviewer-arch` dispatches `claude-fable`. #343's architecture critic ran on opus because the justfile recipe review-arch hardcoded that model; the role file on that commit listed only `fable-claude`. The helper now refuses `opus`.
13
13
 
14
14
  ## This checkout's routes and roster
15
15
 
@@ -25,7 +25,7 @@ skills: []
25
25
  roster:
26
26
  - route: grok-grok-4-7
27
27
  effort: medium
28
- - route: pi-qwen3-coder-plus-openrouter
28
+ - route: pi-qwen3-7-plus-openrouter
29
29
  effort: medium
30
30
  - route: agy-gemini-4-argon-high
31
31
  effort: medium
@@ -37,7 +37,7 @@ roster:
37
37
  effort: medium
38
38
  ```
39
39
 
40
- The writer role lists route ids, in order: `grok-grok-4-7`, then `pi-qwen3-coder-plus-openrouter`, then `agy-gemini-4-argon-high`, `agy-gemini-4-argon-medium`, `agy-gemini-3-8-flash-medium`, and `agy-gemini-3-8-flash-high`. `grok-grok-4-7` is harness `grok`, model `grok-4.7`, vendor `xai`. An agent file does not declare `harness:`. Argon is writer #3 and #4. Flash medium is the safety net because Argon needs a paid Google AI Pro, Ultra, or Enterprise plan and `agy -p` exits when the pinned model is missing. Flash high stays on the roster so that admitted model file is still used. Planner and reviewer primaries stay `claude-fable` and `codex-gpt-5-6-sol`. Argon can serve as a planner or architecture-review fallback; it is not on those rosters.
40
+ The writer role lists route ids, in order: `grok-grok-4-7`, then `pi-qwen3-7-plus-openrouter`, then `agy-gemini-4-argon-high`, `agy-gemini-4-argon-medium`, `agy-gemini-3-8-flash-medium`, and `agy-gemini-3-8-flash-high`. `grok-grok-4-7` is harness `grok`, model `grok-4.7`, vendor `xai`. An agent file does not declare `harness:`. Argon is writer #3 and #4. Flash medium is the safety net because Argon needs a paid Google AI Pro, Ultra, or Enterprise plan and `agy -p` exits when the pinned model is missing. Flash high stays on the roster so that admitted model file is still used. The planner primary stays `claude-fable`. The CLI critic primary is `codex-gpt-6-1-sol`, then `pi-qwen3-8-flash-openrouter`, then `codex-gpt-5-6-sol`. The architecture critic primary stays `claude-fable`, then `pi-glm-5-3-flash-openrouter`. Argon can serve as a planner or architecture-review fallback; it is not on those rosters. GPT-6.1 Sol Pro is the same model with reasoning mode `pro`. The route id does not carry a reasoning mode, role effort has no `pro` value, and codex is limited to `reviewer-cli`, so that mode is not an architecture fallback.
41
41
 
42
42
  `node scripts/kxm.mjs routes list`:
43
43
 
@@ -48,7 +48,8 @@ admitted google/gemini-3.8-flash-medium
48
48
  admitted google/gemini-4-argon-high
49
49
  admitted google/gemini-4-argon-medium
50
50
  admitted openai/gpt-5.6-sol
51
- admitted openrouter/qwen/qwen3-coder-plus
51
+ admitted openai/gpt-6.1-sol
52
+ admitted openrouter/qwen/qwen3.7-plus
52
53
  admitted openrouter/qwen/qwen3.8-flash
53
54
  admitted openrouter/z-ai/glm-5.3-flash
54
55
  admitted xai/grok-4.7
@@ -56,17 +57,18 @@ planner claude-fable
56
57
  planner pi-qwen3-8-flash-openrouter
57
58
  reviewer-arch claude-fable
58
59
  reviewer-arch pi-glm-5-3-flash-openrouter
59
- reviewer-cli codex-gpt-5-6-sol
60
+ reviewer-cli codex-gpt-6-1-sol
60
61
  reviewer-cli pi-qwen3-8-flash-openrouter
62
+ reviewer-cli codex-gpt-5-6-sol
61
63
  writer grok-grok-4-7
62
- writer pi-qwen3-coder-plus-openrouter
64
+ writer pi-qwen3-7-plus-openrouter
63
65
  writer agy-gemini-4-argon-high
64
66
  writer agy-gemini-4-argon-medium
65
67
  writer agy-gemini-3-8-flash-medium
66
68
  writer agy-gemini-3-8-flash-high
67
69
  ```
68
70
 
69
- `routes admit --model openrouter/qwen/qwen3-coder-plus --dry-run` exits 2 with `select a model from the refreshed inventory` even though that selector is already admitted, because the inventory never carries `openrouter/…` selectors. Selectors like these are admitted by a Git-reviewed edit of `.kxm/routes.yaml`.
71
+ `routes admit --model openrouter/qwen/qwen3.7-plus --dry-run` exits 2 with `select a model from the refreshed inventory` even though that selector is already admitted, because the inventory never carries `openrouter/…` selectors. Selectors like these are admitted by a Git-reviewed edit of `.kxm/routes.yaml`.
70
72
 
71
73
  On the capture machine, `kxm harness list` showed `claude` detected but logged out (`dispatch no (not_authenticated)`), `deepseek` not installed, and `grok`, `codex`, `kimi` and `agy` ready.
72
74
 
@@ -83,9 +85,9 @@ The issue-127 runner (`kxm assign`, see the [assignment runner](assignment-runne
83
85
  harness: grok
84
86
  model: grok-4.7
85
87
  vendor: xai
86
- pi-qwen3-coder-plus-openrouter:
88
+ pi-qwen3-7-plus-openrouter:
87
89
  harness: pi
88
- model: openrouter/qwen/qwen3-coder-plus
90
+ model: openrouter/qwen/qwen3.7-plus
89
91
  vendor: alibaba
90
92
  ```
91
93
 
@@ -106,7 +108,7 @@ The product layers are in [What the brake refuses](../reference/harness-routing.
106
108
 
107
109
  | Layer | Where | What it refuses | What you see |
108
110
  |---|---|---|---|
109
- | Dev helper | `scripts/harness-run.mjs` | A braked Pi provider, a Pi provider outside the allowlist, a Pi writer other than `openrouter/qwen/qwen3-coder-plus`, or an aggregator id whose vendor segment is a native vendor | `pi brake: xai has a native harness; refusing Pi impersonation`, or `… refusing to bill it through openrouter` |
111
+ | Dev helper | `scripts/harness-run.mjs` | A braked Pi provider, a Pi provider outside the allowlist, a Pi writer other than `openrouter/qwen/qwen3.7-plus`, or an aggregator id whose vendor segment is a native vendor | `pi brake: xai has a native harness; refusing Pi impersonation`, or `… refusing to bill it through openrouter` |
110
112
  | Developer roster | `scripts/roster-policy.mjs` | An aggregator route whose vendor segment is a native vendor | `Roster policy refused: native vendor cannot use Pi` |
111
113
 
112
114
  The dev helper's allowlist (`openrouter`, `nous-portal`, `antigravity`) is a different list from `PI_ALLOWED_PROVIDERS` in `plugins/kxm/src/harness.ts`, which gates nothing. Which of the two should govern is an open decision (Tracking → Still open). Edit permission exists only in the dev helper, and only for admitted writer or experiment routes. The helper accepts only a ChatGPT login for codex, not an API key.
@@ -127,18 +129,18 @@ These extend the generic examples on the reference page with this checkout's adm
127
129
  | Billing | grok.com subscription (OAuth) | $2.00 input, $6.00 output, $0.50 cached input |
128
130
  | Context | 500,000 (`x-ai/grok-4.7` in the refreshed inventory) | 500,000 |
129
131
 
130
- Pi's own `xai` provider reported `ready` (OAuth) on the capture machine. When the grok quota runs out, the next writer in the lineup is `pi-qwen3-coder-plus-openrouter`, a different vendor.
132
+ Pi's own `xai` provider reported `ready` (OAuth) on the capture machine. When the grok quota runs out, the next writer in the lineup is `pi-qwen3-7-plus-openrouter`, a different vendor.
131
133
 
132
- ### GPT-5.6 Sol
134
+ ### GPT-6.1 Sol
133
135
 
134
136
  | | Native `codex` | Pi + OpenRouter |
135
137
  |---|---|---|
136
- | Selector | `openai/gpt-5.6-sol`: admitted, the CLI critic | `openrouter/openai/gpt-5.6-sol`: not admitted |
137
- | Developer roster | `codex-gpt-5-6-sol`: `reviewer-cli`, `read-only` | Refused |
138
- | Billing | ChatGPT subscription | $4.00 input, $20.00 output, $0.40 cached input |
139
- | Context | Pi's `openai-codex` row, the same ChatGPT backend, lists 272K | 1,050,000 |
138
+ | Selector | `openai/gpt-6.1-sol`: admitted, the CLI critic | `openrouter/openai/gpt-6.1-sol`: not admitted |
139
+ | Developer roster | `codex-gpt-6-1-sol`: `reviewer-cli` primary, `read-only`, effort `low` | Refused |
140
+ | Billing | ChatGPT subscription. List price $2.00 input, $10.00 output, $0.10 cached input, $2.50 cache write through 272,000 prompt tokens, then $4.00 / $15.00 | Same per-token list price. OpenRouter's `openai/gpt-6.1-sol-pro` row is reasoning mode `pro`, not a second model |
141
+ | Context | 1,050,000 (922,000 max input, 128,000 max output). Reasoning is mandatory | 1,050,000 |
140
142
 
141
- In the inventory, `openai/gpt-5.6-sol` has sources `openrouter+nous` and carries OpenRouter prices. `pi auth check --provider openai-codex` reported `ready` on the capture machine.
143
+ `codex-gpt-5-6-sol` stays on the `reviewer-cli` roster after the Qwen fallback. Its selector `openai/gpt-5.6-sol` stays admitted. OpenRouter lists that model at $4.00 input, $20.00 output, and $0.40 cached input. `pi auth check --provider openai-codex` reported `ready` on the capture machine. That readiness is not permission to bill OpenAI through Pi.
142
144
 
143
145
  ### Claude Fable
144
146
 
@@ -175,11 +177,11 @@ The code differs from that decision: `.kxm/routes.yaml` admits `google/gemini-3.
175
177
  | Model | Vendor-plan route | OpenRouter route | Notes |
176
178
  |---|---|---|---|
177
179
  | Qwen3.8 Flash | `qwen-token-plan/qwen3.8-flash`: removed from the admitted list on 2026-09-27; `qwen-token-plan` is not allowlisted | `openrouter/qwen/qwen3.8-flash`: admitted, route `pi-qwen3-8-flash-openrouter`, read-only fallback for planner and reviewer-cli | `prices.yaml` keeps both rows. |
178
- | Qwen3 Coder Plus | none | `openrouter/qwen/qwen3-coder-plus`: route `pi-qwen3-coder-plus-openrouter` | The only admitted Pi writer: exact model, `edit` permission. |
180
+ | Qwen3.7 Plus | none | `openrouter/qwen/qwen3.7-plus`: route `pi-qwen3-7-plus-openrouter`, writer #2 | The only admitted Pi writer: exact model, `edit` permission. OpenRouter list on 2026-10-17 is $0.32 input and $1.28 output per 1M tokens, 1,000,000 context, tools supported. |
179
181
  | GLM 5.3 and 5.3 Flash | `zai-coding-cn/glm-5.3` and `…/glm-5.3-flash`: removed from the admitted list on 2026-09-27; `zai-coding-cn` is not allowlisted | `openrouter/z-ai/glm-5.3-flash`: admitted, route `pi-glm-5-3-flash-openrouter`, read-only fallback for reviewer-arch | Z.ai has no native harness. |
180
182
  | DeepSeek V4.1 Flash | `qwen-token-plan/deepseek-v4.1-flash`: removed from the admitted list on 2026-09-27 | `deepseek/deepseek-v4.1-flash` in the OpenRouter feed | Bills a DeepSeek model through Alibaba's plan. `deepseek` is a native-vendor Pi brake, so this is not a route. |
181
183
 
182
- The developer runner is stricter. Its only Pi writer is `openrouter/qwen/qwen3-coder-plus`, and it does not allowlist `qwen-token-plan` or `zai-coding-cn`. Today OpenRouter is the right answer here for Qwen3 Coder Plus, Qwen3.8 Flash and GLM 5.3 Flash.
184
+ The developer runner is stricter. Its only Pi writer is `openrouter/qwen/qwen3.7-plus`, and it does not allowlist `qwen-token-plan` or `zai-coding-cn`. Today OpenRouter is the right answer here for Qwen3.7 Plus, Qwen3.8 Flash and GLM 5.3 Flash. `qwen/qwen3-coder-plus` is retired.
183
185
 
184
186
  ### Nous
185
187
 
package/docs/glossary.md CHANGED
@@ -427,7 +427,7 @@ A list of allowed models. It means either a [role](#role)'s roster, or the devel
427
427
 
428
428
  ### Route
429
429
 
430
- A model selector, such as `xai/grok-4.6` or `openrouter/qwen/qwen3-coder-plus`, that a step can run on. The harness that runs it comes from the agent or the project default. See [Harness routing](reference/harness-routing.md).
430
+ A model selector, such as `xai/grok-4.6` or `openrouter/qwen/qwen3.7-plus`, that a step can run on. The harness that runs it comes from the agent or the project default. See [Harness routing](reference/harness-routing.md).
431
431
 
432
432
  ### Session
433
433
 
@@ -61,7 +61,7 @@ Write the procedure as a Markdown file. KXM adds `name` and `description` front
61
61
  ```bash
62
62
  kxm skills create --file flaky.md --name "Triage flaky test" \
63
63
  --description "Isolate and classify a flaky test before changing code" \
64
- --created-by agent-a --harness pi --models openrouter/qwen/qwen3-coder-plus \
64
+ --created-by agent-a --harness pi --models openrouter/qwen/qwen3.7-plus \
65
65
  --journal journal_abc
66
66
  ```
67
67
 
@@ -82,7 +82,7 @@ When no unused fallback remains, the worker waits `KXM_WORKER_PROVIDER_RETRY_MS`
82
82
  > [!IMPORTANT]
83
83
  > A worker refuses to start on a model whose vendor has its own native harness. Before Pi starts, the worker runs `--model` and every `--fallback-models` entry through the Pi native-vendor brake, and exits 1 with `pi_native_impersonation_blocked` on the first one it refuses: a native provider (`xai/…`), that vendor's own Pi provider (`openai-codex/…`, `kimi-coding/…`), or an aggregator path to it (`openrouter/x-ai/…`). `--dry-run` does not run this check.
84
84
 
85
- Pick every model with [Harness routing](../reference/harness-routing.md), for example `openrouter/qwen/qwen3-coder-plus` with the fallback `openrouter/z-ai/glm-5.3-flash`. The brake cannot check a worker started without `--model`, which runs Pi's default model, or a bare model id that lets Pi choose the provider, so name the provider.
85
+ Pick every model with [Harness routing](../reference/harness-routing.md), for example `openrouter/qwen/qwen3.7-plus` with the fallback `openrouter/z-ai/glm-5.3-flash`. The brake cannot check a worker started without `--model`, which runs Pi's default model, or a bare model id that lets Pi choose the provider, so name the provider.
86
86
 
87
87
  An agent name is only a label. To use a native-harness model as a peer, connect that harness to the hub under the agent name instead, for example the Claude Code plugin with the name `reviewer-claude`.
88
88
 
@@ -203,7 +203,7 @@ kxm hub stop
203
203
  | `KXM worker <project>/<name> is already managed by PID <pid>` | A supervisor for this agent is already running. | Use the running worker, or stop it first. |
204
204
  | The worker exits with `worker requires --name and --project` | Name or project missing. | Pass `--name` and `--project`, or set `KXM_AGENT_NAME` and `KXM_PROJECT`. |
205
205
  | `KXM_WORKER_FALLBACK_MODELS requires KXM_WORKER_MODEL` | Fallbacks without a primary model. | Add `--model`. |
206
- | The worker exits 1 with `pi_native_impersonation_blocked: …` | `--model` or a fallback is a model whose vendor has its own harness. | Run that model in its native harness, or use an admitted Pi route such as `openrouter/qwen/qwen3-coder-plus`. |
206
+ | The worker exits 1 with `pi_native_impersonation_blocked: …` | `--model` or a fallback is a model whose vendor has its own harness. | Run that model in its native harness, or use an admitted Pi route such as `openrouter/qwen/qwen3.7-plus`. |
207
207
  | `kxm connection failed` in the Pi log, or Pi shows `hub:off` | Wrong URL, token, or project, or the name is live elsewhere (`duplicate_agent_name`). | Compare `KXM_SERVER_URL`, `KXM_AUTH_TOKEN`, and `KXM_PROJECT` with the hub; check `kxm peer list`. |
208
208
  | Workflow runs share one conversation | Isolation is `off`, the default. | Restart with `--session-isolation workflow`. |
209
209
  | A request stays `delivered` | A turn, tool, or provider call is still running, or the watchdogs are recovering it. | Read the lifecycle log. Do not send a duplicate. |
@@ -173,7 +173,7 @@ kxm agent worker --name reviewer-grok --project provenance-demo --model <reviewe
173
173
  </details>
174
174
 
175
175
  > [!IMPORTANT]
176
- > The reviewer names are labels. Choose every Pi model with [Harness routing](../reference/harness-routing.md), for example `openrouter/qwen/qwen3-coder-plus` and `openrouter/z-ai/glm-5.3-flash` for two reviewers from different vendors. A worker refuses a model whose vendor has its own native harness, such as Anthropic or xAI, with `pi_native_impersonation_blocked`. To use such a model as a reviewer, connect its native harness under the same agent name instead, for example the Claude Code plugin as `reviewer-claude`.
176
+ > The reviewer names are labels. Choose every Pi model with [Harness routing](../reference/harness-routing.md), for example `openrouter/qwen/qwen3.7-plus` and `openrouter/z-ai/glm-5.3-flash` for two reviewers from different vendors. A worker refuses a model whose vendor has its own native harness, such as Anthropic or xAI, with `pi_native_impersonation_blocked`. To use such a model as a reviewer, connect its native harness under the same agent name instead, for example the Claude Code plugin as `reviewer-claude`.
177
177
 
178
178
  In an operator terminal, supply the workflow-start secret, validate the definition, and create a run:
179
179
 
@@ -134,7 +134,7 @@ The [plugin troubleshooting guide](../../plugins/kxm/README.md#troubleshooting)
134
134
  | The heartbeat is healthy but one tool never finishes | A tool exceeded `KXM_WORKER_TOOL_TIMEOUT_MS` (31 minutes by default, above the 30-minute fanout wait) | The worker logs `worker_tool_timeout` and restarts the child; raise the limit only above the longest legitimate call |
135
135
  | A long-lived worker keeps restarting | Pi is missing from the service `PATH`, the working directory is gone, or model credentials are missing | Read `worker_process_error` and `worker_exited`; set `KXM_PI_COMMAND` to an explicit path |
136
136
  | A read-only reviewer edits files | Prompt wording does not remove tools | Set `KXM_WORKER_TOOLS=read,grep,find,ls` |
137
- | The worker exits at once with `pi_native_impersonation_blocked` | `--model` or a `--fallback-models` entry is a model whose vendor has its own harness, such as `xai/…`, `openai-codex/…` or `openrouter/x-ai/…` | Run that model in its native harness, or pick an admitted Pi route such as `openrouter/qwen/qwen3-coder-plus`; see [Harness routing](../reference/harness-routing.md#what-the-brake-refuses) |
137
+ | The worker exits at once with `pi_native_impersonation_blocked` | `--model` or a `--fallback-models` entry is a model whose vendor has its own harness, such as `xai/…`, `openai-codex/…` or `openrouter/x-ai/…` | Run that model in its native harness, or pick an admitted Pi route such as `openrouter/qwen/qwen3.7-plus`; see [Harness routing](../reference/harness-routing.md#what-the-brake-refuses) |
138
138
 
139
139
  Use `--fresh-start`, not `--no-continue`, when only the first launch must avoid old session state.
140
140
 
@@ -1156,7 +1156,8 @@ admitted google/gemini-3.8-flash-medium
1156
1156
  admitted google/gemini-4-argon-high
1157
1157
  admitted google/gemini-4-argon-medium
1158
1158
  admitted openai/gpt-5.6-sol
1159
- admitted openrouter/qwen/qwen3-coder-plus
1159
+ admitted openai/gpt-6.1-sol
1160
+ admitted openrouter/qwen/qwen3.7-plus
1160
1161
  admitted openrouter/qwen/qwen3.8-flash
1161
1162
  admitted openrouter/z-ai/glm-5.3-flash
1162
1163
  admitted xai/grok-4.7
@@ -1164,10 +1165,11 @@ planner claude-fable
1164
1165
  planner pi-qwen3-8-flash-openrouter
1165
1166
  reviewer-arch claude-fable
1166
1167
  reviewer-arch pi-glm-5-3-flash-openrouter
1167
- reviewer-cli codex-gpt-5-6-sol
1168
+ reviewer-cli codex-gpt-6-1-sol
1168
1169
  reviewer-cli pi-qwen3-8-flash-openrouter
1170
+ reviewer-cli codex-gpt-5-6-sol
1169
1171
  writer grok-grok-4-7
1170
- writer pi-qwen3-coder-plus-openrouter
1172
+ writer pi-qwen3-7-plus-openrouter
1171
1173
  writer agy-gemini-4-argon-high
1172
1174
  writer agy-gemini-4-argon-medium
1173
1175
  writer agy-gemini-3-8-flash-medium
@@ -1179,7 +1181,7 @@ kxm routes list --json
1179
1181
  ```
1180
1182
 
1181
1183
  ```text
1182
- {"schema":"kxm.cli-result.v1","ok":true,"command":"routes list","policy":{"schema":"kxm.routes.v2","updatedAt":"2026-10-17T00:00:00.000Z","admitted":["anthropic/fable","google/gemini-3.8-flash-high","google/gemini-3.8-flash-medium","google/gemini-4-argon-high","google/gemini-4-argon-medium","openai/gpt-5.6-sol","openrouter/qwen/qwen3-coder-plus","openrouter/qwen/qwen3.8-flash","openrouter/z-ai/glm-5.3-flash","xai/grok-4.7"],"disabled":[]},"membership":["planner claude-fable","planner pi-qwen3-8-flash-openrouter","reviewer-arch claude-fable","reviewer-arch pi-glm-5-3-flash-openrouter","reviewer-cli codex-gpt-5-6-sol","reviewer-cli pi-qwen3-8-flash-openrouter","writer grok-grok-4-7","writer pi-qwen3-coder-plus-openrouter","writer agy-gemini-4-argon-high","writer agy-gemini-4-argon-medium","writer agy-gemini-3-8-flash-medium","writer agy-gemini-3-8-flash-high"]}
1184
+ {"schema":"kxm.cli-result.v1","ok":true,"command":"routes list","policy":{"schema":"kxm.routes.v2","updatedAt":"2026-10-17T14:30:00.000Z","admitted":["anthropic/fable","google/gemini-3.8-flash-high","google/gemini-3.8-flash-medium","google/gemini-4-argon-high","google/gemini-4-argon-medium","openai/gpt-5.6-sol","openai/gpt-6.1-sol","openrouter/qwen/qwen3.7-plus","openrouter/qwen/qwen3.8-flash","openrouter/z-ai/glm-5.3-flash","xai/grok-4.7"],"disabled":[]},"membership":["planner claude-fable","planner pi-qwen3-8-flash-openrouter","reviewer-arch claude-fable","reviewer-arch pi-glm-5-3-flash-openrouter","reviewer-cli codex-gpt-6-1-sol","reviewer-cli pi-qwen3-8-flash-openrouter","reviewer-cli codex-gpt-5-6-sol","writer grok-grok-4-7","writer pi-qwen3-7-plus-openrouter","writer agy-gemini-4-argon-high","writer agy-gemini-4-argon-medium","writer agy-gemini-3-8-flash-medium","writer agy-gemini-3-8-flash-high"]}
1183
1185
  ```
1184
1186
 
1185
1187
  ### `kxm routes count`
@@ -1384,7 +1386,7 @@ kxm role get writer --json
1384
1386
  ```
1385
1387
 
1386
1388
  ```text
1387
- {"schema":"kxm.cli-result.v1","ok":true,"command":"role get","roleId":"writer","scope":"local","filePath":"/work/kxm/.kxm/roles/writer.yaml","role":{"schema":"kxm.role.v2","id":"writer","purpose":"writer","permission":"edit","description":"Primary implementation agent.","skills":[],"roster":[{"route":"grok-grok-4-7","effort":"medium"},{"route":"pi-qwen3-coder-plus-openrouter","effort":"medium"},{"route":"agy-gemini-4-argon-high","effort":"medium"},{"route":"agy-gemini-4-argon-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-high","effort":"medium"}]}}
1389
+ {"schema":"kxm.cli-result.v1","ok":true,"command":"role get","roleId":"writer","scope":"local","filePath":"/work/kxm/.kxm/roles/writer.yaml","role":{"schema":"kxm.role.v2","id":"writer","purpose":"writer","permission":"edit","description":"Primary implementation agent.","skills":[],"roster":[{"route":"grok-grok-4-7","effort":"medium"},{"route":"pi-qwen3-7-plus-openrouter","effort":"medium"},{"route":"agy-gemini-4-argon-high","effort":"medium"},{"route":"agy-gemini-4-argon-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-high","effort":"medium"}]}}
1388
1390
  ```
1389
1391
 
1390
1392
  Captured from this checkout with `node scripts/kxm.mjs role get writer --json`. The path is shortened to `/work/kxm`.
@@ -1394,7 +1396,7 @@ kxm role modify writer --add-skill kxm --dry-run --json
1394
1396
  ```
1395
1397
 
1396
1398
  ```text
1397
- {"schema":"kxm.cli-result.v1","ok":true,"command":"role modify","roleId":"writer","id":"writer","role":{"schema":"kxm.role.v2","id":"writer","purpose":"writer","permission":"edit","description":"Primary implementation agent.","skills":["kxm"],"roster":[{"route":"grok-grok-4-7","effort":"medium"},{"route":"pi-qwen3-coder-plus-openrouter","effort":"medium"},{"route":"agy-gemini-4-argon-high","effort":"medium"},{"route":"agy-gemini-4-argon-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-high","effort":"medium"}]},"filePath":"/work/kxm/.kxm/roles/writer.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/kxm/.kxm/roles/writer.yaml"}]}
1399
+ {"schema":"kxm.cli-result.v1","ok":true,"command":"role modify","roleId":"writer","id":"writer","role":{"schema":"kxm.role.v2","id":"writer","purpose":"writer","permission":"edit","description":"Primary implementation agent.","skills":["kxm"],"roster":[{"route":"grok-grok-4-7","effort":"medium"},{"route":"pi-qwen3-7-plus-openrouter","effort":"medium"},{"route":"agy-gemini-4-argon-high","effort":"medium"},{"route":"agy-gemini-4-argon-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-medium","effort":"medium"},{"route":"agy-gemini-3-8-flash-high","effort":"medium"}]},"filePath":"/work/kxm/.kxm/roles/writer.yaml","scope":"local","dryRun":true,"planned":[{"action":"write","target":"/work/kxm/.kxm/roles/writer.yaml"}]}
1398
1400
  ```
1399
1401
 
1400
1402
  Add an existing route to a role's roster (Not run):
@@ -2012,11 +2014,11 @@ Starts a long-lived, supervised Pi RPC worker in the foreground through `scripts
2012
2014
  - Needs Pi and a reachable hub. Runs until stopped (`kxm hub stop` stops managed workers too). The exit code is the worker's.
2013
2015
  - A name and project are required (exit 2 otherwise); an invalid isolation mode exits 2.
2014
2016
  - `--dry-run` prints a `kxm.worker-result.v1` envelope with `workspace`, `name`, `project`, `model`, `fallbackModels`, `tools`, `sessionIsolation`, `continue`, `freshStart`.
2015
- - Before Pi starts, the worker runs `--model` and every `--fallback-models` entry through the Pi native-vendor brake. A model whose vendor has its own harness (for example `xai/…`, `openai-codex/…`, `openrouter/x-ai/…` or `antigravity/claude-…`) exits 1 with `pi_native_impersonation_blocked: <message>` on stderr; use the native harness, or an admitted Pi route such as `openrouter/qwen/qwen3-coder-plus`. `--dry-run` does not run this check. See [Harness routing](harness-routing.md#what-the-brake-refuses).
2017
+ - Before Pi starts, the worker runs `--model` and every `--fallback-models` entry through the Pi native-vendor brake. A model whose vendor has its own harness (for example `xai/…`, `openai-codex/…`, `openrouter/x-ai/…` or `antigravity/claude-…`) exits 1 with `pi_native_impersonation_blocked: <message>` on stderr; use the native harness, or an admitted Pi route such as `openrouter/qwen/qwen3.7-plus`. `--dry-run` does not run this check. See [Harness routing](harness-routing.md#what-the-brake-refuses).
2016
2018
  - The remaining worker variables are described in [Long-lived worker settings](configuration.md#long-lived-worker-settings).
2017
2019
 
2018
2020
  ```bash
2019
- kxm agent worker --name reviewer --project demo --model openrouter/qwen/qwen3-coder-plus --tools read,grep,find,ls --session-isolation workflow --fresh-start --dry-run
2021
+ kxm agent worker --name reviewer --project demo --model openrouter/qwen/qwen3.7-plus --tools read,grep,find,ls --session-isolation workflow --fresh-start --dry-run
2020
2022
  ```
2021
2023
 
2022
2024
  ```text
@@ -2024,7 +2026,7 @@ would start worker
2024
2026
  ```
2025
2027
 
2026
2028
  ```bash
2027
- kxm agent worker --name coordinator --project demo --model openrouter/qwen/qwen3-coder-plus --session-isolation workflow
2029
+ kxm agent worker --name coordinator --project demo --model openrouter/qwen/qwen3.7-plus --session-isolation workflow
2028
2030
  ```
2029
2031
 
2030
2032
  Not run: starts a long-lived Pi worker.
@@ -3360,7 +3362,7 @@ Submit a skill candidate from verified episodes.
3360
3362
  - Writes a candidate. Honors `--dry-run`. JSON keys: `metadata` (or `name` for a dry run).
3361
3363
 
3362
3364
  ```bash
3363
- kxm skills create --file SKILL.md --name retry-backoff --created-by alice --harness pi --models openrouter/qwen/qwen3-coder-plus --run wf_123 --dry-run --json
3365
+ kxm skills create --file SKILL.md --name retry-backoff --created-by alice --harness pi --models openrouter/qwen/qwen3.7-plus --run wf_123 --dry-run --json
3364
3366
  ```
3365
3367
 
3366
3368
  ```text
@@ -3625,7 +3627,7 @@ Dedicated offline benchmark for side-by-side model comparison (Decision Q12). To
3625
3627
  | Option | Argument | Default | Description |
3626
3628
  |---|---|---|---|
3627
3629
  | `--task` | `<fixture>` | `Deterministic benchmark task` | Task prompt or fixture path for benchmark comparison |
3628
- | `--arms` | `<models>` | `grok/grok-4.6,claude/fable,pi/qwen3-coder-plus` | Comma-separated model routes to benchmark (e.g. grok/grok-4.6,claude/fable) |
3630
+ | `--arms` | `<models>` | `grok/grok-4.6,claude/fable,pi/qwen3.7-plus` | Comma-separated model routes to benchmark (e.g. grok/grok-4.6,claude/fable) |
3629
3631
  | `--runs` | `<count>` | `1` | Benchmark runs per arm |
3630
3632
 
3631
3633
  - Reads nothing. JSON keys: `task`, `runs`, `timestamp`, `arms` (`harness`, `model`, `latencyMs`, `tokensIn`, `tokensOut`, `costUsd`, `outcome`).
@@ -3639,7 +3641,7 @@ Routing Benchmark Results (task: Deterministic benchmark task, runs: 1)
3639
3641
  Harness Model Latency(ms) TokensIn TokensOut Cost($) Outcome
3640
3642
  grok grok-4.6 420 1200 450 $0.17 passed
3641
3643
  claude fable 680 1200 450 $0.45 passed
3642
- pi qwen3-coder-plus 560 1200 450 $0.12 passed
3644
+ pi qwen3.7-plus 560 1200 450 $0.12 passed
3643
3645
  ```
3644
3646
 
3645
3647
  ## `kxm prices`
@@ -686,7 +686,7 @@ Example (validated with `kxm init --json` and compiled with
686
686
  the `critic-claude` profile shown above, it needs a `planner` agent (the
687
687
  workflow coordinator; `coordinator` still resolves as an alias), a
688
688
  `reviewer-cli` agent, and a second profile tagged `critic`, `critic-sol`
689
- (`openai/gpt-5.6-sol`). Routes, not agent files, name the harness and model.
689
+ (`openai/gpt-6.1-sol`). Routes, not agent files, name the harness and model.
690
690
  The two providers among the `critic` candidates satisfy
691
691
  `distinctBy: [provider]` with `target: 2`.
692
692
 
@@ -963,7 +963,7 @@ description: Primary implementation agent.
963
963
  roster:
964
964
  - route: grok-grok-4-7
965
965
  effort: medium
966
- - route: pi-qwen3-coder-plus-openrouter
966
+ - route: pi-qwen3-7-plus-openrouter
967
967
  effort: medium
968
968
  ```
969
969
 
@@ -991,7 +991,7 @@ unknown keys are ignored).
991
991
 
992
992
  A route string is derived from the selected model file's `vendor` and
993
993
  `model`, joined by a slash: `xai/grok-4.6`, `anthropic/fable`,
994
- `openrouter/qwen/qwen3-coder-plus`. When the file is missing, nothing is
994
+ `openrouter/qwen/qwen3.7-plus`. When the file is missing, nothing is
995
995
  admitted and every live attempt is refused (`producer_route_unsupported`, or
996
996
  `producer_route_not_admitted` from the live producer). A leftover
997
997
  `.kxm/producers.yaml` makes every reader fail with `retired
@@ -1002,7 +1002,7 @@ admitted and every live attempt is refused (`producer_route_unsupported`, or
1002
1002
  `model_selection_required`. Inventory IDs come in several shapes (bare
1003
1003
  `grok-4.6` from `grok models`, `vendor/model` from OpenRouter,
1004
1004
  `provider/model` from `pi --list-models`), so a route such as
1005
- `openrouter/qwen/qwen3-coder-plus` or `anthropic/fable` usually has to be
1005
+ `openrouter/qwen/qwen3.7-plus` or `anthropic/fable` usually has to be
1006
1006
  added by editing the file.
1007
1007
 
1008
1008
  ```yaml
@@ -1011,8 +1011,9 @@ updatedAt: '2026-09-23T00:00:00.000Z'
1011
1011
  admitted:
1012
1012
  - anthropic/fable
1013
1013
  - openai/gpt-5.6-sol
1014
+ - openai/gpt-6.1-sol
1014
1015
  - xai/grok-4.6
1015
- - openrouter/qwen/qwen3-coder-plus
1016
+ - openrouter/qwen/qwen3.7-plus
1016
1017
  disabled: []
1017
1018
  ```
1018
1019
 
@@ -1067,9 +1068,9 @@ routes:
1067
1068
  roles: [writer]
1068
1069
  permissions: [edit]
1069
1070
  status: admitted # admitted | retired
1070
- pi-qwen3-coder-plus-openrouter:
1071
+ pi-qwen3-7-plus-openrouter:
1071
1072
  harness: pi
1072
- model: openrouter/qwen/qwen3-coder-plus # Pi: allowed provider prefix + vendor/model
1073
+ model: openrouter/qwen/qwen3.7-plus # Pi: allowed provider prefix + vendor/model
1073
1074
  vendor: alibaba
1074
1075
  roles: [writer]
1075
1076
  permissions: [edit]
@@ -1081,6 +1082,13 @@ routes:
1081
1082
  roles: [planner, reviewer-arch]
1082
1083
  permissions: [read-only]
1083
1084
  status: admitted
1085
+ codex-gpt-6-1-sol:
1086
+ harness: codex
1087
+ model: gpt-6.1-sol
1088
+ vendor: openai
1089
+ roles: [reviewer-cli]
1090
+ permissions: [read-only]
1091
+ status: admitted
1084
1092
  codex-gpt-5-6-sol:
1085
1093
  harness: codex
1086
1094
  model: gpt-5.6-sol
@@ -1089,19 +1097,19 @@ routes:
1089
1097
  permissions: [read-only]
1090
1098
  status: admitted
1091
1099
  lineup: # routes admitted for each role, preference order
1092
- writer: [grok-grok-4-7, pi-qwen3-coder-plus-openrouter, agy-gemini-4-argon-high, agy-gemini-4-argon-medium, agy-gemini-3-8-flash-medium, agy-gemini-3-8-flash-high]
1100
+ writer: [grok-grok-4-7, pi-qwen3-7-plus-openrouter, agy-gemini-4-argon-high, agy-gemini-4-argon-medium, agy-gemini-3-8-flash-medium, agy-gemini-3-8-flash-high]
1093
1101
  planner: [claude-fable, pi-qwen3-8-flash-openrouter]
1094
1102
  reviewer-arch: [claude-fable, pi-glm-5-3-flash-openrouter]
1095
- reviewer-cli: [codex-gpt-5-6-sol, pi-qwen3-8-flash-openrouter]
1103
+ reviewer-cli: [codex-gpt-6-1-sol, pi-qwen3-8-flash-openrouter, codex-gpt-5-6-sol]
1096
1104
  required_critics:
1097
1105
  review-arch: claude-fable
1098
- review-cli: codex-gpt-5-6-sol
1106
+ review-cli: codex-gpt-6-1-sol
1099
1107
  model_origins: # required for every Pi route model
1100
- openrouter/qwen/qwen3-coder-plus:
1108
+ openrouter/qwen/qwen3.7-plus:
1101
1109
  vendor: alibaba
1102
1110
  evidence:
1103
- source: plans/evidence/route-qwen-openrouter-pi.md
1104
- sha256: b15f8a54adc398b33e75609e959076eee310bf4ff6623d0b8470ea3da95e6c54
1111
+ source: plans/evidence/route-pi-qwen3-7-plus-openrouter.md
1112
+ sha256: 10e11cfa572ef4891e514d229fa8b7f0f355b31e6481315a6dd763bbe44244a1
1105
1113
  ```
1106
1114
 
1107
1115
  Validated with `validateRosterDocument` from `scripts/roster-policy.mjs`,
@@ -166,14 +166,14 @@ For example, a review-only worker that cannot edit the checkout:
166
166
 
167
167
  ```bash
168
168
  export KXM_WORKER_TOOLS="read,grep,find,ls,kxm_list,kxm_get,kxm_reply"
169
- kxm agent worker --name reviewer --project <project> --model openrouter/qwen/qwen3-coder-plus
169
+ kxm agent worker --name reviewer --project <project> --model openrouter/qwen/qwen3.7-plus
170
170
  ```
171
171
 
172
172
  <details><summary>PowerShell</summary>
173
173
 
174
174
  ```powershell
175
175
  $env:KXM_WORKER_TOOLS = "read,grep,find,ls,kxm_list,kxm_get,kxm_reply"
176
- kxm agent worker --name reviewer --project <project> --model openrouter/qwen/qwen3-coder-plus
176
+ kxm agent worker --name reviewer --project <project> --model openrouter/qwen/qwen3.7-plus
177
177
  ```
178
178
 
179
179
  </details>
@@ -12,11 +12,11 @@ These are KXM's routing rules. The code enforces them in layers: the Pi native-v
12
12
  - **Same model, prefer the subscription.** Prefer an authenticated native subscription for the same model.
13
13
  - **Quota exhaustion is not a license to cross-bill.** Take the **next best** authenticated option by quality, then cost, from the report, not a silent Pi API key for the same vendor.
14
14
  - **A harness is not a model, and it is not a worker.** A harness runs only the models it hosts. Only Pi is a long-lived worker. `grok` and `agy` are one-shot CLIs.
15
- - **Admission is a decision, not a config tweak.** A route that is not admitted is refused. Admit one precise selector, such as `openrouter/qwen/qwen3-coder-plus`, never a whole provider.
15
+ - **Admission is a decision, not a config tweak.** A route that is not admitted is refused. Admit one precise selector, such as `openrouter/qwen/qwen3.7-plus`, never a whole provider.
16
16
 
17
17
  ## 1. Decision procedure: "I want model X"
18
18
 
19
- 1. **Name the vendor of X.** The vendor is the lab that trained the model, not whoever bills you for it. `x-ai/grok-4.6` is xAI. `qwen/qwen3-coder-plus` is Alibaba. `z-ai/glm-5.3` is Z.ai.
19
+ 1. **Name the vendor of X.** The vendor is the lab that trained the model, not whoever bills you for it. `x-ai/grok-4.6` is xAI. `qwen/qwen3.7-plus` is Alibaba. `z-ai/glm-5.3` is Z.ai.
20
20
  2. **Check whether the vendor has a native harness.** KXM maps `anthropic→claude`, `openai→codex`, `xai→grok`, `google→agy`, `moonshot→kimi` and `deepseek→deepseek`. Google is an exception (section 4). If the vendor is not in this list, go to step 6.
21
21
  3. **Check that the native harness is installed and logged in.** In `kxm harness list`, the row must show `detected yes`, `auth yes` and `dispatch yes`. `no` and `unknown` are never eligible.
22
22
  4. **Check that the harness hosts X.** `claude` runs only Anthropic models. `grok` runs only `grok-*`. `agy` runs only `gemini-*`. `kimi` runs only `kimi-*` or `moonshot-*`. `deepseek` runs only `deepseek-*`. `codex` refuses other vendors' model prefixes. To see the exact ids, use the harness's own catalog: `grok models`, `agy models` or `kimi provider list`.
@@ -92,14 +92,14 @@ codex login status
92
92
  grok models
93
93
  agy models
94
94
  kimi provider list
95
- pi auth check --model openrouter/qwen/qwen3-coder-plus --json --no-refresh
95
+ pi auth check --model openrouter/qwen/qwen3.7-plus --json --no-refresh
96
96
  ```
97
97
 
98
98
  ## 2. Which route will a config line use?
99
99
 
100
100
  ### How KXM builds a route
101
101
 
102
- - **Selector.** The selector is `<vendor>/<model>` from the selected `.kxm/models/<route>.yaml`. The agent names a `role`, `.kxm/roles/<role>.yaml` lists route ids, and the chosen roster entry names that model file. The model id may contain `/`, for example `openrouter/qwen/qwen3-coder-plus`.
102
+ - **Selector.** The selector is `<vendor>/<model>` from the selected `.kxm/models/<route>.yaml`. The agent names a `role`, `.kxm/roles/<role>.yaml` lists route ids, and the chosen roster entry names that model file. The model id may contain `/`, for example `openrouter/qwen/qwen3.7-plus`.
103
103
  - **Harness.** The harness is the `harness` field on that model file. An agent file does not select it.
104
104
  - **Admission.** The selector must be admitted. The engine uses the first roster entry whose model file is readable and whose route is admitted.
105
105
  - **Dispatch probe.** Before spawning anything, the producer probes the exact harness, provider and model triple. It refuses unhosted pairs and the Pi brake.
@@ -135,7 +135,7 @@ model: openrouter/x-ai/grok-4.7
135
135
  vendor: xai
136
136
  ```
137
137
 
138
- The selector is `openrouter/x-ai/grok-4.7` and the harness is `pi`. The Pi brake refuses it before Pi starts, because the vendor segment `x-ai` is xAI, which has a native harness. A vendor with no native harness runs in the same shape: with `model: openrouter/qwen/qwen3-coder-plus`, Pi is spawned with `--model openrouter/qwen/qwen3-coder-plus`, its read-only flags (section 3) and `-p --mode json`. Write `model` exactly as the provider names it. For OpenRouter that is the vendor slug, so `x-ai`, not `xai`.
138
+ The selector is `openrouter/x-ai/grok-4.7` and the harness is `pi`. The Pi brake refuses it before Pi starts, because the vendor segment `x-ai` is xAI, which has a native harness. A vendor with no native harness runs in the same shape: with `model: openrouter/qwen/qwen3.7-plus`, Pi is spawned with `--model openrouter/qwen/qwen3.7-plus`, its read-only flags (section 3) and `-p --mode json`. Write `model` exactly as the provider names it. For OpenRouter that is the vendor slug, so `x-ai`, not `xai`.
139
139
 
140
140
  The harness and the selector have to agree. Pi refuses `provider: xai` and `openrouter/x-ai/…`. `grok` refuses `provider: openrouter`. [What the brake refuses](#what-the-brake-refuses) has the exact messages.
141
141
 
@@ -153,7 +153,7 @@ description: Primary implementation agent.
153
153
  roster:
154
154
  - route: grok-grok-4-7
155
155
  effort: medium
156
- - route: pi-qwen3-coder-plus-openrouter
156
+ - route: pi-qwen3-7-plus-openrouter
157
157
  effort: medium
158
158
  - route: agy-gemini-4-argon-high
159
159
  effort: medium
@@ -165,7 +165,7 @@ roster:
165
165
  effort: medium
166
166
  ```
167
167
 
168
- `grok-grok-4-7` resolves to `.kxm/models/grok-grok-4-7.yaml`: harness `grok`, model `grok-4.7`, vendor `xai`, status `admitted`, permission `edit`. `pi-qwen3-coder-plus-openrouter` is harness `pi`, model `openrouter/qwen/qwen3-coder-plus`, vendor `alibaba`. `agy-gemini-4-argon-high` is harness `agy`, model `gemini-4-argon-high`, vendor `google`. `kxm role list` prints the first route id as the primary, for example `(grok-grok-4-7)`. The previous ids (`grok-native`, `qwen-openrouter-pi`, `gemini-agy`) are aliases. `gemini-agy` resolves to `agy-gemini-4-argon-high`.
168
+ `grok-grok-4-7` resolves to `.kxm/models/grok-grok-4-7.yaml`: harness `grok`, model `grok-4.7`, vendor `xai`, status `admitted`, permission `edit`. `pi-qwen3-7-plus-openrouter` is harness `pi`, model `openrouter/qwen/qwen3.7-plus`, vendor `alibaba`, and it is writer #2. `agy-gemini-4-argon-high` is harness `agy`, model `gemini-4-argon-high`, vendor `google`. `kxm role list` prints the first route id as the primary, for example `(grok-grok-4-7)`. The previous ids `grok-native` and `gemini-agy` are aliases. `gemini-agy` resolves to `agy-gemini-4-argon-high`. `qwen-openrouter-pi` is not an alias: it belonged to retired `pi-qwen3-coder-plus-openrouter` (`openrouter/qwen/qwen3-coder-plus`, catalog 404) and does not resolve to `pi-qwen3-7-plus-openrouter`.
169
169
 
170
170
  Dispatch resolves a step from the agent `role`, then `.kxm/roles/<role>.yaml`, then the selected `.kxm/models/<route>.yaml`. That model file carries `harness`, `model`, `vendor`, `status`, and `permissions`. The engine walks the roster in order and uses the first admitted route whose model file is readable. A missing or unreadable model file is a refusal (`roster_model_unreadable` at load, `producer_route_unsupported` at dispatch), not a skip to the next entry. A route file that names a harness the model cannot run on still fails closed with `harness_unhosted_model`.
171
171
 
@@ -176,7 +176,7 @@ Role files are what `kxm role` and the Runtime membership check use.
176
176
  `kxm routes list` prints one line per decision, for example:
177
177
 
178
178
  ```text
179
- admitted openrouter/qwen/qwen3-coder-plus
179
+ admitted openrouter/qwen/qwen3.7-plus
180
180
  admitted xai/grok-4.7
181
181
  disabled openrouter/x-ai/grok-4.7
182
182
  ```
@@ -201,7 +201,7 @@ The first segment of an id is the provider, and the rest is the model id. A rout
201
201
  `kxm routes admit --model <id>` only takes an id that exists in `.kxm/models/inventory.yaml`. The inventory is a different namespace from these selectors (next section), and it never carries an `openrouter/…` selector, so a dry run refuses one:
202
202
 
203
203
  ```bash
204
- kxm routes admit --model openrouter/qwen/qwen3-coder-plus --dry-run
204
+ kxm routes admit --model openrouter/qwen/qwen3.7-plus --dry-run
205
205
  ```
206
206
 
207
207
  ```text
@@ -232,7 +232,7 @@ The same model shows up under different ids depending on the file:
232
232
  | `.kxm/models/inventory.yaml`, source `openrouter` | `x-ai/grok-4.7` | The OpenRouter catalog slug. The inventory stores OpenRouter ids without an `openrouter/` prefix. |
233
233
  | `.kxm/prices.yaml` | `id: xai/grok-4.7`, `provider: xai`, alias `x-ai/grok-4.7` | A list price that applies only to provider `xai`, because price lookup filters by provider. `xai/grok-4.6` remains a separate row. |
234
234
 
235
- An inventory id can also mean something else in `.kxm/routes.yaml`. For example, the inventory can list `openai/gpt-5.6-sol` from the OpenRouter feed with OpenRouter prices, while in `.kxm/routes.yaml` the same string means provider `openai` through native `codex`.
235
+ An inventory id can also mean something else in `.kxm/routes.yaml`. For example, the inventory can list `openai/gpt-6.1-sol` from the OpenRouter feed with OpenRouter prices, while in `.kxm/routes.yaml` the same string means provider `openai` through native `codex`. `openai/gpt-5.6-sol` is the same kind of selector and stays admitted.
236
236
 
237
237
  ### What the brake refuses
238
238
 
@@ -249,10 +249,10 @@ The brake runs wherever KXM starts Pi on a model: in the dispatch probe that eac
249
249
  | How the id names the vendor | Refused examples | Message |
250
250
  |---|---|---|
251
251
  | The provider is the vendor | `anthropic/…`, `openai/…`, `xai/…`, `moonshot/…`, `google/…`, `deepseek/…` | `pi must not impersonate native provider xai; use the native harness` |
252
- | A Pi provider that belongs to the vendor | `openai-codex/…`, `moonshotai/…`, `moonshotai-cn/…`, `kimi-coding/…`, `google-vertex/…`, `claude-bridge/…`, and `antigravity/…` except Gemini ids | `pi provider openai-codex bills native vendor openai for gpt-5.6-sol; use the native harness` |
252
+ | A Pi provider that belongs to the vendor | `openai-codex/…`, `moonshotai/…`, `moonshotai-cn/…`, `kimi-coding/…`, `google-vertex/…`, `claude-bridge/…`, and `antigravity/…` except Gemini ids | `pi provider openai-codex bills native vendor openai for gpt-6.1-sol; use the native harness` |
253
253
  | The vendor segment of an aggregator id, including the aliases `x-ai`, `moonshotai` and `google-ai` | `openrouter/x-ai/grok-4.6`, `openrouter/anthropic/claude-fable-5.1`, `nous-portal/google/…` | `pi must not bill native vendor xai through openrouter; use the native harness` |
254
254
 
255
- The brake accepts `antigravity/gemini-…` and any id whose vendor has no native harness, such as `openrouter/qwen/qwen3-coder-plus`, `zai-coding-cn/glm-5.3` or `qwen-token-plan/qwen3.8-flash`. Passing the brake is not admission: the route must still be admitted. The hosting refusal at dispatch reads `grok_not_authenticated: grok harness not detected (harness_unhosted_model)`.
255
+ The brake accepts `antigravity/gemini-…` and any id whose vendor has no native harness, such as `openrouter/qwen/qwen3.7-plus`, `zai-coding-cn/glm-5.3` or `qwen-token-plan/qwen3.8-flash`. Passing the brake is not admission: the route must still be admitted. The hosting refusal at dispatch reads `grok_not_authenticated: grok harness not detected (harness_unhosted_model)`.
256
256
 
257
257
  To run the load-time check, which covers only agents that declare a harness and select a profile or tag, run the read-only validation:
258
258
 
@@ -367,18 +367,22 @@ pi auth check --provider xai --json --no-refresh
367
367
  {"status":"ready","provider":"xai","authType":"oauth"}
368
368
  ```
369
369
 
370
- ### GPT-5.6 Sol
370
+ ### GPT-6.1 Sol
371
371
 
372
372
  | | Native `codex` | Pi + OpenRouter |
373
373
  |---|---|---|
374
- | Model file | `harness: codex`, `model: gpt-5.6-sol`, `vendor: openai` | `harness: pi`, `model: openrouter/openai/gpt-5.6-sol`, `vendor: openai` |
375
- | Selector | `openai/gpt-5.6-sol` | `openrouter/openai/gpt-5.6-sol` |
374
+ | Model file | `harness: codex`, `model: gpt-6.1-sol`, `vendor: openai` | `harness: pi`, `model: openrouter/openai/gpt-6.1-sol`, `vendor: openai` |
375
+ | Selector | `openai/gpt-6.1-sol`: admitted, the CLI critic | `openrouter/openai/gpt-6.1-sol` |
376
376
  | Readiness | Needs `codex` auth `yes` with `authMethod: ChatGPT` | Never reached: the brake refuses it first |
377
- | Billing | ChatGPT subscription | OpenRouter credit |
377
+ | Billing | ChatGPT subscription. List price $2 / $10 per 1M tokens through 272,000 prompt tokens ($0.10 cached input, $2.50 cache write), then $4 / $15 | OpenRouter credit, same per-token list price |
378
378
  | Recorded `costBasis` | `unmetered`, `priceRef: subscription:codex` | None: refused before dispatch |
379
- | Mode | One-shot `codex exec --json -` | Refused |
379
+ | Mode | One-shot `codex exec --json -`. Reasoning is mandatory (`low`, `medium`, `high`, `xhigh`, `max`) | Refused |
380
380
 
381
- **KXM picks the native route.** Two traps apply here. The first is `openai-codex/gpt-5.6-sol`, which is the same ChatGPT subscription driven through Pi. `pi auth check --provider openai-codex` can report `ready`, but readiness is not permission: the brake refuses `openai-codex` as OpenAI's own Pi provider. The second is a codex login made with an API key: the row shows `API key`, and the run records `unknown`.
381
+ `codex-gpt-6-1-sol` is the `reviewer-cli` primary at effort `low`. `pi-qwen3-8-flash-openrouter` is the other-vendor fallback. `codex-gpt-5-6-sol` stays admitted as the last fallback. Architecture review stays `claude-fable`, then `pi-glm-5-3-flash-openrouter`.
382
+
383
+ Pro is not a separate model. It is `gpt-6.1-sol` with reasoning mode `pro`. OpenRouter lists that mode as `openai/gpt-6.1-sol-pro` at the same per-token price. A route id is `<harness>-<model-slug>`, role `effort` has no `pro` value, and the codex harness ceiling is `reviewer-cli` only. There is no pro architecture-review fallback.
384
+
385
+ **KXM picks the native route.** Two traps apply here. The first is `openai-codex/gpt-6.1-sol`, which is the same ChatGPT subscription driven through Pi. `pi auth check --provider openai-codex` can report `ready`, but readiness is not permission: the brake refuses `openai-codex` as OpenAI's own Pi provider. The second is a codex login made with an API key: the row shows `API key`, and the run records `unknown`. `openai/gpt-5.6-sol` is the same shape of selector and stays admitted. On OpenRouter it now lists at $4 / $20 per 1M tokens.
382
386
 
383
387
  ```bash
384
388
  pi auth check --provider openai-codex --json --no-refresh
@@ -448,7 +452,7 @@ Admit an `antigravity/…` route only through a reviewed admission decision. The
448
452
  Pi is the right harness when the vendor has no native harness in KXM, for example Qwen (Alibaba) and GLM (Z.ai). The choice is then between the vendor's own plan provider in Pi and an aggregator:
449
453
 
450
454
  - Prefer the vendor-plan provider when `pi auth check` reports it `ready`, for example `qwen-token-plan/qwen3.8-flash` or `zai-coding-cn/glm-5.3`.
451
- - Otherwise use an aggregator selector, such as `openrouter/qwen/qwen3-coder-plus`.
455
+ - Otherwise use an aggregator selector, such as `openrouter/qwen/qwen3.7-plus`.
452
456
  - Admit the exact selector, with the permission it needs, never a whole provider.
453
457
 
454
458
  DeepSeek has a native harness entry, but it is never eligible: its auth is always `unknown`, and it has no audited read-only profile. A DeepSeek model billed through another vendor's plan, such as `qwen-token-plan/deepseek-…`, passes the brake because its id names no vendor segment. It is an admission question, not a precedent.
@@ -493,7 +497,7 @@ Each of those is a fail-closed stop, or a new admission decision.
493
497
  | `pi auth check --provider nous-portal` or `--provider antigravity` returns `provider_not_found`. | The provider comes from a Pi package or the KXM Pi extension, and `pi auth check` never loads extensions, not even one passed with `-e`. | Confirm with `pi list` and `pi --list-models <id>`. The Runtime's Pi one-shot runs with `--no-extensions` and checks readiness with `pi auth check`, so it cannot reach extension providers. |
494
498
  | `producer_route_unsupported: model '<selector>' is not admitted`, or `producer_route_not_admitted`. | The selector is missing from `admitted` in `.kxm/routes.yaml`, or it is under `disabled`. | Check with `kxm routes list`. After a reviewed decision, run `kxm routes admit --model <id>`, or edit the file when the inventory lacks the id. |
495
499
  | `producer_route_unsupported: model '<selector>' not in role '<role>' roster` | The role file exists and does not list the selector. | Add it to `.kxm/roles/<role>.yaml` by Git review, and check with `kxm role get <role>`. |
496
- | `pi_native_impersonation_blocked`, at dispatch or when a worker starts. | A Pi agent or worker names a native vendor's model: directly, through that vendor's Pi provider, or behind an aggregator. | Use the native harness (`harness: grok` for `provider: xai`), or an admitted Pi route whose vendor has no native harness, such as `openrouter/qwen/qwen3-coder-plus`. |
500
+ | `pi_native_impersonation_blocked`, at dispatch or when a worker starts. | A Pi agent or worker names a native vendor's model: directly, through that vendor's Pi provider, or behind an aggregator. | Use the native harness (`harness: grok` for `provider: xai`), or an admitted Pi route whose vendor has no native harness, such as `openrouter/qwen/qwen3.7-plus`. |
497
501
  | `grok_not_authenticated: grok harness not detected (harness_unhosted_model)`, or `harness grok does not host provider openrouter`. | A native-harness agent was given an aggregator or another vendor's selector, often from a mixed role roster. | Give that selector its own agent with `harness:` omitted. |
498
502
  | `routing report` shows every attempt under `Unk*`, and records carry `costBasis: unknown`. | Grok and every Pi route are recorded as `unknown` today. That is the design, not a missing price. | Nothing to fix per run. Compare quality and latency, and use list estimates for cost. |
499
503
  | `providerMetadata.priceCatalogStale: true`, and there is no `listCostUsd`. | `.kxm/prices.yaml` is not dated today, or no row matches the route's provider. | Edit `.kxm/prices.yaml` by Git review: add a row for the provider, then update `date` and `sha256`. The loader refuses a hash mismatch. |
@@ -26,7 +26,7 @@ details:
26
26
  - kind: "review-cli"
27
27
  role: "reviewer-cli"
28
28
  harness: "codex"
29
- model: "gpt-5.6-sol"
29
+ model: "gpt-6.1-sol"
30
30
  verdict: "PASS" # PASS | BLOCK
31
31
  ---
32
32
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@kontextmind/kxm",
3
- "version": "0.7.184",
3
+ "version": "0.7.186",
4
4
  "description": "KXM local-first multi-agent orchestration and operator dashboard",
5
5
  "type": "module",
6
6
  "author": "KontextMind",
@@ -1167,7 +1167,7 @@ function evaluatePlanOptimizations(tasks) {
1167
1167
  projectedTimeSavingsSeconds: 5,
1168
1168
  projectedCostSavingsPercent: 65,
1169
1169
  suggestedHarness: "pi",
1170
- suggestedModel: "qwen/qwen3-coder-plus",
1170
+ suggestedModel: "qwen/qwen3.7-plus",
1171
1171
  selected: true
1172
1172
  });
1173
1173
  } else if (isFrontier && (task.category === "lint" || /lint|format|style/i.test(task.title))) {
@@ -84,7 +84,7 @@ export function evaluatePlanOptimizations(tasks: readonly OptimizerTaskInput[]):
84
84
  projectedTimeSavingsSeconds: 5,
85
85
  projectedCostSavingsPercent: 65,
86
86
  suggestedHarness: "pi",
87
- suggestedModel: "qwen/qwen3-coder-plus",
87
+ suggestedModel: "qwen/qwen3.7-plus",
88
88
  selected: true,
89
89
  });
90
90
  } else if (isFrontier && (task.category === "lint" || /lint|format|style/i.test(task.title))) {
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json.schemastore.org/claude-code-plugin-manifest.json",
3
3
  "name": "kxm",
4
4
  "displayName": "KXM",
5
- "version": "0.7.184",
5
+ "version": "0.7.186",
6
6
  "description": "Headless multi-agent orchestration, durable workflows, and a live operator dashboard for Pi and Claude Code",
7
7
  "author": {
8
8
  "name": "KontextMind",
@@ -18541,9 +18541,14 @@ function lintWorkforce(root) {
18541
18541
  if (!expected || model.id !== expected) {
18542
18542
  push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
18543
18543
  }
18544
- if (!used.has(model.id)) {
18544
+ const retired = doc.status === "retired";
18545
+ if (retired && used.has(model.id)) {
18546
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
18547
+ }
18548
+ if (!retired && !used.has(model.id)) {
18545
18549
  push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
18546
18550
  }
18551
+ if (retired) continue;
18547
18552
  const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
18548
18553
  if (!selectorHit) {
18549
18554
  push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
@@ -18614,9 +18619,9 @@ var init_workforce_names = __esm({
18614
18619
  ]);
18615
18620
  ROUTE_RENAMES = Object.freeze([
18616
18621
  ["grok-native", "grok-grok-4-7"],
18617
- ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
18618
18622
  ["gemini-agy", "agy-gemini-4-argon-high"],
18619
18623
  ["fable-claude", "claude-fable"],
18624
+ // sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
18620
18625
  ["sol-codex", "codex-gpt-5-6-sol"],
18621
18626
  ["grok-default", "grok-grok-4-6"],
18622
18627
  ["fable-default", "claude-fable"]
@@ -56720,7 +56725,7 @@ var ADMITTED_GUIDE_BINDINGS = Object.freeze({
56720
56725
  "openai/gpt-5.6-sol": { harness: "codex", provider: "openai", model: "gpt-5.6-sol" },
56721
56726
  "x-ai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
56722
56727
  "xai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
56723
- "qwen/qwen3-coder-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3-coder-plus" }
56728
+ "qwen/qwen3.7-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3.7-plus" }
56724
56729
  });
56725
56730
  var GUIDE_WORKFLOWS = [
56726
56731
  {
@@ -56751,7 +56756,7 @@ var GUIDE_WORKFLOWS = [
56751
56756
  { vendor: "openai", model: "gpt-5.6-sol" },
56752
56757
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
56753
56758
  { vendor: "google", model: "gemini-3.8-flash" },
56754
- { vendor: "qwen", model: "qwen3-coder-plus" },
56759
+ { vendor: "qwen", model: "qwen3.7-plus" },
56755
56760
  { vendor: "anthropic", model: "claude-fable-5.1" }
56756
56761
  ]
56757
56762
  },
@@ -56763,7 +56768,7 @@ var GUIDE_WORKFLOWS = [
56763
56768
  candidates: [
56764
56769
  { vendor: "x-ai", model: "grok-4.6" },
56765
56770
  { vendor: "mistralai", model: "devstral-2512" },
56766
- { vendor: "qwen", model: "qwen3-coder-plus" },
56771
+ { vendor: "qwen", model: "qwen3.7-plus" },
56767
56772
  { vendor: "openai", model: "gpt-5.3-codex" },
56768
56773
  { vendor: "kwaipilot", model: "kat-coder-pro-v2.5" }
56769
56774
  ]
@@ -56775,7 +56780,7 @@ var GUIDE_WORKFLOWS = [
56775
56780
  domain: "Implements domain entities, SQL queries/migrations, ORM persistence, concurrency primitives, and transactional boundaries.",
56776
56781
  candidates: [
56777
56782
  { vendor: "x-ai", model: "grok-4.6" },
56778
- { vendor: "qwen", model: "qwen3-coder-plus" },
56783
+ { vendor: "qwen", model: "qwen3.7-plus" },
56779
56784
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
56780
56785
  { vendor: "openai", model: "gpt-5.3-codex" },
56781
56786
  { vendor: "kwaipilot", model: "kat-coder-pro-v2.5" }
@@ -56802,7 +56807,7 @@ var GUIDE_WORKFLOWS = [
56802
56807
  candidates: [
56803
56808
  { vendor: "openai", model: "gpt-5.6-sol" },
56804
56809
  { vendor: "x-ai", model: "grok-4.6" },
56805
- { vendor: "qwen", model: "qwen3-coder-plus" },
56810
+ { vendor: "qwen", model: "qwen3.7-plus" },
56806
56811
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
56807
56812
  { vendor: "google", model: "gemini-3.8-flash" }
56808
56813
  ]
@@ -56929,7 +56934,7 @@ var GUIDE_WORKFLOWS = [
56929
56934
  domain: "Generates declarative Terraform/OpenTofu, Pulumi, Kubernetes CRDs, and VPC networking definitions.",
56930
56935
  candidates: [
56931
56936
  { vendor: "x-ai", model: "grok-4.6" },
56932
- { vendor: "qwen", model: "qwen3-coder-plus" },
56937
+ { vendor: "qwen", model: "qwen3.7-plus" },
56933
56938
  { vendor: "openai", model: "gpt-5.3-codex" },
56934
56939
  { vendor: "google", model: "gemini-3.8-flash" },
56935
56940
  { vendor: "mistralai", model: "devstral-2512" }
@@ -56989,7 +56994,7 @@ var GUIDE_WORKFLOWS = [
56989
56994
  domain: "Authors concise, accurate developer and operator documentation with clear terminology, correct command flags, and consistent formatting without marketing drift.",
56990
56995
  candidates: [
56991
56996
  { vendor: "x-ai", model: "grok-4.6" },
56992
- { vendor: "qwen", model: "qwen3-coder-plus" },
56997
+ { vendor: "qwen", model: "qwen3.7-plus" },
56993
56998
  { vendor: "anthropic", model: "claude-sonnet-5" },
56994
56999
  { vendor: "openai", model: "gpt-5.3-codex" },
56995
57000
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" }
@@ -57094,11 +57099,11 @@ function workflowDocument(workflow) {
57094
57099
  };
57095
57100
  }
57096
57101
  var GUIDE_PI_EVIDENCE_SOURCE = "plans/evidence/route-guide-qwen-pi.md";
57097
- var GUIDE_PI_EVIDENCE_SHA256 = "109f39728b251dd0565e275ae689a6e1d9b889a488d996b157d500c538115759";
57102
+ var GUIDE_PI_EVIDENCE_SHA256 = "8a24a7dc6db416df2153cfec7bccf1a4462f838e35c4e6707dc421ca84cf069b";
57098
57103
  var GUIDE_PI_NOTE = {
57099
57104
  harness: "pi",
57100
57105
  vendor: "openrouter",
57101
- model: "qwen/qwen3-coder-plus",
57106
+ model: "qwen/qwen3.7-plus",
57102
57107
  reason: "Qwen has no supported native harness on this runner, and the operator admitted that exact model for guided setup.",
57103
57108
  provingCommand: "pi auth check --provider openrouter"
57104
57109
  };
@@ -58100,7 +58105,7 @@ async function cmdRoutingReport(runtime, options) {
58100
58105
  }
58101
58106
  async function cmdRoutingBenchmark(runtime, options) {
58102
58107
  const task = options.task || "Deterministic benchmark task";
58103
- const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3-coder-plus";
58108
+ const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3.7-plus";
58104
58109
  const armsList = armsStr.split(",").map((s) => s.trim()).filter(Boolean);
58105
58110
  const runsCount = Math.max(1, parseInt(options.runs || "1", 10) || 1);
58106
58111
  const arms = armsList.map((arm) => {
@@ -25462,7 +25462,7 @@ function sessionTokenFixHint(policy) {
25462
25462
  }
25463
25463
 
25464
25464
  // plugins/kxm/src/mcp-server.ts
25465
- var VERSION = "0.7.184";
25465
+ var VERSION = "0.7.186";
25466
25466
  var CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
25467
25467
  var inbox = /* @__PURE__ */ new Map();
25468
25468
  var notifiedInbox = /* @__PURE__ */ new Set();
@@ -15543,9 +15543,9 @@ var ROLE_IDS = Object.freeze([
15543
15543
  ]);
15544
15544
  var ROUTE_RENAMES = Object.freeze([
15545
15545
  ["grok-native", "grok-grok-4-7"],
15546
- ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
15547
15546
  ["gemini-agy", "agy-gemini-4-argon-high"],
15548
15547
  ["fable-claude", "claude-fable"],
15548
+ // sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
15549
15549
  ["sol-codex", "codex-gpt-5-6-sol"],
15550
15550
  ["grok-default", "grok-grok-4-6"],
15551
15551
  ["fable-default", "claude-fable"]
@@ -15734,9 +15734,14 @@ function lintWorkforce(root) {
15734
15734
  if (!expected || model.id !== expected) {
15735
15735
  push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
15736
15736
  }
15737
- if (!used.has(model.id)) {
15737
+ const retired = doc.status === "retired";
15738
+ if (retired && used.has(model.id)) {
15739
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
15740
+ }
15741
+ if (!retired && !used.has(model.id)) {
15738
15742
  push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
15739
15743
  }
15744
+ if (retired) continue;
15740
15745
  const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
15741
15746
  if (!selectorHit) {
15742
15747
  push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
@@ -15516,9 +15516,9 @@ var ROLE_IDS = Object.freeze([
15516
15516
  ]);
15517
15517
  var ROUTE_RENAMES = Object.freeze([
15518
15518
  ["grok-native", "grok-grok-4-7"],
15519
- ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
15520
15519
  ["gemini-agy", "agy-gemini-4-argon-high"],
15521
15520
  ["fable-claude", "claude-fable"],
15521
+ // sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
15522
15522
  ["sol-codex", "codex-gpt-5-6-sol"],
15523
15523
  ["grok-default", "grok-grok-4-6"],
15524
15524
  ["fable-default", "claude-fable"]
@@ -15707,9 +15707,14 @@ function lintWorkforce(root) {
15707
15707
  if (!expected || model.id !== expected) {
15708
15708
  push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
15709
15709
  }
15710
- if (!used.has(model.id)) {
15710
+ const retired = doc.status === "retired";
15711
+ if (retired && used.has(model.id)) {
15712
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
15713
+ }
15714
+ if (!retired && !used.has(model.id)) {
15711
15715
  push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
15712
15716
  }
15717
+ if (retired) continue;
15713
15718
  const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
15714
15719
  if (!selectorHit) {
15715
15720
  push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
@@ -36446,7 +36451,7 @@ var SUBAGENT_TYPES = Object.freeze([
36446
36451
  ]);
36447
36452
  var DEFAULT_SUBAGENT_MODELS = Object.freeze({
36448
36453
  general: "grok/grok-4.6",
36449
- Explore: "openrouter/qwen/qwen3-coder-plus",
36454
+ Explore: "openrouter/qwen/qwen3.7-plus",
36450
36455
  Plan: "claude/fable",
36451
36456
  Reviewer: "openai/gpt-5.6-sol",
36452
36457
  Auditor: "claude/fable"
@@ -15008,9 +15008,9 @@ var ROLE_IDS = Object.freeze([
15008
15008
  ]);
15009
15009
  var ROUTE_RENAMES = Object.freeze([
15010
15010
  ["grok-native", "grok-grok-4-7"],
15011
- ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
15012
15011
  ["gemini-agy", "agy-gemini-4-argon-high"],
15013
15012
  ["fable-claude", "claude-fable"],
15013
+ // sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
15014
15014
  ["sol-codex", "codex-gpt-5-6-sol"],
15015
15015
  ["grok-default", "grok-grok-4-6"],
15016
15016
  ["fable-default", "claude-fable"]
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "claude-plugin",
3
- "version": "0.7.184",
3
+ "version": "0.7.186",
4
4
  "private": true,
5
5
  "type": "module",
6
6
  "engines": {
@@ -1071,7 +1071,7 @@ export async function cmdRoutingBenchmark(
1071
1071
  options: { task?: string | undefined; arms?: string | undefined; runs?: string | undefined },
1072
1072
  ): Promise<number> {
1073
1073
  const task = options.task || "Deterministic benchmark task";
1074
- const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3-coder-plus";
1074
+ const armsStr = options.arms || "grok/grok-4.6,claude/fable,pi/qwen3.7-plus";
1075
1075
  const armsList = armsStr.split(",").map((s) => s.trim()).filter(Boolean);
1076
1076
  const runsCount = Math.max(1, parseInt(options.runs || "1", 10) || 1);
1077
1077
 
@@ -64,7 +64,7 @@ const ADMITTED_GUIDE_BINDINGS: Readonly<Record<string, AgentBinding>> = Object.f
64
64
  "openai/gpt-5.6-sol": { harness: "codex", provider: "openai", model: "gpt-5.6-sol" },
65
65
  "x-ai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
66
66
  "xai/grok-4.6": { harness: "grok", provider: "xai", model: "grok-4.6" },
67
- "qwen/qwen3-coder-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3-coder-plus" },
67
+ "qwen/qwen3.7-plus": { harness: "pi", provider: "openrouter", model: "qwen/qwen3.7-plus" },
68
68
  });
69
69
 
70
70
  /** Guide candidates are ordered by preference; the first eligible wins. */
@@ -97,7 +97,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
97
97
  { vendor: "openai", model: "gpt-5.6-sol" },
98
98
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
99
99
  { vendor: "google", model: "gemini-3.8-flash" },
100
- { vendor: "qwen", model: "qwen3-coder-plus" },
100
+ { vendor: "qwen", model: "qwen3.7-plus" },
101
101
  { vendor: "anthropic", model: "claude-fable-5.1" },
102
102
  ],
103
103
  },
@@ -109,7 +109,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
109
109
  candidates: [
110
110
  { vendor: "x-ai", model: "grok-4.6" },
111
111
  { vendor: "mistralai", model: "devstral-2512" },
112
- { vendor: "qwen", model: "qwen3-coder-plus" },
112
+ { vendor: "qwen", model: "qwen3.7-plus" },
113
113
  { vendor: "openai", model: "gpt-5.3-codex" },
114
114
  { vendor: "kwaipilot", model: "kat-coder-pro-v2.5" },
115
115
  ],
@@ -121,7 +121,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
121
121
  domain: "Implements domain entities, SQL queries/migrations, ORM persistence, concurrency primitives, and transactional boundaries.",
122
122
  candidates: [
123
123
  { vendor: "x-ai", model: "grok-4.6" },
124
- { vendor: "qwen", model: "qwen3-coder-plus" },
124
+ { vendor: "qwen", model: "qwen3.7-plus" },
125
125
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
126
126
  { vendor: "openai", model: "gpt-5.3-codex" },
127
127
  { vendor: "kwaipilot", model: "kat-coder-pro-v2.5" },
@@ -148,7 +148,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
148
148
  candidates: [
149
149
  { vendor: "openai", model: "gpt-5.6-sol" },
150
150
  { vendor: "x-ai", model: "grok-4.6" },
151
- { vendor: "qwen", model: "qwen3-coder-plus" },
151
+ { vendor: "qwen", model: "qwen3.7-plus" },
152
152
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
153
153
  { vendor: "google", model: "gemini-3.8-flash" },
154
154
  ],
@@ -275,7 +275,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
275
275
  domain: "Generates declarative Terraform/OpenTofu, Pulumi, Kubernetes CRDs, and VPC networking definitions.",
276
276
  candidates: [
277
277
  { vendor: "x-ai", model: "grok-4.6" },
278
- { vendor: "qwen", model: "qwen3-coder-plus" },
278
+ { vendor: "qwen", model: "qwen3.7-plus" },
279
279
  { vendor: "openai", model: "gpt-5.3-codex" },
280
280
  { vendor: "google", model: "gemini-3.8-flash" },
281
281
  { vendor: "mistralai", model: "devstral-2512" },
@@ -335,7 +335,7 @@ export const GUIDE_WORKFLOWS: readonly GuideWorkflow[] = [
335
335
  domain: "Authors concise, accurate developer and operator documentation with clear terminology, correct command flags, and consistent formatting without marketing drift.",
336
336
  candidates: [
337
337
  { vendor: "x-ai", model: "grok-4.6" },
338
- { vendor: "qwen", model: "qwen3-coder-plus" },
338
+ { vendor: "qwen", model: "qwen3.7-plus" },
339
339
  { vendor: "anthropic", model: "claude-sonnet-5" },
340
340
  { vendor: "openai", model: "gpt-5.3-codex" },
341
341
  { vendor: "deepseek", model: "deepseek-v4-pro-0813" },
@@ -490,11 +490,11 @@ function workflowDocument(workflow: GuideWorkflow): Record<string, unknown> {
490
490
  * id, and harness gets no model file and no origin.
491
491
  */
492
492
  const GUIDE_PI_EVIDENCE_SOURCE = "plans/evidence/route-guide-qwen-pi.md";
493
- const GUIDE_PI_EVIDENCE_SHA256 = "109f39728b251dd0565e275ae689a6e1d9b889a488d996b157d500c538115759";
493
+ const GUIDE_PI_EVIDENCE_SHA256 = "8a24a7dc6db416df2153cfec7bccf1a4462f838e35c4e6707dc421ca84cf069b";
494
494
  const GUIDE_PI_NOTE = {
495
495
  harness: "pi",
496
496
  vendor: "openrouter",
497
- model: "qwen/qwen3-coder-plus",
497
+ model: "qwen/qwen3.7-plus",
498
498
  reason: "Qwen has no supported native harness on this runner, and the operator admitted that exact model for guided setup.",
499
499
  provingCommand: "pi auth check --provider openrouter",
500
500
  } as const;
@@ -11,7 +11,7 @@ import { deliverInboxNotification } from "./inbox.ts";
11
11
  import type { HubEvent, MessageRecord } from "./protocol.ts";
12
12
  import { sessionTokenFixHint } from "./session-token-hint.ts";
13
13
 
14
- const VERSION = "0.7.184";
14
+ const VERSION = "0.7.186";
15
15
  const CONFIGURE_PLUGIN = "/plugin configure kxm@kxm";
16
16
  const inbox = new Map<string, MessageRecord>();
17
17
  const notifiedInbox = new Set<string>();
@@ -270,7 +270,7 @@ export function createKxmOneShotProducer(options: KxmOneShotProducerOptions = {}
270
270
  ): { provider: string; model: string; thinking?: string | undefined } {
271
271
  if (request.model) {
272
272
  // A separate provider field means the model id is bare and may itself be
273
- // namespaced (openrouter + qwen/qwen3-coder-plus); reparsing it as a
273
+ // namespaced (openrouter + qwen/qwen3.7-plus); reparsing it as a
274
274
  // provider/model selector strips the namespace — the same defect #262 fixed
275
275
  // in the pi producer. Only parse when the provider must come from the string.
276
276
  if (request.provider) {
@@ -401,7 +401,7 @@ export function createKxmOneShotProducer(options: KxmOneShotProducerOptions = {}
401
401
  // pi's model flag takes the provider-qualified id — exactly the auth probe's
402
402
  // rule (#265): prefix with the provider unless the model already starts with it.
403
403
  // A bare "contains a slash" test is wrong for provider-local namespaces
404
- // (openrouter + qwen/qwen3-coder-plus must spawn as the full three-part id).
404
+ // (openrouter + qwen/qwen3.7-plus must spawn as the full three-part id).
405
405
  const qualified = resolved.provider && resolved.model.startsWith(`${resolved.provider}/`)
406
406
  ? resolved.model
407
407
  : resolved.provider ? `${resolved.provider}/${resolved.model}` : resolved.model;
@@ -463,7 +463,7 @@ export function createKxmPiProducer(options: KxmPiProducerOptions = {}): KxmPiPr
463
463
  function resolveModelForRequest(request: KxmProducerRequest): { provider: string; model: string; thinking?: string | undefined } {
464
464
  if (request.model) {
465
465
  // A separate provider field means the model id is bare and may itself be
466
- // namespaced (`qwen/qwen3-coder-plus` under `openrouter`); reparsing it as a
466
+ // namespaced (`qwen/qwen3.7-plus` under `openrouter`); reparsing it as a
467
467
  // provider/model selector strips the namespace and sends the wrong model. Only
468
468
  // parse when the provider must come from the string itself.
469
469
  if (request.provider) {
@@ -77,7 +77,7 @@ export const SUBAGENT_TYPES: readonly SubagentType[] = Object.freeze([
77
77
 
78
78
  export const DEFAULT_SUBAGENT_MODELS: Readonly<Record<SubagentType, string>> = Object.freeze({
79
79
  general: "grok/grok-4.6",
80
- Explore: "openrouter/qwen/qwen3-coder-plus",
80
+ Explore: "openrouter/qwen/qwen3.7-plus",
81
81
  Plan: "claude/fable",
82
82
  Reviewer: "openai/gpt-5.6-sol",
83
83
  Auditor: "claude/fable",
@@ -12,7 +12,9 @@
12
12
  * the assignment runner reads at one commit. A tree that has already renamed
13
13
  * the files still accepts the old id. A mixed tree accepts either side.
14
14
  * `opus-claude` is not renamed: that route pointed at an unadmitted model and
15
- * was removed.
15
+ * was removed. `qwen-openrouter-pi` is not renamed either: it belonged to
16
+ * retired `pi-qwen3-coder-plus-openrouter` and does not resolve to
17
+ * `pi-qwen3-7-plus-openrouter`.
16
18
  */
17
19
 
18
20
  import { existsSync, readdirSync, readFileSync } from "node:fs";
@@ -32,9 +34,9 @@ export const ROLE_IDS = Object.freeze([
32
34
  /** Old id, canonical id. Listed once; lookup tries both directions. */
33
35
  export const ROUTE_RENAMES = Object.freeze([
34
36
  ["grok-native", "grok-grok-4-7"],
35
- ["qwen-openrouter-pi", "pi-qwen3-coder-plus-openrouter"],
36
37
  ["gemini-agy", "agy-gemini-4-argon-high"],
37
38
  ["fable-claude", "claude-fable"],
39
+ // sol-codex stays the GPT-5.6 route. codex-gpt-6-1-sol is a separate route.
38
40
  ["sol-codex", "codex-gpt-5-6-sol"],
39
41
  ["grok-default", "grok-grok-4-6"],
40
42
  ["fable-default", "claude-fable"],
@@ -190,7 +192,9 @@ function selectorsFor(doc) {
190
192
 
191
193
  /**
192
194
  * Lint one project's `.kxm` workforce. Errors fail CI. An admitted model with
193
- * no route is a warning. Alias declarations are not uses; a roster or step
195
+ * no route is a warning. A model file with `status: retired` may stay off
196
+ * every roster and off `.kxm/routes.yaml`; a roster that still names it is
197
+ * `route_not_admitted`. Alias declarations are not uses; a roster or step
194
198
  * that still cites an old id is a `deprecated_id` warning.
195
199
  */
196
200
  export function lintWorkforce(root) {
@@ -256,9 +260,14 @@ export function lintWorkforce(root) {
256
260
  if (!expected || model.id !== expected) {
257
261
  push(errors, "error", "route_id_convention", `.kxm/models/${model.id}.yaml`, `route id '${model.id}' must be '${expected ?? "<harness>-<model-slug>[-<provider>]"}'`);
258
262
  }
259
- if (!used.has(model.id)) {
263
+ const retired = doc.status === "retired";
264
+ if (retired && used.has(model.id)) {
265
+ push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `retired route '${model.id}' is still on a role roster`);
266
+ }
267
+ if (!retired && !used.has(model.id)) {
260
268
  push(errors, "error", "route_unused", `.kxm/models/${model.id}.yaml`, `route '${model.id}' is not on any role roster`);
261
269
  }
270
+ if (retired) continue;
262
271
  const selectorHit = selectorsFor(doc).find((selector) => admitted.includes(selector));
263
272
  if (!selectorHit) {
264
273
  push(errors, "error", "route_not_admitted", `.kxm/models/${model.id}.yaml`, `model '${doc.model ?? ""}' is not an admitted selector`);
@@ -141,7 +141,7 @@ export const ATTRIBUTION_CLASSES = Object.freeze(["orchestration", "model", "env
141
141
  export const ACCEPTED_NOTE = "developer record; not human approval, hub peer evidence, CI success, or merged/released status";
142
142
  export const REQUIRED_ACCEPT_CRITICS = Object.freeze({
143
143
  "review-arch": Object.freeze({ harness: "claude", model: "fable", role: "reviewer-arch" }),
144
- "review-cli": Object.freeze({ harness: "codex", model: "gpt-5.6-sol", role: "reviewer-cli" }),
144
+ "review-cli": Object.freeze({ harness: "codex", model: "gpt-6.1-sol", role: "reviewer-cli" }),
145
145
  });
146
146
  export const ASSIGNMENT_KINDS = Object.freeze([
147
147
  "plan",
@@ -19,7 +19,7 @@ export const PI_ALLOWED_PROVIDERS: readonly string[];
19
19
  export const PI_NATIVE_VENDOR_PROVIDERS: Readonly<Record<string, string>>;
20
20
  export const PI_ANTIGRAVITY_MODEL_ID: RegExp;
21
21
  export const PI_NOUS_PORTAL_HY4: "nous-portal/tencent/hy4-preview";
22
- export const PI_ADMITTED_WRITER: "openrouter/qwen/qwen3-coder-plus";
22
+ export const PI_ADMITTED_WRITER: "openrouter/qwen/qwen3.7-plus";
23
23
  export const ROUTES: Record<string, {
24
24
  provider: string;
25
25
  roles: readonly string[];
@@ -88,7 +88,7 @@ export const PI_ANTIGRAVITY_MODEL_ID = /^gemini-[a-z0-9.-]+$/;
88
88
  export const PI_NOUS_PORTAL_HY4 = "nous-portal/tencent/hy4-preview";
89
89
 
90
90
  /** Narrowly admitted Pi writer. Other Pi models need reviewed route admission. */
91
- export const PI_ADMITTED_WRITER = "openrouter/qwen/qwen3-coder-plus";
91
+ export const PI_ADMITTED_WRITER = "openrouter/qwen/qwen3.7-plus";
92
92
 
93
93
  const REQUEST_KEYS = Object.freeze([
94
94
  "schema",
@@ -164,7 +164,7 @@ export const ROUTES = Object.freeze({
164
164
  provider: "openai",
165
165
  roles: Object.freeze(["reviewer-cli"]),
166
166
  permissions: Object.freeze(["read-only"]),
167
- models: Object.freeze(["gpt-5.6-sol"]),
167
+ models: Object.freeze(["gpt-6.1-sol", "gpt-5.6-sol"]),
168
168
  efforts: Object.freeze(["low", "medium", "high"]),
169
169
  auth: Object.freeze({ args: ["login", "status"], loginHint: "codex login" }),
170
170
  },
@@ -1555,7 +1555,7 @@ export function preflightRequest(request) {
1555
1555
  }
1556
1556
  }
1557
1557
  if (request.role === "writer" && (request.model !== PI_ADMITTED_WRITER || request.permission !== "edit")) {
1558
- throw failClosed("pi writer refuses unsupported route; allows only authenticated openrouter/qwen/qwen3-coder-plus with edit permission; other models need reviewed route admission");
1558
+ throw failClosed("pi writer refuses unsupported route; allows only authenticated openrouter/qwen/qwen3.7-plus with edit permission; other models need reviewed route admission");
1559
1559
  }
1560
1560
  const segment = piProviderOf(piModelId(request.model));
1561
1561
  const vendor = segment && Object.hasOwn(PI_VENDOR_SEGMENT_ALIASES, segment) ? PI_VENDOR_SEGMENT_ALIASES[segment] : segment;