@promptci/core 0.2.2 → 0.4.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 (181) hide show
  1. package/dist/action-pinning.d.ts.map +1 -1
  2. package/dist/action-pinning.js +86 -55
  3. package/dist/action-pinning.js.map +1 -1
  4. package/dist/agent-practices.d.ts +5 -1
  5. package/dist/agent-practices.d.ts.map +1 -1
  6. package/dist/agent-practices.js +59 -34
  7. package/dist/agent-practices.js.map +1 -1
  8. package/dist/ai-config.d.ts +13 -6
  9. package/dist/ai-config.d.ts.map +1 -1
  10. package/dist/ai-config.js +25 -78
  11. package/dist/ai-config.js.map +1 -1
  12. package/dist/baseline.d.ts +8 -0
  13. package/dist/baseline.d.ts.map +1 -1
  14. package/dist/baseline.js +15 -0
  15. package/dist/baseline.js.map +1 -1
  16. package/dist/ci-alignment.d.ts +3 -1
  17. package/dist/ci-alignment.d.ts.map +1 -1
  18. package/dist/ci-alignment.js +8 -1
  19. package/dist/ci-alignment.js.map +1 -1
  20. package/dist/close-match.d.ts +97 -0
  21. package/dist/close-match.d.ts.map +1 -0
  22. package/dist/close-match.js +215 -0
  23. package/dist/close-match.js.map +1 -0
  24. package/dist/command-context.d.ts +67 -0
  25. package/dist/command-context.d.ts.map +1 -0
  26. package/dist/command-context.js +291 -0
  27. package/dist/command-context.js.map +1 -0
  28. package/dist/command-validity.d.ts.map +1 -1
  29. package/dist/command-validity.js +510 -32
  30. package/dist/command-validity.js.map +1 -1
  31. package/dist/context-optimizer.d.ts.map +1 -1
  32. package/dist/context-optimizer.js +9 -2
  33. package/dist/context-optimizer.js.map +1 -1
  34. package/dist/dead-references.d.ts +14 -1
  35. package/dist/dead-references.d.ts.map +1 -1
  36. package/dist/dead-references.js +264 -17
  37. package/dist/dead-references.js.map +1 -1
  38. package/dist/dependency-staleness.d.ts.map +1 -1
  39. package/dist/dependency-staleness.js +24 -38
  40. package/dist/dependency-staleness.js.map +1 -1
  41. package/dist/detectors.js +1 -1
  42. package/dist/detectors.js.map +1 -1
  43. package/dist/discovery.d.ts +138 -0
  44. package/dist/discovery.d.ts.map +1 -0
  45. package/dist/discovery.js +569 -0
  46. package/dist/discovery.js.map +1 -0
  47. package/dist/duplicates.d.ts +24 -2
  48. package/dist/duplicates.d.ts.map +1 -1
  49. package/dist/duplicates.js +313 -9
  50. package/dist/duplicates.js.map +1 -1
  51. package/dist/fix-engine.d.ts.map +1 -1
  52. package/dist/fix-engine.js +75 -1
  53. package/dist/fix-engine.js.map +1 -1
  54. package/dist/frameworks/dotnet.d.ts.map +1 -1
  55. package/dist/frameworks/dotnet.js +10 -11
  56. package/dist/frameworks/dotnet.js.map +1 -1
  57. package/dist/frameworks/go.d.ts.map +1 -1
  58. package/dist/frameworks/go.js +8 -4
  59. package/dist/frameworks/go.js.map +1 -1
  60. package/dist/frameworks/nextjs.d.ts.map +1 -1
  61. package/dist/frameworks/nextjs.js +8 -17
  62. package/dist/frameworks/nextjs.js.map +1 -1
  63. package/dist/frameworks/python.d.ts.map +1 -1
  64. package/dist/frameworks/python.js +5 -3
  65. package/dist/frameworks/python.js.map +1 -1
  66. package/dist/frameworks/rust.d.ts.map +1 -1
  67. package/dist/frameworks/rust.js +3 -3
  68. package/dist/frameworks/rust.js.map +1 -1
  69. package/dist/frameworks/unity.d.ts.map +1 -1
  70. package/dist/frameworks/unity.js +6 -5
  71. package/dist/frameworks/unity.js.map +1 -1
  72. package/dist/gitignore.d.ts +31 -2
  73. package/dist/gitignore.d.ts.map +1 -1
  74. package/dist/gitignore.js +33 -8
  75. package/dist/gitignore.js.map +1 -1
  76. package/dist/health-score.d.ts +15 -1
  77. package/dist/health-score.d.ts.map +1 -1
  78. package/dist/health-score.js +25 -2
  79. package/dist/health-score.js.map +1 -1
  80. package/dist/hooks-settings-detector.d.ts.map +1 -1
  81. package/dist/hooks-settings-detector.js +5 -1
  82. package/dist/hooks-settings-detector.js.map +1 -1
  83. package/dist/index.d.ts +10 -2
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +16 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/known-paths.d.ts +82 -0
  88. package/dist/known-paths.d.ts.map +1 -0
  89. package/dist/known-paths.js +152 -0
  90. package/dist/known-paths.js.map +1 -0
  91. package/dist/makefile.d.ts.map +1 -1
  92. package/dist/makefile.js +17 -13
  93. package/dist/makefile.js.map +1 -1
  94. package/dist/manifest-consistency.d.ts +1 -1
  95. package/dist/manifest-consistency.d.ts.map +1 -1
  96. package/dist/manifest-consistency.js +18 -8
  97. package/dist/manifest-consistency.js.map +1 -1
  98. package/dist/markdown-fences.d.ts.map +1 -1
  99. package/dist/markdown-fences.js +7 -3
  100. package/dist/markdown-fences.js.map +1 -1
  101. package/dist/mcp-config-detector.d.ts.map +1 -1
  102. package/dist/mcp-config-detector.js +5 -1
  103. package/dist/mcp-config-detector.js.map +1 -1
  104. package/dist/project-type.d.ts +2 -1
  105. package/dist/project-type.d.ts.map +1 -1
  106. package/dist/project-type.js +36 -48
  107. package/dist/project-type.js.map +1 -1
  108. package/dist/prompt-cache.d.ts.map +1 -1
  109. package/dist/prompt-cache.js +13 -2
  110. package/dist/prompt-cache.js.map +1 -1
  111. package/dist/provenance/check.d.ts +40 -0
  112. package/dist/provenance/check.d.ts.map +1 -0
  113. package/dist/provenance/check.js +157 -0
  114. package/dist/provenance/check.js.map +1 -0
  115. package/dist/provenance/index.d.ts +13 -0
  116. package/dist/provenance/index.d.ts.map +1 -0
  117. package/dist/provenance/index.js +21 -0
  118. package/dist/provenance/index.js.map +1 -0
  119. package/dist/provenance/instruction-advice.d.ts +3 -0
  120. package/dist/provenance/instruction-advice.d.ts.map +1 -0
  121. package/dist/provenance/instruction-advice.js +570 -0
  122. package/dist/provenance/instruction-advice.js.map +1 -0
  123. package/dist/provenance/repo-checks.d.ts +3 -0
  124. package/dist/provenance/repo-checks.d.ts.map +1 -0
  125. package/dist/provenance/repo-checks.js +644 -0
  126. package/dist/provenance/repo-checks.js.map +1 -0
  127. package/dist/provenance/tool-config.d.ts +3 -0
  128. package/dist/provenance/tool-config.d.ts.map +1 -0
  129. package/dist/provenance/tool-config.js +480 -0
  130. package/dist/provenance/tool-config.js.map +1 -0
  131. package/dist/provenance/types.d.ts +116 -0
  132. package/dist/provenance/types.d.ts.map +1 -0
  133. package/dist/provenance/types.js +17 -0
  134. package/dist/provenance/types.js.map +1 -0
  135. package/dist/repo-context.d.ts +9 -0
  136. package/dist/repo-context.d.ts.map +1 -1
  137. package/dist/repo-context.js +35 -41
  138. package/dist/repo-context.js.map +1 -1
  139. package/dist/repo-tree.d.ts +163 -9
  140. package/dist/repo-tree.d.ts.map +1 -1
  141. package/dist/repo-tree.js +226 -34
  142. package/dist/repo-tree.js.map +1 -1
  143. package/dist/report.d.ts.map +1 -1
  144. package/dist/report.js +6 -0
  145. package/dist/report.js.map +1 -1
  146. package/dist/sample-text.d.ts +36 -0
  147. package/dist/sample-text.d.ts.map +1 -0
  148. package/dist/sample-text.js +72 -0
  149. package/dist/sample-text.js.map +1 -0
  150. package/dist/sarif.d.ts +27 -0
  151. package/dist/sarif.d.ts.map +1 -0
  152. package/dist/sarif.js +357 -0
  153. package/dist/sarif.js.map +1 -0
  154. package/dist/scan.d.ts.map +1 -1
  155. package/dist/scan.js +8 -2
  156. package/dist/scan.js.map +1 -1
  157. package/dist/scanner.d.ts +4 -3
  158. package/dist/scanner.d.ts.map +1 -1
  159. package/dist/scanner.js +36 -77
  160. package/dist/scanner.js.map +1 -1
  161. package/dist/security-pack.d.ts.map +1 -1
  162. package/dist/security-pack.js +117 -35
  163. package/dist/security-pack.js.map +1 -1
  164. package/dist/skill-supply-chain.d.ts.map +1 -1
  165. package/dist/skill-supply-chain.js +29 -19
  166. package/dist/skill-supply-chain.js.map +1 -1
  167. package/dist/skills-detector.d.ts.map +1 -1
  168. package/dist/skills-detector.js +11 -3
  169. package/dist/skills-detector.js.map +1 -1
  170. package/dist/token-estimates.d.ts +42 -0
  171. package/dist/token-estimates.d.ts.map +1 -0
  172. package/dist/token-estimates.js +200 -0
  173. package/dist/token-estimates.js.map +1 -0
  174. package/dist/types.d.ts +99 -0
  175. package/dist/types.d.ts.map +1 -1
  176. package/dist/types.js.map +1 -1
  177. package/dist/workspace-manifests.d.ts +6 -0
  178. package/dist/workspace-manifests.d.ts.map +1 -1
  179. package/dist/workspace-manifests.js +13 -8
  180. package/dist/workspace-manifests.js.map +1 -1
  181. package/package.json +5 -2
