@pennyfarthing/shared 7.0.2

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 (46) hide show
  1. package/dist/generate-skill-docs.d.ts +35 -0
  2. package/dist/generate-skill-docs.d.ts.map +1 -0
  3. package/dist/generate-skill-docs.js +442 -0
  4. package/dist/generate-skill-docs.js.map +1 -0
  5. package/dist/generate-skill-docs.test.d.ts +13 -0
  6. package/dist/generate-skill-docs.test.d.ts.map +1 -0
  7. package/dist/generate-skill-docs.test.js +519 -0
  8. package/dist/generate-skill-docs.test.js.map +1 -0
  9. package/dist/index.d.ts +10 -0
  10. package/dist/index.d.ts.map +1 -0
  11. package/dist/index.js +10 -0
  12. package/dist/index.js.map +1 -0
  13. package/dist/portrait-resolver.d.ts +32 -0
  14. package/dist/portrait-resolver.d.ts.map +1 -0
  15. package/dist/portrait-resolver.js +147 -0
  16. package/dist/portrait-resolver.js.map +1 -0
  17. package/dist/portrait-resolver.test.d.ts +2 -0
  18. package/dist/portrait-resolver.test.d.ts.map +1 -0
  19. package/dist/portrait-resolver.test.js +156 -0
  20. package/dist/portrait-resolver.test.js.map +1 -0
  21. package/dist/skill-search.d.ts +36 -0
  22. package/dist/skill-search.d.ts.map +1 -0
  23. package/dist/skill-search.js +300 -0
  24. package/dist/skill-search.js.map +1 -0
  25. package/dist/skill-search.sh +41 -0
  26. package/dist/skill-search.test.d.ts +16 -0
  27. package/dist/skill-search.test.d.ts.map +1 -0
  28. package/dist/skill-search.test.js +193 -0
  29. package/dist/skill-search.test.js.map +1 -0
  30. package/dist/skill-suggest.d.ts +76 -0
  31. package/dist/skill-suggest.d.ts.map +1 -0
  32. package/dist/skill-suggest.js +256 -0
  33. package/dist/skill-suggest.js.map +1 -0
  34. package/dist/skill-suggest.test.d.ts +12 -0
  35. package/dist/skill-suggest.test.d.ts.map +1 -0
  36. package/dist/skill-suggest.test.js +257 -0
  37. package/dist/skill-suggest.test.js.map +1 -0
  38. package/dist/theme-loader.d.ts +35 -0
  39. package/dist/theme-loader.d.ts.map +1 -0
  40. package/dist/theme-loader.js +170 -0
  41. package/dist/theme-loader.js.map +1 -0
  42. package/dist/theme-loader.test.d.ts +2 -0
  43. package/dist/theme-loader.test.d.ts.map +1 -0
  44. package/dist/theme-loader.test.js +72 -0
  45. package/dist/theme-loader.test.js.map +1 -0
  46. package/package.json +38 -0
