skill-flow 1.0.3 → 1.0.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.
Files changed (84) hide show
  1. package/README.md +40 -3
  2. package/README.zh.md +40 -3
  3. package/dist/adapters/channel-adapters.js +11 -3
  4. package/dist/adapters/channel-adapters.js.map +1 -1
  5. package/dist/cli.js +69 -37
  6. package/dist/cli.js.map +1 -1
  7. package/dist/domain/types.d.ts +54 -1
  8. package/dist/services/config-coordinator.d.ts +38 -0
  9. package/dist/services/config-coordinator.js +81 -0
  10. package/dist/services/config-coordinator.js.map +1 -0
  11. package/dist/services/doctor-service.d.ts +2 -0
  12. package/dist/services/doctor-service.js +62 -0
  13. package/dist/services/doctor-service.js.map +1 -1
  14. package/dist/services/inventory-service.d.ts +3 -1
  15. package/dist/services/inventory-service.js +12 -5
  16. package/dist/services/inventory-service.js.map +1 -1
  17. package/dist/services/skill-flow.d.ts +50 -26
  18. package/dist/services/skill-flow.js +502 -89
  19. package/dist/services/skill-flow.js.map +1 -1
  20. package/dist/services/source-service.d.ts +20 -10
  21. package/dist/services/source-service.js +359 -75
  22. package/dist/services/source-service.js.map +1 -1
  23. package/dist/services/workflow-service.d.ts +2 -2
  24. package/dist/services/workflow-service.js +17 -4
  25. package/dist/services/workflow-service.js.map +1 -1
  26. package/dist/services/workspace-bootstrap-service.d.ts +25 -0
  27. package/dist/services/workspace-bootstrap-service.js +140 -0
  28. package/dist/services/workspace-bootstrap-service.js.map +1 -0
  29. package/dist/state/store.d.ts +16 -0
  30. package/dist/state/store.js +93 -18
  31. package/dist/state/store.js.map +1 -1
  32. package/dist/tests/clawhub.test.d.ts +1 -0
  33. package/dist/tests/clawhub.test.js +63 -0
  34. package/dist/tests/clawhub.test.js.map +1 -0
  35. package/dist/tests/cli-utils.test.d.ts +1 -0
  36. package/dist/tests/cli-utils.test.js +15 -0
  37. package/dist/tests/cli-utils.test.js.map +1 -0
  38. package/dist/tests/config-coordinator.test.d.ts +1 -0
  39. package/dist/tests/config-coordinator.test.js +172 -0
  40. package/dist/tests/config-coordinator.test.js.map +1 -0
  41. package/dist/tests/config-integration.test.d.ts +1 -0
  42. package/dist/tests/config-integration.test.js +238 -0
  43. package/dist/tests/config-integration.test.js.map +1 -0
  44. package/dist/tests/config-ui-utils.test.d.ts +1 -0
  45. package/dist/tests/config-ui-utils.test.js +389 -0
  46. package/dist/tests/config-ui-utils.test.js.map +1 -0
  47. package/dist/tests/find-and-naming-utils.test.d.ts +1 -0
  48. package/dist/tests/find-and-naming-utils.test.js +127 -0
  49. package/dist/tests/find-and-naming-utils.test.js.map +1 -0
  50. package/dist/tests/skill-flow.test.js +334 -881
  51. package/dist/tests/skill-flow.test.js.map +1 -1
  52. package/dist/tests/source-lifecycle.test.d.ts +1 -0
  53. package/dist/tests/source-lifecycle.test.js +605 -0
  54. package/dist/tests/source-lifecycle.test.js.map +1 -0
  55. package/dist/tests/target-definitions.test.d.ts +1 -0
  56. package/dist/tests/target-definitions.test.js +51 -0
  57. package/dist/tests/target-definitions.test.js.map +1 -0
  58. package/dist/tests/test-helpers.d.ts +18 -0
  59. package/dist/tests/test-helpers.js +123 -0
  60. package/dist/tests/test-helpers.js.map +1 -0
  61. package/dist/tui/config-app.d.ts +147 -24
  62. package/dist/tui/config-app.js +1081 -335
  63. package/dist/tui/config-app.js.map +1 -1
  64. package/dist/tui/find-app.d.ts +1 -1
  65. package/dist/tui/find-app.js +36 -4
  66. package/dist/tui/find-app.js.map +1 -1
  67. package/dist/utils/clawhub.d.ts +3 -0
  68. package/dist/utils/clawhub.js +32 -3
  69. package/dist/utils/clawhub.js.map +1 -1
  70. package/dist/utils/cli.d.ts +1 -0
  71. package/dist/utils/cli.js +15 -0
  72. package/dist/utils/cli.js.map +1 -0
  73. package/dist/utils/constants.d.ts +4 -0
  74. package/dist/utils/constants.js +31 -0
  75. package/dist/utils/constants.js.map +1 -1
  76. package/dist/utils/fs.d.ts +5 -0
  77. package/dist/utils/fs.js +52 -1
  78. package/dist/utils/fs.js.map +1 -1
  79. package/dist/utils/naming.d.ts +1 -0
  80. package/dist/utils/naming.js +7 -1
  81. package/dist/utils/naming.js.map +1 -1
  82. package/dist/utils/source-id.js +4 -0
  83. package/dist/utils/source-id.js.map +1 -1
  84. package/package.json +1 -1
