@tanstack/intent 0.0.44 → 0.1.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 (42) hide show
  1. package/dist/artifact-coverage-BfJ7f-S9.mjs +3 -0
  2. package/dist/{cli-support-BNDR3l1g.mjs → cli-support-BevVu4gw.mjs} +34 -8
  3. package/dist/cli-support-Cpo_9JfL.mjs +6 -0
  4. package/dist/cli.mjs +17 -13
  5. package/dist/{core-qlBI_aQL.mjs → core-6UP6jyL8.mjs} +31 -15
  6. package/dist/core.d.mts +4 -2
  7. package/dist/core.mjs +6 -4
  8. package/dist/exclude-BTaE6TNh.mjs +126 -0
  9. package/dist/excludes-DG83YEzb.mjs +111 -0
  10. package/dist/index.d.mts +2 -2
  11. package/dist/index.mjs +9 -8
  12. package/dist/{install-D1dsnbr9.mjs → install-DXQsQQIL.mjs} +13 -9
  13. package/dist/{list-DrChOziX.mjs → list-CxB37mvm.mjs} +14 -8
  14. package/dist/{load-ll7s5E3J.mjs → load-Ch4UjIza.mjs} +8 -6
  15. package/dist/{resolver-D9cjsz11.mjs → resolver-CDbVXv4g.mjs} +3 -86
  16. package/dist/{scanner-DaG82zNc.mjs → scanner-CRCZwhKS.mjs} +2 -0
  17. package/dist/{setup-BklJkH_6.mjs → setup-DpCYUVSf.mjs} +1 -1
  18. package/dist/setup.d.mts +1 -1
  19. package/dist/setup.mjs +2 -2
  20. package/dist/source-policy-DaImacFt.mjs +247 -0
  21. package/dist/source-policy-y3sktvzu.mjs +9 -0
  22. package/dist/{stale-C6dPKQ98.mjs → stale-DxZyYibt.mjs} +4 -2
  23. package/dist/{staleness-CB3qpVCq.mjs → staleness-BoFc6DMh.mjs} +2 -2
  24. package/dist/{staleness-BGFfic-Y.mjs → staleness-DVFARTES.mjs} +1 -1
  25. package/dist/{types-CIha6LtJ.d.mts → types-DhITOzhi.d.mts} +1 -0
  26. package/dist/{validate-CEhp9gDs.mjs → validate-CnQBn6v9.mjs} +2 -2
  27. package/dist/{workflow-review-CrWkP7Hc.mjs → workflow-review-CtOR1bgh.mjs} +1 -1
  28. package/package.json +1 -1
  29. package/dist/artifact-coverage-DA26utB1.mjs +0 -3
  30. package/dist/cli-support-BtHFD7gl.mjs +0 -6
  31. package/dist/scanner-BV7X5n_z.mjs +0 -6
  32. /package/dist/{artifact-coverage-DgWuVqUp.mjs → artifact-coverage-nGwun1tt.mjs} +0 -0
  33. /package/dist/{command-runner-C0yCOHLi.mjs → command-runner-fstUIUhe.mjs} +0 -0
  34. /package/dist/{display-0FnzlKRq.mjs → display-CVMGtcHz.mjs} +0 -0
  35. /package/dist/{edit-package-json-CtuelQ_q.mjs → edit-package-json-DKyJ04t1.mjs} +0 -0
  36. /package/dist/{meta-BEJIfnPG.mjs → meta-C-t9P5Ls.mjs} +0 -0
  37. /package/dist/{project-context-BRIMzhi4.mjs → project-context-DBSibDPb.mjs} +0 -0
  38. /package/dist/{scaffold-CLM6bt3c.mjs → scaffold-D2vwv9ls.mjs} +0 -0
  39. /package/dist/{setup-DhMqESd3.d.mts → setup-DW3pn0QW.d.mts} +0 -0
  40. /package/dist/{setup-github-actions-CUd1oncY.mjs → setup-github-actions-emXSyGy3.mjs} +0 -0
  41. /package/dist/{skill-use-umYvZl94.mjs → skill-use-CUrNHf-u.mjs} +0 -0
  42. /package/dist/{workflow-review-D9Fg1G0P.mjs → workflow-review-wL1Iu2Sf.mjs} +0 -0