@@ -0,0 +1,519 @@
1
+ /**
2
+ * Tests for Story 9-4: Skill Documentation Generator
3
+ *
4
+ * These tests verify:
5
+ * - AC1: docs/SKILLS.md auto-generated from skill-registry.yaml
6
+ * - AC2: Generated docs include all skill metadata
7
+ * - AC3: Skills organized by category with table of contents
8
+ * - AC4: Build process triggers doc generation
9
+ *
10
+ * Run with: npm test -- packages/shared/src/generate-skill-docs.test.ts
11
+ */
12
+ import { describe, it } from 'node:test';
13
+ import assert from 'node:assert';
14
+ import { execSync } from 'child_process';
15
+ import { existsSync, readFileSync, mkdirSync, writeFileSync, rmSync, statSync } from 'fs';
16
+ import { join, dirname } from 'path';
17
+ import { tmpdir } from 'os';
18
+ import { fileURLToPath } from 'url';
19
+ // Import the generator function - this doesn't exist yet, tests should fail (RED)
20
+ import { generateSkillDocs, } from './generate-skill-docs.js';
21
+ // Paths
22
+ const __dirname = dirname(fileURLToPath(import.meta.url));
23
+ const PROJECT_ROOT = join(__dirname, '../../..');
24
+ const REGISTRY_PATH = join(PROJECT_ROOT, 'pennyfarthing-dist/skills/skill-registry.yaml');
25
+ const OUTPUT_PATH = join(PROJECT_ROOT, 'docs/SKILLS.md');
26
+ const GENERATOR_SCRIPT = join(PROJECT_ROOT, 'scripts/utils/generate-skill-docs.sh');
27
+ // Sample minimal registry for isolated tests
28
+ const MINIMAL_REGISTRY = `
29
+ version: "1.0.0"
30
+ skills:
31
+ test-skill:
32
+ name: test-skill
33
+ description: A test skill for verification
34
+ category: development
35
+ tags: [test, example]
36
+ version: "1.0.0"
37
+ prerequisites: []
38
+ examples:
39
+ - context: Testing the generator
40
+ invocation: /test-skill
41
+ anti_patterns:
42
+ - Don't use in production
43
+ related_skills: []
44
+ keywords: [test, sample]
45
+ `;
46
+ describe('Story 9-4: Skill Documentation Generator', () => {
47
+ describe('AC1: Auto-generate docs/SKILLS.md from skill-registry.yaml', () => {
48
+ it('should read skill-registry.yaml and generate markdown', async () => {
49
+ // AC1: docs/SKILLS.md auto-generated from skill-registry.yaml
50
+ const result = await generateSkillDocs({
51
+ registryPath: REGISTRY_PATH,
52
+ });
53
+ assert.ok(result.success, 'Generation should succeed');
54
+ assert.ok(result.content, 'Should produce content');
55
+ assert.ok(result.content.length > 0, 'Content should not be empty');
56
+ });
57
+ it('should generate valid markdown output', async () => {
58
+ // AC1: Output should be valid markdown
59
+ const result = await generateSkillDocs({
60
+ registryPath: REGISTRY_PATH,
61
+ });
62
+ assert.ok(result.content, 'Should produce content');
63
+ // Basic markdown structure checks
64
+ assert.ok(result.content.startsWith('#'), 'Should start with a heading');
65
+ assert.ok(result.content.includes('##'), 'Should have section headings');
66
+ });
67
+ it('should include all 19 skills from registry', async () => {
68
+ // AC1: All skills from registry should appear in output
69
+ const result = await generateSkillDocs({
70
+ registryPath: REGISTRY_PATH,
71
+ });
72
+ assert.ok(result.skillCount === 19, `Should include all 19 skills, got ${result.skillCount}`);
73
+ // Check for a sample of known skills
74
+ const expectedSkills = ['testing', 'jira', 'code-review', 'changelog', 'theme'];
75
+ for (const skill of expectedSkills) {
76
+ assert.ok(result.content.includes(skill), `Output should include ${skill} skill`);
77
+ }
78
+ });
79
+ it('should be idempotent - running twice produces same output', async () => {
80
+ // AC1: Generator should be deterministic
81
+ const result1 = await generateSkillDocs({
82
+ registryPath: REGISTRY_PATH,
83
+ });
84
+ const result2 = await generateSkillDocs({
85
+ registryPath: REGISTRY_PATH,
86
+ });
87
+ assert.strictEqual(result1.content, result2.content, 'Running twice should produce identical output');
88
+ });
89
+ it('should handle custom output path', async () => {
90
+ // AC1: Support writing to custom location
91
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
92
+ mkdirSync(tempDir, { recursive: true });
93
+ const customOutput = join(tempDir, 'SKILLS.md');
94
+ try {
95
+ const result = await generateSkillDocs({
96
+ registryPath: REGISTRY_PATH,
97
+ outputPath: customOutput,
98
+ writeFile: true,
99
+ });
100
+ assert.ok(result.success, 'Generation should succeed');
101
+ assert.ok(existsSync(customOutput), 'Output file should be created');
102
+ const fileContent = readFileSync(customOutput, 'utf-8');
103
+ assert.strictEqual(fileContent, result.content, 'File content should match returned content');
104
+ }
105
+ finally {
106
+ rmSync(tempDir, { recursive: true, force: true });
107
+ }
108
+ });
109
+ it('should throw helpful error when registry file is missing', async () => {
110
+ // AC1: Error handling for missing registry
111
+ await assert.rejects(async () => generateSkillDocs({
112
+ registryPath: '/nonexistent/path/registry.yaml',
113
+ }), {
114
+ message: /registry.*not found|cannot find|no such file/i,
115
+ }, 'Should throw error with helpful message for missing registry');
116
+ });
117
+ it('should handle malformed YAML gracefully', async () => {
118
+ // AC1: Error handling for invalid registry
119
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
120
+ mkdirSync(tempDir, { recursive: true });
121
+ const badRegistry = join(tempDir, 'bad-registry.yaml');
122
+ writeFileSync(badRegistry, 'this is not valid: yaml: content: [broken');
123
+ try {
124
+ await assert.rejects(async () => generateSkillDocs({
125
+ registryPath: badRegistry,
126
+ }), {
127
+ message: /invalid|parse|yaml/i,
128
+ }, 'Should throw error for malformed YAML');
129
+ }
130
+ finally {
131
+ rmSync(tempDir, { recursive: true, force: true });
132
+ }
133
+ });
134
+ });
135
+ describe('AC2: Include all skill metadata', () => {
136
+ it('should include skill description in output', async () => {
137
+ // AC2: description field included
138
+ const result = await generateSkillDocs({
139
+ registryPath: REGISTRY_PATH,
140
+ });
141
+ // Check that descriptions are included (not just skill names)
142
+ assert.ok(result.content.includes('TDD') || result.content.includes('test'), 'Should include skill descriptions mentioning TDD or testing');
143
+ });
144
+ it('should include tags for each skill', async () => {
145
+ // AC2: tags field included
146
+ const result = await generateSkillDocs({
147
+ registryPath: REGISTRY_PATH,
148
+ });
149
+ // Tags should appear in some form (could be **Tags:** or similar)
150
+ assert.ok(result.content.toLowerCase().includes('tag') ||
151
+ result.content.includes('tdd') ||
152
+ result.content.includes('quality'), 'Should include tags in output');
153
+ });
154
+ it('should include examples for each skill', async () => {
155
+ // AC2: examples field included
156
+ const result = await generateSkillDocs({
157
+ registryPath: REGISTRY_PATH,
158
+ });
159
+ // Examples section or invocation patterns should appear
160
+ assert.ok(result.content.toLowerCase().includes('example') ||
161
+ result.content.includes('/testing') ||
162
+ result.content.includes('invocation'), 'Should include examples or invocations');
163
+ });
164
+ it('should include anti-patterns for each skill', async () => {
165
+ // AC2: anti_patterns field included
166
+ const result = await generateSkillDocs({
167
+ registryPath: REGISTRY_PATH,
168
+ });
169
+ // Anti-patterns section should appear
170
+ assert.ok(result.content.toLowerCase().includes('anti-pattern') ||
171
+ result.content.toLowerCase().includes('antipattern') ||
172
+ result.content.toLowerCase().includes("don't"), 'Should include anti-patterns section');
173
+ });
174
+ it('should include related skills references', async () => {
175
+ // AC2: related_skills field included
176
+ const result = await generateSkillDocs({
177
+ registryPath: REGISTRY_PATH,
178
+ });
179
+ // Related skills should appear
180
+ assert.ok(result.content.toLowerCase().includes('related') ||
181
+ result.content.includes('See also'), 'Should include related skills references');
182
+ });
183
+ it('should include keywords for searchability', async () => {
184
+ // AC2: keywords field included (for skill discovery)
185
+ const result = await generateSkillDocs({
186
+ registryPath: REGISTRY_PATH,
187
+ });
188
+ // Keywords should appear (might be in a keywords section or as searchable terms)
189
+ assert.ok(result.content.toLowerCase().includes('keyword') ||
190
+ result.content.includes('jest') ||
191
+ result.content.includes('vitest'), 'Should include keywords for searchability');
192
+ });
193
+ it('should validate required fields are present in registry', async () => {
194
+ // AC2: Error if registry missing required fields
195
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
196
+ mkdirSync(tempDir, { recursive: true });
197
+ const incompleteRegistry = join(tempDir, 'incomplete-registry.yaml');
198
+ // Registry with skill missing required description
199
+ writeFileSync(incompleteRegistry, `
200
+ version: "1.0.0"
201
+ skills:
202
+ incomplete-skill:
203
+ name: incomplete-skill
204
+ # missing description
205
+ category: development
206
+ tags: []
207
+ `);
208
+ try {
209
+ await assert.rejects(async () => generateSkillDocs({
210
+ registryPath: incompleteRegistry,
211
+ strict: true,
212
+ }), {
213
+ message: /missing.*description|required.*field/i,
214
+ }, 'Should error when required fields are missing');
215
+ }
216
+ finally {
217
+ rmSync(tempDir, { recursive: true, force: true });
218
+ }
219
+ });
220
+ });
221
+ describe('AC3: Category organization with table of contents', () => {
222
+ it('should organize skills by category', async () => {
223
+ // AC3: Skills organized by category
224
+ const result = await generateSkillDocs({
225
+ registryPath: REGISTRY_PATH,
226
+ });
227
+ // Category headings should appear
228
+ const categories = ['development', 'project-management', 'tools', 'ai-llm', 'documentation', 'theming', 'benchmarking'];
229
+ let foundCategories = 0;
230
+ for (const category of categories) {
231
+ // Check for category as heading (could be ## Development or ## AI/LLM, etc.)
232
+ const normalizedCategory = category.replace(/-/g, ' ').replace(/ai llm/i, 'AI/LLM');
233
+ if (result.content.toLowerCase().includes(`## ${category}`) ||
234
+ result.content.toLowerCase().includes(normalizedCategory.toLowerCase())) {
235
+ foundCategories++;
236
+ }
237
+ }
238
+ assert.ok(foundCategories >= 3, `Should have at least 3 category sections, found ${foundCategories}`);
239
+ });
240
+ it('should include table of contents with links', async () => {
241
+ // AC3: Table of contents with anchor links
242
+ const result = await generateSkillDocs({
243
+ registryPath: REGISTRY_PATH,
244
+ });
245
+ // TOC should have links (markdown format: [Text](#anchor))
246
+ assert.ok(result.content.includes('](#') ||
247
+ result.content.toLowerCase().includes('table of contents') ||
248
+ result.content.toLowerCase().includes('contents'), 'Should include table of contents with anchor links');
249
+ });
250
+ it('should place skills under correct category heading', async () => {
251
+ // AC3: Skills appear under their category
252
+ const result = await generateSkillDocs({
253
+ registryPath: REGISTRY_PATH,
254
+ });
255
+ // testing skill should be under development category
256
+ // Check that testing appears after development heading and before next category
257
+ const content = result.content.toLowerCase();
258
+ const devIndex = content.indexOf('development');
259
+ const testingIndex = content.indexOf('testing');
260
+ assert.ok(devIndex > -1, 'Development category should exist');
261
+ assert.ok(testingIndex > -1, 'Testing skill should exist');
262
+ // Testing should appear in development section (after heading, before significant distance)
263
+ });
264
+ it('should sort categories alphabetically', async () => {
265
+ // AC3: Predictable ordering
266
+ const result = await generateSkillDocs({
267
+ registryPath: REGISTRY_PATH,
268
+ });
269
+ // Find positions of category headings
270
+ const content = result.content.toLowerCase();
271
+ const _aiIndex = content.indexOf('ai') > -1 ? content.indexOf('ai') : Infinity;
272
+ const devIndex = content.indexOf('development');
273
+ const toolsIndex = content.indexOf('tools');
274
+ // AI/LLM should come before Development alphabetically
275
+ // (or however the ordering is defined - at least should be consistent)
276
+ assert.ok(devIndex > -1 && toolsIndex > -1, 'Multiple category sections should exist');
277
+ });
278
+ it('should sort skills alphabetically within category', async () => {
279
+ // AC3: Skills sorted within their category
280
+ const result = await generateSkillDocs({
281
+ registryPath: REGISTRY_PATH,
282
+ });
283
+ // Within development: code-review should come before dev-patterns (alphabetically)
284
+ const content = result.content.toLowerCase();
285
+ const codeReviewIndex = content.indexOf('code-review');
286
+ const devPatternsIndex = content.indexOf('dev-patterns');
287
+ if (codeReviewIndex > -1 && devPatternsIndex > -1) {
288
+ assert.ok(codeReviewIndex < devPatternsIndex, 'Skills should be sorted alphabetically within category');
289
+ }
290
+ });
291
+ it('should generate valid TOC anchors', async () => {
292
+ // AC3: TOC links should match heading anchors
293
+ const result = await generateSkillDocs({
294
+ registryPath: REGISTRY_PATH,
295
+ });
296
+ // Extract TOC links and verify they have corresponding headings
297
+ const tocLinkMatches = result.content.match(/\[([^\]]+)\]\(#([^)]+)\)/g) || [];
298
+ if (tocLinkMatches.length > 0) {
299
+ // At least some TOC links should exist
300
+ assert.ok(tocLinkMatches.length > 0, 'TOC should have anchor links');
301
+ // Verify at least one link has a valid target
302
+ for (const link of tocLinkMatches.slice(0, 3)) {
303
+ const anchorMatch = link.match(/\(#([^)]+)\)/);
304
+ if (anchorMatch) {
305
+ const anchor = anchorMatch[1];
306
+ // The heading for this anchor should exist somewhere
307
+ // (GitHub-style anchors: lowercase, spaces to dashes)
308
+ assert.ok(anchor.length > 0, `Anchor should not be empty: ${link}`);
309
+ }
310
+ }
311
+ }
312
+ });
313
+ });
314
+ describe('AC4: Build process triggers doc generation', () => {
315
+ it('should have generate-skill-docs.sh script', () => {
316
+ // AC4: Script exists for build integration
317
+ assert.ok(existsSync(GENERATOR_SCRIPT), `Generator script should exist at ${GENERATOR_SCRIPT}`);
318
+ });
319
+ it('should script be executable', () => {
320
+ // AC4: Script should have execute permissions
321
+ if (!existsSync(GENERATOR_SCRIPT)) {
322
+ assert.fail('Generator script does not exist yet');
323
+ }
324
+ // Try to get file stats - executable bit
325
+ const stats = statSync(GENERATOR_SCRIPT);
326
+ const isExecutable = (stats.mode & parseInt('111', 8)) !== 0;
327
+ assert.ok(isExecutable, 'Script should have execute permissions');
328
+ });
329
+ it('should script produce output when run directly', () => {
330
+ // AC4: Shell script integration
331
+ if (!existsSync(GENERATOR_SCRIPT)) {
332
+ assert.fail('Generator script does not exist yet');
333
+ }
334
+ try {
335
+ const output = execSync(`bash ${GENERATOR_SCRIPT} --dry-run`, {
336
+ encoding: 'utf-8',
337
+ cwd: PROJECT_ROOT,
338
+ });
339
+ assert.ok(output.length > 0, 'Script should produce output');
340
+ assert.ok(output.includes('#') || output.includes('Generated'), 'Output should be markdown or status message');
341
+ }
342
+ catch (error) {
343
+ assert.fail(`Script execution failed: ${error}`);
344
+ }
345
+ });
346
+ it('should package.json include docs generation script', () => {
347
+ // AC4: Build process integration
348
+ const packageJsonPath = join(PROJECT_ROOT, 'package.json');
349
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
350
+ const hasDocsScript = packageJson.scripts?.docs ||
351
+ packageJson.scripts?.['generate-docs'] ||
352
+ packageJson.scripts?.build?.includes('generate-skill-docs');
353
+ assert.ok(hasDocsScript, 'package.json should have docs generation in scripts');
354
+ });
355
+ it('should build script include docs generation', () => {
356
+ // AC4: Build triggers doc generation
357
+ const packageJsonPath = join(PROJECT_ROOT, 'package.json');
358
+ const packageJson = JSON.parse(readFileSync(packageJsonPath, 'utf-8'));
359
+ const buildScript = packageJson.scripts?.build || '';
360
+ // Either build includes docs, or there's a prebuild/postbuild hook
361
+ const triggersDocGen = buildScript.includes('generate-skill-docs') ||
362
+ buildScript.includes('docs') ||
363
+ packageJson.scripts?.prebuild?.includes('docs') ||
364
+ packageJson.scripts?.postbuild?.includes('docs');
365
+ assert.ok(triggersDocGen, 'Build process should trigger doc generation');
366
+ });
367
+ it('should generate fresh docs match current registry', async () => {
368
+ // AC4: Generated docs should be up-to-date with registry
369
+ if (!existsSync(OUTPUT_PATH)) {
370
+ assert.fail('docs/SKILLS.md does not exist yet');
371
+ }
372
+ const result = await generateSkillDocs({
373
+ registryPath: REGISTRY_PATH,
374
+ });
375
+ const currentDocs = readFileSync(OUTPUT_PATH, 'utf-8');
376
+ // The generated content should match what's in the file
377
+ // (allowing for timestamp differences if there's a "generated at" header)
378
+ const normalize = (s) => s.replace(/Generated at:.*/g, '').replace(/\s+/g, ' ').trim();
379
+ assert.strictEqual(normalize(result.content), normalize(currentDocs), 'Generated docs should match current docs/SKILLS.md (regenerate if stale)');
380
+ });
381
+ });
382
+ describe('Shell Script Integration', () => {
383
+ it('should script accept --help flag', () => {
384
+ // Usability: Show help text
385
+ if (!existsSync(GENERATOR_SCRIPT)) {
386
+ assert.fail('Generator script does not exist yet');
387
+ }
388
+ try {
389
+ const output = execSync(`bash ${GENERATOR_SCRIPT} --help`, {
390
+ encoding: 'utf-8',
391
+ cwd: PROJECT_ROOT,
392
+ });
393
+ assert.ok(output.includes('usage') || output.includes('Usage') || output.includes('help'), 'Should show usage information');
394
+ }
395
+ catch (error) {
396
+ // --help might exit with 0 or non-zero depending on implementation
397
+ assert.fail(`--help should work: ${error}`);
398
+ }
399
+ });
400
+ it('should script accept custom registry path', () => {
401
+ // Flexibility: Allow custom registry
402
+ if (!existsSync(GENERATOR_SCRIPT)) {
403
+ assert.fail('Generator script does not exist yet');
404
+ }
405
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
406
+ mkdirSync(tempDir, { recursive: true });
407
+ const customRegistry = join(tempDir, 'custom-registry.yaml');
408
+ writeFileSync(customRegistry, MINIMAL_REGISTRY);
409
+ try {
410
+ const output = execSync(`bash ${GENERATOR_SCRIPT} --registry ${customRegistry} --dry-run`, {
411
+ encoding: 'utf-8',
412
+ cwd: PROJECT_ROOT,
413
+ });
414
+ assert.ok(output.includes('test-skill'), 'Should use custom registry');
415
+ }
416
+ catch (error) {
417
+ assert.fail(`Custom registry should work: ${error}`);
418
+ }
419
+ finally {
420
+ rmSync(tempDir, { recursive: true, force: true });
421
+ }
422
+ });
423
+ it('should script exit with error code on failure', () => {
424
+ // Error handling: Non-zero exit on failure
425
+ if (!existsSync(GENERATOR_SCRIPT)) {
426
+ assert.fail('Generator script does not exist yet');
427
+ }
428
+ try {
429
+ execSync(`bash ${GENERATOR_SCRIPT} --registry /nonexistent/path.yaml`, {
430
+ encoding: 'utf-8',
431
+ cwd: PROJECT_ROOT,
432
+ });
433
+ assert.fail('Should have thrown for missing registry');
434
+ }
435
+ catch (error) {
436
+ assert.ok(error.status !== 0, 'Should exit with non-zero status on error');
437
+ }
438
+ });
439
+ });
440
+ describe('Error Handling', () => {
441
+ it('should handle empty registry gracefully', async () => {
442
+ // Edge case: Registry with no skills
443
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
444
+ mkdirSync(tempDir, { recursive: true });
445
+ const emptyRegistry = join(tempDir, 'empty-registry.yaml');
446
+ writeFileSync(emptyRegistry, 'version: "1.0.0"\nskills: {}');
447
+ try {
448
+ const result = await generateSkillDocs({
449
+ registryPath: emptyRegistry,
450
+ });
451
+ assert.ok(result.success, 'Should succeed with empty registry');
452
+ assert.strictEqual(result.skillCount, 0, 'Should report 0 skills');
453
+ assert.ok(result.content.includes('#'), 'Should still produce valid markdown structure');
454
+ }
455
+ finally {
456
+ rmSync(tempDir, { recursive: true, force: true });
457
+ }
458
+ });
459
+ it('should handle skills with missing optional fields', async () => {
460
+ // Edge case: Skills missing optional fields
461
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
462
+ mkdirSync(tempDir, { recursive: true });
463
+ const minimalSkillRegistry = join(tempDir, 'minimal-registry.yaml');
464
+ writeFileSync(minimalSkillRegistry, `
465
+ version: "1.0.0"
466
+ skills:
467
+ minimal:
468
+ name: minimal
469
+ description: A minimal skill
470
+ category: development
471
+ tags: []
472
+ # optional fields omitted: examples, anti_patterns, related_skills, keywords
473
+ `);
474
+ try {
475
+ const result = await generateSkillDocs({
476
+ registryPath: minimalSkillRegistry,
477
+ });
478
+ assert.ok(result.success, 'Should succeed with minimal skill');
479
+ assert.ok(result.content.includes('minimal'), 'Should include minimal skill');
480
+ }
481
+ finally {
482
+ rmSync(tempDir, { recursive: true, force: true });
483
+ }
484
+ });
485
+ it('should handle special characters in skill content', async () => {
486
+ // Edge case: Special markdown characters in content
487
+ const tempDir = join(tmpdir(), `skill-docs-test-${Date.now()}`);
488
+ mkdirSync(tempDir, { recursive: true });
489
+ const specialRegistry = join(tempDir, 'special-registry.yaml');
490
+ writeFileSync(specialRegistry, `
491
+ version: "1.0.0"
492
+ skills:
493
+ special:
494
+ name: special
495
+ description: "A skill with *asterisks* and [brackets] and \`backticks\`"
496
+ category: development
497
+ tags: [tag-with-dash, tag_with_underscore]
498
+ examples:
499
+ - context: "Example with 'quotes'"
500
+ invocation: /special --flag=value
501
+ anti_patterns:
502
+ - "Don't do this: \`bad code\`"
503
+ related_skills: []
504
+ keywords: []
505
+ `);
506
+ try {
507
+ const result = await generateSkillDocs({
508
+ registryPath: specialRegistry,
509
+ });
510
+ assert.ok(result.success, 'Should handle special characters');
511
+ assert.ok(result.content.includes('special'), 'Should include skill');
512
+ }
513
+ finally {
514
+ rmSync(tempDir, { recursive: true, force: true });
515
+ }
516
+ });
517
+ });
518
+ });
519
+ //# sourceMappingURL=generate-skill-docs.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"generate-skill-docs.test.js","sourceRoot":"","sources":["../src/generate-skill-docs.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @pennyfarthing/shared
3
+ * Shared utilities for Pennyfarthing including portrait path resolution
4
+ */
5
+ export { resolvePennyfarthingDist, resolvePortraitPath, getPortraitPaths, type PortraitPaths, } from './portrait-resolver.js';
6
+ export { loadTheme, listThemes, getAgentPersona, type Theme, type ThemeAgent, } from './theme-loader.js';
7
+ export { searchSkills, type SearchOptions, type SkillResult, } from './skill-search.js';
8
+ export { suggestSkills, suggestFromSession, suggestFromKeywords, type SuggestOptions, type SkillSuggestion, type SessionContext, } from './skill-suggest.js';
9
+ export { generateSkillDocs, type GeneratorOptions, type GeneratorResult, } from './generate-skill-docs.js';
10
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,EAChB,KAAK,aAAa,GACnB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,SAAS,EACT,UAAU,EACV,eAAe,EACf,KAAK,KAAK,EACV,KAAK,UAAU,GAChB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,EACZ,KAAK,aAAa,EAClB,KAAK,WAAW,GACjB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,mBAAmB,EACnB,KAAK,cAAc,EACnB,KAAK,eAAe,EACpB,KAAK,cAAc,GACpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,EACjB,KAAK,gBAAgB,EACrB,KAAK,eAAe,GACrB,MAAM,0BAA0B,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,10 @@
1
+ /**
2
+ * @pennyfarthing/shared
3
+ * Shared utilities for Pennyfarthing including portrait path resolution
4
+ */
5
+ export { resolvePennyfarthingDist, resolvePortraitPath, getPortraitPaths, } from './portrait-resolver.js';
6
+ export { loadTheme, listThemes, getAgentPersona, } from './theme-loader.js';
7
+ export { searchSkills, } from './skill-search.js';
8
+ export { suggestSkills, suggestFromSession, suggestFromKeywords, } from './skill-suggest.js';
9
+ export { generateSkillDocs, } from './generate-skill-docs.js';
10
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA;;;GAGG;AAEH,OAAO,EACL,wBAAwB,EACxB,mBAAmB,EACnB,gBAAgB,GAEjB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,EACL,SAAS,EACT,UAAU,EACV,eAAe,GAGhB,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,YAAY,GAGb,MAAM,mBAAmB,CAAC;AAE3B,OAAO,EACL,aAAa,EACb,kBAAkB,EAClB,mBAAmB,GAIpB,MAAM,oBAAoB,CAAC;AAE5B,OAAO,EACL,iBAAiB,GAGlB,MAAM,0BAA0B,CAAC"}
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Portrait Resolver - Smart path resolution for Pennyfarthing portraits
3
+ *
4
+ * Checks paths in priority order:
5
+ * 1. PENNYFARTHING_DIST env var (explicit override)
6
+ * 2. Monorepo root (pennyfarthing-dist/ at repo root for dogfooding)
7
+ * 3. Sibling directory (for dev scenarios)
8
+ * 4. Scoped npm (node_modules/@pennyfarthing/core/pennyfarthing-dist/)
9
+ * 5. Legacy npm (node_modules/pennyfarthing/pennyfarthing-dist/)
10
+ */
11
+ export interface PortraitPaths {
12
+ portraitsDir: string;
13
+ themesDir: string;
14
+ agentsDir: string;
15
+ }
16
+ /**
17
+ * Resolve the pennyfarthing-dist directory path
18
+ * Checks multiple locations in priority order
19
+ */
20
+ export declare function resolvePennyfarthingDist(): string | null;
21
+ /**
22
+ * Resolve the full path to a portrait image
23
+ * @param theme - Theme name (e.g., 'shakespeare', 'norse-mythology')
24
+ * @param agent - Agent name (e.g., 'sm', 'tea', 'dev')
25
+ * @returns Full path to portrait file, or null if not found
26
+ */
27
+ export declare function resolvePortraitPath(theme: string, agent: string): string | null;
28
+ /**
29
+ * Get all portrait-related paths for a resolved dist directory
30
+ */
31
+ export declare function getPortraitPaths(distPath: string): PortraitPaths;
32
+ //# sourceMappingURL=portrait-resolver.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"portrait-resolver.d.ts","sourceRoot":"","sources":["../src/portrait-resolver.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAMH,MAAM,WAAW,aAAa;IAC5B,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;CACnB;AAMD;;;GAGG;AACH,wBAAgB,wBAAwB,IAAI,MAAM,GAAG,IAAI,CAgDxD;AAED;;;;;GAKG;AACH,wBAAgB,mBAAmB,CAAC,KAAK,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAsE/E;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,aAAa,CAShE"}