agentwheel 0.16.6 → 0.18.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/AGENT.md CHANGED
@@ -18,7 +18,7 @@ plugin directories to complete an Agentwheel change.
18
18
  ## Standard Flow
19
19
 
20
20
  ```bash
21
- agentwheel add github:owner/agent-pack --adapter codex --installation-type local --mode tracking
21
+ agentwheel add github:owner/agent-pack --adapter codex --local --mode tracking
22
22
  agentwheel plan
23
23
  agentwheel install
24
24
  agentwheel status
@@ -35,9 +35,35 @@ Use explicit scope when the target matters:
35
35
  ```bash
36
36
  agentwheel install github:owner/agent-pack --adapter claude --user
37
37
  agentwheel install github:owner/agent-pack --adapter codex --local
38
- agentwheel install github:owner/agent-pack --adapter openclaw --installation-type local
38
+ agentwheel install --fleet example-fleet --profile daily --dry-run
39
39
  ```
40
40
 
41
+ `--user`, `--local`, and `--fleet <fleet-id>` select separate desired-state scopes. Named fleets
42
+ are optional. Do not merge scopes or assume a fleet has priority over user or local state.
43
+
44
+ Register and inspect a schema-v3 fleet only after its canonical root, matching `fleetId`, and
45
+ required packages exist:
46
+
47
+ ```bash
48
+ agentwheel fleet register example-fleet --root /srv/agentwheel/fleets/example-fleet --required-package core-agent-pack
49
+ agentwheel fleet list
50
+ agentwheel fleet show example-fleet
51
+ ```
52
+
53
+ If a configured runtime path is owned by another scope, stop and use the separate plan-first
54
+ normalization workflow. Review its digest before apply; matching content is not permission to take
55
+ ownership.
56
+
57
+ ```bash
58
+ agentwheel fleet normalize example-fleet --from user --package core-agent-pack --json
59
+ agentwheel fleet normalize example-fleet --from user --package core-agent-pack --plan-digest <reviewed-sha256> --apply
60
+ agentwheel fleet normalize example-fleet --from user --recover
61
+ ```
62
+
63
+ Named fleets require a schema-v3-capable CLI. Upgrade Agentwheel first and verify
64
+ `agentwheel fleet --help` before creating, registering, reading, or planning fleet state. Do not
65
+ downgrade the config, strip fleet fields, or run a planning/mutation command with the old CLI.
66
+
41
67
  ## Companion Skills
42
68
 
43
69
  Install the Agentwheel companion skill when the user wants Agentwheel guidance inside the runtime:
@@ -69,7 +95,7 @@ agentwheel install clawhub:@openclaw/package-name --adapter openclaw --local
69
95
  Use the catalogue for browsing and copy-ready commands:
70
96
 
71
97
  ```text
72
- https://nestdevlab.github.io/agentwheel/catalogue.html
98
+ https://www.nestdev.it/agentwheel/catalogue.html
73
99
  ```
74
100
 
75
101
  Draft a public catalogue submission without editing the registry by hand:
package/README.md CHANGED
@@ -26,7 +26,7 @@ forward explicitly; installs make the current declaration true.
26
26
  ```bash
27
27
  npm i -g agentwheel
28
28
  agentwheel init
29
- agentwheel add github:your-org/agent-pack --adapter codex --installation-type local --mode tracking
29
+ agentwheel add github:your-org/agent-pack --adapter codex --local --mode tracking
30
30
  agentwheel plan
31
31
  agentwheel install
32
32
  ```
@@ -65,10 +65,6 @@ agentwheel install github:NestDevLab/agentwheel --adapter codex --local --skill
65
65
  agentwheel install github:NestDevLab/agentwheel --adapter codex --local --skill agentwheel-discovery
66
66
  ```
67
67
 
68
- > **Status: early (v0.12).** The public CLI vocabulary is package-manager style:
69
- > `add`, `install`, `update`, and `uninstall`. A hidden `sync` shim remains for old bootstrapped
70
- > skills; use `install` in all new docs and scripts.
71
-
72
68
  ## Supported runtimes & resources
73
69
 
74
70
  agentwheel installs OpenPack resources into five built-in runtimes and into custom harnesses.
