@tanstack/intent 0.0.36 → 0.0.38

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 (54) hide show
  1. package/dist/artifact-coverage-DA26utB1.mjs +3 -0
  2. package/dist/cli-error-BrMXlbtx.mjs +15 -0
  3. package/dist/cli-support-BON5hn4L.mjs +114 -0
  4. package/dist/cli-support-BlSsqyx7.mjs +6 -0
  5. package/dist/cli.mjs +17 -763
  6. package/dist/core-baYs6H7Z.mjs +497 -0
  7. package/dist/core.d.mts +85 -0
  8. package/dist/core.mjs +9 -0
  9. package/dist/display-COlw5FaB.mjs +5 -0
  10. package/dist/{display-CAof6doy.mjs → display-CVeoAwBd.mjs} +1 -1
  11. package/dist/edit-package-json-CzWlMXOf.mjs +8 -0
  12. package/dist/index.d.mts +5 -2
  13. package/dist/index.mjs +11 -11
  14. package/dist/{install-2_wkomiT.mjs → install-BPWtaOuo.mjs} +7 -111
  15. package/dist/install-RZpz279M.mjs +7 -0
  16. package/dist/intent-library.mjs +8 -7
  17. package/dist/{library-scanner-fexXlPXb.mjs → library-scanner-CHepLJQJ.mjs} +2 -2
  18. package/dist/library-scanner.d.mts +1 -1
  19. package/dist/library-scanner.mjs +3 -3
  20. package/dist/list-iLIL-EO3.mjs +107 -0
  21. package/dist/load-8868G50-.mjs +70 -0
  22. package/dist/meta-CYV9EzM8.mjs +38 -0
  23. package/dist/{project-context-alYMNoNa.mjs → project-context-Dx6XIJJo.mjs} +1 -1
  24. package/dist/resolver-CP0S8UjZ.mjs +196 -0
  25. package/dist/scaffold-D2vwv9ls.mjs +75 -0
  26. package/dist/scanner-ByG70-E3.mjs +6 -0
  27. package/dist/{scanner-B1j-wDhj.mjs → scanner-DwYsjXzI.mjs} +101 -19
  28. package/dist/{setup-t1i2o2-h.d.mts → setup-2SE9zYJk.d.mts} +1 -0
  29. package/dist/setup-github-actions-emXSyGy3.mjs +8 -0
  30. package/dist/{setup-Dp-W8y0Y.mjs → setup-kvWN4xCr.mjs} +2 -2
  31. package/dist/setup.d.mts +1 -1
  32. package/dist/setup.mjs +4 -4
  33. package/dist/{skill-paths-8k9K9y26.mjs → skill-paths-DNOHrvL5.mjs} +1 -1
  34. package/dist/stale-flPZnWfI.mjs +53 -0
  35. package/dist/{staleness-PdgakrCQ.mjs → staleness-CFr3W-RI.mjs} +2 -2
  36. package/dist/staleness-DpyuNdd5.mjs +5 -0
  37. package/dist/{types-DT7Y6TFz.d.mts → types-S2zpibHp.d.mts} +1 -1
  38. package/dist/{utils-dkVvY7D7.mjs → utils-BHzSyNeJ.mjs} +1 -1
  39. package/dist/validate-BL1SYAwh.mjs +271 -0
  40. package/dist/{workflow-review-Dz_ofcYQ.mjs → workflow-review-CIdJXmKP.mjs} +1 -1
  41. package/dist/workspace-patterns-BWMz7TsI.mjs +4 -0
  42. package/dist/workspace-patterns-BZLEaMcS.mjs +195 -0
  43. package/package.json +9 -4
  44. package/dist/artifact-coverage-BAN2W6aH.mjs +0 -3
  45. package/dist/display-B3vkG99D.mjs +0 -5
  46. package/dist/resolver-Whd12ksO.mjs +0 -70
  47. package/dist/scanner-C2YjF4w_.mjs +0 -6
  48. package/dist/staleness-DpbmYod4.mjs +0 -5
  49. package/dist/workspace-patterns-BN2A_60g.mjs +0 -172
  50. package/dist/workspace-patterns-x-dLZxx4.mjs +0 -4
  51. /package/dist/{artifact-coverage-wLNVX8yC.mjs → artifact-coverage-DgWuVqUp.mjs} +0 -0
  52. /package/dist/{skill-use-BzuuvLM7.mjs → skill-use-umYvZl94.mjs} +0 -0
  53. /package/dist/{utils-COlDcU72.mjs → utils-mdb4i6VA.mjs} +0 -0
  54. /package/dist/{workflow-review-CwkPVIQf.mjs → workflow-review-CwcR2ge4.mjs} +0 -0
