@tanstack/intent 0.1.0 → 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.
- package/README.md +0 -3
- package/dist/artifact-coverage-CXX6wav1.mjs +2 -0
- package/dist/{artifact-coverage-nGwun1tt.mjs → artifact-coverage-DFtI6V_H.mjs} +1 -3
- package/dist/{cli-error-BrMXlbtx.mjs → cli-error-DDAO6DIL.mjs} +1 -2
- package/dist/{cli-support-BevVu4gw.mjs → cli-support-BQSl7gAE.mjs} +8 -11
- package/dist/{cli-support-Cpo_9JfL.mjs → cli-support-DK1Kq8Ue.mjs} +2 -6
- package/dist/cli.d.mts +0 -1
- package/dist/cli.mjs +14 -16
- package/dist/{command-runner-fstUIUhe.mjs → command-runner-B5OofX0E.mjs} +1 -2
- package/dist/{core-6UP6jyL8.mjs → core-BRUBEMwe.mjs} +9 -13
- package/dist/core.d.mts +3 -4
- package/dist/core.mjs +2 -11
- package/dist/{display-CVMGtcHz.mjs → display-CnpA7XuV.mjs} +3 -7
- package/dist/{edit-package-json-DKyJ04t1.mjs → edit-package-json-D8xfcy2X.mjs} +1 -2
- package/dist/{exclude-BTaE6TNh.mjs → exclude-DbHwcgQQ.mjs} +6 -11
- package/dist/{excludes-DG83YEzb.mjs → excludes-ByvSbmmj.mjs} +3 -6
- package/dist/index.d.mts +3 -31
- package/dist/index.mjs +9 -280
- package/dist/{install-DXQsQQIL.mjs → install-CTGQvXoB.mjs} +18 -24
- package/dist/{list-CxB37mvm.mjs → list-9SbFGUd5.mjs} +5 -19
- package/dist/{load-Ch4UjIza.mjs → load-BY8vh7Gp.mjs} +4 -14
- package/dist/{meta-C-t9P5Ls.mjs → meta-CF4XIYOo.mjs} +3 -5
- package/dist/{package-manager-BUgTjW9Q.mjs → package-manager-Dw7lYcI0.mjs} +1 -3
- package/dist/{project-context-DBSibDPb.mjs → project-context-oi_m7paK.mjs} +2 -4
- package/dist/{resolver-CDbVXv4g.mjs → resolver-Uwx8B5jv.mjs} +4 -6
- package/dist/{scaffold-D2vwv9ls.mjs → scaffold-D8TAMXvs.mjs} +1 -3
- package/dist/{scanner-CRCZwhKS.mjs → scanner-qT_M6nV5.mjs} +9 -16
- package/dist/{setup-DW3pn0QW.d.mts → setup-CdfBc7Oe.d.mts} +0 -1
- package/dist/{setup-DpCYUVSf.mjs → setup-Cx1r2y-1.mjs} +3 -5
- package/dist/{setup-github-actions-emXSyGy3.mjs → setup-github-actions-IxZTZihi.mjs} +1 -2
- package/dist/setup.d.mts +1 -1
- package/dist/setup.mjs +3 -6
- package/dist/{skill-paths-B-j0dWDA.mjs → skill-paths-Bm1P6IYe.mjs} +2 -4
- package/dist/{skill-use-CUrNHf-u.mjs → skill-use-B2xRF1i9.mjs} +1 -2
- package/dist/{source-policy-DaImacFt.mjs → source-policy-DkR80hkL.mjs} +4 -7
- package/dist/source-policy-hMYcpIgm.mjs +2 -0
- package/dist/{stale-DxZyYibt.mjs → stale-DhjSTIt-.mjs} +3 -5
- package/dist/staleness-B5Cqe77_.mjs +2 -0
- package/dist/{staleness-DVFARTES.mjs → staleness-DoZU3lzy.mjs} +10 -17
- package/dist/{types-DhITOzhi.d.mts → types-P6UfPVdp.d.mts} +1 -33
- package/dist/{utils-9fhWAVua.mjs → utils-6FtqhOYf.mjs} +14 -3
- package/dist/utils-BKBDYbCx.mjs +2 -0
- package/dist/{validate-CnQBn6v9.mjs → validate-BSfTOq0v.mjs} +134 -47
- package/dist/{workflow-review-wL1Iu2Sf.mjs → workflow-review-B4AfwtHH.mjs} +1 -3
- package/dist/{workflow-review-CtOR1bgh.mjs → workflow-review-Bo2kPVXV.mjs} +2 -3
- package/dist/{workspace-patterns-BffPlZ1D.mjs → workspace-patterns-BDoJIWk-.mjs} +2 -4
- package/dist/workspace-patterns-CrL8hAbd.mjs +2 -0
- package/meta/domain-discovery/SKILL.md +1 -1
- package/meta/generate-skill/SKILL.md +35 -28
- package/meta/tree-generator/SKILL.md +43 -39
- package/package.json +5 -6
- package/dist/artifact-coverage-BfJ7f-S9.mjs +0 -3
- package/dist/source-policy-y3sktvzu.mjs +0 -9
- package/dist/staleness-BoFc6DMh.mjs +0 -5
- package/dist/utils-CSPzvaFu.mjs +0 -3
- package/dist/workspace-patterns-Bjq_cXww.mjs +0 -4
- package/meta/feedback-collection/SKILL.md +0 -234
|
@@ -1,7 +1,6 @@
|
|
|
1
|
-
import {
|
|
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-
|
|
2
|
-
import { t as resolveProjectContext } from "./project-context-
|
|
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-
|
|
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 };
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { n as isCliFailure } from "./cli-error-
|
|
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-
|
|
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 };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { c as parseFrontmatter,
|
|
2
|
-
import { t as readIntentArtifacts } from "./artifact-coverage-
|
|
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.
|
|
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.
|
|
176
|
+
skill: matchingSkill.relName
|
|
181
177
|
});
|
|
182
178
|
}
|
|
183
179
|
return signals;
|
|
@@ -217,12 +213,10 @@ 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
|
-
|
|
223
|
-
relName,
|
|
217
|
+
relName: toPosixPath(relative(skillsDir, filePath)).replace(/[/\\]SKILL\.md$/, ""),
|
|
224
218
|
filePath,
|
|
225
|
-
libraryVersion: fm
|
|
219
|
+
libraryVersion: readScalarField(fm, "library_version"),
|
|
226
220
|
sources: Array.isArray(fm?.sources) ? fm.sources : void 0
|
|
227
221
|
};
|
|
228
222
|
});
|
|
@@ -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.
|
|
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.
|
|
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 };
|
|
@@ -117,37 +117,5 @@ interface IntentArtifactWarning {
|
|
|
117
117
|
artifactPath: string;
|
|
118
118
|
message: string;
|
|
119
119
|
}
|
|
120
|
-
interface FeedbackPayload {
|
|
121
|
-
skill: string;
|
|
122
|
-
package: string;
|
|
123
|
-
skillVersion: string;
|
|
124
|
-
task: string;
|
|
125
|
-
whatWorked: string;
|
|
126
|
-
whatFailed: string;
|
|
127
|
-
missing: string;
|
|
128
|
-
selfCorrections: string;
|
|
129
|
-
userRating: 'good' | 'mixed' | 'bad';
|
|
130
|
-
userComments?: string;
|
|
131
|
-
}
|
|
132
|
-
type MetaSkillName = 'domain-discovery' | 'tree-generator' | 'generate-skill' | 'skill-staleness-check';
|
|
133
|
-
type AgentName = 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other';
|
|
134
|
-
interface MetaFeedbackPayload {
|
|
135
|
-
metaSkill: MetaSkillName;
|
|
136
|
-
library: string;
|
|
137
|
-
agentUsed: AgentName;
|
|
138
|
-
artifactQuality: 'good' | 'mixed' | 'bad';
|
|
139
|
-
interviewQuality?: 'good' | 'mixed' | 'bad' | 'skipped';
|
|
140
|
-
failureModeQuality?: 'good' | 'mixed' | 'bad' | 'not-applicable';
|
|
141
|
-
whatWorked: string;
|
|
142
|
-
whatFailed: string;
|
|
143
|
-
suggestions: string;
|
|
144
|
-
userRating: 'good' | 'mixed' | 'bad';
|
|
145
|
-
}
|
|
146
|
-
type FeedbackFrequency = 'always' | 'never' | `every-${number}`;
|
|
147
|
-
interface IntentProjectConfig {
|
|
148
|
-
feedback: {
|
|
149
|
-
frequency: FeedbackFrequency;
|
|
150
|
-
};
|
|
151
|
-
}
|
|
152
120
|
//#endregion
|
|
153
|
-
export { VersionConflict as
|
|
121
|
+
export { VersionConflict as _, IntentArtifactWarning as a, PackageManager as c, ScanScope as d, ScanStats as f, StalenessSignal as g, StalenessReport as h, IntentArtifactSkill as i, ScanOptions as l, SkillStaleness as m, IntentArtifactFile as n, IntentConfig as o, SkillEntry as p, IntentArtifactSet as r, IntentPackage as s, IntentArtifactCoverageIgnore as t, ScanResult as u };
|
|
@@ -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,
|
|
@@ -230,6 +229,19 @@ function resolveDepDir(depName, parentDir) {
|
|
|
230
229
|
return null;
|
|
231
230
|
}
|
|
232
231
|
/**
|
|
232
|
+
* Read a scalar string field from frontmatter, preferring `metadata.<key>` over
|
|
233
|
+
* a top-level `<key>` (#159 back-compat for the frontmatter migration).
|
|
234
|
+
*/
|
|
235
|
+
function readScalarField(fm, key) {
|
|
236
|
+
const metadata = fm?.metadata;
|
|
237
|
+
if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
|
|
238
|
+
const nested = metadata[key];
|
|
239
|
+
if (typeof nested === "string") return nested;
|
|
240
|
+
}
|
|
241
|
+
const top = fm?.[key];
|
|
242
|
+
return typeof top === "string" ? top : void 0;
|
|
243
|
+
}
|
|
244
|
+
/**
|
|
233
245
|
* Parse YAML frontmatter from a file. Returns null if no frontmatter or on error.
|
|
234
246
|
*/
|
|
235
247
|
function parseFrontmatter(filePath, fs = nodeReadFs) {
|
|
@@ -277,6 +289,5 @@ function readFrontmatterRegion(filePath, fs) {
|
|
|
277
289
|
return null;
|
|
278
290
|
}
|
|
279
291
|
}
|
|
280
|
-
|
|
281
292
|
//#endregion
|
|
282
|
-
export { listNestedNodeModulesPackageDirs as a, parseFrontmatter as c, getDeps as i,
|
|
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 };
|
|
@@ -0,0 +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-6FtqhOYf.mjs";
|
|
2
|
+
export { createFsIdentityCache, detectGlobalNodeModules, findSkillFiles, getDeps, listNestedNodeModulesPackageDirs, listNodeModulesPackageDirs, nodeReadFs, parseFrontmatter, readScalarField, resolveDepDir, toPosixPath };
|
|
@@ -1,13 +1,29 @@
|
|
|
1
|
-
import "./
|
|
2
|
-
import {
|
|
3
|
-
import { t as
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
6
|
-
import {
|
|
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
|
|
52
|
-
const
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
for (const
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
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 }] = await Promise.all([import("yaml"), import("./utils-
|
|
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,22 +223,49 @@ async function runValidateCommandInternal(dir) {
|
|
|
175
223
|
message: "Missing required field: description"
|
|
176
224
|
});
|
|
177
225
|
if (typeof fm.name === "string") {
|
|
178
|
-
const
|
|
179
|
-
if (fm.name
|
|
226
|
+
const parentDir = basename(dirname(filePath));
|
|
227
|
+
if (fm.name.length > 64) errors.push({
|
|
180
228
|
file: rel,
|
|
181
|
-
message: `name
|
|
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({
|
|
185
261
|
file: rel,
|
|
186
262
|
message: `Description exceeds 1024 character limit (${fm.description.length} chars)`
|
|
187
263
|
});
|
|
188
|
-
if (fm
|
|
264
|
+
if (readScalarField(fm, "type") === "framework" && !Array.isArray(fm.requires)) errors.push({
|
|
189
265
|
file: rel,
|
|
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
|
|
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 };
|
|
@@ -1,9 +1,8 @@
|
|
|
1
|
-
import { r as findSkillFiles } from "./utils-
|
|
1
|
+
import { r as findSkillFiles } from "./utils-6FtqhOYf.mjs";
|
|
2
2
|
import { existsSync, readFileSync, readdirSync } from "node:fs";
|
|
3
3
|
import { dirname, join } from "node:path";
|
|
4
4
|
import { parse } from "yaml";
|
|
5
5
|
import { parse as parse$1 } from "jsonc-parser";
|
|
6
|
-
|
|
7
6
|
//#region src/workspace-patterns.ts
|
|
8
7
|
function normalizeWorkspacePattern(pattern) {
|
|
9
8
|
return pattern.replace(/\\/g, "/").replace(/^\.\//, "").replace(/\/+$/, "");
|
|
@@ -189,6 +188,5 @@ function findPackagesWithSkills(root) {
|
|
|
189
188
|
function findWorkspacePackages(root) {
|
|
190
189
|
return readWorkspacePackageDirs(root) ?? [];
|
|
191
190
|
}
|
|
192
|
-
|
|
193
191
|
//#endregion
|
|
194
|
-
export { readWorkspacePatterns as a, getWorkspaceInfo as i, findWorkspacePackages as n, resolveWorkspacePackages as o, findWorkspaceRoot as r, findPackagesWithSkills as t };
|
|
192
|
+
export { readWorkspacePatterns as a, getWorkspaceInfo as i, findWorkspacePackages as n, resolveWorkspacePackages as o, findWorkspaceRoot as r, findPackagesWithSkills as t };
|
|
@@ -572,7 +572,7 @@ Include the full draft domain_map.yaml in your message so the maintainer
|
|
|
572
572
|
can review it. Also include a checklist of all docs files you read.
|
|
573
573
|
|
|
574
574
|
**── STOP ── Do not proceed to Phase 4 until the maintainer has
|
|
575
|
-
reviewed the draft and responded. Their
|
|
575
|
+
reviewed the draft and responded. Their response to the draft informs
|
|
576
576
|
the detail interview questions.**
|
|
577
577
|
|
|
578
578
|
---
|