@tanstack/intent 0.0.13 → 0.0.19

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 (36) hide show
  1. package/README.md +58 -21
  2. package/dist/cli.d.mts +6 -1
  3. package/dist/cli.mjs +250 -171
  4. package/dist/display-CuCDLPP_.mjs +3 -0
  5. package/dist/index.d.mts +18 -6
  6. package/dist/index.mjs +38 -15
  7. package/dist/install-prompt-C0M-U3WZ.mjs +59 -0
  8. package/dist/intent-library.mjs +5 -49
  9. package/dist/{library-scanner-V9sTOhrb.mjs → library-scanner-CU0OozQE.mjs} +4 -12
  10. package/dist/library-scanner.d.mts +4 -4
  11. package/dist/library-scanner.mjs +2 -2
  12. package/dist/scanner-B1UvuEBQ.mjs +4 -0
  13. package/dist/scanner-f82qRq7h.mjs +338 -0
  14. package/dist/setup-6m3IfxyO.d.mts +30 -0
  15. package/dist/setup-CncHbQlb.mjs +360 -0
  16. package/dist/setup.d.mts +2 -2
  17. package/dist/setup.mjs +3 -2
  18. package/dist/staleness-CWWuoPop.mjs +4 -0
  19. package/dist/{staleness-lP6B0O4z.mjs → staleness-D_ZiK4Tf.mjs} +24 -3
  20. package/dist/{types-BmnI8kFB.d.mts → types-ddLtccfV.d.mts} +30 -7
  21. package/dist/utils-DY1eH2E_.mjs +157 -0
  22. package/dist/utils-XSyO19J6.mjs +3 -0
  23. package/meta/domain-discovery/SKILL.md +95 -20
  24. package/meta/feedback-collection/SKILL.md +20 -1
  25. package/meta/generate-skill/SKILL.md +56 -5
  26. package/meta/templates/workflows/check-skills.yml +4 -4
  27. package/meta/templates/workflows/{notify-playbooks.yml → notify-intent.yml} +4 -4
  28. package/meta/tree-generator/SKILL.md +2 -2
  29. package/package.json +4 -3
  30. package/dist/scanner-DQeiZRzp.mjs +0 -4
  31. package/dist/scanner-dIYdkHQ1.mjs +0 -180
  32. package/dist/setup-BYOg-Ii-.mjs +0 -197
  33. package/dist/setup-CANkTz55.d.mts +0 -18
  34. package/dist/staleness-B5gUj7FR.mjs +0 -4
  35. package/dist/utils-DH3jY3CI.mjs +0 -39
  36. /package/dist/{display-D_XzuGnu.mjs → display-DhsUxNJW.mjs} +0 -0
package/dist/cli.mjs CHANGED
@@ -1,39 +1,88 @@
1
1
  #!/usr/bin/env node
2
- import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
3
- import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
4
- import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-D_XzuGnu.mjs";
2
+ import { t as INSTALL_PROMPT } from "./install-prompt-C0M-U3WZ.mjs";
5
3
  import { existsSync, readFileSync, readdirSync } from "node:fs";
6
4
  import { dirname, join, relative, sep } from "node:path";
7
- import { parse } from "yaml";
8
- import { fileURLToPath } from "node:url";
5
+ import { fileURLToPath, pathToFileURL } from "node:url";
9
6
 
10
7
  //#region src/cli.ts
11
8
  function getMetaDir() {
12
9
  return join(dirname(fileURLToPath(import.meta.url)), "..", "meta");
13
10
  }