@@ -106,11 +102,14 @@ Fragments are Agentwheel composition inputs, not runtime file-drop targets.
106
102
  | `agentwheel install` | Reconcile configured packages into the current target or selected fleet. Uses the graph lock as input by default. |
107
103
  | `agentwheel install <name-or-source>` | Ensure semantics: configured name/source scopes the install; a new source is added and installed. |
108
104
  | `agentwheel update [name]` | Re-resolve tracking packages, then apply. A configured name preserves artifacts owned by other roots; `--dependency <name-or-source>` moves one tracking dependency while unrelated graph nodes stay locked. |
105
+ | `agentwheel skill update <name>` | Resolve the owning configured package and reconcile only that skill plus genuine transitive composition inputs; sibling artifacts stay byte-identical and retain manifest/lock state. |
109
106
  | `agentwheel uninstall <name-or-source>` | Remove a configured package from runtimes and config. |
110
107
  | `agentwheel uninstall <name> --keep-files` | Remove from config/manifest while leaving runtime files unmanaged. |
111
- | `agentwheel status` | Show configured packages, manifest/lock presence, and install state. Use `--profile <name>` for profile-managed fleets; `status --all` uses profile `all` when present. |
108
+ | `agentwheel status` | Show configured packages, manifest/lock presence, and install state. For a named fleet, use `--fleet <fleet-id> --profile <name>`; `--fleet <fleet-id> --all` uses profile `all` when present. |
112
109
  | `agentwheel ownership handoff <type/name>` | Transfer one manifest entry to a different workspace root after exact owner, hash, and revision checks; runtime content is not rewritten. |
110
+ | `agentwheel mcp retire <package>` | Preview removal of one exact legacy MCP contribution under an explicitly selected install-state key; add `--apply` only after review. |
113
111
  | `agentwheel doctor` | Check runtime setup and suggest explicit companion/selected skill install commands when they are missing. |
112
+ | `agentwheel cache prune` | Preview old Git source snapshots; add `--apply` to remove them while retaining locked commits. |
114
113
 
115
114
  Mental model: **`install` = make what is declared true. `update` = move tracking declarations forward,
116
115
  then make them true.**
@@ -133,6 +132,22 @@ Apply the same command with the reviewed values added as `--expected-hash <sha25
133
132
  journal, rechecks the old owner and the live artifact hash, then atomically updates only the install
134
133
  manifest. Run one target at a time; named SSH agents use the same contract through `--agent`.
135
134
 
135
+ For a one-time MCP rename, keep the legacy artifact in a dedicated cutover workspace rather than
136
+ the canonical desired-state profile. Set the legacy manifest `stateKey` on its named agent, then
137
+ preview one runtime at a time:
138
+
139
+ ```bash
140
+ agentwheel mcp retire legacy-mcp --agent legacy-codex \
141
+ --from-workspace-root /old/cutover/workspace --dry-run
142
+ agentwheel mcp retire legacy-mcp --agent legacy-claude --dry-run
143
+ ```
144
+
145
+ The package must render exactly one MCP artifact. The command accepts only an exact JSON MCP server
146
+ object or exact Codex TOML MCP sections, rejects unexpected manifest entries or owners, and
147
+ revalidates the exact contribution under the apply lock. It removes only the selected legacy
148
+ server; sibling servers and user configuration remain. The command previews by default. A later
149
+ runtime approval must use the same command with `--apply` instead of `--dry-run`.
150
+
136
151
  For a surgical dependency update, start with a dry-run:
137
152
 
138
153
  ```bash
@@ -295,45 +310,45 @@ agentwheel install github:your-org/agent-pack --adapter codex,claude
295
310
  ```
296
311
 
297
312
  Use `--local` for the current directory or `-t/--target-root <project>` for another
298
- project/workspace. Use `--user`, `--local`, or `-i/--installation-type <type>` when you want the
299
- scope to be explicit. For example, Codex local skills install into `.agents/skills`, while Codex user
300
- skills install into `~/.agents/skills`.
313
+ project/workspace. Use exactly one of `--user`, `--local`, or `--fleet <fleet-id>` when desired
314
+ state scope matters. `-i/--installation-type <type>` selects the runtime's install layout inside
315
+ that scope. For example, Codex local skills install into `.agents/skills`, while Codex user skills
316
+ install into `~/.agents/skills`. Named fleets are optional; ordinary user and local work does not
317
+ require a fleet registry.
301
318
 
302
319
  When adding a new source this way, Agentwheel saves one package entry per adapter so later installs
303
320
  do not collapse Codex and Claude state into the same config entry.
304
321
 
305
- For a control-plane setup, define named agents in config. Global config lives at
306
- `~/.agentwheel/config.json`; project config lives at `.agentwheel/config.json`; project values win.
322
+ For a control-plane setup, register a named fleet and define its agents and profiles in that fleet's
323
+ config. A fleet is selected explicitly with `--fleet <fleet-id>`; no fleet has global priority and
324
+ Agentwheel never merges desired state from user, local, and fleet scopes.
307
325
 
308
326
  ```jsonc