@@ -0,0 +1,75 @@
1
+ import { join } from "node:path";
2
+
3
+ //#region src/commands/scaffold.ts
4
+ function runScaffoldCommand(metaDir) {
5
+ function metaSkillPath(name) {
6
+ return join(metaDir, name, "SKILL.md");
7
+ }
8
+ const prompt = `You are helping a library maintainer scaffold Intent skills.
9
+
10
+ Run the three meta skills below **one at a time, in order**. For each step:
11
+ 1. Load the SKILL.md file specified
12
+ 2. Follow its instructions completely
13
+ 3. Present outputs to the maintainer for review
14
+ 4. Do NOT proceed to the next step until the maintainer confirms
15
+
16
+ ## Before you start
17
+
18
+ Gather this context yourself (do not ask the maintainer — agents should never
19
+ ask for information they can discover):
20
+ 1. Read package.json for library name, repository URL, and homepage/docs URL
21
+ 2. Detect if this is a monorepo (look for workspaces field, packages/ directory, lerna.json)
22
+ 3. Use skills/ as the default skills root
23
+ 4. For monorepos:
24
+ - Domain map artifacts go at the REPO ROOT: _artifacts/
25
+ - Skills go INSIDE EACH PACKAGE: packages/<pkg>/skills/
26
+ - Identify which packages are client-facing (usually client SDKs and primary framework adapters)
27
+
28
+ ---
29
+
30
+ ## Step 1 — Domain Discovery
31
+
32
+ Load and follow: ${metaSkillPath("domain-discovery")}
33
+
34
+ This produces: domain_map.yaml and skill_spec.md in the artifacts directory.
35
+ Domain discovery covers the WHOLE library (one domain map even for monorepos).
36
+
37
+ **STOP. Review outputs with the maintainer before continuing.**
38
+
39
+ ---
40
+
41
+ ## Step 2 — Tree Generator
42
+
43
+ Load and follow: ${metaSkillPath("tree-generator")}
44
+
45
+ This produces: skill_tree.yaml in the artifacts directory.
46
+ For monorepos, each skill entry should include a \`package\` field.
47
+
48
+ **STOP. Review outputs with the maintainer before continuing.**
49
+
50
+ ---
51
+
52
+ ## Step 3 — Generate Skills
53
+
54
+ Load and follow: ${metaSkillPath("generate-skill")}
55
+
56
+ This produces: individual SKILL.md files.
57
+ - Single-repo: skills/<domain>/<skill>/SKILL.md
58
+ - Monorepo: packages/<pkg>/skills/<domain>/<skill>/SKILL.md
59
+
60
+ ---
61
+
62
+ ## After all skills are generated
63
+
64
+ 1. Run \`intent validate\` in each package directory
65
+ 2. Commit skills/ and artifacts
66
+ 3. For each publishable package, run: \`npx @tanstack/intent edit-package-json\`
67
+ 4. Ensure each package has \`@tanstack/intent\` as a devDependency
68
+ 5. Create a \`skill:<skill-name>\` label on the GitHub repo for each skill (use \`gh label create\`)
69
+ 6. Add a README note: "If you use an AI agent, run \`npx @tanstack/intent@latest install\`"
70
+ `;
71
+ console.log(prompt);
72
+ }
73
+
74
+ //#endregion
75
+ export { runScaffoldCommand };
@@ -0,0 +1,6 @@
1
+ import "./utils-mdb4i6VA.mjs";
2
+ import "./skill-paths-DNOHrvL5.mjs";
3
+ import { n as scanIntentPackageAtRoot, t as scanForIntents } from "./scanner-DwYsjXzI.mjs";
4
+ import "./workspace-patterns-BZLEaMcS.mjs";
5
+
6
+ export { scanForIntents };
@@ -1,9 +1,9 @@
1
- import { a as parseFrontmatter, i as listNodeModulesPackageDirs, o as resolveDepDir, r as getDeps, s as toPosixPath, t as detectGlobalNodeModules } from "./utils-COlDcU72.mjs";
2
- import { r as rewriteSkillLoadPaths } from "./skill-paths-8k9K9y26.mjs";
3
- import { a as resolveWorkspacePackages, i as readWorkspacePatterns, r as findWorkspaceRoot } from "./workspace-patterns-BN2A_60g.mjs";
1
+ import { a as parseFrontmatter, i as listNodeModulesPackageDirs, o as resolveDepDir, r as getDeps, s as toPosixPath, t as detectGlobalNodeModules } from "./utils-mdb4i6VA.mjs";
2
+ import { r as rewriteSkillLoadPaths } from "./skill-paths-DNOHrvL5.mjs";
3
+ import { a as readWorkspacePatterns, o as resolveWorkspacePackages, r as findWorkspaceRoot } from "./workspace-patterns-BZLEaMcS.mjs";
4
4
  import { createRequire } from "node:module";
5
5
  import { existsSync, readFileSync, readdirSync } from "node:fs";
6
- import { dirname, join, relative, resolve, sep } from "node:path";
6
+ import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
7
7
 
8
8
  //#region src/discovery/register.ts
9
9
  function isLocalToProject(dirPath, projectRoot) {
@@ -232,7 +232,35 @@ function deriveIntentConfig(pkgJson) {
232
232
  requires
233
233
  };
234
234
  }
