@promptci/core 0.0.1 → 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (253) hide show
  1. package/LICENSE +201 -201
  2. package/README.md +29 -30
  3. package/dist/action-pinning.d.ts +37 -0
  4. package/dist/action-pinning.d.ts.map +1 -0
  5. package/dist/action-pinning.js +277 -0
  6. package/dist/action-pinning.js.map +1 -0
  7. package/dist/agent-practices.d.ts +3 -1
  8. package/dist/agent-practices.d.ts.map +1 -1
  9. package/dist/agent-practices.js +198 -94
  10. package/dist/agent-practices.js.map +1 -1
  11. package/dist/ai-config.d.ts +178 -0
  12. package/dist/ai-config.d.ts.map +1 -0
  13. package/dist/ai-config.js +721 -0
  14. package/dist/ai-config.js.map +1 -0
  15. package/dist/alias-files.d.ts +33 -0
  16. package/dist/alias-files.d.ts.map +1 -0
  17. package/dist/alias-files.js +60 -0
  18. package/dist/alias-files.js.map +1 -0
  19. package/dist/baseline.d.ts +17 -1
  20. package/dist/baseline.d.ts.map +1 -1
  21. package/dist/baseline.js +5 -1
  22. package/dist/baseline.js.map +1 -1
  23. package/dist/buried-critical.d.ts +17 -0
  24. package/dist/buried-critical.d.ts.map +1 -0
  25. package/dist/buried-critical.js +107 -0
  26. package/dist/buried-critical.js.map +1 -0
  27. package/dist/canonical-owner.d.ts.map +1 -1
  28. package/dist/canonical-owner.js +60 -30
  29. package/dist/canonical-owner.js.map +1 -1
  30. package/dist/ci-alignment.d.ts.map +1 -1
  31. package/dist/ci-alignment.js +3 -2
  32. package/dist/ci-alignment.js.map +1 -1
  33. package/dist/command-validity.d.ts +16 -0
  34. package/dist/command-validity.d.ts.map +1 -1
  35. package/dist/command-validity.js +387 -134
  36. package/dist/command-validity.js.map +1 -1
  37. package/dist/conflicts.d.ts.map +1 -1
  38. package/dist/conflicts.js +4 -44
  39. package/dist/conflicts.js.map +1 -1
  40. package/dist/context-analysis.d.ts.map +1 -1
  41. package/dist/context-analysis.js +13 -2
  42. package/dist/context-analysis.js.map +1 -1
  43. package/dist/context-bloat.d.ts +20 -1
  44. package/dist/context-bloat.d.ts.map +1 -1
  45. package/dist/context-bloat.js +99 -15
  46. package/dist/context-bloat.js.map +1 -1
  47. package/dist/context-optimizer.d.ts.map +1 -1
  48. package/dist/context-optimizer.js +18 -54
  49. package/dist/context-optimizer.js.map +1 -1
  50. package/dist/copilot-instructions-detector.d.ts +24 -0
  51. package/dist/copilot-instructions-detector.d.ts.map +1 -0
  52. package/dist/copilot-instructions-detector.js +145 -0
  53. package/dist/copilot-instructions-detector.js.map +1 -0
  54. package/dist/cursor-rules-detector.d.ts +17 -0
  55. package/dist/cursor-rules-detector.d.ts.map +1 -0
  56. package/dist/cursor-rules-detector.js +110 -0
  57. package/dist/cursor-rules-detector.js.map +1 -0
  58. package/dist/custom-rules.d.ts +52 -0
  59. package/dist/custom-rules.d.ts.map +1 -0
  60. package/dist/custom-rules.js +303 -0
  61. package/dist/custom-rules.js.map +1 -0
  62. package/dist/dead-references.d.ts +8 -2
  63. package/dist/dead-references.d.ts.map +1 -1
  64. package/dist/dead-references.js +315 -68
  65. package/dist/dead-references.js.map +1 -1
  66. package/dist/dependency-staleness.d.ts +35 -0
  67. package/dist/dependency-staleness.d.ts.map +1 -0
  68. package/dist/dependency-staleness.js +1001 -0
  69. package/dist/dependency-staleness.js.map +1 -0
  70. package/dist/detectors.d.ts +1 -3
  71. package/dist/detectors.d.ts.map +1 -1
  72. package/dist/detectors.js +74 -56
  73. package/dist/detectors.js.map +1 -1
  74. package/dist/duplicates.d.ts.map +1 -1
  75. package/dist/duplicates.js +15 -9
  76. package/dist/duplicates.js.map +1 -1
  77. package/dist/evidence.d.ts +39 -0
  78. package/dist/evidence.d.ts.map +1 -0
  79. package/dist/evidence.js +78 -0
  80. package/dist/evidence.js.map +1 -0
  81. package/dist/finding-id.d.ts +21 -0
  82. package/dist/finding-id.d.ts.map +1 -0
  83. package/dist/finding-id.js +31 -0
  84. package/dist/finding-id.js.map +1 -0
  85. package/dist/fix-engine.d.ts +11 -0
  86. package/dist/fix-engine.d.ts.map +1 -1
  87. package/dist/fix-engine.js +88 -71
  88. package/dist/fix-engine.js.map +1 -1
  89. package/dist/frameworks/dotnet.js +2 -2
  90. package/dist/frameworks/dotnet.js.map +1 -1
  91. package/dist/frameworks/python.d.ts.map +1 -1
  92. package/dist/frameworks/python.js +5 -2
  93. package/dist/frameworks/python.js.map +1 -1
  94. package/dist/frameworks/rust.d.ts.map +1 -1
  95. package/dist/frameworks/rust.js +2 -1
  96. package/dist/frameworks/rust.js.map +1 -1
  97. package/dist/git-symlinks.d.ts +30 -0
  98. package/dist/git-symlinks.d.ts.map +1 -0
  99. package/dist/git-symlinks.js +161 -0
  100. package/dist/git-symlinks.js.map +1 -0
  101. package/dist/gitignore.d.ts +22 -0
  102. package/dist/gitignore.d.ts.map +1 -0
  103. package/dist/gitignore.js +157 -0
  104. package/dist/gitignore.js.map +1 -0
  105. package/dist/health-score.d.ts.map +1 -1
  106. package/dist/health-score.js +35 -5
  107. package/dist/health-score.js.map +1 -1
  108. package/dist/hooks-settings-detector.d.ts +17 -0
  109. package/dist/hooks-settings-detector.d.ts.map +1 -0
  110. package/dist/hooks-settings-detector.js +228 -0
  111. package/dist/hooks-settings-detector.js.map +1 -0
  112. package/dist/index.d.ts +29 -8
  113. package/dist/index.d.ts.map +1 -1
  114. package/dist/index.js +21 -6
  115. package/dist/index.js.map +1 -1
  116. package/dist/makefile.d.ts +37 -0
  117. package/dist/makefile.d.ts.map +1 -0
  118. package/dist/makefile.js +156 -0
  119. package/dist/makefile.js.map +1 -0
  120. package/dist/manifest-consistency.d.ts +6 -0
  121. package/dist/manifest-consistency.d.ts.map +1 -1
  122. package/dist/manifest-consistency.js +75 -10
  123. package/dist/manifest-consistency.js.map +1 -1
  124. package/dist/markdown-fences.d.ts +112 -0
  125. package/dist/markdown-fences.d.ts.map +1 -0
  126. package/dist/markdown-fences.js +174 -0
  127. package/dist/markdown-fences.js.map +1 -0
  128. package/dist/mcp-config-detector.d.ts +20 -0
  129. package/dist/mcp-config-detector.d.ts.map +1 -0
  130. package/dist/mcp-config-detector.js +237 -0
  131. package/dist/mcp-config-detector.js.map +1 -0
  132. package/dist/missing-context.d.ts.map +1 -1
  133. package/dist/missing-context.js +2 -52
  134. package/dist/missing-context.js.map +1 -1
  135. package/dist/model-budgets.d.ts +69 -0
  136. package/dist/model-budgets.d.ts.map +1 -0
  137. package/dist/model-budgets.js +110 -0
  138. package/dist/model-budgets.js.map +1 -0
  139. package/dist/negative-instructions.d.ts +26 -0
  140. package/dist/negative-instructions.d.ts.map +1 -0
  141. package/dist/negative-instructions.js +169 -0
  142. package/dist/negative-instructions.js.map +1 -0
  143. package/dist/path-containment.d.ts +41 -0
  144. package/dist/path-containment.d.ts.map +1 -0
  145. package/dist/path-containment.js +123 -0
  146. package/dist/path-containment.js.map +1 -0
  147. package/dist/project-type.d.ts +12 -2
  148. package/dist/project-type.d.ts.map +1 -1
  149. package/dist/project-type.js +25 -12
  150. package/dist/project-type.js.map +1 -1
  151. package/dist/prompt-cache.d.ts.map +1 -1
  152. package/dist/prompt-cache.js +33 -24
  153. package/dist/prompt-cache.js.map +1 -1
  154. package/dist/promptci-gitignore.d.ts +34 -0
  155. package/dist/promptci-gitignore.d.ts.map +1 -0
  156. package/dist/promptci-gitignore.js +42 -0
  157. package/dist/promptci-gitignore.js.map +1 -0
  158. package/dist/repo-context.d.ts +80 -0
  159. package/dist/repo-context.d.ts.map +1 -1
  160. package/dist/repo-context.js +170 -16
  161. package/dist/repo-context.js.map +1 -1
  162. package/dist/report.d.ts +8 -0
  163. package/dist/report.d.ts.map +1 -1
  164. package/dist/report.js +163 -63
  165. package/dist/report.js.map +1 -1
  166. package/dist/scan.d.ts.map +1 -1
  167. package/dist/scan.js +47 -4
  168. package/dist/scan.js.map +1 -1
  169. package/dist/scanner.d.ts +61 -1
  170. package/dist/scanner.d.ts.map +1 -1
  171. package/dist/scanner.js +367 -70
  172. package/dist/scanner.js.map +1 -1
  173. package/dist/security-pack.d.ts +20 -0
  174. package/dist/security-pack.d.ts.map +1 -1
  175. package/dist/security-pack.js +33 -14
  176. package/dist/security-pack.js.map +1 -1
  177. package/dist/skill-supply-chain.d.ts +132 -0
  178. package/dist/skill-supply-chain.d.ts.map +1 -0
  179. package/dist/skill-supply-chain.js +2954 -0
  180. package/dist/skill-supply-chain.js.map +1 -0
  181. package/dist/skills-detector.d.ts +23 -0
  182. package/dist/skills-detector.d.ts.map +1 -0
  183. package/dist/skills-detector.js +279 -0
  184. package/dist/skills-detector.js.map +1 -0
  185. package/dist/stale-instructions.d.ts +4 -1
  186. package/dist/stale-instructions.d.ts.map +1 -1
  187. package/dist/stale-instructions.js +53 -55
  188. package/dist/stale-instructions.js.map +1 -1
  189. package/dist/subagents-detector.d.ts +19 -0
  190. package/dist/subagents-detector.d.ts.map +1 -0
  191. package/dist/subagents-detector.js +155 -0
  192. package/dist/subagents-detector.js.map +1 -0
  193. package/dist/suppression.d.ts +2 -0
  194. package/dist/suppression.d.ts.map +1 -1
  195. package/dist/suppression.js +16 -47
  196. package/dist/suppression.js.map +1 -1
  197. package/dist/types.d.ts +62 -4
  198. package/dist/types.d.ts.map +1 -1
  199. package/dist/types.js +47 -1
  200. package/dist/types.js.map +1 -1
  201. package/dist/vague-guidance.d.ts +15 -2
  202. package/dist/vague-guidance.d.ts.map +1 -1
  203. package/dist/vague-guidance.js +44 -41
  204. package/dist/vague-guidance.js.map +1 -1
  205. package/dist/windsurf-detector.d.ts +22 -0
  206. package/dist/windsurf-detector.d.ts.map +1 -0
  207. package/dist/windsurf-detector.js +96 -0
  208. package/dist/windsurf-detector.js.map +1 -0
  209. package/dist/within-section-dedup.d.ts +16 -0
  210. package/dist/within-section-dedup.d.ts.map +1 -0
  211. package/dist/within-section-dedup.js +148 -0
  212. package/dist/within-section-dedup.js.map +1 -0
  213. package/dist/workspace-manifests.d.ts +80 -0
  214. package/dist/workspace-manifests.d.ts.map +1 -0
  215. package/dist/workspace-manifests.js +333 -0
  216. package/dist/workspace-manifests.js.map +1 -0
  217. package/package.json +11 -8
  218. package/dist/cheap-model-routing.d.ts +0 -4
  219. package/dist/cheap-model-routing.d.ts.map +0 -1
  220. package/dist/cheap-model-routing.js +0 -43
  221. package/dist/cheap-model-routing.js.map +0 -1
  222. package/dist/cli-output-filter.d.ts +0 -16
  223. package/dist/cli-output-filter.d.ts.map +0 -1
  224. package/dist/cli-output-filter.js +0 -88
  225. package/dist/cli-output-filter.js.map +0 -1
  226. package/dist/context-cost.d.ts +0 -4
  227. package/dist/context-cost.d.ts.map +0 -1
  228. package/dist/context-cost.js +0 -70
  229. package/dist/context-cost.js.map +0 -1
  230. package/dist/context-recommender.d.ts +0 -3
  231. package/dist/context-recommender.d.ts.map +0 -1
  232. package/dist/context-recommender.js +0 -329
  233. package/dist/context-recommender.js.map +0 -1
  234. package/dist/llm.d.ts +0 -6
  235. package/dist/llm.d.ts.map +0 -1
  236. package/dist/llm.js +0 -67
  237. package/dist/llm.js.map +0 -1
  238. package/dist/mcp-detector.d.ts +0 -4
  239. package/dist/mcp-detector.d.ts.map +0 -1
  240. package/dist/mcp-detector.js +0 -131
  241. package/dist/mcp-detector.js.map +0 -1
  242. package/dist/native-tool-preference.d.ts +0 -20
  243. package/dist/native-tool-preference.d.ts.map +0 -1
  244. package/dist/native-tool-preference.js +0 -94
  245. package/dist/native-tool-preference.js.map +0 -1
  246. package/dist/output-verbosity.d.ts +0 -3
  247. package/dist/output-verbosity.d.ts.map +0 -1
  248. package/dist/output-verbosity.js +0 -83
  249. package/dist/output-verbosity.js.map +0 -1
  250. package/dist/product-boundary.d.ts +0 -11
  251. package/dist/product-boundary.d.ts.map +0 -1
  252. package/dist/product-boundary.js +0 -301
  253. package/dist/product-boundary.js.map +0 -1