@@ -1,11 +1,11 @@
1
1
  import "./utils-9fhWAVua.mjs";
2
2
  import "./workspace-patterns-BffPlZ1D.mjs";
3
3
  import { t as detectPackageManager } from "./package-manager-BUgTjW9Q.mjs";
4
- import { i as parseSkillUse, n as formatSkillUse } from "./skill-use-umYvZl94.mjs";
5
- import "./project-context-BRIMzhi4.mjs";
4
+ import { i as parseSkillUse, n as formatSkillUse } from "./skill-use-CUrNHf-u.mjs";
5
+ import "./project-context-DBSibDPb.mjs";
6
6
  import { t as fail } from "./cli-error-BrMXlbtx.mjs";
7
- import { c as scanOptionsFromGlobalFlags, l as printWarnings } from "./cli-support-BNDR3l1g.mjs";
8
- import { t as formatIntentCommand } from "./command-runner-C0yCOHLi.mjs";
7
+ import { a as noticeOptionsFromGlobalFlags, l as printNotices, n as coreOptionsFromGlobalFlags, u as printWarnings } from "./cli-support-BevVu4gw.mjs";
8
+ import { t as formatIntentCommand } from "./command-runner-fstUIUhe.mjs";
9
9
  import { existsSync, mkdirSync, readFileSync, writeFileSync } from "node:fs";
10
10
  import { dirname, join, relative } from "node:path";
11
11
  import { parse } from "yaml";