235
- function discoverSkills(skillsDir, _baseName) {
235
+ function readSkillEntry(skillsDir, childDir, skillFile) {
236
+ const fm = parseFrontmatter(skillFile);
237
+ const relName = toPosixPath(relative(skillsDir, childDir));
238
+ const desc = typeof fm?.description === "string" ? fm.description.replace(/\s+/g, " ").trim() : "";
239
+ return {
240
+ name: typeof fm?.name === "string" ? fm.name : relName,
241
+ path: skillFile,
242
+ description: desc,
243
+ type: typeof fm?.type === "string" ? fm.type : void 0,
244
+ framework: typeof fm?.framework === "string" ? fm.framework : void 0
245
+ };
246
+ }
247
+ function discoverSkillByNameHint(skillsDir, packageName, skillNameHint) {
248
+ const skills = [];
249
+ const seen = /* @__PURE__ */ new Set();
250
+ const skillNameHints = getSkillNameHints(packageName, skillNameHint);
251
+ for (const hint of skillNameHints) {
252
+ const resolvedHint = resolveSkillNameHintPath(skillsDir, hint);
253
+ if (!resolvedHint) continue;
254
+ const { childDir, skillFile } = resolvedHint;
255
+ if (!existsSync(skillFile)) continue;
256
+ const skill = readSkillEntry(skillsDir, childDir, skillFile);
257
+ if (skill.name !== hint || seen.has(skill.name)) continue;
258
+ seen.add(skill.name);
259
+ skills.push(skill);
260
+ }
261
+ return skills;
262
+ }
263
+ function discoverSkills(skillsDir) {
236
264
  const skills = [];
237
265
  function walk(dir) {
238
266
  let entries;
@@ -248,24 +276,37 @@ function discoverSkills(skillsDir, _baseName) {
248
276
  if (!entry.isDirectory()) continue;
249
277
  const childDir = join(dir, entry.name);
250
278
  const skillFile = join(childDir, "SKILL.md");
251
- if (existsSync(skillFile)) {
252
- const fm = parseFrontmatter(skillFile);
253
- const relName = toPosixPath(relative(skillsDir, childDir));
254
- const desc = typeof fm?.description === "string" ? fm.description.replace(/\s+/g, " ").trim() : "";
255
- skills.push({
256
- name: typeof fm?.name === "string" ? fm.name : relName,
257
- path: skillFile,
258
- description: desc,
259
- type: typeof fm?.type === "string" ? fm.type : void 0,
260
- framework: typeof fm?.framework === "string" ? fm.framework : void 0
261
- });
262
- }
279
+ if (existsSync(skillFile)) skills.push(readSkillEntry(skillsDir, childDir, skillFile));
263
280
  walk(childDir);
264
281
  }
265
282
  }
266
283
  walk(skillsDir);
267
284
  return skills;
268
285
  }
286
+ function getPackageShortName(packageName) {
287
+ return packageName.split("/").pop() ?? packageName;
288
+ }
289
+ function isWithinOrEqual(path, parentDir) {
290
+ const rel = relative(parentDir, path);
291
+ return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
292
+ }
293
+ function resolveSkillNameHintPath(skillsDir, hint) {
294
+ if (hint.startsWith("/") || hint.startsWith("\\")) return null;
295
+ const parts = hint.split("/");
296
+ if (parts.some((part) => part === "" || part === "." || part === ".." || part.includes("\\"))) return null;
297
+ const resolvedSkillsDir = resolve(skillsDir);
298
+ const childDir = resolve(resolvedSkillsDir, ...parts);
299
+ if (!isWithinOrEqual(childDir, resolvedSkillsDir)) return null;
300
+ return {
301
+ childDir,
302
+ skillFile: join(childDir, "SKILL.md")
303
+ };
304
+ }
305
+ function getSkillNameHints(packageName, skillNameHint) {
306
+ const packageShortName = getPackageShortName(packageName);
307
+ if (skillNameHint.startsWith(`${packageShortName}/`)) return [skillNameHint];
308
+ return [skillNameHint, `${packageShortName}/${skillNameHint}`];
309
+ }
269
310
  function topoSort(packages) {
270
311
  const byName = new Map(packages.map((p) => [p.name, p]));
271
312
  const visited = /* @__PURE__ */ new Set();
@@ -460,10 +501,15 @@ function scanForIntents(root, options = {}) {
460
501
  }
461
502
  }
462
503
  assertLocalNodeModulesSupported(projectRoot);
463
- scanTarget(nodeModules.local);
464
504
  walkWorkspacePackages();
505
+ const packageCountBeforeDependencyDiscovery = packages.length;
506
+ scanTarget(nodeModules.local);
465
507
  walkKnownPackages();
466
508
  walkProjectDeps();
509
+ if (packages.length === packageCountBeforeDependencyDiscovery) {
510
+ const api = getPnpApi();
511
+ if (api) scanPnpPackages(api);
512
+ }
467
513
  }