@@ -0,0 +1,389 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { buildActionRows, buildDetailMetadataRows, buildDraftsFromSummaries, buildConfigGroupSkillRows, buildConfigGroups, buildProjectionWarningMap, buildScrollableRows, buildTopBar, captureFocusSnapshot, draftsEqual, getInitialDetailFocus, getNextSelectionIndexAfterDelete, getPaneViewportCount, getPaneWidths, getRequestedAction, getStatusDisplay, moveDetailFocus, prioritizeAlerts, reconcileFocusAfterReload, } from "../tui/config-app.js";
3
+ import { getParentSelectionState, toggleChild, toggleParent, } from "../tui/selection-state.js";
4
+ describe("config ui utils", () => {
5
+ test("selection state machine handles parent child partial transitions", () => {
6
+ let state = {
7
+ allLeafIds: ["a", "b"],
8
+ selectedLeafIds: [],
9
+ };
10
+ expect(getParentSelectionState(state)).toBe("empty");
11
+ state = toggleChild(state, "a");
12
+ expect(getParentSelectionState(state)).toBe("partial");
13
+ state = toggleParent(state);
14
+ expect(getParentSelectionState(state)).toBe("full");
15
+ state = toggleChild(state, "b");
16
+ expect(getParentSelectionState(state)).toBe("partial");
17
+ });
18
+ test("top bar and status helpers follow the v1.1.1 contract", () => {
19
+ expect(draftsEqual({
20
+ enabledTargets: ["codex", "claude-code"],
21
+ selectedLeafIds: ["b", "a"],
22
+ }, {
23
+ enabledTargets: ["claude-code", "codex"],
24
+ selectedLeafIds: ["a", "b"],
25
+ })).toBe(true);
26
+ expect(getPaneViewportCount(16, 1)).toBe(10);
27
+ expect(getPaneWidths(100).reduce((sum, width) => sum + width, 0)).toBeLessThanOrEqual(99);
28
+ expect(buildTopBar({
29
+ width: 120,
30
+ isDirty: true,
31
+ changeCount: 3,
32
+ showDelete: true,
33
+ statusLabel: "Saved",
34
+ })).toContain("Changes: 3");
35
+ expect(buildTopBar({
36
+ width: 90,
37
+ isDirty: false,
38
+ changeCount: 3,
39
+ showDelete: false,
40
+ statusLabel: "Saved",
41
+ })).not.toContain("Changes:");
42
+ expect(buildTopBar({
43
+ width: 120,
44
+ isDirty: false,
45
+ changeCount: 0,
46
+ showDelete: false,
47
+ statusLabel: "Clean",
48
+ })).not.toContain("[d] Delete");
49
+ expect(getStatusDisplay({
50
+ deleteState: {
51
+ phase: "deleting",
52
+ sourceId: "alpha",
53
+ message: undefined,
54
+ },
55
+ isSelectedDelete: true,
56
+ saveState: { phase: "saving", message: undefined },
57
+ updateState: { phase: "failed", message: "boom" },
58
+ }).label).toBe("Deleting");
59
+ expect(getStatusDisplay({
60
+ deleteState: {
61
+ phase: "idle",
62
+ sourceId: undefined,
63
+ message: undefined,
64
+ },
65
+ isSelectedDelete: false,
66
+ saveState: { phase: "failed", message: "boom" },
67
+ updateState: { phase: "updated", message: undefined },
68
+ }).label).toBe("Failed");
69
+ });
70
+ test("alerts are prioritized error before blocked before warning", () => {
71
+ const alerts = prioritizeAlerts([
72
+ { level: "warning", message: "rename warning" },
73
+ { level: "blocked", message: "target path blocked" },
74
+ { level: "error", message: "update failed" },
75
+ { level: "warning", message: "rename warning" },
76
+ ]);
77
+ expect(alerts).toEqual([
78
+ { level: "error", message: "update failed" },
79
+ { level: "blocked", message: "target path blocked" },
80
+ ]);
81
+ });
82
+ test("detail focus enters agents first and skips empty sections", () => {
83
+ expect(getInitialDetailFocus({ hasAgents: true, hasSkills: true })).toBe("detail.agents");
84
+ expect(getInitialDetailFocus({ hasAgents: false, hasSkills: true })).toBe("detail.skills");
85
+ expect(getInitialDetailFocus({ hasAgents: false, hasSkills: false })).toBe("detail.actions");
86
+ expect(moveDetailFocus({
87
+ actionCursor: 0,
88
+ actionCount: 2,
89
+ agentCount: 2,
90
+ agentCursor: 1,
91
+ direction: 1,
92
+ focus: "detail.agents",
93
+ skillCount: 3,
94
+ skillCursor: 0,
95
+ })).toMatchObject({
96
+ focus: "detail.skills",
97
+ skillCursor: 0,
98
+ });
99
+ expect(moveDetailFocus({
100
+ actionCursor: 0,
101
+ actionCount: 1,
102
+ agentCount: 0,
103
+ agentCursor: 0,
104
+ direction: -1,
105
+ focus: "detail.actions",
106
+ skillCount: 0,
107
+ skillCursor: 0,
108
+ })).toMatchObject({
109
+ focus: "detail.actions",
110
+ actionCursor: 0,
111
+ });
112
+ });
113
+ test("keyboard action resolution keeps d and action enter equivalent", () => {
114
+ expect(getRequestedAction({
115
+ actionCursor: 0,
116
+ canDelete: true,
117
+ focus: "groups",
118
+ input: "d",
119
+ keyReturn: false,
120
+ })).toBe("delete");
121
+ expect(getRequestedAction({
122
+ actionCursor: 1,
123
+ canDelete: false,
124
+ focus: "detail.actions",
125
+ input: "",
126
+ keyReturn: true,
127
+ })).toBe("update");
128
+ expect(getRequestedAction({
129
+ actionCursor: 0,
130
+ canDelete: true,
131
+ focus: "detail.actions",
132
+ input: "",
133
+ keyReturn: true,
134
+ })).toBe("update");
135
+ });
136
+ test("focus reconciliation preserves section and falls back to the first surviving item", () => {
137
+ const nextSummaries = [
138
+ createSummary({
139
+ sourceId: "alpha",
140
+ leafIds: ["alpha:browse", "alpha:review"],
141
+ }),
142
+ ];
143
+ const snapshot = captureFocusSnapshot({
144
+ actionCursor: 0,
145
+ agentCursor: 1,
146
+ availableTargets: ["claude-code", "codex"],
147
+ focus: "detail.skills",
148
+ groupId: "alpha",
149
+ selectedGroupIndex: 0,
150
+ selectedSummary: createSummary({
151
+ sourceId: "alpha",
152
+ leafIds: ["alpha:browse", "alpha:slides"],
153
+ }),
154
+ skillCursor: 2,
155
+ });
156
+ expect(reconcileFocusAfterReload({
157
+ availableTargets: ["claude-code", "codex"],
158
+ nextGroups: buildConfigGroups(nextSummaries),
159
+ snapshot,
160
+ })).toMatchObject({
161
+ focus: "detail.skills",
162
+ skillCursor: 0,
163
+ selectedGroupIndex: 0,
164
+ });
165
+ });
166
+ test("focus reconciliation falls back to the nearest remaining group after update removal", () => {
167
+ const snapshot = captureFocusSnapshot({
168
+ actionCursor: 1,
169
+ agentCursor: 0,
170
+ availableTargets: ["claude-code"],
171
+ focus: "detail.actions",
172
+ groupId: "beta",
173
+ selectedGroupIndex: 1,
174
+ selectedSummary: createSummary({
175
+ sourceId: "beta",
176
+ leafIds: ["beta:browse"],
177
+ }),
178
+ skillCursor: 0,
179
+ });
180
+ expect(reconcileFocusAfterReload({
181
+ availableTargets: ["claude-code"],
182
+ nextGroups: buildConfigGroups([
183
+ createSummary({
184
+ sourceId: "alpha",
185
+ leafIds: ["alpha:browse"],
186
+ }),
187
+ ]),
188
+ snapshot,
189
+ })).toMatchObject({
190
+ focus: "detail.actions",
191
+ selectedGroupIndex: 0,
192
+ actionCursor: 1,
193
+ });
194
+ });
195
+ test("buildConfigGroups folds clawhub sources into one view group", () => {
196
+ const groups = buildConfigGroups([
197
+ createSummary({ sourceId: "alpha", leafIds: ["alpha:browse"] }),
198
+ createSummary({ sourceId: "beta", kind: "clawhub", leafIds: ["beta:summary"] }),
199
+ createSummary({ sourceId: "gamma", kind: "clawhub", leafIds: ["gamma:review"] }),
200
+ createSummary({ sourceId: "delta", leafIds: ["delta:slides"] }),
201
+ ]);
202
+ expect(groups.map((group) => group.title)).toEqual([
203
+ "alpha",
204
+ "ClawHub Skills",
205
+ "delta",
206
+ ]);
207
+ expect(groups[1]?.kind).toBe("clawhub");
208
+ expect(groups[1]?.summaries.map((summary) => summary.source.id)).toEqual(["beta", "gamma"]);
209
+ expect(buildConfigGroupSkillRows(groups[1]).map((row) => row.summary.source.id)).toEqual([
210
+ "beta",
211
+ "gamma",
212
+ ]);
213
+ });
214
+ test("buildActionRows hides delete for clawhub aggregate detail", () => {
215
+ const rows = buildActionRows({
216
+ actionCursor: 0,
217
+ canRunActions: true,
218
+ deleteState: {
219
+ phase: "idle",
220
+ sourceId: undefined,
221
+ message: undefined,
222
+ },
223
+ focus: "detail.actions",
224
+ isSelectedDelete: false,
225
+ showDeleteAction: false,
226
+ updateState: { phase: "idle", message: undefined },
227
+ });
228
+ expect(rows.map((row) => row.key)).toEqual(["__actions_separator__", "__action_update__"]);
229
+ });
230
+ test("buildDetailMetadataRows hides clean-state status noise", () => {
231
+ const rows = buildDetailMetadataRows({
232
+ alerts: [],
233
+ detailWidth: 80,
234
+ group: buildConfigGroups([createSummary({ sourceId: "alpha", leafIds: ["alpha:browse"] })])[0],
235
+ summary: createSummary({ sourceId: "alpha", leafIds: ["alpha:browse"] }),
236
+ });
237
+ expect(rows.map((row) => row.key)).toEqual(["__title__", "__source__"]);
238
+ });
239
+ test("buildDetailMetadataRows never shows status/save/preview rows", () => {
240
+ const rows = buildDetailMetadataRows({
241
+ alerts: [],
242
+ detailWidth: 80,
243
+ group: buildConfigGroups([createSummary({ sourceId: "alpha", leafIds: ["alpha:browse"] })])[0],
244
+ summary: createSummary({ sourceId: "alpha", leafIds: ["alpha:browse"] }),
245
+ });
246
+ expect(rows.map((row) => row.key)).toEqual(["__title__", "__source__"]);
247
+ });
248
+ test("buildDetailMetadataRows describes clawhub aggregate detail as a group", () => {
249
+ const group = buildConfigGroups([
250
+ createSummary({ sourceId: "beta", kind: "clawhub", leafIds: ["beta:summary"] }),
251
+ createSummary({ sourceId: "gamma", kind: "clawhub", leafIds: ["gamma:review"] }),
252
+ ])[0];
253
+ const rows = buildDetailMetadataRows({
254
+ alerts: [],
255
+ detailWidth: 80,
256
+ group,
257
+ summary: group.summaries[0],
258
+ });
259
+ expect(rows.find((row) => row.key === "__source__")?.text).toContain("2 clawhub sources");
260
+ expect(rows.find((row) => row.key === "__focused_source__")?.text).toContain("beta@clawhub");
261
+ });
262
+ test("buildScrollableRows adds up/down hints when content is clipped", () => {
263
+ const rows = buildScrollableRows(Array.from({ length: 8 }, (_, index) => ({
264
+ key: `row-${index}`,
265
+ text: `row ${index}`,
266
+ active: false,
267
+ color: undefined,
268
+ })), 4, 4, "skills");
269
+ expect(rows.rows[0]?.key).toBe("__scroll_up__:skills");
270
+ expect(rows.rows.at(-1)?.key).toBe("__scroll_down__:skills");
271
+ });
272
+ test("buildScrollableRows can reserve blank hint slots without overflow", () => {
273
+ const rows = buildScrollableRows(Array.from({ length: 2 }, (_, index) => ({
274
+ key: `row-${index}`,
275
+ text: `row ${index}`,
276
+ active: false,
277
+ color: undefined,
278
+ })), 0, 4, "skills", true);
279
+ expect(rows.rows[0]).toMatchObject({ key: "__scroll_up__:skills", text: "" });
280
+ expect(rows.rows.at(-1)).toMatchObject({ key: "__scroll_down__:skills", text: "" });
281
+ });
282
+ test("delete selection falls back to the nearest remaining group", () => {
283
+ expect(getNextSelectionIndexAfterDelete(2, 2)).toBe(1);
284
+ expect(getNextSelectionIndexAfterDelete(0, 0)).toBe(-1);
285
+ });
286
+ test("buildDraftsFromSummaries normalizes enabled targets and leaf ids", () => {
287
+ const drafts = buildDraftsFromSummaries([
288
+ {
289
+ ...createSummary({
290
+ sourceId: "alpha",
291
+ leafIds: ["alpha:browse", "alpha:review"],
292
+ }),
293
+ bindings: {
294
+ targets: {
295
+ codex: {
296
+ enabled: true,
297
+ leafIds: ["alpha:review", "alpha:browse"],
298
+ },
299
+ "claude-code": {
300
+ enabled: true,
301
+ leafIds: ["alpha:browse"],
302
+ },
303
+ },
304
+ },
305
+ },
306
+ ]);
307
+ expect(drafts.alpha).toEqual({
308
+ enabledTargets: ["claude-code", "codex"],
309
+ selectedLeafIds: ["alpha:browse", "alpha:review"],
310
+ });
311
+ });
312
+ test("projection warning helper marks identical cross-group skills as skipped", () => {
313
+ const warnings = buildProjectionWarningMap({
314
+ drafts: {
315
+ alpha: { enabledTargets: ["claude-code"], selectedLeafIds: ["alpha:browse"] },
316
+ beta: { enabledTargets: ["claude-code"], selectedLeafIds: ["beta:browse"] },
317
+ },
318
+ summaries: [
319
+ createSummary({
320
+ sourceId: "alpha",
321
+ leafIds: ["alpha:browse"],
322
+ descriptions: { "alpha:browse": "Browser flow." },
323
+ }),
324
+ createSummary({
325
+ sourceId: "beta",
326
+ leafIds: ["beta:browse"],
327
+ descriptions: { "beta:browse": "Browser flow." },
328
+ }),
329
+ ],
330
+ sourceId: "beta",
331
+ });
332
+ expect(warnings["beta:browse"]?.[0]).toContain("will be skipped");
333
+ });
334
+ test("projection warning helper marks cross-group name collisions as renamed", () => {
335
+ const warnings = buildProjectionWarningMap({
336
+ drafts: {
337
+ alpha: { enabledTargets: ["claude-code"], selectedLeafIds: ["alpha:browse"] },
338
+ beta: { enabledTargets: ["claude-code"], selectedLeafIds: ["beta:browse"] },
339
+ },
340
+ summaries: [
341
+ createSummary({
342
+ sourceId: "alpha",
343
+ leafIds: ["alpha:browse"],
344
+ descriptions: { "alpha:browse": "Browser flow A." },
345
+ }),
346
+ createSummary({
347
+ sourceId: "beta",
348
+ leafIds: ["beta:browse"],
349
+ descriptions: { "beta:browse": "Browser flow B." },
350
+ }),
351
+ ],
352
+ sourceId: "beta",
353
+ });
354
+ expect(warnings["beta:browse"]?.[0]).toContain("will deploy as");
355
+ });
356
+ });
357
+ function createSummary({ sourceId, leafIds, kind = "git", descriptions = {}, }) {
358
+ return {
359
+ source: {
360
+ id: sourceId,
361
+ locator: sourceId,
362
+ kind,
363
+ displayName: sourceId,
364
+ addedAt: "",
365
+ },
366
+ lock: undefined,
367
+ bindings: { targets: {} },
368
+ activeTargetCount: 0,
369
+ health: "ACTIVE",
370
+ leafs: leafIds.map((leafId) => {
371
+ const name = leafId.split(":")[1] ?? leafId;
372
+ return {
373
+ id: leafId,
374
+ sourceId,
375
+ name,
376
+ linkName: name,
377
+ title: name,
378
+ description: descriptions[leafId] ?? `${name} description`,
379
+ relativePath: name,
380
+ absolutePath: `/tmp/${sourceId}/${name}`,
381
+ skillFilePath: `/tmp/${sourceId}/${name}/SKILL.md`,
382
+ contentHash: leafId,
383
+ metadataWarnings: [],
384
+ valid: true,
385
+ };
386
+ }),
387
+ };
388
+ }
389
+ //# sourceMappingURL=config-ui-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"config-ui-utils.test.js","sourceRoot":"","sources":["../../src/tests/config-ui-utils.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,127 @@
1
+ import { describe, expect, test } from "vitest";
2
+ import { buildFindCommand } from "../utils/find-command.js";
3
+ import { buildProjectedSkillName, formatGroupLabel, resolveProjectedSkillNames } from "../utils/naming.js";
4
+ import { deriveSourceId } from "../utils/source-id.js";
5
+ describe("find and naming utils", () => {
6
+ test("normalizes GitHub locators to the same source id across supported formats", () => {
7
+ const locators = [
8
+ "https://github.com/garrytan/gstack",
9
+ "https://github.com/garrytan/gstack.git",
10
+ "git@github.com:garrytan/gstack.git",
11
+ "garrytan/gstack",
12
+ ];
13
+ expect(locators.map((locator) => deriveSourceId(locator))).toEqual([
14
+ "garrytan-gstack",
15
+ "garrytan-gstack",
16
+ "garrytan-gstack",
17
+ "garrytan-gstack",
18
+ ]);
19
+ });
20
+ test("normalizes ClawHub locators to the same source id across version forms", () => {
21
+ expect(deriveSourceId("clawhub:find-skills")).toBe("clawhub-find-skills");
22
+ expect(deriveSourceId("clawhub:find-skills@1.2.3")).toBe("clawhub-find-skills");
23
+ });
24
+ test("builds follow-up commands for search candidates", () => {
25
+ expect(buildFindCommand({
26
+ id: "builtin:1",
27
+ title: "find-skills",
28
+ description: "Find skills",
29
+ source: "builtin-git",
30
+ sourceLabel: "skills(@anthropics)",
31
+ sourceId: "anthropics-skills",
32
+ sourceKind: "git",
33
+ locator: "https://github.com/anthropics/skills.git",
34
+ relativePath: "skills/find-skills",
35
+ installed: false,
36
+ action: {
37
+ type: "add-git",
38
+ locator: "https://github.com/anthropics/skills.git",
39
+ requestedPath: "skills/find-skills",
40
+ },
41
+ })).toBe("skill-flow add https://github.com/anthropics/skills.git --path skills/find-skills");
42
+ expect(buildFindCommand({
43
+ id: "clawhub:1",
44
+ title: "Find Skills",
45
+ description: "Find skills",
46
+ source: "clawhub",
47
+ sourceLabel: "ClawHub",
48
+ sourceId: "clawhub-find-skills",
49
+ sourceKind: "clawhub",
50
+ locator: "clawhub:find-skills",
51
+ installed: false,
52
+ action: {
53
+ type: "add-clawhub",
54
+ slug: "find-skills",
55
+ version: "1.2.3",
56
+ },
57
+ })).toBe("skill-flow add clawhub:find-skills@1.2.3");
58
+ });
59
+ test("formats GitHub groups as groupName(@owner)", () => {
60
+ expect(formatGroupLabel({
61
+ id: "garrytan-gstack",
62
+ locator: "git@github.com:garrytan/gstack.git",
63
+ displayName: "gstack",
64
+ })).toBe("gstack@garrytan");
65
+ });
66
+ test("prefers groupName-skillName for projected collisions", () => {
67
+ const projected = resolveProjectedSkillNames([
68
+ {
69
+ leafId: "a:browse",
70
+ groupId: "garrytan-gstack",
71
+ groupName: "gstack",
72
+ groupAuthor: "garrytan",
73
+ skillName: "browse",
74
+ },
75
+ {
76
+ leafId: "b:browse",
77
+ groupId: "alice-toolkit",
78
+ groupName: "toolkit",
79
+ groupAuthor: "alice",
80
+ skillName: "browse",
81
+ },
82
+ ]);
83
+ expect(projected.get("a:browse")).toBe(buildProjectedSkillName("gstack", "browse", "garrytan"));
84
+ expect(projected.get("b:browse")).toBe(buildProjectedSkillName("toolkit", "browse", "alice"));
85
+ });
86
+ test("falls back to groupId-skillName when projected names still collide", () => {
87
+ const projected = resolveProjectedSkillNames([
88
+ {
89
+ leafId: "a:browse",
90
+ groupId: "alice-gstack",
91
+ groupName: "gstack",
92
+ groupAuthor: "alice",
93
+ skillName: "browse",
94
+ },
95
+ {
96
+ leafId: "b:browse",
97
+ groupId: "garrytan-gstack",
98
+ groupName: "gstack",
99
+ groupAuthor: "garrytan",
100
+ skillName: "browse",
101
+ },
102
+ ]);
103
+ expect(projected.get("a:browse")).toBe("gstack(alice)-browse");
104
+ expect(projected.get("b:browse")).toBe("gstack(garrytan)-browse");
105
+ });
106
+ test("prefers author prefix when repo prefix would repeat the skill prefix", () => {
107
+ const projected = resolveProjectedSkillNames([
108
+ {
109
+ leafId: "a:skill-creator",
110
+ groupId: "anthropic-skill",
111
+ groupName: "skill",
112
+ groupAuthor: "anthropic",
113
+ skillName: "skill-creator",
114
+ },
115
+ {
116
+ leafId: "b:skill-creator",
117
+ groupId: "openai-skill",
118
+ groupName: "skill",
119
+ groupAuthor: "openai",
120
+ skillName: "skill-creator",
121
+ },
122
+ ]);
123
+ expect(projected.get("a:skill-creator")).toBe("anthropic-skill-creator");
124
+ expect(projected.get("b:skill-creator")).toBe("openai-skill-creator");
125
+ });
126
+ });
127
+ //# sourceMappingURL=find-and-naming-utils.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"find-and-naming-utils.test.js","sourceRoot":"","sources":["../../src/tests/find-and-naming-utils.test.ts"],"names":[],"mappings":"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"}