@paperclipai/skills-catalog 0.3.1

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 (43) hide show
  1. package/catalog/bundled/docs/doc-maintenance/SKILL.md +75 -0
  2. package/catalog/bundled/paperclip-operations/issue-triage/SKILL.md +74 -0
  3. package/catalog/bundled/paperclip-operations/task-planning/SKILL.md +84 -0
  4. package/catalog/bundled/quality/qa-acceptance/SKILL.md +93 -0
  5. package/catalog/bundled/software-development/github-pr-workflow/SKILL.md +93 -0
  6. package/catalog/optional/browser/agent-browser/SKILL.md +93 -0
  7. package/catalog/optional/content/release-announcement/SKILL.md +128 -0
  8. package/catalog/optional/product/design-critique/SKILL.md +121 -0
  9. package/dist/generated/catalog.json +285 -0
  10. package/dist/scripts/build-catalog-manifest.d.ts +2 -0
  11. package/dist/scripts/build-catalog-manifest.d.ts.map +1 -0
  12. package/dist/scripts/build-catalog-manifest.js +15 -0
  13. package/dist/scripts/build-catalog-manifest.js.map +1 -0
  14. package/dist/scripts/validate-catalog.d.ts +2 -0
  15. package/dist/scripts/validate-catalog.d.ts.map +1 -0
  16. package/dist/scripts/validate-catalog.js +15 -0
  17. package/dist/scripts/validate-catalog.js.map +1 -0
  18. package/dist/src/catalog-builder.d.ts +16 -0
  19. package/dist/src/catalog-builder.d.ts.map +1 -0
  20. package/dist/src/catalog-builder.js +357 -0
  21. package/dist/src/catalog-builder.js.map +1 -0
  22. package/dist/src/catalog-builder.test.d.ts +2 -0
  23. package/dist/src/catalog-builder.test.d.ts.map +1 -0
  24. package/dist/src/catalog-builder.test.js +124 -0
  25. package/dist/src/catalog-builder.test.js.map +1 -0
  26. package/dist/src/frontmatter.d.ts +11 -0
  27. package/dist/src/frontmatter.d.ts.map +1 -0
  28. package/dist/src/frontmatter.js +141 -0
  29. package/dist/src/frontmatter.js.map +1 -0
  30. package/dist/src/index.d.ts +7 -0
  31. package/dist/src/index.d.ts.map +1 -0
  32. package/dist/src/index.js +21 -0
  33. package/dist/src/index.js.map +1 -0
  34. package/dist/src/shipped-catalog.test.d.ts +2 -0
  35. package/dist/src/shipped-catalog.test.d.ts.map +1 -0
  36. package/dist/src/shipped-catalog.test.js +83 -0
  37. package/dist/src/shipped-catalog.test.js.map +1 -0
  38. package/dist/src/types.d.ts +42 -0
  39. package/dist/src/types.d.ts.map +1 -0
  40. package/dist/src/types.js +2 -0
  41. package/dist/src/types.js.map +1 -0
  42. package/generated/catalog.json +285 -0
  43. package/package.json +49 -0