468
514
  function scanGlobalPackages() {
469
515
  ensureGlobalNodeModules();
@@ -506,6 +552,42 @@ function scanForIntents(root, options = {}) {
506
552
  nodeModules
507
553
  };
508
554
  }
555
+ function scanIntentPackageAtRoot(packageRoot, options = {}) {
556
+ const projectRoot = options.projectRoot ?? packageRoot;
557
+ const packages = [];
558
+ const warnings = [];
559
+ const packageIndexes = /* @__PURE__ */ new Map();
560
+ const packageJsonCache = /* @__PURE__ */ new Map();
561
+ function readPkgJson(dirPath) {
562
+ if (packageJsonCache.has(dirPath)) return packageJsonCache.get(dirPath) ?? null;
563
+ try {
564
+ const pkgJson = JSON.parse(readFileSync(join(dirPath, "package.json"), "utf8"));
565
+ packageJsonCache.set(dirPath, pkgJson);
566
+ return pkgJson;
567
+ } catch {
568
+ packageJsonCache.set(dirPath, null);
569
+ return null;
570
+ }
571
+ }
572
+ const { tryRegister } = createPackageRegistrar({
573
+ comparePackageVersions,
574
+ deriveIntentConfig,
575
+ discoverSkills: options.skillNameHint ? (skillsDir, packageName) => discoverSkillByNameHint(skillsDir, packageName, options.skillNameHint) : discoverSkills,
576
+ getPackageDepth,
577
+ packageIndexes,
578
+ packages,
579
+ projectRoot,
580
+ readPkgJson,
581
+ rememberVariant() {},
582
+ validateIntentField,
583
+ warnings
584
+ });
585
+ tryRegister(packageRoot, options.fallbackName ?? "unknown", options.source ?? "local");
586
+ return {
587
+ package: packages[0] ?? null,
588
+ warnings
589
+ };
590
+ }
509
591
 
510
592
  //#endregion
511
- export { scanForIntents as t };
593
+ export { scanIntentPackageAtRoot as n, scanForIntents as t };
@@ -1,4 +1,5 @@
1
1
  //#region src/workspace-patterns.d.ts
2
+
2
3
  declare function readWorkspacePatterns(root: string): Array<string> | null;
3
4
  declare function resolveWorkspacePackages(root: string, patterns: Array<string>): Array<string>;
4
5
  declare function findWorkspaceRoot(start: string): string | null;
