@tanstack/intent 0.0.44 → 0.1.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (54) hide show
  1. package/README.md +0 -3
  2. package/dist/artifact-coverage-BfJ7f-S9.mjs +3 -0
  3. package/dist/cli-support-BADtMg6z.mjs +6 -0
  4. package/dist/{cli-support-BNDR3l1g.mjs → cli-support-C8SKYTA4.mjs} +35 -9
  5. package/dist/cli.mjs +17 -13
  6. package/dist/{core-qlBI_aQL.mjs → core-hEMP5GMV.mjs} +33 -17
  7. package/dist/core.d.mts +4 -2
  8. package/dist/core.mjs +9 -7
  9. package/dist/{display-0FnzlKRq.mjs → display-CFnFnrtx.mjs} +2 -2
  10. package/dist/exclude-CBxkyK3Q.mjs +126 -0
  11. package/dist/excludes-DDMe-4iu.mjs +111 -0
  12. package/dist/index.d.mts +3 -30
  13. package/dist/index.mjs +13 -278
  14. package/dist/{install-D1dsnbr9.mjs → install-BE7gVoNT.mjs} +15 -11
  15. package/dist/{list-DrChOziX.mjs → list-UqYivAcV.mjs} +17 -15
  16. package/dist/{load-ll7s5E3J.mjs → load-Dgw151E3.mjs} +11 -9
  17. package/dist/{meta-BEJIfnPG.mjs → meta-BZMVgIzJ.mjs} +1 -1
  18. package/dist/{project-context-BRIMzhi4.mjs → project-context-DDCie6Ro.mjs} +1 -1
  19. package/dist/{resolver-D9cjsz11.mjs → resolver-CZXZ0rft.mjs} +3 -86
  20. package/dist/{scanner-DaG82zNc.mjs → scanner-2XDBAsbm.mjs} +7 -5
  21. package/dist/{setup-BklJkH_6.mjs → setup-CMec7fht.mjs} +2 -2
  22. package/dist/setup.d.mts +1 -1
  23. package/dist/setup.mjs +4 -4
  24. package/dist/{skill-paths-B-j0dWDA.mjs → skill-paths-Cr74uFk4.mjs} +1 -1
  25. package/dist/source-policy-D4slvwwI.mjs +9 -0
  26. package/dist/source-policy-rGOtjQSM.mjs +247 -0
  27. package/dist/{stale-C6dPKQ98.mjs → stale-DxZyYibt.mjs} +4 -2
  28. package/dist/{staleness-BGFfic-Y.mjs → staleness-B8IvDS_9.mjs} +3 -3
  29. package/dist/staleness-Ctzy2Zac.mjs +5 -0
  30. package/dist/{types-CIha6LtJ.d.mts → types-oEflMSso.d.mts} +2 -33
  31. package/dist/utils-BuNMwKct.mjs +3 -0
  32. package/dist/{utils-9fhWAVua.mjs → utils-Dj49bkF_.mjs} +14 -1
  33. package/dist/{validate-CEhp9gDs.mjs → validate-B3pkTIZl.mjs} +6 -6
  34. package/dist/{workflow-review-CrWkP7Hc.mjs → workflow-review-CtOR1bgh.mjs} +1 -1
  35. package/dist/{workspace-patterns-Bjq_cXww.mjs → workspace-patterns-BBW4c1gr.mjs} +2 -2
  36. package/dist/{workspace-patterns-BffPlZ1D.mjs → workspace-patterns-Cz_lNhwz.mjs} +1 -1
  37. package/meta/domain-discovery/SKILL.md +1 -1
  38. package/meta/generate-skill/SKILL.md +1 -8
  39. package/meta/tree-generator/SKILL.md +1 -1
  40. package/package.json +1 -1
  41. package/dist/artifact-coverage-DA26utB1.mjs +0 -3
  42. package/dist/cli-support-BtHFD7gl.mjs +0 -6
  43. package/dist/scanner-BV7X5n_z.mjs +0 -6
  44. package/dist/staleness-CB3qpVCq.mjs +0 -5
  45. package/dist/utils-CSPzvaFu.mjs +0 -3
  46. package/meta/feedback-collection/SKILL.md +0 -234
  47. /package/dist/{artifact-coverage-DgWuVqUp.mjs → artifact-coverage-nGwun1tt.mjs} +0 -0
  48. /package/dist/{command-runner-C0yCOHLi.mjs → command-runner-fstUIUhe.mjs} +0 -0
  49. /package/dist/{edit-package-json-CtuelQ_q.mjs → edit-package-json-DKyJ04t1.mjs} +0 -0
  50. /package/dist/{scaffold-CLM6bt3c.mjs → scaffold-D2vwv9ls.mjs} +0 -0
  51. /package/dist/{setup-DhMqESd3.d.mts → setup-DW3pn0QW.d.mts} +0 -0
  52. /package/dist/{setup-github-actions-CUd1oncY.mjs → setup-github-actions-emXSyGy3.mjs} +0 -0
  53. /package/dist/{skill-use-umYvZl94.mjs → skill-use-CUrNHf-u.mjs} +0 -0
  54. /package/dist/{workflow-review-D9Fg1G0P.mjs → workflow-review-wL1Iu2Sf.mjs} +0 -0