309
327
  {
328
+ "schemaVersion": 3,
329
+ "fleetId": "example-fleet",
330
+ "packages": [
331
+ {
332
+ "name": "core-agent-pack",
333
+ "source": "github:example-org/core-agent-pack",
334
+ "driver": "git",
335
+ "adapter": "codex",
336
+ "installationType": "local",
337
+ "mode": "tracking"
338
+ }
339
+ ],
310
340
  "agents": {
311
- "lab-openclaw": { "adapter": "openclaw", "installationType": "local", "root": "$HOME/.openclaw-home", "transport": "local" },
312
- "remote-codex": {
341
+ "lab-codex": {
313
342
  "adapter": "codex",
314
343
  "installationType": "local",
315
344
  "root": "/workspace/project",
316
- "transport": "ssh",
317
- "host": "agent-host.example",
318
- "user": "agent",
319
- "port": 22,
320
- "identityFile": "~/.ssh/id_ed25519"
321
- },
322
- "tirrenia": {
323
- "adapter": "openclaw",
324
- "installationType": "local",
325
- "root": "/home/openclaw-tirrenia",
326
- "transport": "ssh",
327
- "host": "ct110",
328
- "user": "openclaw-tirrenia",
329
- "reloadCommands": [["systemctl", "restart", "openclaw-gateway-tirrenia.service"]]
345
+ "transport": "local"
330
346
  }
331
347
  },
332
348
  "profiles": {
333
349
  "daily": {
334
350
  "runtimes": [
335
- { "agent": "lab-openclaw" },
336
- { "agent": "remote-codex" }
351
+ { "agent": "lab-codex" }
337
352
  ]
338
353
  }
339
354
  }
@@ -341,24 +356,41 @@ For a control-plane setup, define named agents in config. Global config lives at
341
356
  ```
342
357
 
343
358
  ```bash
344
- agentwheel install --agent lab-openclaw
345
- agentwheel install --all
346
- agentwheel update --profile daily --dry-run
347
- agentwheel install --profile daily
348
- agentwheel status --profile daily
359
+ agentwheel fleet register example-fleet \
360
+ --root /srv/agentwheel/fleets/example-fleet \
361
+ --required-package core-agent-pack
362
+ agentwheel fleet list
363
+ agentwheel fleet show example-fleet
364
+ agentwheel install --fleet example-fleet --agent lab-codex
365
+ agentwheel install --fleet example-fleet --all
366
+ agentwheel update --fleet example-fleet --profile daily --dry-run
367
+ agentwheel install --fleet example-fleet --profile daily
368
+ agentwheel status --fleet example-fleet --profile daily
349
369
  agentwheel install --all-detected
350
370
  ```
351
371
 
352
- SSH targets use the same manifest and drift model as local targets. Planning reads the remote
353
- install manifest and hashes remote files before deciding whether a file is up to date, drifted, or
354
- conflicting. SSH hosts need `ssh`, `tar`, and `node` available on `PATH`.
355
-
356
- To scaffold a control-plane example:
372
+ If another scope already owns an intended runtime path, the plan fails closed even when the bytes
373
+ match. Use the separate normalization command to preview an explicit ownership transfer, review its
374
+ plan digest, and apply only that same plan. Fleet selection never implies takeover.
357
375
 
358
376
  ```bash
359
- agentwheel init --fleet-example
377
+ agentwheel fleet normalize example-fleet --from user --package core-agent-pack --json
378
+ agentwheel fleet normalize example-fleet --from user --package core-agent-pack \
379
+ --plan-digest <reviewed-sha256> --apply
380
+ agentwheel fleet normalize example-fleet --from user --recover
360
381
  ```
361
382
 
383
+ Recovery restores the source side from a pending normalization journal after verifying that the
384
+ recorded configs, manifests, and graph locks have not changed outside the transaction.
385
+
386
+ Configuration with named fleets requires a schema-v3-capable Agentwheel CLI. Upgrade the CLI first,
387
+ verify `agentwheel --version` and `agentwheel fleet --help`, then create the fleet config and
388
+ register it. Do not edit the config to an older schema or run an older CLI against it.
389
+
390
+ SSH targets use the same manifest and drift model as local targets. Planning reads the remote
391
+ install manifest and hashes remote files before deciding whether a file is up to date, drifted, or
392
+ conflicting. SSH hosts need `ssh`, `tar`, and `node` available on `PATH`.
393
+
362
394
  Target resolution order is exact: `--target-root` wins, then `--agent`, then auto-detect from the
363
395
  current directory, then fallback to the current directory. `--all-detected` is an explicit escape hatch
364
396
  for applying to every runtime marker found in the current directory or `--target-root`; `--all` remains
@@ -723,7 +755,7 @@ Built-in runtime targets:
723
755
  - [`docs/fleet-config.md`](docs/fleet-config.md) — named agents, SSH targets, and profiles.
724
756
  - [`docs/design/federated-fleet-clusters.md`](docs/design/federated-fleet-clusters.md) — federating autonomous workspaces under one doctor/update control plane.
725
757
  - [`docs/design/artifact-harness-compatibility.md`](docs/design/artifact-harness-compatibility.md) — artifact/harness compatibility matrix and rule semantics.
726
- - Resource catalogue: https://nestdevlab.github.io/agentwheel/catalogue.html.
758
+ - Resource catalogue: https://www.nestdev.it/agentwheel/catalogue.html.
727
759
  - [`DESIGN.md`](DESIGN.md) — architecture and module layout.
728
760
  - [`LIFECYCLE.md`](LIFECYCLE.md) — publish, install, update, and customization model.
729
761
 
@@ -84,6 +84,31 @@ async function writeJsonAtomic(path, data) {
84
84
  `, "utf8");
85
85
  await rename(temp, path);
86
86
  }
