agentwheel 0.20.19 → 0.20.20

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/README.md CHANGED
@@ -644,6 +644,11 @@ project's curated selection for a remote runtime.
644
644
  }
645
645
  ```
646
646
 
647
+ Configured packages can opt into adapter runtimes with `"runtimes": ["claude"]`. Profile and
648
+ named-agent plans match the declared target adapter; plain workspace commands match each package's
649
+ configured adapter. Agents sharing an adapter receive the same package roots. Upgrade every member
650
+ to a version supporting this field before using it in shared configuration.
651
+
647
652
  The import is data-only: Agentwheel resolves the package first, then reads only
648
653
  `exports.selections` from that resolved source's `.agentwheel/config.json`. It never imports the
649
654
  source project's agents, profiles, SSH fields, adapter modules, trust policy, or other workspace
@@ -5,8 +5,8 @@ import {
5
5
  commitManifestMetadataJournal,
6
6
  recoverPendingApply,
7
7
  uninstall
8
- } from "./chunk-L37KQVRS.js";
9
- import "./chunk-BHT57MK5.js";
8
+ } from "./chunk-45WVSUJA.js";
9
+ import "./chunk-FGFPAZ4J.js";
10
10
  import "./chunk-BNIF3FUR.js";
11
11
  export {
12
12
  applyCombinedInstallPlan,
@@ -24,7 +24,7 @@ import {
24
24
  rollbackCompletedOperations,
25
25
  sourceLockPath,
26
26
  writeApplyJournal
27
- } from "./chunk-BHT57MK5.js";
27
+ } from "./chunk-FGFPAZ4J.js";
28
28
  import {
29
29
  pathExists,
30
30
  writeJsonAtomic
@@ -1525,6 +1525,188 @@ function readMutationPathDeclarations(operationIdInput) {
1525
1525
  return [...paths].sort((a, b) => a.localeCompare(b));
1526
1526
  }
1527
1527
 
1528
+ // src/adapters/claude.ts
1529
+ var claudeAdapter = {
1530
+ name: "claude",
1531
+ displayName: "Claude Code",
1532
+ targets: {
1533
+ instructions: {
1534
+ local: { enabled: true, dest: "CLAUDE.md", mode: "managed-block" },
1535
+ user: { enabled: true, root: "home", dest: ".claude/CLAUDE.md", mode: "managed-block" }
1536
+ },
1537
+ rules: {
1538
+ local: { enabled: true, dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] },
1539
+ user: { enabled: true, root: "home", dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] }
1540
+ },
1541
+ skills: {
1542
+ local: { enabled: true, dest: ".claude/skills" },
1543
+ user: { enabled: true, root: "home", dest: ".claude/skills" }
1544
+ },
1545
+ commands: {
1546
+ local: { enabled: true, dest: ".claude/commands" },
1547
+ user: { enabled: true, root: "home", dest: ".claude/commands" }
1548
+ },
1549
+ subagents: {
1550
+ local: { enabled: true, dest: ".claude/agents" },
1551
+ user: { enabled: true, root: "home", dest: ".claude/agents" }
1552
+ },
1553
+ plugins: {
1554
+ local: { enabled: true, dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" },
1555
+ user: { enabled: true, root: "home", dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" }
1556
+ },
1557
+ mcp: {
1558
+ local: { enabled: true, dest: ".mcp.json", merge: "json-deep" }
1559
+ },
1560
+ hooks: {
1561
+ local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
1562
+ user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
1563
+ },
1564
+ settings: {
1565
+ local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
1566
+ user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
1567
+ }
1568
+ }
1569
+ };
1570
+
1571
+ // src/adapters/copilot.ts
1572
+ var copilotAdapter = {
1573
+ name: "copilot",
1574
+ displayName: "GitHub Copilot CLI",
1575
+ targets: {
1576
+ instructions: {
1577
+ local: { enabled: true, dest: ".github/copilot-instructions.md", mode: "managed-block" },
1578
+ user: { enabled: true, root: "home", dest: ".copilot/copilot-instructions.md", mode: "managed-block" }
1579
+ },
1580
+ rules: {
1581
+ local: { enabled: true, dest: ".github/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" },
1582
+ user: { enabled: true, root: "home", dest: ".copilot/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" }
1583
+ },
1584
+ commands: {
1585
+ local: { enabled: true, dest: ".github/prompts", semantic: "copilot-prompt" }
1586
+ },
1587
+ skills: {
1588
+ local: { enabled: true, dest: ".github/skills" },
1589
+ user: { enabled: true, root: "home", dest: ".copilot/skills" }
1590
+ },
1591
+ plugins: {
1592
+ user: { enabled: true, root: "home", dest: ".agentwheel/plugins/copilot", semantic: "copilot-plugin" }
1593
+ },
1594
+ subagents: {
1595
+ local: { enabled: true, dest: ".github/agents", semantic: "copilot-agent" },
1596
+ user: { enabled: true, root: "home", dest: ".copilot/agents", semantic: "copilot-agent" }
1597
+ },
1598
+ mcp: {
1599
+ local: { enabled: true, dest: ".github/mcp.json", merge: "json-deep" },
1600
+ user: { enabled: true, root: "home", dest: ".copilot/mcp-config.json", merge: "json-deep" }
1601
+ },
1602
+ hooks: {
1603
+ local: { enabled: true, dest: ".github/hooks" },
1604
+ user: { enabled: true, root: "home", dest: ".copilot/hooks" }
1605
+ },
1606
+ settings: {
1607
+ local: { enabled: true, dest: ".github/settings.json", merge: "json-deep" },
1608
+ user: { enabled: true, root: "home", dest: ".copilot/settings.json", merge: "json-deep" }
1609
+ }
1610
+ }
1611
+ };
1612
+
1613
+ // src/adapters/codex.ts
1614
+ var codexAdapter = {
1615
+ name: "codex",
1616
+ displayName: "Codex CLI",
1617
+ targets: {
1618
+ instructions: {
1619
+ local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
1620
+ user: { enabled: true, root: "home", dest: ".codex/AGENTS.md", mode: "managed-block" }
1621
+ },
1622
+ skills: {
1623
+ local: { enabled: true, dest: ".agents/skills" },
1624
+ user: { enabled: true, root: "home", dest: ".agents/skills" }
1625
+ },
1626
+ plugins: {
1627
+ local: { enabled: true, dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" },
1628
+ user: { enabled: true, root: "home", dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" }
1629
+ },
1630
+ subagents: {
1631
+ local: { enabled: true, dest: ".codex/agents", semantic: "codex-subagent" },
1632
+ user: { enabled: true, root: "home", dest: ".codex/agents", semantic: "codex-subagent" }
1633
+ },
1634
+ mcp: {
1635
+ local: { enabled: true, dest: ".codex/config.toml", merge: "codex-toml-mcp" },
1636
+ user: { enabled: true, root: "home", dest: ".codex/config.toml", merge: "codex-toml-mcp" }
1637
+ },
1638
+ hooks: {
1639
+ local: { enabled: true, dest: ".codex/hooks.json", merge: "json-deep" },
1640
+ user: { enabled: true, root: "home", dest: ".codex/hooks.json", merge: "json-deep" }
1641
+ }
1642
+ }
1643
+ };
1644
+
1645
+ // src/adapters/hermes.ts
1646
+ var hermesAdapter = {
1647
+ name: "hermes",
1648
+ displayName: "Hermes",
1649
+ targets: {
1650
+ instructions: {
1651
+ local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
1652
+ // Hermes documents SOUL.md as the user-level instruction surface.
1653
+ user: { enabled: true, root: "home", dest: ".hermes/SOUL.md", mode: "managed-block" }
1654
+ },
1655
+ skills: {
1656
+ user: { enabled: true, root: "home", dest: ".hermes/skills" }
1657
+ },
1658
+ mcp: {
1659
+ user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
1660
+ },
1661
+ settings: {
1662
+ user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
1663
+ },
1664
+ plugins: {
1665
+ user: { enabled: true, root: "home", dest: ".agentwheel/plugins/hermes", semantic: "hermes-plugin" }
1666
+ }
1667
+ }
1668
+ };
1669
+
1670
+ // src/adapters/openclaw.ts
1671
+ var openClawAdapter = {
1672
+ name: "openclaw",
1673
+ displayName: "OpenClaw",
1674
+ targets: {
1675
+ instructions: {
1676
+ user: { enabled: true, root: "home", dest: ".openclaw/workspace/AGENTS.md", mode: "managed-block" }
1677
+ },
1678
+ skills: {
1679
+ local: { enabled: true, dest: "skills" },
1680
+ user: { enabled: true, root: "home", dest: ".openclaw/skills" }
1681
+ },
1682
+ subagents: {
1683
+ user: { enabled: true, root: "home", dest: ".openclaw/workspace-subagents", semantic: "openclaw-subagent" }
1684
+ },
1685
+ mcp: {
1686
+ user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
1687
+ },
1688
+ settings: {
1689
+ user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
1690
+ },
1691
+ plugins: {
1692
+ local: { enabled: true, dest: ".openclaw/plugins", formats: ["openclaw-plugin", "openclaw-clawhub-plugin"], semantic: "openclaw-plugin" }
1693
+ }
1694
+ }
1695
+ };
1696
+
1697
+ // src/adapters/index.ts
1698
+ var adapters = [openClawAdapter, claudeAdapter, codexAdapter, hermesAdapter, copilotAdapter];
1699
+ function getAdapter(name) {
1700
+ const adapter = adapters.find((candidate) => candidate.name === name);
1701
+ if (!adapter) {
1702
+ throw new Error(`Unknown adapter: ${name}`);
1703
+ }
1704
+ return adapter;
1705
+ }
1706
+ function listAdapters() {
1707
+ return [...adapters];
1708
+ }
1709
+
1528
1710
  // src/model/workspace.ts
1529
1711
  var artifactSelectorListSchema = z7.array(z7.string().min(1));
1530
1712
  var CURRENT_WORKSPACE_SCHEMA_VERSION = 4;
@@ -1562,6 +1744,9 @@ var workspacePackageBaseSchema = z7.object({
1562
1744
  source: z7.string().min(1),
1563
1745
  driver: z7.enum(["local", "git", "skillkit", "vercel-skills", "mcp-registry", "clawhub"]).default("local"),
1564
1746
  adapter: z7.string().min(1).default("openclaw"),
1747
+ runtimes: z7.array(z7.string().min(1)).min(1).refine((runtimes) => new Set(runtimes).size === runtimes.length, {
1748
+ message: "Package runtimes must be unique."
1749
+ }).transform((runtimes) => [...runtimes].sort()).optional(),
1565
1750
  adapterConfig: z7.string().min(1).optional(),
1566
1751
  adapterModule: z7.string().min(1).optional(),
1567
1752
  adapterCodeHash: z7.string().min(16).optional(),
@@ -1726,7 +1911,25 @@ var workspaceConfigSchema = z7.discriminatedUnion("schemaVersion", [
1726
1911
  workspaceConfigV2Schema,
1727
1912
  workspaceConfigV3Schema,
1728
1913
  workspaceConfigV4Schema
1729
- ]);
1914
+ ]).superRefine((config, ctx) => {
1915
+ const known = /* @__PURE__ */ new Set([
1916
+ ...listAdapters().map((adapter) => adapter.name),
1917
+ ...Object.values(config.agents).map((agent) => agent.adapter),
1918
+ ...Object.values(config.profiles).flatMap((profile) => "runtimes" in profile && profile.runtimes ? profile.runtimes.map((runtime) => runtime.agent ? config.agents[runtime.agent]?.adapter ?? runtime.adapter : runtime.adapter) : [])
1919
+ ]);
1920
+ for (const [index, pkg] of config.packages.entries()) {
1921
+ for (const [runtimeIndex, runtime] of (pkg.runtimes ?? []).entries()) {
1922
+ if (!known.has(runtime)) ctx.addIssue({
1923
+ code: "custom",
1924
+ path: ["packages", index, "runtimes", runtimeIndex],
1925
+ message: `Unknown package runtime adapter '${runtime}'. Use a built-in adapter or an adapter declared by an agent/profile runtime.`
1926
+ });
1927
+ }
1928
+ }
1929
+ });
1930
+ function packagesForTarget(packages, target, targetForPackage) {
1931
+ return packages.filter((pkg) => !pkg.runtimes || pkg.runtimes.includes((targetForPackage?.(pkg) ?? target).adapter));
1932
+ }
1730
1933
  function supportsFleetConfig(config) {
1731
1934
  return config.schemaVersion === 3 || config.schemaVersion === 4;
1732
1935
  }
@@ -2865,8 +3068,8 @@ async function recoverMutationRuntime(operationId, options = {}) {
2865
3068
  }
2866
3069
  mutation = GovernedMutation.activateExisting(receipt, baseline, lock);
2867
3070
  const [{ recoverPendingApply }, { readLinkedLocalApplyJournal: readLinkedLocalApplyJournal2, removeApplyJournal: removeApplyJournal2, localPathExists: localPathExists2 }] = await Promise.all([
2868
- import("./apply-QJHTL7IK.js"),
2869
- import("./transaction-JHZJWBII.js")
3071
+ import("./apply-Z5GVCPA4.js"),
3072
+ import("./transaction-NLAIJ2ZZ.js")
2870
3073
  ]);
2871
3074
  let missingReservation = false;
2872
3075
  for (const entry of pending) {
@@ -3361,6 +3564,7 @@ export {
3361
3564
  installRootForArtifacts,
3362
3565
  installRootForAdapterInstallationType,
3363
3566
  loadAdapterConfig,
3567
+ getAdapter,
3364
3568
  readMutationReceipt,
3365
3569
  listMutationReceipts,
3366
3570
  declareMutationPath,
@@ -3380,6 +3584,7 @@ export {
3380
3584
  fleetIdSchema,
3381
3585
  registeredFleetSchema,
3382
3586
  workspaceConfigSchema,
3587
+ packagesForTarget,
3383
3588
  supportsFleetConfig,
3384
3589
  workspaceConfigPath,
3385
3590
  readWorkspaceConfig,
package/dist/index.js CHANGED
@@ -37,7 +37,7 @@ import {
37
37
  uninstall,
38
38
  withManifestRevision,
39
39
  writeInstallManifest
40
- } from "./chunk-L37KQVRS.js";
40
+ } from "./chunk-45WVSUJA.js";
41
41
  import {
42
42
  CURRENT_WORKSPACE_SCHEMA_VERSION,
43
43
  GovernedMutation,
@@ -56,6 +56,7 @@ import {
56
56
  findExistingWorkspaceRoot,
57
57
  findWorkspaceRoot,
58
58
  fleetIdSchema,
59
+ getAdapter,
59
60
  globalWorkspaceConfigPath,
60
61
  installManifestPath,
61
62
  installRootForAdapterInstallationType,
@@ -74,6 +75,7 @@ import {
74
75
  packageItemRequireSchema,
75
76
  packageItemSuggestSchema,
76
77
  packageSupersedesEntrySchema,
78
+ packagesForTarget,
77
79
  parseSemver,
78
80
  readApplyJournal,
79
81
  readMergedWorkspaceConfig,
@@ -98,7 +100,7 @@ import {
98
100
  workspaceSelectionImportSchema,
99
101
  writeApplyJournal,
100
102
  writeWorkspaceConfig
101
- } from "./chunk-BHT57MK5.js";
103
+ } from "./chunk-FGFPAZ4J.js";
102
104
  import {
103
105
  inferSourceDriverName
104
106
  } from "./chunk-QABA4WUP.js";
@@ -125,185 +127,6 @@ import { Command } from "commander";
125
127
  // src/adapters/resolve.ts
126
128
  import { resolve as resolve2 } from "path";
127
129
 
128
- // src/adapters/claude.ts
129
- var claudeAdapter = {
130
- name: "claude",
131
- displayName: "Claude Code",
132
- targets: {
133
- instructions: {
134
- local: { enabled: true, dest: "CLAUDE.md", mode: "managed-block" },
135
- user: { enabled: true, root: "home", dest: ".claude/CLAUDE.md", mode: "managed-block" }
136
- },
137
- rules: {
138
- local: { enabled: true, dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] },
139
- user: { enabled: true, root: "home", dest: ".claude/rules", formats: ["markdown-rule", "claude-markdown-rule"] }
140
- },
141
- skills: {
142
- local: { enabled: true, dest: ".claude/skills" },
143
- user: { enabled: true, root: "home", dest: ".claude/skills" }
144
- },
145
- commands: {
146
- local: { enabled: true, dest: ".claude/commands" },
147
- user: { enabled: true, root: "home", dest: ".claude/commands" }
148
- },
149
- subagents: {
150
- local: { enabled: true, dest: ".claude/agents" },
151
- user: { enabled: true, root: "home", dest: ".claude/agents" }
152
- },
153
- plugins: {
154
- local: { enabled: true, dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" },
155
- user: { enabled: true, root: "home", dest: ".agentwheel/plugins/claude", semantic: "claude-plugin" }
156
- },
157
- mcp: {
158
- local: { enabled: true, dest: ".mcp.json", merge: "json-deep" }
159
- },
160
- hooks: {
161
- local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
162
- user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
163
- },
164
- settings: {
165
- local: { enabled: true, dest: ".claude/settings.json", merge: "json-deep" },
166
- user: { enabled: true, root: "home", dest: ".claude/settings.json", merge: "json-deep" }
167
- }
168
- }
169
- };
170
-
171
- // src/adapters/copilot.ts
172
- var copilotAdapter = {
173
- name: "copilot",
174
- displayName: "GitHub Copilot CLI",
175
- targets: {
176
- instructions: {
177
- local: { enabled: true, dest: ".github/copilot-instructions.md", mode: "managed-block" },
178
- user: { enabled: true, root: "home", dest: ".copilot/copilot-instructions.md", mode: "managed-block" }
179
- },
180
- rules: {
181
- local: { enabled: true, dest: ".github/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" },
182
- user: { enabled: true, root: "home", dest: ".copilot/instructions", formats: ["markdown-rule", "copilot-instruction-rule"], semantic: "copilot-instruction" }
183
- },
184
- commands: {
185
- local: { enabled: true, dest: ".github/prompts", semantic: "copilot-prompt" }
186
- },
187
- skills: {
188
- local: { enabled: true, dest: ".github/skills" },
189
- user: { enabled: true, root: "home", dest: ".copilot/skills" }
190
- },
191
- plugins: {
192
- user: { enabled: true, root: "home", dest: ".agentwheel/plugins/copilot", semantic: "copilot-plugin" }
193
- },
194
- subagents: {
195
- local: { enabled: true, dest: ".github/agents", semantic: "copilot-agent" },
196
- user: { enabled: true, root: "home", dest: ".copilot/agents", semantic: "copilot-agent" }
197
- },
198
- mcp: {
199
- local: { enabled: true, dest: ".github/mcp.json", merge: "json-deep" },
200
- user: { enabled: true, root: "home", dest: ".copilot/mcp-config.json", merge: "json-deep" }
201
- },
202
- hooks: {
203
- local: { enabled: true, dest: ".github/hooks" },
204
- user: { enabled: true, root: "home", dest: ".copilot/hooks" }
205
- },
206
- settings: {
207
- local: { enabled: true, dest: ".github/settings.json", merge: "json-deep" },
208
- user: { enabled: true, root: "home", dest: ".copilot/settings.json", merge: "json-deep" }
209
- }
210
- }
211
- };
212
-
213
- // src/adapters/codex.ts
214
- var codexAdapter = {
215
- name: "codex",
216
- displayName: "Codex CLI",
217
- targets: {
218
- instructions: {
219
- local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
220
- user: { enabled: true, root: "home", dest: ".codex/AGENTS.md", mode: "managed-block" }
221
- },
222
- skills: {
223
- local: { enabled: true, dest: ".agents/skills" },
224
- user: { enabled: true, root: "home", dest: ".agents/skills" }
225
- },
226
- plugins: {
227
- local: { enabled: true, dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" },
228
- user: { enabled: true, root: "home", dest: ".agentwheel/plugins/codex", semantic: "codex-plugin" }
229
- },
230
- subagents: {
231
- local: { enabled: true, dest: ".codex/agents", semantic: "codex-subagent" },
232
- user: { enabled: true, root: "home", dest: ".codex/agents", semantic: "codex-subagent" }
233
- },
234
- mcp: {
235
- local: { enabled: true, dest: ".codex/config.toml", merge: "codex-toml-mcp" },
236
- user: { enabled: true, root: "home", dest: ".codex/config.toml", merge: "codex-toml-mcp" }
237
- },
238
- hooks: {
239
- local: { enabled: true, dest: ".codex/hooks.json", merge: "json-deep" },
240
- user: { enabled: true, root: "home", dest: ".codex/hooks.json", merge: "json-deep" }
241
- }
242
- }
243
- };
244
-
245
- // src/adapters/hermes.ts
246
- var hermesAdapter = {
247
- name: "hermes",
248
- displayName: "Hermes",
249
- targets: {
250
- instructions: {
251
- local: { enabled: true, dest: "AGENTS.md", mode: "managed-block" },
252
- // Hermes documents SOUL.md as the user-level instruction surface.
253
- user: { enabled: true, root: "home", dest: ".hermes/SOUL.md", mode: "managed-block" }
254
- },
255
- skills: {
256
- user: { enabled: true, root: "home", dest: ".hermes/skills" }
257
- },
258
- mcp: {
259
- user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
260
- },
261
- settings: {
262
- user: { enabled: true, root: "home", dest: ".hermes/config.yaml", merge: "yaml-deep" }
263
- },
264
- plugins: {
265
- user: { enabled: true, root: "home", dest: ".agentwheel/plugins/hermes", semantic: "hermes-plugin" }
266
- }
267
- }
268
- };
269
-
270
- // src/adapters/openclaw.ts
271
- var openClawAdapter = {
272
- name: "openclaw",
273
- displayName: "OpenClaw",
274
- targets: {
275
- instructions: {
276
- user: { enabled: true, root: "home", dest: ".openclaw/workspace/AGENTS.md", mode: "managed-block" }
277
- },
278
- skills: {
279
- local: { enabled: true, dest: "skills" },
280
- user: { enabled: true, root: "home", dest: ".openclaw/skills" }
281
- },
282
- subagents: {
283
- user: { enabled: true, root: "home", dest: ".openclaw/workspace-subagents", semantic: "openclaw-subagent" }
284
- },
285
- mcp: {
286
- user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
287
- },
288
- settings: {
289
- user: { enabled: true, root: "home", dest: ".openclaw/openclaw.json", merge: "openclaw-json-deep" }
290
- },
291
- plugins: {
292
- local: { enabled: true, dest: ".openclaw/plugins", formats: ["openclaw-plugin", "openclaw-clawhub-plugin"], semantic: "openclaw-plugin" }
293
- }
294
- }
295
- };
296
-
297
- // src/adapters/index.ts
298
- var adapters = [openClawAdapter, claudeAdapter, codexAdapter, hermesAdapter, copilotAdapter];
299
- function getAdapter(name) {
300
- const adapter = adapters.find((candidate) => candidate.name === name);
301
- if (!adapter) {
302
- throw new Error(`Unknown adapter: ${name}`);
303
- }
304
- return adapter;
305
- }
306
-
307
130
  // src/adapters/programmatic.ts
308
131
  import { stat, readFile, writeFile } from "fs/promises";
309
132
  import { tmpdir } from "os";
@@ -6030,7 +5853,7 @@ var SnapshotConflictError = class extends Error {
6030
5853
  };
6031
5854
  var cacheLocks = /* @__PURE__ */ new Map();
6032
5855
  async function resolveDependencyGraph(roots, options) {
6033
- if (roots.length === 0) throw new Error("At least one graph root is required.");
5856
+ if (roots.length === 0 && !options.allowEmptyRoots) throw new Error("At least one graph root is required.");
6034
5857
  const fetchCache = /* @__PURE__ */ new Map();
6035
5858
  const nodesByKey = /* @__PURE__ */ new Map();
6036
5859
  const nodesBySource = /* @__PURE__ */ new Map();
@@ -8197,7 +8020,7 @@ function targetEndpoint(value, transportKind) {
8197
8020
 
8198
8021
  // src/lifecycle/source-plan.ts
8199
8022
  async function createGraphSourcePlan(options) {
8200
- if (options.roots.length === 0) {
8023
+ if (options.roots.length === 0 && !options.allowEmptyRoots) {
8201
8024
  throw new Error("At least one source is required for a graph plan.");
8202
8025
  }
8203
8026
  if (options.freshGraphOnly && options.readOnly !== true) {
@@ -8313,7 +8136,8 @@ async function createGraphSourcePlan(options) {
8313
8136
  offline: options.offline,
8314
8137
  previousLock,
8315
8138
  warn,
8316
- runtime: options.adapter.name
8139
+ runtime: options.adapter.name,
8140
+ allowEmptyRoots: options.allowEmptyRoots
8317
8141
  });
8318
8142
  assertFrozenGraph(previousLock, graph, lockMode, lockLabel);
8319
8143
  assertTrustArtifactPolicy(graph, trustPolicy);
@@ -8372,6 +8196,16 @@ async function createGraphSourcePlan(options) {
8372
8196
  warn
8373
8197
  });
8374
8198
  const plan = priorState.migration && !basePlan.stateMigration ? { ...basePlan, stateMigration: priorState.migration } : basePlan;
8199
+ if (options.excludedRootIds?.length && previousLock) {
8200
+ const excludedRoots = new Set(options.excludedRootIds);
8201
+ const excludedNodeIds = new Set(previousLock.canonical.roots.filter((root) => excludedRoots.has(root.rootId)).map((root) => root.graphNodeId));
8202
+ for (const operation of plan.operations) {
8203
+ const excludedOwner = operation.owners?.length && operation.owners.every((owner) => excludedRoots.has(owner));
8204
+ if (operation.action === "remove" && (excludedOwner || operation.graphNodeId && excludedNodeIds.has(operation.graphNodeId))) {
8205
+ operation.reason = "excluded by package runtimes";
8206
+ }
8207
+ }
8208
+ }
8375
8209
  plan.targetStateFilePreconditions = {
8376
8210
  graphLockPath,
8377
8211
  graphLockRevision: stableLock ? digestGraphLock(stableLock) : null,
@@ -9256,8 +9090,17 @@ async function syncProfile(options) {
9256
9090
  if (selected && packages.some((pkg) => pkg.selection)) {
9257
9091
  throw new Error("--select/--skill cannot be combined with a package selection import.");
9258
9092
  }
9093
+ if (!options.source) {
9094
+ const adapters = new Set(profile.runtimes.map((runtime) => resolveProfileRuntimeTarget(runtime, config, options.workspaceRoot, options.installationType, options.fleetId).adapter));
9095
+ for (const pkg of packages) {
9096
+ if (pkg.runtimes && !pkg.runtimes.some((runtime) => adapters.has(runtime))) {
9097
+ options.warn?.(`Package '${pkg.name}' matches no runtime in profile '${options.profile}'.`);
9098
+ }
9099
+ }
9100
+ }
9259
9101
  for (const runtime of profile.runtimes) {
9260
9102
  const target = resolveProfileRuntimeTarget(runtime, config, options.workspaceRoot, options.installationType, options.fleetId);
9103
+ const runtimePackages = options.source ? packages : packagesForTarget(packages, target);
9261
9104
  const transport = transportForTarget(target);
9262
9105
  const adapter = await resolveAdapter({
9263
9106
  adapter: target.adapter,
@@ -9270,7 +9113,7 @@ async function syncProfile(options) {
9270
9113
  const installationType = target.installationType ?? defaultInstallationType;
9271
9114
  resolveInstallationTypeForAdapter(adapter, installationType);
9272
9115
  const graphPlan = await createGraphSourcePlan({
9273
- roots: packages.map((pkg) => ({
9116
+ roots: runtimePackages.map((pkg) => ({
9274
9117
  rootId: pkg.name,
9275
9118
  source: pkg.source,
9276
9119
  mode: options.mode ?? pkg.mode,
@@ -9319,14 +9162,16 @@ async function syncProfile(options) {
9319
9162
  forceConflict: options.forceConflict,
9320
9163
  forceForeignState: options.forceForeignState,
9321
9164
  replaceConflict: options.replaceConflict,
9322
- recoverLegacyState: options.recoverLegacyState
9165
+ recoverLegacyState: options.recoverLegacyState,
9166
+ allowEmptyRoots: runtimePackages.length === 0,
9167
+ excludedRootIds: options.source ? [] : packages.filter((pkg) => !runtimePackages.includes(pkg)).map((pkg) => pkg.name)
9323
9168
  });
9324
9169
  try {
9325
9170
  const result = {
9326
9171
  runtime: adapter.name,
9327
9172
  targetRoot: installRootForAdapterInstallationType(adapter, target.targetRoot, installationType, transport.kind === "ssh"),
9328
9173
  transport: transport.kind,
9329
- packageName: packages.map((pkg) => pkg.name).join(","),
9174
+ packageName: runtimePackages.map((pkg) => pkg.name).join(",") || "(no packages)",
9330
9175
  plan: graphPlan.plan,
9331
9176
  graphPlan,
9332
9177
  graphLockDigest: graphPlan.graphLockDigest,
@@ -12468,7 +12313,7 @@ async function planFleetNormalization(request) {
12468
12313
  const destinationDeclaration = canonicalJson2(destinationPackage);
12469
12314
  if (sourceDeclaration !== destinationDeclaration) {
12470
12315
  throw new Error(
12471
- `Package '${name}' has divergent declarations. Source, driver, adapter, adapter configuration, installation type, version policy, selections, aliases, overrides, and suggestions must match before normalization.`
12316
+ `Package '${name}' has divergent declarations. Source, driver, adapter, adapter configuration, installation type, version policy, runtime restrictions, selections, aliases, overrides, and suggestions must match before normalization.`
12472
12317
  );
12473
12318
  }
12474
12319
  packages.push({ name, declarationDigest: sha2565(sourceDeclaration) });
@@ -14504,8 +14349,9 @@ ownershipCommand.command("recovery-plan").description("write a read-only per-pat
14504
14349
  }
14505
14350
  const installationType = target.installationType ?? resolveInstallationTypeForAdapter(adapter, void 0);
14506
14351
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
14507
- if (config.packages.length === 0) throw new Error("Fleet has no configured source packages.");
14508
- await withFreshReadOnlyGraphPlan(target, adapter, adapterOptionsForTarget(target, {}), installationType, config.packages, async (graphPlan) => {
14352
+ const targetPackages = packagesForCliTarget(config.packages, target, {});
14353
+ if (targetPackages.length === 0) throw new Error("Fleet target has no configured source packages.");
14354
+ await withFreshReadOnlyGraphPlan(target, adapter, adapterOptionsForTarget(target, {}), installationType, targetPackages, async (graphPlan) => {
14509
14355
  const installRoot = installRootForAdapterInstallationType(adapter, target.targetRoot, installationType, transport.kind === "ssh");
14510
14356
  const report = await planLegacyRecovery({
14511
14357
  graphPlan,
@@ -14632,7 +14478,7 @@ ownershipCommand.command("adopt-legacy").description("move proven legacy-keyed o
14632
14478
  if (target.transport === "ssh") throw new Error("Legacy ownership adoption does not support SSH targets.");
14633
14479
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
14634
14480
  const groups = /* @__PURE__ */ new Map();
14635
- for (const pkg of config.packages) graphGroupForPackage(groups, target, pkg, plainInstallOptions).packages.push(pkg);
14481
+ for (const pkg of packagesForCliTarget(config.packages, target, plainInstallOptions)) graphGroupForPackage(groups, target, pkg, plainInstallOptions).packages.push(pkg);
14636
14482
  if (groups.size === 0) throw new Error(`No configured source packages in ${target.workspaceRoot}.`);
14637
14483
  const installationTypes = [...new Set([...groups.values()].map((candidate) => candidate.installationType))];
14638
14484
  if (installationTypes.length > 1) {
@@ -14974,7 +14820,7 @@ async function runInstallCommand(nameOrSource, options, behavior) {
14974
14820
  for (const target of targets) {
14975
14821
  const targetOptions = optionsForResolvedTarget(normalizedOptions, target);
14976
14822
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
14977
- const configured = nameOrSource ? findConfiguredPackageForTarget(config.packages, nameOrSource, targetOptions, target) : void 0;
14823
+ const configured = nameOrSource ? findConfiguredPackageForTarget(packagesForCliTarget(config.packages, target, targetOptions), nameOrSource, targetOptions, target) : void 0;
14978
14824
  let source;
14979
14825
  let scope = configured?.name;
14980
14826
  let extraPackage;
@@ -15065,11 +14911,11 @@ async function buildPlanReport(nameOrSource, options) {
15065
14911
  yes: normalizedOptions.yes,
15066
14912
  trustPatterns: normalizedOptions.trust ?? [],
15067
14913
  readOnly: true,
15068
- isTTY: false
14914
+ isTTY: false,
14915
+ warn: collectWarning
15069
14916
  });
15070
14917
  for (const result of results) {
15071
14918
  reportTargets.push(installPlanReportTarget(result.plan, result.graphLockDigest));
15072
- reportWarnings.push(...result.warnings);
15073
14919
  }
15074
14920
  return planReport(reportTargets, reportWarnings);
15075
14921
  }
@@ -15077,7 +14923,7 @@ async function buildPlanReport(nameOrSource, options) {
15077
14923
  for (const target of targets) {
15078
14924
  const targetOptions = optionsForResolvedTarget(normalizedOptions, target);
15079
14925
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
15080
- const configured = nameOrSource ? findConfiguredPackageForTarget(config.packages, nameOrSource, targetOptions, target) : void 0;
14926
+ const configured = nameOrSource ? findConfiguredPackageForTarget(packagesForCliTarget(config.packages, target, targetOptions), nameOrSource, targetOptions, target) : void 0;
15081
14927
  let source;
15082
14928
  let scope = configured?.name;
15083
14929
  let extraPackage;
@@ -15307,13 +15153,13 @@ async function resolveCliTargets(options, behavior = {}) {
15307
15153
  if (normalizedOptions.profile && (normalizedOptions.all || normalizedOptions.allDetected || normalizedOptions.agent)) {
15308
15154
  throw new Error("--profile cannot be combined with --all, --all-detected, or --agent.");
15309
15155
  }
15310
- const adapters2 = adapterListFromOption(normalizedOptions.adapter);
15311
- if (adapters2.length > 1) {
15156
+ const adapters = adapterListFromOption(normalizedOptions.adapter);
15157
+ if (adapters.length > 1) {
15312
15158
  if (normalizedOptions.all || normalizedOptions.allDetected || normalizedOptions.agent || normalizedOptions.profile) {
15313
15159
  throw new Error("--adapter <a,b> cannot be combined with --all, --all-detected, --agent, or --profile. Use a profile for mixed configured targets.");
15314
15160
  }
15315
15161
  const targets = [];
15316
- for (const adapter of adapters2) {
15162
+ for (const adapter of adapters) {
15317
15163
  targets.push(await resolveRuntimeTarget({
15318
15164
  cwd: scopeRoot,
15319
15165
  targetRoot: normalizedOptions.targetRoot,
@@ -15459,7 +15305,7 @@ async function runSkillUpdateCommand(skillName, options) {
15459
15305
  const targets = await resolveCliTargets(normalizedOptions, { preferAllProfile: true });
15460
15306
  for (const target of targets) {
15461
15307
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
15462
- const owner = await configuredPackageForSkill(target, config.packages, skillName, normalizedOptions, options.package);
15308
+ const owner = await configuredPackageForSkill(target, packagesForCliTarget(config.packages, target, normalizedOptions), skillName, normalizedOptions, options.package);
15463
15309
  const mode = owner.mode === "tracking" ? "update" : "install";
15464
15310
  console.log(`Skill ${skillName}: ${owner.name} (${mode}).`);
15465
15311
  await runConfiguredGraphPackages(target, {
@@ -15512,22 +15358,28 @@ async function buildGraphPlansForTarget(target, source, options, behavior) {
15512
15358
  async function collectGraphPlansForTarget(target, source, options, behavior, bundleRoots) {
15513
15359
  const targetOptions = optionsForResolvedTarget(options, target);
15514
15360
  const config = await readMergedWorkspaceConfig(target.workspaceRoot);
15361
+ const targetPackages = packagesForCliTarget(config.packages, target, targetOptions);
15515
15362
  const groups = /* @__PURE__ */ new Map();
15516
15363
  const selectedArtifacts = selectedArtifactsFromOptions(targetOptions);
15517
15364
  const dependencyUpdateSelectors = sortedUniqueValues(targetOptions.dependency ?? []);
15518
15365
  const scopedDependencyUpdate = behavior.mode === "update" && dependencyUpdateSelectors.length > 0;
15519
- const scopedPackage = targetOptions.scope ? findConfiguredPackage(config.packages, targetOptions.scope) : void 0;
15366
+ const scopedPackage = targetOptions.scope ? findConfiguredPackage(targetPackages, targetOptions.scope) : void 0;
15520
15367
  const scopedRootId = scopedPackage?.name ?? (source ? targetOptions.scope : void 0);
15521
15368
  if (targetOptions.scope && !scopedPackage && !source) throw new Error(`Configured package not found: ${targetOptions.scope}`);
15522
15369
  if (scopedPackage && targetOptions.onlySource) {
15523
15370
  const group = graphGroupForPackage(groups, target, scopedPackage, targetOptions);
15524
15371
  group.packages.push(scopedPackage);
15525
15372
  } else if (!source || !targetOptions.onlySource) {
15526
- for (const pkg of config.packages) {
15373
+ for (const pkg of targetPackages) {
15527
15374
  const group = graphGroupForPackage(groups, target, pkg, targetOptions);
15528
15375
  group.packages.push(pkg);
15529
15376
  }
15530
15377
  }
15378
+ if (!source && !targetOptions.scope) {
15379
+ for (const pkg of config.packages.filter((candidate) => !targetPackages.includes(candidate))) {
15380
+ graphGroupForPackage(groups, target, pkg, targetOptions);
15381
+ }
15382
+ }
15531
15383
  if (source) {
15532
15384
  let entry = targetOptions.extraPackage ?? await packageEntryFromSource(source, target.workspaceRoot, {
15533
15385
  ...targetOptions,
@@ -15567,6 +15419,11 @@ async function collectGraphPlansForTarget(target, source, options, behavior, bun
15567
15419
  const adapter = await resolveAdapterForTarget(group.target, { ...group.adapterOptions, warn: targetOptions.warn });
15568
15420
  const transport = transportForTarget(group.target);
15569
15421
  const allPackages = [...group.packages, ...group.extraPackages];
15422
+ const excludedRootIds = config.packages.filter((pkg) => !targetPackages.includes(pkg) && graphGroupKey(targetForPackage(target, pkg, targetOptions), {
15423
+ installationType: targetOptions.installationType ?? pkg.installationType ?? target.installationType ?? "local",
15424
+ adapterConfig: targetOptions.adapterConfig ?? target.adapterConfig ?? pkg.adapterConfig,
15425
+ adapterModule: targetOptions.adapterModule ?? target.adapterModule ?? pkg.adapterModule
15426
+ }) === graphGroupKey(group.target, { ...group.adapterOptions, installationType: group.installationType })).map((pkg) => pkg.name);
15570
15427
  const groupHasScope = !scopedRootId || allPackages.some((pkg) => pkg.name === scopedRootId || pkg.source === targetOptions.scope);
15571
15428
  if (behavior.mode === "install" && scopedRootId && !groupHasScope) continue;
15572
15429
  if (behavior.readOnly !== true && targetOptions.dryRun !== true) {
@@ -15665,15 +15522,16 @@ async function collectGraphPlansForTarget(target, source, options, behavior, bun
15665
15522
  ];
15666
15523
  if (behavior.mode === "update") {
15667
15524
  const changed = roots.filter((root) => root.useLock === false);
15668
- if (changed.length === 0 && !scopedDependencyUpdate) {
15525
+ if (changed.length === 0 && !scopedDependencyUpdate && excludedRootIds.length === 0) {
15669
15526
  const label = targetOptions.scope ? ` ${targetOptions.scope}` : "";
15670
15527
  console.log(`No tracking packages to update${label}.`);
15671
15528
  continue;
15672
15529
  }
15673
15530
  }
15674
- if (roots.length === 0) continue;
15675
15531
  const result = await createGraphSourcePlan({
15676
15532
  roots,
15533
+ allowEmptyRoots: roots.length === 0,
15534
+ excludedRootIds,
15677
15535
  targetRoot: group.target.targetRoot,
15678
15536
  workspaceRoot: group.target.workspaceRoot,
15679
15537
  fleetId: group.target.fleetId,
@@ -16307,7 +16165,7 @@ async function uninstallConfiguredPackage(target, packageName, options) {
16307
16165
  if (removed.length === 0) {
16308
16166
  throw new Error(`Configured package not found: ${packageName}`);
16309
16167
  }
16310
- const remaining = config.packages.filter((pkg) => !removed.includes(pkg));
16168
+ const remaining = packagesForCliTarget(config.packages.filter((pkg) => !removed.includes(pkg)), target, options);
16311
16169
  const groups = /* @__PURE__ */ new Map();
16312
16170
  for (const pkg of remaining) {
16313
16171
  const group = graphGroupForPackage(groups, target, pkg, options);
@@ -16443,6 +16301,9 @@ function targetForPackage(target, pkg, options) {
16443
16301
  const installationType = options.installationType ?? pkg.installationType ?? target.installationType;
16444
16302
  return options.adapter || target.source !== "cwd" ? { ...target, installationType } : { ...target, adapter: pkg.adapter, installationType };
16445
16303
  }
16304
+ function packagesForCliTarget(packages, target, options) {
16305
+ return packagesForTarget(packages, target, (pkg) => targetForPackage(target, pkg, options));
16306
+ }
16446
16307
  function graphGroupKey(target, options) {
16447
16308
  return JSON.stringify({
16448
16309
  adapter: target.adapter,
@@ -16619,7 +16480,7 @@ async function collectTargetStatus(target, options) {
16619
16480
  observation.manifestRevision
16620
16481
  ]).sort())).digest("hex") : null;
16621
16482
  const packages = [];
16622
- for (const pkg of config.packages) {
16483
+ for (const pkg of packagesForCliTarget(config.packages, target, options)) {
16623
16484
  const root = effectiveGraphLock?.canonical.roots.find((candidate) => candidate.rootId === pkg.name);
16624
16485
  const node = root ? effectiveGraphLock?.canonical.nodes.find((candidate) => candidate.id === root.graphNodeId) : void 0;
16625
16486
  const availability = await discoverPackageVersions(pkg, target.workspaceRoot, {
@@ -17357,9 +17218,9 @@ function isHomePath(path) {
17357
17218
  }
17358
17219
  function adapterListFromOption(adapter) {
17359
17220
  if (!adapter) return [];
17360
- const adapters2 = splitSelectorList(adapter);
17361
- const unique = [...new Set(adapters2)];
17362
- if (unique.length !== adapters2.length) {
17221
+ const adapters = splitSelectorList(adapter);
17222
+ const unique = [...new Set(adapters)];
17223
+ if (unique.length !== adapters.length) {
17363
17224
  throw new Error(`Duplicate adapter in --adapter: ${adapter}`);
17364
17225
  }
17365
17226
  return unique;
@@ -18,7 +18,7 @@ import {
18
18
  removeApplyJournal,
19
19
  rollbackCompletedOperations,
20
20
  writeApplyJournal
21
- } from "./chunk-BHT57MK5.js";
21
+ } from "./chunk-FGFPAZ4J.js";
22
22
  import "./chunk-BNIF3FUR.js";
23
23
  export {
24
24
  abortApplyJournal,
package/openpack.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "schemaVersion": 2,
3
3
  "name": "NestDevLab/agentwheel",
4
- "version": "0.20.19",
4
+ "version": "0.20.20",
5
5
  "provides": [
6
6
  { "type": "skills", "path": "skills" }
7
7
  ]
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "agentwheel",
3
- "version": "0.20.19",
3
+ "version": "0.20.20",
4
4
  "description": "Weave skills, rules, and instructions across every AI agent.",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -5,7 +5,7 @@ allowed-tools: [Bash]
5
5
  license: MIT
6
6
  metadata:
7
7
  author: NestDevLab
8
- version: "0.20.19"
8
+ version: "0.20.20"
9
9
  ---
10
10
 
11
11
  # agentwheel
@@ -357,6 +357,12 @@ Current config shape:
357
357
 
358
358
  Use named targets:
359
359
 
360
+ Configured packages may declare `"runtimes": ["claude"]` to select adapter runtimes. All
361
+ configured-package plans honor it, including `--agent`, `--profile`, status, and update. Named
362
+ targets match their declared adapter; plain workspace commands match each package's adapter.
363
+ Agents sharing an adapter cannot be selected separately. Upgrade all members to a version
364
+ supporting this field before adding it to shared configuration.
365
+
360
366
  ```bash