@@ -0,0 +1,9 @@
1
+ import "./utils-Dj49bkF_.mjs";
2
+ import "./skill-paths-Cr74uFk4.mjs";
3
+ import "./scanner-2XDBAsbm.mjs";
4
+ import "./workspace-patterns-Cz_lNhwz.mjs";
5
+ import "./project-context-DDCie6Ro.mjs";
6
+ import "./excludes-DDMe-4iu.mjs";
7
+ import { a as checkLoadAllowed, i as applySourcePolicy, n as EMPTY_NOTE, o as readSkillSourcesConfig, r as MIGRATION_NOTICE, s as scanForPolicedIntents, t as ALLOW_ALL_NOTICE } from "./source-policy-rGOtjQSM.mjs";
8
+
9
+ export { scanForPolicedIntents };
@@ -0,0 +1,247 @@
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
+
5
+ //#region src/core/skill-sources.ts
6
+ var SkillSourcesParseError = class extends Error {
7
+ constructor(issues) {
8
+ super(formatIssues(issues));
9
+ this.name = "SkillSourcesParseError";
10
+ this.issues = issues;
11
+ }
12
+ };
13
+ /**
14
+ * Strictness is fail-whole-list: every malformed entry is collected and
15
+ * reported together, and a single bad entry rejects the entire list rather
16
+ * than silently applying a partial allowlist.
17
+ */
18
+ function parseSkillSources(value) {
19
+ if (value === void 0 || value === null) return { mode: "absent" };
20
+ if (!Array.isArray(value)) throw new SkillSourcesParseError([{
21
+ raw: null,
22
+ message: `intent.skills must be an array of source strings, received ${describeType(value)}.`
23
+ }]);
24
+ if (value.length === 0) return { mode: "empty" };
25
+ const issues = [];
26
+ const sources = [];
27
+ const seenRaw = /* @__PURE__ */ new Set();
28
+ const seenIdentity = /* @__PURE__ */ new Set();
29
+ let allowAll = false;
30
+ for (const entry of value) {
31
+ if (typeof entry !== "string") {
32
+ issues.push({
33
+ raw: null,
34
+ message: `Entry must be a string, received ${describeType(entry)}.`
35
+ });
36
+ continue;
37
+ }
38
+ if (seenRaw.has(entry)) {
39
+ issues.push({
40
+ raw: entry,
41
+ message: "Duplicate entry."
42
+ });
43
+ continue;
44
+ }
45
+ seenRaw.add(entry);
46
+ const trimmed = entry.trim();
47
+ if (trimmed === "") {
48
+ issues.push({
49
+ raw: entry,
50
+ message: "Entry is empty."
51
+ });
52
+ continue;
53
+ }
54
+ if (entry.includes("*")) {
55
+ if (entry === "*") {
56
+ allowAll = true;
57
+ continue;
58
+ }
59
+ issues.push({
60
+ raw: entry,
61
+ message: "The \"*\" wildcard must be the exact entry \"*\"; globs are not supported in intent.skills."
62
+ });
63
+ continue;
64
+ }
65
+ const parsed = parseEntry(entry, trimmed);
66
+ if ("message" in parsed) {
67
+ issues.push(parsed);
68
+ continue;
69
+ }
70
+ const identity = `${parsed.kind}\u0000${parsed.id}`;
71
+ if (seenIdentity.has(identity)) continue;
72
+ seenIdentity.add(identity);
73
+ sources.push(parsed);
74
+ }
75
+ if (issues.length > 0) throw new SkillSourcesParseError(issues);
76
+ if (allowAll) return { mode: "allow-all" };
77
+ return {
78
+ mode: "explicit",
79
+ sources
80
+ };
81
+ }
82
+ function parseEntry(raw, trimmed) {
83
+ const colon = trimmed.indexOf(":");
84
+ if (colon === -1) {
85
+ const invalid = validateId(trimmed);
86
+ if (invalid) return {
87
+ raw,
88
+ message: `Invalid npm source "${trimmed}": ${invalid}`
89
+ };
90
+ return {
91
+ raw,
92
+ id: trimmed,
93
+ kind: "npm"
94
+ };
95
+ }
96
+ const prefix = trimmed.slice(0, colon);
97
+ const rest = trimmed.slice(colon + 1).trim();
98
+ switch (prefix) {
99
+ case "workspace": {
100
+ if (rest === "") return {
101
+ raw,
102
+ message: `Workspace source "${trimmed}" is missing a package name.`
103
+ };
104
+ const invalid = validateId(rest);
105
+ if (invalid) return {
106
+ raw,
107
+ message: `Invalid workspace source "${trimmed}": ${invalid}`
108
+ };
109
+ return {
110
+ raw,
111
+ id: rest,
112
+ kind: "workspace"
113
+ };
114
+ }
115
+ case "git": return {
116
+ raw,
117
+ message: `Git source "${trimmed}" is not supported until the lockfile lands (M2).`
118
+ };
119
+ default: return {
120
+ raw,
121
+ message: `Unknown source prefix "${prefix}" in "${trimmed}".`
122
+ };
123
+ }
124
+ }
125
+ function validateId(id) {
126
+ if (id.includes("#")) return "skill-level granularity (#) is not supported in intent.skills (it is package-level); use intent.exclude for skill-level control.";
127
+ if (/\s/.test(id)) return "package names cannot contain whitespace.";
128
+ if (id.includes(":")) return "package names cannot contain \":\".";
129
+ return null;
130
+ }
131
+ function describeType(value) {
132
+ if (value === null) return "null";
133
+ return Array.isArray(value) ? "array" : typeof value;
134
+ }
135
+ function formatIssues(issues) {
136
+ return ["Invalid intent.skills configuration:", ...issues.map((issue) => issue.raw === null ? ` - ${issue.message}` : ` - "${issue.raw}": ${issue.message}`)].join("\n");
137
+ }
138
+
139
+ //#endregion
140
+ //#region src/core/source-policy.ts
141
+ const ALLOW_ALL_NOTICE = "All skill sources allowed (intent.skills: [\"*\"]) — unvetted skills may be surfaced into agent guidance.";
142
+ const MIGRATION_NOTICE = "intent.skills is not set — all discovered skill sources are surfaced. A future version will require an explicit intent.skills allowlist; add one to opt in to specific sources.";
143
+ const EMPTY_NOTE = "intent.skills is empty — no skill sources are permitted.";
144
+ function isSourcePermitted(config, packageName) {
145
+ switch (config.mode) {
146
+ case "absent":
147
+ case "allow-all": return true;
148
+ case "empty": return false;
149
+ case "explicit": return config.sources.some((source) => source.id === packageName);
150
+ }
151
+ }
152
+ function checkLoadAllowed(use, parsed, params) {
153
+ const { config, excludeMatchers } = params;
154
+ const { packageName, skillName } = parsed;
155
+ if (isPackageExcluded(packageName, excludeMatchers)) return {
156
+ code: "package-excluded",
157
+ message: `Cannot load skill use "${use}": package "${packageName}" is excluded by Intent configuration.`
158
+ };
159
+ if (!isSourcePermitted(config, packageName)) return {
160
+ code: "package-not-listed",
161
+ message: `Cannot load skill use "${use}": package "${packageName}" is not listed in intent.skills.`
162
+ };
163
+ if (isSkillExcluded(packageName, skillName, excludeMatchers)) return {
164
+ code: "skill-excluded",
165
+ message: `Cannot load skill use "${use}": skill "${packageName}#${skillName}" is excluded by Intent configuration.`
166
+ };
167
+ return null;
168
+ }
169
+ function formatUnlistedNotice(names) {
170
+ const sorted = [...names].sort();
171
+ const noun = sorted.length === 1 ? "package ships" : "packages ship";
172
+ return `${sorted.length} discovered ${noun} skills but ${sorted.length === 1 ? "is" : "are"} not listed in intent.skills: ${sorted.join(", ")}. Add to opt in.`;
173
+ }
174
+ function applySourcePolicy(scanResult, options) {
175
+ const { config, excludeMatchers } = options;
176
+ const seen = /* @__PURE__ */ new Set();
177
+ const notices = [];
178
+ const emit = (notice) => {
179
+ if (seen.has(notice)) return;
180
+ seen.add(notice);
181
+ notices.push(notice);
182
+ };
183
+ const packages = [];
184
+ const unlistedNames = [];
185
+ for (const pkg of scanResult.packages) {
186
+ if (isPackageExcluded(pkg.name, excludeMatchers)) continue;
187
+ if (!isSourcePermitted(config, pkg.name)) {
188
+ if (config.mode === "explicit") unlistedNames.push(pkg.name);
189
+ continue;
190
+ }
191
+ const skills = pkg.skills.filter((skill) => !isSkillExcluded(pkg.name, skill.name, excludeMatchers));
192
+ packages.push(skills.length === pkg.skills.length ? pkg : {
193
+ ...pkg,
194
+ skills
195
+ });
196
+ }
197
+ if (unlistedNames.length > 0) emit(formatUnlistedNotice(unlistedNames));
198
+ if (config.mode === "explicit") {
199
+ const discoveredNames = new Set(scanResult.packages.map((pkg) => pkg.name));
200
+ for (const source of config.sources) if (!discoveredNames.has(source.id)) emit(`"${source.raw}" is declared in intent.skills but was not discovered.`);
201
+ }
202
+ if (config.mode === "absent") emit(MIGRATION_NOTICE);
203
+ else if (config.mode === "allow-all") emit(ALLOW_ALL_NOTICE);
204
+ else if (config.mode === "empty") emit(EMPTY_NOTE);
205
+ return {
206
+ packages,
207
+ notices
208
+ };
209
+ }
210
+ function readSkillSourcesConfig(cwd, context = resolveProjectContext({ cwd })) {
211
+ for (const dir of getConfigDirs(cwd, context)) {
212
+ const intent = readPackageJson(dir)?.intent;
213
+ if (!intent || typeof intent !== "object") continue;
214
+ if ("skills" in intent) {
215
+ const skills = intent.skills;
216
+ if (skills === null || skills === void 0) continue;
217
+ return parseSkillSources(skills);
218
+ }
219
+ }
220
+ return { mode: "absent" };
221
+ }
222
+ function scanForPolicedIntents(params) {
223
+ const { cwd, scanOptions, coreOptions } = params;
224
+ const context = params.context ?? resolveProjectContext({ cwd });
225
+ const scanResult = scanForIntents(cwd, scanOptions);
226
+ const config = readSkillSourcesConfig(cwd, context);
227
+ const excludePatterns = getEffectiveExcludePatterns(coreOptions, context);
228
+ const policy = applySourcePolicy(scanResult, {
229
+ config,
230
+ excludeMatchers: compileExcludePatterns(excludePatterns)
231
+ });
232
+ const survivingNames = new Set(policy.packages.map((pkg) => pkg.name));
233
+ const droppedNames = scanResult.packages.map((pkg) => pkg.name).filter((name) => !survivingNames.has(name));
234
+ return {
235
+ scan: {
236
+ ...scanResult,
237
+ packages: policy.packages,
238
+ warnings: scanResult.warnings.filter((warning) => !droppedNames.some((name) => warningMentionsPackage(warning, name))),
239
+ notices: policy.notices,
240
+ conflicts: scanResult.conflicts.filter((conflict) => survivingNames.has(conflict.packageName))
241
+ },
242
+ excludePatterns
243
+ };
244
+ }
245
+
246
+ //#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 };
@@ -1,3 +1,5 @@
1
+ import { n as isCliFailure } from "./cli-error-BrMXlbtx.mjs";
2
+
1
3
  //#region src/commands/stale.ts
