@mmerterden/multi-agent-pipeline 19.1.2 → 19.1.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -14,6 +14,30 @@ Internal file-layout changes that don't affect the slash-command surface are sti
14
14
 
15
15
  ---
16
16
 
17
+ ## [19.1.3] - 2026-09-21
18
+
19
+ ### Fixed
20
+
21
+ - **Routing no longer hands back a rung the caller cannot dispatch to.** The
22
+ router permitted a non-Anthropic rung at `bulk-read`, and `bulk-read.sh`
23
+ passes the rung straight to `claude -p --model <rung>` - a CLI that speaks the
24
+ Anthropic ladder and nothing else. `research_ask` never consulted the router
25
+ at all. So no call site could honour an external rung, and the permission was
26
+ empty: a rule naming one produced a failed call rather than a cheaper one.
27
+
28
+ `model-dispatch.sh` now refuses a non-Anthropic rung at every call site and
29
+ falls to the NEXT rung the rule named, not to the caller's default - the user
30
+ asked for a preference order, and only the part that cannot be honoured is
31
+ dropped. `provider` in `cost-table.json` stays, because it is what makes the
32
+ refusal checkable and is the seam a future call site would use.
33
+
34
+ `smoke-model-dispatch.sh` asserts the reason rather than the rule:
35
+ `bulk-read.sh` still dispatches through the Anthropic CLI. The day a call site
36
+ grows its own provider path, that assertion is what says the refusal may be
37
+ lifted.
38
+
39
+ ---
40
+
17
41
  ## [19.1.2] - 2026-09-21
18
42
 
19
43
  ### Added
package/docs/facts.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$comment": "Generated by pipeline/scripts/gen-facts.mjs. Do not hand-edit: the site reads this, and a number edited here instead of at its source is the drift this file removes.",
3
- "generatedAt": "2026-09-20",
4
- "version": "19.1.2",
3
+ "generatedAt": "2026-09-21",
4
+ "version": "19.1.3",
5
5
  "phaseSchema": 2,
