@vltpkg/cli-js 1.4.0 → 1.6.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 (105) hide show
  1. package/{access-422UGEWN.js → access-AJ654YKY.js} +13 -12
  2. package/{bugs-RED7Y33Q.js → bugs-N73DVYHD.js} +32 -25
  3. package/{build-IHMPBWRO.js → build-VZ3EZKMM.js} +65 -21
  4. package/{cache-FJP2RZJX.js → cache-VROEWG2C.js} +20 -17
  5. package/cache-unzip-src-unzip.js +58 -15
  6. package/{chunk-TPRK6IDA.js → chunk-22LZBDEC.js} +2 -2
  7. package/chunk-36UIE654.js +6248 -0
  8. package/{chunk-UGCKF5ZE.js → chunk-3JIN46K5.js} +1 -1
  9. package/{chunk-OAJ3PO3Z.js → chunk-44AWMA4F.js} +25 -13
  10. package/chunk-4E65BBTM.js +77 -0
  11. package/{chunk-SR2VOY5J.js → chunk-4GMNWW4C.js} +1 -1
  12. package/{chunk-5IJTPZXP.js → chunk-6D3QAFNZ.js} +1 -1
  13. package/{chunk-X4FVR4R5.js → chunk-75HGJVNG.js} +12 -10
  14. package/{chunk-THSYN5EK.js → chunk-7M2VTFLP.js} +12 -1
  15. package/{chunk-2AMOC4DN.js → chunk-ANW36H4T.js} +4 -4
  16. package/chunk-B6RIGNEO.js +626 -0
  17. package/{chunk-FLH4YC6W.js → chunk-BF5DRGRZ.js} +60 -15
  18. package/chunk-BH5CVXNY.js +115 -0
  19. package/{chunk-PLG3OYCX.js → chunk-CAV7FKWQ.js} +3 -2
  20. package/{chunk-C23TDXRG.js → chunk-CYK6I4M6.js} +1 -1
  21. package/chunk-DXED4ARV.js +436 -0
  22. package/chunk-E74WGW5C.js +49 -0
  23. package/{chunk-WF6KLKRN.js → chunk-EFHOWRKU.js} +103 -1
  24. package/chunk-EMTGRCSE.js +1111 -0
  25. package/{chunk-5Y4SYLJ2.js → chunk-EYGOEAJM.js} +1 -1
  26. package/{chunk-OVPHE4O7.js → chunk-F5LZMLAQ.js} +5335 -10902
  27. package/{chunk-HZXJ423P.js → chunk-FXD3IV2S.js} +4 -2
  28. package/chunk-GCTREKA4.js +115 -0
  29. package/{chunk-ZJMJ7MCT.js → chunk-GEQFMH5M.js} +1 -1
  30. package/{chunk-ISE4IRHF.js → chunk-GZVI75KX.js} +7 -14
  31. package/chunk-HOF7LEIC.js +24 -0
  32. package/{chunk-LHPEBLOU.js → chunk-HT6FS4VB.js} +1 -1
  33. package/{chunk-PHJJPY5G.js → chunk-IXAMCWIT.js} +5 -5
  34. package/{chunk-ASLX43R3.js → chunk-JCNI6ZHH.js} +7 -5
  35. package/chunk-JV5XR5JQ.js +349 -0
  36. package/{chunk-7T3XAYP4.js → chunk-KD5ZK72K.js} +1 -1
  37. package/{chunk-FZUYGJZU.js → chunk-KVWGMSPW.js} +137 -19
  38. package/{chunk-TO23PR7J.js → chunk-LCLRP64K.js} +14 -12
  39. package/{chunk-QCSUWACA.js → chunk-LGQVZTYR.js} +8 -36
  40. package/{chunk-5RHABCYI.js → chunk-LP3ORD3D.js} +143 -17
  41. package/chunk-MCDLJZXT.js +82 -0
  42. package/{chunk-DNRR3XMG.js → chunk-N6HV7JWC.js} +1 -1
  43. package/chunk-O6MQ7NN6.js +1155 -0
  44. package/{chunk-GIIAODRI.js → chunk-PC2HOBAQ.js} +7 -5
  45. package/{chunk-APMYKJI2.js → chunk-QNHBAGXQ.js} +1 -1
  46. package/chunk-RBQO54TG.js +59 -0
  47. package/chunk-SUU2WETN.js +268 -0
  48. package/{chunk-I7UMHYZX.js → chunk-TQQO2F56.js} +113 -1187
  49. package/{chunk-4UCADW6S.js → chunk-TWDSXQPN.js} +9 -7
  50. package/{chunk-MKWPTN3C.js → chunk-VLVMLSIF.js} +2 -2
  51. package/chunk-W4T5CGCO.js +52 -0
  52. package/{chunk-5TNXLRW2.js → chunk-YTDABXPD.js} +50 -12
  53. package/{ci-YSKNNO5M.js → ci-3BVMVQIT.js} +35 -13
  54. package/cli-package.json +3 -1
  55. package/{config-HO7GY3QT.js → config-2KQV7N5A.js} +16 -13
  56. package/{config-CSPCDMR3.js → config-EKHBW6I5.js} +12 -9
  57. package/{create-2TJT3AHJ.js → create-QVHNOIV3.js} +35 -29
  58. package/{deprecate-7FRJI2RL.js → deprecate-E254QBH6.js} +17 -15
  59. package/{dist-tag-WCFF5OEG.js → dist-tag-SITRFD7O.js} +13 -12
  60. package/{docs-JMBPTU23.js → docs-IDL2P7CA.js} +32 -25
  61. package/{exec-FBOUKZZ2.js → exec-7BK2W2WL.js} +35 -29
  62. package/{exec-cache-X3ZWM5S3.js → exec-cache-VY46L7DR.js} +27 -21
  63. package/{exec-local-Y3KQC22N.js → exec-local-D7R5T3DF.js} +26 -20
  64. package/{help-PUKVH5X7.js → help-RMRIEJQL.js} +6 -5
  65. package/{init-GOKAQXXZ.js → init-BGW4HJ6V.js} +15 -11
  66. package/{install-XFN4UFOC.js → install-U5GATZ2N.js} +144 -49
  67. package/{list-43JFFG5D.js → list-3VG4M2XL.js} +41 -28
  68. package/{login-RSTZKNKN.js → login-PHQWI6S6.js} +19 -16
  69. package/{logout-4576FFXZ.js → logout-DJCOGRFF.js} +13 -12
  70. package/{outdated-ACQ5A2Y7.js → outdated-JH3O6R3Y.js} +27 -22
  71. package/{pack-QQVJ3G25.js → pack-U5W5YWHK.js} +23 -18
  72. package/package.json +1 -1
  73. package/{ping-QCDQQRO5.js → ping-EKX43AOW.js} +13 -12
  74. package/{pkg-CSOJV7UC.js → pkg-SW5GMERT.js} +19 -14
  75. package/{profile-VL4HPW3N.js → profile-UGDRDMQ6.js} +13 -12
  76. package/{publish-2YBO6ZXE.js → publish-HTWKK3NN.js} +60 -45
  77. package/{query-IHHFMJRT.js → query-YE3FUVGG.js} +43 -30
  78. package/{registry-W7BRZZZ2.js → registry-ZGGWVLBM.js} +7 -7
  79. package/registry-client-src-revalidate.js +76 -22
  80. package/{repo-L3BXAAWS.js → repo-WDOCU6SE.js} +32 -25
  81. package/{reporter-5NYOHBO7.js → reporter-N5PAXB26.js} +121 -17
  82. package/{run-AMUUVLTI.js → run-IPARVIIQ.js} +26 -20
  83. package/{run-exec-5W3XWQZA.js → run-exec-C4RTREEW.js} +26 -20
  84. package/security-archive-src-update-expired.js +66 -21
  85. package/{setup-TFM4GJF7.js → setup-SYYUEHZL.js} +212 -32
  86. package/skills-KA2VR5Q5.js +480 -0
  87. package/skills-UBBMSBDQ.js +416 -0
  88. package/{src-4CYCUWZL.js → src-FUSTSM4J.js} +33 -22
  89. package/{src-I3GMULFP.js → src-QO5G2S4O.js} +11 -8
  90. package/{src-LUTN2ODD.js → src-W2VQULRG.js} +2 -2
  91. package/{token-OANOBE3G.js → token-UQNABECH.js} +15 -13
  92. package/{uninstall-YXTQ4AIZ.js → uninstall-FHBJ3OUV.js} +59 -18
  93. package/{unpublish-SZXYMYIU.js → unpublish-APJTEUBA.js} +31 -16
  94. package/{update-FHLMWGIM.js → update-NWZTL4S7.js} +52 -25
  95. package/{version-ZWFCTU5V.js → version-EMKKTL77.js} +20 -14
  96. package/{view-NFNJXMLV.js → view-BUUI33RV.js} +17 -15
  97. package/vlr.js +1 -1
  98. package/vlrx.js +1 -1
  99. package/vlt.js +1 -1
  100. package/vlx.js +1 -1
  101. package/vlxl.js +1 -1
  102. package/{whoami-O7GOSGCI.js → whoami-F6BSXGQ2.js} +13 -12
  103. package/chunk-G2YT2GWF.js +0 -120
  104. package/chunk-T6FBP4OU.js +0 -76
  105. package/chunk-U7TEQCBN.js +0 -880