2
4
  async function runStaleCommand(targetDir, options, resolveStaleTargets) {
3
5
  if (options.githubReview) {
@@ -33,7 +35,7 @@ async function runStaleCommand(targetDir, options, resolveStaleTargets) {
33
35
  }
34
36
  }
35
37
  async function runGithubReview(targetDir, options, resolveStaleTargets) {
36
- const { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles } = await import("./workflow-review-CrWkP7Hc.mjs");
38
+ const { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles } = await import("./workflow-review-CtOR1bgh.mjs");
37
39
  const packageLabel = options.packageLabel ?? "workspace";
38
40
  try {
39
41
  const { reports, workflowAdvisories = [] } = await resolveStaleTargets(targetDir);
@@ -43,7 +45,7 @@ async function runGithubReview(targetDir, options, resolveStaleTargets) {
43
45
  else console.log(`Wrote ${items.length} intent skill review item(s).`);
44
46
  } catch (err) {
45
47
  writeStaleReviewWorkflowFiles([createFailedStaleReviewItem(packageLabel)]);
46
- const message = err instanceof Error ? err.message : String(err);
48
+ const message = isCliFailure(err) ? err.message : err instanceof Error ? err.message : String(err);
47
49
  console.log(`Intent stale check failed: ${message}`);
48
50
  console.log("Wrote a review PR body so maintainers can inspect the logs.");
49
51
  }
@@ -1,5 +1,5 @@
1
- import { c as parseFrontmatter, r as findSkillFiles, u as toPosixPath } from "./utils-9fhWAVua.mjs";
2
- import { t as readIntentArtifacts } from "./artifact-coverage-DgWuVqUp.mjs";
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";
3
3
  import { existsSync, readFileSync } from "node:fs";
4
4
  import { isAbsolute, join, relative, resolve } from "node:path";
5
5
  import semver from "semver";
@@ -222,7 +222,7 @@ async function checkStaleness(packageDir, packageName, artifactRoot = packageDir
222
222
  name: typeof fm?.name === "string" ? fm.name : relName,
223
223
  relName,
224
224
  filePath,
225
- libraryVersion: fm?.library_version,
225
+ libraryVersion: readScalarField(fm, "library_version"),
226
226
  sources: Array.isArray(fm?.sources) ? fm.sources : void 0
227
227
  };
228
228
  });
@@ -0,0 +1,5 @@
1
+ import "./utils-Dj49bkF_.mjs";
2
+ import "./artifact-coverage-nGwun1tt.mjs";
3
+ import { n as checkStaleness, r as readPackageName, t as buildWorkspaceCoverageSignals } from "./staleness-B8IvDS_9.mjs";
4
+
5
+ export { buildWorkspaceCoverageSignals, checkStaleness, readPackageName };
@@ -9,6 +9,7 @@ interface ScanResult {
9
9
  packageManager: PackageManager;
10
10
  packages: Array<IntentPackage>;
11
11
  warnings: Array<string>;
12
+ notices: Array<string>;
12
13
  conflicts: Array<VersionConflict>;
13
14
  nodeModules: {
14
15
  local: NodeModulesScanTarget;
@@ -116,37 +117,5 @@ interface IntentArtifactWarning {
116
117
  artifactPath: string;
117
118
  message: string;
118
119
  }
119
- interface FeedbackPayload {
120
- skill: string;
121
- package: string;
122
- skillVersion: string;
123
- task: string;
124
- whatWorked: string;
125
- whatFailed: string;
126
- missing: string;
127
- selfCorrections: string;
128
- userRating: 'good' | 'mixed' | 'bad';
129
- userComments?: string;
130
- }
131
- type MetaSkillName = 'domain-discovery' | 'tree-generator' | 'generate-skill' | 'skill-staleness-check';
132
- type AgentName = 'claude-code' | 'cursor' | 'copilot' | 'codex' | 'other';
133
- interface MetaFeedbackPayload {
134
- metaSkill: MetaSkillName;
135
- library: string;
136
- agentUsed: AgentName;
137
- artifactQuality: 'good' | 'mixed' | 'bad';
138
- interviewQuality?: 'good' | 'mixed' | 'bad' | 'skipped';
139
- failureModeQuality?: 'good' | 'mixed' | 'bad' | 'not-applicable';
140
- whatWorked: string;
141
- whatFailed: string;
142
- suggestions: string;
143
- userRating: 'good' | 'mixed' | 'bad';
144
- }
145
- type FeedbackFrequency = 'always' | 'never' | `every-${number}`;
146
- interface IntentProjectConfig {
147
- feedback: {
148
- frequency: FeedbackFrequency;
149
- };
150
- }
151
120
  //#endregion
152
- export { VersionConflict as S, ScanStats as _, IntentArtifactSet as a, StalenessReport as b, IntentConfig as c, MetaFeedbackPayload as d, MetaSkillName as f, ScanScope as g, ScanResult as h, IntentArtifactFile as i, IntentPackage as l, ScanOptions as m, FeedbackPayload as n, IntentArtifactSkill as o, PackageManager as p, IntentArtifactCoverageIgnore as r, IntentArtifactWarning as s, AgentName as t, IntentProjectConfig as u, SkillEntry as v, StalenessSignal as x, SkillStaleness as y };
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 };
@@ -0,0 +1,3 @@
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 };
@@ -230,6 +230,19 @@ function resolveDepDir(depName, parentDir) {
230
230
  return null;
231
231
  }
232
232
  /**
233
+ * Read a scalar string field from frontmatter, preferring `metadata.<key>` over
234
+ * a top-level `<key>` (#159 back-compat for the frontmatter migration).
235
+ */
236
+ function readScalarField(fm, key) {
237
+ const metadata = fm?.metadata;
238
+ if (metadata && typeof metadata === "object" && !Array.isArray(metadata)) {
239
+ const nested = metadata[key];
240
+ if (typeof nested === "string") return nested;
241
+ }
242
+ const top = fm?.[key];
243
+ return typeof top === "string" ? top : void 0;
244
+ }
245
+ /**
233
246
  * Parse YAML frontmatter from a file. Returns null if no frontmatter or on error.
234
247
  */
235
248
  function parseFrontmatter(filePath, fs = nodeReadFs) {
@@ -279,4 +292,4 @@ function readFrontmatterRegion(filePath, fs) {
279
292
  }
280
293
 
281
294
  //#endregion
282
- export { listNestedNodeModulesPackageDirs as a, parseFrontmatter as c, getDeps as i, resolveDepDir as l, detectGlobalNodeModules as n, listNodeModulesPackageDirs as o, findSkillFiles as r, nodeReadFs as s, createFsIdentityCache as t, toPosixPath as u };
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 };
@@ -1,8 +1,8 @@
1
- import "./utils-9fhWAVua.mjs";
2
- import { n as findWorkspacePackages } from "./workspace-patterns-BffPlZ1D.mjs";
3
- import { t as resolveProjectContext } from "./project-context-BRIMzhi4.mjs";
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
4
  import { n as isCliFailure, t as fail } from "./cli-error-BrMXlbtx.mjs";
5
- import { l as printWarnings } from "./cli-support-BNDR3l1g.mjs";
5
+ import { u as printWarnings } from "./cli-support-C8SKYTA4.mjs";
6
6
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
7
7
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
8
 
@@ -115,7 +115,7 @@ async function runValidateCommand(dir, options = {}) {
115
115
  }
116
116
  }
