@tanstack/intent 0.1.1 → 0.2.0

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 (53) hide show
  1. package/dist/artifact-coverage-CXX6wav1.mjs +2 -0
  2. package/dist/{artifact-coverage-nGwun1tt.mjs → artifact-coverage-DFtI6V_H.mjs} +1 -3
  3. package/dist/{cli-error-BrMXlbtx.mjs → cli-error-DDAO6DIL.mjs} +1 -2
  4. package/dist/{cli-support-C8SKYTA4.mjs → cli-support-BQSl7gAE.mjs} +8 -11
  5. package/dist/{cli-support-BADtMg6z.mjs → cli-support-DK1Kq8Ue.mjs} +2 -6
  6. package/dist/cli.d.mts +0 -1
  7. package/dist/cli.mjs +14 -16
  8. package/dist/{command-runner-fstUIUhe.mjs → command-runner-B5OofX0E.mjs} +1 -2
  9. package/dist/{core-hEMP5GMV.mjs → core-BRUBEMwe.mjs} +9 -13
  10. package/dist/core.d.mts +3 -4
  11. package/dist/core.mjs +2 -11
  12. package/dist/{display-CFnFnrtx.mjs → display-CnpA7XuV.mjs} +3 -7
  13. package/dist/{edit-package-json-DKyJ04t1.mjs → edit-package-json-D8xfcy2X.mjs} +1 -2
  14. package/dist/{exclude-CBxkyK3Q.mjs → exclude-DbHwcgQQ.mjs} +6 -11
  15. package/dist/{excludes-DDMe-4iu.mjs → excludes-ByvSbmmj.mjs} +3 -6
  16. package/dist/index.d.mts +2 -3
  17. package/dist/index.mjs +9 -14
  18. package/dist/{install-BE7gVoNT.mjs → install-CTGQvXoB.mjs} +18 -24
  19. package/dist/{list-UqYivAcV.mjs → list-9SbFGUd5.mjs} +5 -15
  20. package/dist/{load-Dgw151E3.mjs → load-BY8vh7Gp.mjs} +4 -14
  21. package/dist/{meta-BZMVgIzJ.mjs → meta-CF4XIYOo.mjs} +3 -5
  22. package/dist/{package-manager-BUgTjW9Q.mjs → package-manager-Dw7lYcI0.mjs} +1 -3
  23. package/dist/{project-context-DDCie6Ro.mjs → project-context-oi_m7paK.mjs} +2 -4
  24. package/dist/{resolver-CZXZ0rft.mjs → resolver-Uwx8B5jv.mjs} +4 -6
  25. package/dist/{scaffold-D2vwv9ls.mjs → scaffold-D8TAMXvs.mjs} +1 -3
  26. package/dist/{scanner-2XDBAsbm.mjs → scanner-qT_M6nV5.mjs} +7 -14
  27. package/dist/{setup-DW3pn0QW.d.mts → setup-CdfBc7Oe.d.mts} +0 -1
  28. package/dist/{setup-CMec7fht.mjs → setup-Cx1r2y-1.mjs} +3 -5
  29. package/dist/{setup-github-actions-emXSyGy3.mjs → setup-github-actions-IxZTZihi.mjs} +1 -2
  30. package/dist/setup.d.mts +1 -1
  31. package/dist/setup.mjs +3 -6
  32. package/dist/{skill-paths-Cr74uFk4.mjs → skill-paths-Bm1P6IYe.mjs} +2 -4
  33. package/dist/{skill-use-CUrNHf-u.mjs → skill-use-B2xRF1i9.mjs} +1 -2
  34. package/dist/{source-policy-rGOtjQSM.mjs → source-policy-DkR80hkL.mjs} +4 -7
  35. package/dist/source-policy-hMYcpIgm.mjs +2 -0
  36. package/dist/{stale-DxZyYibt.mjs → stale-DhjSTIt-.mjs} +3 -5
  37. package/dist/staleness-B5Cqe77_.mjs +2 -0
  38. package/dist/{staleness-B8IvDS_9.mjs → staleness-DoZU3lzy.mjs} +9 -16
  39. package/dist/{utils-Dj49bkF_.mjs → utils-6FtqhOYf.mjs} +1 -3
  40. package/dist/{utils-BuNMwKct.mjs → utils-BKBDYbCx.mjs} +2 -3
  41. package/dist/{validate-B3pkTIZl.mjs → validate-BSfTOq0v.mjs} +133 -46
  42. package/dist/{workflow-review-wL1Iu2Sf.mjs → workflow-review-B4AfwtHH.mjs} +1 -3
  43. package/dist/{workflow-review-CtOR1bgh.mjs → workflow-review-Bo2kPVXV.mjs} +2 -3
  44. package/dist/{workspace-patterns-Cz_lNhwz.mjs → workspace-patterns-BDoJIWk-.mjs} +2 -4
  45. package/dist/workspace-patterns-CrL8hAbd.mjs +2 -0
  46. package/meta/generate-skill/SKILL.md +34 -20
  47. package/meta/tree-generator/SKILL.md +42 -38
  48. package/package.json +5 -6
  49. package/dist/artifact-coverage-BfJ7f-S9.mjs +0 -3
  50. package/dist/source-policy-D4slvwwI.mjs +0 -9
  51. package/dist/staleness-Ctzy2Zac.mjs +0 -5
  52. package/dist/workspace-patterns-BBW4c1gr.mjs +0 -4
  53. /package/dist/{types-oEflMSso.d.mts → types-P6UfPVdp.d.mts} +0 -0
