mcp-pacemaker 2.0.2 → 2.1.1

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 (90) hide show
  1. package/CHANGELOG.md +171 -1
  2. package/CONTRIBUTING.md +46 -13
  3. package/README.md +109 -524
  4. package/THIRD_PARTY_NOTICES.txt +1 -28
  5. package/autostart/windows/account-task.ps1 +167 -0
  6. package/autostart/windows/inspect-task.ps1 +42 -0
  7. package/autostart/windows/inspect-worker-process-sessions.ps1 +155 -0
  8. package/autostart/windows/legacy-access.ps1 +359 -0
  9. package/autostart/windows/legacy-task.ps1 +301 -0
  10. package/autostart/windows/register-task.ps1 +11 -2
  11. package/bin/account-task-adapter.mjs +47 -0
  12. package/bin/account-upgrade-controller.mjs +198 -0
  13. package/bin/account-upgrade-worker.mjs +141 -0
  14. package/bin/account-worker-session.mjs +215 -0
  15. package/bin/cli-dispatch.mjs +154 -0
  16. package/bin/cli-main.mjs +1063 -0
  17. package/bin/cli-selection.mjs +43 -0
  18. package/bin/cli.mjs +7 -876
  19. package/bin/dependency-lock.json +642 -0
  20. package/bin/legacy-1.3.json +32 -0
  21. package/bin/legacy-access.mjs +73 -0
  22. package/bin/legacy-installation.mjs +273 -0
  23. package/bin/legacy-task.mjs +76 -0
  24. package/bin/legacy-upgrade.mjs +527 -0
  25. package/bin/managed-runtime.mjs +170 -0
  26. package/bin/managed-state.mjs +257 -0
  27. package/bin/managed-upgrade.mjs +581 -0
  28. package/bin/mcp-bridge.mjs +150 -4
  29. package/bin/pooling-batches.mjs +13 -0
  30. package/bin/pooling-writer.mjs +4 -0
  31. package/bin/prewarm.mjs +59 -25
  32. package/bin/runtime-context.mjs +100 -0
  33. package/bin/service-control.mjs +32 -4
  34. package/bin/stable-launcher.mjs +54 -0
  35. package/bin/task-only-controller.mjs +226 -0
  36. package/bin/task-scope.mjs +65 -0
  37. package/bin/task-transaction-protocol.mjs +173 -0
  38. package/bin/top.mjs +22 -10
  39. package/bin/update-check.mjs +13 -2
  40. package/bin/upgrade-autostart.mjs +47 -0
  41. package/bin/upgrade-capability.json +9 -0
  42. package/bin/upgrade-dependencies.mjs +183 -0
  43. package/bin/upgrade-package.mjs +205 -0
  44. package/bin/windows-legacy/LegacyProcessBroker.build.json +42 -0
  45. package/bin/windows-legacy/LegacyProcessBroker.exe +0 -0
  46. package/bin/windows-legacy/src/AssemblyInfo.cs +8 -0
  47. package/bin/windows-legacy/src/LegacyNative.cs +832 -0
  48. package/bin/windows-legacy/src/LegacyProcessBroker.cs +961 -0
  49. package/bin/windows-legacy-process.mjs +248 -0
  50. package/bin/windows-lifetime/ProcessLifetimeHelper.build.json +38 -0
  51. package/bin/windows-lifetime/ProcessLifetimeHelper.exe +0 -0
  52. package/bin/windows-lifetime/src/AssemblyInfo.cs +8 -0
  53. package/bin/windows-lifetime/src/ProcessLifetimeHelper.cs +468 -0
  54. package/bin/windows-process-lifetime.mjs +218 -0
  55. package/bin/windows-task-channel/TaskChannelGuard.build.json +45 -0
  56. package/bin/windows-task-channel/TaskChannelGuard.exe +0 -0
  57. package/bin/windows-task-channel/src/AssemblyInfo.cs +8 -0
  58. package/bin/windows-task-channel/src/ChannelCliContext.cs +210 -0
  59. package/bin/windows-task-channel/src/ChannelFiles.cs +231 -0
  60. package/bin/windows-task-channel/src/ChannelNative.cs +477 -0
  61. package/bin/windows-task-channel/src/ChannelSession.cs +203 -0
  62. package/bin/windows-task-channel/src/TaskChannelGuard.cs +686 -0
  63. package/bin/windows-task-channel.mjs +335 -0
  64. package/docs/account-upgrades.md +218 -0
  65. package/docs/compatibility.md +39 -0
  66. package/docs/configuration.md +146 -0
  67. package/docs/dashboards.md +125 -0
  68. package/docs/execution-context.md +119 -0
  69. package/docs/http-api.md +47 -0
  70. package/docs/install.md +52 -0
  71. package/docs/operations.md +99 -0
  72. package/docs/upgrades.md +324 -0
  73. package/package.json +19 -5
  74. package/supervisor/supervise.mjs +226 -40
  75. package/tools/account-upgrade/qualify-two-account.ps1 +66 -0
  76. package/tools/windows-legacy/README.md +251 -0
  77. package/tools/windows-legacy/build.ps1 +122 -0
  78. package/tools/windows-legacy/inventory.mjs +92 -0
  79. package/tools/windows-process-lifetime/README.md +119 -0
  80. package/tools/windows-process-lifetime/build.ps1 +122 -0
  81. package/tools/windows-process-lifetime/inventory.mjs +86 -0
  82. package/tools/windows-task-channel/README.md +329 -0
  83. package/tools/windows-task-channel/build.ps1 +107 -0
  84. package/tools/windows-task-channel/inventory.mjs +117 -0
  85. package/ui/dist/THIRD_PARTY_NOTICES.txt +1 -28
  86. package/ui/dist/assets/{index-CgPruWYi.js → index-CcwMo2sI.js} +1 -1
  87. package/ui/dist/assets/index-PVcuDNrN.css +1 -0
  88. package/ui/dist/index.html +2 -2
  89. package/ui/dist/third-party-manifest.json +37 -25
  90. package/ui/dist/assets/index-CaLPg0c-.css +0 -1