87
+ async function withFilesystemLock(lockPath, timeoutMs, fn, description = "cache") {
88
+ await mkdir(dirname(lockPath), { recursive: true });
89
+ const started = Date.now();
90
+ while (true) {
91
+ try {
92
+ await mkdir(lockPath);
93
+ await writeFile(join(lockPath, "owner.json"), JSON.stringify({ pid: process.pid, createdAt: (/* @__PURE__ */ new Date()).toISOString() }), "utf8");
94
+ break;
95
+ } catch (error) {
96
+ if (!isAlreadyExists(error)) throw error;
97
+ if (Date.now() - started > timeoutMs) {
98
+ throw new Error(`Timed out waiting for ${description} lock at ${lockPath}`);
99
+ }
100
+ await new Promise((resolve2) => setTimeout(resolve2, 50));
101
+ }
102
+ }
103
+ try {
104
+ return await fn();
105
+ } finally {
106
+ await rm(lockPath, { recursive: true, force: true });
107
+ }
108
+ }
109
+ function isAlreadyExists(error) {
110
+ return typeof error === "object" && error !== null && "code" in error && error.code === "EEXIST";
111
+ }
87
112
 
88
113
  // src/source/identify.ts
89
114
  function inferSourceDriverName(source) {
@@ -111,9 +136,12 @@ function resolveLocalPath(source) {
111
136
  export {
112
137
  pathExists,
113
138
  hashPath,
139
+ listFiles,
114
140
  isIgnoredGeneratedEntry,
115
141
  atomicCopy,
116
142
  writeJsonAtomic,
143
+ withFilesystemLock,
144
+ isAlreadyExists,
117
145
  inferSourceDriverName,
118
146
  isExplicitSource
119
147
  };
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  inferSourceDriverName,
4
4
  isExplicitSource
5
- } from "./chunk-PKAPR55N.js";
5
+ } from "./chunk-UQLRZV5W.js";
6
6
  export {
7
7
  inferSourceDriverName,
8
8
  isExplicitSource