skills-console 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (101) hide show
  1. package/CHANGELOG.md +30 -0
  2. package/LICENSE +21 -0
  3. package/README.md +130 -0
  4. package/dist/adapters/filesystem/agent-registry.d.ts +5 -0
  5. package/dist/adapters/filesystem/agent-registry.js +236 -0
  6. package/dist/adapters/filesystem/agent-registry.js.map +1 -0
  7. package/dist/adapters/filesystem/frontmatter.d.ts +2 -0
  8. package/dist/adapters/filesystem/frontmatter.js +73 -0
  9. package/dist/adapters/filesystem/frontmatter.js.map +1 -0
  10. package/dist/adapters/filesystem/skill-scanner.d.ts +8 -0
  11. package/dist/adapters/filesystem/skill-scanner.js +157 -0
  12. package/dist/adapters/filesystem/skill-scanner.js.map +1 -0
  13. package/dist/adapters/filesystem/skills-lock.d.ts +2 -0
  14. package/dist/adapters/filesystem/skills-lock.js +44 -0
  15. package/dist/adapters/filesystem/skills-lock.js.map +1 -0
  16. package/dist/adapters/skills-cli/command-builder.d.ts +7 -0
  17. package/dist/adapters/skills-cli/command-builder.js +144 -0
  18. package/dist/adapters/skills-cli/command-builder.js.map +1 -0
  19. package/dist/adapters/skills-cli/executor.d.ts +20 -0
  20. package/dist/adapters/skills-cli/executor.js +51 -0
  21. package/dist/adapters/skills-cli/executor.js.map +1 -0
  22. package/dist/adapters/skills-cli/source-parser.d.ts +3 -0
  23. package/dist/adapters/skills-cli/source-parser.js +38 -0
  24. package/dist/adapters/skills-cli/source-parser.js.map +1 -0
  25. package/dist/adapters/skills-cli/types.d.ts +56 -0
  26. package/dist/adapters/skills-cli/types.js +2 -0
  27. package/dist/adapters/skills-cli/types.js.map +1 -0
  28. package/dist/application/backup-manager.d.ts +7 -0
  29. package/dist/application/backup-manager.js +164 -0
  30. package/dist/application/backup-manager.js.map +1 -0
  31. package/dist/application/build-inventory.d.ts +5 -0
  32. package/dist/application/build-inventory.js +103 -0
  33. package/dist/application/build-inventory.js.map +1 -0
  34. package/dist/application/doctor-fixes.d.ts +21 -0
  35. package/dist/application/doctor-fixes.js +103 -0
  36. package/dist/application/doctor-fixes.js.map +1 -0
  37. package/dist/application/history-store.d.ts +5 -0
  38. package/dist/application/history-store.js +42 -0
  39. package/dist/application/history-store.js.map +1 -0
  40. package/dist/application/profile-apply.d.ts +22 -0
  41. package/dist/application/profile-apply.js +69 -0
  42. package/dist/application/profile-apply.js.map +1 -0
  43. package/dist/application/profile-diff.d.ts +3 -0
  44. package/dist/application/profile-diff.js +105 -0
  45. package/dist/application/profile-diff.js.map +1 -0
  46. package/dist/application/profile-store.d.ts +9 -0
  47. package/dist/application/profile-store.js +109 -0
  48. package/dist/application/profile-store.js.map +1 -0
  49. package/dist/application/restore-operation.d.ts +8 -0
  50. package/dist/application/restore-operation.js +27 -0
  51. package/dist/application/restore-operation.js.map +1 -0
  52. package/dist/application/skill-operations.d.ts +32 -0
  53. package/dist/application/skill-operations.js +129 -0
  54. package/dist/application/skill-operations.js.map +1 -0
  55. package/dist/cli-commands.d.ts +8 -0
  56. package/dist/cli-commands.js +111 -0
  57. package/dist/cli-commands.js.map +1 -0
  58. package/dist/cli.d.ts +2 -0
  59. package/dist/cli.js +15 -0
  60. package/dist/cli.js.map +1 -0
  61. package/dist/domain/operations.d.ts +50 -0
  62. package/dist/domain/operations.js +25 -0
  63. package/dist/domain/operations.js.map +1 -0
  64. package/dist/domain/profile.d.ts +43 -0
  65. package/dist/domain/profile.js +2 -0
  66. package/dist/domain/profile.js.map +1 -0
  67. package/dist/domain/types.d.ts +98 -0
  68. package/dist/domain/types.js +2 -0
  69. package/dist/domain/types.js.map +1 -0
  70. package/dist/platform/data-paths.d.ts +3 -0
  71. package/dist/platform/data-paths.js +17 -0
  72. package/dist/platform/data-paths.js.map +1 -0
  73. package/dist/platform/environment.d.ts +6 -0
  74. package/dist/platform/environment.js +71 -0
  75. package/dist/platform/environment.js.map +1 -0
  76. package/dist/platform/redaction.d.ts +1 -0
  77. package/dist/platform/redaction.js +7 -0
  78. package/dist/platform/redaction.js.map +1 -0
  79. package/dist/ui/App.d.ts +2 -0
  80. package/dist/ui/App.js +330 -0
  81. package/dist/ui/App.js.map +1 -0
  82. package/dist/ui/DoctorFixWizard.d.ts +12 -0
  83. package/dist/ui/DoctorFixWizard.js +58 -0
  84. package/dist/ui/DoctorFixWizard.js.map +1 -0
  85. package/dist/ui/OperationWizard.d.ts +19 -0
  86. package/dist/ui/OperationWizard.js +301 -0
  87. package/dist/ui/OperationWizard.js.map +1 -0
  88. package/dist/ui/ProfileWizard.d.ts +15 -0
  89. package/dist/ui/ProfileWizard.js +68 -0
  90. package/dist/ui/ProfileWizard.js.map +1 -0
  91. package/dist/ui/RestoreWizard.d.ts +12 -0
  92. package/dist/ui/RestoreWizard.js +42 -0
  93. package/dist/ui/RestoreWizard.js.map +1 -0
  94. package/dist/version.d.ts +1 -0
  95. package/dist/version.js +2 -0
  96. package/dist/version.js.map +1 -0
  97. package/docs/ARCHITECTURE.md +145 -0
  98. package/docs/OPERATIONS.md +200 -0
  99. package/docs/PROFILES.md +83 -0
  100. package/examples/skills-profile.json +21 -0
  101. package/package.json +71 -0