@@ -119,6 +119,7 @@ import { realPathWithinRoot } from './path-containment.js';
119
119
  import { scanFencedLines } from './markdown-fences.js';
120
120
  import { extractFileRefs } from './skills-detector.js';
121
121
  import { codepointLabel, visibleText } from './evidence.js';
122
+ import { treeFor } from './repo-tree.js';
122
123
  /** First entry of every finding's `tags`. */
123
124
  export const SKILL_SUPPLY_CHAIN_TAG = 'skill-supply-chain';
124
125
  /** Total bytes of skill content read per scan; the rest is reported, not read. */
@@ -2531,7 +2532,7 @@ function checkManifest(doc, hit, add) {
2531
2532
  * Bundled reference docs are not checked: they are where skills keep worked
2532
2533
  * examples of scripts the *reader* would write, which never exist.
2533
2534
  */
2534
- function checkMissingScripts(repoRoot, skillDir, doc, alreadyReported, add) {
2535
+ function checkMissingScripts(tree, skillDir, doc, alreadyReported, add) {
2535
2536
  const pluginRoot = /^(.*?)\/?skills\/[^/]+$/.exec(skillDir)?.[1];
2536
2537
  const resolveCandidates = (raw) => {
2537
2538
  let ref = raw;
@@ -2578,7 +2579,7 @@ function checkMissingScripts(repoRoot, skillDir, doc, alreadyReported, add) {
2578
2579
  if (fsChecks >= MAX_FS_CHECKS_PER_DOC)
2579
2580
  return undefined;
2580
2581
  fsChecks++;
2581
- const result = isFileWithinRoot(repoRoot, p);
2582
+ const result = isFileWithinRoot(tree, p);
2582
2583
  exists.set(p, result);
2583
2584
  return result;
2584
2585
  };
@@ -2751,7 +2752,7 @@ function loadDocs(repoRoot, relPath, isSkillMd, priority, budget) {
2751
2752
  }
2752
2753
  // ── Detector ──────────────────────────────────────────────────────────────────
2753
2754
  /** Scan one document (dropped by the caller right after). Returns package `bin` targets to scan next. */
2754
- function scanDoc(repoRoot, skillDir, doc, isSkillMd, alreadyReported, collector, unscanned) {
2755
+ function scanDoc(tree, skillDir, doc, isSkillMd, alreadyReported, collector, unscanned) {
2755
2756
  const add = (rule, line, excerptText, severity, confidence) => {
2756
2757
  if (!collector.accepts(rule, doc.path, severity, confidence)) {
2757
2758
  collector.count(rule, doc.path);
@@ -2779,7 +2780,7 @@ function scanDoc(repoRoot, skillDir, doc, isSkillMd, alreadyReported, collector,
2779
2780
  const rel = name.replace(/^\.\//, '');
2780
2781
  if (!rel || rel.startsWith('/') || /^[a-z]:/i.test(rel))
2781
2782
  return false;
2782
- return [`${path.posix.dirname(doc.path)}/${rel}`, `${skillDir}/${rel}`, rel].some((p) => isFileWithinRoot(repoRoot, p));
2783
+ return [`${path.posix.dirname(doc.path)}/${rel}`, `${skillDir}/${rel}`, rel].some((p) => isFileWithinRoot(tree, p));
2783
2784
  };
2784
2785
  const consumed = checkExec(doc, logical, commands, add, manifestExists);
2785
2786
  checkUnpinned(doc, commands, consumed, add);
@@ -2787,7 +2788,7 @@ function scanDoc(repoRoot, skillDir, doc, isSkillMd, alreadyReported, collector,
2787
2788
  checkProse(doc, add);
2788
2789
  checkHiddenMarkup(doc, add);
2789
2790
  if (isSkillMd && !doc.tail)
2790
- checkMissingScripts(repoRoot, skillDir, doc, alreadyReported, add);
2791
+ checkMissingScripts(tree, skillDir, doc, alreadyReported, add);
2791
2792
  }
2792
2793
  else {
2793
2794
  checkScript(doc, consumed, add);
@@ -2807,19 +2808,24 @@ const DEPENDENCY_REF_RE = {
2807
2808
  worktrees: /(?:^|[\s'"`(=:])(?:\.\/)?worktrees\//m,
2808
2809
  '.worktrees': /(?:^|[\s'"`(=:])(?:\.\/)?\.worktrees\//m,
2809
2810
  };
2810
- /** Non-sample hook files under a skill's `.git/hooks`. */
2811
- function hasGitHooks(repoRoot, gitDir) {
2812
- const abs = resolveWithinRoot(repoRoot, `${gitDir}/hooks`);
2813
- if (!abs)
2814
- return false;
2815
- try {
2816
- return fs.readdirSync(abs).some((f) => !f.endsWith('.sample'));
2817
- }
2818
- catch {
2811
+ /**
2812
+ * Non-sample hook files under a skill's `.git/hooks`.
2813
+ *
2814
+ * pcic-e6xa: listed through the scan's tree. The path is a fixed name under a
2815
+ * discovered skill directory, but a `.git` committed as a link out of the
2816
+ * repository used to decide whether this `warning` fires, and in the hosted
2817
+ * product the scan root is a server temp directory.
2818
+ */
2819
+ function hasGitHooks(tree, gitDir) {
2820
+ const entries = tree.entries(`${gitDir}/hooks`);
2821
+ if (typeof entries === 'string')
2819
2822
  return false;
2820
- }
2823
+ for (const name of entries.keys())
2824
+ if (!name.endsWith('.sample'))
2825
+ return true;
2826
+ return false;
2821
2827
  }
2822
- function skipReason(skip, referenced, repoRoot) {
2828
+ function skipReason(skip, referenced, tree) {
2823
2829
  switch (skip.kind) {
2824
2830
  case 'dependency-dir': {
2825
2831
  const name = path.posix.basename(skip.path);
@@ -2828,7 +2834,7 @@ function skipReason(skip, referenced, repoRoot) {
2828
2834
  if (referenced.has(name)) {
2829
2835
  return { path: skip.path, reason: `dependency/VCS directory the skill runs or references by path — not walked${read}`, severity: 'high' };
2830
2836
  }
2831
- if (name === '.git' && hasGitHooks(repoRoot, skip.path)) {
2837
+ if (name === '.git' && hasGitHooks(tree, skip.path)) {
2832
2838
  return { path: skip.path, reason: 'git directory with hooks — hooks run on git operations and were not scanned', severity: 'warning' };
2833
2839
  }
2834
2840
  return { path: skip.path, reason: `dependency/VCS directory — not walked${read}`, severity: 'info' };
@@ -2840,6 +2846,10 @@ function skipReason(skip, referenced, repoRoot) {
2840
2846
  }
2841
2847
  }
2842
2848
  export function detectSkillSupplyChain(context, limits = {}) {
2849
+ // pcic-e6xa: every existence check this scan makes goes through the scan's
2850
+ // tree, so a skill cannot point it outside the repository through a committed
2851
+ // link; pcic-csf: a caller's file inventory answers first.
2852
+ const tree = treeFor(context);
2843
2853
  // `allSkills`/`skillFiles` are optional for hand-built contexts from older releases.
2844
2854
  const ai = context.aiConfig ?? {};
2845
2855
  const allSkills = ai.allSkills ?? ai.skills ?? [];
@@ -2913,7 +2923,7 @@ export function detectSkillSupplyChain(context, limits = {}) {
2913
2923
  state.headContent = loaded.docs[0]?.content;
2914
2924
  for (const doc of loaded.docs) {
2915
2925
  noteReferences(state, doc);
2916
- extra.push(...scanDoc(context.repoRoot, state.dir, doc, isSkillMd, state.alreadyReported, state.collector, state.unscanned));
2926
+ extra.push(...scanDoc(tree, state.dir, doc, isSkillMd, state.alreadyReported, state.collector, state.unscanned));
2917
2927
  }
2918
2928
  // A dependency package's `bin` targets are what `npx`/install runs: scan them as scripts.
2919
2929
  for (const target of extra)
@@ -2940,7 +2950,7 @@ export function detectSkillSupplyChain(context, limits = {}) {
2940
2950
  continue; // unreadable SKILL.md
2941
2951
  for (const skip of ai.skillBundleSkips ?? []) {
2942
2952
  if (owner(skip.path) === states.indexOf(state))
2943
- state.unscanned.push(skipReason(skip, state.referenced, context.repoRoot));
2953
+ state.unscanned.push(skipReason(skip, state.referenced, tree));
2944
2954
  }
2945
2955
  // Name what could not be scanned — never drop it silently.
2946
2956
  for (const u of state.unscanned) {