@@ -0,0 +1,357 @@
1
+ import { createHash } from "node:crypto";
2
+ import { existsSync } from "node:fs";
3
+ import fs from "node:fs/promises";
4
+ import path from "node:path";
5
+ import { asBoolean, asString, asStringArray, parseFrontmatterMarkdown, } from "./frontmatter.js";
6
+ const CATALOG_PACKAGE_NAME = "@paperclipai/skills-catalog";
7
+ const CATALOG_SCHEMA_VERSION = 1;
8
+ const SKILL_ENTRYPOINT = "SKILL.md";
9
+ const MAX_CATALOG_FILE_BYTES = 1024 * 1024;
10
+ const SLUG_PATTERN = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
11
+ const CATALOG_KINDS = new Set(["bundled", "optional"]);
12
+ export function formatCatalogManifest(manifest) {
13
+ return `${JSON.stringify(manifest, null, 2)}\n`;
14
+ }
15
+ export async function buildExpectedCatalogManifest(packageDir) {
16
+ const existing = await readExistingManifest(packageDir);
17
+ const firstPass = await buildCatalogManifest({
18
+ packageDir,
19
+ generatedAt: existing?.generatedAt ?? new Date().toISOString(),
20
+ });
21
+ if (existing && sameManifestExceptGeneratedAt(existing, firstPass.manifest)) {
22
+ return firstPass;
23
+ }
24
+ return buildCatalogManifest({
25
+ packageDir,
26
+ generatedAt: new Date().toISOString(),
27
+ });
28
+ }
29
+ export async function buildCatalogManifest(options) {
30
+ const packageDir = path.resolve(options.packageDir);
31
+ const packageJson = await readPackageJson(packageDir);
32
+ const errors = [];
33
+ const candidates = await discoverSkillCandidates(packageDir, errors);
34
+ const skills = [];
35
+ collectCandidateUniquenessErrors(candidates, errors);
36
+ for (const candidate of candidates) {
37
+ const skill = await buildCatalogSkill(packageDir, candidate, errors);
38
+ if (skill)
39
+ skills.push(skill);
40
+ }
41
+ skills.sort((a, b) => a.id.localeCompare(b.id));
42
+ collectUniquenessErrors(skills, errors);
43
+ return {
44
+ manifest: {
45
+ schemaVersion: CATALOG_SCHEMA_VERSION,
46
+ packageName: CATALOG_PACKAGE_NAME,
47
+ packageVersion: packageJson.version,
48
+ generatedAt: options.generatedAt ?? new Date().toISOString(),
49
+ skills,
50
+ },
51
+ errors,
52
+ };
53
+ }
54
+ export async function validateCatalog(packageDir) {
55
+ const expected = await buildExpectedCatalogManifest(packageDir);
56
+ const generatedPath = path.join(packageDir, "generated", "catalog.json");
57
+ const errors = [...expected.errors];
58
+ let generatedText = null;
59
+ try {
60
+ generatedText = await fs.readFile(generatedPath, "utf8");
61
+ JSON.parse(generatedText);
62
+ }
63
+ catch (error) {
64
+ errors.push(`generated/catalog.json is missing or invalid: ${errorMessage(error)}`);
65
+ }
66
+ if (generatedText !== null) {
67
+ const expectedText = formatCatalogManifest(expected.manifest);
68
+ if (generatedText !== expectedText) {
69
+ errors.push("generated/catalog.json is stale. Run pnpm --filter @paperclipai/skills-catalog build:manifest.");
70
+ }
71
+ }
72
+ return {
73
+ manifest: expected.manifest,
74
+ errors,
75
+ };
76
+ }
77
+ export async function writeCatalogManifest(packageDir) {
78
+ const result = await buildExpectedCatalogManifest(packageDir);
79
+ if (result.errors.length > 0)
80
+ return result;
81
+ const generatedDir = path.join(packageDir, "generated");
82
+ await fs.mkdir(generatedDir, { recursive: true });
83
+ await fs.writeFile(path.join(generatedDir, "catalog.json"), formatCatalogManifest(result.manifest), "utf8");
84
+ return result;
85
+ }
86
+ async function readPackageJson(packageDir) {
87
+ const packageJsonPath = path.join(packageDir, "package.json");
88
+ const packageJson = JSON.parse(await fs.readFile(packageJsonPath, "utf8"));
89
+ const version = asString(packageJson.version);
90
+ if (!version)
91
+ throw new Error(`${packageJsonPath} must declare a package version.`);
92
+ return { version };
93
+ }
94
+ async function readExistingManifest(packageDir) {
95
+ try {
96
+ return JSON.parse(await fs.readFile(path.join(packageDir, "generated", "catalog.json"), "utf8"));
97
+ }
98
+ catch {
99
+ return null;
100
+ }
101
+ }
102
+ async function discoverSkillCandidates(packageDir, errors) {
103
+ const catalogDir = path.join(packageDir, "catalog");
104
+ const candidates = [];
105
+ if (!existsSync(catalogDir)) {
106
+ errors.push("catalog directory is missing.");
107
+ return candidates;
108
+ }
109
+ await collectMisplacedSkillFiles(catalogDir, errors);
110
+ for (const kind of ["bundled", "optional"]) {
111
+ const kindDir = path.join(catalogDir, kind);
112
+ if (!existsSync(kindDir))
113
+ continue;
114
+ for (const categoryEntry of await sortedDirEntries(kindDir)) {
115
+ if (!categoryEntry.isDirectory())
116
+ continue;
117
+ const category = categoryEntry.name;
118
+ const categoryDir = path.join(kindDir, category);
119
+ for (const slugEntry of await sortedDirEntries(categoryDir)) {
120
+ if (!slugEntry.isDirectory())
121
+ continue;
122
+ const slug = slugEntry.name;
123
+ const skillDir = path.join(categoryDir, slug);
124
+ if (!existsSync(path.join(skillDir, SKILL_ENTRYPOINT))) {
125
+ errors.push(`${relativePackagePath(packageDir, skillDir)} is missing SKILL.md.`);
126
+ continue;
127
+ }
128
+ candidates.push({ kind, category, slug, absolutePath: skillDir });
129
+ }
130
+ }
131
+ }
132
+ return candidates;
133
+ }
134
+ async function collectMisplacedSkillFiles(catalogDir, errors) {
135
+ async function visit(dir) {
136
+ for (const entry of await sortedDirEntries(dir)) {
137
+ const absolutePath = path.join(dir, entry.name);
138
+ if (entry.isDirectory()) {
139
+ await visit(absolutePath);
140
+ continue;
141
+ }
142
+ if (entry.name !== SKILL_ENTRYPOINT)
143
+ continue;
144
+ const relativePath = toPosixPath(path.relative(catalogDir, absolutePath));
145
+ const parts = relativePath.split("/");
146
+ const kind = parts[0];
147
+ if (parts.length !== 4 || !CATALOG_KINDS.has(kind)) {
148
+ errors.push(`catalog/${relativePath} is not under catalog/<bundled|optional>/<category>/<slug>/SKILL.md.`);
149
+ }
150
+ }
151
+ }
152
+ await visit(catalogDir);
153
+ }
154
+ async function buildCatalogSkill(packageDir, candidate, errors) {
155
+ const prefix = relativePackagePath(packageDir, candidate.absolutePath);
156
+ validateSlug("category", candidate.category, prefix, errors);
157
+ validateSlug("slug", candidate.slug, prefix, errors);
158
+ const id = `paperclipai:${candidate.kind}:${candidate.category}:${candidate.slug}`;
159
+ const key = `paperclipai/${candidate.kind}/${candidate.category}/${candidate.slug}`;
160
+ const skillMarkdownPath = path.join(candidate.absolutePath, SKILL_ENTRYPOINT);
161
+ const parsed = parseFrontmatterMarkdown(await fs.readFile(skillMarkdownPath, "utf8"));
162
+ if (!parsed.hasFrontmatter) {
163
+ errors.push(`${prefix}/SKILL.md must start with YAML frontmatter.`);
164
+ }
165
+ const name = asString(parsed.frontmatter.name);
166
+ if (!name)
167
+ errors.push(`${prefix}/SKILL.md frontmatter must include name.`);
168
+ const description = asString(parsed.frontmatter.description);
169
+ if (!description)
170
+ errors.push(`${prefix}/SKILL.md frontmatter must include description.`);
171
+ const explicitKey = asString(parsed.frontmatter.key);
172
+ if (explicitKey && explicitKey !== key) {
173
+ errors.push(`${prefix}/SKILL.md key must be ${key}.`);
174
+ }
175
+ const explicitSlug = asString(parsed.frontmatter.slug);
176
+ if (explicitSlug && explicitSlug !== candidate.slug) {
177
+ errors.push(`${prefix}/SKILL.md slug must be ${candidate.slug}.`);
178
+ }
179
+ const defaultInstall = asBoolean(parsed.frontmatter.defaultInstall) ?? false;
180
+ const recommendedForRoles = readStringArrayField(parsed.frontmatter.recommendedForRoles, "recommendedForRoles", prefix, errors);
181
+ const requires = readStringArrayField(parsed.frontmatter.requires, "requires", prefix, errors);
182
+ const tags = readStringArrayField(parsed.frontmatter.tags, "tags", prefix, errors);
183
+ const files = await collectSkillFiles(packageDir, candidate.absolutePath, prefix, errors);
184
+ if (!name || !description)
185
+ return null;
186
+ return {
187
+ id,
188
+ key,
189
+ kind: candidate.kind,
190
+ category: candidate.category,
191
+ slug: candidate.slug,
192
+ name,
193
+ description,
194
+ path: toPosixPath(path.relative(packageDir, candidate.absolutePath)),
195
+ entrypoint: SKILL_ENTRYPOINT,
196
+ trustLevel: deriveTrustLevel(files),
197
+ compatibility: "compatible",
198
+ defaultInstall,
199
+ recommendedForRoles,
200
+ requires,
201
+ tags,
202
+ files,
203
+ contentHash: buildContentHash(files),
204
+ };
205
+ }
206
+ async function collectSkillFiles(packageDir, skillDir, prefix, errors) {
207
+ const files = [];
208
+ const skillRoot = await fs.realpath(skillDir);
209
+ async function visit(dir) {
210
+ for (const entry of await sortedDirEntries(dir)) {
211
+ const absolutePath = path.join(dir, entry.name);
212
+ const lstat = await fs.lstat(absolutePath);
213
+ let stat = lstat;
214
+ let realPath = absolutePath;
215
+ if (lstat.isSymbolicLink()) {
216
+ try {
217
+ realPath = await fs.realpath(absolutePath);
218
+ stat = await fs.stat(absolutePath);
219
+ }
220
+ catch {
221
+ errors.push(`${relativePackagePath(packageDir, absolutePath)} is a broken symlink.`);
222
+ continue;
223
+ }
224
+ if (!isPathInside(skillRoot, realPath)) {
225
+ errors.push(`${relativePackagePath(packageDir, absolutePath)} points outside its skill directory.`);
226
+ continue;
227
+ }
228
+ if (stat.isDirectory()) {
229
+ errors.push(`${relativePackagePath(packageDir, absolutePath)} is a directory symlink; copy files into the skill directory instead.`);
230
+ continue;
231
+ }
232
+ }
233
+ if (stat.isDirectory()) {
234
+ await visit(absolutePath);
235
+ continue;
236
+ }
237
+ if (!stat.isFile())
238
+ continue;
239
+ const relativePath = toPosixPath(path.relative(skillDir, absolutePath));
240
+ if (path.isAbsolute(relativePath) || relativePath.split("/").includes("..")) {
241
+ errors.push(`${prefix}/${relativePath} has an invalid inventory path.`);
242
+ continue;
243
+ }
244
+ if (stat.size > MAX_CATALOG_FILE_BYTES) {
245
+ errors.push(`${prefix}/${relativePath} exceeds ${MAX_CATALOG_FILE_BYTES} bytes.`);
246
+ }
247
+ const contents = await fs.readFile(absolutePath);
248
+ files.push({
249
+ path: relativePath,
250
+ kind: classifyCatalogFile(relativePath),
251
+ sizeBytes: stat.size,
252
+ sha256: sha256(contents),
253
+ });
254
+ }
255
+ }
256
+ await visit(skillDir);
257
+ files.sort((a, b) => {
258
+ if (a.path === SKILL_ENTRYPOINT)
259
+ return -1;
260
+ if (b.path === SKILL_ENTRYPOINT)
261
+ return 1;
262
+ return a.path.localeCompare(b.path);
263
+ });
264
+ if (!files.some((file) => file.path === SKILL_ENTRYPOINT && file.kind === "skill")) {
265
+ errors.push(`${prefix} inventory does not contain SKILL.md.`);
266
+ }
267
+ return files;
268
+ }
269
+ function readStringArrayField(value, field, prefix, errors) {
270
+ const parsed = asStringArray(value);
271
+ if (!parsed) {
272
+ errors.push(`${prefix}/SKILL.md frontmatter field ${field} must be an array of strings.`);
273
+ return [];
274
+ }
275
+ return parsed;
276
+ }
277
+ function classifyCatalogFile(relativePath) {
278
+ if (relativePath === SKILL_ENTRYPOINT)
279
+ return "skill";
280
+ if (relativePath.startsWith("references/"))
281
+ return "reference";
282
+ if (relativePath.startsWith("scripts/"))
283
+ return "script";
284
+ if (relativePath.startsWith("assets/"))
285
+ return "asset";
286
+ if (relativePath.endsWith(".md") || relativePath.endsWith(".mdx"))
287
+ return "markdown";
288
+ return "other";
289
+ }
290
+ function deriveTrustLevel(files) {
291
+ if (files.some((file) => file.kind === "script"))
292
+ return "scripts_executables";
293
+ if (files.some((file) => file.kind === "asset" || file.kind === "other"))
294
+ return "assets";
295
+ return "markdown_only";
296
+ }
297
+ function buildContentHash(files) {
298
+ const hashInput = files.map((file) => ({
299
+ path: file.path,
300
+ sha256: file.sha256,
301
+ }));
302
+ return `sha256:${sha256(Buffer.from(JSON.stringify(hashInput)))}`;
303
+ }
304
+ function collectUniquenessErrors(skills, errors) {
305
+ collectDuplicateErrors(skills, "id", errors);
306
+ collectDuplicateErrors(skills, "key", errors);
307
+ collectDuplicateErrors(skills, "slug", errors);
308
+ }
309
+ function collectCandidateUniquenessErrors(candidates, errors) {
310
+ const projected = candidates.map((candidate) => ({
311
+ id: `paperclipai:${candidate.kind}:${candidate.category}:${candidate.slug}`,
312
+ key: `paperclipai/${candidate.kind}/${candidate.category}/${candidate.slug}`,
313
+ slug: candidate.slug,
314
+ path: toPosixPath(path.join("catalog", candidate.kind, candidate.category, candidate.slug)),
315
+ }));
316
+ collectUniquenessErrors(projected, errors);
317
+ }
318
+ function collectDuplicateErrors(fieldSkills, field, errors) {
319
+ const seen = new Map();
320
+ for (const skill of fieldSkills) {
321
+ const value = skill[field];
322
+ const first = seen.get(value);
323
+ if (first) {
324
+ errors.push(`Duplicate catalog ${field} "${value}" in ${first} and ${skill.path}.`);
325
+ continue;
326
+ }
327
+ seen.set(value, skill.path);
328
+ }
329
+ }
330
+ function validateSlug(label, value, prefix, errors) {
331
+ if (!SLUG_PATTERN.test(value)) {
332
+ errors.push(`${prefix} has invalid ${label} "${value}"; use lowercase URL slugs.`);
333
+ }
334
+ }
335
+ async function sortedDirEntries(dir) {
336
+ return (await fs.readdir(dir, { withFileTypes: true })).sort((a, b) => a.name.localeCompare(b.name));
337
+ }
338
+ function sameManifestExceptGeneratedAt(a, b) {
339
+ return JSON.stringify({ ...a, generatedAt: "" }) === JSON.stringify({ ...b, generatedAt: "" });
340
+ }
341
+ function sha256(contents) {
342
+ return createHash("sha256").update(contents).digest("hex");
343
+ }
344
+ function relativePackagePath(packageDir, absolutePath) {
345
+ return toPosixPath(path.relative(packageDir, absolutePath));
346
+ }
347
+ function toPosixPath(input) {
348
+ return input.split(path.sep).join("/");
349
+ }
350
+ function isPathInside(parent, child) {
351
+ const relativePath = path.relative(parent, child);
352
+ return relativePath === "" || (!relativePath.startsWith("..") && !path.isAbsolute(relativePath));
353
+ }
354
+ function errorMessage(error) {
355
+ return error instanceof Error ? error.message : String(error);
356
+ }
357
+ //# sourceMappingURL=catalog-builder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-builder.js","sourceRoot":"","sources":["../../src/catalog-builder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=catalog-builder.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-builder.test.d.ts","sourceRoot":"","sources":["../../src/catalog-builder.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,124 @@
1
+ import fs from "node:fs/promises";
2
+ import os from "node:os";
3
+ import path from "node:path";
4
+ import { afterEach, describe, expect, it } from "vitest";
5
+ import { buildCatalogManifest, formatCatalogManifest, validateCatalog, } from "./catalog-builder.js";
6
+ const tempDirs = [];
7
+ describe("skills catalog manifest", () => {
8
+ afterEach(async () => {
9
+ await Promise.all(tempDirs.splice(0).map((dir) => fs.rm(dir, { recursive: true, force: true })));
10
+ });
11
+ it("builds stable manifest entries from catalog skill directories", async () => {
12
+ const packageDir = await createCatalogPackage();
13
+ await writeSkill(packageDir, "bundled", "software-development", "github-pr-workflow", {
14
+ frontmatter: [
15
+ "name: GitHub PR Workflow",
16
+ "description: Prepare pull requests and verification notes.",
17
+ "key: paperclipai/bundled/software-development/github-pr-workflow",
18
+ "recommendedForRoles:",
19
+ " - engineer",
20
+ "tags:",
21
+ " - github",
22
+ " - pull-requests",
23
+ ],
24
+ files: {
25
+ "references/checklist.md": "# Checklist\n",
26
+ },
27
+ });
28
+ const result = await buildCatalogManifest({
29
+ packageDir,
30
+ generatedAt: "2026-05-26T00:00:00.000Z",
31
+ });
32
+ expect(result.errors).toEqual([]);
33
+ expect(result.manifest.skills).toHaveLength(1);
34
+ expect(result.manifest.skills[0]).toMatchObject({
35
+ id: "paperclipai:bundled:software-development:github-pr-workflow",
36
+ key: "paperclipai/bundled/software-development/github-pr-workflow",
37
+ kind: "bundled",
38
+ category: "software-development",
39
+ slug: "github-pr-workflow",
40
+ name: "GitHub PR Workflow",
41
+ trustLevel: "markdown_only",
42
+ compatibility: "compatible",
43
+ recommendedForRoles: ["engineer"],
44
+ tags: ["github", "pull-requests"],
45
+ });
46
+ expect(result.manifest.skills[0].files.map((file) => file.path)).toEqual([
47
+ "SKILL.md",
48
+ "references/checklist.md",
49
+ ]);
50
+ expect(result.manifest.skills[0].contentHash).toMatch(/^sha256:[a-f0-9]{64}$/);
51
+ });
52
+ it("reports frontmatter, directory, uniqueness, and inventory errors together", async () => {
53
+ const packageDir = await createCatalogPackage();
54
+ await writeSkill(packageDir, "bundled", "Bad_Category", "duplicate", {
55
+ frontmatter: [
56
+ "name: Duplicate",
57
+ "key: paperclipai/bundled/software-development/other",
58
+ "recommendedForRoles: engineer",
59
+ ],
60
+ });
61
+ await writeSkill(packageDir, "optional", "software-development", "duplicate", {
62
+ frontmatter: [
63
+ "name: Duplicate Optional",
64
+ "description: Optional duplicate slug.",
65
+ ],
66
+ });
67
+ await fs.mkdir(path.join(packageDir, "catalog", "bundled", "software-development", "missing-skill"), {
68
+ recursive: true,
69
+ });
70
+ await fs.mkdir(path.join(packageDir, "catalog", "misc"), { recursive: true });
71
+ await fs.writeFile(path.join(packageDir, "catalog", "misc", "SKILL.md"), "# Misplaced\n", "utf8");
72
+ const result = await buildCatalogManifest({
73
+ packageDir,
74
+ generatedAt: "2026-05-26T00:00:00.000Z",
75
+ });
76
+ expect(result.errors).toEqual(expect.arrayContaining([
77
+ expect.stringContaining("catalog/misc/SKILL.md is not under catalog/<bundled|optional>/<category>/<slug>/SKILL.md"),
78
+ expect.stringContaining("catalog/bundled/software-development/missing-skill is missing SKILL.md"),
79
+ expect.stringContaining("has invalid category"),
80
+ expect.stringContaining("frontmatter must include description"),
81
+ expect.stringContaining("key must be paperclipai/bundled/Bad_Category/duplicate"),
82
+ expect.stringContaining("field recommendedForRoles must be an array of strings"),
83
+ expect.stringContaining("Duplicate catalog slug \"duplicate\""),
84
+ ]));
85
+ });
86
+ it("detects stale generated manifests", async () => {
87
+ const packageDir = await createCatalogPackage();
88
+ await writeSkill(packageDir, "bundled", "software-development", "review", {
89
+ frontmatter: [
90
+ "name: Review",
91
+ "description: Review implementation work.",
92
+ ],
93
+ });
94
+ await fs.mkdir(path.join(packageDir, "generated"), { recursive: true });
95
+ await fs.writeFile(path.join(packageDir, "generated", "catalog.json"), formatCatalogManifest({
96
+ schemaVersion: 1,
97
+ packageName: "@paperclipai/skills-catalog",
98
+ packageVersion: "0.3.1",
99
+ generatedAt: "2026-05-26T00:00:00.000Z",
100
+ skills: [],
101
+ }), "utf8");
102
+ const result = await validateCatalog(packageDir);
103
+ expect(result.errors).toContain("generated/catalog.json is stale. Run pnpm --filter @paperclipai/skills-catalog build:manifest.");
104
+ });
105
+ });
106
+ async function createCatalogPackage() {
107
+ const packageDir = await fs.mkdtemp(path.join(os.tmpdir(), "skills-catalog-"));
108
+ tempDirs.push(packageDir);
109
+ await fs.mkdir(path.join(packageDir, "catalog", "bundled"), { recursive: true });
110
+ await fs.mkdir(path.join(packageDir, "catalog", "optional"), { recursive: true });
111
+ await fs.writeFile(path.join(packageDir, "package.json"), JSON.stringify({ version: "0.3.1" }), "utf8");
112
+ return packageDir;
113
+ }
114
+ async function writeSkill(packageDir, kind, category, slug, options) {
115
+ const skillDir = path.join(packageDir, "catalog", kind, category, slug);
116
+ await fs.mkdir(skillDir, { recursive: true });
117
+ await fs.writeFile(path.join(skillDir, "SKILL.md"), `---\n${options.frontmatter.join("\n")}\n---\n\nUse this skill.\n`, "utf8");
118
+ for (const [relativePath, content] of Object.entries(options.files ?? {})) {
119
+ const filePath = path.join(skillDir, relativePath);
120
+ await fs.mkdir(path.dirname(filePath), { recursive: true });
121
+ await fs.writeFile(filePath, content, "utf8");
122
+ }
123
+ }
124
+ //# sourceMappingURL=catalog-builder.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"catalog-builder.test.js","sourceRoot":"","sources":["../../src/catalog-builder.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,11 @@
1
+ export interface MarkdownDoc {
2
+ frontmatter: Record<string, unknown>;
3
+ body: string;
4
+ hasFrontmatter: boolean;
5
+ }
6
+ export declare function isPlainRecord(value: unknown): value is Record<string, unknown>;
7
+ export declare function asString(value: unknown): string | null;
8
+ export declare function asBoolean(value: unknown): boolean | null;
9
+ export declare function asStringArray(value: unknown): string[] | null;
10
+ export declare function parseFrontmatterMarkdown(raw: string): MarkdownDoc;
11
+ //# sourceMappingURL=frontmatter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"frontmatter.d.ts","sourceRoot":"","sources":["../../src/frontmatter.ts"],"names":[],"mappings":"AAAA,MAAM,WAAW,WAAW;IAC1B,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IACrC,IAAI,EAAE,MAAM,CAAC;IACb,cAAc,EAAE,OAAO,CAAC;CACzB;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED,wBAAgB,QAAQ,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,GAAG,IAAI,CAItD;AAED,wBAAgB,SAAS,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,GAAG,IAAI,CAExD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,EAAE,GAAG,IAAI,CAW7D;AAED,wBAAgB,wBAAwB,CAAC,GAAG,EAAE,MAAM,GAAG,WAAW,CAkBjE"}