@@ -0,0 +1,164 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { cp, lstat, mkdir, readFile, readlink, realpath, rename, rm, stat, symlink, writeFile } from 'node:fs/promises';
3
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
4
+ import { backupsDirectory } from '../platform/data-paths.js';
5
+ function isContained(root, target, allowRoot = false) {
6
+ const relativePath = relative(resolve(root), resolve(target));
7
+ if (!relativePath) {
8
+ return allowRoot;
9
+ }
10
+ return !relativePath.startsWith('..') && !isAbsolute(relativePath);
11
+ }
12
+ async function pathExists(path) {
13
+ try {
14
+ await lstat(path);
15
+ return true;
16
+ }
17
+ catch {
18
+ return false;
19
+ }
20
+ }
21
+ function matchesPlan(installation, plan) {
22
+ return (installation.mutable &&
23
+ plan.skillNames.includes(installation.skillName) &&
24
+ (!plan.scope || installation.scope === plan.scope) &&
25
+ (plan.agentIds.length === 0 ||
26
+ installation.agentIds.some((agentId) => plan.agentIds.includes(agentId))));
27
+ }
28
+ function allowedRootsForPlan(inventory, plan) {
29
+ return [
30
+ ...new Set(inventory.roots
31
+ .filter((root) => root.mutable)
32
+ .filter((root) => !plan.scope || root.scope === plan.scope)
33
+ .filter((root) => plan.agentIds.length === 0 ||
34
+ root.agentIds.some((agentId) => plan.agentIds.includes(agentId)))
35
+ .map((root) => resolve(root.path))),
36
+ ];
37
+ }
38
+ async function writeSnapshot(snapshot) {
39
+ const finalPath = join(snapshot.directory, 'snapshot.json');
40
+ const temporaryPath = `${finalPath}.tmp`;
41
+ await writeFile(temporaryPath, `${JSON.stringify(snapshot, null, 2)}\n`, 'utf8');
42
+ await rename(temporaryPath, finalPath);
43
+ }
44
+ export async function createOperationSnapshot(plan, inventory, dataRoot) {
45
+ if (plan.kind === 'preview') {
46
+ throw new Error('Cannot snapshot a preview command.');
47
+ }
48
+ const id = randomUUID();
49
+ const directory = join(backupsDirectory(dataRoot), id);
50
+ const contentDirectory = join(directory, 'content');
51
+ await mkdir(contentDirectory, { recursive: true });
52
+ const allowedRoots = allowedRootsForPlan(inventory, plan);
53
+ const existing = inventory.installations.filter((installation) => matchesPlan(installation, plan));
54
+ const entries = [];
55
+ for (const installation of existing) {
56
+ const containingRoot = allowedRoots.find((root) => isContained(root, installation.path));
57
+ if (!containingRoot) {
58
+ throw new Error(`Refusing to back up a path outside approved Skill roots: ${installation.path}`);
59
+ }
60
+ const entryId = randomUUID();
61
+ const backupRelativePath = join('content', entryId);
62
+ const backupPath = join(directory, backupRelativePath);
63
+ let linkTarget;
64
+ if (installation.linkKind === 'symlink') {
65
+ linkTarget = await readlink(installation.path);
66
+ }
67
+ await cp(installation.realPath, backupPath, {
68
+ recursive: true,
69
+ force: false,
70
+ errorOnExist: true,
71
+ preserveTimestamps: true,
72
+ });
73
+ entries.push({
74
+ id: entryId,
75
+ skillName: installation.skillName,
76
+ originalPath: resolve(installation.path),
77
+ realPath: resolve(installation.realPath),
78
+ backupRelativePath,
79
+ linkKind: installation.linkKind,
80
+ linkTarget,
81
+ scope: installation.scope,
82
+ });
83
+ }
84
+ const snapshot = {
85
+ schemaVersion: 1,
86
+ id,
87
+ operationKind: plan.kind,
88
+ createdAt: new Date().toISOString(),
89
+ restoredAt: undefined,
90
+ directory,
91
+ allowedRoots,
92
+ entries,
93
+ createdPaths: [],
94
+ };
95
+ await writeSnapshot(snapshot);
96
+ return snapshot;
97
+ }
98
+ export async function finalizeOperationSnapshot(snapshot, plan, before, after) {
99
+ const beforePaths = new Set(before.installations.filter((installation) => matchesPlan(installation, plan)).map((item) => resolve(item.path)));
100
+ snapshot.createdPaths = after.installations
101
+ .filter((installation) => matchesPlan(installation, plan))
102
+ .map((item) => resolve(item.path))
103
+ .filter((path) => !beforePaths.has(path));
104
+ await writeSnapshot(snapshot);
105
+ return snapshot;
106
+ }
107
+ export async function loadOperationSnapshot(snapshotId, dataRoot) {
108
+ const directory = join(backupsDirectory(dataRoot), snapshotId);
109
+ const parsed = JSON.parse(await readFile(join(directory, 'snapshot.json'), 'utf8'));
110
+ if (parsed.schemaVersion !== 1 || parsed.id !== snapshotId) {
111
+ throw new Error('Unsupported or mismatched snapshot manifest.');
112
+ }
113
+ parsed.directory = directory;
114
+ return parsed;
115
+ }
116
+ function assertRestorablePath(snapshot, path) {
117
+ if (!snapshot.allowedRoots.some((root) => isContained(root, path))) {
118
+ throw new Error(`Refusing to restore a path outside recorded Skill roots: ${path}`);
119
+ }
120
+ }
121
+ export async function restoreOperationSnapshot(snapshot) {
122
+ const fallbacks = [];
123
+ let removedCreatedPaths = 0;
124
+ let restoredEntries = 0;
125
+ for (const createdPath of snapshot.createdPaths) {
126
+ assertRestorablePath(snapshot, createdPath);
127
+ if (await pathExists(createdPath)) {
128
+ await rm(createdPath, { recursive: true, force: true });
129
+ removedCreatedPaths += 1;
130
+ }
131
+ }
132
+ for (const entry of snapshot.entries) {
133
+ assertRestorablePath(snapshot, entry.originalPath);
134
+ const backupPath = join(snapshot.directory, entry.backupRelativePath);
135
+ if (!isContained(snapshot.directory, backupPath)) {
136
+ throw new Error('Snapshot content path escapes its backup directory.');
137
+ }
138
+ await stat(backupPath);
139
+ if (await pathExists(entry.originalPath)) {
140
+ await rm(entry.originalPath, { recursive: true, force: true });
141
+ }
142
+ await mkdir(dirname(entry.originalPath), { recursive: true });
143
+ if (entry.linkKind === 'symlink' && entry.linkTarget) {
144
+ const target = isAbsolute(entry.linkTarget)
145
+ ? entry.linkTarget
146
+ : resolve(dirname(entry.originalPath), entry.linkTarget);
147
+ if (await pathExists(target)) {
148
+ await symlink(entry.linkTarget, entry.originalPath, 'dir');
149
+ }
150
+ else {
151
+ await cp(backupPath, entry.originalPath, { recursive: true, preserveTimestamps: true });
152
+ fallbacks.push(`${entry.skillName}: restored as a directory because its link target is missing.`);
153
+ }
154
+ }
155
+ else {
156
+ await cp(backupPath, entry.originalPath, { recursive: true, preserveTimestamps: true });
157
+ }
158
+ restoredEntries += 1;
159
+ }
160
+ snapshot.restoredAt = new Date().toISOString();
161
+ await writeSnapshot(snapshot);
162
+ return { snapshotId: snapshot.id, restoredEntries, removedCreatedPaths, fallbacks };
163
+ }
164
+ //# sourceMappingURL=backup-manager.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"backup-manager.js","sourceRoot":"","sources":["../../src/application/backup-manager.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { Inventory } from '../domain/types.js';
2
+ export declare function buildInventory(options?: {
3
+ cwd?: string;
4
+ homeDir?: string;
5
+ }): Promise<Inventory>;
@@ -0,0 +1,103 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { resolveAgentRegistry } from '../adapters/filesystem/agent-registry.js';
3
+ import { scanSkillRoots } from '../adapters/filesystem/skill-scanner.js';
4
+ import { enrichInstallationsFromSkillsLocks } from '../adapters/filesystem/skills-lock.js';
5
+ import { detectEnvironment } from '../platform/environment.js';
6
+ function stableId(...parts) {
7
+ return createHash('sha1').update(parts.join('\0')).digest('hex').slice(0, 16);
8
+ }
9
+ function diagnostic(input) {
10
+ return { id: stableId(input.code, input.path ?? '', input.message), ...input };
11
+ }
12
+ function markEffectiveInstallations(installations) {
13
+ const diagnostics = [];
14
+ const byAgentAndName = new Map();
15
+ for (const installation of installations) {
16
+ for (const agentId of installation.agentIds) {
17
+ const key = `${agentId}:${installation.skillName}`;
18
+ byAgentAndName.set(key, [...(byAgentAndName.get(key) ?? []), installation]);
19
+ }
20
+ }
21
+ for (const [key, matches] of byAgentAndName) {
22
+ const projectMatches = matches.filter((item) => item.scope === 'project');
23
+ const effective = projectMatches.length > 0 ? projectMatches : matches;
24
+ for (const installation of matches) {
25
+ installation.isEffective = effective.includes(installation);
26
+ }
27
+ const uniqueEffectivePaths = new Set(effective.map((item) => item.realPath));
28
+ if (uniqueEffectivePaths.size > 1) {
29
+ const skillName = matches[0]?.skillName;
30
+ diagnostics.push(diagnostic({
31
+ code: 'duplicate-effective-skill',
32
+ severity: 'warning',
33
+ message: `${key} resolves to ${uniqueEffectivePaths.size} different physical copies.`,
34
+ path: undefined,
35
+ skillName,
36
+ }));
37
+ }
38
+ if (projectMatches.length > 0 && matches.some((item) => item.scope === 'user')) {
39
+ const skillName = matches[0]?.skillName;
40
+ diagnostics.push(diagnostic({
41
+ code: 'project-shadows-user',
42
+ severity: 'info',
43
+ message: `${key} uses the project installation instead of the user installation.`,
44
+ path: projectMatches[0]?.path,
45
+ skillName,
46
+ }));
47
+ }
48
+ }
49
+ return diagnostics;
50
+ }
51
+ function groupSkills(installations) {
52
+ const grouped = new Map();
53
+ for (const installation of installations) {
54
+ grouped.set(installation.skillName, [
55
+ ...(grouped.get(installation.skillName) ?? []),
56
+ installation,
57
+ ]);
58
+ }
59
+ return [...grouped.entries()]
60
+ .map(([name, matches]) => {
61
+ const diagnostics = matches.flatMap((item) => item.diagnostics);
62
+ return {
63
+ name,
64
+ description: matches.find((item) => item.description)?.description ?? 'No description available.',
65
+ installations: matches.sort((a, b) => a.path.localeCompare(b.path)),
66
+ agentIds: [...new Set(matches.flatMap((item) => item.agentIds))].sort(),
67
+ scopes: [...new Set(matches.map((item) => item.scope))].sort(),
68
+ errorCount: diagnostics.filter((item) => item.severity === 'error').length,
69
+ warningCount: diagnostics.filter((item) => item.severity === 'warning').length,
70
+ };
71
+ })
72
+ .sort((a, b) => a.name.localeCompare(b.name));
73
+ }
74
+ export async function buildInventory(options = {}) {
75
+ const environment = await detectEnvironment(options);
76
+ const { agents, roots } = await resolveAgentRegistry(environment);
77
+ const scanResult = await scanSkillRoots(roots);
78
+ await enrichInstallationsFromSkillsLocks(scanResult.installations, environment);
79
+ const relationshipDiagnostics = markEffectiveInstallations(scanResult.installations);
80
+ const diagnostics = [...scanResult.diagnostics, ...relationshipDiagnostics].sort((a, b) => {
81
+ const rank = { error: 0, warning: 1, info: 2 };
82
+ return rank[a.severity] - rank[b.severity] || a.message.localeCompare(b.message);
83
+ });
84
+ const skills = groupSkills(scanResult.installations);
85
+ return {
86
+ environment,
87
+ agents,
88
+ roots,
89
+ installations: scanResult.installations,
90
+ skills,
91
+ diagnostics,
92
+ stats: {
93
+ skillCount: skills.length,
94
+ installationCount: scanResult.installations.length,
95
+ detectedAgentCount: agents.filter((agent) => agent.detected).length,
96
+ scannedRootCount: roots.filter((root) => root.exists && root.readable).length,
97
+ errorCount: diagnostics.filter((item) => item.severity === 'error').length,
98
+ warningCount: diagnostics.filter((item) => item.severity === 'warning').length,
99
+ },
100
+ scannedAt: new Date().toISOString(),
101
+ };
102
+ }
103
+ //# sourceMappingURL=build-inventory.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"build-inventory.js","sourceRoot":"","sources":["../../src/application/build-inventory.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AAEvC,OAAO,EAAC,oBAAoB,EAAC,MAAM,0CAA0C,CAAC;AAC9E,OAAO,EAAC,cAAc,EAAC,MAAM,yCAAyC,CAAC;AACvE,OAAO,EAAC,kCAAkC,EAAC,MAAM,uCAAuC,CAAC;AAOzF,OAAO,EAAC,iBAAiB,EAAC,MAAM,4BAA4B,CAAC;AAE7D,SAAS,QAAQ,CAAC,GAAG,KAAe;IAClC,OAAO,UAAU,CAAC,MAAM,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;AAChF,CAAC;AAED,SAAS,UAAU,CAAC,KAA6B;IAC/C,OAAO,EAAC,EAAE,EAAE,QAAQ,CAAC,KAAK,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,IAAI,EAAE,EAAE,KAAK,CAAC,OAAO,CAAC,EAAE,GAAG,KAAK,EAAC,CAAC;AAC/E,CAAC;AAED,SAAS,0BAA0B,CAAC,aAAkC;IACpE,MAAM,WAAW,GAAiB,EAAE,CAAC;IACrC,MAAM,cAAc,GAAG,IAAI,GAAG,EAA+B,CAAC;IAE9D,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,KAAK,MAAM,OAAO,IAAI,YAAY,CAAC,QAAQ,EAAE,CAAC;YAC5C,MAAM,GAAG,GAAG,GAAG,OAAO,IAAI,YAAY,CAAC,SAAS,EAAE,CAAC;YACnD,cAAc,CAAC,GAAG,CAAC,GAAG,EAAE,CAAC,GAAG,CAAC,cAAc,CAAC,GAAG,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,EAAE,YAAY,CAAC,CAAC,CAAC;QAC9E,CAAC;IACH,CAAC;IAED,KAAK,MAAM,CAAC,GAAG,EAAE,OAAO,CAAC,IAAI,cAAc,EAAE,CAAC;QAC5C,MAAM,cAAc,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC;QAC1E,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,OAAO,CAAC;QAEvE,KAAK,MAAM,YAAY,IAAI,OAAO,EAAE,CAAC;YACnC,YAAY,CAAC,WAAW,GAAG,SAAS,CAAC,QAAQ,CAAC,YAAY,CAAC,CAAC;QAC9D,CAAC;QAED,MAAM,oBAAoB,GAAG,IAAI,GAAG,CAAC,SAAS,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;QAC7E,IAAI,oBAAoB,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;YAClC,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;YACxC,WAAW,CAAC,IAAI,CACd,UAAU,CAAC;gBACT,IAAI,EAAE,2BAA2B;gBACjC,QAAQ,EAAE,SAAS;gBACnB,OAAO,EAAE,GAAG,GAAG,gBAAgB,oBAAoB,CAAC,IAAI,6BAA6B;gBACrF,IAAI,EAAE,SAAS;gBACf,SAAS;aACV,CAAC,CACH,CAAC;QACJ,CAAC;QAED,IAAI,cAAc,CAAC,MAAM,GAAG,CAAC,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,KAAK,MAAM,CAAC,EAAE,CAAC;YAC/E,MAAM,SAAS,GAAG,OAAO,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC;YACxC,WAAW,CAAC,IAAI,CACd,UAAU,CAAC;gBACT,IAAI,EAAE,sBAAsB;gBAC5B,QAAQ,EAAE,MAAM;gBAChB,OAAO,EAAE,GAAG,GAAG,kEAAkE;gBACjF,IAAI,EAAE,cAAc,CAAC,CAAC,CAAC,EAAE,IAAI;gBAC7B,SAAS;aACV,CAAC,CACH,CAAC;QACJ,CAAC;IACH,CAAC;IAED,OAAO,WAAW,CAAC;AACrB,CAAC;AAED,SAAS,WAAW,CAAC,aAAkC;IACrD,MAAM,OAAO,GAAG,IAAI,GAAG,EAA+B,CAAC;IAEvD,KAAK,MAAM,YAAY,IAAI,aAAa,EAAE,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,EAAE;YAClC,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,YAAY,CAAC,SAAS,CAAC,IAAI,EAAE,CAAC;YAC9C,YAAY;SACb,CAAC,CAAC;IACL,CAAC;IAED,OAAO,CAAC,GAAG,OAAO,CAAC,OAAO,EAAE,CAAC;SAC1B,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,OAAO,CAAC,EAAE,EAAE;QACvB,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAChE,OAAO;YACL,IAAI;YACJ,WAAW,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,WAAW,CAAC,EAAE,WAAW,IAAI,2BAA2B;YACjG,aAAa,EAAE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;YACnE,QAAQ,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YACvE,MAAM,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE;YAC9D,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;YAC1E,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;SAC1D,CAAC;IACzB,CAAC,CAAC;SACD,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC;AAClD,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,cAAc,CAAC,OAAO,GAGxC,EAAE;IACJ,MAAM,WAAW,GAAG,MAAM,iBAAiB,CAAC,OAAO,CAAC,CAAC;IACrD,MAAM,EAAC,MAAM,EAAE,KAAK,EAAC,GAAG,MAAM,oBAAoB,CAAC,WAAW,CAAC,CAAC;IAChE,MAAM,UAAU,GAAG,MAAM,cAAc,CAAC,KAAK,CAAC,CAAC;IAC/C,MAAM,kCAAkC,CAAC,UAAU,CAAC,aAAa,EAAE,WAAW,CAAC,CAAC;IAChF,MAAM,uBAAuB,GAAG,0BAA0B,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IACrF,MAAM,WAAW,GAAG,CAAC,GAAG,UAAU,CAAC,WAAW,EAAE,GAAG,uBAAuB,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE;QACxF,MAAM,IAAI,GAAG,EAAC,KAAK,EAAE,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAC,CAAC;QAC7C,OAAO,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,IAAI,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,OAAO,CAAC,aAAa,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC;IACnF,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,WAAW,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAErD,OAAO;QACL,WAAW;QACX,MAAM;QACN,KAAK;QACL,aAAa,EAAE,UAAU,CAAC,aAAa;QACvC,MAAM;QACN,WAAW;QACX,KAAK,EAAE;YACL,UAAU,EAAE,MAAM,CAAC,MAAM;YACzB,iBAAiB,EAAE,UAAU,CAAC,aAAa,CAAC,MAAM;YAClD,kBAAkB,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAC,MAAM;YACnE,gBAAgB,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,IAAI,IAAI,CAAC,QAAQ,CAAC,CAAC,MAAM;YAC7E,UAAU,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,OAAO,CAAC,CAAC,MAAM;YAC1E,YAAY,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;SAC/E;QACD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;KACpC,CAAC;AACJ,CAAC"}
@@ -0,0 +1,21 @@
1
+ import type { OperationRecord, OperationSnapshot } from '../domain/operations.js';
2
+ import type { Diagnostic, Inventory, SkillInstallation, SkillRoot } from '../domain/types.js';
3
+ export interface DoctorFixPlan {
4
+ kind: 'rename-skill-directory';
5
+ diagnosticId: string;
6
+ description: string;
7
+ sourcePath: string;
8
+ targetPath: string;
9
+ skillName: string;
10
+ agentIds: string[];
11
+ root: SkillRoot;
12
+ installation: SkillInstallation;
13
+ }
14
+ export interface DoctorFixResult {
15
+ inventory: Inventory;
16
+ record: OperationRecord;
17
+ snapshot: OperationSnapshot;
18
+ message: string;
19
+ }
20
+ export declare function buildDoctorFixPlan(diagnostic: Diagnostic, inventory: Inventory): Promise<DoctorFixPlan | undefined>;
21
+ export declare function executeDoctorFix(fix: DoctorFixPlan, inventory: Inventory, dataRoot: string): Promise<DoctorFixResult>;
@@ -0,0 +1,103 @@
1
+ import { lstat, rename, stat } from 'node:fs/promises';
2
+ import { dirname, isAbsolute, join, relative, resolve } from 'node:path';
3
+ import { createOperationSnapshot, finalizeOperationSnapshot, } from './backup-manager.js';
4
+ import { buildInventory } from './build-inventory.js';
5
+ import { createHistoryRecord, saveHistoryRecord, } from './history-store.js';
6
+ function isContained(root, target) {
7
+ const relativePath = relative(resolve(root), resolve(target));
8
+ return Boolean(relativePath) && !relativePath.startsWith('..') && !isAbsolute(relativePath);
9
+ }
10
+ async function pathExists(path) {
11
+ try {
12
+ await lstat(path);
13
+ return true;
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ }
19
+ export async function buildDoctorFixPlan(diagnostic, inventory) {
20
+ if (diagnostic.code !== 'name-directory-mismatch') {
21
+ return undefined;
22
+ }
23
+ const installation = inventory.installations.find((item) => item.diagnostics.some((itemDiagnostic) => itemDiagnostic.id === diagnostic.id));
24
+ if (!installation?.mutable) {
25
+ return undefined;
26
+ }
27
+ const root = inventory.roots.find((candidate) => candidate.mutable && isContained(candidate.path, installation.path));
28
+ if (!root) {
29
+ return undefined;
30
+ }
31
+ const targetPath = join(dirname(installation.path), installation.skillName);
32
+ if (!isContained(root.path, targetPath) || (await pathExists(targetPath))) {
33
+ return undefined;
34
+ }
35
+ return {
36
+ kind: 'rename-skill-directory',
37
+ diagnosticId: diagnostic.id,
38
+ description: `Rename ${installation.directoryName} to ${installation.skillName}`,
39
+ sourcePath: installation.path,
40
+ targetPath,
41
+ skillName: installation.skillName,
42
+ agentIds: installation.agentIds,
43
+ root,
44
+ installation,
45
+ };
46
+ }
47
+ function commandPlan(fix, inventory) {
48
+ return {
49
+ kind: 'repair',
50
+ executable: 'internal-doctor-fix',
51
+ args: [],
52
+ cwd: inventory.environment.projectRoot,
53
+ environment: {},
54
+ displayCommand: `skills-console doctor rename '${fix.sourcePath}' '${fix.targetPath}'`,
55
+ mutatesFilesystem: true,
56
+ skillNames: [fix.skillName],
57
+ agentIds: fix.agentIds,
58
+ scope: fix.installation.scope,
59
+ source: undefined,
60
+ };
61
+ }
62
+ export async function executeDoctorFix(fix, inventory, dataRoot) {
63
+ const plan = commandPlan(fix, inventory);
64
+ const snapshot = await createOperationSnapshot(plan, inventory, dataRoot);
65
+ const record = await createHistoryRecord(plan, snapshot.id, dataRoot);
66
+ try {
67
+ await stat(fix.sourcePath);
68
+ if (await pathExists(fix.targetPath)) {
69
+ throw new Error(`Repair target already exists: ${fix.targetPath}`);
70
+ }
71
+ await rename(fix.sourcePath, fix.targetPath);
72
+ const updatedInventory = await buildInventory({
73
+ cwd: inventory.environment.projectRoot,
74
+ homeDir: inventory.environment.homeDir,
75
+ });
76
+ await finalizeOperationSnapshot(snapshot, plan, inventory, updatedInventory);
77
+ const stillBroken = updatedInventory.diagnostics.some((diagnostic) => diagnostic.code === 'name-directory-mismatch' && diagnostic.skillName === fix.skillName);
78
+ record.status = stillBroken ? 'failed' : 'succeeded';
79
+ record.finishedAt = new Date().toISOString();
80
+ record.exitCode = 0;
81
+ record.verificationStatus = stillBroken ? 'failed' : 'verified';
82
+ record.verificationMessages = [
83
+ stillBroken
84
+ ? 'Directory rename completed but the mismatch diagnostic remains.'
85
+ : `Renamed Skill directory to ${fix.skillName}.`,
86
+ ];
87
+ await saveHistoryRecord(record, dataRoot);
88
+ return {
89
+ inventory: updatedInventory,
90
+ record,
91
+ snapshot,
92
+ message: record.verificationMessages[0] ?? 'Repair complete.',
93
+ };
94
+ }
95
+ catch (caught) {
96
+ record.status = 'failed';
97
+ record.finishedAt = new Date().toISOString();
98
+ record.error = caught instanceof Error ? caught.message : 'Unknown Doctor repair failure.';
99
+ await saveHistoryRecord(record, dataRoot);
100
+ throw caught;
101
+ }
102
+ }
103
+ //# sourceMappingURL=doctor-fixes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"doctor-fixes.js","sourceRoot":"","sources":["../../src/application/doctor-fixes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,5 @@
1
+ import type { SkillsCommandPlan } from '../adapters/skills-cli/types.js';
2
+ import { type OperationRecord } from '../domain/operations.js';
3
+ export declare function createHistoryRecord(plan: SkillsCommandPlan, snapshotId: string, dataRoot: string): Promise<OperationRecord>;
4
+ export declare function saveHistoryRecord(record: OperationRecord, dataRoot: string): Promise<void>;
5
+ export declare function listHistoryRecords(dataRoot: string): Promise<OperationRecord[]>;
@@ -0,0 +1,42 @@
1
+ import { randomUUID } from 'node:crypto';
2
+ import { mkdir, readFile, readdir, rename, writeFile } from 'node:fs/promises';
3
+ import { join } from 'node:path';
4
+ import { operationRecordFromPlan, } from '../domain/operations.js';
5
+ import { historyDirectory } from '../platform/data-paths.js';
6
+ export async function createHistoryRecord(plan, snapshotId, dataRoot) {
7
+ const record = operationRecordFromPlan(randomUUID(), snapshotId, plan);
8
+ await saveHistoryRecord(record, dataRoot);
9
+ return record;
10
+ }
11
+ export async function saveHistoryRecord(record, dataRoot) {
12
+ const directory = historyDirectory(dataRoot);
13
+ await mkdir(directory, { recursive: true });
14
+ const finalPath = join(directory, `${record.id}.json`);
15
+ const temporaryPath = `${finalPath}.tmp`;
16
+ await writeFile(temporaryPath, `${JSON.stringify(record, null, 2)}\n`, 'utf8');
17
+ await rename(temporaryPath, finalPath);
18
+ }
19
+ export async function listHistoryRecords(dataRoot) {
20
+ const directory = historyDirectory(dataRoot);
21
+ let names;
22
+ try {
23
+ names = await readdir(directory);
24
+ }
25
+ catch {
26
+ return [];
27
+ }
28
+ const records = [];
29
+ for (const name of names.filter((value) => value.endsWith('.json'))) {
30
+ try {
31
+ const record = JSON.parse(await readFile(join(directory, name), 'utf8'));
32
+ if (record.schemaVersion === 1) {
33
+ records.push(record);
34
+ }
35
+ }
36
+ catch {
37
+ // Ignore malformed records and keep the remaining history available.
38
+ }
39
+ }
40
+ return records.sort((a, b) => b.startedAt.localeCompare(a.startedAt));
41
+ }
42
+ //# sourceMappingURL=history-store.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"history-store.js","sourceRoot":"","sources":["../../src/application/history-store.ts"],"names":[],"mappings":"AAAA,OAAO,EAAC,UAAU,EAAC,MAAM,aAAa,CAAC;AACvC,OAAO,EAAC,KAAK,EAAE,QAAQ,EAAE,OAAO,EAAE,MAAM,EAAE,SAAS,EAAC,MAAM,kBAAkB,CAAC;AAC7E,OAAO,EAAC,IAAI,EAAC,MAAM,WAAW,CAAC;AAG/B,OAAO,EACL,uBAAuB,GAExB,MAAM,yBAAyB,CAAC;AACjC,OAAO,EAAC,gBAAgB,EAAC,MAAM,2BAA2B,CAAC;AAE3D,MAAM,CAAC,KAAK,UAAU,mBAAmB,CACvC,IAAuB,EACvB,UAAkB,EAClB,QAAgB;IAEhB,MAAM,MAAM,GAAG,uBAAuB,CAAC,UAAU,EAAE,EAAE,UAAU,EAAE,IAAI,CAAC,CAAC;IACvE,MAAM,iBAAiB,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;IAC1C,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,iBAAiB,CACrC,MAAuB,EACvB,QAAgB;IAEhB,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7C,MAAM,KAAK,CAAC,SAAS,EAAE,EAAC,SAAS,EAAE,IAAI,EAAC,CAAC,CAAC;IAC1C,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,EAAE,GAAG,MAAM,CAAC,EAAE,OAAO,CAAC,CAAC;IACvD,MAAM,aAAa,GAAG,GAAG,SAAS,MAAM,CAAC;IACzC,MAAM,SAAS,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,MAAM,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;IAC/E,MAAM,MAAM,CAAC,aAAa,EAAE,SAAS,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,CAAC,KAAK,UAAU,kBAAkB,CAAC,QAAgB;IACvD,MAAM,SAAS,GAAG,gBAAgB,CAAC,QAAQ,CAAC,CAAC;IAC7C,IAAI,KAAe,CAAC;IACpB,IAAI,CAAC;QACH,KAAK,GAAG,MAAM,OAAO,CAAC,SAAS,CAAC,CAAC;IACnC,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,EAAE,CAAC;IACZ,CAAC;IACD,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,KAAK,MAAM,IAAI,IAAI,KAAK,CAAC,MAAM,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC,EAAE,CAAC;QACpE,IAAI,CAAC;YACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,QAAQ,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,EAAE,MAAM,CAAC,CAAoB,CAAC;YAC5F,IAAI,MAAM,CAAC,aAAa,KAAK,CAAC,EAAE,CAAC;gBAC/B,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,qEAAqE;QACvE,CAAC;IACH,CAAC;IACD,OAAO,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,aAAa,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC;AACxE,CAAC"}
@@ -0,0 +1,22 @@
1
+ import type { SpawnProcess } from '../adapters/skills-cli/executor.js';
2
+ import type { SkillsCommandPlan } from '../adapters/skills-cli/types.js';
3
+ import type { OperationResult } from './skill-operations.js';
4
+ import type { ProfileDiff, ProfileDiffEntry } from '../domain/profile.js';
5
+ import type { Inventory } from '../domain/types.js';
6
+ export interface ProfileApplyPlanItem {
7
+ entry: ProfileDiffEntry;
8
+ action: 'install' | 'remove' | 'skip';
9
+ command?: SkillsCommandPlan;
10
+ reason?: string;
11
+ }
12
+ export interface ProfileApplyResult {
13
+ inventory: Inventory;
14
+ operations: OperationResult[];
15
+ skipped: ProfileApplyPlanItem[];
16
+ }
17
+ export declare function buildProfileApplyPlan(diff: ProfileDiff, inventory: Inventory): ProfileApplyPlanItem[];
18
+ export declare function applyProfilePlan(plan: ProfileApplyPlanItem[], inventory: Inventory, options?: {
19
+ dataRoot?: string;
20
+ spawnProcess?: SpawnProcess;
21
+ onProgress?: (item: ProfileApplyPlanItem, index: number, total: number) => void;
22
+ }): Promise<ProfileApplyResult>;
@@ -0,0 +1,69 @@
1
+ import { buildInstallPlan, buildRemovePlan, } from '../adapters/skills-cli/command-builder.js';
2
+ import { executeOperation } from './skill-operations.js';
3
+ export function buildProfileApplyPlan(diff, inventory) {
4
+ return diff.entries.flatMap((entry) => {
5
+ if (entry.status === 'missing' || entry.status === 'source-mismatch') {
6
+ if (!entry.expected?.source) {
7
+ return [{ entry, action: 'skip', reason: 'Missing source; cannot install reproducibly.' }];
8
+ }
9
+ return [
10
+ {
11
+ entry,
12
+ action: 'install',
13
+ command: buildInstallPlan({
14
+ source: entry.expected.source,
15
+ skillNames: [entry.expected.name],
16
+ agentIds: entry.status === 'missing' && entry.missingAgentIds.length > 0
17
+ ? entry.missingAgentIds
18
+ : entry.expected.agentIds,
19
+ scope: entry.expected.scope,
20
+ mode: entry.expected.mode,
21
+ cwd: inventory.environment.projectRoot,
22
+ }),
23
+ },
24
+ ];
25
+ }
26
+ if (entry.status === 'extra' && diff.profile.policy.removeExtras) {
27
+ const agentIds = [...new Set(entry.actual.flatMap((item) => item.agentIds))];
28
+ return [
29
+ {
30
+ entry,
31
+ action: 'remove',
32
+ command: buildRemovePlan({
33
+ skillNames: [entry.skillName],
34
+ agentIds,
35
+ scope: entry.scope,
36
+ cwd: inventory.environment.projectRoot,
37
+ }),
38
+ },
39
+ ];
40
+ }
41
+ if (entry.status === 'source-unknown') {
42
+ return [{ entry, action: 'skip', reason: 'Source is unknown; refusing to overwrite.' }];
43
+ }
44
+ return [];
45
+ });
46
+ }
47
+ export async function applyProfilePlan(plan, inventory, options = {}) {
48
+ let currentInventory = inventory;
49
+ const operations = [];
50
+ const skipped = plan.filter((item) => item.action === 'skip' || !item.command);
51
+ const executable = plan.filter((item) => item.command && item.action !== 'skip');
52
+ for (let index = 0; index < executable.length; index += 1) {
53
+ const item = executable[index];
54
+ options.onProgress?.(item, index, executable.length);
55
+ const result = await executeOperation(item.command, {
56
+ homeDir: currentInventory.environment.homeDir,
57
+ inventoryBefore: currentInventory,
58
+ ...(options.dataRoot ? { dataRoot: options.dataRoot } : {}),
59
+ ...(options.spawnProcess ? { spawnProcess: options.spawnProcess } : {}),
60
+ });
61
+ operations.push(result);
62
+ currentInventory = result.inventory;
63
+ if (result.verification.status === 'failed') {
64
+ break;
65
+ }
66
+ }
67
+ return { inventory: currentInventory, operations, skipped };
68
+ }
69
+ //# sourceMappingURL=profile-apply.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"profile-apply.js","sourceRoot":"","sources":["../../src/application/profile-apply.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,3 @@
1
+ import type { ProfileDiff, SkillsProfile } from '../domain/profile.js';
2
+ import type { Inventory } from '../domain/types.js';
3
+ export declare function diffProfile(profile: SkillsProfile, inventory: Inventory): ProfileDiff;