agentwheel 0.14.8 → 0.14.13

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
@@ -9,7 +9,7 @@ commands, subagents, MCP, hooks, settings, plugins, or fragments.
9
9
  - `add` records desired packages in `.agentwheel/config.json`.
10
10
  - `plan` previews what would change.
11
11
  - `install` makes the declared state true.
12
- - `update` refreshes tracking packages, then installs.
12
+ - `update` refreshes tracking packages, then installs; a configured package name preserves other roots, while `update --dependency <name-or-source>` advances one tracking dependency and keeps unrelated graph nodes locked.
13
13
  - `uninstall` removes managed runtime output and config entries.
14
14
 
15
15
  Runtime output directories are generated. Do not hand-edit generated skills, runtime config, or
package/README.md CHANGED
@@ -99,13 +99,14 @@ Fragments are Agentwheel composition inputs, not runtime file-drop targets.
99
99
  | Command | Meaning |
100
100
  |---|---|
101
101
  | `agentwheel add <source>` | Validate and save a package entry in `.agentwheel/config.json`; does not touch runtimes. |
102
- | `agentwheel plan [name-or-source]` | Preview what `install` would reconcile without writing. |
102
+ | `agentwheel plan [name-or-source]` | Preview what `install` would reconcile without writing; supports `--profile <name>` and `--json`. |
103
103
  | `agentwheel install` | Reconcile configured packages into the current target or selected fleet. Uses the graph lock as input by default. |
104
104
  | `agentwheel install <name-or-source>` | Ensure semantics: configured name/source scopes the install; a new source is added and installed. |
105
- | `agentwheel update [name]` | Re-resolve tracking packages, then apply. Pinned packages stay locked. Use `--profile <name>` for profile-managed fleets. |
105
+ | `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. |
106
106
  | `agentwheel uninstall <name-or-source>` | Remove a configured package from runtimes and config. |
107
107
  | `agentwheel uninstall <name> --keep-files` | Remove from config/manifest while leaving runtime files unmanaged. |
108
108
  | `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. |
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. |
109
110
  | `agentwheel doctor` | Check runtime setup and suggest explicit companion/selected skill install commands when they are missing. |
110
111
 
111
112
  Mental model: **`install` = make what is declared true. `update` = move tracking declarations forward,
@@ -113,6 +114,35 @@ then make them true.**
113
114
  Scoped installs do not remove files owned only by other configured packages; run a full `agentwheel install`
114
115
  to reconcile those removals.
115
116
 
117
+ When a managed fleet profile moves between workspace roots, preview a single-artifact ownership
118
+ handoff first. The dry-run prints the current artifact hash and manifest revision:
119
+
120
+ ```bash
121
+ agentwheel ownership handoff skills/example-skill \
122
+ --adapter codex --user --target-root "$HOME" \
123
+ --from-workspace-root /old/fleet/profile \
124
+ --to-workspace-root /new/fleet/profile \
125
+ --dry-run
126
+ ```
127
+
128
+ Apply the same command with the reviewed values added as `--expected-hash <sha256>` and
129
+ `--expected-revision <sha256>`. Agentwheel takes the target apply lock, rejects a pending apply
130
+ journal, rechecks the old owner and the live artifact hash, then atomically updates only the install
131
+ manifest. Run one target at a time; named SSH agents use the same contract through `--agent`.
132
+
133
+ For a surgical dependency update, start with a dry-run:
134
+
135
+ ```bash
136
+ agentwheel update --dependency shared-core --agent lab-codex --dry-run
137
+ agentwheel update --dependency github:your-org/shared-core --agent lab-codex
138
+ ```
139
+
140
+ The selector must uniquely match a locked tracking dependency by package name, dependency alias,
141
+ node id, or source. Agentwheel advances that node and its required tracking closure, writes the
142
+ complete graph lock, and applies atomically. Configured selections stay unchanged, so this mode
143
+ rejects package arguments, `--select`, `--skill`, `--frozen-lock`, and `--offline`. A later full
144
+ `update` can advance the remaining graph.
145
+
116
146
  ## Quick Start
117
147
 
118
148
  ```bash
@@ -145,6 +175,14 @@ wrapped by an explicit OpenPack source.
145
175
  wrapper for OpenClaw. The generated artifact plans `openclaw plugins install --force clawhub:<name>`;
146
176
  plugin execution remains opt-in through Agentwheel's plugin execution controls.
147
177
 
178
+ Runtime reloads or service restarts remain a separate opt-in gate. Configure structured
179
+ `reloadCommands` on an agent or profile runtime, then pass `--reload-runtimes` (or the alias
180
+ `--restart-runtimes`) with an apply command that executes plugins:
181
+
182
+ ```bash
183
+ agentwheel install --profile extra-message-policy --execute-plugins --reload-runtimes
184
+ ```
185
+
148
186
  Submit a public resource to the catalogue without editing `index.json` by hand:
149
187
 
150
188
  ```bash
@@ -243,6 +281,15 @@ For a control-plane setup, define named agents in config. Global config lives at
243
281
  "user": "agent",
244
282
  "port": 22,