@@ -0,0 +1,480 @@
1
+ var global = globalThis;
2
+ import {Buffer} from "node:buffer";
3
+ import {setTimeout as _vlt_setTimeout,clearTimeout as _vlt_clearTimeout,setImmediate as _vlt_setImmediate,clearImmediate as _vlt_clearImmediate,setInterval as _vlt_setInterval,clearInterval as _vlt_clearInterval} from "node:timers";
4
+ globalThis.setTimeout = _vlt_setTimeout;
5
+ globalThis.clearTimeout = _vlt_clearTimeout;
6
+ globalThis.setImmediate = _vlt_setImmediate;
7
+ globalThis.clearImmediate = _vlt_clearImmediate;
8
+ globalThis.setInterval = _vlt_setInterval;
9
+ globalThis.clearInterval = _vlt_clearInterval;
10
+ import {createRequire as _vlt_createRequire} from "node:module";
11
+ var require = _vlt_createRequire(import.meta.filename);
12
+ import {
13
+ editGitignore,
14
+ filterNodesByQueryParts,
15
+ load2 as load,
16
+ lstat,
17
+ mountSkill,
18
+ norm,
19
+ packageKey,
20
+ readMounts,
21
+ realOr,
22
+ samePath,
23
+ skillsDirs,
24
+ unmountSkill,
25
+ unshare
26
+ } from "./chunk-F5LZMLAQ.js";
27
+ import "./chunk-YTDABXPD.js";
28
+ import {
29
+ Monorepo
30
+ } from "./chunk-TQQO2F56.js";
31
+ import {
32
+ splitDepID
33
+ } from "./chunk-CAV7FKWQ.js";
34
+ import "./chunk-6D3QAFNZ.js";
35
+ import "./chunk-HTOTG4TS.js";
36
+ import "./chunk-GEQFMH5M.js";
37
+ import "./chunk-B6RIGNEO.js";
38
+ import "./chunk-XNLSTHDK.js";
39
+ import "./chunk-Y5PA7DVK.js";
40
+ import {
41
+ parse
42
+ } from "./chunk-BF5DRGRZ.js";
43
+ import "./chunk-WZWDS3W4.js";
44
+ import "./chunk-PZLD7RTK.js";
45
+
46
+ // ../../src/graph/src/skills/index.ts
47
+ import { existsSync } from "node:fs";
48
+
49
+ // ../../src/graph/src/skills/discover.ts
50
+ import { readdirSync, readFileSync } from "node:fs";
51
+ import { resolve } from "node:path";
52
+ var skillDirName = /^[a-z0-9][a-z0-9._-]*$/i;
53
+ var specName = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
54
+ var topKey = /^([A-Za-z0-9_-]+):/;
55
+ var blockIndicator = /^[>|][-+1-9]*$/;
56
+ var fold = (inline, more) => {
57
+ let value = [blockIndicator.test(inline) ? "" : inline, ...more].filter(Boolean).join(" ");
58
+ const q = value[0];
59
+ if (value.length > 1 && (q === '"' || q === "'") && value.endsWith(q)) {
60
+ value = value.slice(1, -1).trim();
61
+ }
62
+ return value || void 0;
63
+ };
64
+ var readFrontmatter = (file) => {
65
+ let text;
66
+ try {
67
+ text = readFileSync(file, "utf8");
68
+ } catch {
69
+ return {};
70
+ }
71
+ const lines = text.split(/\r?\n/);
72
+ if (lines[0]?.trim() !== "---") return {};
73
+ const end = lines.findIndex((l, i) => i > 0 && l.trim() === "---");
74
+ if (end === -1) return {};
75
+ const fm = {};
76
+ let key;
77
+ let inline = "";
78
+ let more = [];
79
+ const flush = () => {
80
+ if (key) fm[key] = fold(inline, more);
81
+ key = void 0;
82
+ };
83
+ for (const line of lines.slice(1, end)) {
84
+ if (!line.trim()) continue;
85
+ const m = topKey.exec(line);
86
+ if (m) {
87
+ flush();
88
+ const k = m[1];
89
+ if (k === "name" || k === "description") {
90
+ key = k;
91
+ inline = line.slice(k.length + 1).trim();
92
+ const hash = inline.search(/(?:^|\s)#/);
93
+ if (hash !== -1 && !/^["']/.test(inline)) {
94
+ inline = inline.slice(0, hash).trim();
95
+ }
96
+ more = [];
97
+ }
98
+ } else if (/^\s/.test(line)) {
99
+ if (key) more.push(line.trim());
100
+ } else {
101
+ flush();
102
+ }
103
+ }
104
+ flush();
105
+ return fm;
106
+ };
107
+ var sanitize = (s) => {
108
+ const clean = s?.replace(/\p{Cc}/gu, " ").replace(/\s+/g, " ").trim();
109
+ return clean ? clean.slice(0, 1024) : void 0;
110
+ };
111
+ var lc = (s) => s.toLowerCase();
112
+ var isDir = (path) => !!lstat(path)?.isDirectory();
113
+ var isFile = (path) => !!lstat(path)?.isFile();
114
+ var isSkillMd = (name) => name.toLowerCase() === "skill.md";
115
+ var shipDirs = ["skills", "dist/skills", ".agents/skills"];
116
+ var subdir = (dir, sub) => {
117
+ let path = dir;
118
+ for (const seg of sub.split("/")) {
119
+ path = resolve(path, seg);
120
+ if (!isDir(path)) return void 0;
121
+ }
122
+ return path;
123
+ };
124
+ var scan = (dir, pkgName) => {
125
+ const found = [];
126
+ const has = (skill) => found.some((f) => lc(f.skill) === lc(skill));
127
+ const root = resolve(dir, "SKILL.md");
128
+ if (isFile(root)) {
129
+ const { name, description } = readFrontmatter(root);
130
+ const skill = name && name.length <= 64 && specName.test(name) ? name : pkgName.slice(pkgName.lastIndexOf("/") + 1);
131
+ if (skillDirName.test(skill) && !isSkillMd(skill)) {
132
+ found.push({ skill, path: dir, name, description });
133
+ }
134
+ }
135
+ for (const sub of shipDirs) {
136
+ const skillsDir = subdir(dir, sub);
137
+ if (!skillsDir) continue;
138
+ for (const d of readdirSync(skillsDir).sort()) {
139
+ if (!skillDirName.test(d) || isSkillMd(d) || has(d)) continue;
140
+ const path = resolve(skillsDir, d);
141
+ const file = resolve(path, "SKILL.md");
142
+ if (!isDir(path) || !isFile(file)) continue;
143
+ const { name, description } = readFrontmatter(file);
144
+ found.push({ skill: d, path, name, description });
145
+ }
146
+ }
147
+ return found;
148
+ };
149
+ var rank = (node) => {
150
+ if (node.importer) return 0;
151
+ let r = 2;
152
+ for (const { from } of node.edgesIn) {
153
+ if (from.mainImporter) return 0;
154
+ if (from.importer) r = 1;
155
+ }
156
+ return r;
157
+ };
158
+ var ver = (node) => node.version ? parse(node.version) : void 0;
159
+ var byVersion = (a, b) => {
160
+ const va = ver(a);
161
+ const vb = ver(b);
162
+ return va && vb ? vb.compare(va) : 0;
163
+ };
164
+ var compare = (a, b) => rank(a) - rank(b) || byVersion(a, b) || a.id.localeCompare(b.id, "en");
165
+ var aliasOf = (node) => {
166
+ const edges = [...node.edgesIn];
167
+ const n = (edges.find((e) => e.from.mainImporter) ?? edges.find((e) => e.from.importer))?.name;
168
+ return n === node.name ? void 0 : n;
169
+ };
170
+ var scannable = (node) => node.importer ? !node.mainImporter : node.inVltStore() && splitDepID(node.id)[0] !== "file";
171
+ var shipsSkills = (node) => scannable(node) && scan(realOr(resolve(node.projectRoot, node.location)), node.name).length > 0;
172
+ var discoverSkills = (nodes, scurry, mounts = []) => {
173
+ const key = (name, path) => `${lc(name)}\0${norm(path)}`;
174
+ const linkedIn = /* @__PURE__ */ new Map();
175
+ for (const m of mounts) {
176
+ const k = key(m.name, realOr(m.target));
177
+ const dirs = linkedIn.get(k) ?? [];
178
+ if (!dirs.includes(m.dir.dir)) dirs.push(m.dir.dir);
179
+ linkedIn.set(k, dirs);
180
+ }
181
+ const scanned = /* @__PURE__ */ new Map();
182
+ const byPkg = /* @__PURE__ */ new Map();
183
+ for (const node of nodes) {
184
+ if (!scannable(node)) continue;
185
+ const found = scan(
186
+ realOr(node.resolvedLocation(scurry)),
187
+ node.name
188
+ );
189
+ scanned.set(
190
+ node.id,
191
+ found.map(({ skill, path }) => ({ skill, path }))
192
+ );
193
+ const key2 = packageKey(node.id);
194
+ const list = byPkg.get(key2) ?? [];
195
+ list.push({ node, found });
196
+ byPkg.set(key2, list);
197
+ }
198
+ const rows = [];
199
+ for (const list of byPkg.values()) {
200
+ const { node, found } = list.reduce(
201
+ (a, b) => compare(a.node, b.node) <= 0 ? a : b
202
+ );
203
+ for (const { skill, path, name, description } of found) {
204
+ const fm = sanitize(name);
205
+ rows.push([
206
+ {
207
+ name: node.name,
208
+ alias: aliasOf(node),
209
+ version: node.version,
210
+ id: node.id,
211
+ skill,
212
+ ...fm && lc(fm) !== lc(skill) && { frontmatterName: fm },
213
+ description: sanitize(description),
214
+ path,
215
+ linked: linkedIn.get(key(skill, path)) ?? []
216
+ },
217
+ rank(node)
218
+ ]);
219
+ }
220
+ }
221
+ const skills = rows.sort(
222
+ ([a, ra], [b, rb]) => lc(a.skill).localeCompare(lc(b.skill), "en") || ra - rb || a.id.localeCompare(b.id, "en")
223
+ ).map(([s]) => s);
224
+ return { skills, scanned };
225
+ };
226
+
227
+ // ../../src/graph/src/skills/mask.ts
228
+ var escape = (s) => s.replace(/[.*+?^${}()|[\]\\]/g, "\\$&");
229
+ var globRegExp = (pattern) => new RegExp(`^${pattern.split("*").map(escape).join(".*")}$`, "i");
230
+ var matches = (re, s) => re.test(s.skill) || !!s.frontmatterName && re.test(s.frontmatterName);
231
+ var maskSkills = (skills, parts) => {
232
+ const compiled = parts.map((p) => ({
233
+ keys: new Set([...p.ids].map(packageKey)),
234
+ patterns: p.patterns?.map((pattern) => ({
235
+ pattern,
236
+ re: globRegExp(pattern)
237
+ }))
238
+ }));
239
+ const picked = skills.filter(
240
+ (s) => compiled.some(
241
+ (p) => p.keys.has(packageKey(s.id)) && (!p.patterns || p.patterns.some(({ re }) => matches(re, s)))
242
+ )
243
+ );
244
+ const unmatched = [];
245
+ for (const p of compiled) {
246
+ if (!p.patterns) continue;
247
+ const own = skills.filter((s) => p.keys.has(packageKey(s.id)));
248
+ for (const { pattern, re } of p.patterns) {
249
+ if (own.some((s) => matches(re, s))) continue;
250
+ unmatched.push({
251
+ pattern,
252
+ ...p.keys.size > 0 && {
253
+ skills: [...new Set(own.map((s) => s.skill))].sort(
254
+ (a, b) => a.localeCompare(b, "en")
255
+ )
256
+ }
257
+ });
258
+ }
259
+ }
260
+ return { skills: picked, unmatched };
261
+ };
262
+
263
+ // ../../src/graph/src/skills/index.ts
264
+ var lc2 = (s) => s.toLowerCase();
265
+ var selectNodes = async (o) => {
266
+ const graph = o.graph ?? load({ ...o, loadManifests: true });
267
+ const { ids, parts, unscanned } = await filterNodesByQueryParts(
268
+ graph,
269
+ o.target ?? "*"
270
+ );
271
+ const nodes = [...graph.nodes.values()].filter((n) => ids.has(n.id));
272
+ return { graph, nodes, parts, unscanned };
273
+ };
274
+ var dirsOf = (o, create = false) => skillsDirs({
275
+ projectRoot: o.projectRoot,
276
+ configured: o.skillsDirs,
277
+ env: o.env,
278
+ create
279
+ });
280
+ var workspaceDirs = (graph, scurry) => [...graph.importers].filter((n) => !n.mainImporter).map((n) => ({
281
+ id: n.id,
282
+ path: realOr(n.resolvedLocation(scurry))
283
+ }));
284
+ var allWorkspaces = (m) => m ? [
285
+ ...Monorepo.load(m.projectRoot, {
286
+ config: m.config,
287
+ scurry: m.scurry,
288
+ packageJson: m.packageJson
289
+ }).values()
290
+ ].map((ws) => ({ id: ws.id, path: realOr(ws.fullpath) })) : [];
291
+ var liveOwners = (mounts) => mounts.flatMap(
292
+ (m) => m.owner && existsSync(m.target) ? [m.owner] : []
293
+ );
294
+ var unshareSkills = async (graph, ids, scurry) => {
295
+ for (const id of new Set(ids)) {
296
+ const node = graph.nodes.get(id);
297
+ if (node?.inVltStore())
298
+ await unshare(node.resolvedLocation(scurry));
299
+ }
300
+ };
301
+ var label = (s) => {
302
+ const pkg = s.version ? `${s.name}@${s.version}` : s.name;
303
+ return s.alias ? `${s.alias} (${pkg})` : pkg;
304
+ };
305
+ var pick = (found, parts, unscanned) => {
306
+ const { skills: masked, unmatched } = maskSkills(found, parts);
307
+ const ok = (s) => !unscanned?.ids.has(s.id);
308
+ const picked = masked.filter(ok);
309
+ const names = new Set(picked.map((s) => lc2(s.skill)));
310
+ const dropped = masked.filter(
311
+ (s) => !ok(s) && !names.has(lc2(s.skill))
312
+ );
313
+ return { skills: found.filter(ok), picked, unmatched, dropped };
314
+ };
315
+ var report = (dropped, unscanned) => unscanned && dropped.length ? {
316
+ unscanned: dropped.map((s) => `${s.skill} (${label(s)})`),
317
+ unscannedReason: unscanned.reason
318
+ } : {};
319
+ var listSkills = async (o) => {
320
+ const { graph, nodes, parts, unscanned } = await selectNodes(o);
321
+ const { targets, scan: scan2, skipped } = dirsOf(o);
322
+ const { skills } = discoverSkills(
323
+ nodes,
324
+ o.scurry,
325
+ readMounts(scan2, { workspaces: workspaceDirs(graph, o.scurry) })
326
+ );
327
+ const { picked, dropped } = pick(skills, parts, unscanned);
328
+ return {
329
+ project: graph.mainImporter.name,
330
+ graph,
331
+ skills: picked,
332
+ dirs: targets.map((d) => d.dir),
333
+ ...skipped.length ? { skipped } : null,
334
+ ...report(dropped, unscanned)
335
+ };
336
+ };
337
+ var linkSkills = async (o) => {
338
+ const { graph, nodes, parts, unscanned } = await selectNodes(o);
339
+ const { skills: found, scanned } = discoverSkills(nodes, o.scurry);
340
+ const { skills, picked, unmatched, dropped } = pick(
341
+ found,
342
+ parts,
343
+ unscanned
344
+ );
345
+ const inMask = new Set(picked);
346
+ const { targets, scan: scan2, skipped } = dirsOf(o, picked.length > 0);
347
+ const res = {
348
+ linked: [],
349
+ unchanged: [],
350
+ removed: [],
351
+ conflicts: [],
352
+ dirs: targets.map((d) => d.dir)
353
+ };
354
+ const workspaces = workspaceDirs(graph, o.scurry);
355
+ const mounts = readMounts(scan2, { workspaces });
356
+ const byName = new Map(
357
+ mounts.map((m) => [`${m.dir.dir}\0${lc2(m.name)}`, m])
358
+ );
359
+ const stale = (m) => !m.owner || !graph.nodes.has(m.owner) || !existsSync(m.target) || scanned.get(m.owner)?.some(
360
+ (f) => lc2(f.skill) === lc2(m.name) && samePath(f.path, m.target)
361
+ ) === false;
362
+ const groups = /* @__PURE__ */ new Map();
363
+ for (const s of skills) {
364
+ const k = lc2(s.skill);
365
+ groups.set(k, [...groups.get(k) ?? [], s]);
366
+ }
367
+ const at = (dir, k, group) => {
368
+ const m = byName.get(`${dir.dir}\0${k}`);
369
+ const key = m?.owner && packageKey(m.owner);
370
+ return { m, own: group.find((s) => packageKey(s.id) === key) };
371
+ };
372
+ const cands = (group) => group.filter((s) => inMask.has(s));
373
+ const first = new Map(
374
+ [...groups].map(([k, group]) => {
375
+ const c = cands(group);
376
+ return [
377
+ k,
378
+ targets.map((d) => at(d, k, c).own).find((s) => !!s) ?? c[0]
379
+ ];
380
+ })
381
+ );
382
+ const isTarget = new Set(targets);
383
+ const picks = [];
384
+ for (const dir of scan2) {
385
+ for (const [k, group] of groups) {
386
+ const { m, own } = at(dir, k, group);
387
+ if (isTarget.has(dir)) {
388
+ const winner = o.apply ? first.get(k) : own ?? (m && !stale(m) ? void 0 : first.get(k));
389
+ picks.push({
390
+ dir,
391
+ winner,
392
+ losers: cands(group).filter((s) => s !== winner),
393
+ m
394
+ });
395
+ } else if (own && !o.apply) {
396
+ picks.push({ dir, winner: own, losers: [], m });
397
+ }
398
+ }
399
+ }
400
+ await unshareSkills(
401
+ graph,
402
+ [
403
+ ...picks.flatMap(({ winner }) => winner ? [winner.id] : []),
404
+ ...liveOwners(mounts)
405
+ ],
406
+ o.scurry
407
+ );
408
+ const gone = [];
409
+ const foreign = [];
410
+ const kept = /* @__PURE__ */ new Set();
411
+ const made = /* @__PURE__ */ new Set();
412
+ const where = /* @__PURE__ */ new Map();
413
+ let every;
414
+ for (const { dir, winner, losers, m } of picks) {
415
+ if (winner) {
416
+ if (m && m.name !== winner.skill) {
417
+ unmountSkill(m);
418
+ gone.push(m);
419
+ }
420
+ const mount = `${dir.dir}/${winner.skill}`;
421
+ const r = mountSkill(winner, dir, m?.name === winner.skill);
422
+ if (r === "linked") made.add(mount);
423
+ if (r === "conflict") {
424
+ res.conflicts.push(mount);
425
+ every ??= allWorkspaces(o.monorepo);
426
+ if (!readMounts([dir], { workspaces: every }).some(
427
+ (l) => l.name === winner.skill
428
+ )) {
429
+ foreign.push({ dir, name: winner.skill });
430
+ }
431
+ } else {
432
+ const k = `${winner.id}\0${winner.skill}`;
433
+ const linked = where.get(k) ?? [];
434
+ linked.push(dir.dir);
435
+ where.set(k, linked);
436
+ res[r].push({ ...winner, linked, dir: dir.dir, mount });
437
+ kept.add(mount);
438
+ }
439
+ }
440
+ for (const s of losers)
441
+ res.conflicts.push(`${dir.dir}/${s.skill} (${label(s)})`);
442
+ }
443
+ const after = readMounts(scan2, { workspaces, made });
444
+ const present = [];
445
+ for (const m of after) {
446
+ if (o.apply ? kept.has(m.mount) : !stale(m)) {
447
+ present.push(m);
448
+ continue;
449
+ }
450
+ unmountSkill(m);
451
+ gone.push(m);
452
+ res.removed.push(m.mount);
453
+ }
454
+ const gitignore = [];
455
+ for (const dir of scan2) {
456
+ const add = present.filter((m) => m.dir === dir).map((m) => m.name);
457
+ const remove = [...gone, ...foreign].filter((m) => m.dir === dir && !add.includes(m.name)).map((m) => m.name);
458
+ if ((add.length || remove.length) && editGitignore(dir.real, { add, remove }) === "refused") {
459
+ gitignore.push(`${dir.dir}/.gitignore`);
460
+ }
461
+ }
462
+ if (skipped.length) res.skipped = skipped;
463
+ if (gitignore.length) res.gitignore = gitignore;
464
+ if (unmatched.length) res.unmatched = unmatched;
465
+ const left = dropped.filter(
466
+ (s) => !targets.every(
467
+ (d) => present.some(
468
+ (m) => m.dir === d && m.owner === s.id && lc2(m.name) === lc2(s.skill)
469
+ )
470
+ )
471
+ );
472
+ return Object.assign(res, report(left, unscanned));
473
+ };
474
+ export {
475
+ discoverSkills,
476
+ linkSkills,
477
+ listSkills,
478
+ readFrontmatter,
479
+ shipsSkills
480
+ };