@twinsearth/w2m-dsh-plugin 1.4.0 → 1.4.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.
@@ -5,14 +5,14 @@
5
5
  },
6
6
  "metadata": {
7
7
  "description": "The w2m fleet plugins: one account, many machines, any of Windows, macOS or Linux.",
8
- "version": "1.4.0"
8
+ "version": "1.4.1"
9
9
  },
10
10
  "plugins": [
11
11
  {
12
12
  "name": "w2m-fleet",
13
13
  "source": "./",
14
14
  "description": "Read fleet state and dispatch commands across the machines registered to one account. Read-only MCP surface: the five exposed tools cannot change anything.",
15
- "version": "1.4.0",
15
+ "version": "1.4.1",
16
16
  "author": {
17
17
  "name": "TwinsEarth"
18
18
  },
@@ -26,5 +26,5 @@
26
26
  ]
27
27
  }
28
28
  ],
29
- "version": "1.4.0"
29
+ "version": "1.4.1"
30
30
  }
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "w2m-fleet",
3
3
  "description": "Drive the same project on online Windows, macOS and Linux machines from one account: read fleet state, dispatch commands and read results. The MCP surface is deliberately read-only.",
4
- "version": "1.4.0",
4
+ "version": "1.4.1",
5
5
  "author": {
6
6
  "name": "TwinsEarth"
7
7
  },
package/CHANGELOG.md CHANGED
@@ -7,6 +7,36 @@
7
7
 
8
8
  All notable changes to this project are documented here.
9
9
 
10
+ ## [1.4.1] — 2026-10-22
11
+
12
+ **修复:授权模型在从未 bootstrap 的机器上不可用(真机发现)。**
13
+
14
+ - relay 的 offer 对 **grant 任务**也携带 `operator_key`(此前只有 maintenance 请求携带)。在空 allow-list 的机器上,
15
+ agent 首次收到 offer 时据此 TOFU pin;修复前该机器只会得到 `GRANT_NO_PINNED_KEY`,即"显式授权"形同虚设。
16
+ - 任务台账记录 `operator_key`,relay 重启回放恢复 `workspace / grant / grant_summary / maintenance / operator_key`:
17
+ 修复前重启后 re-offer 会丢失授权字段,机器会以错误的理由拒绝任务。
18
+
19
+ 真机验收(relay 1.4.1 候选,TwinsEarth 插件 1.4.0、allow-list 为空):
20
+
21
+ - 无 grant 的 `node --version` → `COMMAND_NOT_ALLOWED`
22
+ - operator grant 授权的 `node -e` → **ok**,输出 `{plugin:"1.4.0", pinned:"^1.4.0", node:"v24.21.0"}`
23
+ - relay M1 diag(root runner)→ ok,66,046 bytes
24
+ - 证据:`docs/acceptance/1.4.1/TWIN-GRANT-LIVE.json`、`M1-LIVE-DIAG.json`
25
+
26
+ Verified: relay TOFU offer 测试 1/1、grant/ledger 相关 3/3;候选部署后真机全部通过。
27
+
28
+ ## [1.4.1-beta.1] — 2026-10-22
29
+
30
+ **候选:授权模型在"从未 bootstrap 的机器"上可用。**
31
+
32
+ - relay 的 offer 现在对 **grant 任务**也携带 `operator_key`(此前只有 maintenance 请求携带),首次见到该键的
33
+ agent 因此可以 TOFU pin;在此之前,空 allow-list 的新机器收到 grant 只会得到 `GRANT_NO_PINNED_KEY`。
34
+ - 任务台账记录 `operator_key`,重启回放恢复 `workspace / grant / grant_summary / maintenance / operator_key`:
35
+ 此前 relay 重启后 re-offer 的任务会丢失授权/工作区字段,机器会以错误的理由拒绝。
36
+ - 真机验证路径:TwinsEarth(allow-list 为空、插件 1.4.0)用 operator grant 执行 `node -e` 读取版本。
37
+
38
+ Verified: relay TOFU offer 测试 1/1,grant/ledger 相关 3/3;候选部署到 relay 后做真机验收。
39
+
10
40
  ## [1.4.0] — 2026-10-22
11
41
 
12
42
  **稳定版:执行授权、任务、协作三个模型的第一版落地。**
@@ -12,6 +12,6 @@
12
12
 
13
13
  [mcp_servers.w2m-fleet]
14
14
  command = "npx"
15
- args = ["-y", "-p", "@twinsearth/w2m-dsh-plugin@1.4.0", "w2m-mcp"]
15
+ args = ["-y", "-p", "@twinsearth/w2m-dsh-plugin@1.4.1", "w2m-mcp"]
16
16
  startup_timeout_sec = 20
17
17
  tool_timeout_sec = 60
@@ -0,0 +1,17 @@
1
+ {
2
+ "version": "1.4.1-beta.1",
3
+ "executed_at": "2026-10-22T04:32:10.058Z",
4
+ "executor": "lead",
5
+ "case": "M1-LIVE-DIAG",
6
+ "kind": "positive",
7
+ "machines": [
8
+ "1c14d7d2-d9e2-43dd-a7e5-eda98f4864bc"
9
+ ],
10
+ "requirement": "the 1.4.1 candidate executes a signed maintenance diag request on the relay host",
11
+ "task_id": "01M5GY2TVNKG3FB49WPCKGH9PA",
12
+ "result": {
13
+ "outcome": "ok",
14
+ "stdout_bytes": 66046,
15
+ "deployed_version": "1.4.1-beta.1"
16
+ }
17
+ }
@@ -0,0 +1,23 @@
1
+ {
2
+ "version": "1.4.1-beta.1",
3
+ "executed_at": "2026-10-22T04:32:10.058Z",
4
+ "executor": "lead",
5
+ "case": "TWIN-GRANT-LIVE",
6
+ "kind": "positive",
7
+ "machines": [
8
+ "6c92b251-3728-48bc-82a9-56cc40df48f2"
9
+ ],
10
+ "requirement": "a machine with an empty allow-list executes a command only through an explicit operator grant, and is refused without one",
11
+ "task_id": "01M5TWINGRANTOK0000000000001",
12
+ "result": {
13
+ "outcome": "ok",
14
+ "assertions": {
15
+ "plain_refused": "COMMAND_NOT_ALLOWED",
16
+ "granted_outcome": "ok",
17
+ "granted_stdout": "{\"node\":\"v24.21.0\",\"platform\":\"win32\",\"plugin\":\"1.4.0\",\"pinned\":\"^1.4.0\"}\n",
18
+ "grant_id": "gr-mvj1ns5e-8b1745e3a9",
19
+ "relay_version": "1.4.1-beta.1"
20
+ }
21
+ },
22
+ "note": "TwinsEarth runs plugin 1.4.0 with an empty allow-list; the grant path required the relay operator_key offer fix (1.4.1)"
23
+ }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@twinsearth/w2m-dsh-plugin",
3
- "version": "1.4.0",
3
+ "version": "1.4.1",
4
4
  "description": "Run one project across your own Windows and macOS machines from a single DeepSeek account, through 11 w2m_* tools. Four coordination modes (replicate, split, broadcast, pipeline) and six aggregate verdicts (consistent, divergent, divergent-platform, failed, partial, unverifiable). P2P hole punching by default, with a bundled relay, STUN responder and ledger fallback, so the fleet needs no third-party service. Joining needs a pairing code plus autoStartAgent: true; installing alone does not join.",
5
5
  "type": "module",
6
6
  "exports": {
package/plugin.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "$schema": "https://agent-plugins.org/schemas/1.0.0/plugin.schema.json",
3
3
  "name": "twinsearth-w2m-dsh",
4
- "version": "1.4.0",
4
+ "version": "1.4.1",
5
5
  "description": "Run one project across your own Windows and macOS machines from a single DeepSeek account, through 12 w2m_* tools. Four coordination modes (replicate, split, broadcast, pipeline) and six aggregate verdicts (consistent, divergent, divergent-platform, failed, partial, unverifiable). P2P hole punching by default, with a bundled relay, STUN responder and ledger fallback, so the fleet needs no third-party service. Joining needs a pairing code plus autoStartAgent: true; installing alone does not join.",
6
6
  "license": "MIT",
7
7
  "keywords": [
@@ -274,7 +274,7 @@ const MAX_STAGES = 16;
274
274
  * `package.json` during `scripts/pack.mjs` rather than hand-maintained, and `W2M_PLUGIN_VERSION`
275
275
  * overrides it at runtime for tests and packagers.
276
276
  */
277
- const PLUGIN_VERSION = '1.4.0';
277
+ const PLUGIN_VERSION = '1.4.1';
278
278
 
279
279
  /** How long any single HTTP call may take before it is aborted, in milliseconds. */
280
280
  const DEFAULT_REQUEST_TIMEOUT_MS = 15_000;
@@ -821,6 +821,14 @@ export class RabbitState {
821
821
  depends_on: Array.isArray(t.depends_on) ? t.depends_on : [],
822
822
  assignee: typeof t.assignee === 'string' && t.assignee !== '' ? t.assignee : null,
823
823
  project_id: typeof t.project_id === 'string' ? t.project_id : null,
824
+ // v1.4.1: an authorization or workspace must survive a relay restart, or a re-offered task reaches the machine
825
+ // without the grant/key/workspace it was dispatched with and the machine's own gate refuses it for the wrong reason.
826
+ workspace: t.workspace ?? null,
827
+ grant: t.grant ?? null,
828
+ grant_summary: t.grant_summary ?? null,
829
+ maintenance: t.maintenance ?? null,
830
+ maintenance_summary: t.maintenance_summary ?? null,
831
+ operator_key: t.operator_key ?? null,
824
832
  reduce_of: typeof t.reduce_of === 'string' ? t.reduce_of : null,
825
833
  reduce_inputs: Array.isArray(t.reduce_inputs) ? t.reduce_inputs : [],
826
834
  leases: new Map(),
@@ -2241,6 +2249,7 @@ export class RabbitState {
2241
2249
  reduce_of: task.reduce_of ?? null,
2242
2250
  maintenance_summary: task.maintenance_summary ?? null,
2243
2251
  grant_summary: task.grant_summary ?? null,
2252
+ operator_key: task.operator_key ?? null,
2244
2253
  reduce_inputs: Array.isArray(task.reduce_inputs) ? task.reduce_inputs : [],
2245
2254
  origin_machine_id: task.origin_machine_id ?? null,
2246
2255
  p2p: task.p2p ?? null,
@@ -2361,7 +2370,10 @@ export class RabbitState {
2361
2370
  // v1.2.10: present only on a reduce task, so a normal offer stays byte-identical.
2362
2371
  ...(task.reduce_of !== null ? { reduce_of: task.reduce_of, reduce_inputs: task.reduce_inputs } : {}),
2363
2372
  // v1.3.10-beta.2: the signed request and its operator key travel together; the agent pins the key on first sight.
2364
- ...(task.maintenance !== null && task.maintenance !== undefined ? { maintenance: task.maintenance, operator_key: task.operator_key } : {}),
2373
+ ...(task.maintenance !== null && task.maintenance !== undefined ? { maintenance: task.maintenance } : {}),
2374
+ // v1.4.1: a grant on a machine that has never pinned the operator key is useless unless the offer carries the key it should
2375
+ // trust. Maintenance requests always shipped it; grants must too, or the TOFU pin path is unreachable.
2376
+ ...(task.operator_key !== null && task.operator_key !== undefined ? { operator_key: task.operator_key } : {}),
2365
2377
  ...(task.workspace !== null && task.workspace !== undefined ? { workspace: task.workspace } : {}),
2366
2378
  ...(task.grant !== null && task.grant !== undefined ? { grant: task.grant } : {}),
2367
2379
  cwd_rel: task.cwd_rel,