@mmerterden/multi-agent-pipeline 16.4.0 → 16.5.0
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
|
@@ -16,6 +16,20 @@ Internal file-layout changes that don't affect the slash-command surface are sti
|
|
|
16
16
|
|
|
17
17
|
## [Unreleased]
|
|
18
18
|
|
|
19
|
+
## [16.5.0] - 2026-08-25
|
|
20
|
+
|
|
21
|
+
Staying current stops being something a user has to be told to do.
|
|
22
|
+
|
|
23
|
+
### Changed
|
|
24
|
+
|
|
25
|
+
- **`updateCheck.autoUpdate` now defaults to `true`.** A newer version is installed before the run starts, in interactive modes and autopilot alike, instead of asking once per `ttlHours`. The old default made "be current" opt-in, which in practice meant a maintainer telling people to run a command - and since v15.14 the Supported Version Gate already halts any install below the `required` floor, so the real choice was never "update or not", it was "update, or be stopped and told to update". `autoUpdate: false` restores the question; `updateCheck.enabled: false` silences the advisory check (neither disables the required floor, whose only override remains `MULTI_AGENT_ALLOW_OUTDATED=1`). Docs already loaded finish the current run on the old version; the update takes full effect on the next run.
|
|
26
|
+
- **The MCP server is registered as `@latest`.** The registration was the bare package name, so `npx` reused any cached copy: a machine that had cached toolkit 3.0.0 kept starting 3.0.0 after 3.1.0 was published and tagged `latest`. The new tool existed on the registry and in the docs, and in no running server. Measured, not assumed - the npx cache held exactly `3.0.0` while `latest` was `3.1.0`. The cost is a registry round-trip when the server starts, and an offline start now depends on what npx can resolve rather than on any cached version being present: a stale server is a silent wrong answer, a failed start is a loud one.
|
|
27
|
+
- **Registration is rewritten on every install and update, not skipped when present.** The installer treated "already registered" as done and left the stored args alone, so an existing install would have kept the bare spec forever and the `@latest` change would have reached new installs only. The current entry is now removed before the add, exactly as the pre-rename entry already was. A host that refuses the remove is reported as possibly-stale with the manual command, rather than counted as a clean registration.
|
|
28
|
+
|
|
29
|
+
### Fixed
|
|
30
|
+
|
|
31
|
+
- Two comments in `install/_mcp-register.mjs` and one in `smoke-npm-scope-pinning.sh` still said 83 tools / `MCP_SERVER_PACKAGE`; the toolkit serves 84 and the registration builds from `MCP_SERVER_SPEC`.
|
|
32
|
+
|
|
19
33
|
## [16.4.0] - 2026-08-24
|
|
20
34
|
|
|
21
35
|
Two default changes are worth reading before upgrading. `/multi-agent:analysis`
|
package/docs/features.md
CHANGED
|
@@ -173,7 +173,7 @@ Existing tests are immutable during a task: deleting, renaming, or weakening an
|
|
|
173
173
|
|
|
174
174
|
Phase 0 Step 0.6. Once per `ttlHours` window (cached, 3s-bounded curl to the npm registry), the installed version is compared against two dist-tags.
|
|
175
175
|
|
|
176
|
-
**`latest` -
|
|
176
|
+
**`latest` - automatic**, since v16.5.0. `prefs.global.updateCheck.autoUpdate` defaults to `true`: a newer version is installed before the run starts, in interactive modes and autopilot alike, and the run continues. Set `autoUpdate: false` to be asked once per `ttlHours` instead, or `updateCheck.enabled: false` to silence the check (neither disables the required-version floor).
|
|
177
177
|
|
|
178
178
|
**`required` - blocking** (v15.14.0+). Most releases do not publish this tag and nothing changes for them. A release that changed a contract a run depends on is promoted with `npm dist-tag add <pkg>@<version> required`, and an install below that floor is not behind, it is wrong: `require-supported-version.sh` exits 3, the run halts, `/multi-agent:update` runs, and the user re-issues the command on the new version rather than continuing on docs already loaded from the old one. Interactive and autopilot behave identically. The gate fails open on every undeterminable answer (offline, blocked registry, no tag), `updateCheck.enabled: false` does not disable it, and the single override is the env var `MULTI_AGENT_ALLOW_OUTDATED=1`, which is logged in the run record. Exemptions: `update`, `setup`, `uninstall`, `help`, `status`, `log`, `search`, `routines`, `forget`, `language`.
|
|
179
179
|
|
|
@@ -31,6 +31,22 @@ import { isDryRun } from "./_common.mjs";
|
|
|
31
31
|
export const MCP_SERVER_NAME = "multi-agent-toolkit";
|
|
32
32
|
export const MCP_SERVER_PACKAGE = "@mmerterden/multi-agent-toolkit-mcp";
|
|
33
33
|
|
|
34
|
+
/**
|
|
35
|
+
* The spec the host is registered with. `@latest` is deliberate and it is the
|
|
36
|
+
* difference between "the toolkit was published" and "the toolkit is running".
|
|
37
|
+
*
|
|
38
|
+
* Measured before this was added: the registration was the bare package name,
|
|
39
|
+
* npx found ANY cached version and reused it, and a machine that had cached
|
|
40
|
+
* 3.0.0 kept starting 3.0.0 after 3.1.0 was published and tagged `latest`. The
|
|
41
|
+
* new tool existed on the registry and in the docs, and in no running server.
|
|
42
|
+
*
|
|
43
|
+
* The cost is a registry round-trip when the MCP server starts, and an offline
|
|
44
|
+
* start now depends on what npx can resolve from its cache rather than on a
|
|
45
|
+
* cached version being present at all. That trade was made explicitly: a stale
|
|
46
|
+
* server is a silent wrong answer, a failed start is a loud one.
|
|
47
|
+
*/
|
|
48
|
+
export const MCP_SERVER_SPEC = `${MCP_SERVER_PACKAGE}@latest`;
|
|
49
|
+
|
|
34
50
|
/**
|
|
35
51
|
* The registry the package is published to, pinned BY SCOPE.
|
|
36
52
|
*
|
|
@@ -44,7 +60,7 @@ export const MCP_SERVER_PACKAGE = "@mmerterden/multi-agent-toolkit-mcp";
|
|
|
44
60
|
*
|
|
45
61
|
* So `npx` fetched from the wrong registry, the package was not there, the
|
|
46
62
|
* process never started, and the host reported `CONNECTION_CLOSED` - a server
|
|
47
|
-
* that works perfectly when run directly (
|
|
63
|
+
* that works perfectly when run directly (84 tools) looked broken.
|
|
48
64
|
*
|
|
49
65
|
* `--registry` does NOT fix this: a scope mapping outranks it. The scope itself
|
|
50
66
|
* has to be pinned, which is why the flag below is built from the package name
|
|
@@ -64,7 +80,7 @@ export function scopeRegistryFlag(pkg = MCP_SERVER_PACKAGE, registry = MCP_REGIS
|
|
|
64
80
|
* A host keys its registration by name, so renaming does NOT upgrade an entry in
|
|
65
81
|
* place: without this, an existing install ends up with both `dev-toolkit`
|
|
66
82
|
* (pointing at the old package, still resolvable, now frozen at 2.26.0) and
|
|
67
|
-
* `multi-agent-toolkit`. Two servers advertising the same
|
|
83
|
+
* `multi-agent-toolkit`. Two servers advertising the same 84 tools is worse than
|
|
68
84
|
* either alone - the host has to pick, and which one it picks is not something
|
|
69
85
|
* the pipeline controls. Registration removes the legacy entry first.
|
|
70
86
|
*/
|
|
@@ -152,7 +168,7 @@ function saysAlreadyExists(text) {
|
|
|
152
168
|
export function registerMcpServer(host, label) {
|
|
153
169
|
const cli = resolveCli(host);
|
|
154
170
|
const scopeArgs = HOSTS[host]?.scopeArgs || [];
|
|
155
|
-
const npxArgs = ["-y", ...scopeRegistryFlag(),
|
|
171
|
+
const npxArgs = ["-y", ...scopeRegistryFlag(), MCP_SERVER_SPEC];
|
|
156
172
|
const manual = `${host} mcp add ${scopeArgs.join(" ")}${scopeArgs.length ? " " : ""}${MCP_SERVER_NAME} -- npx ${npxArgs.join(" ")}`;
|
|
157
173
|
|
|
158
174
|
if (isDryRun()) {
|
|
@@ -182,6 +198,24 @@ export function registerMcpServer(host, label) {
|
|
|
182
198
|
/* not present, or the host declines - either way the add below is what matters */
|
|
183
199
|
}
|
|
184
200
|
|
|
201
|
+
// Drop the CURRENT entry too, so the add below rewrites its spec. Without this
|
|
202
|
+
// the host answers "already exists", the installer reported success, and the
|
|
203
|
+
// stored args stayed whatever an older version wrote - which is how a machine
|
|
204
|
+
// kept starting the toolkit from a bare package name (and therefore from
|
|
205
|
+
// whatever npx had cached) long after the spec gained `@latest`. The entry is
|
|
206
|
+
// installer-owned, so replacing it is not clobbering a user's work; a host
|
|
207
|
+
// that refuses the remove is reported below rather than counted as current.
|
|
208
|
+
let replacedExisting = false;
|
|
209
|
+
try {
|
|
210
|
+
execFileSync(cli, ["mcp", "remove", ...scopeArgs, MCP_SERVER_NAME], {
|
|
211
|
+
stdio: "pipe",
|
|
212
|
+
timeout: 20_000,
|
|
213
|
+
});
|
|
214
|
+
replacedExisting = true;
|
|
215
|
+
} catch {
|
|
216
|
+
/* not registered yet - the common case on a fresh install */
|
|
217
|
+
}
|
|
218
|
+
|
|
185
219
|
try {
|
|
186
220
|
// Bounded: an installer must never hang on a child process. This is a local config
|
|
187
221
|
// write and returns in milliseconds.
|
|
@@ -193,10 +227,18 @@ export function registerMcpServer(host, label) {
|
|
|
193
227
|
// Claude Code refuses a duplicate on the SUCCESS path (exit 0), so the check
|
|
194
228
|
// cannot live in the catch alone.
|
|
195
229
|
if (saysAlreadyExists(stdout?.toString() ?? "")) {
|
|
196
|
-
|
|
197
|
-
|
|
230
|
+
// Reached only when the remove above did not take. The entry survives, but
|
|
231
|
+
// its spec is whatever was there before, so this is not a current
|
|
232
|
+
// registration - say that instead of reporting a clean pass.
|
|
233
|
+
console.log(
|
|
234
|
+
` -> ${label}: ${MCP_SERVER_NAME} already registered and the host declined to replace it; ` +
|
|
235
|
+
`its spec may predate ${MCP_SERVER_SPEC}. Re-register manually with: ${manual}`,
|
|
236
|
+
);
|
|
237
|
+
return { registered: true, alreadyPresent: true, staleSpec: true };
|
|
198
238
|
}
|
|
199
|
-
console.log(
|
|
239
|
+
console.log(
|
|
240
|
+
` -> ${label}: ${replacedExisting ? "re-registered" : "registered"} the ${MCP_SERVER_NAME} MCP server (${MCP_SERVER_SPEC})`,
|
|
241
|
+
);
|
|
200
242
|
return { registered: true };
|
|
201
243
|
} catch (e) {
|
|
202
244
|
// The CLI writes its diagnosis to stderr, which execFileSync parks on the error
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@mmerterden/multi-agent-pipeline",
|
|
3
|
-
"version": "16.
|
|
3
|
+
"version": "16.5.0",
|
|
4
4
|
"description": "8-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",
|
|
@@ -118,8 +118,8 @@ Run `bash $HOME/.claude/scripts/update-check.sh` (cached per `updateCheck.ttlHou
|
|
|
118
118
|
|
|
119
119
|
**Advisory branch (never blocks).**
|
|
120
120
|
|
|
121
|
-
- **Interactive**:
|
|
122
|
-
- **Autopilot**: never ask (zero-interaction contract).
|
|
121
|
+
- **Interactive**: `updateCheck.autoUpdate` defaults to `true`, so do not ask - run the `/multi-agent:update` flow, log `→ updated to v<latest>`, continue (docs already loaded finish this run on the old version; full effect next run). Only `autoUpdate: false` makes it a question: log `→ update available: v<local> -> v<latest>`, ask ONE AskUserQuestion - **Update now** (recommended) / **Continue without updating**; on *Continue*, no re-ask until the TTL expires.
|
|
122
|
+
- **Autopilot**: never ask (zero-interaction contract). On the default it updates first, logging `→ updated to v<latest>`; on `autoUpdate: false` it is log-only and continues.
|
|
123
123
|
|
|
124
124
|
Both branches must run BEFORE Step 6 (worktree creation) so an accepted or forced update cannot mutate `~/.claude` under a mid-phase run.
|
|
125
125
|
|
|
@@ -840,8 +840,8 @@
|
|
|
840
840
|
},
|
|
841
841
|
"autoUpdate": {
|
|
842
842
|
"type": "boolean",
|
|
843
|
-
"default":
|
|
844
|
-
"description": "
|
|
843
|
+
"default": true,
|
|
844
|
+
"description": "Run the update flow automatically before the run starts, in interactive modes and autopilot alike, instead of asking. ON by default since v16.5.0: the alternative was telling every user to run a command, and the Supported Version Gate already halts an install below the required floor - so the real choice was never 'update or not', it was 'update, or stop and be told to update'. Set false to be asked once per ttlHours instead; updateCheck.enabled: false silences the check entirely (it does not disable the required floor). Already-loaded phase docs finish the current run on the old version either way; the update takes full effect on the next run."
|
|
845
845
|
}
|
|
846
846
|
}
|
|
847
847
|
},
|