@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 +24 -0
- package/docs/facts.json +2 -2
- package/manifest.json +10 -10
- package/package.json +1 -1
- package/pipeline/lib/model-dispatch.sh +16 -10
- package/pipeline/multi-agent-refs/features/model-fallback.md +11 -7
- package/pipeline/schemas/route-config.schema.json +1 -1
- package/pipeline/skills/.skill-manifest.json +1 -1
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-
|
|
4
|
-
"version": "19.1.
|
|
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.
|
|
4
|
-
"commit": "
|
|
5
|
-
"generatedAt": "2026-09-
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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": "
|
|
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.
|
|
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.
|
|
26
|
-
#
|
|
27
|
-
#
|
|
28
|
-
#
|
|
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" ]
|
|
128
|
-
# The honest limit, said out loud at the moment it bites.
|
|
129
|
-
#
|
|
130
|
-
#
|
|
131
|
-
#
|
|
132
|
-
echo "model-dispatch: rung '$rung' is $PROVIDER and
|
|
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
|
-
- **
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
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
|
|
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"],
|