@agentxm/workspace-sync 0.28.4 → 0.28.5
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/dist/src/index.d.ts +1 -1
- package/dist/src/index.js +1 -1
- package/dist/src/materialize.d.ts +3 -1
- package/dist/src/materialize.js +4 -22
- package/dist/src/plan.d.ts +4 -2
- package/dist/src/plan.js +19 -23
- package/dist/src/rendered-file-cleanup.d.ts +11 -29
- package/dist/src/rendered-file-cleanup.js +94 -356
- package/package.json +7 -6
package/dist/src/index.d.ts
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { WorkspaceSyncFailed, type WorkspaceSyncCleanupFailure } from "./errors.js";
|
|
10
10
|
export { type SyncFailureAdapter, type SyncPolicyFailure } from "./failure-adapter.js";
|
|
11
|
-
export {
|
|
11
|
+
export { inspectWorkspaceOwnership, reconcileAgentOutputs, type ReconcileAgentOutputsArgs, type ReconcileAgentOutputsResult, } from "./rendered-file-cleanup.js";
|
|
12
12
|
export { buildInlineMcpServerSyncOperation, buildMcpServerPruneOperation, collectCleanupStep, collectHooksStep, collectInstructionStep, collectKnowledgeStep, isInlineMcpServerEntry, makeSyncPlan, projectionDivergenceLabel, projectionFactsNeedReconciliation, SYNC_PLAN_DESCRIPTION, SYNC_PLAN_NAME, SYNC_PRESENTATION, SYNC_RECOVERY_IDS, syncRecoveryIdentifiers, type SyncStepRequirements, } from "./plan.js";
|
|
13
13
|
export { collectMaterializeSteps, normalizedIdentity, recoverableExternalPackName, scopedProblems, type ConfiguredPackRecovery, type ResolvedDesiredRef, type RunMcpServerInstall, type SyncSelection, } from "./materialize.js";
|
|
14
14
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/src/index.js
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
*/
|
|
9
9
|
export { WorkspaceSyncFailed } from "./errors.js";
|
|
10
10
|
export {} from "./failure-adapter.js";
|
|
11
|
-
export {
|
|
11
|
+
export { inspectWorkspaceOwnership, reconcileAgentOutputs, } from "./rendered-file-cleanup.js";
|
|
12
12
|
export { buildInlineMcpServerSyncOperation, buildMcpServerPruneOperation, collectCleanupStep, collectHooksStep, collectInstructionStep, collectKnowledgeStep, isInlineMcpServerEntry, makeSyncPlan, projectionDivergenceLabel, projectionFactsNeedReconciliation, SYNC_PLAN_DESCRIPTION, SYNC_PLAN_NAME, SYNC_PRESENTATION, SYNC_RECOVERY_IDS, syncRecoveryIdentifiers, } from "./plan.js";
|
|
13
13
|
export { collectMaterializeSteps, normalizedIdentity, recoverableExternalPackName, scopedProblems, } from "./materialize.js";
|
|
14
14
|
//# sourceMappingURL=index.js.map
|
|
@@ -64,6 +64,8 @@ export declare const collectMaterializeSteps: <E = never, R = SyncStepRequiremen
|
|
|
64
64
|
serialMaterialization: boolean;
|
|
65
65
|
expectedSkillNames: Set<string & import("effect/Brand").Brand<"ExtensionName">>;
|
|
66
66
|
expectedSubagentNames: Set<string & import("effect/Brand").Brand<"ExtensionName">>;
|
|
67
|
+
expectedMcpServerNames: Set<string>;
|
|
68
|
+
expectedHookNames: Set<string & import("effect/Brand").Brand<"ExtensionName">>;
|
|
67
69
|
releaseAge: {
|
|
68
70
|
evaluatedAt: string;
|
|
69
71
|
holdbacks: readonly import("@agentxm/registry-protocol/unstable/registry/release-age-policy").ReleaseAgeRecordBase[];
|
|
@@ -121,5 +123,5 @@ export declare const collectMaterializeSteps: <E = never, R = SyncStepRequiremen
|
|
|
121
123
|
registryLifecycle?: import("@agentxm/workspace-operations").RegistryLifecycleEvidence;
|
|
122
124
|
run: Effect.Effect<JobStepResult<never>, StepFailure, never>;
|
|
123
125
|
})[];
|
|
124
|
-
}, WorkspaceSyncFailed | import("@agentxm/extension-workspace").CoupledDependencyFailure | import("@agentxm/extension-workspace").PackageMaterializationFailed | import("@agentxm/extension-workspace").StagedPackageInvalid | import("@agentxm/extension-workspace").CanonicalPackageProbeFailed | import("@agentxm/extension-workspace").PackageCopyFailed | import("@agentxm/extension-workspace").ArchiveIntegrityMismatch | import("@agentxm/extension-workspace").CreateDestinationExists | import("@agentxm/extension-workspace").CreateNameConfigured | import("@agentxm/extension-workspace").CreateDestinationInspectionFailed | import("@agentxm/workspace-state").PathTraversalDetected | import("@agentxm/extension-workspace").ForkPackageInvalid | import("@agentxm/extension-workspace").ForkPackageConflict | import("@agentxm/extension-workspace").ForkPackageFailed | import("@agentxm/extension-workspace").NativeImportUnsupported | import("@agentxm/extension-workspace").NativeImportInvalid | import("@agentxm/extension-workspace").NativeImportConflict | import("@agentxm/extension-workspace").NativeImportFailed | import("@agentxm/extension-workspace").SourceAuthorityBlocked | import("@agentxm/extension-workspace").LifecyclePostconditionViolated | import("@agentxm/extension-workspace").ScaffoldedExtensionUnresolved | import("@agentxm/extension-workspace").DesiredStateIncomplete | import("@agentxm/extension-workspace").AuthoredContributorUnsupported | import("@agentxm/extension-workspace").ContributorIdentityInvalid | import("@agentxm/extension-workspace").ContributorUnresolved | import("@agentxm/extension-workspace").ContributorTreeMismatch | import("@agentxm/extension-workspace").ProjectionTargetUnsupported | import("@agentxm/extension-workspace").ManagedRegionViolation | import("@agentxm/extension-workspace").ProjectionIoFailed | import("@agentxm/extension-workspace").InstructionMaintenanceFailed | import("@agentxm/extension-workspace").RuleDefinitionInvalid | import("@agentxm/extension-workspace").RuleInstallStateMissing | import("@agentxm/extension-workspace").HookDefinitionInvalid | import("@agentxm/extension-workspace").HookConfigInvalid | import("@agentxm/extension-workspace").HookIoFailed | import("@agentxm/extension-workspace").HookInstallStateMissing | import("@agentxm/extension-workspace").SubagentDefinitionInvalid | import("@agentxm/extension-workspace").SubagentContentUnreadable | import("@agentxm/extension-workspace").SubagentIoFailed | import("@agentxm/extension-workspace").SubagentInstallStateMissing | import("@agentxm/extension-workspace").McpConfigInvalid | import("@agentxm/extension-workspace").McpConfigIoFailed | import("@agentxm/extension-workspace").McpEntryUnmanaged | import("@agentxm/extension-workspace").McpOwnershipMarkerInvalid | import("@agentxm/extension-workspace").McpDefinitionInvalid | import("@agentxm/extension-workspace").McpRegistryOnlyInstall | import("@agentxm/extension-workspace").McpInstallStateMissing | import("@agentxm/extension-workspace").McpSharedTargetConflict | import("@agentxm/extension-workspace").SkillDefinitionInvalid | import("@agentxm/extension-workspace").SkillMaterializationFailed | import("@agentxm/extension-workspace").SkillInstallStateMissing | import("@agentxm/extension-workspace").AxmSkillCompatibilityUnavailable | import("@agentxm/extension-workspace").AxmSkillIncompatible | import("@agentxm/extension-workspace").PackDefinitionInvalid | import("@agentxm/extension-workspace").PackInstallStateMissing | import("@agentxm/extension-workspace").PackArchiveFetchFailed | import("@agentxm/extension-workspace").PackStagingFailed | import("@agentxm/extension-workspace").PackDependencyInvalid | import("@agentxm/extension-workspace").PackDependencyConflict | import("@agentxm/extension-workspace").PackConstraintShadowed | import("@agentxm/extension-workspace").PackDependencyMissing | import("@agentxm/extension-workspace").PackDependencyUnsatisfied | import("@agentxm/extension-workspace").KnowledgeDefinitionInvalid | import("@agentxm/extension-workspace").KnowledgeIoFailed | import("@agentxm/extension-workspace").KnowledgeInstallStateMissing | import("@agentxm/extension-workspace").KnowledgeResolutionMissing | import("@agentxm/extension-workspace").KnowledgeDesiredStateUnreconcilable | import("@agentxm/extension-workspace").KnowledgeUnavailable | import("@agentxm/extension-workspace").KnowledgeObservableContractViolated | import("@agentxm/workspace-state").MaterializedTreeInvalid | import("@agentxm/extension-workspace").TransientBackupFailed | import("@agentxm/extension-workspace").WriteBackupRetained | import("@agentxm/workspace-state").SettingsIoError | import("@agentxm/workspace-state").SettingsParseError | import("@agentxm/workspace-state").SettingsDecodeError | import("@agentxm/workspace-state").LockfileIoError | import("@agentxm/workspace-state").LockfileParseError | import("@agentxm/workspace-state").LockfileDecodeError | import("@agentxm/workspace-state").WorkspaceRootEscape | import("@agentxm/workspace-state").SettingsWriteError | import("@agentxm/workspace-state").WorkspaceSnapshotError | import("@agentxm/workspace-state").LockfileValidationError | import("@agentxm/workspace-state").LockfileWriteError | import("@agentxm/workspace-state").WorkspaceDirectoryError | import("@agentxm/workspace-state").TransitionLockError | import("@agentxm/workspace-state").TransitionLockUnavailable | import("@agentxm/workspace-state").WorkspaceTransitionCompromised | import("@agentxm/workspace-state").WorkspaceRestorationIncomplete | import("@agentxm/workspace-state").WorkspaceLayoutError | import("@agentxm/workspace-state").WorkspaceNotInitialized | import("@agentxm/workspace-state").LockedSkillMissing | import("@agentxm/workspace-state").SettingsEntryMissing | import("@agentxm/workspace-state").InvalidAgentId | import("@agentxm/workspace-state").DesiredPackGraphIncomplete | import("@agentxm/workspace-state").CanonicalPathRemovalError | import("@agentxm/workspace-state").SymlinkCreationError | import("@agentxm/workspace-state").LockEntrySourceMissing | import("@agentxm/workspace-state").LockEntryUrlInvalid | import("@agentxm/workspace-state").LockEntryNameInvalid | import("@agentxm/workspace-state").LockEntryEndpointConflict | import("@agentxm/workspace-state").LockEntrySourceTypeConflict | import("@agentxm/workspace-state").AcceptedResolutionMissing | import("@agentxm/workspace-state").InlineExtensionSourceMissing | import("@agentxm/workspace-state").SupersededCanonicalRemovalFailed | import("@agentxm/workspace-state").PackageContentHashFailed | import("@agentxm/workspace-state").WorkspaceSourceInvalid | import("@agentxm/workspace-state").SkillDiscoveryRootInvalid | import("@agentxm/workspace-state").SubagentScanFailed | import("@agentxm/workspace-state").LockfileResolvedVersionInvalid | import("@agentxm/extension-model/unstable/extensions").FqnInvalidError | import("@agentxm/registry-protocol/unstable/content/frontmatter").FrontmatterParseFailure | import("@agentxm/registry-protocol/unstable/content/subagent-content").SubagentContentError | E,
|
|
126
|
+
}, WorkspaceSyncFailed | import("@agentxm/extension-workspace").CoupledDependencyFailure | import("@agentxm/extension-workspace").PackageMaterializationFailed | import("@agentxm/extension-workspace").StagedPackageInvalid | import("@agentxm/extension-workspace").CanonicalPackageProbeFailed | import("@agentxm/extension-workspace").PackageCopyFailed | import("@agentxm/extension-workspace").ArchiveIntegrityMismatch | import("@agentxm/extension-workspace").CreateDestinationExists | import("@agentxm/extension-workspace").CreateNameConfigured | import("@agentxm/extension-workspace").CreateDestinationInspectionFailed | import("@agentxm/workspace-state").PathTraversalDetected | import("@agentxm/extension-workspace").ForkPackageInvalid | import("@agentxm/extension-workspace").ForkPackageConflict | import("@agentxm/extension-workspace").ForkPackageFailed | import("@agentxm/extension-workspace").NativeImportUnsupported | import("@agentxm/extension-workspace").NativeImportInvalid | import("@agentxm/extension-workspace").NativeImportConflict | import("@agentxm/extension-workspace").NativeImportFailed | import("@agentxm/extension-workspace").SourceAuthorityBlocked | import("@agentxm/extension-workspace").LifecyclePostconditionViolated | import("@agentxm/extension-workspace").ScaffoldedExtensionUnresolved | import("@agentxm/extension-workspace").DesiredStateIncomplete | import("@agentxm/extension-workspace").AuthoredContributorUnsupported | import("@agentxm/extension-workspace").ContributorIdentityInvalid | import("@agentxm/extension-workspace").ContributorUnresolved | import("@agentxm/extension-workspace").ContributorTreeMismatch | import("@agentxm/extension-workspace").ProjectionTargetUnsupported | import("@agentxm/extension-workspace").ManagedRegionViolation | import("@agentxm/extension-workspace").ProjectionIoFailed | import("@agentxm/extension-workspace").InstructionMaintenanceFailed | import("@agentxm/extension-workspace").RuleDefinitionInvalid | import("@agentxm/extension-workspace").RuleInstallStateMissing | import("@agentxm/extension-workspace").HookDefinitionInvalid | import("@agentxm/extension-workspace").HookConfigInvalid | import("@agentxm/extension-workspace").HookIoFailed | import("@agentxm/extension-workspace").HookInstallStateMissing | import("@agentxm/extension-workspace").SubagentDefinitionInvalid | import("@agentxm/extension-workspace").SubagentContentUnreadable | import("@agentxm/extension-workspace").SubagentIoFailed | import("@agentxm/extension-workspace").SubagentInstallStateMissing | import("@agentxm/extension-workspace").McpConfigInvalid | import("@agentxm/extension-workspace").McpConfigIoFailed | import("@agentxm/extension-workspace").McpEntryUnmanaged | import("@agentxm/extension-workspace").McpOwnershipMarkerInvalid | import("@agentxm/extension-workspace").McpDefinitionInvalid | import("@agentxm/extension-workspace").McpRegistryOnlyInstall | import("@agentxm/extension-workspace").McpInstallStateMissing | import("@agentxm/extension-workspace").McpSharedTargetConflict | import("@agentxm/extension-workspace").SkillDefinitionInvalid | import("@agentxm/extension-workspace").SkillMaterializationFailed | import("@agentxm/extension-workspace").SkillInstallStateMissing | import("@agentxm/extension-workspace").AxmSkillCompatibilityUnavailable | import("@agentxm/extension-workspace").AxmSkillIncompatible | import("@agentxm/extension-workspace").PackDefinitionInvalid | import("@agentxm/extension-workspace").PackInstallStateMissing | import("@agentxm/extension-workspace").PackArchiveFetchFailed | import("@agentxm/extension-workspace").PackStagingFailed | import("@agentxm/extension-workspace").PackDependencyInvalid | import("@agentxm/extension-workspace").PackDependencyConflict | import("@agentxm/extension-workspace").PackConstraintShadowed | import("@agentxm/extension-workspace").PackDependencyMissing | import("@agentxm/extension-workspace").PackDependencyUnsatisfied | import("@agentxm/extension-workspace").KnowledgeDefinitionInvalid | import("@agentxm/extension-workspace").KnowledgeIoFailed | import("@agentxm/extension-workspace").KnowledgeInstallStateMissing | import("@agentxm/extension-workspace").KnowledgeResolutionMissing | import("@agentxm/extension-workspace").KnowledgeDesiredStateUnreconcilable | import("@agentxm/extension-workspace").KnowledgeUnavailable | import("@agentxm/extension-workspace").KnowledgeObservableContractViolated | import("@agentxm/workspace-state").MaterializedTreeInvalid | import("@agentxm/extension-workspace").TransientBackupFailed | import("@agentxm/extension-workspace").WriteBackupRetained | import("@agentxm/workspace-state").SettingsIoError | import("@agentxm/workspace-state").SettingsParseError | import("@agentxm/workspace-state").SettingsDecodeError | import("@agentxm/workspace-state").LockfileIoError | import("@agentxm/workspace-state").LockfileParseError | import("@agentxm/workspace-state").LockfileDecodeError | import("@agentxm/workspace-state").LockfileVersionUnsupported | import("@agentxm/workspace-state").WorkspaceRootEscape | import("@agentxm/workspace-state").SettingsWriteError | import("@agentxm/workspace-state").WorkspaceSnapshotError | import("@agentxm/workspace-state").LockfileValidationError | import("@agentxm/workspace-state").LockfileWriteError | import("@agentxm/workspace-state").WorkspaceDirectoryError | import("@agentxm/workspace-state").TransitionLockError | import("@agentxm/workspace-state").TransitionLockUnavailable | import("@agentxm/workspace-state").WorkspaceTransitionCompromised | import("@agentxm/workspace-state").WorkspaceRestorationIncomplete | import("@agentxm/workspace-state").WorkspaceLayoutError | import("@agentxm/workspace-state").WorkspaceNotInitialized | import("@agentxm/workspace-state").LockedSkillMissing | import("@agentxm/workspace-state").SettingsEntryMissing | import("@agentxm/workspace-state").InvalidAgentId | import("@agentxm/workspace-state").DesiredPackGraphIncomplete | import("@agentxm/workspace-state").CanonicalPathRemovalError | import("@agentxm/workspace-state").SymlinkCreationError | import("@agentxm/workspace-state").LockEntrySourceMissing | import("@agentxm/workspace-state").LockEntryUrlInvalid | import("@agentxm/workspace-state").LockEntryNameInvalid | import("@agentxm/workspace-state").LockEntryEndpointConflict | import("@agentxm/workspace-state").LockEntrySourceTypeConflict | import("@agentxm/workspace-state").AcceptedResolutionMissing | import("@agentxm/workspace-state").InlineExtensionSourceMissing | import("@agentxm/workspace-state").SupersededCanonicalRemovalFailed | import("@agentxm/workspace-state").PackageContentHashFailed | import("@agentxm/workspace-state").WorkspaceSourceInvalid | import("@agentxm/workspace-state").SkillDiscoveryRootInvalid | import("@agentxm/workspace-state").SubagentScanFailed | import("@agentxm/workspace-state").LockfileResolvedVersionInvalid | import("@agentxm/extension-model/unstable/extensions").FqnInvalidError | import("@agentxm/registry-protocol/unstable/content/frontmatter").FrontmatterParseFailure | import("@agentxm/registry-protocol/unstable/content/subagent-content").SubagentContentError | E, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations | KnowledgeManager | HookManager | RuleManager | SubagentManager | RResolve | SkillManager>;
|
|
125
127
|
//# sourceMappingURL=materialize.d.ts.map
|
package/dist/src/materialize.js
CHANGED
|
@@ -15,7 +15,7 @@ import * as Option from "effect/Option";
|
|
|
15
15
|
import * as Path from "effect/Path";
|
|
16
16
|
import * as ServiceMap from "effect/Context";
|
|
17
17
|
import * as semver from "semver";
|
|
18
|
-
import { CodingAgentRepository, HookManager, KnowledgeManager, RuleManager, SkillManager, SubagentManager, buildMaterializeOperation, collectManagedAgentMcpServers, enabledConfiguredEntries, extensionConstraintFactText, inspectMcpServerAcrossAgents, isConfiguredEntryEnabled, makeExtensionConstraintInvariantFact, planExtensionConstraintFact,
|
|
18
|
+
import { CodingAgentRepository, HookManager, KnowledgeManager, RuleManager, SkillManager, SubagentManager, buildMaterializeOperation, collectManagedAgentMcpServers, enabledConfiguredEntries, extensionConstraintFactText, inspectMcpServerAcrossAgents, isConfiguredEntryEnabled, makeExtensionConstraintInvariantFact, planExtensionConstraintFact, skillArtifactFromTargets, targetFromRef, toStepKey, } from "@agentxm/extension-workspace";
|
|
19
19
|
import { normalizeReleaseAgeRecords, } from "@agentxm/registry-protocol/unstable/registry/release-age-policy";
|
|
20
20
|
import {} from "@agentxm/extension-model/unstable/extensions/release-age";
|
|
21
21
|
import { sanitizeName, acceptedResolutionRef, acceptedCanonicalObservation, isSourcedDesiredExtension, desiredStateProblemsText, WorkspaceMutations, usableAcceptedCanonical, } from "@agentxm/workspace-state";
|
|
@@ -29,7 +29,7 @@ import {} from "@agentxm/extension-model/unstable/extensions/refs/subagent";
|
|
|
29
29
|
import { parseExtensionFqnParts, } from "@agentxm/extension-model/unstable/extensions";
|
|
30
30
|
import { StepFailure, } from "@agentxm/workspace-operations";
|
|
31
31
|
import { WorkspaceSyncFailed } from "./errors.js";
|
|
32
|
-
import { isInlineMcpServerEntry, SYNC_RECOVERY_IDS, buildInlineMcpServerSyncOperation,
|
|
32
|
+
import { isInlineMcpServerEntry, SYNC_RECOVERY_IDS, buildInlineMcpServerSyncOperation, } from "./plan.js";
|
|
33
33
|
export const normalizedIdentity = (identity) => identity.startsWith("workspace:") ? identity.slice("workspace:".length) : identity;
|
|
34
34
|
const sourceTransitionIdentity = (authority, identity) => authority === "workspace"
|
|
35
35
|
? "workspace"
|
|
@@ -205,7 +205,6 @@ export const collectMaterializeSteps = (args) => Effect.gen(function* () {
|
|
|
205
205
|
const configuredAgents = args.configuredAgents ?? (yield* ws.getConfiguredAgents());
|
|
206
206
|
const desiredState = yield* ws.getDesiredStateGraph();
|
|
207
207
|
const selection = args.selection ?? { target: Option.none(), type: Option.none() };
|
|
208
|
-
const isScoped = Option.isSome(selection.target) || Option.isSome(selection.type);
|
|
209
208
|
const problems = scopedProblems(desiredState, selection);
|
|
210
209
|
const blockers = problems.filter((problem) => {
|
|
211
210
|
const name = recoverableExternalPackName(desiredState, problem);
|
|
@@ -435,15 +434,6 @@ export const collectMaterializeSteps = (args) => Effect.gen(function* () {
|
|
|
435
434
|
adapter: args.adapter,
|
|
436
435
|
}));
|
|
437
436
|
}), { concurrency: "unbounded" }).pipe(Effect.map((steps) => steps.flatMap((step) => (Option.isSome(step) ? [step.value] : []))));
|
|
438
|
-
const needsMcpServerPrune = problems.length === 0 &&
|
|
439
|
-
!isScoped &&
|
|
440
|
-
configuredAgents.length > 0 &&
|
|
441
|
-
(yield* Effect.forEach(configuredAgents, (agentId) => pruneManagedMcpServersForAgent(agentId, {
|
|
442
|
-
workspaceRoot: ws.baseDir,
|
|
443
|
-
declaredServerNames: declaredMcpServerNames,
|
|
444
|
-
scope: ws.scope,
|
|
445
|
-
dryRun: true,
|
|
446
|
-
}).pipe(Effect.provideService(FileSystem.FileSystem, fs), Effect.provideService(Path.Path, path)), { concurrency: "unbounded" }).pipe(Effect.map((outcomes) => outcomes.some((outcome) => outcome._tag === "success" && outcome.targets !== undefined))));
|
|
447
437
|
const skillMaterializeStep = ({ ref, force, transitionLabel }) => Effect.gen(function* () {
|
|
448
438
|
const buildArtifact = () => skillSyncArtifact({
|
|
449
439
|
ref,
|
|
@@ -490,6 +480,8 @@ export const collectMaterializeSteps = (args) => Effect.gen(function* () {
|
|
|
490
480
|
serialMaterialization: packRecoverySteps.length > 0,
|
|
491
481
|
expectedSkillNames: new Set(skillRefs.map(({ ref }) => ref.skill.name)),
|
|
492
482
|
expectedSubagentNames: new Set(subagentRefs.map(({ ref }) => ref.subagent.name)),
|
|
483
|
+
expectedMcpServerNames: declaredMcpServerNames,
|
|
484
|
+
expectedHookNames: new Set(hookRefs.map(({ ref }) => ref.hook.name)),
|
|
493
485
|
releaseAge: {
|
|
494
486
|
evaluatedAt: DateTime.formatIso(releaseAgeEvaluation.evaluatedAt),
|
|
495
487
|
holdbacks: normalizeReleaseAgeRecords([
|
|
@@ -513,16 +505,6 @@ export const collectMaterializeSteps = (args) => Effect.gen(function* () {
|
|
|
513
505
|
runMcpServerInstall: args.runMcpServerInstall,
|
|
514
506
|
})),
|
|
515
507
|
...inlineMcpServerSteps,
|
|
516
|
-
...(needsMcpServerPrune
|
|
517
|
-
? [
|
|
518
|
-
buildMcpServerPruneOperation({
|
|
519
|
-
declaredServerNames: declaredMcpServerNames,
|
|
520
|
-
agentIds: configuredAgents,
|
|
521
|
-
ws,
|
|
522
|
-
adapter: args.adapter,
|
|
523
|
-
}),
|
|
524
|
-
]
|
|
525
|
-
: []),
|
|
526
508
|
...subagentRefs.filter(({ materialize }) => materialize).map(subagentMaterializeStep),
|
|
527
509
|
...ruleRefs
|
|
528
510
|
.filter(({ materialize }) => materialize)
|
package/dist/src/plan.d.ts
CHANGED
|
@@ -76,8 +76,10 @@ export declare const collectKnowledgeStep: (args: {
|
|
|
76
76
|
export declare const collectCleanupStep: (args: {
|
|
77
77
|
readonly expectedSkillNames: ReadonlySet<string>;
|
|
78
78
|
readonly expectedSubagentNames: ReadonlySet<string>;
|
|
79
|
+
readonly expectedMcpServerNames: ReadonlySet<string>;
|
|
80
|
+
readonly expectedHookNames: ReadonlySet<string>;
|
|
79
81
|
readonly adapter: SyncFailureAdapter;
|
|
80
|
-
}) => Effect.Effect<Option.Option<PlannedJobStep<SyncStepRequirements>>, import("./errors.ts").
|
|
82
|
+
}) => Effect.Effect<Option.Option<PlannedJobStep<SyncStepRequirements>>, import("./errors.ts").WorkspaceSyncFailed | import("@agentxm/extension-workspace").CoupledDependencyFailure | import("@agentxm/extension-workspace").PackageMaterializationFailed | import("@agentxm/extension-workspace").StagedPackageInvalid | import("@agentxm/extension-workspace").CanonicalPackageProbeFailed | import("@agentxm/extension-workspace").PackageCopyFailed | import("@agentxm/extension-workspace").ArchiveIntegrityMismatch | import("@agentxm/extension-workspace").CreateDestinationExists | import("@agentxm/extension-workspace").CreateNameConfigured | import("@agentxm/extension-workspace").CreateDestinationInspectionFailed | import("@agentxm/workspace-state").PathTraversalDetected | import("@agentxm/extension-workspace").ForkPackageInvalid | import("@agentxm/extension-workspace").ForkPackageConflict | import("@agentxm/extension-workspace").ForkPackageFailed | import("@agentxm/extension-workspace").NativeImportUnsupported | import("@agentxm/extension-workspace").NativeImportInvalid | import("@agentxm/extension-workspace").NativeImportConflict | import("@agentxm/extension-workspace").NativeImportFailed | import("@agentxm/extension-workspace").SourceAuthorityBlocked | import("@agentxm/extension-workspace").LifecyclePostconditionViolated | import("@agentxm/extension-workspace").ScaffoldedExtensionUnresolved | import("@agentxm/extension-workspace").DesiredStateIncomplete | import("@agentxm/extension-workspace").AuthoredContributorUnsupported | import("@agentxm/extension-workspace").ContributorIdentityInvalid | import("@agentxm/extension-workspace").ContributorUnresolved | import("@agentxm/extension-workspace").ContributorTreeMismatch | import("@agentxm/extension-workspace").ProjectionTargetUnsupported | import("@agentxm/extension-workspace").ManagedRegionViolation | import("@agentxm/extension-workspace").ProjectionIoFailed | import("@agentxm/extension-workspace").InstructionMaintenanceFailed | import("@agentxm/extension-workspace").RuleDefinitionInvalid | import("@agentxm/extension-workspace").RuleInstallStateMissing | import("@agentxm/extension-workspace").HookDefinitionInvalid | import("@agentxm/extension-workspace").HookConfigInvalid | import("@agentxm/extension-workspace").HookIoFailed | import("@agentxm/extension-workspace").HookInstallStateMissing | import("@agentxm/extension-workspace").SubagentDefinitionInvalid | import("@agentxm/extension-workspace").SubagentContentUnreadable | import("@agentxm/extension-workspace").SubagentIoFailed | import("@agentxm/extension-workspace").SubagentInstallStateMissing | import("@agentxm/extension-workspace").McpConfigInvalid | import("@agentxm/extension-workspace").McpConfigIoFailed | import("@agentxm/extension-workspace").McpEntryUnmanaged | import("@agentxm/extension-workspace").McpOwnershipMarkerInvalid | import("@agentxm/extension-workspace").McpDefinitionInvalid | import("@agentxm/extension-workspace").McpRegistryOnlyInstall | import("@agentxm/extension-workspace").McpInstallStateMissing | import("@agentxm/extension-workspace").McpSharedTargetConflict | import("@agentxm/extension-workspace").SkillDefinitionInvalid | import("@agentxm/extension-workspace").SkillMaterializationFailed | import("@agentxm/extension-workspace").SkillInstallStateMissing | import("@agentxm/extension-workspace").AxmSkillCompatibilityUnavailable | import("@agentxm/extension-workspace").AxmSkillIncompatible | import("@agentxm/extension-workspace").PackDefinitionInvalid | import("@agentxm/extension-workspace").PackInstallStateMissing | import("@agentxm/extension-workspace").PackArchiveFetchFailed | import("@agentxm/extension-workspace").PackStagingFailed | import("@agentxm/extension-workspace").PackDependencyInvalid | import("@agentxm/extension-workspace").PackDependencyConflict | import("@agentxm/extension-workspace").PackConstraintShadowed | import("@agentxm/extension-workspace").PackDependencyMissing | import("@agentxm/extension-workspace").PackDependencyUnsatisfied | import("@agentxm/extension-workspace").KnowledgeDefinitionInvalid | import("@agentxm/extension-workspace").KnowledgeIoFailed | import("@agentxm/extension-workspace").KnowledgeInstallStateMissing | import("@agentxm/extension-workspace").KnowledgeResolutionMissing | import("@agentxm/extension-workspace").KnowledgeDesiredStateUnreconcilable | import("@agentxm/extension-workspace").KnowledgeUnavailable | import("@agentxm/extension-workspace").KnowledgeObservableContractViolated | import("@agentxm/workspace-state").MaterializedTreeInvalid | import("@agentxm/extension-workspace").TransientBackupFailed | import("@agentxm/extension-workspace").WriteBackupRetained | import("@agentxm/workspace-state").SettingsIoError | import("@agentxm/workspace-state").SettingsParseError | import("@agentxm/workspace-state").SettingsDecodeError | import("@agentxm/workspace-state").LockfileIoError | import("@agentxm/workspace-state").LockfileParseError | import("@agentxm/workspace-state").LockfileDecodeError | import("@agentxm/workspace-state").LockfileVersionUnsupported | import("@agentxm/workspace-state").WorkspaceRootEscape | import("@agentxm/workspace-state").SettingsWriteError | import("@agentxm/workspace-state").WorkspaceSnapshotError | import("@agentxm/workspace-state").LockfileValidationError | import("@agentxm/workspace-state").LockfileWriteError | import("@agentxm/workspace-state").WorkspaceDirectoryError | import("@agentxm/workspace-state").TransitionLockError | import("@agentxm/workspace-state").TransitionLockUnavailable | import("@agentxm/workspace-state").WorkspaceTransitionCompromised | import("@agentxm/workspace-state").WorkspaceRestorationIncomplete | import("@agentxm/workspace-state").WorkspaceLayoutError | import("@agentxm/workspace-state").WorkspaceNotInitialized | import("@agentxm/workspace-state").LockedSkillMissing | import("@agentxm/workspace-state").SettingsEntryMissing | import("@agentxm/workspace-state").InvalidAgentId | import("@agentxm/workspace-state").DesiredPackGraphIncomplete | import("@agentxm/workspace-state").CanonicalPathRemovalError | import("@agentxm/workspace-state").SymlinkCreationError | import("@agentxm/workspace-state").LockEntrySourceMissing | import("@agentxm/workspace-state").LockEntryUrlInvalid | import("@agentxm/workspace-state").LockEntryNameInvalid | import("@agentxm/workspace-state").LockEntryEndpointConflict | import("@agentxm/workspace-state").LockEntrySourceTypeConflict | import("@agentxm/workspace-state").AcceptedResolutionMissing | import("@agentxm/workspace-state").InlineExtensionSourceMissing | import("@agentxm/workspace-state").SupersededCanonicalRemovalFailed | import("@agentxm/workspace-state").PackageContentHashFailed | import("@agentxm/workspace-state").WorkspaceSourceInvalid | import("@agentxm/workspace-state").SkillDiscoveryRootInvalid | import("@agentxm/workspace-state").SubagentScanFailed | import("@agentxm/workspace-state").LockfileResolvedVersionInvalid | import("@agentxm/extension-model/unstable/extensions").FqnInvalidError | import("@agentxm/registry-protocol/unstable/content/frontmatter").FrontmatterParseFailure | import("@agentxm/registry-protocol/unstable/content/subagent-content").SubagentContentError, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations>;
|
|
81
83
|
export declare const collectHooksStep: (args: {
|
|
82
84
|
readonly facts: ReadonlyArray<ProjectionInvariantFact>;
|
|
83
85
|
readonly adapter: SyncFailureAdapter;
|
|
@@ -85,7 +87,7 @@ export declare const collectHooksStep: (args: {
|
|
|
85
87
|
export declare const collectInstructionStep: (args: {
|
|
86
88
|
readonly projectionFacts: ReadonlyArray<ProjectionInvariantFact>;
|
|
87
89
|
readonly adapter: SyncFailureAdapter;
|
|
88
|
-
}) => Effect.Effect<Option.Option<PlannedJobStep<SyncStepRequirements>>, import("@agentxm/workspace-state").WorkspaceSettingsReadFailure,
|
|
90
|
+
}) => Effect.Effect<Option.Option<PlannedJobStep<SyncStepRequirements>>, import("@agentxm/workspace-state").WorkspaceSettingsReadFailure, FileSystem.FileSystem | Path.Path | WorkspaceMutations | RuleManager>;
|
|
89
91
|
export declare const makeSyncPlan: <R>({ materializeSteps, knowledgeStep, hooksStep, cleanupStep, instructionStep, releaseAge, serialMaterialization, name, description, }: {
|
|
90
92
|
readonly materializeSteps: ReadonlyArray<PlannedJobStep<R>>;
|
|
91
93
|
readonly knowledgeStep: Option.Option<PlannedJobStep<R>>;
|
package/dist/src/plan.js
CHANGED
|
@@ -19,7 +19,7 @@ import * as Result from "effect/Result";
|
|
|
19
19
|
import { CodingAgentRepository, HookManager, KnowledgeManager, RuleManager, applyPlannedProjections, inspectMcpServerAcrossAgents, observeInstructionProjection, projectionFactRequiresReconciliation, pruneManagedMcpServersForAgent, resolveInstructionsConfig, syncInlineMcpServerToAgents, assertInstructionTargetsSafe, assertInstructionsGitignoreSafe, instructionProjectionEffects, instructionProjectionIsCurrent, } from "@agentxm/extension-workspace";
|
|
20
20
|
import { StepFailure, } from "@agentxm/workspace-operations";
|
|
21
21
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
22
|
-
import {
|
|
22
|
+
import { reconcileAgentOutputs } from "./rendered-file-cleanup.js";
|
|
23
23
|
export const SYNC_RECOVERY_IDS = {
|
|
24
24
|
packManifestDivergence: "pack:manifest-divergence",
|
|
25
25
|
extensionConstraintMismatch: "extension:constraint-mismatch",
|
|
@@ -53,9 +53,7 @@ export const projectionFactsNeedReconciliation = (facts) => facts.some(projectio
|
|
|
53
53
|
export const projectionDivergenceLabel = (label, facts) => {
|
|
54
54
|
const violations = facts.filter(projectionFactRequiresReconciliation);
|
|
55
55
|
const statuses = Array.from(new Set(violations.map(({ observation }) => observation.status))).join(", ");
|
|
56
|
-
|
|
57
|
-
const details = contributors.length === 0 ? statuses : `${statuses}: ${contributors.join(", ")}`;
|
|
58
|
-
return details.length === 0 ? label : `${label} (${details})`;
|
|
56
|
+
return statuses.length === 0 ? label : `${label} (${statuses})`;
|
|
59
57
|
};
|
|
60
58
|
const managedRegionsForFacts = (facts) => facts.flatMap(({ subject }) => subject.owner === undefined
|
|
61
59
|
? []
|
|
@@ -188,7 +186,7 @@ export const collectKnowledgeStep = Effect.fn("Sync.collectKnowledgeStep")(funct
|
|
|
188
186
|
};
|
|
189
187
|
return Option.some({
|
|
190
188
|
key: "knowledge:discovery",
|
|
191
|
-
label: "Knowledge discovery",
|
|
189
|
+
label: projectionDivergenceLabel("Knowledge discovery", args.facts ?? []),
|
|
192
190
|
readiness: "ready",
|
|
193
191
|
artifact,
|
|
194
192
|
...(message.length === 0 ? {} : { message }),
|
|
@@ -215,21 +213,24 @@ export const collectKnowledgeStep = Effect.fn("Sync.collectKnowledgeStep")(funct
|
|
|
215
213
|
});
|
|
216
214
|
export const collectCleanupStep = Effect.fn("Sync.collectCleanupStep")(function* (args) {
|
|
217
215
|
const ws = yield* WorkspaceMutations;
|
|
216
|
+
const agentRepo = yield* CodingAgentRepository;
|
|
217
|
+
const desiredAgentIds = new Set((yield* agentRepo.getMaterializationAgents()).map(({ id }) => id));
|
|
218
218
|
const expectedSkillProjectionNames = new Set([
|
|
219
219
|
...args.expectedSkillNames,
|
|
220
220
|
...args.expectedSubagentNames,
|
|
221
221
|
]);
|
|
222
|
-
const
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
222
|
+
const expectedNames = {
|
|
223
|
+
skill: expectedSkillProjectionNames,
|
|
224
|
+
subagent: args.expectedSubagentNames,
|
|
225
|
+
"mcp-server": args.expectedMcpServerNames,
|
|
226
|
+
hook: args.expectedHookNames,
|
|
227
|
+
};
|
|
228
|
+
const preview = yield* reconcileAgentOutputs({
|
|
229
|
+
desiredAgentIds,
|
|
230
|
+
expectedNames,
|
|
231
|
+
dryRun: true,
|
|
232
|
+
});
|
|
233
|
+
const previewPaths = preview.removedPaths;
|
|
233
234
|
if (previewPaths.length === 0)
|
|
234
235
|
return Option.none();
|
|
235
236
|
return Option.some({
|
|
@@ -243,13 +244,8 @@ export const collectCleanupStep = Effect.fn("Sync.collectCleanupStep")(function*
|
|
|
243
244
|
fileCount: previewPaths.length,
|
|
244
245
|
targets: previewPaths.map((filePath) => ({ path: filePath, change: "removed" })),
|
|
245
246
|
},
|
|
246
|
-
run: Effect.
|
|
247
|
-
|
|
248
|
-
expectedSkillNames: expectedSkillProjectionNames,
|
|
249
|
-
}),
|
|
250
|
-
cleanupStaleManagedSubagentFiles({ expectedSubagentNames: args.expectedSubagentNames }),
|
|
251
|
-
]).pipe(Effect.mapError(args.adapter.toStepFailure), Effect.map((results) => {
|
|
252
|
-
const removedPaths = results.flatMap((result) => result.removedPaths);
|
|
247
|
+
run: reconcileAgentOutputs({ desiredAgentIds, expectedNames }).pipe(Effect.mapError(args.adapter.toStepFailure), Effect.map((result) => {
|
|
248
|
+
const removedPaths = result.removedPaths;
|
|
253
249
|
return {
|
|
254
250
|
result: "success",
|
|
255
251
|
message: `Removed ${count(removedPaths.length, "stale managed agent projection")}`,
|
|
@@ -1,45 +1,27 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Destructive
|
|
3
|
-
*
|
|
4
|
-
* managed hook groups. Read-only discovery primitives live in
|
|
5
|
-
* `extension-workspace/managed-file-discovery.ts`.
|
|
2
|
+
* Destructive reconciliation of AXM-owned agent-native outputs. Read-only
|
|
3
|
+
* ownership and claimant discovery lives in `@agentxm/extension-workspace`.
|
|
6
4
|
*
|
|
7
5
|
* @experimental This API is unstable and may change without notice.
|
|
8
|
-
* @packageDocumentation
|
|
9
6
|
*/
|
|
10
7
|
import * as Effect from "effect/Effect";
|
|
11
8
|
import * as FileSystem from "effect/FileSystem";
|
|
12
9
|
import * as Path from "effect/Path";
|
|
13
|
-
import { type WorkspaceSyncCleanupFailure } from "./errors.js";
|
|
14
10
|
import { CodingAgentRepository, type WorkspaceOwnershipIssue } from "@agentxm/extension-workspace";
|
|
11
|
+
import type { PerAgentType } from "@agentxm/extension-model/unstable/extensions/common";
|
|
15
12
|
import { WorkspaceMutations } from "@agentxm/workspace-state";
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
}
|
|
19
|
-
export interface RemovedAgentArtifactCleanupResult {
|
|
13
|
+
import { type WorkspaceSyncCleanupFailure } from "./errors.js";
|
|
14
|
+
export interface ReconcileAgentOutputsResult {
|
|
20
15
|
readonly removedPaths: ReadonlyArray<string>;
|
|
21
16
|
readonly preservedPaths: ReadonlyArray<string>;
|
|
22
17
|
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
readonly
|
|
18
|
+
export interface ReconcileAgentOutputsArgs {
|
|
19
|
+
readonly desiredAgentIds: ReadonlySet<string>;
|
|
20
|
+
readonly expectedNames: Readonly<Record<PerAgentType, ReadonlySet<string>>>;
|
|
26
21
|
readonly dryRun?: boolean;
|
|
27
|
-
}
|
|
28
|
-
/**
|
|
29
|
-
|
|
30
|
-
* workspace: rendered skill and subagent files, plus the agent's
|
|
31
|
-
* managed MCP server entries and hook groups. Only content carrying an
|
|
32
|
-
* AXM-managed signal is removed; user-authored files and entries are left
|
|
33
|
-
* untouched.
|
|
34
|
-
*/
|
|
35
|
-
export declare const cleanupManagedArtifactsForRemovedAgents: (args: {
|
|
36
|
-
readonly removedAgentIds: ReadonlySet<string>;
|
|
37
|
-
readonly dryRun?: boolean;
|
|
38
|
-
}) => Effect.Effect<RemovedAgentArtifactCleanupResult, WorkspaceSyncCleanupFailure, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations>;
|
|
22
|
+
}
|
|
23
|
+
/** Converge all AXM-owned per-agent outputs on desired workspace state. */
|
|
24
|
+
export declare const reconcileAgentOutputs: (args: ReconcileAgentOutputsArgs) => Effect.Effect<ReconcileAgentOutputsResult, WorkspaceSyncCleanupFailure, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations>;
|
|
39
25
|
/** Inspect ownership proofs without mutating any agent-native artifact. */
|
|
40
26
|
export declare const inspectWorkspaceOwnership: () => Effect.Effect<ReadonlyArray<WorkspaceOwnershipIssue>, WorkspaceSyncCleanupFailure, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations>;
|
|
41
|
-
export declare const cleanupStaleManagedSubagentFiles: (args: {
|
|
42
|
-
readonly expectedSubagentNames: ReadonlySet<string>;
|
|
43
|
-
readonly dryRun?: boolean;
|
|
44
|
-
}) => Effect.Effect<RenderedFileCleanupResult, WorkspaceSyncCleanupFailure, CodingAgentRepository | FileSystem.FileSystem | Path.Path | WorkspaceMutations>;
|
|
45
27
|
//# sourceMappingURL=rendered-file-cleanup.d.ts.map
|
|
@@ -1,381 +1,119 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* Destructive
|
|
3
|
-
*
|
|
4
|
-
* managed hook groups. Read-only discovery primitives live in
|
|
5
|
-
* `extension-workspace/managed-file-discovery.ts`.
|
|
2
|
+
* Destructive reconciliation of AXM-owned agent-native outputs. Read-only
|
|
3
|
+
* ownership and claimant discovery lives in `@agentxm/extension-workspace`.
|
|
6
4
|
*
|
|
7
5
|
* @experimental This API is unstable and may change without notice.
|
|
8
|
-
* @packageDocumentation
|
|
9
6
|
*/
|
|
10
7
|
import * as Effect from "effect/Effect";
|
|
11
8
|
import * as FileSystem from "effect/FileSystem";
|
|
12
9
|
import * as Path from "effect/Path";
|
|
13
|
-
import {
|
|
14
|
-
import { CodingAgentRepository, pruneManagedMcpServersForAgent, extensionNameFromFilename, hasAxmManagedMarker, safeReadDirectory, safeReadFileString, readAmbiguousHookCommands, stripManagedHooksFromJson, } from "@agentxm/extension-workspace";
|
|
10
|
+
import { CodingAgentRepository, observeAgentOutputs, pruneManagedHooksFromJson, pruneManagedMcpServersForAgent, safeReadFileString, } from "@agentxm/extension-workspace";
|
|
15
11
|
import { AGENTS as CAPABILITY_AGENTS } from "@agentxm/extension-model/unstable/agent-capabilities";
|
|
16
|
-
import {
|
|
17
|
-
import {
|
|
18
|
-
|
|
19
|
-
import { protectWorkspacePath } from "@agentxm/workspace-state";
|
|
20
|
-
import { recordFootprint } from "@agentxm/workspace-state";
|
|
21
|
-
const isWithin = (path, parent, child) => {
|
|
22
|
-
const relative = path.relative(path.resolve(parent), path.resolve(child));
|
|
23
|
-
return relative === "" || (!relative.startsWith("..") && !path.isAbsolute(relative));
|
|
24
|
-
};
|
|
25
|
-
const removePath = (fs, filePath, dryRun) => dryRun
|
|
26
|
-
? Effect.void
|
|
27
|
-
: protectWorkspacePath(filePath).pipe(Effect.andThen(fs.remove(filePath, { recursive: true })), Effect.andThen(recordFootprint({ path: filePath, change: "removed" })), Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
28
|
-
category: "internal",
|
|
29
|
-
detail: `Failed to remove managed agent artifact: ${filePath}`,
|
|
30
|
-
cause: error,
|
|
31
|
-
})));
|
|
32
|
-
const hasManagedSkillCopyMarker = (fs, path, artifactPath) => safeReadFileString(fs, path.join(artifactPath, "SKILL.md")).pipe(Effect.map(hasAxmManagedMarker));
|
|
33
|
-
const cleanupSkillArtifactsInDir = (args) => Effect.gen(function* () {
|
|
34
|
-
const removedPaths = [];
|
|
35
|
-
const preservedPaths = [];
|
|
36
|
-
const entries = yield* safeReadDirectory(args.fs, args.skillsDir);
|
|
37
|
-
const configuredRoots = args.ownershipRoots ?? [
|
|
38
|
-
args.path.join(args.baseDir, ACQUIRED_EXTENSIONS_DIR),
|
|
39
|
-
];
|
|
40
|
-
const ownershipRoots = yield* Effect.forEach(configuredRoots, (root) => args.fs.realPath(root).pipe(Effect.orElseSucceed(() => root)));
|
|
41
|
-
for (const entry of entries) {
|
|
42
|
-
if (args.expectedNames?.has(entry) === true)
|
|
43
|
-
continue;
|
|
44
|
-
const artifactPath = args.path.join(args.skillsDir, entry);
|
|
45
|
-
const linkTarget = yield* args.fs.readLink(artifactPath).pipe(Effect.option);
|
|
46
|
-
if (linkTarget._tag === "Some") {
|
|
47
|
-
const resolvedTarget = args.path.resolve(args.skillsDir, linkTarget.value);
|
|
48
|
-
const canonicalTarget = yield* args.fs.realPath(resolvedTarget).pipe(Effect.option);
|
|
49
|
-
const ownershipTarget = canonicalTarget._tag === "Some" ? canonicalTarget.value : resolvedTarget;
|
|
50
|
-
if (!ownershipRoots.some((root) => isWithin(args.path, root, ownershipTarget))) {
|
|
51
|
-
preservedPaths.push(artifactPath);
|
|
52
|
-
continue;
|
|
53
|
-
}
|
|
54
|
-
yield* removePath(args.fs, artifactPath, args.dryRun);
|
|
55
|
-
removedPaths.push(artifactPath);
|
|
56
|
-
continue;
|
|
57
|
-
}
|
|
58
|
-
const stat = yield* args.fs.stat(artifactPath).pipe(Effect.option);
|
|
59
|
-
if (stat._tag === "None")
|
|
60
|
-
continue;
|
|
61
|
-
if (stat.value.type !== "Directory") {
|
|
62
|
-
preservedPaths.push(artifactPath);
|
|
63
|
-
continue;
|
|
64
|
-
}
|
|
65
|
-
const managedCopy = yield* hasManagedSkillCopyMarker(args.fs, args.path, artifactPath);
|
|
66
|
-
if (!managedCopy) {
|
|
67
|
-
preservedPaths.push(artifactPath);
|
|
68
|
-
continue;
|
|
69
|
-
}
|
|
70
|
-
yield* removePath(args.fs, artifactPath, args.dryRun);
|
|
71
|
-
removedPaths.push(artifactPath);
|
|
72
|
-
}
|
|
73
|
-
return { removedPaths, preservedPaths };
|
|
74
|
-
});
|
|
75
|
-
/** Remove AXM-owned skill projections whose package is no longer desired. */
|
|
76
|
-
export const cleanupStaleManagedSkillDirectories = (args) => Effect.gen(function* () {
|
|
77
|
-
const fs = yield* FileSystem.FileSystem;
|
|
78
|
-
const path = yield* Path.Path;
|
|
12
|
+
import { WorkspaceMutations, protectWorkspacePath, recordFootprint, } from "@agentxm/workspace-state";
|
|
13
|
+
import { WorkspaceSyncFailed } from "./errors.js";
|
|
14
|
+
const inventory = (args) => Effect.gen(function* () {
|
|
79
15
|
const ws = yield* WorkspaceMutations;
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
if (!configuredAgentIds.has(agent.id))
|
|
89
|
-
continue;
|
|
90
|
-
const resolved = yield* agent.resolveEffectiveSkillsDir({ workspaceRoot: ws.baseDir });
|
|
91
|
-
if (resolved._tag !== "supported")
|
|
92
|
-
continue;
|
|
93
|
-
const result = yield* cleanupSkillArtifactsInDir({
|
|
94
|
-
fs,
|
|
95
|
-
path,
|
|
96
|
-
baseDir: ws.baseDir,
|
|
97
|
-
skillsDir: resolved.dir,
|
|
98
|
-
dryRun: args.dryRun === true,
|
|
99
|
-
ownershipRoots,
|
|
100
|
-
expectedNames: args.expectedSkillNames,
|
|
101
|
-
});
|
|
102
|
-
removedPaths.push(...result.removedPaths);
|
|
103
|
-
}
|
|
104
|
-
return { removedPaths: [...new Set(removedPaths)] };
|
|
105
|
-
});
|
|
106
|
-
const cleanupSubagentArtifactsInDir = (args) => Effect.gen(function* () {
|
|
107
|
-
const removedPaths = [];
|
|
108
|
-
const preservedPaths = [];
|
|
109
|
-
const entries = yield* safeReadDirectory(args.fs, args.subagentsDir);
|
|
110
|
-
for (const entry of entries) {
|
|
111
|
-
const filePath = args.path.join(args.subagentsDir, entry);
|
|
112
|
-
const stat = yield* args.fs.stat(filePath).pipe(Effect.option);
|
|
113
|
-
if (stat._tag === "None" || stat.value.type !== "File")
|
|
114
|
-
continue;
|
|
115
|
-
const content = yield* safeReadFileString(args.fs, filePath);
|
|
116
|
-
if (!hasAxmManagedMarker(content)) {
|
|
117
|
-
preservedPaths.push(filePath);
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
yield* removePath(args.fs, filePath, args.dryRun);
|
|
121
|
-
removedPaths.push(filePath);
|
|
122
|
-
}
|
|
123
|
-
return { removedPaths, preservedPaths };
|
|
124
|
-
});
|
|
125
|
-
const NO_PATHS = { removedPaths: [], preservedPaths: [] };
|
|
126
|
-
const cleanupAgentSkills = (context) => Effect.gen(function* () {
|
|
127
|
-
const skillsDir = yield* context.agent.resolveEffectiveSkillsDir({
|
|
128
|
-
workspaceRoot: context.workspaceRoot,
|
|
129
|
-
});
|
|
130
|
-
if (skillsDir._tag !== "supported")
|
|
131
|
-
return NO_PATHS;
|
|
132
|
-
return yield* cleanupSkillArtifactsInDir({
|
|
133
|
-
fs: context.fs,
|
|
134
|
-
path: context.path,
|
|
135
|
-
baseDir: context.workspaceRoot,
|
|
136
|
-
skillsDir: skillsDir.dir,
|
|
137
|
-
dryRun: context.dryRun,
|
|
138
|
-
ownershipRoots: context.skillOwnershipRoots,
|
|
139
|
-
});
|
|
140
|
-
});
|
|
141
|
-
const cleanupAgentSubagents = (context) => Effect.gen(function* () {
|
|
142
|
-
const subagentsDir = yield* context.agent.resolveEffectiveSubagentsDir({
|
|
143
|
-
workspaceRoot: context.workspaceRoot,
|
|
144
|
-
scope: context.scope,
|
|
145
|
-
});
|
|
146
|
-
if (subagentsDir._tag !== "supported")
|
|
147
|
-
return NO_PATHS;
|
|
148
|
-
return yield* cleanupSubagentArtifactsInDir({
|
|
149
|
-
fs: context.fs,
|
|
150
|
-
path: context.path,
|
|
151
|
-
subagentsDir: subagentsDir.dir,
|
|
152
|
-
dryRun: context.dryRun,
|
|
16
|
+
return yield* observeAgentOutputs({
|
|
17
|
+
workspaceRoot: ws.baseDir,
|
|
18
|
+
scope: ws.scope,
|
|
19
|
+
desiredAgentIds: args.desiredAgentIds,
|
|
20
|
+
expectedNames: args.expectedNames,
|
|
21
|
+
skillOwnershipRoots: ws.layout.scope === "project"
|
|
22
|
+
? [ws.layout.acquiredRoot, ws.layout.authoredRoot("skill")]
|
|
23
|
+
: [ws.layout.acquiredRoot],
|
|
153
24
|
});
|
|
154
25
|
});
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
26
|
+
const cleanupFailure = (detail, cause) => new WorkspaceSyncFailed({ category: "internal", detail, cause });
|
|
27
|
+
const removeOwnedFile = (fs, output) => protectWorkspacePath(output.path).pipe(Effect.andThen(fs.remove(output.path, { recursive: true })), Effect.andThen(recordFootprint({ path: output.path, change: "removed" })), Effect.mapError((error) => cleanupFailure(`Failed to remove managed agent artifact: ${output.path}`, error)));
|
|
28
|
+
const uniqueContainers = (outputs) => outputs.filter((output, index) => outputs.findIndex((candidate) => candidate.extensionType === output.extensionType &&
|
|
29
|
+
candidate.containerPath === output.containerPath) === index);
|
|
30
|
+
const desiredNamesForContainer = (output, args) => output.claimantAgentIds.some((agentId) => args.desiredAgentIds.has(agentId))
|
|
31
|
+
? args.expectedNames[output.extensionType]
|
|
32
|
+
: new Set();
|
|
33
|
+
const pruneMcpContainer = (output, args, workspaceRoot, scope) => {
|
|
34
|
+
const claimant = output.claimantAgentIds[0];
|
|
35
|
+
if (claimant === undefined)
|
|
36
|
+
return Effect.void;
|
|
37
|
+
return pruneManagedMcpServersForAgent(claimant, {
|
|
38
|
+
workspaceRoot,
|
|
39
|
+
scope,
|
|
40
|
+
declaredServerNames: desiredNamesForContainer(output, args),
|
|
41
|
+
}).pipe(Effect.mapError((error) => cleanupFailure(`Failed to reconcile managed MCP entries in: ${output.containerPath}`, error)), Effect.asVoid);
|
|
42
|
+
};
|
|
43
|
+
const pruneHookContainer = (fs, path, output, args, workspaceRoot, scope) => Effect.gen(function* () {
|
|
44
|
+
const writer = CAPABILITY_AGENTS.flatMap((agent) => {
|
|
45
|
+
if (!output.claimantAgentIds.includes(agent.id))
|
|
46
|
+
return [];
|
|
47
|
+
const candidate = agent.capabilities.hook.axm.writer;
|
|
48
|
+
if (candidate === null)
|
|
49
|
+
return [];
|
|
50
|
+
const ownsPath = candidate.configFiles.some((file) => file.scope === scope &&
|
|
51
|
+
file.format === "json" &&
|
|
52
|
+
path.resolve(workspaceRoot, file.path) === output.containerPath);
|
|
53
|
+
return ownsPath ? [candidate] : [];
|
|
54
|
+
})[0];
|
|
55
|
+
if (writer === undefined)
|
|
56
|
+
return;
|
|
57
|
+
const raw = yield* safeReadFileString(fs, output.containerPath);
|
|
58
|
+
const next = yield* pruneManagedHooksFromJson(output.containerPath, writer.settingsKey, raw, desiredNamesForContainer(output, args)).pipe(Effect.mapError((error) => cleanupFailure(`Failed to reconcile managed hooks in: ${output.containerPath}`, error)));
|
|
59
|
+
if (next === raw)
|
|
60
|
+
return;
|
|
61
|
+
yield* protectWorkspacePath(output.containerPath).pipe(Effect.andThen(fs.writeFileString(output.containerPath, next)), Effect.andThen(recordFootprint({ path: output.containerPath, change: "modified" })), Effect.mapError((error) => cleanupFailure(`Failed to write reconciled hooks to: ${output.containerPath}`, error)));
|
|
173
62
|
});
|
|
174
|
-
/**
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
const removedPaths = [];
|
|
185
|
-
const configFiles = writer.configFiles.filter((file) => file.scope === "project" && file.format === "json");
|
|
186
|
-
for (const file of configFiles) {
|
|
187
|
-
const configPath = context.path.resolve(context.workspaceRoot, file.path);
|
|
188
|
-
const exists = yield* context.fs
|
|
189
|
-
.exists(configPath)
|
|
190
|
-
.pipe(Effect.catch(() => Effect.succeed(false)));
|
|
191
|
-
if (!exists)
|
|
192
|
-
continue;
|
|
193
|
-
const raw = yield* safeReadFileString(context.fs, configPath);
|
|
194
|
-
const next = yield* stripManagedHooksFromJson(configPath, writer.settingsKey, raw);
|
|
195
|
-
if (next === raw)
|
|
196
|
-
continue;
|
|
197
|
-
if (!context.dryRun) {
|
|
198
|
-
yield* protectWorkspacePath(configPath);
|
|
199
|
-
yield* context.fs.writeFileString(configPath, next).pipe(Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
200
|
-
category: "internal",
|
|
201
|
-
detail: `Failed to strip managed hooks from: ${configPath}`,
|
|
202
|
-
cause: error,
|
|
203
|
-
})));
|
|
204
|
-
}
|
|
205
|
-
removedPaths.push(configPath);
|
|
63
|
+
/** Converge all AXM-owned per-agent outputs on desired workspace state. */
|
|
64
|
+
export const reconcileAgentOutputs = (args) => Effect.gen(function* () {
|
|
65
|
+
const before = yield* inventory(args);
|
|
66
|
+
const candidates = before.ownedResidue;
|
|
67
|
+
const preservedPaths = [...new Set(before.unownedFootprints.map(({ path }) => path))].sort();
|
|
68
|
+
if (args.dryRun === true) {
|
|
69
|
+
return {
|
|
70
|
+
removedPaths: [...new Set(candidates.map(({ path }) => path))].sort(),
|
|
71
|
+
preservedPaths,
|
|
72
|
+
};
|
|
206
73
|
}
|
|
207
|
-
return { removedPaths, preservedPaths: [] };
|
|
208
|
-
});
|
|
209
|
-
/**
|
|
210
|
-
* Cleanup keyed on the placement axis: every extension type that renders into a
|
|
211
|
-
* directory the agent owns needs removal behavior here, and adding a per-agent
|
|
212
|
-
* type fails to compile until that behavior is decided.
|
|
213
|
-
*
|
|
214
|
-
* Workspace-placed types are deliberately absent rather than mapped to a no-op.
|
|
215
|
-
* Workspace-placed extensions live in shared workspace content and are not
|
|
216
|
-
* keyed to a single agent, so removing one agent must not delete them.
|
|
217
|
-
*/
|
|
218
|
-
const cleanupByExtensionType = {
|
|
219
|
-
skill: cleanupAgentSkills,
|
|
220
|
-
subagent: cleanupAgentSubagents,
|
|
221
|
-
"mcp-server": cleanupAgentMcpServers,
|
|
222
|
-
hook: cleanupAgentHooks,
|
|
223
|
-
};
|
|
224
|
-
/**
|
|
225
|
-
* Remove AXM-managed artifacts for agents that are no longer configured for a
|
|
226
|
-
* workspace: rendered skill and subagent files, plus the agent's
|
|
227
|
-
* managed MCP server entries and hook groups. Only content carrying an
|
|
228
|
-
* AXM-managed signal is removed; user-authored files and entries are left
|
|
229
|
-
* untouched.
|
|
230
|
-
*/
|
|
231
|
-
export const cleanupManagedArtifactsForRemovedAgents = (args) => Effect.gen(function* () {
|
|
232
74
|
const fs = yield* FileSystem.FileSystem;
|
|
233
75
|
const path = yield* Path.Path;
|
|
234
76
|
const ws = yield* WorkspaceMutations;
|
|
235
|
-
const
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
const preservedPaths = [];
|
|
239
|
-
for (const agent of agents) {
|
|
240
|
-
if (!args.removedAgentIds.has(agent.id))
|
|
241
|
-
continue;
|
|
242
|
-
const context = {
|
|
243
|
-
fs,
|
|
244
|
-
path,
|
|
245
|
-
agent,
|
|
246
|
-
workspaceRoot: ws.baseDir,
|
|
247
|
-
scope: ws.scope,
|
|
248
|
-
skillOwnershipRoots: ws.layout.scope === "project"
|
|
249
|
-
? [ws.layout.acquiredRoot, ws.layout.authoredRoot("skill")]
|
|
250
|
-
: [ws.layout.acquiredRoot],
|
|
251
|
-
dryRun: args.dryRun === true,
|
|
252
|
-
};
|
|
253
|
-
for (const type of PER_AGENT_EXTENSION_TYPES) {
|
|
254
|
-
const result = yield* cleanupByExtensionType[type](context);
|
|
255
|
-
removedPaths.push(...result.removedPaths);
|
|
256
|
-
preservedPaths.push(...result.preservedPaths);
|
|
77
|
+
for (const output of candidates) {
|
|
78
|
+
if (output.extensionType === "skill" || output.extensionType === "subagent") {
|
|
79
|
+
yield* removeOwnedFile(fs, output);
|
|
257
80
|
}
|
|
258
81
|
}
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
}
|
|
82
|
+
for (const output of uniqueContainers(candidates.filter(({ extensionType }) => extensionType === "mcp-server"))) {
|
|
83
|
+
yield* pruneMcpContainer(output, args, ws.baseDir, ws.scope);
|
|
84
|
+
}
|
|
85
|
+
for (const output of uniqueContainers(candidates.filter(({ extensionType }) => extensionType === "hook"))) {
|
|
86
|
+
yield* pruneHookContainer(fs, path, output, args, ws.baseDir, ws.scope);
|
|
87
|
+
}
|
|
88
|
+
const after = yield* inventory(args);
|
|
89
|
+
const remaining = new Set(after.outputs.map((output) => `${output.extensionType}\u0000${output.path}\u0000${output.entryName}`));
|
|
90
|
+
const removedPaths = candidates
|
|
91
|
+
.filter((output) => !remaining.has(`${output.extensionType}\u0000${output.path}\u0000${output.entryName}`))
|
|
92
|
+
.map(({ path: outputPath }) => outputPath);
|
|
93
|
+
return { removedPaths: [...new Set(removedPaths)].sort(), preservedPaths };
|
|
263
94
|
});
|
|
264
95
|
/** Inspect ownership proofs without mutating any agent-native artifact. */
|
|
265
96
|
export const inspectWorkspaceOwnership = () => Effect.gen(function* () {
|
|
266
|
-
const fs = yield* FileSystem.FileSystem;
|
|
267
|
-
const path = yield* Path.Path;
|
|
268
97
|
const ws = yield* WorkspaceMutations;
|
|
269
|
-
const agentRepo = yield* CodingAgentRepository;
|
|
270
98
|
const configured = new Set(yield* ws.getConfiguredAgents());
|
|
271
|
-
const
|
|
272
|
-
const
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
path: artifactPath,
|
|
291
|
-
detail: "Agent skill artifact has no AXM symlink or structured file ownership proof.",
|
|
292
|
-
})));
|
|
293
|
-
}
|
|
294
|
-
const subagentsDir = yield* agent.resolveEffectiveSubagentsDir({
|
|
295
|
-
workspaceRoot: ws.baseDir,
|
|
296
|
-
scope: ws.scope,
|
|
297
|
-
});
|
|
298
|
-
if (subagentsDir._tag === "supported") {
|
|
299
|
-
const result = yield* cleanupSubagentArtifactsInDir({
|
|
300
|
-
fs,
|
|
301
|
-
path,
|
|
302
|
-
subagentsDir: subagentsDir.dir,
|
|
303
|
-
dryRun: true,
|
|
304
|
-
});
|
|
305
|
-
issues.push(...result.preservedPaths.map((artifactPath) => ({
|
|
306
|
-
kind: "managed-file-unowned",
|
|
307
|
-
path: artifactPath,
|
|
308
|
-
detail: "Agent subagent artifact has no structured file ownership proof.",
|
|
309
|
-
})));
|
|
310
|
-
}
|
|
311
|
-
const capabilityAgent = CAPABILITY_AGENTS.find((candidate) => candidate.id === agent.id);
|
|
312
|
-
const writer = capabilityAgent?.capabilities.hook.axm.writer;
|
|
313
|
-
if (writer === undefined || writer === null)
|
|
314
|
-
continue;
|
|
315
|
-
for (const file of writer.configFiles.filter((candidate) => candidate.scope === ws.scope && candidate.format === "json")) {
|
|
316
|
-
const configPath = path.resolve(ws.baseDir, file.path);
|
|
317
|
-
if (!(yield* fs.exists(configPath).pipe(Effect.catch(() => Effect.succeed(false)))))
|
|
318
|
-
continue;
|
|
319
|
-
const raw = yield* safeReadFileString(fs, configPath);
|
|
320
|
-
const commands = yield* readAmbiguousHookCommands(configPath, writer.settingsKey, raw);
|
|
321
|
-
issues.push(...commands.map((command) => ({
|
|
322
|
-
kind: "hook-ownership-ambiguous",
|
|
323
|
-
path: configPath,
|
|
324
|
-
detail: `Hook command targets an AXM canonical extension path without x-axm ownership metadata: ${command}`,
|
|
325
|
-
})));
|
|
326
|
-
}
|
|
327
|
-
}
|
|
328
|
-
return issues.filter((issue, index) => issues.findIndex((candidate) => candidate.kind === issue.kind &&
|
|
329
|
-
candidate.path === issue.path &&
|
|
330
|
-
candidate.detail === issue.detail) === index);
|
|
331
|
-
});
|
|
332
|
-
export const cleanupStaleManagedSubagentFiles = (args) => Effect.gen(function* () {
|
|
333
|
-
const fs = yield* FileSystem.FileSystem;
|
|
334
|
-
const path = yield* Path.Path;
|
|
335
|
-
const ws = yield* WorkspaceMutations;
|
|
336
|
-
const agentRepo = yield* CodingAgentRepository;
|
|
337
|
-
const configuredAgentIds = new Set(yield* ws.getConfiguredAgents());
|
|
338
|
-
const agents = yield* agentRepo.all;
|
|
339
|
-
const removedPaths = [];
|
|
340
|
-
for (const agent of agents) {
|
|
341
|
-
const resolved = yield* agent.resolveEffectiveSubagentsDir({
|
|
342
|
-
workspaceRoot: ws.baseDir,
|
|
343
|
-
scope: ws.scope,
|
|
344
|
-
});
|
|
345
|
-
if (resolved._tag !== "supported")
|
|
346
|
-
continue;
|
|
347
|
-
const exists = yield* fs.exists(resolved.dir).pipe(Effect.catch(() => Effect.succeed(false)));
|
|
348
|
-
if (!exists)
|
|
349
|
-
continue;
|
|
350
|
-
const entries = yield* fs
|
|
351
|
-
.readDirectory(resolved.dir)
|
|
352
|
-
.pipe(Effect.catch(() => Effect.succeed([])));
|
|
353
|
-
for (const entry of entries) {
|
|
354
|
-
const filePath = path.join(resolved.dir, entry);
|
|
355
|
-
const stat = yield* fs.stat(filePath).pipe(Effect.option);
|
|
356
|
-
if (stat._tag === "None" || stat.value.type !== "File")
|
|
357
|
-
continue;
|
|
358
|
-
const content = yield* fs
|
|
359
|
-
.readFileString(filePath)
|
|
360
|
-
.pipe(Effect.catch(() => Effect.succeed("")));
|
|
361
|
-
if (!hasAxmManagedMarker(content))
|
|
362
|
-
continue;
|
|
363
|
-
const expected = configuredAgentIds.has(agent.id) &&
|
|
364
|
-
args.expectedSubagentNames.has(extensionNameFromFilename(entry));
|
|
365
|
-
if (expected)
|
|
366
|
-
continue;
|
|
367
|
-
if (args.dryRun !== true) {
|
|
368
|
-
yield* protectWorkspacePath(filePath);
|
|
369
|
-
yield* fs.remove(filePath).pipe(Effect.mapError((error) => new WorkspaceSyncFailed({
|
|
370
|
-
category: "internal",
|
|
371
|
-
detail: `Failed to remove stale managed subagent file: ${filePath}`,
|
|
372
|
-
cause: error,
|
|
373
|
-
})));
|
|
374
|
-
yield* recordFootprint({ path: filePath, change: "removed" });
|
|
375
|
-
}
|
|
376
|
-
removedPaths.push(filePath);
|
|
377
|
-
}
|
|
378
|
-
}
|
|
379
|
-
return { removedPaths };
|
|
99
|
+
const empty = new Set();
|
|
100
|
+
const observed = yield* inventory({
|
|
101
|
+
desiredAgentIds: configured,
|
|
102
|
+
expectedNames: {
|
|
103
|
+
skill: empty,
|
|
104
|
+
subagent: empty,
|
|
105
|
+
"mcp-server": empty,
|
|
106
|
+
hook: empty,
|
|
107
|
+
},
|
|
108
|
+
});
|
|
109
|
+
return observed.unownedFootprints.map((output) => ({
|
|
110
|
+
kind: output.extensionType === "hook"
|
|
111
|
+
? "hook-ownership-ambiguous"
|
|
112
|
+
: "managed-file-unowned",
|
|
113
|
+
path: output.path,
|
|
114
|
+
detail: output.extensionType === "hook"
|
|
115
|
+
? `Hook command targets an AXM canonical extension path without x-axm ownership metadata: ${output.entryName}`
|
|
116
|
+
: `Agent ${output.extensionType} artifact has no AXM ownership proof.`,
|
|
117
|
+
}));
|
|
380
118
|
});
|
|
381
119
|
//# sourceMappingURL=rendered-file-cleanup.js.map
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@agentxm/workspace-sync",
|
|
3
|
-
"version": "0.28.
|
|
3
|
+
"version": "0.28.5",
|
|
4
4
|
"description": "AXM workspace-sync feature: desired-state reconciliation planning, projection realization, and reconciliation outcomes for the axm CLI. Unstable and unsupported — use the axm.sh CLI.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"license": "FSL-1.1-MIT",
|
|
@@ -18,6 +18,7 @@
|
|
|
18
18
|
"exports": {
|
|
19
19
|
".": {
|
|
20
20
|
"types": "./dist/src/index.d.ts",
|
|
21
|
+
"axm-source": "./src/index.ts",
|
|
21
22
|
"default": "./dist/src/index.js"
|
|
22
23
|
}
|
|
23
24
|
},
|
|
@@ -37,11 +38,11 @@
|
|
|
37
38
|
"dependencies": {
|
|
38
39
|
"effect": "4.0.0-rc.112",
|
|
39
40
|
"semver": "^7.8.5",
|
|
40
|
-
"@agentxm/
|
|
41
|
-
"@agentxm/extension-
|
|
42
|
-
"@agentxm/registry-protocol": "^0.28.
|
|
43
|
-
"@agentxm/workspace-state": "^0.28.
|
|
44
|
-
"@agentxm/workspace
|
|
41
|
+
"@agentxm/workspace-operations": "^0.28.5",
|
|
42
|
+
"@agentxm/extension-model": "^0.28.5",
|
|
43
|
+
"@agentxm/registry-protocol": "^0.28.5",
|
|
44
|
+
"@agentxm/workspace-state": "^0.28.5",
|
|
45
|
+
"@agentxm/extension-workspace": "^0.28.5"
|
|
45
46
|
},
|
|
46
47
|
"devDependencies": {
|
|
47
48
|
"@effect/platform-node": "4.0.0-rc.112",
|