361
367
  agentwheel fleet register example-fleet --root /srv/agentwheel/fleets/example-fleet --required-package core-agent-pack
362
368
  agentwheel fleet list
@@ -475,6 +481,9 @@ Drift means a managed runtime output changed outside agentwheel. Fix drift by ch
475
481
  colliding upstream artifact.
476
482
  - Eject an item into `.agentwheel/ejected` when the user wants local ownership.
477
483
 
484
+ When the plan instead keeps a file as foreign or refuses because another workspace owns it, that is
485
+ an ownership problem, not drift: see "Choosing an ownership command" under Troubleshooting.
486
+
478
487
  Append durable local instruction text:
479
488
 
480
489
  ```bash
@@ -646,3 +655,23 @@ before Fleet qualification, owns paths under a fingerprint-only legacy key, run
646
655
  --from-workspace-root <previous-owner-root> --json` from that workspace. It moves only proven,
647
656
  still-desired entries into the stable state; add `--carry-drift` only after reviewing the drifted
648
657
  paths. Apply the emitted command, then require a normal install plan without force flags.
658
+
659
+ ### Choosing an ownership command
660
+
661
+ `agentwheel ownership --help` lists the commands; each subcommand's `--help` is the authoritative flag
662
+ reference. All of them dry-run by default and change only manifest metadata.
663
+
664
+ | Situation | Command |
665
+ |---|---|
666
+ | Unclear who owns what | `ownership recovery-plan` (read-only evidence report) |
667
+ | Refused: paths owned under a fingerprint-only legacy key | `ownership adopt-legacy` |
668
+ | `adopt-legacy` says entries are "already owned by the destination owner" (mixed legacy manifest) | Run a normal `install --agent <agent>` first; it migrates the state and keeps the foreign entry. Then hand off that entry. |
669
+ | Plan keeps one file as a `foreign artifact owned by …` in a stable manifest | `ownership handoff <type/name>` with `--from-workspace-root <root>`, or `--from-unknown-owner` for `workspace:unknown`; add `--to-fleet <id>` for a Fleet owner |
670
+ | Stale foreign entry already covered by the Fleet manifest | `ownership retire-stale` |
671
+
672
+ `handoff` refuses a file whose runtime hash differs from the manifest. If the drift is reviewed and
673
+ harmless, add `--carry-drift`; applying then also needs `--expected-runtime-hash` from the dry-run.
674
+ The recorded hash is kept, so the next install reports `DRIFT` for that file. Replacing it needs
675
+ `install --agent <agent> --force-drift`, which also force-refreshes every merge contribution of that
676
+ target (for example hooks): check that each merge destination is byte-identical afterwards. Never
677
+ narrow that install with `--select`: it removes unselected merge contributions.
@@ -5,7 +5,7 @@ allowed-tools: [Bash]
5
5
  license: MIT
6
6
  metadata:
7
7
  author: NestDevLab
8
- version: "0.20.19"
8
+ version: "0.20.20"
9
9
  ---
10
10
 
11
11
  # Agentwheel Discovery