6
6
  "phases": [
7
7
  {
package/manifest.json CHANGED
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "19.1.2",
4
- "commit": "074b9a4c2cfd511e61c43582551a8147b0326f20",
5
- "generatedAt": "2026-09-20T21:00:49.167Z",
3
+ "version": "19.1.3",
4
+ "commit": "ab89855c58cbddec0ea834d80efc7dfc3f630c69",
5
+ "generatedAt": "2026-09-21T06:32:52.127Z",
6
6
  "algorithm": "sha256",
7
7
  "fileCount": 1057,
8
8
  "files": {
9
- "CHANGELOG.md": "237e1085d742fec90a3ad103f302af3bf9edb41ff554c45385b00df8970b16a0",
9
+ "CHANGELOG.md": "a17d55e5b1f00236a491817510d60a845f6ff31a9b466dc56fed3daf19cb2deb",
10
10
  "LICENSE": "8d8c51aaf1e1538b180c69965fa038db71be86798cc3e26a143bebfefe16a43e",
11
11
  "README.md": "63cba0443ff6750cf979ca39093f80f414a9ffa72bdf08a196a4fb821520fb5d",
12
12
  "README.tr.md": "429823b93ae79e783ac91559251ff741d01b147146fffb6fb30f8a980ca157c2",
@@ -31,7 +31,7 @@
31
31
  "docs/best-practices.md": "aeaaa12d518233cb09577c1dbaee00d62cd26f9f7e0400c681fe38742d6a7ba2",
32
32
  "docs/ecosystem.md": "051520cefee38d34894ef563ab987be15dc47cc9172fc6692ee440a77fa1f2c0",
33
33
  "docs/engineering.md": "550528cd47c7d2c921729c68d0782a00ac8e77a4bdfec479f6749f9c3235d188",
34
- "docs/facts.json": "d370370218be4a0b8edc2dff38f6595dcf90879e546add18abac8a60b9c0f6b6",
34
+ "docs/facts.json": "58ed4849960aee5efe4cbbb66e576db5b077468e9bcb6f936bae4cbcba6fe51d",
35
35
  "docs/features.md": "927e5e54f7b1348ce2cddecb0d11115dc5ae9db20558b12d67932d38b26dad3f",
36
36
  "docs/performance.md": "bbf2f3922c25dcba0c1a9e69ef420e3871a729af5b35009a49b48a5d3c5cd151",
37
37
  "docs/recovery-guide.md": "1cc014295f8c8ffba1f1c44397b657e925f1bc0e4757217d6e69e8cfb271f3cb",
@@ -58,7 +58,7 @@
58
58
  "install/templates/codex-instructions.md": "dd78eb9553e725c039380457245793a5fc748ae37ebf5ccfe11be5ed5b9a4025",
59
59
  "install/templates/copilot-instructions.md": "18161f2a8c995044aeae69d47200795b8babcf8b80d5e09e8d91dcfb7c841ce2",
60
60
  "install/templates/multi-agent-autopilot.plist.template": "d79de637b17330e720be43b96bfcdd51797bd9ce219eafaa3dd5a8ece96e4814",
61
- "package.json": "e5a60cbc1e2626aeed503073d89f6db25873db661589d6dd813c5c8f1af90367",
61
+ "package.json": "0fab4746bdc36850af7a7e5900578ea934202f13e8bbe71831ab619a4e28c9a0",
62
62
  "pipeline/agents/android-architect.md": "baa5787b3a4c800dd065e27e05f44462927c9938c8bb676c80f18cb10e2b12c4",
63
63
  "pipeline/agents/backend-architect.md": "a83bd7f8b0a5289a1ef9a9b59d60fc759b8db260606ff2df427cf5ade5db8530",
64
64
  "pipeline/agents/bulk-reader.md": "0b9d415fab2c449d43329d759049af9401255d06b32d57a38c95e684837b19bf",
@@ -164,7 +164,7 @@
164
164
  "pipeline/lib/issue-fetcher.sh": "c496ad6b07c0f6c64c69cb6293a0a4f3010b3ce3945a525e602c0d51c665ac67",
165
165
  "pipeline/lib/jira-publish.sh": "a32e6a682ae730ddd9c6df64b9ece1fb73c797111c63f5c247d7e733668da6b7",
166
166
  "pipeline/lib/md2confluence-v3.py": "3677ca47931e4b3d0fd2ce3e11299fc5f6d24799eb8332e37dd60b6c3c4653a2",
167
- "pipeline/lib/model-dispatch.sh": "929b665bda7116da219cc9e0f3e0b17b1e73472482293d251803e35822c8daa0",
167
+ "pipeline/lib/model-dispatch.sh": "467ee01628c2a4a706410fdc7b04b0dd92ad2c2cbdd2150f6fd91f2d7a773796",
168
168
  "pipeline/lib/model-rung.sh": "befcd1a250a04f9ea9c8dca18c9d8905286330197e54da41ad4fd12b845f604d",
169
169
  "pipeline/lib/multi-repo-pipeline.sh": "392b06b4d40924b16a74d85dfceb68a5aeed8a50aed832a5ca92f27e2a5d7e80",
170
170
  "pipeline/lib/outbound-gate.mjs": "76547f21ca92793f4c59e1dbf91c498278614281607e3ecbeeddbafe7e3a6a56",
@@ -222,7 +222,7 @@
222
222
  "pipeline/multi-agent-refs/features/external-context-injection.md": "8fcf5229f92276af7714638602ec4da076f9f3f0a170303e3c1e178f55e39863",
223
223
  "pipeline/multi-agent-refs/features/jira-context.md": "6f6fe697451e061909aa125366defbcc0baae5cecd8341bfabbad09011256684",
224
224
  "pipeline/multi-agent-refs/features/maturity-followup.md": "2a6166869101b00ea273b92e3fe1ea07b375a0190aaab6b42ff5691db3748eec",
225
- "pipeline/multi-agent-refs/features/model-fallback.md": "fb982661127075930450cfff89857c892569e5068b60fab2fb59af2fc5613791",
225
+ "pipeline/multi-agent-refs/features/model-fallback.md": "7ac6a048c3ac2c494fbe03b027850703dba0995dc9dc0c63ceb14e0a8c8925b2",
226
226
  "pipeline/multi-agent-refs/features/package-manager.md": "b9e52f798f5dcba43abff1fe5cad8d5d5374058c9a6847c993975c665acab05a",
227
227
  "pipeline/multi-agent-refs/features/plan-todos.md": "8780d80b4541daee2b05080759a0694ef7e6270abe9a4621deb92ec7bac94e8e",
228
228
  "pipeline/multi-agent-refs/features/prior-fix-detection.md": "f194c444f1685bb103e1aa16164ca6737ba9910b7c8f89874924da950838b074",
@@ -320,7 +320,7 @@
320
320
  "pipeline/schemas/prefs.schema.json": "1a5e041385d251fb62fa39771ca0a357b9ce2270d39fe0b3dd84c9fc0f4c8f7b",
321
321
  "pipeline/schemas/review-file-exclusions.json": "2e8c44b45d21d2c82fc95aa2bf76ad3fbf2d5c68180c7b2ebf89c4a926688d77",
322
322
  "pipeline/schemas/reviewer-output.schema.json": "1bc8dd8feb416ea2101457e071d72b5a6ab0aefa7da3d42063bbe1c153755754",
323
- "pipeline/schemas/route-config.schema.json": "ddade61393ee7c2f5863ca26324af70a1d2153ef7221526878ea07a4d5c9b54c",
323
+ "pipeline/schemas/route-config.schema.json": "6f606926c257b7ad3d2972e53d0b772714774140c473b9cb8c7cd9e52731020f",
324
324
  "pipeline/schemas/scope-check.schema.json": "f96973c59372b36b7d68b9ac4b03490e7da8d54acf29a35947f5f610e82b98ea",
325
325
  "pipeline/schemas/secret-patterns.json": "d9a7bec7b2ba704b73f2302c3498874c6298cde69bde0f181932c282d3fe0b0e",
326
326
  "pipeline/schemas/skill-observation.schema.json": "05f16c6e5055ef99a102b12b578ba841251267d41dd7343f8ab66cd8070180ff",
@@ -480,7 +480,7 @@
480
480
  "pipeline/scripts/website-deploy-commit.sh": "523482438b265ca1f1883ec5fb450e803566a1239eaccdc423e12c5426140a84",
481
481
  "pipeline/scripts/worktree-finalize.sh": "f905ba69272d32afc75b5deb8406efabfe0865bdeec2e150a521d5a1b0c51b8a",
482
482
  "pipeline/scripts/write-state.mjs": "1367280057d2b747da55ba62af6f884a647f2675c0bde10c39dc68c84ff7daac",
483
- "pipeline/skills/.skill-manifest.json": "e1fa2300f9152fcbf1c8667ba0bc7cee5d0a8125a8e1e0f57d3fc98d2cb4aa35",
483
+ "pipeline/skills/.skill-manifest.json": "fc25b360a03932f8c5575e337cc476524d15c199fb6ff8e76b23fe3668267f22",
484
484
  "pipeline/skills/.skills-index.json": "05545f7603267576f614d6eedd0369bfcf5b8d1aadbf4c791295559f930b4bb2",
485
485
  "pipeline/skills/shared/README.md": "12692c36caaf2f4567cf21b788dad66e1bc34cae345dc8045e0569834b819414",
486
486
  "pipeline/skills/shared/core/apple-archive-compliance/SKILL.md": "6675a53441f2f3bedc82284998f402bd51fa251c7491a595e12c6c4016830337",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mmerterden/multi-agent-pipeline",
3
- "version": "19.1.2",
3
+ "version": "19.1.3",
4
4
  "description": "6-phase AI development pipeline with full orchestration on Claude Code, Copilot CLI and Codex CLI. Analysis, planning, TDD, CLI-aware parallel review with consensus surfacing + Fable triage, default-FAIL evidence gates, secret + intent guards, per-phase cost ledger, persistent learnings memory, wiki generation, commit automation. Token-preserving uninstall.",
5
5
  "type": "module",
6
6
  "main": "index.js",
@@ -22,10 +22,16 @@
22
22
  #
23
23
  # Layer 1 an Anthropic rung. Reachable from every call site, because it
24
24
  # writes to a seam that already exists and opens no new network path.
25
- # Layer 2 a non-Anthropic rung. Reachable ONLY from a call site the pipeline
26
- # makes itself. A subagent is dispatched by the HOST, so a rule that
27
- # prefers an external rung for a subagent cannot be honoured - and
28
- # this script says so on stderr rather than pretending it was.
25
+ # Layer 2 a non-Anthropic rung. NO call site can dispatch to one today, and
26
+ # the router refuses it rather than returning a rung its caller will
27
+ # hand to a CLI that does not know the name:
28
+ # - a subagent is dispatched by the HOST;
29
+ # - bulk-read shells out to `claude -p --model <rung>`;
30
+ # - research_ask runs in the MCP server and picks its own model.
31
+ # `provider` in cost-table.json is what makes this checkable, and it
32
+ # is the seam a future call site would use. Until one exists, the
33
+ # refusal is the honest answer: an allowed rung nothing can honour is
34
+ # a rule the user believes worked.
29
35
 
30
36
  set -uo pipefail
31
37
 
@@ -124,12 +130,12 @@ for rung in $MATCH; do
124
130
  echo "model-dispatch: rule prefers 'fable' but modelFallback.fableEnabled is false; skipping it" >&2
125
131
  continue
126
132
  fi
127
- if [ "$PROVIDER" != "anthropic" ] && [ "$CALL_SITE" = "subagent" ]; then
128
- # The honest limit, said out loud at the moment it bites. Subagent dispatch
129
- # belongs to the host; we cannot send one to another provider, and a router
130
- # that quietly downgraded to an Anthropic rung here would leave the user
131
- # believing a rule worked that never could.
132
- echo "model-dispatch: rung '$rung' is $PROVIDER and subagent dispatch belongs to the host; skipping it" >&2
133
+ if [ "$PROVIDER" != "anthropic" ]; then
134
+ # The honest limit, said out loud at the moment it bites. Every call site
135
+ # that asks here hands the rung to something that only speaks the Anthropic
136
+ # ladder, so returning an external rung would produce a failed call rather
137
+ # than a cheaper one.
138
+ echo "model-dispatch: rung '$rung' is $PROVIDER and no call site can dispatch to one yet; skipping it" >&2
133
139
  continue
134
140
  fi
135
141
  record "$rung" "rule matched"
@@ -193,13 +193,17 @@ Two limits are enforced by the script rather than written here and hoped for:
193
193
  - **A rule may not turn the fable rung on.** With `modelFallback.fableEnabled`
194
194
  false, a rule preferring `fable` falls past it to the next rung. Otherwise
195
195
  `/multi-agent:model off` would have a second door.
196
- - **A subagent stays inside the Anthropic ladder.** Subagent dispatch belongs to
197
- the host, so a rule preferring a non-Anthropic rung cannot be honoured there;
198
- the script says so on stderr and moves on rather than substituting an
199
- Anthropic rung and leaving the user believing a rule worked that never could.
200
- `bulk-read.sh` is a call site the pipeline makes itself, so the same rung IS
201
- allowed there. That asymmetry is why `/multi-agent:route-status` reports scope
202
- per call site instead of one on/off.
196
+ - **Every call site stays inside the Anthropic ladder.** No call site can
197
+ dispatch to another provider today: a subagent is dispatched by the host,
198
+ `bulk-read.sh` shells out to `claude -p --model <rung>`, and `research_ask`
199
+ runs in the MCP server and picks its own model. A rule preferring an external
200
+ rung falls to the next rung the rule named, and the script says why on stderr.
201
+ Returning the external rung instead would hand a caller a name it passes
202
+ straight to a CLI that does not know it - a failed call, not a cheaper one.
203
+ `provider` in `cost-table.json` is what makes the refusal checkable and is the
204
+ seam a future call site would use; `smoke-model-dispatch.sh` asserts that
205
+ `bulk-read.sh` still dispatches through the Anthropic CLI, so the day that
206
+ changes, the gate says the refusal may be lifted.
203
207
 
204
208
  The script never fails and never returns an empty rung: a missing preferences
205
209
  file, a missing `jq`, unparseable JSON, an out-of-scope call site and a rung
@@ -2,7 +2,7 @@
2
2
  "$schema": "https://json-schema.org/draft/2020-12/schema",
3
3
  "$id": "https://github.com/mmerterden/multi-agent-pipeline/pipeline/schemas/route-config.schema.json",
4
4
  "title": "Model routing configuration",
5
- "description": "Policy-driven model selection, OFF by default. Lives under prefs.global.modelRouting. Two layers, and the difference is the whole safety argument. Layer 1 chooses a rung INSIDE the Anthropic ladder and writes to the existing PHASE_MODEL_OVERRIDE seam - no new network path, no new account. Layer 2 sends a call to a non-Anthropic provider, and only at the call sites the pipeline makes itself (bulk-read.sh, research_ask), never at a call site the host owns. `scope` has no `host-session` member and that absence is enforced here rather than written in prose: rewriting the host's base URL would route the user's ENTIRE session, including work that has nothing to do with this pipeline, through a third layer - breaking the subscription's auth model and silently changing which model answers. Shipping this disabled is the same reasoning as modelFallback.fableEnabled: a cost control that is on by default is not a control.",
5
+ "description": "Policy-driven model selection, OFF by default. Lives under prefs.global.modelRouting. Two layers, and the difference is the whole safety argument. Layer 1 chooses a rung INSIDE the Anthropic ladder and writes to the existing PHASE_MODEL_OVERRIDE seam - no new network path, no new account. Layer 2 would send a call to a non-Anthropic provider, and no call site can do that yet: a subagent is dispatched by the host, bulk-read.sh shells out to `claude -p --model <rung>`, and research_ask runs in the MCP server and picks its own model. model-dispatch.sh therefore refuses a non-Anthropic rung everywhere and falls to the rule's next rung, because an allowed rung nothing can honour is a rule the user believes worked. `provider` in cost-table.json is the seam a future call site would use. `scope` has no `host-session` member and that absence is enforced here rather than written in prose: rewriting the host's base URL would route the user's ENTIRE session, including work that has nothing to do with this pipeline, through a third layer - breaking the subscription's auth model and silently changing which model answers. Shipping this disabled is the same reasoning as modelFallback.fableEnabled: a cost control that is on by default is not a control.",
6
6
  "type": "object",
7
7
  "additionalProperties": false,
8
8
  "required": ["enabled"],
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "schemaVersion": "1.0.0",
3
- "generatedAt": "2026-09-20T20:46:21Z",
3
+ "generatedAt": "2026-09-21T06:17:16Z",
4
4
  "skillCount": 216,
5
5
  "entries": [
6
6
  {