@@ -343,9 +343,10 @@ function formatTargetPath(targetPath) {
343
343
  function formatMappingCount(mappingCount) {
344
344
  return `${mappingCount} ${mappingCount === 1 ? "mapping" : "mappings"}`;
345
345
  }
346
- function printNoActionableSkills(warnings) {
346
+ function printNoActionableSkills(warnings, notices, noticeOptions) {
347
347
  console.log("No intent-enabled skills found.");
348
348
  printWarnings(warnings);
349
+ printNotices(notices, noticeOptions);
349
350
  }
350
351
  function printPlacementTip(targetPath) {
351
352
  console.log(`Tip: Keep the intent-skills block near the top of ${formatTargetPath(targetPath)} so agents read it before task-specific instructions.`);
@@ -383,7 +384,8 @@ async function runInstallCommand(options, scanIntentsOrFail) {
383
384
  console.log(INSTALL_PROMPT);
384
385
  return;
385
386
  }
386
- const scanOptions = scanOptionsFromGlobalFlags(options);
387
+ const coreOptions = coreOptionsFromGlobalFlags(options);
388
+ const noticeOptions = noticeOptionsFromGlobalFlags(options);
387
389
  if (!options.map) {
388
390
  const generated$1 = buildIntentSkillGuidanceBlock(detectPackageManager());
389
391
  if (options.dryRun) {
@@ -408,17 +410,18 @@ async function runInstallCommand(options, scanIntentsOrFail) {
408
410
  printPlacementTip(result$1.targetPath);
409
411
  return;
410
412
  }
411
- const scanResult = await scanIntentsOrFail(scanOptions);
413
+ const scanResult = await scanIntentsOrFail(coreOptions);
412
414
  const generated = buildIntentSkillsBlock(scanResult);
413
415
  if (options.dryRun) {
414
416
  const targetPath = resolveIntentSkillsBlockTargetPath(process.cwd(), generated.mappingCount);
415
417
  if (!targetPath) {
416
- printNoActionableSkills(scanResult.warnings);
418
+ printNoActionableSkills(scanResult.warnings, scanResult.notices, noticeOptions);
417
419
  return;
418
420
  }
419
421
  console.log(`Generated ${formatMappingCount(generated.mappingCount)} for ${formatTargetPath(targetPath)}.`);
420
422
  console.log(generated.block);
421
423
  printWarnings(scanResult.warnings);
424
+ printNotices(scanResult.notices, noticeOptions);
422
425
  return;
423
426
  }
424
427
  const result = writeIntentSkillsBlock({
@@ -426,7 +429,7 @@ async function runInstallCommand(options, scanIntentsOrFail) {
426
429
  root: process.cwd()
427
430
  });
428
431
  if (!result.targetPath) {
429
- printNoActionableSkills(scanResult.warnings);
432
+ printNoActionableSkills(scanResult.warnings, scanResult.notices, noticeOptions);
430
433
  return;
431
434
  }
432
435
  const target = formatTargetPath(result.targetPath);
@@ -439,6 +442,7 @@ async function runInstallCommand(options, scanIntentsOrFail) {
439
442
  printWriteResult(result);
440
443
  printPlacementTip(result.targetPath);
441
444
  printWarnings(scanResult.warnings);
445
+ printNotices(scanResult.notices, noticeOptions);
442
446
  }
443
447
 
444
448
  //#endregion
@@ -1,12 +1,14 @@
1
1
  import "./utils-9fhWAVua.mjs";
2
2
  import "./skill-paths-B-j0dWDA.mjs";
3
- import "./scanner-DaG82zNc.mjs";
3
+ import "./scanner-CRCZwhKS.mjs";
4
4
  import "./workspace-patterns-BffPlZ1D.mjs";
5
- import "./project-context-BRIMzhi4.mjs";
6
- import "./resolver-D9cjsz11.mjs";
7
- import { n as listIntentSkills } from "./core-qlBI_aQL.mjs";
8
- import { a as printDebugInfo, l as printWarnings, n as coreOptionsFromGlobalFlags } from "./cli-support-BNDR3l1g.mjs";
9
- import { t as formatIntentCommand } from "./command-runner-C0yCOHLi.mjs";
5
+ import "./project-context-DBSibDPb.mjs";
6
+ import "./excludes-DG83YEzb.mjs";
7
+ import "./resolver-CDbVXv4g.mjs";
8
+ import { n as listIntentSkills } from "./core-6UP6jyL8.mjs";
9
+ import "./source-policy-DaImacFt.mjs";
10
+ import { a as noticeOptionsFromGlobalFlags, l as printNotices, n as coreOptionsFromGlobalFlags, o as printDebugInfo, u as printWarnings } from "./cli-support-BevVu4gw.mjs";
11
+ import { t as formatIntentCommand } from "./command-runner-fstUIUhe.mjs";
10
12
 
11
13
  //#region src/commands/list.ts
12
14
  function printListDebug(result) {
@@ -18,6 +20,7 @@ function printListDebug(result) {
18
20
  ["packages", result.debug.packageCount],
19
21
  ["skills", result.debug.skillCount],
20
22
  ["warnings", result.debug.warningCount],
23
+ ["notices", result.debug.noticeCount],
21
24
  ["conflicts", result.debug.conflictCount],
22
25
  ["packageJsonReadCount", result.debug.scan.packageJsonReadCount],
23
26
  ["packageJsonCacheHits", result.debug.scan.packageJsonCacheHits]
@@ -51,21 +54,23 @@ function getPackageSkills(pkg, skillsByPackageRoot) {
51
54
  function formatLoadCommand(skill, packageManager, scopeFlag) {
52
55
  return formatIntentCommand(packageManager, `load ${skill.use}${scopeFlag}`);
53
56
  }
54
- async function runListCommand(options, _scanIntentsOrFail) {
57
+ async function runListCommand(options) {
55
58
  const result = listIntentSkills(coreOptionsFromGlobalFlags(options));
59
+ const noticeOptions = noticeOptionsFromGlobalFlags(options);
56
60
  printListDebug(result);
57
61
  if (options.json) {
58
62
  const { debug: _debug, packageManager: _packageManager, ...jsonResult } = result;
59
63
  console.log(JSON.stringify(jsonResult, null, 2));
60
64
  return;
61
65
  }
62
- const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-0FnzlKRq.mjs");
66
+ const { computeSkillNameWidth, printSkillTree, printTable } = await import("./display-CVMGtcHz.mjs");
63
67
  if (result.packages.length === 0) {
64
68
  console.log("No intent-enabled packages found.");
65
69
  if (result.warnings.length > 0) {
66
70
  console.log();
67
71
  printWarnings(result.warnings);
68
72
  }
73
+ printNotices(result.notices, noticeOptions);
69
74
  return;
70
75
  }
71
76
  console.log(`\n${result.packages.length} intent-enabled packages, ${result.skills.length} skills\n`);
@@ -109,6 +114,7 @@ async function runListCommand(options, _scanIntentsOrFail) {
109
114
  console.log(" Load: node_modules/@tanstack/intent/meta/feedback-collection/SKILL.md");
110
115
  console.log();
111
116
  printWarnings(result.warnings);
117
+ printNotices(result.notices, noticeOptions);
112
118
  }
113
119
 
114
120
  //#endregion
@@ -1,12 +1,14 @@
1
1
  import "./utils-9fhWAVua.mjs";
2
2
  import "./skill-paths-B-j0dWDA.mjs";
3
- import "./scanner-DaG82zNc.mjs";
3
+ import "./scanner-CRCZwhKS.mjs";
4
4
  import "./workspace-patterns-BffPlZ1D.mjs";
5
- import "./project-context-BRIMzhi4.mjs";
6
- import "./resolver-D9cjsz11.mjs";
5
+ import "./project-context-DBSibDPb.mjs";
6
+ import "./excludes-DG83YEzb.mjs";
7
+ import "./resolver-CDbVXv4g.mjs";
7
8
  import { t as fail } from "./cli-error-BrMXlbtx.mjs";
8
- import { i as resolveIntentSkill, r as loadIntentSkill, t as IntentCoreError } from "./core-qlBI_aQL.mjs";
9
- import { a as printDebugInfo, n as coreOptionsFromGlobalFlags } from "./cli-support-BNDR3l1g.mjs";
9
+ import { i as resolveIntentSkill, r as loadIntentSkill, t as IntentCoreError } from "./core-6UP6jyL8.mjs";
10
+ import "./source-policy-DaImacFt.mjs";
11
+ import { n as coreOptionsFromGlobalFlags, o as printDebugInfo } from "./cli-support-BevVu4gw.mjs";
10
12
 
11
13
  //#region src/commands/load.ts
12
14
  function printLoadDebug(loaded) {
@@ -26,7 +28,7 @@ function printLoadDebug(loaded) {
26
28
  ["packageJsonCacheHits", loaded.debug.scan.packageJsonCacheHits]
27
29
  ]);
28
30
  }
29
- async function runLoadCommand(use, options, _scanIntentsOrFail) {
31
+ async function runLoadCommand(use, options) {
30
32
  if (!use) fail("Missing skill use. Expected: intent load <package>#<skill>");
31
33
  if (options.json && options.path) fail("Use either --json or --path, not both.");
32
34
  const coreOptions = coreOptionsFromGlobalFlags(options);
@@ -1,89 +1,6 @@
1
- import { i as parseSkillUse } from "./skill-use-umYvZl94.mjs";
2
- import { t as resolveProjectContext } from "./project-context-BRIMzhi4.mjs";
3
- import { readFileSync } from "node:fs";
4
- import { dirname, isAbsolute, join, relative, resolve } from "node:path";
1
+ import { i as parseSkillUse } from "./skill-use-CUrNHf-u.mjs";
2
+ import { o as warningMentionsPackage } from "./excludes-DG83YEzb.mjs";
5
3
 
6
- //#region src/core/package-json.ts
7
- function readPackageJson(dir) {
8
- try {
9
- return JSON.parse(readFileSync(join(dir, "package.json"), "utf8"));
10
- } catch {
11
- return null;
12
- }
13
- }
14
-
15
- //#endregion
16
- //#region src/core/excludes.ts
17
- const MAX_EXCLUDE_PATTERN_LENGTH = 200;
18
- const PACKAGE_NAME_BOUNDARY = /[^a-zA-Z0-9_.-]/;
19
- function normalizeExcludePatterns(value) {
20
- if (!Array.isArray(value)) return [];
21
- return value.filter((pattern) => typeof pattern === "string").map((pattern) => pattern.trim()).filter(Boolean);
22
- }
23
- function isWithinOrEqual(path, parentDir) {
24
- const rel = relative(parentDir, path);
25
- return rel === "" || !rel.startsWith("..") && !isAbsolute(rel);
26
- }
27
- function readPackageExcludes(dir) {
28
- const intent = readPackageJson(dir)?.intent;
29
- if (!intent || typeof intent !== "object") return [];
30
- return normalizeExcludePatterns(intent.exclude);
31
- }
32
- function getConfigExcludePatterns(cwd, context = resolveProjectContext({ cwd })) {
33
- const root = context.workspaceRoot ?? context.packageRoot ?? cwd;
34
- const dirs = [];
35
- let dir = cwd;
36
- while (isWithinOrEqual(dir, root)) {
37
- dirs.push(dir);
38
- if (dir === root) break;
39
- const next = dirname(dir);
40
- if (next === dir) break;
41
- dir = next;
42
- }
43
- return dirs.reverse().flatMap(readPackageExcludes);
44
- }
45
- function getEffectiveExcludePatterns(options = {}, context) {
46
- return [...getConfigExcludePatterns(context?.cwd ?? resolve(process.cwd(), options.cwd ?? process.cwd()), context), ...normalizeExcludePatterns(options.exclude)];
47
- }
48
- function normalizeGlobPattern(pattern) {
49
- if (pattern.length > MAX_EXCLUDE_PATTERN_LENGTH) throw new Error(`Intent exclude pattern is too long: ${pattern.length} characters. Maximum is ${MAX_EXCLUDE_PATTERN_LENGTH}.`);
50
- return pattern.replace(/\*+/g, "*");
51
- }
52
- function globToRegExp(pattern) {
53
- const source = normalizeGlobPattern(pattern).split("*").map((part) => part.replace(/[\\^$+?.()|[\]{}]/g, "\\$&")).join(".*");
54
- return /* @__PURE__ */ new RegExp(`^${source}$`);
55
- }
56
- function compileExcludePatterns(patterns) {
57
- return patterns.map((pattern) => {
58
- if (!pattern.includes("*")) {
59
- normalizeGlobPattern(pattern);
60
- return {
61
- pattern,
62
- matches: (packageName) => packageName === pattern
63
- };
64
- }
65
- const regex = globToRegExp(pattern);
66
- return {
67
- pattern,
68
- matches: (packageName) => regex.test(packageName)
69
- };
70
- });
71
- }
72
- function isPackageExcluded(packageName, matchers) {
73
- return matchers.some((matcher) => matcher.matches(packageName));
74
- }
75
- function warningMentionsPackage(warning, packageName) {
76
- let idx = warning.indexOf(packageName);
77
- while (idx !== -1) {
78
- const before = warning[idx - 1];
79
- const after = warning[idx + packageName.length];
80
- if ((before === void 0 || PACKAGE_NAME_BOUNDARY.test(before)) && (after === void 0 || PACKAGE_NAME_BOUNDARY.test(after))) return true;
81
- idx = warning.indexOf(packageName, idx + packageName.length);
82
- }
83
- return false;
84
- }
85
-
86
- //#endregion
87
4
  //#region src/resolver.ts
88
5
  var ResolveSkillUseError = class extends Error {
89
6
  constructor({ availablePackages = [], availableSkills = [], code, packageName, skillName, suggestedSkills = [], use }) {
@@ -192,4 +109,4 @@ function formatSkillSuggestions(packageName, skillNames) {
192
109
  }
193
110
 
194
111
  //#endregion
195
- export { compileExcludePatterns as a, warningMentionsPackage as c, resolveSkillUse as i, isResolveSkillUseError as n, getEffectiveExcludePatterns as o, resolveSkillEntry as r, isPackageExcluded as s, ResolveSkillUseError as t };
112
+ export { resolveSkillUse as i, isResolveSkillUseError as n, resolveSkillEntry as r, ResolveSkillUseError as t };
@@ -587,6 +587,7 @@ function scanForIntents(root, options = {}) {
587
587
  packageManager,
588
588
  packages,
589
589
  warnings,
590
+ notices: [],
590
591
  conflicts,
591
592
  nodeModules,
592
593
  stats: getStats()
@@ -603,6 +604,7 @@ function scanForIntents(root, options = {}) {
603
604
  packageManager,
604
605
  packages: topoSort(packages),
605
606
  warnings,
607
+ notices: [],
606
608
  conflicts,
607
609
  nodeModules,
608
610
  stats: getStats()
@@ -1,5 +1,5 @@
1
1
  import { a as readWorkspacePatterns, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BffPlZ1D.mjs";
2
- import { t as resolveProjectContext } from "./project-context-BRIMzhi4.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-DBSibDPb.mjs";
3
3
  import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from "node:fs";
4
4
  import { basename, join, relative } from "node:path";
5
5
 
package/dist/setup.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as runEditPackageJsonAll, c as findWorkspaceRoot, i as runEditPackageJson, l as readWorkspacePatterns, n as MonorepoResult, o as runSetupGithubActions, r as SetupGithubActionsResult, s as findPackagesWithSkills, t as EditPackageJsonResult, u as resolveWorkspacePackages } from "./setup-DhMqESd3.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-DW3pn0QW.mjs";
2
2
  export { EditPackageJsonResult, MonorepoResult, SetupGithubActionsResult, findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
package/dist/setup.mjs CHANGED
@@ -1,6 +1,6 @@
1
1
  import "./utils-9fhWAVua.mjs";
2
2
  import { a as readWorkspacePatterns, o as resolveWorkspacePackages, r as findWorkspaceRoot, t as findPackagesWithSkills } from "./workspace-patterns-BffPlZ1D.mjs";
3
- import "./project-context-BRIMzhi4.mjs";
4
- import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-BklJkH_6.mjs";
3
+ import "./project-context-DBSibDPb.mjs";
4
+ import { n as runEditPackageJsonAll, r as runSetupGithubActions, t as runEditPackageJson } from "./setup-DpCYUVSf.mjs";
5
5
 
6
6
  export { findPackagesWithSkills, findWorkspaceRoot, readWorkspacePatterns, resolveWorkspacePackages, runEditPackageJson, runEditPackageJsonAll, runSetupGithubActions };
@@ -0,0 +1,247 @@
1
+ import { t as scanForIntents } from "./scanner-CRCZwhKS.mjs";
2
+ import { t as resolveProjectContext } from "./project-context-DBSibDPb.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-DG83YEzb.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 };
@@ -0,0 +1,9 @@
1
+ import "./utils-9fhWAVua.mjs";
2
+ import "./skill-paths-B-j0dWDA.mjs";
3
+ import "./scanner-CRCZwhKS.mjs";
4
+ import "./workspace-patterns-BffPlZ1D.mjs";
5
+ import "./project-context-DBSibDPb.mjs";
6
+ import "./excludes-DG83YEzb.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-DaImacFt.mjs";
8
+
9
+ export { scanForPolicedIntents };
@@ -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
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";
2
+ import "./artifact-coverage-nGwun1tt.mjs";
3
+ import { n as checkStaleness, r as readPackageName, t as buildWorkspaceCoverageSignals } from "./staleness-DVFARTES.mjs";
4
4
 
5
5
  export { buildWorkspaceCoverageSignals, checkStaleness, readPackageName };
@@ -1,5 +1,5 @@
1
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";
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";
@@ -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;
@@ -1,8 +1,8 @@
1
1
  import "./utils-9fhWAVua.mjs";
2
2
  import { n as findWorkspacePackages } from "./workspace-patterns-BffPlZ1D.mjs";
3
- import { t as resolveProjectContext } from "./project-context-BRIMzhi4.mjs";
3
+ import { t as resolveProjectContext } from "./project-context-DBSibDPb.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-BevVu4gw.mjs";
6
6
  import { appendFileSync, existsSync, readFileSync } from "node:fs";
7
7
  import { basename, dirname, join, relative, resolve, sep } from "node:path";
8
8
 
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@tanstack/intent",
3
- "version": "0.0.44",
3
+ "version": "0.1.0",
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 };