117
117
  async function runValidateCommandInternal(dir) {
118
- const [{ parse: parseYaml }, { findSkillFiles }] = await Promise.all([import("yaml"), import("./utils-CSPzvaFu.mjs")]);
118
+ const [{ parse: parseYaml }, { findSkillFiles, readScalarField }] = await Promise.all([import("yaml"), import("./utils-BuNMwKct.mjs")]);
119
119
  const context = resolveProjectContext({
120
120
  cwd: process.cwd(),
121
121
  targetPath: dir
@@ -185,7 +185,7 @@ async function runValidateCommandInternal(dir) {
185
185
  file: rel,
186
186
  message: `Description exceeds 1024 character limit (${fm.description.length} chars)`
187
187
  });
188
- if (fm.type === "framework" && !Array.isArray(fm.requires)) errors.push({
188
+ if (readScalarField(fm, "type") === "framework" && !Array.isArray(fm.requires)) errors.push({
189
189
  file: rel,
190
190
  message: "Framework skills must have a \"requires\" field"
191
191
  });
@@ -1,3 +1,3 @@
1
- import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem, t as buildStaleReviewBody } from "./workflow-review-D9Fg1G0P.mjs";
1
+ import { a as writeStaleReviewWorkflowFiles, i as createWorkflowAdvisoryReviewItems, n as collectStaleReviewItems, r as createFailedStaleReviewItem, t as buildStaleReviewBody } from "./workflow-review-wL1Iu2Sf.mjs";
2
2
 
3
3
  export { collectStaleReviewItems, createFailedStaleReviewItem, createWorkflowAdvisoryReviewItems, writeStaleReviewWorkflowFiles };
@@ -1,4 +1,4 @@
1
- import "./utils-9fhWAVua.mjs";
2
- import { a as readWorkspacePatterns, i as getWorkspaceInfo, n as findWorkspacePackages, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BffPlZ1D.mjs";
1
+ import "./utils-Dj49bkF_.mjs";
2
+ import { a as readWorkspacePatterns, i as getWorkspaceInfo, n as findWorkspacePackages, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-Cz_lNhwz.mjs";
3
3
 
4
4
  export { findWorkspaceRoot, getWorkspaceInfo };
@@ -1,4 +1,4 @@
1
- import { r as findSkillFiles } from "./utils-9fhWAVua.mjs";
1
+ import { r as findSkillFiles } from "./utils-Dj49bkF_.mjs";
2
2
  import { existsSync, readFileSync, readdirSync } from "node:fs";
3
3
  import { dirname, join } from "node:path";
4
4
  import { parse } from "yaml";
@@ -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 feedback on the draft informs
575
+ reviewed the draft and responded. Their response to the draft informs
576
576
  the detail interview questions.**
577
577
 
578
578
  ---
@@ -118,7 +118,7 @@ cannot already know:
118
118
 
119
119
  Before writing the skill body, search the library's GitHub repo for issues
120
120
  and discussions relevant to THIS skill's topic. This step is important for
121
- both initial generation and regeneration — community feedback reveals
121
+ both initial generation and regeneration — issue discussions reveal
122
122
  failure modes that docs miss.
123
123
 
124
124
  **Search strategy:**
@@ -443,11 +443,4 @@ Output is consumed by all major AI coding agents. To ensure consistency:
443
443
  - Critical info at start or end of sections (not buried in middle)
444
444
  - Each SKILL.md is self-contained except for declared `requires`
445
445
 
446
- ---
447
-
448
- ## Meta-skill feedback
449
-
450
- After generating all skills, run the `skill-feedback-collection` skill to
451
- capture feedback about the scaffolding process (domain-discovery,
452
- tree-generator, and generate-skill).
453
446
  ```
@@ -702,7 +702,7 @@ Run when:
702
702
  - The library has released a new version
703
703
  - A maintainer reports skills produce outdated code
704
704
  - A changelog or migration guide has been published since skill creation
705
- - Feedback reports indicate skill content is inaccurate
705
+ - Issue reports indicate skill content is inaccurate
706
706
 
707
707
  ### Step 1 — Detect staleness
708
708
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/intent",
3
- "version": "0.0.44",
3
+ "version": "0.1.1",
4
4
  "description": "Ship compositional knowledge for AI coding agents alongside your npm packages",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -1,3 +0,0 @@
1
- import { t as readIntentArtifacts } from "./artifact-coverage-DgWuVqUp.mjs";
2
-
3
- export { readIntentArtifacts };
@@ -1,6 +0,0 @@
1
- import "./utils-9fhWAVua.mjs";
2
- import "./workspace-patterns-BffPlZ1D.mjs";
3
- import "./project-context-BRIMzhi4.mjs";
4
- import { a as printDebugInfo, c as scanOptionsFromGlobalFlags, i as getMetaDir, l as printWarnings, n as coreOptionsFromGlobalFlags, o as resolveStaleTargets, r as getCheckSkillsWorkflowAdvisories, s as scanIntentsOrFail, t as INTENT_CHECK_SKILLS_WORKFLOW_VERSION } from "./cli-support-BNDR3l1g.mjs";
5
-
6
- export { INTENT_CHECK_SKILLS_WORKFLOW_VERSION, coreOptionsFromGlobalFlags, getCheckSkillsWorkflowAdvisories, getMetaDir, printDebugInfo, printWarnings, resolveStaleTargets, scanIntentsOrFail, scanOptionsFromGlobalFlags };
@@ -1,6 +0,0 @@
1
- import "./utils-9fhWAVua.mjs";
2
- import "./skill-paths-B-j0dWDA.mjs";
3
- import { n as scanIntentPackageAtRoot, t as scanForIntents } from "./scanner-DaG82zNc.mjs";
4
- import "./workspace-patterns-BffPlZ1D.mjs";
5
-
6
- export { scanForIntents };
@@ -1,5 +0,0 @@
1
- import "./utils-9fhWAVua.mjs";
2
- import "./artifact-coverage-DgWuVqUp.mjs";
3
- import { n as checkStaleness, r as readPackageName, t as buildWorkspaceCoverageSignals } from "./staleness-BGFfic-Y.mjs";
4
-
5
- export { buildWorkspaceCoverageSignals, checkStaleness, readPackageName };
@@ -1,3 +0,0 @@
1
- import { a as listNestedNodeModulesPackageDirs, c as parseFrontmatter, i as getDeps, l as resolveDepDir, n as detectGlobalNodeModules, o as listNodeModulesPackageDirs, r as findSkillFiles, s as nodeReadFs, t as createFsIdentityCache, u as toPosixPath } from "./utils-9fhWAVua.mjs";
2
-
3
- export { createFsIdentityCache, detectGlobalNodeModules, findSkillFiles, getDeps, listNestedNodeModulesPackageDirs, listNodeModulesPackageDirs, nodeReadFs, parseFrontmatter, resolveDepDir, toPosixPath };