@@ -1,7 +1,6 @@
1
- import { a as readWorkspacePatterns, r as findWorkspaceRoot } from "./workspace-patterns-Cz_lNhwz.mjs";
1
+ import { a as readWorkspacePatterns, r as findWorkspaceRoot } from "./workspace-patterns-BDoJIWk-.mjs";
2
2
  import { existsSync, statSync } from "node:fs";
3
3
  import { dirname, join, relative, resolve } from "node:path";
4
-
5
4
  //#region src/core/project-context.ts
6
5
  /**
7
6
  * Resolves project structure by walking up from targetPath (or cwd) to find the
@@ -49,6 +48,5 @@ function isWithinOrEqual(path, parentDir) {
49
48
  const rel = relative(parentDir, path);
50
49
  return rel === "" || !rel.startsWith("..") && !rel.startsWith("/");
51
50
  }
52
-
53
51
  //#endregion
54
- export { resolveProjectContext as t };
52
+ export { resolveProjectContext as t };
@@ -1,6 +1,5 @@
1
- import { i as parseSkillUse } from "./skill-use-CUrNHf-u.mjs";
2
- import { o as warningMentionsPackage } from "./excludes-DDMe-4iu.mjs";
3
-
1
+ import { i as parseSkillUse } from "./skill-use-B2xRF1i9.mjs";
2
+ import { o as warningMentionsPackage } from "./excludes-ByvSbmmj.mjs";
4
3
  //#region src/resolver.ts
5
4
  var ResolveSkillUseError = class extends Error {
6
5
  constructor({ availablePackages = [], availableSkills = [], code, packageName, skillName, suggestedSkills = [], use }) {
@@ -65,7 +64,7 @@ function resolveSkillEntry(packageName, skillName, skills) {
65
64
  }
66
65
  function resolveSkillUse(use, scanResult) {
67
66
  const { packageName, skillName } = parseSkillUse(use);
68
- const packages = scanResult.packages.filter((pkg$1) => pkg$1.name === packageName);
67
+ const packages = scanResult.packages.filter((pkg) => pkg.name === packageName);
69
68
  const pkg = packages.find((candidate) => candidate.source === "local") ?? packages[0];
70
69
  if (!pkg) throw new ResolveSkillUseError({
71
70
  availablePackages: scanResult.packages.map((candidate) => candidate.name),
@@ -107,6 +106,5 @@ function formatSkillSuggestions(packageName, skillNames) {
107
106
  if (uses.length <= 2) return uses.join(" or ");
108
107
  return `${uses.slice(0, -1).join(", ")}, or ${uses.at(-1)}`;
109
108
  }
110
-
111
109
  //#endregion
112
- export { resolveSkillUse as i, isResolveSkillUseError as n, resolveSkillEntry as r, ResolveSkillUseError as t };
110
+ export { resolveSkillUse as i, isResolveSkillUseError as n, resolveSkillEntry as r, ResolveSkillUseError as t };
@@ -1,5 +1,4 @@
1
1
  import { join } from "node:path";
2
-
3
2
  //#region src/commands/scaffold.ts
4
3
  function runScaffoldCommand(metaDir) {
5
4
  function metaSkillPath(name) {
@@ -70,6 +69,5 @@ This produces: individual SKILL.md files.
70
69
  `;
71
70
  console.log(prompt);
72
71
  }
73
-
74
72
  //#endregion
75
- export { runScaffoldCommand };
73
+ export { runScaffoldCommand };
@@ -1,12 +1,11 @@
1
- import { a as listNestedNodeModulesPackageDirs, c as parseFrontmatter, d as toPosixPath, i as getDeps, l as readScalarField, n as detectGlobalNodeModules, o as listNodeModulesPackageDirs, r as findSkillFiles, s as nodeReadFs, t as createFsIdentityCache, u as resolveDepDir } from "./utils-Dj49bkF_.mjs";
2
- import { r as rewriteSkillLoadPaths } from "./skill-paths-Cr74uFk4.mjs";
3
- import { n as findWorkspacePackages, r as findWorkspaceRoot } from "./workspace-patterns-Cz_lNhwz.mjs";
4
- import { t as detectPackageManager } from "./package-manager-BUgTjW9Q.mjs";
1
+ import { a as listNestedNodeModulesPackageDirs, c as parseFrontmatter, d as toPosixPath, i as getDeps, l as readScalarField, n as detectGlobalNodeModules, o as listNodeModulesPackageDirs, r as findSkillFiles, s as nodeReadFs, t as createFsIdentityCache, u as resolveDepDir } from "./utils-6FtqhOYf.mjs";
2
+ import { r as rewriteSkillLoadPaths } from "./skill-paths-Bm1P6IYe.mjs";
3
+ import { n as findWorkspacePackages, r as findWorkspaceRoot } from "./workspace-patterns-BDoJIWk-.mjs";
4
+ import { t as detectPackageManager } from "./package-manager-Dw7lYcI0.mjs";
5
5
  import { createRequire } from "node:module";
6
6
  import { existsSync } from "node:fs";
7
7
  import { dirname, isAbsolute, join, relative, resolve, sep } from "node:path";
8
8
  import semver from "semver";
9
-
10
9
  //#region src/discovery/register.ts
11
10
  function isLocalToProject(dirPath, projectRoot) {
12
11
  return dirPath.startsWith(projectRoot + sep) || dirPath.startsWith(projectRoot + "/");
@@ -84,7 +83,6 @@ function createPackageRegistrar(opts) {
84
83
  tryRegister
85
84
  };
86
85
  }
87
-
88
86
  //#endregion
89
87
  //#region src/discovery/walk.ts
90
88
  function createDependencyWalker(opts) {
@@ -156,7 +154,6 @@ function createDependencyWalker(opts) {
156
154
  walkWorkspacePackages
157
155
  };
158
156
  }
159
-
160
157
  //#endregion
161
158
  //#region src/fs-cache.ts
162
159
  function isRecord(value) {
@@ -220,7 +217,6 @@ function createIntentFsCache() {
220
217
  exists: (path) => activeFs.existsSync(path)
221
218
  };
222
219
  }
223
-
224
220
  //#endregion
225
221
  //#region src/scanner.ts
226
222
  const requireFromHere = createRequire(import.meta.url);
@@ -325,12 +321,10 @@ function deriveIntentConfig(pkgJson) {
325
321
  }
326
322
  function readSkillEntry(skillsDir, childDir, skillFile, readFs = nodeReadFs) {
327
323
  const fm = parseFrontmatter(skillFile, readFs);
328
- const relName = toPosixPath(relative(skillsDir, childDir));
329
- const desc = typeof fm?.description === "string" ? fm.description.replace(/\s+/g, " ").trim() : "";
330
324
  return {
331
- name: typeof fm?.name === "string" ? fm.name : relName,
325
+ name: toPosixPath(relative(skillsDir, childDir)),
332
326
  path: skillFile,
333
- description: desc,
327
+ description: typeof fm?.description === "string" ? fm.description.replace(/\s+/g, " ").trim() : "",
334
328
  type: readScalarField(fm, "type"),
335
329
  framework: readScalarField(fm, "framework")
336
330
  };
@@ -640,6 +634,5 @@ function scanIntentPackageAtRoot(packageRoot, options = {}) {
640
634
  warnings
641
635
  };
642
636
  }
643
-
644
637
  //#endregion
645
- export { scanIntentPackageAtRoot as n, createIntentFsCache as r, scanForIntents as t };
638
+ export { scanIntentPackageAtRoot as n, createIntentFsCache as r, scanForIntents as t };
@@ -1,5 +1,4 @@
1
1
  //#region src/workspace-patterns.d.ts
2
-
3
2
  declare function readWorkspacePatterns(root: string): Array<string> | null;
4
3
  declare function resolveWorkspacePackages(root: string, patterns: Array<string>): Array<string>;
5
4
  declare function findWorkspaceRoot(start: string): string | null;
@@ -1,8 +1,7 @@
1
- import { a as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-Cz_lNhwz.mjs";
2
- import { t as resolveProjectContext } from "./project-context-DDCie6Ro.mjs";
1
+ import { a as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BDoJIWk-.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-oi_m7paK.mjs";
3
3
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
4
  import { basename, join, relative } from "node:path";
5
-
6
5
  //#region src/setup.ts
7
6
  function isGenericWorkspaceName(name, root) {
8
7
  const normalized = name.trim().toLowerCase();
@@ -195,6 +194,5 @@ function runSetupGithubActions(root, metaDir) {
195
194
  }
196
195
  return result;
197
196
  }
198
-
199
197
  //#endregion
200
- export { runEditPackageJsonAll as n, runSetupGithubActions as r, runEditPackageJson as t };
198
+ export { runEditPackageJsonAll as n, runSetupGithubActions as r, runEditPackageJson as t };
@@ -3,6 +3,5 @@ async function runSetupGithubActionsCommand(root, metaDir) {
3
3
  const { runSetupGithubActions } = await import("./setup.mjs");
4
4
  runSetupGithubActions(root, metaDir);
5
5
  }
6
-
7
6
  //#endregion
8
- export { runSetupGithubActionsCommand };
7
+ export { runSetupGithubActionsCommand };
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-DW3pn0QW.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-CdfBc7Oe.mjs";
2
2
  export { EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
package/dist/setup.mjs CHANGED
@@ -1,6 +1,3 @@
1
- import "./utils-Dj49bkF_.mjs";
2
- import { a as readWorkspacePatterns, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-Cz_lNhwz.mjs";
3
- import "./project-context-DDCie6Ro.mjs";
4
- import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-CMec7fht.mjs";
5
-
6
- export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
1
+ import { a as readWorkspacePatterns, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BDoJIWk-.mjs";
2
+ import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-Cx1r2y-1.mjs";
3
+ export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
@@ -1,7 +1,6 @@
1
- import { d as toPosixPath } from "./utils-Dj49bkF_.mjs";
1
+ import { d as toPosixPath } from "./utils-6FtqhOYf.mjs";
2
2
  import { existsSync } from "node:fs";
3
3
  import { join, relative } from "node:path";
4
-
5
4
  //#region src/skill-paths.ts
6
5
  function isAbsolutePath(path) {
7
6
  return path.startsWith("/") || path.startsWith("\\") || /^[A-Za-z]:[\\/]/.test(path);
@@ -28,6 +27,5 @@ function formatRuntimeSkillLookupComment(target) {
28
27
  function formatRuntimeSkillLookupHint(target) {
29
28
  return `Lookup: ${formatRuntimeSkillLookupComment(target)}`;
30
29
  }
31
-
32
30
  //#endregion
33
- export { isStableLoadPath as n, rewriteSkillLoadPaths as r, formatRuntimeSkillLookupHint as t };
31
+ export { isStableLoadPath as n, rewriteSkillLoadPaths as r, formatRuntimeSkillLookupHint as t };
@@ -37,6 +37,5 @@ function formatSkillUseParseErrorMessage(code, value) {
37
37
  case "empty-skill": return `Invalid skill use "${value}": skill is required.`;
38
38
  }
39
39
  }
40
-
41
40
  //#endregion
42
- export { parseSkillUse as i, formatSkillUse as n, isSkillUseParseError as r, SkillUseParseError as t };
41
+ export { parseSkillUse as i, formatSkillUse as n, isSkillUseParseError as r, SkillUseParseError as t };
@@ -1,7 +1,6 @@
1
- import { t as scanForIntents } from "./scanner-2XDBAsbm.mjs";
2
- import { t as resolveProjectContext } from "./project-context-DDCie6Ro.mjs";
3
- import { a as isSkillExcluded, i as isPackageExcluded, n as getConfigDirs, o as warningMentionsPackage, r as getEffectiveExcludePatterns, s as readPackageJson, t as compileExcludePatterns } from "./excludes-DDMe-4iu.mjs";
4
-
1
+ import { t as scanForIntents } from "./scanner-qT_M6nV5.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-oi_m7paK.mjs";
3
+ import { a as isSkillExcluded, i as isPackageExcluded, n as getConfigDirs, o as warningMentionsPackage, r as getEffectiveExcludePatterns, s as readPackageJson, t as compileExcludePatterns } from "./excludes-ByvSbmmj.mjs";
5
4
  //#region src/core/skill-sources.ts
6
5
  var SkillSourcesParseError = class extends Error {
7
6
  constructor(issues) {
@@ -135,7 +134,6 @@ function describeType(value) {
135
134
  function formatIssues(issues) {
136
135
  return ["Invalid intent.skills configuration:", ...issues.map((issue) => issue.raw === null ? ` - ${issue.message}` : ` - "${issue.raw}": ${issue.message}`)].join("\n");
137
136
  }
138
-
139
137
  //#endregion
140
138
  //#region src/core/source-policy.ts
141
139
  const ALLOW_ALL_NOTICE = "All skill sources allowed (intent.skills: [\"*\"]) — unvetted skills may be surfaced into agent guidance.";
@@ -242,6 +240,5 @@ function scanForPolicedIntents(params) {
242
240
  excludePatterns
243
241
  };
244
242
  }
245
-
246
243
  //#endregion
247
- export { checkLoadAllowed as a, applySourcePolicy as i, EMPTY_NOTE as n, readSkillSourcesConfig as o, MIGRATION_NOTICE as r, scanForPolicedIntents as s, ALLOW_ALL_NOTICE as t };
244
+ export { checkLoadAllowed as a, applySourcePolicy as i, EMPTY_NOTE as n, readSkillSourcesConfig as o, MIGRATION_NOTICE as r, scanForPolicedIntents as s, ALLOW_ALL_NOTICE as t };
@@ -0,0 +1,2 @@
1
+ import { s as scanForPolicedIntents } from "./source-policy-DkR80hkL.mjs";
2
+ export { scanForPolicedIntents };
@@ -1,5 +1,4 @@
1
- import { n as isCliFailure } from "./cli-error-BrMXlbtx.mjs";
2
-
1
+ import { n as isCliFailure } from "./cli-error-DDAO6DIL.mjs";
3
2
  //#region src/commands/stale.ts
4
3
  async function runStaleCommand(targetDir, options, resolveStaleTargets) {
5
4
  if (options.githubReview) {
@@ -35,7 +34,7 @@ async function runStaleCommand(targetDir, options, resolveStaleTargets) {
35
34
  }
36
35
  }
37
36
  async function runGithubReview(targetDir, options, resolveStaleTargets) {
38
- const { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles } = await import("./workflow-review-CtOR1bgh.mjs");
37
+ const { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles } = await import("./workflow-review-Bo2kPVXV.mjs");
39
38
  const packageLabel = options.packageLabel ?? "workspace";
40
39
  try {
41
40
  const { reports, workflowAdvisories = [] } = await resolveStaleTargets(targetDir);
@@ -50,6 +49,5 @@ async function runGithubReview(targetDir, options, resolveStaleTargets) {
50
49
  console.log("Wrote a review PR body so maintainers can inspect the logs.");
51
50
  }
52
51
  }
53
-
54
52
  //#endregion
55
- export { runStaleCommand };
53
+ export { runStaleCommand };
@@ -0,0 +1,2 @@
1
+ import { n as checkStaleness, r as readPackageName, t as buildWorkspaceCoverageSignals } from "./staleness-DoZU3lzy.mjs";
2
+ export { buildWorkspaceCoverageSignals, checkStaleness, readPackageName };
@@ -1,9 +1,8 @@
1
- import { c as parseFrontmatter, d as toPosixPath, l as readScalarField, r as findSkillFiles } from "./utils-Dj49bkF_.mjs";
2
- import { t as readIntentArtifacts } from "./artifact-coverage-nGwun1tt.mjs";
1
+ import { c as parseFrontmatter, d as toPosixPath, l as readScalarField, r as findSkillFiles } from "./utils-6FtqhOYf.mjs";
2
+ import { t as readIntentArtifacts } from "./artifact-coverage-DFtI6V_H.mjs";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { isAbsolute, join, relative, resolve } from "node:path";
5
5
  import semver from "semver";
6
-
7
6
  //#region src/staleness.ts
8
7
  function classifyVersionDrift(oldVer, newVer) {
9
8
  const oldVersion = normalizeVersion(oldVer);
@@ -126,10 +125,7 @@ function findMatchingSkill(artifact, skillMetas, packageDir, artifactRoot) {
126
125
  if (match) return match;
127
126
  }
128
127
  const skillsByName = /* @__PURE__ */ new Map();