14
- async function cmdList(args) {
15
- const jsonOutput = args.includes("--json");
16
- let result;
11
+ function fail(message, exitCode = 1) {
12
+ throw {
13
+ message,
14
+ exitCode
15
+ };
16
+ }
17
+ function isCliFailure(value) {
18
+ return !!value && typeof value === "object" && "message" in value && typeof value.message === "string" && "exitCode" in value && typeof value.exitCode === "number";
19
+ }
20
+ async function scanIntentsOrFail() {
21
+ const { scanForIntents } = await import("./scanner-B1UvuEBQ.mjs");
17
22
  try {
18
- result = await scanForIntents();
23
+ return await scanForIntents();
19
24
  } catch (err) {
20
- console.error(err.message);
21
- process.exit(1);
25
+ fail(err.message);
26
+ }
27
+ }
28
+ function printWarnings(warnings) {
29
+ if (warnings.length === 0) return;
30
+ console.log("Warnings:");
31
+ for (const warning of warnings) console.log(` ⚠ ${warning}`);
32
+ }
33
+ function formatScanCoverage(result) {
34
+ const coverage = [];
35
+ if (result.nodeModules.local.scanned) coverage.push("project node_modules");
36
+ if (result.nodeModules.global.scanned) coverage.push("global node_modules");
37
+ return coverage.join(", ");
38
+ }
39
+ function printVersionConflicts(result) {
40
+ if (result.conflicts.length === 0) return;
41
+ console.log("\nVersion conflicts:\n");
42
+ for (const conflict of result.conflicts) {
43
+ console.log(` ${conflict.packageName} -> using ${conflict.chosen.version}`);
44
+ console.log(` chosen: ${conflict.chosen.packageRoot}`);
45
+ for (const variant of conflict.variants) {
46
+ if (variant.packageRoot === conflict.chosen.packageRoot) continue;
47
+ console.log(` also found: ${variant.version} at ${variant.packageRoot}`);
48
+ }
49
+ console.log();
50
+ }
51
+ }
52
+ function buildValidationFailure(errors, warnings) {
53
+ const lines = [
54
+ "",
55
+ `❌ Validation failed with ${errors.length} error(s):`,
56
+ ""
57
+ ];
58
+ for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
59
+ if (warnings.length > 0) {
60
+ lines.push("", "⚠ Packaging warnings:");
61
+ for (const warning of warnings) lines.push(` ${warning}`);
22
62
  }
63
+ return lines.join("\n");
64
+ }
65
+ async function cmdList(args) {
66
+ const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-CuCDLPP_.mjs");
67
+ const jsonOutput = args.includes("--json");
68
+ const result = await scanIntentsOrFail();
23
69
  if (jsonOutput) {
24
70
  console.log(JSON.stringify(result, null, 2));
25
71
  return;
26
72
  }
73
+ const scanCoverage = formatScanCoverage(result);
27
74
  if (result.packages.length === 0) {
28
75
  console.log("No intent-enabled packages found.");
76
+ if (scanCoverage) console.log(`Scanned: ${scanCoverage}`);
29
77
  if (result.warnings.length > 0) {
30
- console.log(`\nWarnings:`);
31
- for (const w of result.warnings) console.log(` ⚠ ${w}`);
78
+ console.log();
79
+ printWarnings(result.warnings);
32
80
  }
33
81
  return;
34
82
  }
35
83
  const totalSkills = result.packages.reduce((sum, p) => sum + p.skills.length, 0);
36
84
  console.log(`\n${result.packages.length} intent-enabled packages, ${totalSkills} skills (${result.packageManager})\n`);
85
+ if (scanCoverage) console.log(`Scanned: ${scanCoverage}${result.nodeModules.global.scanned ? " (local packages take precedence)" : ""}\n`);
37
86
  printTable([
38
87
  "PACKAGE",
39
88
  "VERSION",
@@ -45,6 +94,7 @@ async function cmdList(args) {
45
94
  String(pkg.skills.length),
46
95
  pkg.intent.requires?.join(", ") || "–"
47
96
  ]));
97
+ printVersionConflicts(result);
48
98
  const nameWidth = computeSkillNameWidth(result.packages.map((p) => p.skills));
49
99
  const showTypes = result.packages.some((p) => p.skills.some((s) => s.type));
50
100
  console.log(`\nSkills:\n`);
@@ -60,35 +110,21 @@ async function cmdList(args) {
60
110
  console.log(` Submit feedback on skill usage to help maintainers improve the skills.`);
61
111
  console.log(` Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md`);
62
112
  console.log();
63
- if (result.warnings.length > 0) {
64
- console.log(`Warnings:`);
65
- for (const w of result.warnings) console.log(` ⚠ ${w}`);
66
- }
113
+ printWarnings(result.warnings);
67
114
  }
68
- function cmdMeta(args) {
115
+ async function cmdMeta(args) {
116
+ const { parseFrontmatter } = await import("./utils-XSyO19J6.mjs");
69
117
  const metaDir = getMetaDir();
70
- if (!existsSync(metaDir)) {
71
- console.error("Meta-skills directory not found.");
72
- process.exit(1);
73
- }
118
+ if (!existsSync(metaDir)) fail("Meta-skills directory not found.");
74
119
  if (args.length > 0) {
75
120
  const name = args[0];
76
- if (name.includes("..") || name.includes("/") || name.includes("\\")) {
77
- console.error(`Invalid meta-skill name: "${name}"`);
78
- process.exit(1);
79
- }
121
+ if (name.includes("..") || name.includes("/") || name.includes("\\")) fail(`Invalid meta-skill name: "${name}"`);
80
122
  const skillFile = join(metaDir, name, "SKILL.md");
81
- if (!existsSync(skillFile)) {
82
- console.error(`Meta-skill "${name}" not found.`);
83
- console.error(`Run \`npx @tanstack/intent meta\` to list available meta-skills.`);
84
- process.exit(1);
85
- }
123
+ if (!existsSync(skillFile)) fail(`Meta-skill "${name}" not found. Run \`intent meta\` to list available meta-skills.`);
86
124
  try {
87
125
  console.log(readFileSync(skillFile, "utf8"));
88
126
  } catch (err) {
89
- const msg = err instanceof Error ? err.message : String(err);
90
- console.error(`Failed to read meta-skill "${name}": ${msg}`);
91
- process.exit(1);
127
+ fail(`Failed to read meta-skill "${name}": ${err instanceof Error ? err.message : String(err)}`);
92
128
  }
93
129
  return;
94
130
  }
@@ -131,19 +167,45 @@ function collectPackagingWarnings(root) {
131
167
  }
132
168
  return warnings;
133
169
  }
134
- function cmdValidate(args) {
170
+ function resolvePackageRoot(startDir) {
171
+ let dir = startDir;
172
+ while (true) {
173
+ if (existsSync(join(dir, "package.json"))) return dir;
174
+ const next = dirname(dir);
175
+ if (next === dir) return startDir;
176
+ dir = next;
177
+ }
178
+ }
179
+ function readPackageName(root) {
180
+ try {
181
+ const pkgJson = JSON.parse(readFileSync(join(root, "package.json"), "utf8"));
182
+ return typeof pkgJson.name === "string" ? pkgJson.name : relative(process.cwd(), root) || "unknown";
183
+ } catch {
184
+ return relative(process.cwd(), root) || "unknown";
185
+ }
186
+ }
187
+ async function resolveStaleTargets(targetDir) {
188
+ const resolvedRoot = targetDir ? join(process.cwd(), targetDir) : process.cwd();
189
+ const { checkStaleness } = await import("./staleness-CWWuoPop.mjs");
190
+ if (existsSync(join(resolvedRoot, "skills"))) return { reports: [await checkStaleness(resolvedRoot, readPackageName(resolvedRoot))] };
191
+ const { findPackagesWithSkills, findWorkspaceRoot } = await import("./setup.mjs");
192
+ const workspaceRoot = findWorkspaceRoot(resolvedRoot);
193
+ if (workspaceRoot) {
194
+ const packageDirs = findPackagesWithSkills(workspaceRoot);
195
+ if (packageDirs.length > 0) return { reports: await Promise.all(packageDirs.map((packageDir) => checkStaleness(packageDir, readPackageName(packageDir)))) };
196
+ }
197
+ const staleResult = await scanIntentsOrFail();
198
+ return { reports: await Promise.all(staleResult.packages.map((pkg) => checkStaleness(pkg.packageRoot, pkg.name))) };
199
+ }
200
+ async function cmdValidate(args) {
201
+ const [{ parse: parseYaml }, { findSkillFiles }] = await Promise.all([import("yaml"), import("./utils-XSyO19J6.mjs")]);
135
202
  const targetDir = args[0] ?? "skills";
136
203
  const skillsDir = join(process.cwd(), targetDir);
137
- if (!existsSync(skillsDir)) {
138
- console.error(`Skills directory not found: ${skillsDir}`);
139
- process.exit(1);
140
- }
204
+ const packageRoot = resolvePackageRoot(skillsDir);
205
+ if (!existsSync(skillsDir)) fail(`Skills directory not found: ${skillsDir}`);
141
206
  const errors = [];
142
207
  const skillFiles = findSkillFiles(skillsDir);
143
- if (skillFiles.length === 0) {
144
- console.error("No SKILL.md files found");
145
- process.exit(1);
146
- }
208
+ if (skillFiles.length === 0) fail("No SKILL.md files found");
147
209
  for (const filePath of skillFiles) {
148
210
  const rel = relative(process.cwd(), filePath);
149
211
  const content = readFileSync(filePath, "utf8");
@@ -164,7 +226,7 @@ function cmdValidate(args) {
164
226
  }
165
227
  let fm;
166
228
  try {
167
- fm = parse(match[1]);
229
+ fm = parseYaml(match[1]);
168
230
  } catch {
169
231
  errors.push({
170
232
  file: rel,
@@ -224,7 +286,7 @@ function cmdValidate(args) {
224
286
  continue;
225
287
  }
226
288
  if (fileName.endsWith(".yaml")) try {
227
- parse(content);
289
+ parseYaml(content);
228
290
  } catch {
229
291
  errors.push({
230
292
  file: relative(process.cwd(), artifactPath),
@@ -232,20 +294,11 @@ function cmdValidate(args) {
232
294
  });
233
295
  }
234
296
  }
235
- const warnings = collectPackagingWarnings(process.cwd());
236
- const printWarnings = (log) => {
237
- if (warnings.length === 0) return;
238
- log(`\n⚠ Packaging warnings:`);
239
- for (const w of warnings) log(` ${w}`);
240
- };
241
- if (errors.length > 0) {
242
- console.error(`\n❌ Validation failed with ${errors.length} error(s):\n`);
243
- for (const { file, message } of errors) console.error(` ${file}: ${message}`);
244
- printWarnings(console.error);
245
- process.exit(1);
246
- }
297
+ const warnings = collectPackagingWarnings(packageRoot);
298
+ if (errors.length > 0) fail(buildValidationFailure(errors, warnings));
247
299
  console.log(`✅ Validated ${skillFiles.length} skill files — all passed`);
248
- printWarnings(console.log);
300
+ if (warnings.length > 0) console.log();
301
+ printWarnings(warnings);
249
302
  }
250
303
  function cmdScaffold() {
251
304
  const metaDir = getMetaDir();
@@ -306,13 +359,13 @@ This produces: individual SKILL.md files.
306
359
 
307
360
  ## After all skills are generated
308
361
 
309
- 1. Run \`npx @tanstack/intent validate\` in each package directory
362
+ 1. Run \`intent validate\` in each package directory
310
363
  2. Commit skills/ and artifacts
311
364
  3. For each publishable package, run: \`npx @tanstack/intent add-library-bin\`
312
365
  4. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
313
366
  5. Ensure each package has \`@tanstack/intent\` as a devDependency
314
367
  6. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
315
- 7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent install\`"
368
+ 7. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
316
369
  `;
317
370
  console.log(prompt);
318
371
  }
@@ -327,122 +380,148 @@ Usage:
327
380
  intent add-library-bin Generate bin/intent.{js,mjs} bridge file
328
381
  intent edit-package-json Wire package.json (files, bin) for skill publishing
329
382
  intent setup-github-actions Copy CI workflow templates to .github/workflows/
330
- intent stale Check skills for staleness`;
331
- const command = process.argv[2];
332
- const commandArgs = process.argv.slice(3);
333
- switch (command) {
334
- case "list":
335
- await cmdList(commandArgs);
336
- break;
337
- case "meta":
338
- cmdMeta(commandArgs);
339
- break;
340
- case "validate":
341
- cmdValidate(commandArgs);
342
- break;
343
- case "install":
344
- console.log(`You are an AI assistant helping a developer set up skill-to-task mappings for their project.
345
-
346
- Follow these steps in order:
347
-
348
- 1. CHECK FOR EXISTING MAPPINGS
349
- Search the project's agent config files (CLAUDE.md, AGENTS.md, .cursorrules,
350
- .github/copilot-instructions.md) for a block delimited by:
351
- <!-- intent-skills:start -->
352
- <!-- intent-skills:end -->
353
- - If found: show the user the current mappings and ask "What would you like to update?"
354
- Then skip to step 4 with their requested changes.
355
- - If not found: continue to step 2.
356
-
357
- 2. DISCOVER AVAILABLE SKILLS
358
- Run: intent list
359
- This outputs each skill's name, description, and full path — grouped by package.
360
-
361
- 3. SCAN THE REPOSITORY
362
- Build a picture of the project's structure and patterns:
363
- - Read package.json for library dependencies
364
- - Survey the directory layout (src/, app/, routes/, components/, api/, etc.)
365
- - Note recurring patterns (routing, data fetching, auth, UI components, etc.)
366
-
367
- Based on this, propose 3–5 skill-to-task mappings. For each one explain:
368
- - The task or code area (in plain language the user would recognise)
369
- - Which skill applies and why
370
-
371
- Then ask: "What other tasks do you commonly use AI coding agents for?
372
- I'll create mappings for those too."
373
-
374
- 4. WRITE THE MAPPINGS BLOCK
375
- Once you have the full set of mappings, write or update the agent config file
376
- (prefer CLAUDE.md; create it if none exists) with this exact block:
377
-
378
- <!-- intent-skills:start -->
379
- # Skill mappings — when working in these areas, load the linked skill file into context.
380
- skills:
381
- - task: "describe the task or code area here"
382
- load: "node_modules/package-name/skills/skill-name/SKILL.md"
383
- <!-- intent-skills:end -->
384
-
385
- Rules:
386
- - Use the user's own words for task descriptions
387
- - Include the exact path from \`intent list\` output so agents can load it directly
388
- - Keep entries concise — this block is read on every agent task
389
- - Preserve all content outside the block tags unchanged`);
390
- break;
391
- case "scaffold":
392
- cmdScaffold();
393
- break;
394
- case "stale": {
395
- const { checkStaleness } = await import("./staleness-B5gUj7FR.mjs");
396
- const { scanForIntents: scanStale } = await import("./scanner-DQeiZRzp.mjs");
397
- let staleResult;
398
- try {
399
- staleResult = await scanStale();
400
- } catch (err) {
401
- console.error(err.message);
402
- process.exit(1);
383
+ intent stale [dir] [--json] Check skills for staleness`;
384
+ const HELP_BY_COMMAND = {
385
+ list: `${USAGE}
386
+
387
+ Examples:
388
+ intent list
389
+ intent list --json`,
390
+ meta: `intent meta [name]
391
+
392
+ List shipped meta-skills, or print a single meta-skill by name.
393
+
394
+ Examples:
395
+ intent meta
396
+ intent meta domain-discovery`,
397
+ validate: `intent validate [dir]
398
+
399
+ Validate SKILL.md files in the target directory.
400
+
401
+ Examples:
402
+ intent validate
403
+ intent validate packages/query/skills`,
404
+ install: `intent install
405
+
406
+ Print the install prompt used to set up skill-to-task mappings.`,
407
+ scaffold: `intent scaffold
408
+
409
+ Print the guided maintainer prompt for generating skills.`,
410
+ stale: `intent stale [dir] [--json]
411
+
412
+ Check installed skills for version and source drift.
413
+
414
+ Examples:
415
+ intent stale
416
+ intent stale packages/query
417
+ intent stale --json`,
418
+ "add-library-bin": `intent add-library-bin
419
+
420
+ Generate bin/intent.{js,mjs} bridge files for publishable packages.`,
421
+ "edit-package-json": `intent edit-package-json
422
+
423
+ Update package.json files so skills and shims are published.`,
424
+ "setup-github-actions": `intent setup-github-actions
425
+
426
+ Copy Intent CI workflow templates into .github/workflows/.`
427
+ };
428
+ function isHelpFlag(arg) {
429
+ return arg === "-h" || arg === "--help";
430
+ }
431
+ function printHelp(command) {
432
+ if (!command) {
433
+ console.log(`${USAGE}
434
+
435
+ Run \`intent help <command>\` for details on a specific command.`);
436
+ return;
437
+ }
438
+ console.log(HELP_BY_COMMAND[command] ?? USAGE);
439
+ }
440
+ async function main(argv = process.argv.slice(2)) {
441
+ const command = argv[0];
442
+ const commandArgs = argv.slice(1);
443
+ try {
444
+ if (!command || isHelpFlag(command)) {
445
+ printHelp();
446
+ return 0;
403
447
  }
404
- if (staleResult.packages.length === 0) {
405
- console.log("No intent-enabled packages found.");
406
- break;
448
+ if (command === "help") {
449
+ printHelp(commandArgs[0]);
450
+ return 0;
407
451
  }
408
- const jsonStale = commandArgs.includes("--json");
409
- const reports = await Promise.all(staleResult.packages.map((pkg) => {
410
- return checkStaleness(join(process.cwd(), "node_modules", pkg.name), pkg.name);
411
- }));
412
- if (jsonStale) {
413
- console.log(JSON.stringify(reports, null, 2));
414
- break;
452
+ if (isHelpFlag(commandArgs[0])) {
453
+ printHelp(command);
454
+ return 0;
415
455
  }
416
- for (const report of reports) {
417
- const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
418
- const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
419
- console.log(`${report.library}${vLabel}${driftLabel}`);
420
- const stale = report.skills.filter((s) => s.needsReview);
421
- if (stale.length === 0) console.log(" All skills up-to-date");
422
- else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
423
- console.log();
456
+ switch (command) {
457
+ case "list":
458
+ await cmdList(commandArgs);
459
+ return 0;
460
+ case "meta":
461
+ await cmdMeta(commandArgs);
462
+ return 0;
463
+ case "validate":
464
+ await cmdValidate(commandArgs);
465
+ return 0;
466
+ case "install":
467
+ console.log(INSTALL_PROMPT);
468
+ return 0;
469
+ case "scaffold":
470
+ cmdScaffold();
471
+ return 0;
472
+ case "stale": {
473
+ const jsonStale = commandArgs.includes("--json");
474
+ const { reports } = await resolveStaleTargets(commandArgs.find((arg) => !arg.startsWith("-")));
475
+ if (reports.length === 0) {
476
+ console.log("No intent-enabled packages found.");
477
+ return 0;
478
+ }
479
+ if (jsonStale) {
480
+ console.log(JSON.stringify(reports, null, 2));
481
+ return 0;
482
+ }
483
+ for (const report of reports) {
484
+ const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
485
+ const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
486
+ console.log(`${report.library}${vLabel}${driftLabel}`);
487
+ const stale = report.skills.filter((s) => s.needsReview);
488
+ if (stale.length === 0) console.log(" All skills up-to-date");
489
+ else for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
490
+ console.log();
491
+ }
492
+ return 0;
493
+ }
494
+ case "add-library-bin": {
495
+ const { runAddLibraryBinAll } = await import("./setup.mjs");
496
+ runAddLibraryBinAll(process.cwd());
497
+ return 0;
498
+ }
499
+ case "edit-package-json": {
500
+ const { runEditPackageJsonAll } = await import("./setup.mjs");
501
+ runEditPackageJsonAll(process.cwd());
502
+ return 0;
503
+ }
504
+ case "setup-github-actions": {
505
+ const { runSetupGithubActions } = await import("./setup.mjs");
506
+ runSetupGithubActions(process.cwd(), getMetaDir());
507
+ return 0;
508
+ }
509
+ default:
510
+ printHelp();
511
+ return command ? 1 : 0;
424
512
  }
425
- break;
426
- }
427
- case "add-library-bin": {
428
- const { runAddLibraryBin } = await import("./setup.mjs");
429
- runAddLibraryBin(process.cwd());
430
- break;
431
- }
432
- case "edit-package-json": {
433
- const { runEditPackageJson } = await import("./setup.mjs");
434
- runEditPackageJson(process.cwd());
435
- break;
436
- }
437
- case "setup-github-actions": {
438
- const { runSetupGithubActions } = await import("./setup.mjs");
439
- runSetupGithubActions(process.cwd(), getMetaDir());
440
- break;
513
+ } catch (err) {
514
+ if (isCliFailure(err)) {
515
+ console.error(err.message);
516
+ return err.exitCode;
517
+ }
518
+ throw err;
441
519
  }
442
- default:
443
- console.log(USAGE);
444
- process.exit(command ? 1 : 0);
520
+ }
521
+ if (process.argv[1] !== void 0 && import.meta.url === pathToFileURL(process.argv[1]).href) {
522
+ const exitCode = await main();
523
+ process.exit(exitCode);
445
524
  }
446
525
 
447
526
  //#endregion
448
- export { };
527
+ export { USAGE, main };
@@ -0,0 +1,3 @@
1
+ import { n as printSkillTree, r as printTable, t as computeSkillNameWidth } from "./display-DhsUxNJW.mjs";
2
+
3
+ export { computeSkillNameWidth, printSkillTree, printTable };
package/dist/index.d.mts CHANGED
@@ -1,5 +1,5 @@
1
- import { a as IntentProjectConfig, c as ScanResult, d as StalenessReport, i as IntentPackage, l as SkillEntry, n as FeedbackPayload, o as MetaFeedbackPayload, r as IntentConfig, s as MetaSkillName, t as AgentName, u as SkillStaleness } from "./types-BmnI8kFB.mjs";
2
- import { a as runEditPackageJson, i as runAddLibraryBin, n as EditPackageJsonResult, o as runSetupGithubActions, r as SetupGithubActionsResult, t as AddLibraryBinResult } from "./setup-CANkTz55.mjs";
1
+ import { a as IntentProjectConfig, c as ScanResult, d as StalenessReport, i as IntentPackage, l as SkillEntry, n as FeedbackPayload, o as MetaFeedbackPayload, r as IntentConfig, s as MetaSkillName, t as AgentName, u as SkillStaleness } from "./types-ddLtccfV.mjs";
2
+ import { c as runAddLibraryBin, f as runSetupGithubActions, i as SetupGithubActionsResult, n as EditPackageJsonResult, t as AddLibraryBinResult, u as runEditPackageJson } from "./setup-6m3IfxyO.mjs";
3
3
 
4
4
  //#region src/scanner.d.ts
5
5
  declare function scanForIntents(root?: string): Promise<ScanResult>;
@@ -13,11 +13,11 @@ declare function hasGhCli(): boolean;
13
13
  declare function resolveFrequency(root: string): string;
14
14
  declare function validatePayload(payload: unknown): {
15
15
  valid: boolean;
16
- errors: string[];
16
+ errors: Array<string>;
17
17
  };
18
18
  declare function validateMetaPayload(payload: unknown): {
19
19
  valid: boolean;
20
- errors: string[];
20
+ errors: Array<string>;
21
21
  };
22
22
  declare function metaToMarkdown(payload: MetaFeedbackPayload): string;
23
23
  declare function toMarkdown(payload: FeedbackPayload): string;
@@ -38,10 +38,22 @@ declare function submitMetaFeedback(payload: MetaFeedbackPayload, opts: {
38
38
  /**
39
39
  * Recursively find all SKILL.md files under a directory.
40
40
  */
41
- declare function findSkillFiles(dir: string): string[];
41
+ declare function findSkillFiles(dir: string): Array<string>;
42
+ /**
43
+ * Read dependencies and peerDependencies (and optionally devDependencies) from
44
+ * a parsed package.json object.
45
+ */
46
+ declare function getDeps(pkgJson: Record<string, unknown>, includeDevDeps?: boolean): Array<string>;
47
+ /**
48
+ * Resolve the directory of a dependency by name. First checks the top-level
49
+ * node_modules (hoisted layout — npm, yarn, bun), then resolves through the
50
+ * parent package's real path to handle pnpm's virtual store layout where
51
+ * transitive deps are siblings in the .pnpm virtual store node_modules.
52
+ */
53
+ declare function resolveDepDir(depName: string, parentDir: string, parentName: string, nodeModulesDirs: string | Array<string>): string | null;
42
54
  /**
43
55
  * Parse YAML frontmatter from a file. Returns null if no frontmatter or on error.
44
56
  */
45
57
  declare function parseFrontmatter(filePath: string): Record<string, unknown> | null;
46
58
  //#endregion
47
- export { type AddLibraryBinResult, type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
59
+ export { type AddLibraryBinResult, type AgentName, type EditPackageJsonResult, type FeedbackPayload, type IntentConfig, type IntentPackage, type IntentProjectConfig, type MetaFeedbackPayload, type MetaSkillName, type ScanResult, type SetupGithubActionsResult, type SkillEntry, type SkillStaleness, type StalenessReport, checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
package/dist/index.mjs CHANGED
@@ -1,7 +1,7 @@
1
- import { n as parseFrontmatter, t as findSkillFiles } from "./utils-DH3jY3CI.mjs";
2
- import { t as scanForIntents } from "./scanner-dIYdkHQ1.mjs";
3
- import { t as checkStaleness } from "./staleness-lP6B0O4z.mjs";
4
- import { n as runEditPackageJson, r as runSetupGithubActions, t as runAddLibraryBin } from "./setup-BYOg-Ii-.mjs";
1
+ import { a as parseFrontmatter, n as findSkillFiles, o as resolveDepDir, r as getDeps } from "./utils-DY1eH2E_.mjs";
2
+ import { t as scanForIntents } from "./scanner-f82qRq7h.mjs";
3
+ import { t as checkStaleness } from "./staleness-D_ZiK4Tf.mjs";
4
+ import { c as runSetupGithubActions, i as runAddLibraryBin, o as runEditPackageJson } from "./setup-CncHbQlb.mjs";
5
5
  import { readFileSync, writeFileSync } from "node:fs";
6
6
  import { join } from "node:path";
7
7
  import { execFileSync, execSync } from "node:child_process";
@@ -31,17 +31,26 @@ function hasGhCli() {
31
31
  function getHomeConfigDir() {
32
32
  return process.env.XDG_CONFIG_HOME ?? join(process.env.HOME ?? process.env.USERPROFILE ?? "", ".config");
33
33
  }
34
- function resolveFrequency(root) {
35
- const userConfigPath = join(getHomeConfigDir(), "intent", "config.json");
36
- try {
37
- const userCfg = JSON.parse(readFileSync(userConfigPath, "utf8"));
38
- if (userCfg.feedback?.frequency) return userCfg.feedback.frequency;
39
- } catch {}
40
- const projectConfigPath = join(root, "intent.config.json");
34
+ function parseFrequency(value) {
35
+ if (value === "always" || value === "never") return value;
36
+ if (typeof value !== "string") return null;
37
+ const match = /^every-(\d+)$/.exec(value);
38
+ if (!match) return null;
39
+ const count = Number(match[1]);
40
+ return Number.isInteger(count) && count > 0 ? `every-${count}` : null;
41
+ }
42
+ function readFrequency(filePath) {
41
43
  try {
42
- const projCfg = JSON.parse(readFileSync(projectConfigPath, "utf8"));
43
- if (projCfg.feedback?.frequency) return projCfg.feedback.frequency;
44
- } catch {}
44
+ return parseFrequency(JSON.parse(readFileSync(filePath, "utf8")).feedback?.frequency);
45
+ } catch {
46
+ return null;
47
+ }
48
+ }
49
+ function resolveFrequency(root) {
50
+ const userFrequency = readFrequency(join(getHomeConfigDir(), "intent", "config.json"));
51
+ if (userFrequency) return userFrequency;
52
+ const projectFrequency = readFrequency(join(root, "intent.config.json"));
53
+ if (projectFrequency) return projectFrequency;
45
54
  return "every-5";
46
55
  }
47
56
  const REQUIRED_FIELDS = [
@@ -102,6 +111,18 @@ const VALID_QUALITY_RATINGS = [
102
111
  "mixed",
103
112
  "bad"
104
113
  ];
114
+ const VALID_INTERVIEW_QUALITY_RATINGS = [
115
+ "good",
116
+ "mixed",
117
+ "bad",
118
+ "skipped"
119
+ ];
120
+ const VALID_FAILURE_MODE_QUALITY_RATINGS = [
121
+ "good",
122
+ "mixed",
123
+ "bad",
124
+ "not-applicable"
125
+ ];
105
126
  function validateMetaPayload(payload) {
106
127
  const errors = [];
107
128
  if (!payload || typeof payload !== "object") return {
@@ -114,6 +135,8 @@ function validateMetaPayload(payload) {
114
135
  if (obj.agentUsed && !VALID_AGENTS.includes(obj.agentUsed)) errors.push(`agentUsed must be one of: ${VALID_AGENTS.join(", ")}`);
115
136
  if (obj.artifactQuality && !VALID_QUALITY_RATINGS.includes(obj.artifactQuality)) errors.push("artifactQuality must be one of: good, mixed, bad");
116
137
  if (obj.userRating && !VALID_QUALITY_RATINGS.includes(obj.userRating)) errors.push("userRating must be one of: good, mixed, bad");
138
+ if (obj.interviewQuality && !VALID_INTERVIEW_QUALITY_RATINGS.includes(obj.interviewQuality)) errors.push("interviewQuality must be one of: good, mixed, bad, skipped");
139
+ if (obj.failureModeQuality && !VALID_FAILURE_MODE_QUALITY_RATINGS.includes(obj.failureModeQuality)) errors.push("failureModeQuality must be one of: good, mixed, bad, not-applicable");
117
140
  if (containsSecrets(Object.values(obj).filter((v) => typeof v === "string").join("\n"))) errors.push("Payload appears to contain secrets or tokens — submission rejected");
118
141
  return {
119
142
  valid: errors.length === 0,
@@ -246,4 +269,4 @@ function submitMetaFeedback(payload, opts) {
246
269
  }
247
270
 
248
271
  //#endregion
249
- export { checkStaleness, containsSecrets, findSkillFiles, hasGhCli, metaToMarkdown, parseFrontmatter, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };
272
+ export { checkStaleness, containsSecrets, findSkillFiles, getDeps, hasGhCli, metaToMarkdown, parseFrontmatter, resolveDepDir, resolveFrequency, runAddLibraryBin, runEditPackageJson, runSetupGithubActions, scanForIntents, submitFeedback, submitMetaFeedback, toMarkdown, validateMetaPayload, validatePayload };