@agentxm/extension-lifecycle 0.29.4 → 0.30.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.
Files changed (49) hide show
  1. package/dist/src/activation/set-activation.d.ts +22 -40
  2. package/dist/src/activation/set-activation.js +191 -336
  3. package/dist/src/demote/demote-to-external-source.d.ts +1 -1
  4. package/dist/src/demote/demote-to-external-source.js +53 -24
  5. package/dist/src/hooks/install/plan.js +6 -3
  6. package/dist/src/hooks/uninstall/plan.js +4 -3
  7. package/dist/src/index.d.ts +1 -2
  8. package/dist/src/index.js +1 -2
  9. package/dist/src/install/root-intent.d.ts +2 -2
  10. package/dist/src/install/vocabulary.d.ts +5 -4
  11. package/dist/src/knowledge/install/plan.js +2 -1
  12. package/dist/src/knowledge/uninstall/plan.js +4 -3
  13. package/dist/src/mcps/install/plan.js +2 -3
  14. package/dist/src/mcps/operations/uninstall.js +2 -1
  15. package/dist/src/mcps/uninstall/plan.js +13 -4
  16. package/dist/src/packs/graph-transition.d.ts +0 -25
  17. package/dist/src/packs/graph-transition.js +0 -101
  18. package/dist/src/packs/install/plan.d.ts +0 -13
  19. package/dist/src/packs/install/plan.js +12 -9
  20. package/dist/src/packs/member-install-step.js +8 -21
  21. package/dist/src/packs/promote-authored-pack.js +6 -3
  22. package/dist/src/packs/uninstall/plan.js +52 -20
  23. package/dist/src/rules/install/plan.js +6 -3
  24. package/dist/src/rules/uninstall/plan.js +4 -3
  25. package/dist/src/skills/install/bundled.js +4 -4
  26. package/dist/src/skills/install/plan.js +3 -2
  27. package/dist/src/skills/operations/install.d.ts +0 -1
  28. package/dist/src/skills/operations/install.js +9 -18
  29. package/dist/src/skills/uninstall/plan.js +4 -3
  30. package/dist/src/subagents/install/plan.js +3 -2
  31. package/dist/src/subagents/operations/enable.js +1 -3
  32. package/dist/src/subagents/uninstall/plan.js +4 -3
  33. package/dist/src/testing.d.ts +1 -1
  34. package/dist/src/testing.js +2 -1
  35. package/dist/src/uninstall/root-intent.d.ts +1 -1
  36. package/dist/src/uninstall/uninstall-extensions.d.ts +1 -1
  37. package/dist/src/uninstall/uninstall-extensions.js +77 -1
  38. package/dist/src/update/root-request.d.ts +2 -2
  39. package/dist/src/update/selective/skills.d.ts +1 -1
  40. package/dist/src/update/selective/skills.js +0 -1
  41. package/dist/src/update/selective/subagents.d.ts +1 -1
  42. package/dist/src/update/selective/subagents.js +3 -2
  43. package/dist/src/update/selective/use-case.d.ts +2 -2
  44. package/dist/src/update/targeted-plan.js +4 -2
  45. package/dist/src/workspace-paths.d.ts +0 -6
  46. package/dist/src/workspace-paths.js +0 -10
  47. package/package.json +22 -24
  48. package/dist/src/uninstall/retention-policy.d.ts +0 -21
  49. package/dist/src/uninstall/retention-policy.js +0 -28
@@ -10,7 +10,9 @@
10
10
  */
11
11
  import * as Effect from "effect/Effect";
12
12
  import * as Option from "effect/Option";
13
- import { HookManager, KnowledgeManager, NO_MATERIALIZATION_OBSERVATION, RuleManager, SkillManager, SubagentManager, buildInstallOperation, extensionRefLifecycleWarnings, extensionRefRegistryLifecycle, installMcpServer, toLabelWithCompanions, } from "@agentxm/extension-materialization";
13
+ import { HookManager, KnowledgeManager, NO_MATERIALIZATION_OBSERVATION, RuleManager, SkillManager, SubagentManager, } from "@agentxm/extension-materialization";
14
+ import { installMcpServer } from "@agentxm/workspace-reconciliation";
15
+ import { buildInstallOperation, extensionRefLifecycleWarnings, extensionRefRegistryLifecycle, toLabelWithCompanions, } from "@agentxm/workspace-reconciliation";
14
16
  import { WorkspaceMutations } from "@agentxm/workspace-state";
15
17
  import { lifecycleStepFailure } from "../step-failure.js";
16
18
  import { registrySourceArtifact } from "./artifact.js";