@@ -0,0 +1,228 @@
1
+ /**
2
+ * Hooks / Settings Detector (issue #23)
3
+ *
4
+ * Audits `.claude/settings.json` and `.claude/settings.local.json`:
5
+ *
6
+ * - Invalid JSON: the file will not load at all.
7
+ * - Hook commands referencing local scripts that do not exist in the repo.
8
+ * - Dangerous hook patterns: piping a remote download straight into a shell
9
+ * (`curl … | sh`), and unquoted `$CLAUDE_PROJECT_DIR` path expansions.
10
+ *
11
+ * Hook commands run automatically on tool events, so a broken or unsafe command
12
+ * is higher-stakes than a stale doc line. Deterministic and offline.
13
+ */
14
+ import { readTextWithinRoot, isFileWithinRoot, shortHash, lineOf, withScannerPaths, SCRIPT_EXT_RE, aiConfigIssue as base, } from './ai-config.js';
15
+ /** curl/wget piped straight into a shell — the classic remote-code-execution footgun. */
16
+ const CURL_PIPE_SH_RE = /\b(curl|wget)\b[^|]*\|\s*(sudo\s+)?(sh|bash|zsh|dash)\b/i;
17
+ function id(kind, key) {
18
+ return `ai-config-hook-${kind}-${shortHash(key)}`;
19
+ }
20
+ /** Recursively collect `{ type: 'command', command }` hook entries, tagged with their event key. */
21
+ function collectCommandHooks(hooks, event, out) {
22
+ if (Array.isArray(hooks)) {
23
+ for (const item of hooks)
24
+ collectCommandHooks(item, event, out);
25
+ return;
26
+ }
27
+ if (typeof hooks !== 'object' || hooks === null)
28
+ return;
29
+ const obj = hooks;
30
+ if (obj.type === 'command' && typeof obj.command === 'string') {
31
+ out.push({ command: obj.command, event });
32
+ }
33
+ for (const [key, value] of Object.entries(obj)) {
34
+ // When we recurse from the top-level `hooks` map, the key names the event
35
+ // (PreToolUse, PostToolUse, …); deeper down `hooks`/`matcher` keys are just
36
+ // structure, so we keep the nearest event label.
37
+ const nextEvent = event === '' ? key : event;
38
+ if (typeof value === 'object' && value !== null)
39
+ collectCommandHooks(value, nextEvent, out);
40
+ }
41
+ }
42
+ /** Interpreters whose script argument is the file they execute. */
43
+ const INTERPRETERS = new Set([
44
+ 'bash', 'sh', 'zsh', 'dash', 'node', 'deno', 'python', 'python3', 'ruby',
45
+ 'ts-node', 'tsx', 'pwsh', 'powershell',
46
+ ]);
47
+ /** Launchers that wrap another command (`npx tsx x.ts`, `timeout 5 bash x.sh`). */
48
+ const WRAPPERS = new Set([
49
+ 'npx', 'bunx', 'pnpm', 'yarn', 'uv', 'uvx', 'env', 'timeout', 'nice', 'sudo', 'exec', 'command',
50
+ ]);
51
+ /** Strip surrounding quotes, then a leading `$CLAUDE_PROJECT_DIR/` / `${CLAUDE_PROJECT_DIR}/`. */
52
+ function normalizeScriptToken(token) {
53
+ const unquoted = token.replace(/^['"]|['"]$/g, '');
54
+ return unquoted.replace(/^\$\{?CLAUDE_PROJECT_DIR\}?[/\\]/, '');
55
+ }
56
+ /**
57
+ * Extract repo-relative local script references from a hook command string.
58
+ *
59
+ * Each `&&`/`||`/`;`/`|`-chained segment is its own command. Within a segment,
60
+ * the *executed script* is verified — the segment's own executable, or (after
61
+ * any interpreter/wrapper prefix like `bash`, `npx tsx`, `timeout 5 node`) the
62
+ * first argument bearing a script extension, which naturally skips flags and
63
+ * their extension-less values (`node --max-old-space-size 4096 scripts/x.js`).
64
+ * Other tokens are checked only when explicitly relative (`./x`, `.claude/x`,
65
+ * `$CLAUDE_PROJECT_DIR/x`), so a lint hook like `eslint --fix src/foo.js` does
66
+ * not get its target argument flagged as a missing script.
67
+ */
68
+ function extractScriptRefs(command) {
69
+ const refs = new Set();
70
+ const add = (rawToken, executed) => {
71
+ if (rawToken.startsWith('-'))
72
+ return;
73
+ const unquoted = rawToken.replace(/^['"]|['"]$/g, '');
74
+ const token = normalizeScriptToken(rawToken);
75
+ if (!token || token.includes('$') || /[<>{}*?|"'`]/.test(token))
76
+ return; // still has a var/placeholder
77
+ if (token.startsWith('/') || /^[a-zA-Z]:[\\/]/.test(token) || /^https?:/i.test(token))
78
+ return; // absolute/url
79
+ if (token.includes('..'))
80
+ return;
81
+ if (!SCRIPT_EXT_RE.test(token))
82
+ return;
83
+ // Tested on the quote-stripped form so `"./scripts/x.sh"` still counts.
84
+ const explicitRel = unquoted.startsWith('./') || unquoted.startsWith('.claude/') ||
85
+ /^\$\{?CLAUDE_PROJECT_DIR\}?[/\\]/.test(unquoted);
86
+ if (executed || explicitRel)
87
+ refs.add(token.replace(/\\/g, '/'));
88
+ };
89
+ for (const segment of command.split(/&&|\|\||;|\|/)) {
90
+ const tokens = segment.trim().split(/\s+/).filter(Boolean);
91
+ if (tokens.length === 0)
92
+ continue;
93
+ const first = normalizeScriptToken(tokens[0]);
94
+ if (INTERPRETERS.has(first) || WRAPPERS.has(first)) {
95
+ // The executed script is the first argument that looks like a script
96
+ // file; flags and their extension-less values are skipped naturally.
97
+ for (let i = 1; i < tokens.length; i++) {
98
+ if (!tokens[i].startsWith('-') && SCRIPT_EXT_RE.test(normalizeScriptToken(tokens[i]))) {
99
+ add(tokens[i], true);
100
+ break;
101
+ }
102
+ }
103
+ }
104
+ else {
105
+ // The segment itself may be a direct script invocation (`./scripts/x.sh`).
106
+ add(tokens[0], true);
107
+ }
108
+ // Remaining tokens are verified only when explicitly relative.
109
+ for (let i = 1; i < tokens.length; i++)
110
+ add(tokens[i], false);
111
+ }
112
+ return [...refs];
113
+ }
114
+ /**
115
+ * True when the character at `index` sits inside a single- or double-quoted
116
+ * region of `command`. Used so `sh -c "cd $CLAUDE_PROJECT_DIR/x"` — quoted,
117
+ * space-safe — is not flagged as an unquoted expansion.
118
+ */
119
+ function insideQuotes(command, index) {
120
+ let quote = '';
121
+ for (let i = 0; i < index; i++) {
122
+ const c = command[i];
123
+ if (quote) {
124
+ if (c === quote)
125
+ quote = '';
126
+ }
127
+ else if (c === '"' || c === "'") {
128
+ quote = c;
129
+ }
130
+ }
131
+ return quote !== '';
132
+ }
133
+ /** Finds a `$CLAUDE_PROJECT_DIR/...` expansion that no quote region protects. */
134
+ function hasUnquotedProjectDir(command) {
135
+ for (const m of command.matchAll(/\$\{?CLAUDE_PROJECT_DIR\}?[/\\]/g)) {
136
+ if (!insideQuotes(command, m.index))
137
+ return true;
138
+ }
139
+ return false;
140
+ }
141
+ export function detectHooksSettings(context) {
142
+ const issues = [];
143
+ for (const filePath of context.aiConfig.settings) {
144
+ const raw = readTextWithinRoot(context.repoRoot, filePath);
145
+ if (raw === undefined)
146
+ continue;
147
+ let parsed;
148
+ try {
149
+ parsed = JSON.parse(raw);
150
+ }
151
+ catch (err) {
152
+ issues.push(base({
153
+ id: id('invalid-json', filePath),
154
+ severity: 'high',
155
+ title: 'Settings file is not valid JSON',
156
+ summary: `${filePath} could not be parsed as JSON, so Claude Code cannot load its hooks or permissions.`,
157
+ filePaths: [filePath],
158
+ locations: [{ filePath, startLine: 1, endLine: 1 }],
159
+ evidence: [`Parse error: ${err.message}`],
160
+ recommendation: 'Fix the JSON syntax (trailing commas and comments are not allowed in settings.json).',
161
+ confidence: 0.95,
162
+ }));
163
+ continue;
164
+ }
165
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
166
+ continue;
167
+ const hooks = parsed.hooks;
168
+ if (hooks === undefined)
169
+ continue;
170
+ const commandHooks = [];
171
+ collectCommandHooks(hooks, '', commandHooks);
172
+ const reportedMissing = new Set();
173
+ for (const { command, event } of commandHooks) {
174
+ const line = lineOf(raw, command);
175
+ // Dangerous: remote download piped into a shell.
176
+ if (CURL_PIPE_SH_RE.test(command)) {
177
+ issues.push(base({
178
+ id: id('curl-pipe-sh', `${filePath}|${command}`),
179
+ severity: 'high',
180
+ impact: 'high',
181
+ title: 'Hook pipes a remote download into a shell',
182
+ summary: `A ${event || 'hook'} command in ${filePath} pipes \`curl\`/\`wget\` output directly into a shell, running whatever the remote host serves with your permissions.`,
183
+ filePaths: [filePath],
184
+ locations: [{ filePath, startLine: line, endLine: line }],
185
+ evidence: [`Command: ${command.slice(0, 160)}`],
186
+ recommendation: 'Download to a file, review it, and pin a checksum before executing — never pipe a network fetch straight into sh/bash.',
187
+ confidence: 0.85,
188
+ }));
189
+ }
190
+ // Footgun: unquoted $CLAUDE_PROJECT_DIR path expansion.
191
+ if (hasUnquotedProjectDir(command)) {
192
+ issues.push(base({
193
+ id: id('unquoted-project-dir', `${filePath}|${command}`),
194
+ severity: 'info',
195
+ title: 'Hook uses an unquoted $CLAUDE_PROJECT_DIR path',
196
+ summary: `A ${event || 'hook'} command in ${filePath} expands \`$CLAUDE_PROJECT_DIR\` unquoted; if the project path contains a space the command breaks or runs the wrong file.`,
197
+ filePaths: [filePath],
198
+ locations: [{ filePath, startLine: line, endLine: line }],
199
+ evidence: [`Command: ${command.slice(0, 160)}`],
200
+ recommendation: 'Wrap the path in double quotes, e.g. `"$CLAUDE_PROJECT_DIR/script.sh"`.',
201
+ confidence: 0.5,
202
+ }));
203
+ }
204
+ // Missing local script references.
205
+ for (const ref of extractScriptRefs(command)) {
206
+ if (isFileWithinRoot(context.repoRoot, ref))
207
+ continue;
208
+ const key = `${filePath}|${ref}`;
209
+ if (reportedMissing.has(key))
210
+ continue;
211
+ reportedMissing.add(key);
212
+ issues.push(base({
213
+ id: id('missing-script', key),
214
+ title: 'Hook command references a script that does not exist',
215
+ summary: `A ${event || 'hook'} command in ${filePath} runs \`${ref}\`, but that file is not present in the repository.`,
216
+ filePaths: [filePath],
217
+ locations: [{ filePath, startLine: line, endLine: line }],
218
+ evidence: [`Referenced script: ${ref}`, `Command: ${command.slice(0, 160)}`],
219
+ recommendation: 'Add the script, fix the path, or remove the hook.',
220
+ confidence: 0.75,
221
+ }));
222
+ }
223
+ }
224
+ }
225
+ // Scanner-form paths so inline suppressions can match (see withScannerPaths).
226
+ return withScannerPaths(context.repoRoot, issues);
227
+ }
228
+ //# sourceMappingURL=hooks-settings-detector.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"hooks-settings-detector.js","sourceRoot":"","sources":["../src/hooks-settings-detector.ts"],"names":[],"mappings":"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"}
package/dist/index.d.ts CHANGED
@@ -1,6 +1,7 @@
1
1
  /** Root export for @promptci/core */
2
2
  export * from './types.js';
3
- export { scanFiles } from './scanner.js';
3
+ export { scanFiles, scanFilesWithAliases, parseSections } from './scanner.js';
4
+ export type { ScanFilesResult } from './scanner.js';
4
5
  export { detectProjectType, detectProjectTypeFromContent } from './project-type.js';
5
6
  export { detectDuplicates, detectDuplicateHeadings, normalizeSection } from './duplicates.js';
6
7
  export { detectConflicts, detectVersionConflicts, detectCompetingTechConflicts } from './conflicts.js';
@@ -9,23 +10,43 @@ export { detectAgentPractices } from './agent-practices.js';
9
10
  export { parseSuppressions, buildValidationIssues, applySuppressions } from './suppression.js';
10
11
  export type { SuppressionAnnotation } from './suppression.js';
11
12
  export { computeHealthScore, selectTopFixes } from './health-score.js';
12
- export { generateMarkdownReport, generateJsonReport, writeReport, readHistoryIndex, archiveExistingReport, historyIndexPath } from './report.js';
13
+ export { generateMarkdownReport, generateJsonReport, writeReport, readHistoryIndex, archiveExistingReport, historyIndexPath, scoreLabel } from './report.js';
13
14
  export type { WriteReportOptions, HistoryEntry } from './report.js';
14
15
  export { detectManifestConsistency } from './manifest-consistency.js';
16
+ export { detectDependencyStaleness } from './dependency-staleness.js';
15
17
  export type { ManifestData } from './manifest-consistency.js';
16
18
  export { buildRepoContext, parsePackageJsonFacts } from './repo-context.js';
17
- export type { RepoContext, PackageJsonFacts, WorkflowFacts, WorkflowCommand } from './repo-context.js';
19
+ export type { RepoContext, PackageJsonFacts, WorkflowFacts, WorkflowCommand, WorkflowSource } from './repo-context.js';
20
+ export type { MakefileFacts } from './makefile.js';
21
+ export { detectActionPinning, extractActionUses } from './action-pinning.js';
18
22
  export { runDetectors } from './detectors.js';
19
- export type { DetectorDefinition, DetectorGroup } from './detectors.js';
23
+ export type { DetectorDefinition } from './detectors.js';
24
+ export { detectSkills } from './skills-detector.js';
25
+ export { detectSkillSupplyChain } from './skill-supply-chain.js';
26
+ export type { SkillSupplyChainRule } from './skill-supply-chain.js';
27
+ export { detectSubagents } from './subagents-detector.js';
28
+ export { detectHooksSettings } from './hooks-settings-detector.js';
29
+ export { detectMcpConfig } from './mcp-config-detector.js';
30
+ export { detectCursorRules } from './cursor-rules-detector.js';
31
+ export { detectCopilotInstructions } from './copilot-instructions-detector.js';
32
+ export { detectWindsurfRules } from './windsurf-detector.js';
33
+ export { detectNegativeInstructionOverload } from './negative-instructions.js';
34
+ export { detectBuriedCriticalInstructions } from './buried-critical.js';
35
+ export { detectWithinSectionDedup } from './within-section-dedup.js';
36
+ export { parseFrontmatter, discoverAiConfigFiles, emptyAiConfigFiles } from './ai-config.js';
37
+ export type { Frontmatter, FrontmatterValue, AiConfigFiles } from './ai-config.js';
20
38
  export { analyzeContext } from './context-analysis.js';
21
39
  export type { ContextAnalysis } from './context-analysis.js';
22
40
  export { scan } from './scan.js';
23
41
  export { computeFingerprint, createBaseline, filterNewIssues, assertValidBaseline } from './baseline.js';
24
- export { applyFixRecipe, resolveSafePath } from './fix-engine.js';
25
- export { detectCliOutputFilter } from './cli-output-filter.js';
26
- export { detectNativeToolPreference } from './native-tool-preference.js';
42
+ export { applyFixRecipe, resolveSafePath, isRepairable } from './fix-engine.js';
27
43
  export type { FileChange } from './fix-engine.js';
28
- export { callLlm } from './llm.js';
44
+ export { isWithinRoot, resolveWithinRoot, realPathWithinRoot, resolveReadableWithinRoot, writeTargetWithinRoot } from './path-containment.js';
29
45
  export { optimizeContext } from './context-optimizer.js';
30
46
  export type { OptimizeOptions, OptimizeResult } from './context-optimizer.js';
47
+ export { TARGET_MODELS, MODEL_BUDGETS_REVIEW_BY, resolveTargetModel, modelBudget, budgetForTargetModel, } from './model-budgets.js';
48
+ export type { TargetModel, ModelBudget } from './model-budgets.js';
49
+ export { loadCustomRules, parseCustomRules, runCustomRules, CustomRulesError, CUSTOM_RULE_TYPES, CUSTOM_RULES_FILE, } from './custom-rules.js';
50
+ export type { CustomRule, CustomRuleType } from './custom-rules.js';
51
+ export { PROMPTCI_GITIGNORE_LINES, PROMPTCI_GITIGNORE_BLOCK, renderPromptCiGitignore, } from './promptci-gitignore.js';
31
52
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAC/F,YAAY,EAAE,qBAAqB,EAAE,MAAM,kBAAkB,CAAC;AAC9D,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AACjJ,YAAY,EAAE,kBAAkB,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACpE,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AACtE,YAAY,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAC5E,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAE,aAAa,EAAE,eAAe,EAAE,MAAM,mBAAmB,CAAC;AACvG,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAC9C,YAAY,EAAE,kBAAkB,EAAE,aAAa,EAAE,MAAM,gBAAgB,CAAC;AACxE,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AACvD,YAAY,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AACzE,YAAY,EAAE,UAAU,EAAE,MAAM,iBAAiB,CAAC;AAClD,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AACzD,YAAY,EAAE,eAAe,EAAE,cAAc,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
package/dist/index.js CHANGED
@@ -1,6 +1,6 @@
1
1
  /** Root export for @promptci/core */
2
2
  export * from './types.js';
3
- export { scanFiles } from './scanner.js';
3
+ export { scanFiles, scanFilesWithAliases, parseSections } from './scanner.js';
4
4
  export { detectProjectType, detectProjectTypeFromContent } from './project-type.js';
5
5
  export { detectDuplicates, detectDuplicateHeadings, normalizeSection } from './duplicates.js';
6
6
  export { detectConflicts, detectVersionConflicts, detectCompetingTechConflicts } from './conflicts.js';
@@ -8,16 +8,31 @@ export { detectDeadReferences } from './dead-references.js';
8
8
  export { detectAgentPractices } from './agent-practices.js';
9
9
  export { parseSuppressions, buildValidationIssues, applySuppressions } from './suppression.js';
10
10
  export { computeHealthScore, selectTopFixes } from './health-score.js';
11
- export { generateMarkdownReport, generateJsonReport, writeReport, readHistoryIndex, archiveExistingReport, historyIndexPath } from './report.js';
11
+ export { generateMarkdownReport, generateJsonReport, writeReport, readHistoryIndex, archiveExistingReport, historyIndexPath, scoreLabel } from './report.js';
12
12
  export { detectManifestConsistency } from './manifest-consistency.js';
13
+ export { detectDependencyStaleness } from './dependency-staleness.js';
13
14
  export { buildRepoContext, parsePackageJsonFacts } from './repo-context.js';
15
+ export { detectActionPinning, extractActionUses } from './action-pinning.js';
14
16
  export { runDetectors } from './detectors.js';
17
+ export { detectSkills } from './skills-detector.js';
18
+ export { detectSkillSupplyChain } from './skill-supply-chain.js';
19
+ export { detectSubagents } from './subagents-detector.js';
20
+ export { detectHooksSettings } from './hooks-settings-detector.js';
21
+ export { detectMcpConfig } from './mcp-config-detector.js';
22
+ export { detectCursorRules } from './cursor-rules-detector.js';
23
+ export { detectCopilotInstructions } from './copilot-instructions-detector.js';
24
+ export { detectWindsurfRules } from './windsurf-detector.js';
25
+ export { detectNegativeInstructionOverload } from './negative-instructions.js';
26
+ export { detectBuriedCriticalInstructions } from './buried-critical.js';
27
+ export { detectWithinSectionDedup } from './within-section-dedup.js';
28
+ export { parseFrontmatter, discoverAiConfigFiles, emptyAiConfigFiles } from './ai-config.js';
15
29
  export { analyzeContext } from './context-analysis.js';
16
30
  export { scan } from './scan.js';
17
31
  export { computeFingerprint, createBaseline, filterNewIssues, assertValidBaseline } from './baseline.js';
18
- export { applyFixRecipe, resolveSafePath } from './fix-engine.js';
19
- export { detectCliOutputFilter } from './cli-output-filter.js';
20
- export { detectNativeToolPreference } from './native-tool-preference.js';
21
- export { callLlm } from './llm.js';
32
+ export { applyFixRecipe, resolveSafePath, isRepairable } from './fix-engine.js';
33
+ export { isWithinRoot, resolveWithinRoot, realPathWithinRoot, resolveReadableWithinRoot, writeTargetWithinRoot } from './path-containment.js';
22
34
  export { optimizeContext } from './context-optimizer.js';
35
+ export { TARGET_MODELS, MODEL_BUDGETS_REVIEW_BY, resolveTargetModel, modelBudget, budgetForTargetModel, } from './model-budgets.js';
36
+ export { loadCustomRules, parseCustomRules, runCustomRules, CustomRulesError, CUSTOM_RULE_TYPES, CUSTOM_RULES_FILE, } from './custom-rules.js';
37
+ export { PROMPTCI_GITIGNORE_LINES, PROMPTCI_GITIGNORE_BLOCK, renderPromptCiGitignore, } from './promptci-gitignore.js';
23
38
  //# sourceMappingURL=index.js.map
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,qCAAqC;AACrC,cAAc,YAAY,CAAC;AAC3B,OAAO,EAAE,SAAS,EAAE,MAAM,cAAc,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAE,4BAA4B,EAAE,MAAM,mBAAmB,CAAC;AACpF,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,gBAAgB,EAAE,MAAM,iBAAiB,CAAC;AAC9F,OAAO,EAAE,eAAe,EAAE,sBAAsB,EAAE,4BAA4B,EAAE,MAAM,gBAAgB,CAAC;AACvG,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,oBAAoB,EAAE,MAAM,sBAAsB,CAAC;AAC5D,OAAO,EAAE,iBAAiB,EAAE,qBAAqB,EAAE,iBAAiB,EAAE,MAAM,kBAAkB,CAAC;AAE/F,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,MAAM,mBAAmB,CAAC;AACvE,OAAO,EAAE,sBAAsB,EAAE,kBAAkB,EAAE,WAAW,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,gBAAgB,EAAE,MAAM,aAAa,CAAC;AAEjJ,OAAO,EAAE,yBAAyB,EAAE,MAAM,2BAA2B,CAAC;AAEtE,OAAO,EAAE,gBAAgB,EAAE,qBAAqB,EAAE,MAAM,mBAAmB,CAAC;AAE5E,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,OAAO,EAAE,cAAc,EAAE,MAAM,uBAAuB,CAAC;AAEvD,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AACjC,OAAO,EAAE,kBAAkB,EAAE,cAAc,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAC;AACzG,OAAO,EAAE,cAAc,EAAE,eAAe,EAAE,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,qBAAqB,EAAE,MAAM,wBAAwB,CAAC;AAC/D,OAAO,EAAE,0BAA0B,EAAE,MAAM,6BAA6B,CAAC;AAEzE,OAAO,EAAE,OAAO,EAAE,MAAM,UAAU,CAAC;AACnC,OAAO,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,37 @@
1
+ /**
2
+ * Makefile target discovery for the command-validity check (`make <target>`).
3
+ *
4
+ * This is a deliberately small reader, not a make implementation. It collects
5
+ * the explicit targets a Makefile defines (`build:`, `lint test: deps`,
6
+ * `check::`), the names listed on `.PHONY`, and pattern rules (`%.o: %.c`).
7
+ * Whenever the file can define targets this reader cannot see — an `include`
8
+ * / `-include` / `sinclude` directive, or a target name computed from a
9
+ * variable or function (`$(BIN):`, `$(eval ...)`) — the result is marked
10
+ * unverifiable and callers must not report anything against it.
11
+ *
12
+ * Deterministic and offline: it only reads the Makefile text.
13
+ */
14
+ export type MakefileFacts = {
15
+ /** Repo-relative POSIX path of the Makefile read. */
16
+ file: string;
17
+ /** Explicit targets and `.PHONY` names. */
18
+ targets: string[];
19
+ /** Pattern-rule targets containing `%` (e.g. `%.o`, `build-%`). */
20
+ patterns: string[];
21
+ /**
22
+ * The file can define targets this reader cannot enumerate (`include`,
23
+ * computed target names, `$(eval)`): never report a target as missing.
24
+ */
25
+ unverifiable: boolean;
26
+ };
27
+ /** Parse Makefile text into its targets. Exported for tests. */
28
+ export declare function parseMakefileTargets(content: string, file?: string): MakefileFacts;
29
+ /** True when `target` is defined explicitly or matched by a pattern rule. */
30
+ export declare function makefileDefines(facts: MakefileFacts, target: string): boolean;
31
+ /**
32
+ * Read the Makefile make would use in a repo-relative directory ('.' = root).
33
+ * `undefined` when there is none (or it is oversized, unreadable, or a symlink
34
+ * leaving the repo).
35
+ */
36
+ export declare function readMakefile(repoRoot: string, dir: string): MakefileFacts | undefined;
37
+ //# sourceMappingURL=makefile.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makefile.d.ts","sourceRoot":"","sources":["../src/makefile.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAOH,MAAM,MAAM,aAAa,GAAG;IAC1B,qDAAqD;IACrD,IAAI,EAAE,MAAM,CAAC;IACb,2CAA2C;IAC3C,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,mEAAmE;IACnE,QAAQ,EAAE,MAAM,EAAE,CAAC;IACnB;;;OAGG;IACH,YAAY,EAAE,OAAO,CAAC;CACvB,CAAC;AAuBF,gEAAgE;AAChE,wBAAgB,oBAAoB,CAAC,OAAO,EAAE,MAAM,EAAE,IAAI,SAAa,GAAG,aAAa,CAwEtF;AAED,6EAA6E;AAC7E,wBAAgB,eAAe,CAAC,KAAK,EAAE,aAAa,EAAE,MAAM,EAAE,MAAM,GAAG,OAAO,CAY7E;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,aAAa,GAAG,SAAS,CAkBrF"}
@@ -0,0 +1,156 @@
1
+ /**
2
+ * Makefile target discovery for the command-validity check (`make <target>`).
3
+ *
4
+ * This is a deliberately small reader, not a make implementation. It collects
5
+ * the explicit targets a Makefile defines (`build:`, `lint test: deps`,
6
+ * `check::`), the names listed on `.PHONY`, and pattern rules (`%.o: %.c`).
7
+ * Whenever the file can define targets this reader cannot see — an `include`
8
+ * / `-include` / `sinclude` directive, or a target name computed from a
9
+ * variable or function (`$(BIN):`, `$(eval ...)`) — the result is marked
10
+ * unverifiable and callers must not report anything against it.
11
+ *
12
+ * Deterministic and offline: it only reads the Makefile text.
13
+ */
14
+ import * as fs from 'node:fs';
15
+ import * as path from 'node:path';
16
+ import { resolveReadableWithinRoot } from './path-containment.js';
17
+ import { MAX_FILE_SIZE } from './scanner.js';
18
+ /** GNU make's lookup order when no `-f` is given. */
19
+ const MAKEFILE_NAMES = ['GNUmakefile', 'makefile', 'Makefile'];
20
+ const TARGET_NAME_RE = /^[A-Za-z0-9_.%/+-]+$/;
21
+ /** Join backslash-continued lines, keeping one logical line per rule. */
22
+ function logicalLines(content) {
23
+ const out = [];
24
+ let pending = '';
25
+ for (const raw of content.split(/\r?\n/)) {
26
+ if (/\\$/.test(raw)) {
27
+ pending += raw.slice(0, -1) + ' ';
28
+ continue;
29
+ }
30
+ out.push(pending + raw);
31
+ pending = '';
32
+ }
33
+ if (pending)
34
+ out.push(pending);
35
+ return out;
36
+ }
37
+ /** Parse Makefile text into its targets. Exported for tests. */
38
+ export function parseMakefileTargets(content, file = 'Makefile') {
39
+ const targets = new Set();
40
+ const patterns = new Set();
41
+ let unverifiable = false;
42
+ let inDefine = false;
43
+ for (const line of logicalLines(content)) {
44
+ // Recipe lines start with a tab; they never define targets.
45
+ if (line.startsWith('\t'))
46
+ continue;
47
+ const text = line.replace(/(?<!\\)#.*$/, '').trimEnd();
48
+ const trimmed = text.trim();
49
+ if (!trimmed)
50
+ continue;
51
+ if (/^define\b/.test(trimmed) || /^(?:override\s+)?define\s/.test(trimmed)) {
52
+ inDefine = true;
53
+ continue;
54
+ }
55
+ if (inDefine) {
56
+ if (/^endef\b/.test(trimmed))
57
+ inDefine = false;
58
+ continue;
59
+ }
60
+ // Targets this reader cannot see.
61
+ if (/^(?:-include|sinclude|include)\s/.test(trimmed)) {
62
+ unverifiable = true;
63
+ continue;
64
+ }
65
+ if (/\$\((?:eval|call)\b/.test(trimmed)) {
66
+ unverifiable = true;
67
+ continue;
68
+ }
69
+ // `NAME := x`, `NAME ::= x`, `NAME ?= x`, `NAME += x`, `NAME = x`, `export X = y`.
70
+ const colon = trimmed.indexOf(':');
71
+ const equals = trimmed.indexOf('=');
72
+ if (colon === -1)
73
+ continue;
74
+ if (equals !== -1 && equals < colon)
75
+ continue; // assignment whose value holds a colon
76
+ const afterColon = trimmed.slice(colon + 1);
77
+ if (/^:?=/.test(afterColon) || /^::=/.test(afterColon))
78
+ continue; // `:=` / `::=` / `:::=`
79
+ const head = trimmed.slice(0, colon).trim();
80
+ if (!head)
81
+ continue;
82
+ if (/^(?:ifeq|ifneq|ifdef|ifndef|else|endif|export|unexport|override|private|vpath)\b/.test(head))
83
+ continue;
84
+ if (head.includes('$')) {
85
+ // `$(BIN): main.o` — the target name is computed.
86
+ unverifiable = true;
87
+ continue;
88
+ }
89
+ if (head === '.DEFAULT') {
90
+ // A `.DEFAULT` recipe runs for any target without a rule of its own.
91
+ unverifiable = true;
92
+ continue;
93
+ }
94
+ if (head === '.PHONY') {
95
+ for (const name of afterColon.replace(/^:/, '').trim().split(/\s+/)) {
96
+ if (name && !name.includes('$') && TARGET_NAME_RE.test(name))
97
+ targets.add(name);
98
+ else if (name.includes('$'))
99
+ unverifiable = true;
100
+ }
101
+ continue;
102
+ }
103
+ for (const name of head.split(/\s+/)) {
104
+ if (!name || !TARGET_NAME_RE.test(name))
105
+ continue;
106
+ if (name.includes('%'))
107
+ patterns.add(name);
108
+ else
109
+ targets.add(name);
110
+ }
111
+ }
112
+ return { file, targets: [...targets].sort(), patterns: [...patterns].sort(), unverifiable };
113
+ }
114
+ /** True when `target` is defined explicitly or matched by a pattern rule. */
115
+ export function makefileDefines(facts, target) {
116
+ if (facts.targets.includes(target))
117
+ return true;
118
+ return facts.patterns.some((pattern) => {
119
+ const idx = pattern.indexOf('%');
120
+ const prefix = pattern.slice(0, idx);
121
+ const suffix = pattern.slice(idx + 1);
122
+ return (target.length > prefix.length + suffix.length &&
123
+ target.startsWith(prefix) &&
124
+ target.endsWith(suffix));
125
+ });
126
+ }
127
+ /**
128
+ * Read the Makefile make would use in a repo-relative directory ('.' = root).
129
+ * `undefined` when there is none (or it is oversized, unreadable, or a symlink
130
+ * leaving the repo).
131
+ */
132
+ export function readMakefile(repoRoot, dir) {
133
+ for (const name of MAKEFILE_NAMES) {
134
+ const rel = dir === '.' || dir === '' ? name : `${dir}/${name}`;
135
+ const abs = resolveReadableWithinRoot(repoRoot, rel);
136
+ if (!abs)
137
+ continue;
138
+ try {
139
+ const stat = fs.statSync(abs);
140
+ if (!stat.isFile())
141
+ continue;
142
+ // An exact-case match: on a case-insensitive filesystem `makefile` would
143
+ // otherwise also "find" `Makefile` and report the wrong file name.
144
+ if (!fs.readdirSync(path.dirname(abs)).includes(name))
145
+ continue;
146
+ if (stat.size > MAX_FILE_SIZE)
147
+ return { file: rel, targets: [], patterns: [], unverifiable: true };
148
+ return parseMakefileTargets(fs.readFileSync(abs, 'utf8'), rel);
149
+ }
150
+ catch {
151
+ continue;
152
+ }
153
+ }
154
+ return undefined;
155
+ }
156
+ //# sourceMappingURL=makefile.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"makefile.js","sourceRoot":"","sources":["../src/makefile.ts"],"names":[],"mappings":"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"}
@@ -24,6 +24,12 @@ export type ManifestData = {
24
24
  packageJson?: string;
25
25
  /** Raw text content of pyproject.toml, if present. */
26
26
  pyproject?: string;
27
+ /**
28
+ * BUG-004: raw text content of requirements.txt, if present. Read once
29
+ * (asynchronously) while building the RepoContext so detectors never do
30
+ * synchronous disk I/O inside the scan pipeline.
31
+ */
32
+ requirements?: string;
27
33
  };
28
34
  /**
29
35
  * Cross-reference instruction files against project manifests and flag
@@ -1 +1 @@
1
- {"version":3,"file":"manifest-consistency.d.ts","sourceRoot":"","sources":["../src/manifest-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAIrD,MAAM,MAAM,YAAY,GAAG;IACzB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,CAAC;AAgsBF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAuB/E"}
1
+ {"version":3,"file":"manifest-consistency.d.ts","sourceRoot":"","sources":["../src/manifest-consistency.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;GAkBG;AAKH,OAAO,KAAK,EAAmB,aAAa,EAAE,MAAM,YAAY,CAAC;AACjE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAQrD,MAAM,MAAM,YAAY,GAAG;IACzB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,sDAAsD;IACtD,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB;;;;OAIG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;CACvB,CAAC;AA2vBF;;;;;;;GAOG;AACH,wBAAgB,yBAAyB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAuB/E"}