245
283
  "identityFile": "~/.ssh/id_ed25519"
284
+ },
285
+ "tirrenia": {
286
+ "adapter": "openclaw",
287
+ "installationType": "local",
288
+ "root": "/home/openclaw-tirrenia",
289
+ "transport": "ssh",
290
+ "host": "ct110",
291
+ "user": "openclaw-tirrenia",
292
+ "reloadCommands": [["systemctl", "restart", "openclaw-gateway-tirrenia.service"]]
246
293
  }
247
294
  },
248
295
  "profiles": {
@@ -331,6 +378,85 @@ be deselected:
331
378
  }
332
379
  ```
333
380
 
381
+ ### Project-owned selection exports
382
+
383
+ Workspace configuration `schemaVersion: 2` can export named artifact selections. This is useful
384
+ when a project owns its content and portable local profiles, while a fleet only references the
385
+ project's curated selection for a remote runtime.
386
+
387
+ ```json
388
+ {
389
+ "schemaVersion": 2,
390
+ "exports": {
391
+ "selections": {
392
+ "default": {
393
+ "select": ["skills/project-start", "skills/project-checkin"]
394
+ },
395
+ "remote": {
396
+ "extends": "default",
397
+ "add": ["skills/remote-guard"],
398
+ "exclude": ["skills/project-checkin"]
399
+ }
400
+ }
401
+ },
402
+ "packages": [
403
+ {
404
+ "name": "project-workspace",
405
+ "source": ".",
406
+ "driver": "local",
407
+ "adapter": "copilot",
408
+ "mode": "pinned",
409
+ "selection": { "export": "default" }
410
+ }
411
+ ],
412
+ "agents": {
413
+ "mac-copilot": { "adapter": "copilot", "root": ".", "installationType": "local" }
414
+ },
415
+ "profiles": {
416
+ "local-mac": { "runtimes": [{ "agent": "mac-copilot" }] }
417
+ }
418
+ }
419
+ ```
420
+
421
+ The import is data-only: Agentwheel resolves the package first, then reads only
422
+ `exports.selections` from that resolved source's `.agentwheel/config.json`. It never imports the
423
+ source project's agents, profiles, SSH fields, adapter modules, trust policy, or other workspace
424
+ settings. Initial support is intentionally limited to `local` and `git` sources, so a Git import
425
+ uses the same immutable checkout as its artifacts.
426
+
427
+ A consuming fleet can reuse that selection without inheriting the project's runtime policy:
428
+
429
+ ```json
430
+ {
431
+ "schemaVersion": 2,
432
+ "packages": [
433
+ {
434
+ "name": "project-workspace",
435
+ "source": "/workspace/project",
436
+ "driver": "local",
437
+ "adapter": "hermes",
438
+ "mode": "pinned",
439
+ "selection": {
440
+ "export": "remote",
441
+ "add": ["skills/fleet-only-check"],
442
+ "exclude": ["skills/remote-guard"]
443
+ }
444
+ }
445
+ ]
446
+ }
447
+ ```
448
+
449
+ Resolution order is: exported base selection, each exported `extends` step, importer `add`, then
450
+ importer `exclude`; exclusion wins. Required artifacts remain selected. A package may use either
451
+ `selection` or `select`/legacy `skills`, never both, and CLI `--select`/`--skill` cannot override an
452
+ imported selection.
453
+
454
+ Plans print `IMPORT` and `SELECT` audit lines with the source, export catalog hash, requested
455
+ export, extension chain, additions, exclusions, and effective selectors. `agentwheel plan --profile
456
+ local-mac`, `agentwheel install --profile local-mac --dry-run`, and `--json` expose the same audit
457
+ data. The export catalog and resolved selection are recorded in graph locks, so `--frozen-lock`
458
+ rejects config-only selection changes.
459
+
334
460
  Package authors can also declare suggested companion packages. Suggestions are not installed by
335
461
  default; users opt in with `--with-suggestions` for all suggestions relevant to selected artifacts,
336
462
  or `--suggestion <alias>` for one named suggestion. The choice is saved when used with `add` or
@@ -97,7 +97,7 @@ async function isExplicitSource(source) {
97
97
  if (source.startsWith("github:") || source.startsWith("git:") || source.startsWith("skillkit:") || source.startsWith("vercel:") || source.startsWith("mcp-registry:") || source.startsWith("clawhub:")) {
98
98
  return true;
99
99
  }
100
- if (source.startsWith("./") || source.startsWith("../") || source.startsWith("/") || source.startsWith("~/")) {
100
+ if (source === "." || source === ".." || source.startsWith("./") || source.startsWith("../") || source.startsWith("/") || source.startsWith("~/")) {
101
101
  return true;
102
102
  }
103
103
  return pathExists(resolveLocalPath(source));
@@ -2,7 +2,7 @@
2
2
  import {
3
3
  inferSourceDriverName,
4
4
  isExplicitSource
5
- } from "./chunk-QJTTISLY.js";
5
+ } from "./chunk-PKAPR55N.js";
6
6
  export {
7
7
  inferSourceDriverName,
8
8
  isExplicitSource