129
- for (const skill of skillMetas) {
130
- skillsByName.set(skill.name, skill);
131
- skillsByName.set(skill.relName, skill);
132
- }
128
+ for (const skill of skillMetas) skillsByName.set(skill.relName, skill);
133
129
  return (artifact.slug ? skillsByName.get(artifact.slug) : void 0) ?? (artifact.name ? skillsByName.get(artifact.name) : void 0) ?? null;
134
130
  }
135
131
  function buildArtifactSignals({ artifactRoot, artifacts, library, packageDir, skillMetas }) {
@@ -167,7 +163,7 @@ function buildArtifactSignals({ artifactRoot, artifacts, library, packageDir, sk
167
163
  reasons: ["artifact sources differ from SKILL.md frontmatter sources"],
168
164
  needsReview: true,
169
165
  artifactPath: artifact.artifactPath,
170
- skill: matchingSkill.name
166
+ skill: matchingSkill.relName
171
167
  });
172
168
  const artifactVersion = artifactFiles.get(artifact.artifactPath)?.libraryVersion;
173
169
  if (artifactVersion && matchingSkill.libraryVersion && artifactVersion !== matchingSkill.libraryVersion) signals.push({
@@ -177,7 +173,7 @@ function buildArtifactSignals({ artifactRoot, artifacts, library, packageDir, sk
177
173
  reasons: [`artifact library.version (${artifactVersion}) differs from SKILL.md library_version (${matchingSkill.libraryVersion})`],
178
174
  needsReview: true,
179
175
  artifactPath: artifact.artifactPath,
180
- skill: matchingSkill.name
176
+ skill: matchingSkill.relName
181
177
  });
182
178
  }
183
179
  return signals;
@@ -217,10 +213,8 @@ async function checkStaleness(packageDir, packageName, artifactRoot = packageDir
217
213
  const library = packageName ?? readPackageName(packageDir);
218
214
  const skillMetas = findSkillFiles(skillsDir).map((filePath) => {
219
215
  const fm = parseFrontmatter(filePath);
220
- const relName = toPosixPath(relative(skillsDir, filePath)).replace(/[/\\]SKILL\.md$/, "");
221
216
  return {
222
- name: typeof fm?.name === "string" ? fm.name : relName,
223
- relName,
217
+ relName: toPosixPath(relative(skillsDir, filePath)).replace(/[/\\]SKILL\.md$/, ""),
224
218
  filePath,
225
219
  libraryVersion: readScalarField(fm, "library_version"),
226
220
  sources: Array.isArray(fm?.sources) ? fm.sources : void 0
@@ -239,12 +233,12 @@ async function checkStaleness(packageDir, packageName, artifactRoot = packageDir
239
233
  skills: skillMetas.map((skill) => {
240
234
  const reasons = [];
241
235
  if (currentVersion && skill.libraryVersion && classifyVersionDrift(skill.libraryVersion, currentVersion) !== null) reasons.push(`version drift (${skill.libraryVersion} → ${currentVersion})`);
242
- const storedShas = syncState?.skills?.[skill.name]?.sources_sha ?? {};
236
+ const storedShas = syncState?.skills?.[skill.relName]?.sources_sha ?? {};
243
237
  if (skill.sources && Object.keys(storedShas).length > 0) {
244
238
  for (const source of skill.sources) if (!storedShas[source]) reasons.push(`new source (${source})`);
245
239
  }
246
240
  return {
247
- name: skill.name,
241
+ name: skill.relName,
248
242
  reasons,
249
243
  needsReview: reasons.length > 0
250
244
  };
@@ -258,6 +252,5 @@ async function checkStaleness(packageDir, packageName, artifactRoot = packageDir
258
252
  })
259
253
  };
260
254
  }
261
-
262
255
  //#endregion
263
- export { checkStaleness as n, readPackageName as r, buildWorkspaceCoverageSignals as t };
256
+ export { checkStaleness as n, readPackageName as r, buildWorkspaceCoverageSignals as t };
@@ -3,7 +3,6 @@ import { closeSync, existsSync, lstatSync, openSync, readFileSync, readSync, rea
3
3
  import { dirname, join, resolve, sep } from "node:path";
4
4
  import { execFileSync } from "node:child_process";
5
5
  import { parse } from "yaml";
6
-
7
6
  //#region src/utils.ts
8
7
  const nodeReadFs = {
9
8
  existsSync,
@@ -290,6 +289,5 @@ function readFrontmatterRegion(filePath, fs) {
290
289
  return null;
291
290
  }
292
291
  }
293
-
294
292
  //#endregion
295
- export { listNestedNodeModulesPackageDirs as a, parseFrontmatter as c, toPosixPath as d, getDeps as i, readScalarField as l, detectGlobalNodeModules as n, listNodeModulesPackageDirs as o, findSkillFiles as r, nodeReadFs as s, createFsIdentityCache as t, resolveDepDir as u };
293
+ export { listNestedNodeModulesPackageDirs as a, parseFrontmatter as c, toPosixPath as d, getDeps as i, readScalarField as l, detectGlobalNodeModules as n, listNodeModulesPackageDirs as o, findSkillFiles as r, nodeReadFs as s, createFsIdentityCache as t, resolveDepDir as u };
@@ -1,3 +1,2 @@
1
- import { a as listNestedNodeModulesPackageDirs, c as parseFrontmatter, d as toPosixPath, i as getDeps, l as readScalarField, n as detectGlobalNodeModules, o as listNodeModulesPackageDirs, r as findSkillFiles, s as nodeReadFs, t as createFsIdentityCache, u as resolveDepDir } from "./utils-Dj49bkF_.mjs";
2
-
3
- export { createFsIdentityCache, detectGlobalNodeModules, findSkillFiles, getDeps, listNestedNodeModulesPackageDirs, listNodeModulesPackageDirs, nodeReadFs, parseFrontmatter, readScalarField, resolveDepDir, toPosixPath };
1
+ import { a as listNestedNodeModulesPackageDirs, c as parseFrontmatter, d as toPosixPath, i as getDeps, l as readScalarField, n as detectGlobalNodeModules, o as listNodeModulesPackageDirs, r as findSkillFiles, s as nodeReadFs, t as createFsIdentityCache, u as resolveDepDir } from "./utils-6FtqhOYf.mjs";
2
+ export { createFsIdentityCache, detectGlobalNodeModules, findSkillFiles, getDeps, listNestedNodeModulesPackageDirs, listNodeModulesPackageDirs, nodeReadFs, parseFrontmatter, readScalarField, resolveDepDir, toPosixPath };
@@ -1,13 +1,29 @@
1
- import "./utils-Dj49bkF_.mjs";
2
- import { n as findWorkspacePackages } from "./workspace-patterns-Cz_lNhwz.mjs";
3
- import { t as resolveProjectContext } from "./project-context-DDCie6Ro.mjs";
4
- import { n as isCliFailure, t as fail } from "./cli-error-BrMXlbtx.mjs";
5
- import { u as printWarnings } from "./cli-support-C8SKYTA4.mjs";
6
- import { appendFileSync, existsSync, readFileSync } from "node:fs";
7
- import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
-
1
+ import { n as findWorkspacePackages } from "./workspace-patterns-BDoJIWk-.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-oi_m7paK.mjs";
3
+ import { n as isCliFailure, t as fail } from "./cli-error-DDAO6DIL.mjs";
4
+ import { u as printWarnings } from "./cli-support-BQSl7gAE.mjs";
5
+ import { appendFileSync, existsSync, readFileSync, writeFileSync } from "node:fs";
6
+ import { basename, dirname, join, relative, resolve } from "node:path";
9
7
  //#region src/commands/validate.ts
10
8
  const agentSkillNamePattern = /^[a-z0-9]+(?:-[a-z0-9]+)*$/;
9
+ const specTopLevelKeys = new Set([
10
+ "name",
11
+ "description",
12
+ "license",
13
+ "compatibility",
14
+ "metadata",
15
+ "allowed-tools"
16
+ ]);
17
+ const intentArrayKeys = new Set(["sources", "requires"]);
18
+ const metadataScalarKeys = [
19
+ "type",
20
+ "library",
21
+ "library_version",
22
+ "framework"
23
+ ];
24
+ function isScalarValue(value) {
25
+ return typeof value === "string" || typeof value === "number" || typeof value === "boolean";
26
+ }
11
27
  function buildValidationFailure(errors, warnings) {
12
28
  const lines = [
13
29
  "",
@@ -48,26 +64,60 @@ function formatWarning({ file, message }) {
48
64
  function isRecord(value) {
49
65
  return !!value && typeof value === "object" && !Array.isArray(value);
50
66
  }
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;
67
+ function collectFrontmatterFixPlan({ filePath, fm, rel }) {
68
+ const changes = [];
69
+ const parentDir = basename(dirname(filePath));
70
+ if (typeof fm.name === "string" && (fm.name.includes("/") || fm.name !== parentDir) && agentSkillNamePattern.test(parentDir)) changes.push(`rewrite name to "${parentDir}"`);
71
+ const metadata = fm.metadata;
72
+ if (metadata === void 0 || isRecord(metadata)) {
73
+ const metadataRecord = isRecord(metadata) ? metadata : void 0;
74
+ for (const key of metadataScalarKeys) {
75
+ if (typeof fm[key] !== "string") continue;
76
+ if (metadataRecord && key in metadataRecord) changes.push(`remove top-level "${key}"; metadata.${key} already exists`);
77
+ else changes.push(`move top-level "${key}" under metadata.${key}`);
64
78
  }
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
79
  }
80
+ return changes.length > 0 ? {
81
+ file: rel,
82
+ filePath,
83
+ changes
84
+ } : null;
85
+ }
86
+ function normalizeLineEndings(value, lineEnding) {
87
+ return lineEnding === "\r\n" ? value.replace(/\r?\n/g, "\r\n") : value;
88
+ }
89
+ async function applyFrontmatterFixes(fixPlans) {
90
+ const { parseDocument } = await import("yaml");
91
+ for (const plan of fixPlans) {
92
+ const match = readFileSync(plan.filePath, "utf8").match(/^---(\r?\n)([\s\S]*?)(\r?\n)---(\r?\n?)([\s\S]*)/);
93
+ if (!match) continue;
94
+ const openingLineEnding = match[1];
95
+ const frontmatter = match[2];
96
+ const closingLineEnding = match[3];
97
+ const afterClose = match[4];
98
+ const body = match[5];
99
+ if (openingLineEnding === void 0 || frontmatter === void 0 || closingLineEnding === void 0 || afterClose === void 0 || body === void 0) continue;
100
+ const doc = parseDocument(frontmatter);
101
+ if (doc.errors.length > 0) continue;
102
+ const fm = doc.toJS();
103
+ const parentDir = basename(dirname(plan.filePath));
104
+ if (typeof fm.name === "string" && (fm.name.includes("/") || fm.name !== parentDir) && agentSkillNamePattern.test(parentDir)) doc.set("name", parentDir);
105
+ const metadata = fm.metadata;
106
+ if (metadata === void 0 || isRecord(metadata)) for (const key of metadataScalarKeys) {
107
+ const value = fm[key];
108
+ if (typeof value !== "string") continue;
109
+ if (!doc.hasIn(["metadata", key])) {
110
+ const valueNode = doc.get(key, true);
111
+ doc.setIn(["metadata", key], valueNode ?? value);
112
+ }
113
+ doc.delete(key);
114
+ }
115
+ const nextContent = `---${openingLineEnding}${normalizeLineEndings(doc.toString().replace(/\r?\n$/, ""), openingLineEnding)}${closingLineEnding}---${afterClose}${body}`;
116
+ writeFileSync(plan.filePath, nextContent);
117
+ }
118
+ }
119
+ function collectAgentSkillSpecWarnings({ fm, rel }) {
120
+ const warnings = [];
71
121
  if (fm.license !== void 0 && (typeof fm.license !== "string" || fm.license.trim().length === 0)) warnings.push({
72
122
  file: rel,
73
123
  message: "Agent Skills spec warning: license should be a non-empty string"
@@ -82,16 +132,6 @@ function collectAgentSkillSpecWarnings({ filePath, fm, rel }) {
82
132
  message: `Agent Skills spec warning: compatibility exceeds 500 characters (${fm.compatibility.length} chars)`
83
133
  });
84
134
  }
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
135
  if (fm["allowed-tools"] !== void 0 && typeof fm["allowed-tools"] !== "string") warnings.push({
96
136
  file: rel,
97
137
  message: "Agent Skills spec warning: allowed-tools should be a space-separated string"
@@ -99,12 +139,13 @@ function collectAgentSkillSpecWarnings({ filePath, fm, rel }) {
99
139
  return warnings;
100
140
  }
101
141
  async function runValidateCommand(dir, options = {}) {
142
+ if (options.fix && options.check) fail("Cannot combine --fix and --check");
102
143
  if (!options.githubSummary) {
103
- await runValidateCommandInternal(dir);
144
+ await runValidateCommandInternal(dir, options);
104
145
  return;
105
146
  }
106
147
  try {
107
- await runValidateCommandInternal(dir);
148
+ await runValidateCommandInternal(dir, options);
108
149
  writeGithubValidationSummary({ ok: true });
109
150
  } catch (err) {
110
151
  writeGithubValidationSummary({
@@ -114,8 +155,8 @@ async function runValidateCommand(dir, options = {}) {
114
155
  throw err;
115
156
  }
116
157
  }
117
- async function runValidateCommandInternal(dir) {
118
- const [{ parse: parseYaml }, { findSkillFiles, readScalarField }] = await Promise.all([import("yaml"), import("./utils-BuNMwKct.mjs")]);
158
+ async function runValidateCommandInternal(dir, options = {}) {
159
+ const [{ parse: parseYaml }, { findSkillFiles, readScalarField }] = await Promise.all([import("yaml"), import("./utils-BKBDYbCx.mjs")]);
119
160
  const context = resolveProjectContext({
120
161
  cwd: process.cwd(),
121
162
  targetPath: dir
@@ -125,6 +166,7 @@ async function runValidateCommandInternal(dir) {
125
166
  if (explicitDir && !existsSync(skillsDirs[0])) fail(`Skills directory not found: ${skillsDirs[0]}`);
126
167
  const errors = [];
127
168
  const warnings = [];
169
+ const fixPlans = [];
128
170
  let validatedCount = 0;
129
171
  if (explicitDir && findSkillFiles(skillsDirs[0]).length === 0) fail("No SKILL.md files found");
130
172
  if (skillsDirs.length === 0) {
@@ -166,6 +208,12 @@ async function runValidateCommandInternal(dir) {
166
208
  });
167
209
  continue;
168
210
  }
211
+ const fixPlan = collectFrontmatterFixPlan({
212
+ filePath,
213
+ fm,
214
+ rel
215
+ });
216
+ if (fixPlan) fixPlans.push(fixPlan);
169
217
  if (!fm.name) errors.push({
170
218
  file: rel,
171
219
  message: "Missing required field: name"
@@ -175,10 +223,38 @@ async function runValidateCommandInternal(dir) {
175
223
  message: "Missing required field: description"
176
224
  });
177
225
  if (typeof fm.name === "string") {
178
- const expectedPath = relative(skillsDir, filePath).replace(/[/\\]SKILL\.md$/, "").split(sep).join("/");
179
- if (fm.name !== expectedPath) errors.push({
226
+ const parentDir = basename(dirname(filePath));
227
+ if (fm.name.length > 64) errors.push({
180
228
  file: rel,
181
- message: `name "${fm.name}" does not match directory path "${expectedPath}"`
229
+ message: `name exceeds 64 characters (${fm.name.length} chars)`
230
+ });
231
+ if (fm.name.includes("/")) errors.push({
232
+ file: rel,
233
+ message: `name "${fm.name}" must be a single leaf segment matching its parent directory "${parentDir}" — the namespace is carried by the directory path, not the name`
234
+ });
235
+ else {
236
+ if (fm.name !== parentDir) errors.push({
237
+ file: rel,
238
+ message: `name "${fm.name}" does not match parent directory "${parentDir}"`
239
+ });
240
+ if (!agentSkillNamePattern.test(fm.name)) errors.push({
241
+ file: rel,
242
+ message: `name "${fm.name}" must use only lowercase letters, numbers, and hyphens`
243
+ });
244
+ }
245
+ }
246
+ for (const [key, value] of Object.entries(fm)) if (!specTopLevelKeys.has(key) && !intentArrayKeys.has(key) && isScalarValue(value)) errors.push({
247
+ file: rel,
248
+ message: `non-spec top-level key "${key}" — move client-specific scalar fields under "metadata"`
249
+ });
250
+ if (fm.metadata !== void 0) {
251
+ if (!isRecord(fm.metadata)) errors.push({
252
+ file: rel,
253
+ message: "metadata must be a mapping"
254
+ });
255
+ else if (Object.values(fm.metadata).some((value) => typeof value !== "string")) errors.push({
256
+ file: rel,
257
+ message: "metadata values must be strings"
182
258
  });
183
259
  }
184
260
  if (typeof fm.description === "string" && fm.description.length > 1024) errors.push({
@@ -190,7 +266,6 @@ async function runValidateCommandInternal(dir) {
190
266
  message: "Framework skills must have a \"requires\" field"
191
267
  });
192
268
  warnings.push(...collectAgentSkillSpecWarnings({
193
- filePath,
194
269
  fm,
195
270
  rel
196
271
  }).map(formatWarning));
@@ -235,6 +310,19 @@ async function runValidateCommandInternal(dir) {
235
310
  validatedCount += skillFiles.length;
236
311
  warnings.push(...collectPackagingWarnings(validateContext));
237
312
  }
313
+ if (options.check) for (const plan of fixPlans) errors.push({
314
+ file: plan.file,
315
+ message: `fixable frontmatter migration pending: ${plan.changes.join("; ")}`
316
+ });
317
+ if (options.fix && fixPlans.length > 0) {
318
+ await applyFrontmatterFixes(fixPlans);
319
+ console.log(`✅ Fixed ${fixPlans.length} skill files`);
320
+ await runValidateCommandInternal(dir, {
321
+ ...options,
322
+ fix: false
323
+ });
324
+ return;
325
+ }
238
326
  if (errors.length > 0) fail(buildValidationFailure(errors, warnings));
239
327
  console.log(`✅ Validated ${validatedCount} skill files — all passed`);
240
328
  if (warnings.length > 0) console.log();
@@ -266,6 +354,5 @@ function collectDefaultSkillsDirs(context, findSkillFiles) {
266
354
  addSkillsDir(context.targetSkillsDir ?? (context.packageRoot ? join(context.packageRoot, "skills") : resolve(context.cwd, "skills")));
267
355
  return skillsDirs;
268
356
  }
269
-
270
357
  //#endregion
271
- export { runValidateCommand };
358
+ export { runValidateCommand };
@@ -1,5 +1,4 @@
1
1
  import { appendFileSync, writeFileSync } from "node:fs";
2
-
3
2
  //#region src/workflow-review.ts
4
3
  function collectStaleReviewItems(reports) {
5
4
  const items = [];
@@ -148,6 +147,5 @@ function writeStaleReviewWorkflowFiles(items, options = {}) {
148
147
  if (hasReview) writeFileSync(prBodyPath, summary);
149
148
  if (summaryPath) appendFileSync(summaryPath, summary);
150
149
  }
151
-
152
150
  //#endregion
153
- export { writeStaleReviewWorkflowFiles as a, createWorkflowAdvisoryReviewItems as i, collectStaleReviewItems as n, createFailedStaleReviewItem as r, buildStaleReviewBody as t };
151
+ export { writeStaleReviewWorkflowFiles as a, createWorkflowAdvisoryReviewItems as i, collectStaleReviewItems as n, createFailedStaleReviewItem as r, buildStaleReviewBody as t };
@@ -1,3 +1,2 @@
1
- import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem, t as buildStaleReviewBody } from "./workflow-review-wL1Iu2Sf.mjs";
2
-
3
- export { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles };
1
+ import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem } from "./workflow-review-B4AfwtHH.mjs";
2
+ export { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles };