@twinsearth/w2m-dsh-plugin 1.1.14 → 1.1.16
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/.claude-plugin/marketplace.json +2 -2
- package/.claude-plugin/plugin.json +1 -1
- package/CHANGELOG.md +100 -0
- package/README.md +151 -899
- package/codex/mcp-servers.toml +1 -1
- package/package.json +6 -4
- package/plugin.json +1 -1
- package/src/agent/agent.mjs +17 -0
- package/src/plugin/account-join.mjs +86 -0
- package/src/plugin/tools.mjs +114 -4
- package/src/relay/admission.mjs +13 -2
- package/src/relay/server.mjs +1496 -1496
|
@@ -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.1.
|
|
8
|
+
"version": "1.1.16"
|
|
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.1.
|
|
15
|
+
"version": "1.1.16",
|
|
16
16
|
"author": {
|
|
17
17
|
"name": "TwinsEarth"
|
|
18
18
|
},
|
|
@@ -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.1.
|
|
4
|
+
"version": "1.1.16",
|
|
5
5
|
"author": {
|
|
6
6
|
"name": "TwinsEarth"
|
|
7
7
|
},
|
package/CHANGELOG.md
CHANGED
|
@@ -2,6 +2,106 @@
|
|
|
2
2
|
|
|
3
3
|
All notable changes to this project are documented here.
|
|
4
4
|
|
|
5
|
+
## [1.1.16] — 2026-10-18
|
|
6
|
+
|
|
7
|
+
**A machine waiting to be admitted now appears where you already answer questions -- and the README leads with how to
|
|
8
|
+
install it.**
|
|
9
|
+
|
|
10
|
+
### Admission in `w2m_approvals`
|
|
11
|
+
|
|
12
|
+
`w2m_approvals` merges `GET /v1/fleet/admission/pending` into its list as `kind:'fleet_admission'` rows, so a machine
|
|
13
|
+
asking to join shows up beside the permission requests already there. Settling an `adm-` id goes to the **relay's**
|
|
14
|
+
decide endpoint, not the local permission index: admission is not an authority escalation, and pushing it through
|
|
15
|
+
`approvalRequestFor` -- whose shape requires a needs-approval verdict and a capability -- would record a lie in the
|
|
16
|
+
audit trail. The list is shared; the stores are not.
|
|
17
|
+
|
|
18
|
+
The countdown is derived from the **relay's clock** (`rabbit_time`), never this machine's: three machines in this fleet
|
|
19
|
+
disagree by tens of seconds, and a local countdown would fire the automatic approval early on a fast machine. The relay
|
|
20
|
+
still owns the decision and still refuses to auto-approve with no member online.
|
|
21
|
+
|
|
22
|
+
### Two defects the tests caught
|
|
23
|
+
|
|
24
|
+
- the merged request omitted `rabbitUrl` and the device token, so it threw into the surrounding catch and the rows were
|
|
25
|
+
**silently missing** -- a probe showed the fetch was never called at all (`calls: []`);
|
|
26
|
+
- the refusal code was read from `json.code`, but protocol errors arrive at `json.error.code`, so `reason_code` was always
|
|
27
|
+
null and a late `ALREADY_DECIDED` decision looked like a success path.
|
|
28
|
+
|
|
29
|
+
Five assertions now cover that seam: rows and their fields, relay-clock countdown, an unreachable relay still showing the
|
|
30
|
+
local queue, `adm-` routing reaching the relay, and a late decision reported rather than thrown.
|
|
31
|
+
|
|
32
|
+
### README rewritten around installation
|
|
33
|
+
|
|
34
|
+
Five routes, easiest first: DSH plugin (zero configuration), npm/MCP for any client, Claude Code marketplace, Codex, and
|
|
35
|
+
the verified release tarball. Then quick start, the 11 tools registered, the `W2M_*` environment a dispatched command
|
|
36
|
+
receives, the fleet model, the security posture, and an explicit **verified / not verified** table that names the approval
|
|
37
|
+
popup, the four-machine `W2M_INDEX` run, the unimplemented chat channel and the macOS P2P downgrade instead of implying
|
|
38
|
+
they work.
|
|
39
|
+
|
|
40
|
+
Two claim checks rejected the first draft and were right: a `SHA256SUMS` release-download URL does not name a
|
|
41
|
+
`<name>-<version>.tgz` asset, and "eleven tools" had to be the measured number.
|
|
42
|
+
|
|
43
|
+
### Not in this release
|
|
44
|
+
|
|
45
|
+
The approval **popup** (a dedicated 10-second countdown control) is not implemented -- the rules are enforced by the
|
|
46
|
+
relay and this tool lists and settles the requests. The fleet chat channel remains designed (FLEET-CHAT-DESIGN.md) and
|
|
47
|
+
not built. No four-machine `W2M_INDEX` run yet.
|
|
48
|
+
|
|
49
|
+
### Verified
|
|
50
|
+
|
|
51
|
+
Gate GREEN (final pass, 15 of 15). 2458 tests in 102 files, 2444 pass, 0 fail, 14 skip. tools 120, tool-cards 8,
|
|
52
|
+
claims 47.
|
|
53
|
+
|
|
54
|
+
## [1.1.15] — 2026-10-17
|
|
55
|
+
|
|
56
|
+
**A machine that cannot join the old way now proves its account, asks to join, and waits for an answer -- and the
|
|
57
|
+
executed command finally learns which machine and which slice it is.**
|
|
58
|
+
|
|
59
|
+
### The fallback path is connected end to end
|
|
60
|
+
|
|
61
|
+
v1.1.14 shipped the server half. This release connects the client:
|
|
62
|
+
|
|
63
|
+
* \`pairNow\` classifies its failure and, for **only** the three degradable reasons (invalid pairing code, unreachable
|
|
64
|
+
relay, timeout), calls the new chain: challenge -> sign with the account key -> submit proof -> poll until a terminal
|
|
65
|
+
state. Anything else still needs a human and still does not change mechanisms;
|
|
66
|
+
* **a rejection is final.** The chain stops on \`rejected\`; re-asking would turn a decision into a notification queue;
|
|
67
|
+
* **an unfinished wait is reported, never hung on**: \`STILL_PENDING\` after the poll budget, \`expired\` when the relay
|
|
68
|
+
says so;
|
|
69
|
+
* the seed for the account key is the **fleet key, never the account code** -- the account code is written to the log,
|
|
70
|
+
and deriving a signing key from a value anyone can read would hand out the account's identity;
|
|
71
|
+
* the machine id comes from the agent object in scope, **not** from device.json: this machine never paired, which is the
|
|
72
|
+
entire situation.
|
|
73
|
+
|
|
74
|
+
### Polling without a device token
|
|
75
|
+
|
|
76
|
+
The asking machine has no device token -- that is why it is asking. The request response therefore carries a
|
|
77
|
+
\`poll_token\`, and \`GET /v1/fleet/admission/{id}?poll_token=\` is reachable **ahead of** the device-token gate. A wrong
|
|
78
|
+
token returns 404 rather than revealing whether the request exists.
|
|
79
|
+
|
|
80
|
+
### The command learns where it is (P1)
|
|
81
|
+
|
|
82
|
+
\`runArgv\` accepts an environment, and every executed command receives \`W2M_INDEX\`, \`W2M_INDEX_TOTAL\`,
|
|
83
|
+
\`W2M_STAGE_INDEX\`, \`W2M_TASK_ID\`, \`W2M_MODE\`, \`W2M_MACHINE_ID\`, \`W2M_MACHINE_NAME\`. Values come from the OFFER,
|
|
84
|
+
never from argv, so one machine cannot reshape a fleet-wide split. The variables are merged over \`process.env\` rather
|
|
85
|
+
than replacing it -- PATH must survive, or no interpreter is found. \`W2M_STAGE_INDEX\` is deliberately separate from
|
|
86
|
+
\`W2M_INDEX\`: for a split over four machines each runs one stage (0) but they are machines 0..3.
|
|
87
|
+
|
|
88
|
+
This makes the operator's acceptance shape possible: \`process.exit(Number(process.env.W2M_INDEX)+1)\` yields 1/2/3/4
|
|
89
|
+
across four machines. The single-machine half is tested here; the four-machine run needs the fleet and is **not yet
|
|
90
|
+
verified**.
|
|
91
|
+
|
|
92
|
+
### NOT shipped, stated plainly
|
|
93
|
+
|
|
94
|
+
* **The approval UI** (10s popup with countdown plus a standing dialog) is not written. The server enforces the rules it
|
|
95
|
+
must: no automatic approval with zero members online, and a rejection beats the ten seconds;
|
|
96
|
+
* **no end-to-end run**: new install -> popup -> admitted has not been executed, so \`agent.runtime.machineId\` being
|
|
97
|
+
non-empty on a real machine is **UNVERIFIED** -- if it is empty the fallback logs and does not fire;
|
|
98
|
+
* the fleet chat / broadcast channel is designed (FLEET-CHAT-DESIGN.md) and not implemented.
|
|
99
|
+
|
|
100
|
+
### Verified
|
|
101
|
+
|
|
102
|
+
Full gate GREEN (final pass, 15 of 15). Suites touched: tools 115, account-join 6, account-identity 6, join-challenge 8,
|
|
103
|
+
join-degradation 3, admission 16, admission-routes 3, relay 163, broadcast 19.
|
|
104
|
+
|
|
5
105
|
## [1.1.14] — 2026-10-17
|
|
6
106
|
|
|
7
107
|
**A new machine joins by itself, and a machine that cannot join the old way can now prove its account and ask.**
|