package/CHANGELOG.md CHANGED
@@ -7,7 +7,172 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7
7
 
8
8
  ## [Unreleased]
9
9
 
10
- Target release: **2.0.2**. This candidate has not yet been published.
10
+ ## [2.1.1] - 2026-10-15
11
+
12
+ ### Added
13
+
14
+ - `upgrade --fix-legacy-access` is a one-time step for a Windows 1.3 install that was set up from
15
+ an administrator terminal. Run it from an administrator terminal. It gives the task's own
16
+ run-as user full control of that 1.3 task and makes that user the owner of the 1.3
17
+ `bin\cli.mjs`, and it records the previous permissions in
18
+ `legacy-upgrade\access-<time>.json` first. Nothing else changes: the task XML, triggers,
19
+ run-as account and run level, the other permission entries and the file contents stay the
20
+ same and are checked afterwards. `--plan` shows the change without making it.
21
+ - The Windows release qualification can resume after a failed or killed run with
22
+ `--resume RUN_DIRECTORY`. Each run records its inputs, controller, Docker engine, Windows
23
+ build and passed steps in `run-state.json`. A resume refuses any change to those or to the
24
+ kept evidence, sets the failed attempt aside next to the run and reruns only the steps that
25
+ did not pass. The offline verifier checks the recorded history; the published regression
26
+ statement is unchanged.
27
+
28
+ ### Fixed
29
+
30
+ - Upgrading a Windows 1.3 install that was set up from an administrator terminal no longer fails
31
+ part-way. Windows makes Administrators the owner of that task and lets your account only read
32
+ it, and makes Administrators the owner of the files, so the upgrade, which must run as an
33
+ ordinary user, was refused while copying the CLI file and would then have failed while holding
34
+ the task. Planning now checks these permissions first and stops before any process capture,
35
+ download or change. It names each item and the fix. Installs set up from a normal terminal
36
+ are unaffected.
37
+ - `upgrade --to` from an elevated terminal is now refused before planning and before any
38
+ confirmation prompt, with the normal-terminal next step. It used to ask for the restart
39
+ confirmation first and refuse afterwards.
40
+ - Managed upgrades no longer fail behind npm mirrors that publish only SHA-1 checksums, such as
41
+ some Azure Artifacts upstreams. Each release now carries the SHA-512 dependency lock it was
42
+ released and tested with (`bin/dependency-lock.json`, declared by `dependencyLock` in
43
+ `bin/upgrade-capability.json`), and staging installs exactly that lock with `npm ci` through
44
+ your configured registry, including when `replace-registry-host` is `never`.
45
+ Staged dependencies no longer move to newer in-range versions at upgrade time. Targets without
46
+ the lock keep the old resolution, and an entry without SHA-512 integrity now names the package.
47
+ - The Windows legacy process broker now waits up to eight seconds instead of two for each WMI
48
+ command-line query, and reports the first real failure instead of a generic
49
+ `Argument query cancelled`. A WMI timeout is reported as `Argument query timed out`. On a busy
50
+ host with about 1,000 processes the two-second limit made legacy planning fail.
51
+ - `reload` no longer reports a slow bridge as `bridge DOWN`. The bridge may spend its whole
52
+ pooling budget settling a pending batch before it answers, but the CLI gave up after five
53
+ seconds. It now waits past that budget and reports a late answer as a timeout. Status
54
+ checks wait ten seconds instead of two before treating a bridge as down. A refused
55
+ connection still fails at once.
56
+ - Upgrading a busy Windows 1.3 install no longer fails. The legacy process broker put every
57
+ process under the 1.3 bridge into the plan and refused when that list changed, but a busy
58
+ bridge starts and ends a session process every few seconds. It also refused any install
59
+ with more than 512 such processes (one had 533), and the upgrade refused whenever 1.3
60
+ rewrote `sessions.json`, which it does on every session start and end. The plan now holds
61
+ only the supervisor and the bridge. The stop ends the supervisor, holds a handle to every
62
+ process under the bridge, ends the bridge, and then stops everything it holds plus anything
63
+ those processes started, up to 2048 processes. Holding them first matters: Node ends a
64
+ process's direct children with it, and 1.3 runs each bare server command under `cmd.exe`,
65
+ so ending the bridge first would have left those servers running with no traceable parent.
66
+ A process it cannot stop is reported and left running instead of blocking the upgrade.
67
+ Capture and revalidation also get 120 seconds from the request instead of 14 to 15 seconds
68
+ from the broker's start, which a loaded host could use up before the capture began.
69
+ - A 1.3 upgrade started from inside the 1.3 tree, for example through an MCP server's shell,
70
+ is now refused before anything changes. It would have stopped itself part-way.
71
+ - A managed upgrade no longer refuses because a client is connected. The bridge counted every
72
+ open session as active work and refused after eight seconds, and once any client had dropped
73
+ a stream it refused every later upgrade until it restarted. Each refusal also left the bridge
74
+ answering 503 until `upgrade --recover`. Now calls in progress and config work get up to
75
+ eight seconds to finish, and open sessions and calls still running end with the restart.
76
+ Config work still unfinished then refuses the upgrade, and the upgrader resumes the current
77
+ version, trying for up to ten seconds while that work settles. A session that starts or ends
78
+ during the download no longer fails the upgrade either; only `servers.json` must be
79
+ unchanged. The installed version runs an upgrade, so this applies to upgrades from 2.1.1 on.
80
+ To upgrade from 2.1.0, close your MCP clients and restart Pacemaker first.
81
+ - `prewarm` no longer crashes on Windows with
82
+ `Assertion failed: !(handle->flags & UV_HANDLE_CLOSING)` after the bridge refuses a change. It
83
+ prints the refusal and exits with status 1. Node 23, 24 before 24.20.0, 25, and 26 before
84
+ 26.7.0 can abort a process that exits soon after `fetch`
85
+ ([nodejs/node#56645](https://github.com/nodejs/node/issues/56645)), so `prewarm` now talks to
86
+ the bridge with `node:http` like the rest of the CLI. A bridge that does not answer within ten
87
+ seconds is now reported by port instead of as `The operation was aborted due to timeout`.
88
+
89
+ ### Changed
90
+
91
+ - Upgrades now follow one written rule: an upgrade may end open sessions and calls in progress,
92
+ and never retries a call; it never changes `servers.json` or your client setup. See
93
+ [upgrades and rollback](docs/upgrades.md#what-an-upgrade-keeps-and-what-it-ends).
94
+ - The Windows 1.3 upgrade accepts `--yes` to confirm the plan shown, like other upgrades, and
95
+ its confirmation now says what ends and what is kept. It used to require an interactive
96
+ terminal and ask you to pause callers first. Explicit-account (`--user`) upgrades still need
97
+ interactive confirmation, because they also create a task for that account.
98
+ - Split the Windows release qualification into a contained lane and a host session lane.
99
+ The qualification container has no interactive logon, so it now verifies the
100
+ `source-ordinary` contract and defers the four session-bound test files; those files run
101
+ on the publishing host under an ordinary, non-elevated interactive account and produce a
102
+ `session-lane.json` receipt that the offline verifier requires, bound to the same commit.
103
+ This closes a gap where those four files ran in no automated lane.
104
+
105
+ ## [2.1.0] - 2026-10-12
106
+
107
+ Published to npm on 2026-10-14.
108
+
109
+ ### Added
110
+
111
+ - Explicit managed `upgrade --to`, read-only plans, isolated `--sxs` instances with
112
+ retained OS-assigned listeners, stable launchers, admission control and a durable
113
+ activation/recovery journal. Bare `upgrade` and `--self` remain compatible.
114
+ - Preserve ports and host wiring during managed replacement; retain the previous
115
+ package and restrict rollback to verified, unchanged pre-admission state.
116
+ - Add one-time restart-only migration for the exact Windows 1.3.0 registration,
117
+ with interactive uncertainty acknowledgement, held process identities, partial
118
+ observed-descendant receipts and scoped task/CLI rollback. No machine reboot.
119
+ - Refuse unsupported or unknown supervisor/autostart identities before interruption.
120
+ - Add explicit Windows original-account upgrades with a task-only administrator
121
+ controller and authenticated original-user worker. Keep current-user scope as
122
+ the default, preserve task security/account settings, and refuse unavailable or
123
+ changed logged-on session identity. Real elevated two-account qualification
124
+ remains required; `--all-users` is unsupported.
125
+
126
+ ### Fixed
127
+
128
+ - Contain Windows bridge descendants in a kill-on-close Job Object before any
129
+ workload starts, preventing nested cmd/Node trees from surviving abrupt bridge
130
+ loss. Fail startup if containment cannot be established.
131
+ - Preserve existing task security during legacy migration instead of resubmitting
132
+ its owner, allowing an ordinary user to update an eligible Administrators-owned
133
+ task without changing its permissions.
134
+ - Handle Task Scheduler's equivalent XML serialization during post-write checks
135
+ and restoration, including rediscovery after rollback. Keep raw revision
136
+ preconditions, original backups and complete resource-security checks intact.
137
+ - Avoid Windows upgrade-authorization failures caused by slow thread enumeration
138
+ and already-terminated thread records while retaining complete identity and
139
+ authority checks.
140
+ - Capture larger legacy process trees with bounded discovery and distinguish
141
+ reused parent PIDs from proven descendant relationships.
142
+ - Recheck shared-session test cooldown deadlines after early timer delivery before
143
+ acquiring a replacement generation.
144
+ - Wait for the metrics test process and its stdio to close before removing fixture files.
145
+ - Pin the Windows process-lifetime and task-channel helpers to their own packaged directory
146
+ instead of inheriting the caller's working directory. A process's working directory cannot
147
+ be removed on Windows, so a detached helper previously blocked removal of the instance,
148
+ configuration and staging directories with `EPERM`.
149
+ - Report the native refusal reason when the task channel declines a request, instead of a
150
+ bare refusal with no cause.
151
+
152
+ ### Security
153
+
154
+ - Refuse elevated or unverified default Windows upgrade and recovery before
155
+ staging, task writes or runtime launch, preserving the original runtime authority.
156
+ - Raise the CLI's `smol-toml` floor to `1.9.0`.
157
+ - Move the dashboard build to Tailwind CSS `4.3.3`, removing the vulnerable
158
+ `braces` and `postcss-selector-parser` dependency paths, and pin `source-map-js`
159
+ to `1.2.2`.
160
+ - Retire the 2.0.2 producer exception from fresh native and OSV scans. New releases
161
+ require complete clean producer evidence; historical receipts retain their
162
+ original source bindings and expiry.
163
+
164
+ ### Changed
165
+
166
+ - **Breaking for privileged callers.** The bridge, supervisor and default upgrades now verify
167
+ the caller before any runtime work and refuse an elevated or root caller at startup with
168
+ `User-runtime execution refused: …`. This is not Windows-only and not upgrade-only: on Linux
169
+ and macOS a `root` process is refused, which includes the default user in most container
170
+ images. There is no override; run as an ordinary account. Shipping this in a minor release is
171
+ deliberate — the previous behaviour let a bridge run with authority it could not verify.
172
+ - Update the Tailwind PostCSS adapter, class-merging dependency, generated dashboard
173
+ assets and license attribution while retaining the existing theme configuration.
174
+
175
+ ## [2.0.2] - 2026-10-06
11
176
 
12
177
  ### Fixed
13
178
 
@@ -475,6 +640,11 @@ one is a trap for anyone building something similar.
475
640
  - Do not report a teardown the bridge initiated as a crash. `taskkill /F` exits non-zero, so
476
641
  every recycle, idle reap and session close was recorded as a failure, burying real ones.
477
642
 
643
+ [Unreleased]: https://github.com/girishkvs/mcp-pacemaker/compare/v2.1.1...HEAD
644
+ [2.1.1]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v2.1.1
645
+ [2.1.0]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v2.1.0
646
+ [2.0.2]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v2.0.2
647
+ [2.0.1]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v2.0.1
478
648
  [2.0.0]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v2.0.0
479
649
  [1.3.0]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v1.3.0
480
650
  [1.2.0]: https://github.com/girishkvs/mcp-pacemaker/releases/tag/v1.2.0
package/CONTRIBUTING.md CHANGED
@@ -18,12 +18,16 @@ part of its security posture. The setup CLI and the dashboard may use dependenci
18
18
 
19
19
  ## Lockfiles must resolve to the public registry
20
20
 
21
- CI fails any lockfile containing a `resolved` URL outside `registry.npmjs.org`. If you work
22
- behind a private mirror, re-resolve before committing:
21
+ CI fails any lockfile containing a `resolved` URL outside `registry.npmjs.org`.
22
+ Do not bypass a required registry policy to produce those URLs. Restore through the
23
+ approved registry and preserve exact package names, versions and verified archive
24
+ integrities when canonicalizing mirror-specific URLs for the public lockfile.
25
+ Hosted CI must still restore the resulting lock from its configured registry.
23
26
 
24
- ```bash
25
- npm install --registry https://registry.npmjs.org
26
- ```
27
+ For npm 12 mirrors whose metadata and tarball URLs have different prefixes,
28
+ `replace-registry-host` supports command-local URL-prefix mapping back through the
29
+ approved registry. This does not require relaxing `allow-remote`, disabling TLS,
30
+ changing global settings or committing a private registry configuration.
27
31
 
28
32
  ## Tests
29
33
 
@@ -35,8 +39,13 @@ Tests are `node:test` only, no framework. Each test file that starts a bridge ow
35
39
  ports, because files run in parallel; the current allocation is listed at the top of
36
40
  `test/auth-token.test.mjs`. Pick unused ones for a new file.
37
41
 
38
- Before submitting, run the complete `npm test` command with its normal file concurrency.
39
- Focused or serialized runs help diagnose failures but do not replace that run. Record the
42
+ Before submitting, run the complete `npm test` command with its normal file concurrency
43
+ (`--test-concurrency=4`, matching the four vCPUs on hosted runners). CI and the local
44
+ publication gate go through `npm run test:contract -- <name>` instead, which adds the
45
+ execution-context preflight and, on Windows, splits the suite into the ordinary-account lane
46
+ and the session lane; `npm run test:contract -- source --check` reports what a lane would run
47
+ without running it. Focused or serialized runs help diagnose failures but do not replace that
48
+ run. Record the
40
49
  exact Node and npm versions, OS, architecture, and command; matching only the Node major is
41
50
  not enough to reproduce a CI failure.
42
51
 
@@ -63,6 +72,14 @@ platform; Windows also exercises the real executable. Those checks do not replac
63
72
  byte-for-byte rebuild, and a rolling CI image may not contain the recorded compiler.
64
73
  No compiler or PowerShell host runs in the production config-write path.
65
74
 
75
+ Windows bridge lifetime containment uses a **separate** packaged helper. Build
76
+ and byte-for-byte verify it with `tools/windows-process-lifetime/build.ps1` and
77
+ `-Verify`; see its README for the ownership and failure contract. Do not change
78
+ the immutable config-security helper to update the lifetime helper. Run both
79
+ `test/windows-process-lifetime.test.mjs` and `test/windows-lifetime-startup.test.mjs`
80
+ on supported Windows/Node versions. They retain owned PID/creation-time cleanup
81
+ receipts and TCP heartbeat observations outside Git.
82
+
66
83
  Batch tests must cover the full five-second trailing debounce, merging complete snapshots,
67
84
  Reload now, requests during a flip, stale active revisions, whole-batch Cancel/Undo and late
68
85
  commit outcomes. Use controlled clocks for scheduling boundaries and real file/HTTP cases for
@@ -77,9 +94,17 @@ sleeping a fixed interval.
77
94
 
78
95
  ## Real-version compatibility gates
79
96
 
97
+ The dashboard uses the Tailwind 4 PostCSS adapter. Its optimizer stays disabled
98
+ until generated selectors and license attribution have been checked; Vite still
99
+ minifies the final CSS. Keep the inline Vite and standalone PostCSS settings
100
+ consistent, and run the UI tests before regenerating the dashboard and notices.
101
+
80
102
  These are separate, mandatory CI gates, not substitutes for `npm test`. The root CI job runs
81
- CLI/API pairs on Windows, Linux and macOS with Node 20, 22 and 24. The Linux/Node 22 UI
82
- job runs one Chromium browser matrix after building the dashboard.
103
+ CLI/API pairs on Linux and macOS with Node 20, 22 and 24. The Windows pair runs in the
104
+ `windows-ordinary` job through `tools/windows-ci/ci-ordinary-user.ps1 -Contract compatibility`,
105
+ which prepares, exercises and removes its fixtures inside a disposable standard account: the
106
+ fixtures record the temp root that owns them, so an administrator-prepared pair is refused. The
107
+ Linux/Node 22 UI job runs one Chromium browser matrix after building the dashboard.
83
108
 
84
109
  ```bash
85
110
  npm ci
@@ -103,6 +128,13 @@ instead of installing bundled Chromium. CI uses bundled Chromium, not that overr
103
128
  Both standalone test commands **fail** when preparation is missing or candidate bytes have
104
129
  changed. Clean and prepare again after changing package files, built assets, or Node major.
105
130
 
131
+ On Windows, run these gates on Node 20, 22, 24.20.0 or a later 24.x, or 26.7.0 and later.
132
+ Released CLIs up to 2.1.0 use `fetch` for `prewarm`, and Node 23, 24 before 24.20.0, 25, and 26
133
+ before 26.7.0 can abort a process that exits soon after `fetch`
134
+ ([nodejs/node#56645](https://github.com/nodejs/node/issues/56645)). There, any test that runs a
135
+ released CLI into a refused change (1.3.0, and 2.0.0 in the historical baseline) fails with exit
136
+ code 3221226505 and a libuv `UV_HANDLE_CLOSING` assertion.
137
+
106
138
  Historical compatibility baselines remain explicitly **1.3.0 and 2.0.0**.
107
139
  Candidate versions must be canonical stable **1.x legacy / 2.x current** versions.
108
140
  The owner selects the actual release and any exact opposite-major patch pair;
@@ -111,13 +143,14 @@ The same harness runs in both maintained branches:
111
143
 
112
144
  | Preparation | Selected legacy / current pair |
113
145
  |---|---|
114
- | Default in the selected 2.0.2 checkout | Immutable 1.3.0 / packed 2.0.2 |
146
+ | Default in the selected 2.1.1 checkout | Immutable 1.3.0 / packed 2.1.1 |
115
147
  | Default in the 1.3.1 checkout | Packed 1.3.1 / immutable 2.0.0 |
116
148
  | `npm run compat:prepare:baseline` | Immutable 1.3.0 / immutable 2.0.0 |
117
- | `npm run compat:prepare -- --peer-root <opposite-patch-checkout>` | Packed 1.3.1 / packed 2.0.2 |
149
+ | `npm run compat:prepare -- --peer-root <opposite-patch-checkout>` | Packed explicit 1.x peer / packed 2.1.1 |
118
150
 
119
- These selections are not qualification evidence. The selected 1.3.1/2.0.2 pair
120
- requires fresh exact-byte gates; earlier 1.3.1/2.0.1 results remain historical.
151
+ These selections are not qualification evidence. The 2.1.1 candidate requires fresh
152
+ exact-byte gates; selecting it does not select an opposite-major patch pair.
153
+ Earlier 1.3.1/2.0.2 and 1.3.1/2.0.1 results remain historical.
121
154
 
122
155
  Run both API and browser gates for the explicit patch pair before publishing either complete
123
156
  dual-major release set. The two default CI pairs alone do not establish that combined result.