@@ -0,0 +1,8 @@
1
+ //#region src/commands/setup-github-actions.ts
2
+ async function runSetupGithubActionsCommand(root, metaDir) {
3
+ const { runSetupGithubActions } = await import("./setup.mjs");
4
+ runSetupGithubActions(root, metaDir);
5
+ }
6
+
7
+ //#endregion
8
+ export { runSetupGithubActionsCommand };
@@ -1,5 +1,5 @@
1
- import { i as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BN2A_60g.mjs";
2
- import { t as resolveProjectContext } from "./project-context-alYMNoNa.mjs";
1
+ import { a as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BZLEaMcS.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-Dx6XIJJo.mjs";
3
3
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
4
  import { basename, join, relative } from "node:path";
5
5
 
package/dist/setup.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as runEditPackageJsonAll, c as findWorkspaceRoot, i as runEditPackageJson, l as readWorkspacePatterns, n as MonorepoResult, o as runSetupGithubActions, r as SetupGithubActionsResult, s as findPackagesWithSkills, t as EditPackageJsonResult, u as resolveWorkspacePackages } from "./setup-t1i2o2-h.mjs";
1
+ import { a as runEditPackageJsonAll, c as findWorkspaceRoot, i as runEditPackageJson, l as readWorkspacePatterns, n as MonorepoResult, o as runSetupGithubActions, r as SetupGithubActionsResult, s as findPackagesWithSkills, t as EditPackageJsonResult, u as resolveWorkspacePackages } from "./setup-2SE9zYJk.mjs";
2
2
  export { EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
package/dist/setup.mjs CHANGED
@@ -1,6 +1,6 @@
1
- import "./utils-COlDcU72.mjs";
2
- import { a as resolveWorkspacePackages, i as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BN2A_60g.mjs";
3
- import "./project-context-alYMNoNa.mjs";
4
- import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-Dp-W8y0Y.mjs";
1
+ import "./utils-mdb4i6VA.mjs";
2
+ import { a as readWorkspacePatterns, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BZLEaMcS.mjs";
3
+ import "./project-context-Dx6XIJJo.mjs";
4
+ import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-kvWN4xCr.mjs";
5
5
 
6
6
  export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
@@ -1,4 +1,4 @@
1
- import { s as toPosixPath } from "./utils-COlDcU72.mjs";
1
+ import { s as toPosixPath } from "./utils-mdb4i6VA.mjs";
2
2
  import { existsSync } from "node:fs";
3
3
  import { join, relative } from "node:path";
4
4
 
@@ -0,0 +1,53 @@
1
+ //#region src/commands/stale.ts
2
+ async function runStaleCommand(targetDir, options, resolveStaleTargets) {
3
+ if (options.githubReview) {
4
+ await runGithubReview(targetDir, options, resolveStaleTargets);
5
+ return;
6
+ }
7
+ const { reports, workflowAdvisories = [] } = await resolveStaleTargets(targetDir);
8
+ if (options.json) {
9
+ console.log(JSON.stringify(reports, null, 2));
10
+ return;
11
+ }
12
+ for (const advisory of workflowAdvisories) console.log(advisory);
13
+ if (workflowAdvisories.length > 0) console.log();
14
+ if (reports.length === 0) {
15
+ console.log("No intent-enabled packages found.");
16
+ return;
17
+ }
18
+ for (const report of reports) {
19
+ const driftLabel = report.versionDrift ? ` [${report.versionDrift} drift]` : "";
20
+ const vLabel = report.skillVersion && report.currentVersion ? ` (${report.skillVersion} → ${report.currentVersion})` : "";
21
+ console.log(`${report.library}${vLabel}${driftLabel}`);
22
+ const stale = report.skills.filter((skill) => skill.needsReview);
23
+ const signals = report.signals.filter((signal) => signal.needsReview);
24
+ if (stale.length === 0 && signals.length === 0) console.log(" All skills up-to-date");
25
+ else {
26
+ for (const skill of stale) console.log(` ⚠ ${skill.name}: ${skill.reasons.join(", ")}`);
27
+ for (const signal of signals) {
28
+ const subject = signal.packageName ?? signal.packageRoot ?? signal.skill ?? signal.artifactPath ?? signal.subject ?? report.library;
29
+ console.log(` ⚠ ${subject}: ${signal.reasons.join(", ")}`);
30
+ }
31
+ }
32
+ console.log();
33
+ }
34
+ }
35
+ async function runGithubReview(targetDir, options, resolveStaleTargets) {
36
+ const { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles } = await import("./workflow-review-CIdJXmKP.mjs");
37
+ const packageLabel = options.packageLabel ?? "workspace";
38
+ try {
39
+ const { reports, workflowAdvisories = [] } = await resolveStaleTargets(targetDir);
40
+ const items = [...collectStaleReviewItems(reports), ...createWorkflowAdvisoryReviewItems(packageLabel, workflowAdvisories)];
41
+ writeStaleReviewWorkflowFiles(items);
42
+ if (items.length === 0) console.log("No stale skills or coverage gaps found.");
43
+ else console.log(`Wrote ${items.length} intent skill review item(s).`);
44
+ } catch (err) {
45
+ writeStaleReviewWorkflowFiles([createFailedStaleReviewItem(packageLabel)]);
46
+ const message = err instanceof Error ? err.message : String(err);
47
+ console.log(`Intent stale check failed: ${message}`);
48
+ console.log("Wrote a review PR body so maintainers can inspect the logs.");
49
+ }
50
+ }
51
+
52
+ //#endregion
53
+ export { runStaleCommand };
@@ -1,5 +1,5 @@
1
- import { a as parseFrontmatter, n as findSkillFiles } from "./utils-COlDcU72.mjs";
2
- import { t as readIntentArtifacts } from "./artifact-coverage-wLNVX8yC.mjs";
1
+ import { a as parseFrontmatter, n as findSkillFiles } from "./utils-mdb4i6VA.mjs";
2
+ import { t as readIntentArtifacts } from "./artifact-coverage-DgWuVqUp.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { isAbsolute, join, relative, resolve, sep } from "node:path";
5
5
 
@@ -0,0 +1,5 @@
1
+ import "./utils-mdb4i6VA.mjs";
2
+ import "./artifact-coverage-DgWuVqUp.mjs";
3
+ import { n as checkStaleness, r as readPackageName, t as buildWorkspaceCoverageSignals } from "./staleness-CFr3W-RI.mjs";
4
+
5
+ export { buildWorkspaceCoverageSignals, checkStaleness, readPackageName };
@@ -143,4 +143,4 @@ interface IntentProjectConfig {
143
143
  };
144
144
  }
145
145
  //#endregion
146
- export { StalenessReport as _, IntentArtifactSet as a, IntentConfig as c, MetaFeedbackPayload as d, MetaSkillName as f, SkillStaleness as g, SkillEntry as h, IntentArtifactFile as i, IntentPackage as l, ScanResult as m, FeedbackPayload as n, IntentArtifactSkill as o, ScanOptions as p, IntentArtifactCoverageIgnore as r, IntentArtifactWarning as s, AgentName as t, IntentProjectConfig as u, StalenessSignal as v, VersionConflict as y };
146
+ export { SkillStaleness as _, IntentArtifactSet as a, VersionConflict as b, IntentConfig as c, MetaFeedbackPayload as d, MetaSkillName as f, SkillEntry as g, ScanScope as h, IntentArtifactFile as i, IntentPackage as l, ScanResult as m, FeedbackPayload as n, IntentArtifactSkill as o, ScanOptions as p, IntentArtifactCoverageIgnore as r, IntentArtifactWarning as s, AgentName as t, IntentProjectConfig as u, StalenessReport as v, StalenessSignal as y };
@@ -1,3 +1,3 @@
1
- import { a as parseFrontmatter, i as listNodeModulesPackageDirs, n as findSkillFiles, o as resolveDepDir, r as getDeps, s as toPosixPath, t as detectGlobalNodeModules } from "./utils-COlDcU72.mjs";
1
+ import { a as parseFrontmatter, i as listNodeModulesPackageDirs, n as findSkillFiles, o as resolveDepDir, r as getDeps, s as toPosixPath, t as detectGlobalNodeModules } from "./utils-mdb4i6VA.mjs";
2
2
 
3
3
  export { detectGlobalNodeModules, findSkillFiles, getDeps, listNodeModulesPackageDirs, parseFrontmatter, resolveDepDir, toPosixPath };
@@ -0,0 +1,271 @@
1
+ import "./utils-mdb4i6VA.mjs";
2
+ import { n as findWorkspacePackages } from "./workspace-patterns-BZLEaMcS.mjs";
3
+ import { t as resolveProjectContext } from "./project-context-Dx6XIJJo.mjs";
4
+ import { n as isCliFailure, t as fail } from "./cli-error-BrMXlbtx.mjs";
5
+ import { l as printWarnings } from "./cli-support-BON5hn4L.mjs";
6
+ import { appendFileSync, existsSync, readFileSync } from "node:fs";
7
+ import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
+
9
+ //#region src/commands/validate.ts
10
+ const agentSkillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
11
+ function buildValidationFailure(errors, warnings) {
12
+ const lines = [
13
+ "",
14
+ `❌ Validation failed with ${errors.length} error(s):`,
15
+ ""
16
+ ];
17
+ for (const { file, message } of errors) lines.push(` ${file}: ${message}`);
18
+ if (warnings.length > 0) {
19
+ lines.push("", "⚠ Packaging warnings:");
20
+ for (const warning of warnings) lines.push(` ${warning}`);
21
+ }
22
+ return lines.join("\n");
23
+ }
24
+ function collectPackagingWarnings(context) {
25
+ if (!context.packageRoot || !context.targetPackageJsonPath) return [];
26
+ const pkgJsonPath = context.targetPackageJsonPath;
27
+ if (!existsSync(pkgJsonPath)) return [];
28
+ let pkgJson;
29
+ try {
30
+ pkgJson = JSON.parse(readFileSync(pkgJsonPath, "utf8"));
31
+ } catch (err) {
32
+ return [`Could not parse package.json: ${err instanceof Error ? err.message : String(err)}`];
33
+ }
34
+ const warnings = [];
35
+ if (!pkgJson.devDependencies?.["@tanstack/intent"]) warnings.push("@tanstack/intent is not in devDependencies");
36
+ const keywords = pkgJson.keywords;
37
+ if (!Array.isArray(keywords) || !keywords.includes("tanstack-intent")) warnings.push("Missing \"tanstack-intent\" in keywords array");
38
+ const files = pkgJson.files;
39
+ if (Array.isArray(files)) {
40
+ if (!files.includes("skills")) warnings.push("\"skills\" is not in the \"files\" array — skills won't be published");
41
+ if (!context.isMonorepo && !files.includes("!skills/_artifacts")) warnings.push("\"!skills/_artifacts\" is not in the \"files\" array — artifacts will be published unnecessarily");
42
+ }
43
+ return warnings;
44
+ }
45
+ function formatWarning({ file, message }) {
46
+ return `${file}: ${message}`;
47
+ }
48
+ function isRecord(value) {
49
+ return !!value && typeof value === "object" && !Array.isArray(value);
50
+ }
51
+ function collectAgentSkillSpecWarnings({ filePath, fm, rel }) {
52
+ const warnings = [];
53
+ if (typeof fm.name === "string") {
54
+ if (fm.name.length > 64) warnings.push({
55
+ file: rel,
56
+ message: `Agent Skills spec warning: name exceeds 64 characters (${fm.name.length} chars)`
57
+ });
58
+ for (const segment of fm.name.split("/")) if (!agentSkillNamePattern.test(segment)) {
59
+ warnings.push({
60
+ file: rel,
61
+ message: "Agent Skills spec warning: each name segment should use lowercase letters, numbers, and single hyphens only"
62
+ });
63
+ break;
64
+ }
65
+ const parentDir = basename(dirname(filePath));
66
+ if (!fm.name.includes("/") && fm.name !== parentDir) warnings.push({
67
+ file: rel,
68
+ message: "Agent Skills spec warning: name should match the parent directory name"
69
+ });
70
+ }
71
+ if (fm.license !== void 0 && (typeof fm.license !== "string" || fm.license.trim().length === 0)) warnings.push({
72
+ file: rel,
73
+ message: "Agent Skills spec warning: license should be a non-empty string"
74
+ });
75
+ if (fm.compatibility !== void 0) {
76
+ if (typeof fm.compatibility !== "string" || fm.compatibility.trim().length === 0) warnings.push({
77
+ file: rel,
78
+ message: "Agent Skills spec warning: compatibility should be a non-empty string"
79
+ });
80
+ else if (fm.compatibility.length > 500) warnings.push({
81
+ file: rel,
82
+ message: `Agent Skills spec warning: compatibility exceeds 500 characters (${fm.compatibility.length} chars)`
83
+ });
84
+ }
85
+ if (fm.metadata !== void 0) {
86
+ if (!isRecord(fm.metadata)) warnings.push({
87
+ file: rel,
88
+ message: "Agent Skills spec warning: metadata should be a mapping"
89
+ });
90
+ else if (Object.values(fm.metadata).some((value) => typeof value !== "string")) warnings.push({
91
+ file: rel,
92
+ message: "Agent Skills spec warning: metadata values should be strings"
93
+ });
94
+ }
95
+ if (fm["allowed-tools"] !== void 0 && typeof fm["allowed-tools"] !== "string") warnings.push({
96
+ file: rel,
97
+ message: "Agent Skills spec warning: allowed-tools should be a space-separated string"
98
+ });
99
+ return warnings;
100
+ }
101
+ async function runValidateCommand(dir, options = {}) {
102
+ if (!options.githubSummary) {
103
+ await runValidateCommandInternal(dir);
104
+ return;
105
+ }
106
+ try {
107
+ await runValidateCommandInternal(dir);
108
+ writeGithubValidationSummary({ ok: true });
109
+ } catch (err) {
110
+ writeGithubValidationSummary({
111
+ ok: false,
112
+ message: validationErrorMessage(err)
113
+ });
114
+ throw err;
115
+ }
116
+ }
117
+ async function runValidateCommandInternal(dir) {
118
+ const [{ parse: parseYaml }, { findSkillFiles }] = await Promise.all([import("yaml"), import("./utils-BHzSyNeJ.mjs")]);
119
+ const context = resolveProjectContext({
120
+ cwd: process.cwd(),
121
+ targetPath: dir
122
+ });
123
+ const explicitDir = dir !== void 0;
124
+ const skillsDirs = explicitDir ? [context.targetSkillsDir ?? resolve(process.cwd(), dir)] : collectDefaultSkillsDirs(context, findSkillFiles);
125
+ if (explicitDir && !existsSync(skillsDirs[0])) fail(`Skills directory not found: ${skillsDirs[0]}`);
126
+ const errors = [];
127
+ const warnings = [];
128
+ let validatedCount = 0;
129
+ if (explicitDir && findSkillFiles(skillsDirs[0]).length === 0) fail("No SKILL.md files found");
130
+ if (skillsDirs.length === 0) {
131
+ console.log("No skills/ directory found — skipping validation.");
132
+ return;
133
+ }
134
+ for (const skillsDir of skillsDirs) {
135
+ const skillFiles = findSkillFiles(skillsDir);
136
+ const validateContext = resolveProjectContext({
137
+ cwd: process.cwd(),
138
+ targetPath: skillsDir
139
+ });
140
+ for (const filePath of skillFiles) {
141
+ const rel = relative(process.cwd(), filePath);
142
+ const content = readFileSync(filePath, "utf8");
143
+ const match = content.match(/^---\r?\n([\s\S]*?)\r?\n---\r?\n([\s\S]*)/);
144
+ if (!match) {
145
+ errors.push({
146
+ file: rel,
147
+ message: "Missing or invalid frontmatter"
148
+ });
149
+ continue;
150
+ }
151
+ if (!match[1]) {
152
+ errors.push({
153
+ file: rel,
154
+ message: "Missing YAML frontmatter"
155
+ });
156
+ continue;
157
+ }
158
+ let fm;
159
+ try {
160
+ fm = parseYaml(match[1]);
161
+ } catch (err) {
162
+ const detail = err instanceof Error ? err.message : String(err);
163
+ errors.push({
164
+ file: rel,
165
+ message: `Invalid YAML frontmatter: ${detail}`
166
+ });
167
+ continue;
168
+ }
169
+ if (!fm.name) errors.push({
170
+ file: rel,
171
+ message: "Missing required field: name"
172
+ });
173
+ if (!fm.description) errors.push({
174
+ file: rel,
175
+ message: "Missing required field: description"
176
+ });
177
+ if (typeof fm.name === "string") {
178
+ const expectedPath = relative(skillsDir, filePath).replace(/[/\\]SKILL\.md$/, "").split(sep).join("/");
179
+ if (fm.name !== expectedPath) errors.push({
180
+ file: rel,
181
+ message: `name "${fm.name}" does not match directory path "${expectedPath}"`
182
+ });
183
+ }
184
+ if (typeof fm.description === "string" && fm.description.length > 1024) errors.push({
185
+ file: rel,
186
+ message: `Description exceeds 1024 character limit (${fm.description.length} chars)`
187
+ });
188
+ if (fm.type === "framework" && !Array.isArray(fm.requires)) errors.push({
189
+ file: rel,
190
+ message: "Framework skills must have a \"requires\" field"
191
+ });
192
+ warnings.push(...collectAgentSkillSpecWarnings({
193
+ filePath,
194
+ fm,
195
+ rel
196
+ }).map(formatWarning));
197
+ const lineCount = content.split(/\r?\n/).length;
198
+ if (lineCount > 500) errors.push({
199
+ file: rel,
200
+ message: `Exceeds 500 line limit (${lineCount} lines). Rewrite for conciseness: move API tables to references/, trim verbose examples, and remove content an agent already knows. Do not simply raise the limit.`
201
+ });
202
+ }
203
+ const artifactsDir = join(skillsDir, "_artifacts");
204
+ if (!validateContext.isMonorepo && existsSync(artifactsDir)) for (const fileName of [
205
+ "domain_map.yaml",
206
+ "skill_spec.md",
207
+ "skill_tree.yaml"
208
+ ]) {
209
+ const artifactPath = join(artifactsDir, fileName);
210
+ if (!existsSync(artifactPath)) {
211
+ errors.push({
212
+ file: relative(process.cwd(), artifactPath),
213
+ message: "Missing required artifact"
214
+ });
215
+ continue;
216
+ }
217
+ const content = readFileSync(artifactPath, "utf8");
218
+ if (content.trim().length === 0) {
219
+ errors.push({
220
+ file: relative(process.cwd(), artifactPath),
221
+ message: "Artifact file is empty"
222
+ });
223
+ continue;
224
+ }
225
+ if (fileName.endsWith(".yaml")) try {
226
+ parseYaml(content);
227
+ } catch (err) {
228
+ const detail = err instanceof Error ? err.message : String(err);
229
+ errors.push({
230
+ file: relative(process.cwd(), artifactPath),
231
+ message: `Invalid YAML in artifact file: ${detail}`
232
+ });
233
+ }
234
+ }
235
+ validatedCount += skillFiles.length;
236
+ warnings.push(...collectPackagingWarnings(validateContext));
237
+ }
238
+ if (errors.length > 0) fail(buildValidationFailure(errors, warnings));
239
+ console.log(`✅ Validated ${validatedCount} skill files — all passed`);
240
+ if (warnings.length > 0) console.log();
241
+ printWarnings(warnings);
242
+ }
243
+ function validationErrorMessage(err) {
244
+ if (isCliFailure(err)) return err.message;
245
+ if (err instanceof Error) return err.message;
246
+ return String(err);
247
+ }
248
+ function writeGithubValidationSummary({ message, ok }) {
249
+ const summaryPath = process.env.GITHUB_STEP_SUMMARY;
250
+ if (!summaryPath) return;
251
+ const lines = ["### Intent skill validation", ""];
252
+ if (ok) lines.push("Skill validation passed.", "");
253
+ else lines.push("Skill validation failed.", "", "Why this failed:", "", "Intent validates SKILL.md frontmatter, skill names, required fields, size limits, framework requirements, and artifact files.", "The command output below contains the exact file-level reasons to fix.", "", "Run locally:", "", "```bash", "npx @tanstack/intent@latest validate", "```", "", "Command output:", "", "```text", message ?? "Unknown validation error.", "```", "");
254
+ appendFileSync(summaryPath, lines.join("\n"));
255
+ }
256
+ function collectDefaultSkillsDirs(context, findSkillFiles) {
257
+ const skillsDirs = [];
258
+ const addSkillsDir = (skillsDir) => {
259
+ if (existsSync(skillsDir) && findSkillFiles(skillsDir).length > 0) skillsDirs.push(skillsDir);
260
+ };
261
+ if (context.workspaceRoot && context.cwd === context.workspaceRoot) {
262
+ addSkillsDir(join(context.workspaceRoot, "skills"));
263
+ for (const packageDir of findWorkspacePackages(context.workspaceRoot)) addSkillsDir(join(packageDir, "skills"));
264
+ return [...new Set(skillsDirs)].sort((a, b) => a.localeCompare(b));
265
+ }
266
+ addSkillsDir(context.targetSkillsDir ?? (context.packageRoot ? join(context.packageRoot, "skills") : resolve(context.cwd, "skills")));
267
+ return skillsDirs;
268
+ }
269
+
270
+ //#endregion
271
+ export { runValidateCommand };
@@ -1,3 +1,3 @@
1
- import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem, t as buildStaleReviewBody } from "./workflow-review-CwkPVIQf.mjs";
1
+ import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem, t as buildStaleReviewBody } from "./workflow-review-CwcR2ge4.mjs";
2
2
 
3
3
  export { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles };
@@ -0,0 +1,4 @@
1
+ import "./utils-mdb4i6VA.mjs";
2
+ import { a as readWorkspacePatterns, i as getWorkspaceInfo, n as findWorkspacePackages, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BZLEaMcS.mjs";
3
+
4
+ export { findWorkspaceRoot, getWorkspaceInfo };