@@ -28,9 +30,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
28
30
  return buildInstallOperation(skillManager, {
29
31
  toStepFailure: lifecycleStepFailure,
30
32
  ref,
31
- versionRange: Option.none(),
32
- skipSettings: true,
33
- deferObservableValidation: true,
33
+ enclosingClosure: { projections: [], postconditions: [ref.type] },
34
34
  installedBefore: args.graphComplete
35
35
  ? skillManager.isInstalled({ target: { type: "skill", name: ref.skill.name } })
36
36
  : Effect.succeed(false),
@@ -55,8 +55,6 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
55
55
  ref,
56
56
  nonInteractive: args.nonInteractive,
57
57
  force: false,
58
- versionRange: Option.none(),
59
- skipSettings: Option.some(true),
60
58
  strictAgentSync: Option.some(true),
61
59
  env: Option.none(),
62
60
  },
@@ -82,9 +80,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
82
80
  return buildInstallOperation(subagentManager, {
83
81
  toStepFailure: lifecycleStepFailure,
84
82
  ref,
85
- versionRange: Option.none(),
86
- skipSettings: true,
87
- deferObservableValidation: true,
83
+ enclosingClosure: { projections: [], postconditions: [ref.type] },
88
84
  installedBefore: args.graphComplete
89
85
  ? subagentManager.isInstalled({ target: { type: "subagent", name: ref.subagent.name } })
90
86
  : Effect.succeed(false),
@@ -104,10 +100,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
104
100
  return buildInstallOperation(ruleManager, {
105
101
  toStepFailure: lifecycleStepFailure,
106
102
  ref,
107
- versionRange: Option.none(),
108
- skipSettings: true,
109
- skipProjections: true,
110
- deferObservableValidation: true,
103
+ enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
111
104
  installedBefore: args.graphComplete
112
105
  ? ruleManager.isInstalled({ target: { type: "rule", name: ref.rule.name } })
113
106
  : Effect.succeed(false),
@@ -124,10 +117,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
124
117
  return buildInstallOperation(hookManager, {
125
118
  toStepFailure: lifecycleStepFailure,
126
119
  ref,
127
- versionRange: Option.none(),
128
- skipSettings: true,
129
- skipProjections: true,
130
- deferObservableValidation: true,
120
+ enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
131
121
  installedBefore: args.graphComplete
132
122
  ? hookManager.isInstalled({ target: { type: "hook", name: ref.hook.name } })
133
123
  : Effect.succeed(false),
@@ -143,10 +133,7 @@ export const buildPackMemberInstallStep = Effect.fn("InstallExtensions.buildPack
143
133
  return buildInstallOperation(knowledgeManager, {
144
134
  toStepFailure: lifecycleStepFailure,
145
135
  ref,
146
- versionRange: Option.none(),
147
- skipSettings: true,
148
- skipProjections: true,
149
- deferObservableValidation: true,
136
+ enclosingClosure: { projections: [ref.type], postconditions: [ref.type] },
150
137
  installedBefore: args.graphComplete
151
138
  ? knowledgeManager.isInstalled({ target: { type: "knowledge", name: ref.knowledge.name } })
152
139
  : Effect.succeed(false),
@@ -1,3 +1,4 @@
1
+ import { buildReconciliationClosure } from "@agentxm/workspace-reconciliation";
1
2
  /**
2
3
  * Unpacking a Pack: promoting its members to direct declarations.
3
4
  *
@@ -22,12 +23,13 @@
22
23
  import * as Effect from "effect/Effect";
23
24
  import * as Option from "effect/Option";
24
25
  import * as Path from "effect/Path";
25
- import { PackManager, buildUninstallOperation, } from "@agentxm/extension-materialization";
26
+ import { PackManager } from "@agentxm/extension-materialization";
27
+ import { buildUninstallOperation, } from "@agentxm/workspace-reconciliation";
26
28
  import { operationPresentation, prepareExecutionCandidate, resolveExecutionCandidate, } from "@agentxm/workspace-operations";
27
29
  import { WorkspaceMutations, usableAcceptedCanonical, } from "@agentxm/workspace-state";
28
30
  import { ExtensionLifecycleFailed } from "../errors.js";
29
31
  import { lifecycleStepFailure } from "../step-failure.js";
30
- import { buildAtomicPackGraphStep, validatePackGraphPostcondition } from "./graph-transition.js";
32
+ import { validatePackGraphPostcondition } from "./graph-transition.js";
31
33
  // -----------------------------------------------------------------------------
32
34
  // Promotion
33
35
  // -----------------------------------------------------------------------------
@@ -186,7 +188,8 @@ const settleUnpack = Effect.fn("PromoteAuthoredPack.prepare")(function* (request
186
188
  })),
187
189
  { path: packDisplayPath(path, ws, packNode), change: "removed" },
188
190
  ];
189
- const graphStep = yield* buildAtomicPackGraphStep({
191
+ const graphStep = yield* buildReconciliationClosure({
192
+ toStepFailure: lifecycleStepFailure,
190
193
  label: packNode.identity,
191
194
  message: `Unpacked ${packNode.identity} into ${promotions.length} direct declaration${promotions.length === 1 ? "" : "s"}`,
192
195
  artifact: {
@@ -1,3 +1,4 @@
1
+ import { buildReconciliationClosure } from "@agentxm/workspace-reconciliation";
1
2
  /**
2
3
  * Uninstalling packs.
3
4
  *
@@ -13,7 +14,8 @@ import * as Effect from "effect/Effect";
13
14
  import * as FileSystem from "effect/FileSystem";
14
15
  import * as Option from "effect/Option";
15
16
  import * as Path from "effect/Path";
16
- import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager, buildUninstallOperation, toLabel, } from "@agentxm/extension-materialization";
17
+ import { HookManager, KnowledgeManager, McpServerManager, PackManager, RuleManager, SkillManager, SubagentManager, } from "@agentxm/extension-materialization";
18
+ import { buildUninstallOperation, prepareUninstallArtifact, collectCleanupStep, proposeDesiredState, } from "@agentxm/workspace-reconciliation";
17
19
  import { parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions";
18
20
  import { operationPresentation, } from "@agentxm/workspace-operations";
19
21
  import { WorkspaceMutations, decodeDesiredExtensionIdentity, } from "@agentxm/workspace-state";
@@ -21,9 +23,8 @@ import { expandGlob } from "../../glob.js";
21
23
  import { lifecycleStepFailure } from "../../step-failure.js";
22
24
  import { buildAggregateProjectionStep } from "../../install/aggregate-projection-step.js";
23
25
  import { installRefused } from "../../install/vocabulary.js";
24
- import { exclusiveMemberRetentionPolicy, makeWorkspaceRetentionPolicy, } from "../../uninstall/retention-policy.js";
25
- import { workspaceCanonicalNodePath } from "../../workspace-paths.js";
26
- import { buildAtomicPackGraphStep, validatePackGraphPostcondition } from "../graph-transition.js";
26
+ import { exclusiveMemberRetentionPolicy, makeWorkspaceRetentionPolicy, } from "@agentxm/workspace-reconciliation";
27
+ import { validatePackGraphPostcondition } from "../graph-transition.js";
27
28
  import { PACK_UNINSTALL_GRAPH_BLOCKER_ID, planPackUninstallGraphReadiness, } from "./readiness.js";
28
29
  const normalizedPackIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
29
30
  const identityValidationError = (identity) => installRefused({
@@ -211,7 +212,7 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
211
212
  const retirement = retirementByIdentity.get(normalizedPackIdentity(pack.desiredIdentity));
212
213
  return retirement === undefined ? [] : [[pack.name, retirement]];
213
214
  }));
214
- const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
215
+ const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
215
216
  const allTargets = new Map();
216
217
  for (const pack of intent.packsToUninstall) {
217
218
  allTargets.set(`pack:${pack.name}`, pack);
@@ -234,10 +235,19 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
234
235
  const packTargets = [...allTargets.values()].filter((target) => target.type === "pack");
235
236
  const depTargets = [...allTargets.values()].filter((target) => target.type !== "pack");
236
237
  const orderedTargets = [...depTargets, ...packTargets];
237
- const sourcePathByTarget = new Map(graph.nodes.map((node) => [
238
- `${node.type}:${node.name}`,
239
- workspaceCanonicalNodePath(path, ws, node),
240
- ]));
238
+ const proposal = yield* proposeDesiredState(intent.packsToUninstall.map((pack) => ({ kind: "remove", type: "pack", name: pack.name }))).pipe(Effect.mapError((cause) => installRefused({
239
+ category: "conflict",
240
+ detail: "Pack retirement intent could not be evaluated",
241
+ cause,
242
+ })));
243
+ const artifacts = yield* Effect.forEach(orderedTargets, (target) => prepareUninstallArtifact(target, proposal)).pipe(Effect.mapError((cause) => installRefused({
244
+ category: "conflict",
245
+ detail: "Pack retirement effects could not be established",
246
+ cause,
247
+ })));
248
+ const artifactTargets = artifacts
249
+ .flatMap((artifact) => artifact.targets ?? [])
250
+ .filter((target, index, all) => all.findIndex((candidate) => candidate.path === target.path && candidate.change === target.change) === index);
241
251
  const steps = orderedTargets.map((target) => {
242
252
  switch (target.type) {
243
253
  case "pack": {
@@ -276,44 +286,66 @@ export const planPackUninstall = Effect.fn("UninstallExtensions.planPacks")(func
276
286
  return buildUninstallOperation(ruleManager, exclusiveMemberRetentionPolicy, {
277
287
  toStepFailure: lifecycleStepFailure,
278
288
  target,
279
- skipProjections: true,
289
+ enclosingClosure: { projections: [target.type] },
280
290
  });
281
291
  case "hook":
282
292
  return buildUninstallOperation(hookManager, exclusiveMemberRetentionPolicy, {
283
293
  toStepFailure: lifecycleStepFailure,
284
294
  target,
285
- skipProjections: true,
295
+ enclosingClosure: { projections: [target.type] },
286
296
  });
287
297
  case "knowledge":
288
298
  return buildUninstallOperation(knowledgeManager, exclusiveMemberRetentionPolicy, {
289
299
  toStepFailure: lifecycleStepFailure,
290
300
  target,
291
- skipProjections: true,
301
+ enclosingClosure: { projections: [target.type] },
292
302
  });
293
303
  }
294
304
  });
305
+ const activeNames = (type) => new Set(proposal.after.nodes
306
+ .filter((node) => node.type === type && node.enabled)
307
+ .map((node) => node.name));
308
+ const cleanup = plannedRetirements.length > 0
309
+ ? Option.none()
310
+ : yield* collectCleanupStep({
311
+ expectedSkillNames: activeNames("skill"),
312
+ expectedSubagentNames: activeNames("subagent"),
313
+ expectedMcpServerNames: activeNames("mcp-server"),
314
+ expectedHookNames: activeNames("hook"),
315
+ subjects: orderedTargets,
316
+ adapter: {
317
+ toStepFailure: (cause) => lifecycleStepFailure(installRefused({
318
+ category: "conflict",
319
+ detail: ("detail" in cause ? cause.detail : undefined) ?? cause._tag,
320
+ cause,
321
+ })),
322
+ },
323
+ }).pipe(Effect.mapError((cause) => installRefused({
324
+ category: "conflict",
325
+ detail: "Cannot establish owned Pack uninstall outputs",
326
+ cause,
327
+ })));
295
328
  const projectionStep = yield* buildAggregateProjectionStep({
296
329
  types: new Set(orderedTargets.map((target) => target.type)),
297
330
  });
298
331
  const registrationOnly = plannedRetirements.length === 0
299
332
  ? ""
300
333
  : ` (${plannedRetirements.length} pack${plannedRetirements.length === 1 ? "" : "s"} unregistered without removing package content)`;
301
- const graphStep = yield* buildAtomicPackGraphStep({
334
+ const graphStep = yield* buildReconciliationClosure({
335
+ toStepFailure: lifecycleStepFailure,
302
336
  label: `${intent.packsToUninstall.length} pack${intent.packsToUninstall.length === 1 ? "" : "s"}`,
303
337
  message: `Uninstalled ${intent.packsToUninstall.length} pack${intent.packsToUninstall.length === 1 ? "" : "s"} and ${depTargets.length} exclusive member${depTargets.length === 1 ? "" : "s"}${registrationOnly}`,
304
338
  artifact: {
305
- path: "pack graph",
339
+ path: artifacts[0]?.path ?? path.relative(ws.baseDir, ws.layout.settingsPath),
306
340
  scope: ws.scope,
307
341
  change: "removed",
308
342
  fileCount: orderedTargets.length,
309
- targets: orderedTargets.map((target) => ({
310
- path: sourcePathByTarget.get(`${target.type}:${target.name}`) ?? toLabel(target),
311
- // Content AXM could not verify is preserved, so its canonical path is
312
- // never reported as removed.
313
- change: target.type === "pack" && retirementByPackName.has(target.name) ? "unchanged" : "removed",
314
- })),
343
+ targets: artifactTargets,
344
+ references: artifacts.flatMap((artifact) => artifact.references ?? []),
345
+ managedRegions: artifacts.flatMap((artifact) => artifact.managedRegions ?? []),
315
346
  },
316
347
  children: [
348
+ ...Option.toArray(cleanup).map((step) => ({ step, coverage: "ineligible" })),
317
349
  ...steps.map((step) => ({ step, coverage: "ineligible" })),
318
350
  ...Option.toArray(projectionStep).map((step) => ({
319
351
  step,
@@ -9,7 +9,8 @@
9
9
  */
10
10
  import * as Effect from "effect/Effect";
11
11
  import * as Option from "effect/Option";
12
- import { RuleManager, buildInstallOperation } from "@agentxm/extension-materialization";
12
+ import { RuleManager } from "@agentxm/extension-materialization";
13
+ import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
13
14
  import { parseSourceQualifiedRegistrySourcePatternParts, } from "@agentxm/extension-model/unstable/extensions";
14
15
  import { SourceHostProviders, resolveSource } from "@agentxm/extension-sources";
15
16
  import { operationPresentation, } from "@agentxm/workspace-operations";
@@ -86,8 +87,10 @@ export const planRuleInstall = Effect.fn("InstallExtensions.planRules")(function
86
87
  const memberSteps = intent.refs.map(({ ref, versionRange }) => buildInstallOperation(ruleManager, {
87
88
  toStepFailure: lifecycleStepFailure,
88
89
  ref,
89
- versionRange,
90
- skipProjections: deferProjections,
90
+ declaration: { name: ref.rule.name, versionRange },
91
+ ...(deferProjections
92
+ ? { enclosingClosure: { projections: [ref.type], postconditions: [] } }
93
+ : {}),
91
94
  installedBefore: ruleManager.isInstalled({
92
95
  target: { type: "rule", name: ref.rule.name },
93
96
  }),
@@ -8,11 +8,12 @@
8
8
  */
9
9
  import * as Effect from "effect/Effect";
10
10
  import * as Option from "effect/Option";
11
- import { RuleManager, buildUninstallOperation } from "@agentxm/extension-materialization";
11
+ import { RuleManager } from "@agentxm/extension-materialization";
12
+ import { buildUninstallOperation } from "@agentxm/workspace-reconciliation";
12
13
  import { WorkspaceMutations } from "@agentxm/workspace-state";
13
14
  import { lifecycleStepFailure } from "../../step-failure.js";
14
15
  import { installRefused } from "../../install/vocabulary.js";
15
- import { makeWorkspaceRetentionPolicy } from "../../uninstall/retention-policy.js";
16
+ import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
16
17
  /** Settle whether this rule has anything to remove. */
17
18
  export const parseRuleUninstallRequest = Effect.fn("UninstallExtensions.parseRuleRequest")(function* (selector) {
18
19
  const ruleManager = yield* RuleManager;
@@ -35,7 +36,7 @@ export const parseRuleUninstallRequest = Effect.fn("UninstallExtensions.parseRul
35
36
  export const planRuleUninstall = Effect.fn("UninstallExtensions.planRules")(function* (intent) {
36
37
  const ws = yield* WorkspaceMutations;
37
38
  const ruleManager = yield* RuleManager;
38
- const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
39
+ const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
39
40
  return {
40
41
  _tag: "Plan",
41
42
  name: "Uninstall rule",
@@ -1,3 +1,4 @@
1
+ import { renderAxmSkillRecovery } from "@agentxm/cli-maintenance/official-skill/adapters/cli";
1
2
  /**
2
3
  * Installing the official AXM skill that ships inside the CLI.
3
4
  *
@@ -16,7 +17,7 @@ import * as FileSystem from "effect/FileSystem";
16
17
  import * as Option from "effect/Option";
17
18
  import * as Path from "effect/Path";
18
19
  import { ensureSkillAgentArtifact, replaceCanonicalDirectory, } from "@agentxm/extension-materialization";
19
- import { AXM_SKILL_CLI_VERSION_METADATA_KEY, AXM_SKILL_CLI_VERSION_RANGE_METADATA_KEY, AXM_SKILL_FQN, evaluateAxmSkillCompatibility, } from "@agentxm/extension-resolution";
20
+ import { AXM_SKILL_CLI_VERSION_METADATA_KEY, AXM_SKILL_CLI_VERSION_RANGE_METADATA_KEY, AXM_SKILL_FQN, evaluateAxmSkillCompatibility, } from "@agentxm/cli-maintenance/official-skill/domain";
20
21
  import { operationPresentation, } from "@agentxm/workspace-operations";
21
22
  import { CodingAgentRepository } from "@agentxm/workspace-projection";
22
23
  import { WorkspaceMutations, sanitizeName } from "@agentxm/workspace-state";
@@ -173,13 +174,12 @@ export const installBundledAxmSkill = Effect.gen(function* () {
173
174
  },
174
175
  });
175
176
  if (compatibility.status === "incompatible") {
177
+ const recovery = renderAxmSkillRecovery(compatibility.recovery);
176
178
  return yield* installRefused({
177
179
  category: "internal",
178
180
  detail: compatibility.detail ??
179
181
  "Bundled AXM skill remained incompatible after workspace installation",
180
- ...(compatibility.recovery.nextAction === null
181
- ? {}
182
- : { cmd: compatibility.recovery.nextAction }),
182
+ ...(recovery.nextAction === null ? {} : { cmd: recovery.nextAction }),
183
183
  });
184
184
  }
185
185
  }),
@@ -17,7 +17,8 @@ import * as Option from "effect/Option";
17
17
  import * as Path from "effect/Path";
18
18
  import * as Result from "effect/Result";
19
19
  import * as Schema from "effect/Schema";
20
- import { SkillManager, artifactAgentIdsFromTargets, artifactTargetAgentIds, buildInstallOperation, computeSkillSourceHash, groupInstallTargetsByDirectory, } from "@agentxm/extension-materialization";
20
+ import { SkillManager, artifactAgentIdsFromTargets, artifactTargetAgentIds, computeSkillSourceHash, groupInstallTargetsByDirectory, } from "@agentxm/extension-materialization";
21
+ import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
21
22
  import { matchesReleaseAgeExcludePattern, } from "@agentxm/extension-model/unstable/extensions";
22
23
  import { PackageUrlPartsSchema, formatPackageDisplay, } from "@agentxm/extension-model/unstable/packaging";
23
24
  import { parseInputPattern, } from "@agentxm/extension-model/unstable/sources/parser";
@@ -379,7 +380,7 @@ export const planSkillInstall = Effect.fn("InstallExtensions.planSkills")(functi
379
380
  return withPlanWarning(buildInstallOperation(skillManager, {
380
381
  toStepFailure: lifecycleStepFailure,
381
382
  ref,
382
- versionRange: entry.versionRange,
383
+ declaration: { name: ref.skill.name, versionRange: entry.versionRange },
383
384
  force: intent.force === true,
384
385
  installedBefore: Effect.succeed(installedBefore),
385
386
  buildArtifact: ({ installedBefore }) => Effect.gen(function* () {
@@ -30,7 +30,6 @@ export type InstallSkillOperationArgs = {
30
30
  /** Version constraint from the original input when available. */
31
31
  readonly versionRange: Option.Option<string>;
32
32
  /** When true, write to lockfile only (skip settings). Used for pack dependencies. */
33
- readonly skipSettings: Option.Option<boolean>;
34
33
  /** When true, fail on unknown configured agents instead of warning+skip. */
35
34
  readonly strictUnknownAgents: Option.Option<boolean>;
36
35
  /** Named registry source that provided the ref (written to lockfile for registry skills). */
@@ -529,25 +529,16 @@ export const installSkill = (op) => Effect.gen(function* () {
529
529
  }),
530
530
  };
531
531
  }
532
- const skipSettings = Option.getOrElse(op.args.skipSettings, () => false);
533
532
  const writeEffect = baseLockEntry === undefined
534
- ? skipSettings
535
- ? Effect.void
536
- : ws.setSkillEntry(ref.skill.name, {
537
- source: ref.refType === "workspace" ? "workspace" : printSourceParams(ref.source),
538
- enabled: true,
539
- })
540
- : skipSettings
541
- ? ws.setSkillLock({
542
- name: ref.skill.name,
543
- lockEntry: baseLockEntry,
544
- versionRange: materialized.versionRange,
545
- })
546
- : ws.setSkill({
547
- name: ref.skill.name,
548
- lockEntry: baseLockEntry,
549
- versionRange: materialized.versionRange,
550
- });
533
+ ? ws.setSkillEntry(ref.skill.name, {
534
+ source: ref.refType === "workspace" ? "workspace" : printSourceParams(ref.source),
535
+ enabled: true,
536
+ })
537
+ : ws.setSkill({
538
+ name: ref.skill.name,
539
+ lockEntry: baseLockEntry,
540
+ versionRange: materialized.versionRange,
541
+ });
551
542
  const writeFailure = yield* writeEffect.pipe(Effect.result);
552
543
  if (writeFailure._tag === "Failure") {
553
544
  const failure = writeFailure.failure;
@@ -12,14 +12,15 @@ import * as Effect from "effect/Effect";
12
12
  import * as FileSystem from "effect/FileSystem";
13
13
  import * as Option from "effect/Option";
14
14
  import * as Path from "effect/Path";
15
- import { SkillManager, buildUninstallOperation, skillArtifactFromTargets, } from "@agentxm/extension-materialization";
15
+ import { SkillManager, skillArtifactFromTargets, } from "@agentxm/extension-materialization";
16
+ import { buildUninstallOperation } from "@agentxm/workspace-reconciliation";
16
17
  import { resolveInstalledIdentifierNameOrInput } from "@agentxm/extension-sources";
17
18
  import { CodingAgentRepository } from "@agentxm/workspace-projection";
18
19
  import { WorkspaceMutations, acquiredExtensionDisplayPathFromLockEntry, installedRowsByName, sanitizeName, } from "@agentxm/workspace-state";
19
20
  import { expandGlob } from "../../glob.js";
20
21
  import { lifecycleStepFailure } from "../../step-failure.js";
21
22
  import { installRefused, } from "../../install/vocabulary.js";
22
- import { makeWorkspaceRetentionPolicy } from "../../uninstall/retention-policy.js";
23
+ import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
23
24
  import { workspaceAuthoredPath, workspaceCanonicalPath, workspaceCanonicalRoot, workspaceLockfilePath, workspaceSettingsPath, } from "../../workspace-paths.js";
24
25
  const skillSourceTarget = (ws, path, configuredSource, lockEntry, sanitizedName) => {
25
26
  if (Option.isSome(configuredSource) && configuredSource.value === "workspace") {
@@ -69,7 +70,7 @@ export const planSkillUninstall = Effect.fn("UninstallExtensions.planSkills")(fu
69
70
  const skillManager = yield* SkillManager;
70
71
  const agentRepo = yield* CodingAgentRepository;
71
72
  const path = yield* Path.Path;
72
- const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
73
+ const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
73
74
  const configuredAgents = yield* agentRepo.getMaterializationAgents().pipe(Effect.mapError((cause) => installRefused({
74
75
  category: "internal",
75
76
  detail: "Configured agents could not be read",
@@ -10,7 +10,8 @@
10
10
  import * as Array from "effect/Array";
11
11
  import * as Effect from "effect/Effect";
12
12
  import * as Option from "effect/Option";
13
- import { NO_MATERIALIZATION_OBSERVATION, SubagentManager, buildInstallOperation, } from "@agentxm/extension-materialization";
13
+ import { NO_MATERIALIZATION_OBSERVATION, SubagentManager, } from "@agentxm/extension-materialization";
14
+ import { buildInstallOperation } from "@agentxm/workspace-reconciliation";
14
15
  import { parseInputPattern, } from "@agentxm/extension-model/unstable/sources/parser";
15
16
  import { SourceHostProviders, sourceResolutionFailureCategory, } from "@agentxm/extension-sources";
16
17
  import { operationPresentation, } from "@agentxm/workspace-operations";
@@ -216,7 +217,7 @@ export const planSubagentInstall = Effect.fn("InstallExtensions.planSubagents")(
216
217
  return buildInstallOperation(subagentManager, {
217
218
  toStepFailure: lifecycleStepFailure,
218
219
  ref,
219
- versionRange: entry.versionRange,
220
+ declaration: { name: ref.subagent.name, versionRange: entry.versionRange },
220
221
  installedBefore: subagentManager
221
222
  .isInstalled({ target: { type: "subagent", name: ref.subagent.name } })
222
223
  .pipe(Effect.catch(() => Effect.succeed(false))),
@@ -64,9 +64,7 @@ export const enableSubagent = (op) => Effect.gen(function* () {
64
64
  });
65
65
  }
66
66
  const baseDir = ws.baseDir;
67
- const subagentSrcPath = canonical.value.ref.refType === "registry" || canonical.value.ref.refType === "workspace"
68
- ? path.join(canonical.value.observation.path, "src")
69
- : canonical.value.observation.path;
67
+ const subagentSrcPath = path.join(canonical.value.observation.path, "src");
70
68
  // Read and parse the subagent content file
71
69
  const expectedFilename = subagentContentFilename(op.args.subagentName);
72
70
  const contentPath = subagentContentPath(path.join, subagentSrcPath, op.args.subagentName);
@@ -9,13 +9,14 @@
9
9
  */
10
10
  import * as Effect from "effect/Effect";
11
11
  import * as Option from "effect/Option";
12
- import { NO_MATERIALIZATION_OBSERVATION, SubagentManager, buildUninstallOperation, } from "@agentxm/extension-materialization";
12
+ import { NO_MATERIALIZATION_OBSERVATION, SubagentManager, } from "@agentxm/extension-materialization";
13
+ import { buildUninstallOperation } from "@agentxm/workspace-reconciliation";
13
14
  import { parseExtensionFqnParts } from "@agentxm/extension-model/unstable/extensions";
14
15
  import { WorkspaceMutations, acquiredExtensionDisplayPathFromLockEntry, } from "@agentxm/workspace-state";
15
16
  import { expandGlob } from "../../glob.js";
16
17
  import { lifecycleStepFailure } from "../../step-failure.js";
17
18
  import { installRefused } from "../../install/vocabulary.js";
18
- import { makeWorkspaceRetentionPolicy } from "../../uninstall/retention-policy.js";
19
+ import { makeWorkspaceRetentionPolicy } from "@agentxm/workspace-reconciliation";
19
20
  import { workspaceCanonicalPath, workspaceCanonicalRoot, workspaceLockfilePath, workspaceSettingsPath, } from "../../workspace-paths.js";
20
21
  const resolvedVersion = (entry) => entry !== undefined && entry.type === "registry" ? entry.resolvedVersion : undefined;
21
22
  const subagentSourceTarget = (args) => args.lockEntry === undefined
@@ -77,7 +78,7 @@ export const parseSubagentUninstallRequest = Effect.fn("UninstallExtensions.pars
77
78
  export const planSubagentUninstall = Effect.fn("UninstallExtensions.planSubagents")(function* (intent) {
78
79
  const ws = yield* WorkspaceMutations;
79
80
  const subagentManager = yield* SubagentManager;
80
- const retentionPolicy = makeWorkspaceRetentionPolicy(ws);
81
+ const retentionPolicy = makeWorkspaceRetentionPolicy(ws, lifecycleStepFailure);
81
82
  // The accepted resolution names the package the removal retires, and the
82
83
  // removal deletes it, so it is read before the step runs.
83
84
  const steps = yield* Effect.forEach(intent.targets, (target) => Effect.gen(function* () {
@@ -99,7 +99,7 @@ export declare const makeLifecycleFixture: (options?: LifecycleFixtureOptions) =
99
99
  readonly type: "skill" | "subagent";
100
100
  readonly offered: ReadonlyArray<string>;
101
101
  }>;
102
- provide: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | import("@agentxm/workspace-state").WorkspaceMutationsError, import("effect/FileSystem").FileSystem | import("effect/Path").Path | Exclude<R, StepFailureConversion | import("@agentxm/workspace-state").WorkspaceMutations | import("@agentxm/workspace-transactions").WorkspaceTransactionScope | import("@agentxm/workspace-projection").CodingAgentRepository | import("@agentxm/agent-integration").NativeWriteAuthority | import("@agentxm/workspace-state").ConfiguredAgentOutcomesProvider | import("@agentxm/extension-materialization").ExtensionManagers | import("@agentxm/workspace-transactions").FootprintRecorder | HttpClient.HttpClient | import("@agentxm/workspace-operations").OperationJournal | import("@agentxm/extension-materialization").McpSecretStore | ReleaseAgePosture | import("@agentxm/workspace-operations").ResolvePlanInteraction | SourceHostProviders | import("@agentxm/extension-materialization").SubagentManager | import("@agentxm/extension-sources").WorkspaceCatalog | import("@agentxm/extension-materialization").HookManager | import("@agentxm/extension-materialization").KnowledgeManager | import("@agentxm/extension-materialization").RuleManager | import("@agentxm/extension-materialization").SkillManager | import("@agentxm/extension-materialization").McpServerManager | import("@agentxm/extension-materialization").PackManager | ExtensionSelectionInteraction | BundledAxmSkillAsset | AgentExecutableResolver | import("@agentxm/workspace-state/live").WorkspaceStateServices | import("@agentxm/workspace-projection").ProjectionParticipants | import("@agentxm/workspace-projection").WorkspaceInvariantFacts>>;
102
+ provide: <A, E, R>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | import("@agentxm/workspace-state").WorkspaceMutationsError, import("effect/FileSystem").FileSystem | import("effect/Path").Path | Exclude<R, StepFailureConversion | import("@agentxm/workspace-state").WorkspaceMutations | import("@agentxm/workspace-transactions").WorkspaceTransactionScope | import("@agentxm/workspace-projection").CodingAgentRepository | import("@agentxm/agent-integration").NativeWriteAuthority | HttpClient.HttpClient | import("@agentxm/workspace-state").ConfiguredAgentOutcomesProvider | import("@agentxm/extension-materialization").ExtensionManagers | import("@agentxm/extension-materialization").HookManager | import("@agentxm/extension-materialization").SkillManager | import("@agentxm/extension-materialization").RuleManager | import("@agentxm/extension-materialization").KnowledgeManager | import("@agentxm/extension-materialization").PackManager | import("@agentxm/extension-materialization").McpServerManager | import("@agentxm/workspace-transactions").FootprintRecorder | import("@agentxm/workspace-operations").OperationJournal | import("@agentxm/extension-materialization").McpSecretStore | ReleaseAgePosture | import("@agentxm/workspace-operations").ResolvePlanInteraction | SourceHostProviders | import("@agentxm/extension-materialization").SubagentManager | import("@agentxm/extension-sources").WorkspaceCatalog | import("@agentxm/workspace-projection").WorkspaceInvariantFacts | ExtensionSelectionInteraction | BundledAxmSkillAsset | AgentExecutableResolver | import("@agentxm/workspace-state/live").WorkspaceStateServices | import("@agentxm/workspace-projection").ProjectionParticipants>>;
103
103
  cleanup: () => void;
104
104
  };
105
105
  export type LifecycleFixture = ReturnType<typeof makeLifecycleFixture>;
@@ -21,7 +21,8 @@ import * as HttpClient from "effect/unstable/http/HttpClient";
21
21
  import { AgentExecutableResolver } from "@agentxm/agent-integration";
22
22
  import { decodeAbsolutePathSync } from "@agentxm/extension-model/unstable/path-types";
23
23
  import { ExtensionManagersLive, HookManagerLive, KnowledgeManagerLive, McpSecretStoreLive, McpServerManagerLive, PackManagerLive, ProjectionParticipantsLive, RuleManagerLive, SkillManagerLive, SubagentManagerLive, } from "@agentxm/extension-materialization/live";
24
- import { ReleaseAgePosture, decideNamedRegistryVersion, makeAxmSkillCompatibilityPolicyLayer, namedRegistryCandidates, resolveVersionEntryWithReleaseAge, } from "@agentxm/extension-resolution";
24
+ import { ReleaseAgePosture, decideNamedRegistryVersion, namedRegistryCandidates, resolveVersionEntryWithReleaseAge, } from "@agentxm/extension-resolution";
25
+ import { makeAxmSkillCompatibilityPolicyLayer } from "@agentxm/cli-maintenance/official-skill/composition";
25
26
  import { AxmSkillCandidateGateLive } from "@agentxm/extension-resolution/live";
26
27
  import { RegistryResolutionPolicy, SourceHostProviders } from "@agentxm/extension-sources";
27
28
  import { SourceHostProvidersLive } from "@agentxm/extension-sources/live";
@@ -1,7 +1,7 @@
1
1
  import * as Effect from "effect/Effect";
2
2
  import type { ExtensionLifecycleFailed } from "../errors.js";
3
3
  import { type InstallableExtensionType } from "@agentxm/extension-model/unstable/extensions/installable-types";
4
- export declare const rootUninstallableTypeSegments: readonly ("knowledge" | "rules" | "hooks" | "mcps" | "skills" | "subagents" | "packs")[];
4
+ export declare const rootUninstallableTypeSegments: readonly ("knowledge" | "rules" | "hooks" | "skills" | "subagents" | "packs" | "mcps")[];
5
5
  export type RootUninstallableType = InstallableExtensionType;
6
6
  export interface RootUninstallIntent {
7
7
  readonly source: string;
@@ -13,7 +13,7 @@ import * as Effect from "effect/Effect";
13
13
  import * as Option from "effect/Option";
14
14
  import type { InstallableExtensionType } from "@agentxm/extension-model/unstable/extensions/installable-types";
15
15
  import { type ExecutionCandidate, type OperationResolution, type PlanExecution } from "@agentxm/workspace-operations";
16
- import type { ExtensionLifecycleFailed } from "../errors.js";
16
+ import { ExtensionLifecycleFailed } from "../errors.js";
17
17
  import { type PackUninstallRequirements } from "../packs/uninstall/plan.js";
18
18
  import type { InstallExecutionFailure, PrepareInstallRequirements } from "../install/vocabulary.js";
19
19
  /** One uninstall request, whatever command spelling produced it. */