@promptci/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +30 -0
  3. package/dist/agent-practices.d.ts +22 -0
  4. package/dist/agent-practices.d.ts.map +1 -0
  5. package/dist/agent-practices.js +582 -0
  6. package/dist/agent-practices.js.map +1 -0
  7. package/dist/baseline.d.ts +40 -0
  8. package/dist/baseline.d.ts.map +1 -0
  9. package/dist/baseline.js +172 -0
  10. package/dist/baseline.js.map +1 -0
  11. package/dist/canonical-owner.d.ts +3 -0
  12. package/dist/canonical-owner.d.ts.map +1 -0
  13. package/dist/canonical-owner.js +131 -0
  14. package/dist/canonical-owner.js.map +1 -0
  15. package/dist/cheap-model-routing.d.ts +4 -0
  16. package/dist/cheap-model-routing.d.ts.map +1 -0
  17. package/dist/cheap-model-routing.js +43 -0
  18. package/dist/cheap-model-routing.js.map +1 -0
  19. package/dist/ci-alignment.d.ts +10 -0
  20. package/dist/ci-alignment.d.ts.map +1 -0
  21. package/dist/ci-alignment.js +343 -0
  22. package/dist/ci-alignment.js.map +1 -0
  23. package/dist/cli-output-filter.d.ts +16 -0
  24. package/dist/cli-output-filter.d.ts.map +1 -0
  25. package/dist/cli-output-filter.js +88 -0
  26. package/dist/cli-output-filter.js.map +1 -0
  27. package/dist/command-validity.d.ts +12 -0
  28. package/dist/command-validity.d.ts.map +1 -0
  29. package/dist/command-validity.js +543 -0
  30. package/dist/command-validity.js.map +1 -0
  31. package/dist/conflicts.d.ts +49 -0
  32. package/dist/conflicts.d.ts.map +1 -0
  33. package/dist/conflicts.js +1065 -0
  34. package/dist/conflicts.js.map +1 -0
  35. package/dist/context-analysis.d.ts +15 -0
  36. package/dist/context-analysis.d.ts.map +1 -0
  37. package/dist/context-analysis.js +24 -0
  38. package/dist/context-analysis.js.map +1 -0
  39. package/dist/context-bloat.d.ts +17 -0
  40. package/dist/context-bloat.d.ts.map +1 -0
  41. package/dist/context-bloat.js +148 -0
  42. package/dist/context-bloat.js.map +1 -0
  43. package/dist/context-cost.d.ts +4 -0
  44. package/dist/context-cost.d.ts.map +1 -0
  45. package/dist/context-cost.js +70 -0
  46. package/dist/context-cost.js.map +1 -0
  47. package/dist/context-optimizer.d.ts +14 -0
  48. package/dist/context-optimizer.d.ts.map +1 -0
  49. package/dist/context-optimizer.js +219 -0
  50. package/dist/context-optimizer.js.map +1 -0
  51. package/dist/context-recommender.d.ts +3 -0
  52. package/dist/context-recommender.d.ts.map +1 -0
  53. package/dist/context-recommender.js +329 -0
  54. package/dist/context-recommender.js.map +1 -0
  55. package/dist/dead-references.d.ts +33 -0
  56. package/dist/dead-references.d.ts.map +1 -0
  57. package/dist/dead-references.js +607 -0
  58. package/dist/dead-references.js.map +1 -0
  59. package/dist/detectors.d.ts +11 -0
  60. package/dist/detectors.d.ts.map +1 -0
  61. package/dist/detectors.js +160 -0
  62. package/dist/detectors.js.map +1 -0
  63. package/dist/duplicates.d.ts +36 -0
  64. package/dist/duplicates.d.ts.map +1 -0
  65. package/dist/duplicates.js +436 -0
  66. package/dist/duplicates.js.map +1 -0
  67. package/dist/fix-engine.d.ts +16 -0
  68. package/dist/fix-engine.d.ts.map +1 -0
  69. package/dist/fix-engine.js +179 -0
  70. package/dist/fix-engine.js.map +1 -0
  71. package/dist/framework-packs.d.ts +8 -0
  72. package/dist/framework-packs.d.ts.map +1 -0
  73. package/dist/framework-packs.js +22 -0
  74. package/dist/framework-packs.js.map +1 -0
  75. package/dist/frameworks/dotnet.d.ts +4 -0
  76. package/dist/frameworks/dotnet.d.ts.map +1 -0
  77. package/dist/frameworks/dotnet.js +77 -0
  78. package/dist/frameworks/dotnet.js.map +1 -0
  79. package/dist/frameworks/go.d.ts +4 -0
  80. package/dist/frameworks/go.d.ts.map +1 -0
  81. package/dist/frameworks/go.js +39 -0
  82. package/dist/frameworks/go.js.map +1 -0
  83. package/dist/frameworks/nextjs.d.ts +4 -0
  84. package/dist/frameworks/nextjs.d.ts.map +1 -0
  85. package/dist/frameworks/nextjs.js +66 -0
  86. package/dist/frameworks/nextjs.js.map +1 -0
  87. package/dist/frameworks/python.d.ts +4 -0
  88. package/dist/frameworks/python.d.ts.map +1 -0
  89. package/dist/frameworks/python.js +66 -0
  90. package/dist/frameworks/python.js.map +1 -0
  91. package/dist/frameworks/rust.d.ts +4 -0
  92. package/dist/frameworks/rust.d.ts.map +1 -0
  93. package/dist/frameworks/rust.js +72 -0
  94. package/dist/frameworks/rust.js.map +1 -0
  95. package/dist/frameworks/unity.d.ts +4 -0
  96. package/dist/frameworks/unity.d.ts.map +1 -0
  97. package/dist/frameworks/unity.js +74 -0
  98. package/dist/frameworks/unity.js.map +1 -0
  99. package/dist/health-score.d.ts +37 -0
  100. package/dist/health-score.d.ts.map +1 -0
  101. package/dist/health-score.js +164 -0
  102. package/dist/health-score.js.map +1 -0
  103. package/dist/index.d.ts +31 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +23 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/llm.d.ts +6 -0
  108. package/dist/llm.d.ts.map +1 -0
  109. package/dist/llm.js +67 -0
  110. package/dist/llm.js.map +1 -0
  111. package/dist/manifest-consistency.d.ts +37 -0
  112. package/dist/manifest-consistency.d.ts.map +1 -0
  113. package/dist/manifest-consistency.js +659 -0
  114. package/dist/manifest-consistency.js.map +1 -0
  115. package/dist/mcp-detector.d.ts +4 -0
  116. package/dist/mcp-detector.d.ts.map +1 -0
  117. package/dist/mcp-detector.js +131 -0
  118. package/dist/mcp-detector.js.map +1 -0
  119. package/dist/missing-context.d.ts +15 -0
  120. package/dist/missing-context.d.ts.map +1 -0
  121. package/dist/missing-context.js +517 -0
  122. package/dist/missing-context.js.map +1 -0
  123. package/dist/native-tool-preference.d.ts +20 -0
  124. package/dist/native-tool-preference.d.ts.map +1 -0
  125. package/dist/native-tool-preference.js +94 -0
  126. package/dist/native-tool-preference.js.map +1 -0
  127. package/dist/output-verbosity.d.ts +3 -0
  128. package/dist/output-verbosity.d.ts.map +1 -0
  129. package/dist/output-verbosity.js +83 -0
  130. package/dist/output-verbosity.js.map +1 -0
  131. package/dist/product-boundary.d.ts +11 -0
  132. package/dist/product-boundary.d.ts.map +1 -0
  133. package/dist/product-boundary.js +301 -0
  134. package/dist/product-boundary.js.map +1 -0
  135. package/dist/project-type.d.ts +15 -0
  136. package/dist/project-type.d.ts.map +1 -0
  137. package/dist/project-type.js +116 -0
  138. package/dist/project-type.js.map +1 -0
  139. package/dist/prompt-cache.d.ts +3 -0
  140. package/dist/prompt-cache.d.ts.map +1 -0
  141. package/dist/prompt-cache.js +151 -0
  142. package/dist/prompt-cache.js.map +1 -0
  143. package/dist/repo-context.d.ts +37 -0
  144. package/dist/repo-context.d.ts.map +1 -0
  145. package/dist/repo-context.js +221 -0
  146. package/dist/repo-context.js.map +1 -0
  147. package/dist/report.d.ts +87 -0
  148. package/dist/report.d.ts.map +1 -0
  149. package/dist/report.js +558 -0
  150. package/dist/report.js.map +1 -0
  151. package/dist/scan.d.ts +7 -0
  152. package/dist/scan.d.ts.map +1 -0
  153. package/dist/scan.js +43 -0
  154. package/dist/scan.js.map +1 -0
  155. package/dist/scanner.d.ts +3 -0
  156. package/dist/scanner.d.ts.map +1 -0
  157. package/dist/scanner.js +216 -0
  158. package/dist/scanner.js.map +1 -0
  159. package/dist/security-pack.d.ts +4 -0
  160. package/dist/security-pack.d.ts.map +1 -0
  161. package/dist/security-pack.js +403 -0
  162. package/dist/security-pack.js.map +1 -0
  163. package/dist/stale-instructions.d.ts +20 -0
  164. package/dist/stale-instructions.d.ts.map +1 -0
  165. package/dist/stale-instructions.js +269 -0
  166. package/dist/stale-instructions.js.map +1 -0
  167. package/dist/suppression.d.ts +64 -0
  168. package/dist/suppression.d.ts.map +1 -0
  169. package/dist/suppression.js +338 -0
  170. package/dist/suppression.js.map +1 -0
  171. package/dist/types.d.ts +128 -0
  172. package/dist/types.d.ts.map +1 -0
  173. package/dist/types.js +3 -0
  174. package/dist/types.js.map +1 -0
  175. package/dist/vague-guidance.d.ts +12 -0
  176. package/dist/vague-guidance.d.ts.map +1 -0
  177. package/dist/vague-guidance.js +235 -0
  178. package/dist/vague-guidance.js.map +1 -0
  179. package/package.json +54 -0
@@ -0,0 +1,543 @@
1
+ import * as fs from 'node:fs';
2
+ import * as path from 'node:path';
3
+ import * as crypto from 'node:crypto';
4
+ /**
5
+ * Command Validity Detector
6
+ *
7
+ * Validates shell commands documented in instruction files without executing
8
+ * them. Checks that referenced scripts, files, and package.json script names
9
+ * actually exist in the repository.
10
+ *
11
+ * Scope:
12
+ * - Commands extracted from fenced code blocks (```bash / ```sh / …)
13
+ * - Inline backtick commands
14
+ * - Prose patterns like "run pnpm test"
15
+ * - Multi-command lines joined with && are split and each segment validated
16
+ *
17
+ * Findings are heuristic — cautious wording is intentional.
18
+ */
19
+ // ── Helpers ───────────────────────────────────────────────────────────────────
20
+ /** Stable per-finding ID based on file + command text. */
21
+ function issueId(filePath, cmdText) {
22
+ const hash = crypto
23
+ .createHash('sha1')
24
+ .update(`${filePath}|${cmdText}`)
25
+ .digest('hex')
26
+ .slice(0, 12);
27
+ return `cmd-validity-${hash}`;
28
+ }
29
+ /** Returns true when a repo-relative path exists on disk. */
30
+ function fileExists(repoRoot, relativePath) {
31
+ try {
32
+ const full = path.resolve(repoRoot, relativePath);
33
+ return fs.existsSync(full);
34
+ }
35
+ catch {
36
+ return false;
37
+ }
38
+ }
39
+ function readPackageScripts(packageJsonPath) {
40
+ try {
41
+ const raw = fs.readFileSync(packageJsonPath, 'utf8');
42
+ const parsed = JSON.parse(raw);
43
+ if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
44
+ return null;
45
+ const scripts = typeof parsed.scripts === 'object' && parsed.scripts !== null && !Array.isArray(parsed.scripts)
46
+ ? Object.fromEntries(Object.entries(parsed.scripts).filter((entry) => typeof entry[1] === 'string'))
47
+ : {};
48
+ return {
49
+ name: typeof parsed.name === 'string' ? parsed.name : undefined,
50
+ scripts,
51
+ };
52
+ }
53
+ catch {
54
+ return null;
55
+ }
56
+ }
57
+ function pnpmFilterValue(parts) {
58
+ for (let i = 1; i < parts.length; i++) {
59
+ const part = parts[i];
60
+ if (part === '--filter' || part === '-F')
61
+ return parts[i + 1];
62
+ if (part.startsWith('--filter='))
63
+ return part.slice('--filter='.length);
64
+ if (part.startsWith('-F='))
65
+ return part.slice('-F='.length);
66
+ }
67
+ return undefined;
68
+ }
69
+ function normalizePnpmFilter(value) {
70
+ if (!value)
71
+ return undefined;
72
+ return value
73
+ .replace(/^['"]|['"]$/g, '')
74
+ .replace(/^\.\.\./, '')
75
+ .replace(/\.\.\.$/, '')
76
+ .replace(/^!/, '')
77
+ .trim();
78
+ }
79
+ function workspacePackageJsonCandidates(repoRoot, selector) {
80
+ const candidates = new Set();
81
+ const selectorAsPath = selector.replace(/\\/g, '/');
82
+ if (selectorAsPath.startsWith('.') || selectorAsPath.includes('/')) {
83
+ candidates.add(path.join(repoRoot, selectorAsPath, 'package.json'));
84
+ }
85
+ for (const dir of ['apps', 'packages', 'libs']) {
86
+ const absDir = path.join(repoRoot, dir);
87
+ try {
88
+ for (const entry of fs.readdirSync(absDir, { withFileTypes: true })) {
89
+ if (entry.isDirectory()) {
90
+ candidates.add(path.join(absDir, entry.name, 'package.json'));
91
+ }
92
+ }
93
+ }
94
+ catch {
95
+ // Workspace directory absent.
96
+ }
97
+ }
98
+ return [...candidates];
99
+ }
100
+ function workspaceHasScript(context, selector, scriptName) {
101
+ const normalizedSelector = normalizePnpmFilter(selector);
102
+ if (!normalizedSelector)
103
+ return false;
104
+ for (const candidate of workspacePackageJsonCandidates(context.repoRoot, normalizedSelector)) {
105
+ const pkg = readPackageScripts(candidate);
106
+ if (!pkg)
107
+ continue;
108
+ const packageDir = path.dirname(candidate).replace(/\\/g, '/');
109
+ const relDir = path.relative(context.repoRoot, packageDir).replace(/\\/g, '/');
110
+ const selectorMatches = pkg.name === normalizedSelector ||
111
+ relDir === normalizedSelector ||
112
+ relDir.endsWith(`/${normalizedSelector}`);
113
+ if (selectorMatches && !!pkg.scripts[scriptName])
114
+ return true;
115
+ }
116
+ return false;
117
+ }
118
+ /** Returns true when a path string looks like a file reference (not a flag). */
119
+ function isLikelyFilePath(str) {
120
+ if (!str)
121
+ return false;
122
+ if (str.startsWith('-'))
123
+ return false; // CLI flag
124
+ // Looks like a path if it has a directory separator or a file extension
125
+ return str.includes('/') || str.includes('\\') || /\.[a-z]{1,5}$/i.test(str);
126
+ }
127
+ // ── Standard subcommands that are NOT user-defined package scripts ─────────────
128
+ const PNPM_BUILTINS = new Set([
129
+ 'install', 'i', 'add', 'remove', 'uninstall', 'test', 'it', 'init',
130
+ 'create', 'publish', 'link', 'unlink', 'outdated', 'audit', 'update',
131
+ 'up', 'exec', 'dlx', 'run', 'store', 'list', 'ls', 'why', 'pack',
132
+ 'recursive', 'm', 'multi', 'prune',
133
+ ]);
134
+ const NPM_BUILTINS = new Set([
135
+ 'install', 'i', 'ci', 'uninstall', 'remove', 'update', 'outdated',
136
+ 'audit', 'start', 'stop', 'restart', 'test', 'it', 'init', 'create',
137
+ 'publish', 'link', 'unlink', 'pack', 'exec', 'run',
138
+ ]);
139
+ const YARN_BUILTINS = new Set([
140
+ 'install', 'add', 'remove', 'upgrade', 'outdated', 'audit', 'init',
141
+ 'create', 'publish', 'link', 'unlink', 'why', 'pack', 'run',
142
+ ]);
143
+ /**
144
+ * CV6: Resolves a `cd <target>` against the current repo-relative directory so
145
+ * that a `cd apps/web && pnpm test:e2e` line validates `test:e2e` against
146
+ * `apps/web/package.json` rather than the repo-root manifest. Returns the new
147
+ * repo-relative POSIX directory ('.' for root), or `null` when the target
148
+ * escapes the repo or is absolute/home (an unknown location we won't validate).
149
+ */
150
+ function resolveCwd(current, target) {
151
+ if (current === null)
152
+ return null;
153
+ const cleaned = target.replace(/^['"]|['"]$/g, '').trim();
154
+ if (!cleaned || cleaned.startsWith('/') || cleaned.startsWith('~') || /^[a-zA-Z]:[\\/]/.test(cleaned)) {
155
+ return null; // absolute or home path — not resolvable to a repo-relative dir
156
+ }
157
+ const parts = current === '.' ? [] : current.split('/');
158
+ for (const seg of cleaned.replace(/\\/g, '/').split('/')) {
159
+ if (seg === '' || seg === '.')
160
+ continue;
161
+ if (seg === '..') {
162
+ if (parts.length === 0)
163
+ return null; // escapes repo root
164
+ parts.pop();
165
+ }
166
+ else {
167
+ parts.push(seg);
168
+ }
169
+ }
170
+ return parts.length === 0 ? '.' : parts.join('/');
171
+ }
172
+ /**
173
+ * Splits a command string on `&&`, `||`, `;`, and newlines, yielding
174
+ * individual segments. This allows a single `run:` block or backtick
175
+ * expression like `pnpm lint && pnpm test` — or `pnpm lint; pnpm bogus`, or
176
+ * `cmd1 || cmd2` — to be validated command-by-command.
177
+ *
178
+ * CV4: previously only `&&`/newline were split, so `;` and `||` joined
179
+ * commands stayed as ONE segment — `pnpm lint; pnpm bogus` read as tool
180
+ * "pnpm", subcommand "lint;" (a false-positive missing-script report on the
181
+ * literal string "lint;"), and the second command was never validated at all.
182
+ */
183
+ function splitOnAmpersand(cmd) {
184
+ return cmd
185
+ .split(/&&|\|\||;|\n/)
186
+ .map((s) => s.trim())
187
+ .filter(Boolean);
188
+ }
189
+ /** Returns true if a text looks like it could be a shell command to validate. */
190
+ function isPotentialCommand(text) {
191
+ const KNOWN_PREFIXES = [
192
+ 'npm', 'pnpm', 'yarn', 'bun',
193
+ 'node', 'tsx', 'ts-node', 'bash', 'sh', 'python', 'python3',
194
+ 'dotnet', 'docker', 'make',
195
+ 'git', 'ls', 'cd', 'mkdir', 'rm', 'cp', 'mv',
196
+ './', '../',
197
+ ];
198
+ const first = text.trim().split(/\s+/)[0] ?? '';
199
+ if (KNOWN_PREFIXES.some((p) => first === p || first.startsWith('./')))
200
+ return true;
201
+ // ./scripts/something.sh style
202
+ if (first.startsWith('./') || first.startsWith('../'))
203
+ return true;
204
+ return false;
205
+ }
206
+ /**
207
+ * Fence languages whose content is treated as shell commands. A bare fence
208
+ * (no language) is also treated as shell — that matches the historical
209
+ * behavior of the old regex, where the language group was optional.
210
+ */
211
+ const SHELL_FENCE_LANGS = new Set([
212
+ 'bash', 'sh', 'shell', 'powershell', 'pwsh', 'zsh', 'command-line', 'cmd',
213
+ ]);
214
+ /** Extracts commands from a single instruction-file content string. */
215
+ function extractCommands(content) {
216
+ const commands = [];
217
+ const lines = content.split(/\r?\n/);
218
+ // CV1: track fence char + length (matching scanner.ts/vague-guidance.ts/
219
+ // stale-instructions.ts/conflicts.ts) so we know we're inside SOME fence
220
+ // even for languages we don't scan for commands. The old regex only
221
+ // recognized bare ``` or a fixed shell-language list as an OPENER — a
222
+ // ```json fence's opener didn't match, so its bare ``` CLOSER was misread
223
+ // as a NEW opener, inverting inBlock state for the rest of the file.
224
+ let inBlock = false;
225
+ let inShellBlock = false;
226
+ let fenceChar = null;
227
+ let fenceLen = 0;
228
+ let blockStartLine = -1;
229
+ // CV2: keep the block's raw (untrimmed) lines so each entry's index still
230
+ // corresponds 1:1 to its physical line offset from blockStartLine. The old
231
+ // code joined the block into one string and called `.trim()` on it before
232
+ // re-splitting — that silently dropped leading/trailing blank lines, so
233
+ // blockLines[j] no longer matched the physical line blockStartLine + j + 1
234
+ // whenever the fenced block had leading blank lines.
235
+ let blockContent = [];
236
+ for (let i = 0; i < lines.length; i++) {
237
+ const line = lines[i];
238
+ if (!inBlock) {
239
+ const openMatch = /^ {0,3}([`~]{3,})\s*([a-zA-Z0-9_-]*)/.exec(line);
240
+ if (openMatch) {
241
+ inBlock = true;
242
+ fenceChar = openMatch[1][0] ?? null;
243
+ fenceLen = openMatch[1].length;
244
+ const lang = (openMatch[2] ?? '').toLowerCase();
245
+ inShellBlock = lang === '' || SHELL_FENCE_LANGS.has(lang);
246
+ blockStartLine = i + 1;
247
+ blockContent = [];
248
+ continue;
249
+ }
250
+ }
251
+ else {
252
+ const closeMatch = /^ {0,3}([`~]{3,})\s*$/.exec(line);
253
+ if (closeMatch && closeMatch[1][0] === fenceChar && closeMatch[1].length >= fenceLen) {
254
+ inBlock = false;
255
+ if (inShellBlock) {
256
+ for (let j = 0; j < blockContent.length; j++) {
257
+ const raw = blockContent[j];
258
+ const rawTrimmed = raw.trim();
259
+ if (rawTrimmed.startsWith('#'))
260
+ continue;
261
+ const trimmed = rawTrimmed.replace(/^\$\s*/, '');
262
+ if (!trimmed)
263
+ continue;
264
+ // CV6: each documented line is treated as an independent example run
265
+ // from the repo root, so `cd` only affects commands chained after it
266
+ // on the SAME line (e.g. `cd apps/web && pnpm test:e2e`). Setup blocks
267
+ // are written this way — repeating `cd apps/web` on separate lines —
268
+ // so a standalone `cd` must not bleed into later lines.
269
+ let lineCwd = '.';
270
+ for (const seg of splitOnAmpersand(trimmed)) {
271
+ const cdMatch = /^cd\s+(.+)$/.exec(seg);
272
+ if (cdMatch) {
273
+ lineCwd = resolveCwd(lineCwd, cdMatch[1].trim());
274
+ }
275
+ commands.push({ text: seg, line: blockStartLine + j + 1, cwd: lineCwd });
276
+ }
277
+ }
278
+ }
279
+ inShellBlock = false;
280
+ fenceChar = null;
281
+ fenceLen = 0;
282
+ continue;
283
+ }
284
+ // Still inside the fence — accumulate only if it's a shell-ish block;
285
+ // non-shell fences (```json, ```ts, …) are tracked for state but their
286
+ // content is never scanned for commands.
287
+ if (inShellBlock)
288
+ blockContent.push(line);
289
+ continue;
290
+ }
291
+ // Inline backticks
292
+ for (const m of line.matchAll(/`([^`]+)`/g)) {
293
+ const inner = m[1].trim();
294
+ // CV6: an inline backtick expression is one shell line, so `cd` inside it
295
+ // affects the commands chained after it (e.g. `cd apps/web && pnpm test:e2e`).
296
+ let lineCwd = '.';
297
+ // Split on && inside backticks
298
+ for (const seg of splitOnAmpersand(inner)) {
299
+ const cdMatch = /^cd\s+(.+)$/.exec(seg);
300
+ if (cdMatch) {
301
+ lineCwd = resolveCwd(lineCwd, cdMatch[1].trim());
302
+ }
303
+ if (isPotentialCommand(seg)) {
304
+ commands.push({ text: seg, line: i + 1, cwd: lineCwd });
305
+ }
306
+ }
307
+ }
308
+ // Prose "run pnpm test" / "run npm run build" patterns
309
+ for (const m of line.matchAll(/\brun\s+(pnpm|npm|yarn|bun|node|tsx|ts-node|bash|python|dotnet|docker)\s+(.+?)(?=[.!?](?:\s|$)|[,;!]|$)/gi)) {
310
+ const args = (m[2] ?? '').trim().replace(/[.!?]+$/, '');
311
+ const fullCmd = `${m[1]} ${args}`.trim();
312
+ commands.push({ text: fullCmd, line: i + 1 });
313
+ }
314
+ }
315
+ return commands;
316
+ }
317
+ // ── Command validation ────────────────────────────────────────────────────────
318
+ /** Placeholder patterns that indicate a command is intentionally abstract. */
319
+ const PLACEHOLDER_RE = /[<{]|\.{3,}|your-file|your-script|example|placeholder/i;
320
+ /**
321
+ * CV3/CV5: CLI flags that take a following value argument, keyed by the flag
322
+ * text. Used to skip PAST both the flag and its value when hunting for the
323
+ * "real" subcommand/script-name or file-path argument — without this, a flag
324
+ * like `--filter` or `--loader` gets mistaken for the subcommand, and its
325
+ * VALUE (a package name or loader module) gets mistaken for a file path.
326
+ */
327
+ const FLAGS_WITH_VALUE = new Set(['--filter', '-F', '--cwd', '-C', '--loader', '--require', '-r']);
328
+ function flagTakesValue(tool, flag) {
329
+ if (tool === 'pnpm' && flag === '-r')
330
+ return false;
331
+ return FLAGS_WITH_VALUE.has(flag);
332
+ }
333
+ /**
334
+ * Returns the index of the first token in `parts` (starting after the tool
335
+ * name at index 0) that is NOT a flag and not a known flag's value.
336
+ *
337
+ * CV3: `pnpm --filter @promptci/core test` previously read parts[1]
338
+ * ("--filter") as the script name, reporting a false-positive missing
339
+ * script. `pnpm -r build` and `yarn --cwd app build` had the same problem.
340
+ * CV5: `node --loader ts-node/esm src/x.ts` previously matched
341
+ * "ts-node/esm" (the loader flag's VALUE, which happens to contain a slash)
342
+ * as the file being executed, instead of the real target "src/x.ts".
343
+ */
344
+ function firstNonFlagArgIndex(parts) {
345
+ let idx = 1;
346
+ const tool = parts[0] ?? '';
347
+ while (idx < parts.length) {
348
+ const p = parts[idx];
349
+ if (!p.startsWith('-'))
350
+ break;
351
+ idx++;
352
+ if (flagTakesValue(tool, p) && parts[idx] && !parts[idx].startsWith('-')) {
353
+ idx++; // also skip the flag's value token
354
+ }
355
+ }
356
+ return idx;
357
+ }
358
+ /**
359
+ * CV6/CV7: Validates one or more package-manager script names, honoring both a
360
+ * `cd`-established working directory and slash-joined shorthand.
361
+ *
362
+ * CV6 (cwd): when a command runs after `cd <subdir>`, its scripts live in
363
+ * `<subdir>/package.json`, NOT the repo-root manifest — so
364
+ * `cd apps/web && pnpm test:e2e` is valid whenever apps/web defines `test:e2e`.
365
+ *
366
+ * CV7 (slash shorthand): `pnpm lint/typecheck/test/build` is a documentation
367
+ * shorthand for four separate scripts, not one literal script named
368
+ * "lint/typecheck/test/build". Each `/`-separated part is validated on its own.
369
+ *
370
+ * Returns an error string for the first genuinely-missing script, or null.
371
+ */
372
+ function findMissingScript(context, cwd, parts, scriptName, builtins, tool) {
373
+ // Unknown working directory (unresolvable `cd`) — cannot verify.
374
+ if (cwd === null)
375
+ return null;
376
+ const names = scriptName.includes('/')
377
+ ? scriptName.split('/').map((s) => s.trim()).filter(Boolean)
378
+ : [scriptName];
379
+ const inSubdir = cwd !== '.' && cwd !== '';
380
+ const dirPkg = inSubdir
381
+ ? readPackageScripts(path.join(context.repoRoot, cwd, 'package.json'))
382
+ : null;
383
+ // cd'd into a directory whose package.json we can't read — don't guess.
384
+ if (inSubdir && !dirPkg)
385
+ return null;
386
+ const rootScriptsLoaded = Object.keys(context.packageJson.scripts).length > 0;
387
+ // No manifest we can check anywhere — stay silent.
388
+ if (!dirPkg && !rootScriptsLoaded)
389
+ return null;
390
+ for (const name of names) {
391
+ if (builtins.has(name))
392
+ continue;
393
+ if (dirPkg) {
394
+ // A command that runs inside a subdir resolves scripts ONLY from that
395
+ // subdir's manifest (pnpm/npm/yarn do not search parent directories) or
396
+ // from an explicit --filter workspace target. A same-named root script is
397
+ // NOT reachable here, so it must not mask a genuinely missing subdir
398
+ // script.
399
+ if (dirPkg.scripts[name])
400
+ continue;
401
+ if (workspaceHasScript(context, pnpmFilterValue(parts), name))
402
+ continue;
403
+ return `${tool} script "${name}" does not appear in ${cwd}/package.json scripts`;
404
+ }
405
+ // Repo-root context: the pnpm --filter workspace target or the root manifest.
406
+ if (workspaceHasScript(context, pnpmFilterValue(parts), name))
407
+ continue;
408
+ if (context.packageJson.scripts[name])
409
+ continue;
410
+ return `${tool} script "${name}" does not appear in package.json scripts`;
411
+ }
412
+ return null;
413
+ }
414
+ /**
415
+ * Validates a single command segment against the repo context.
416
+ * Returns a human-readable error string, or null if the command looks valid.
417
+ *
418
+ * @param cwd Repo-relative directory the command runs in ('.' = root, null =
419
+ * unknown after an unresolvable `cd` — validation is skipped).
420
+ */
421
+ function validateSegment(seg, context, cwd = '.') {
422
+ if (PLACEHOLDER_RE.test(seg))
423
+ return null;
424
+ const parts = seg.trim().split(/\s+/);
425
+ if (parts.length === 0)
426
+ return null;
427
+ const tool = parts[0];
428
+ // Base directory for file-existence checks — respects a `cd`-established cwd.
429
+ const baseDir = cwd === null
430
+ ? null
431
+ : cwd !== '.' && cwd !== ''
432
+ ? path.join(context.repoRoot, cwd)
433
+ : context.repoRoot;
434
+ // ── Package manager scripts ────────────────────────────────────────────────
435
+ if (tool === 'pnpm') {
436
+ const subIdx = firstNonFlagArgIndex(parts);
437
+ const sub = parts[subIdx];
438
+ if (!sub)
439
+ return null;
440
+ const scriptName = sub === 'run' ? parts[subIdx + 1] : sub;
441
+ if (!scriptName)
442
+ return null;
443
+ return findMissingScript(context, cwd, parts, scriptName, PNPM_BUILTINS, 'pnpm');
444
+ }
445
+ if (tool === 'npm') {
446
+ const subIdx = firstNonFlagArgIndex(parts);
447
+ if (parts[subIdx] === 'run' && parts[subIdx + 1]) {
448
+ return findMissingScript(context, cwd, parts, parts[subIdx + 1], NPM_BUILTINS, 'npm');
449
+ }
450
+ }
451
+ if (tool === 'yarn') {
452
+ const subIdx = firstNonFlagArgIndex(parts);
453
+ const sub = parts[subIdx];
454
+ if (!sub)
455
+ return null;
456
+ const scriptName = sub === 'run'
457
+ ? parts[subIdx + 1]
458
+ : sub === 'workspace'
459
+ ? parts[subIdx + 2]
460
+ : sub;
461
+ if (!scriptName)
462
+ return null;
463
+ return findMissingScript(context, cwd, parts, scriptName, YARN_BUILTINS, 'yarn');
464
+ }
465
+ // ── File-executing commands ────────────────────────────────────────────────
466
+ const FILE_EXECUTORS = ['node', 'tsx', 'ts-node', 'bash', 'sh', 'python', 'python3'];
467
+ if (baseDir && FILE_EXECUTORS.includes(tool) && parts[1]) {
468
+ // Skip flags (and known flags' values, e.g. `--loader ts-node/esm`) to
469
+ // find the actual script/file argument.
470
+ const filePart = parts[firstNonFlagArgIndex(parts)];
471
+ if (filePart && isLikelyFilePath(filePart) && !fileExists(baseDir, filePart)) {
472
+ return `File "${filePart}" referenced by "${tool}" does not appear to exist in the repository`;
473
+ }
474
+ }
475
+ // ── Direct script invocations: ./scripts/foo.sh ───────────────────────────
476
+ if (baseDir && (tool.startsWith('./') || tool.startsWith('../'))) {
477
+ if (!fileExists(baseDir, tool)) {
478
+ return `Script "${tool}" does not appear to exist in the repository`;
479
+ }
480
+ }
481
+ // ── docker compose -f <file> ───────────────────────────────────────────────
482
+ if (baseDir && tool === 'docker' && parts[1] === 'compose' && parts.includes('-f')) {
483
+ const fIdx = parts.indexOf('-f');
484
+ const composeFile = parts[fIdx + 1];
485
+ if (composeFile && isLikelyFilePath(composeFile) && !fileExists(baseDir, composeFile)) {
486
+ return `Docker Compose file "${composeFile}" does not appear to exist in the repository`;
487
+ }
488
+ }
489
+ // ── dotnet test <project-or-solution> ─────────────────────────────────────
490
+ if (baseDir && tool === 'dotnet' && parts[1] === 'test' && parts[2]) {
491
+ const target = parts[2];
492
+ if (isLikelyFilePath(target)) {
493
+ if (!fileExists(baseDir, target)) {
494
+ return `dotnet test target "${target}" does not appear to exist`;
495
+ }
496
+ if (!/\.(sln|csproj|fsproj)$/.test(target)) {
497
+ return `dotnet test target "${target}" should be a .sln, .csproj, or .fsproj file`;
498
+ }
499
+ }
500
+ }
501
+ return null;
502
+ }
503
+ // ── Public detector ───────────────────────────────────────────────────────────
504
+ /**
505
+ * Validates commands documented in instruction files against the repository's
506
+ * actual scripts and file structure.
507
+ *
508
+ * Returns findings only for high-confidence breakages — missing package
509
+ * scripts and missing file references. Executable binary availability is
510
+ * out of scope.
511
+ */
512
+ export function detectCommandValidity(context) {
513
+ const issues = [];
514
+ const reported = new Set();
515
+ for (const file of context.files) {
516
+ const commands = extractCommands(file.content);
517
+ for (const cmd of commands) {
518
+ const error = validateSegment(cmd.text, context, cmd.cwd ?? '.');
519
+ if (!error)
520
+ continue;
521
+ // Deduplicate same command text appearing twice in the same file
522
+ const dedupeKey = `${file.path}|${cmd.text}`;
523
+ if (reported.has(dedupeKey))
524
+ continue;
525
+ reported.add(dedupeKey);
526
+ issues.push({
527
+ id: issueId(file.path, cmd.text),
528
+ severity: 'warning',
529
+ category: 'command_validity',
530
+ title: `Possible reference to missing command or file: \`${cmd.text.split(/\s+/).slice(0, 3).join(' ')}\``,
531
+ summary: error,
532
+ filePaths: [file.path],
533
+ locations: [{ filePath: file.path, startLine: cmd.line, endLine: cmd.line }],
534
+ evidence: [`Command: \`${cmd.text}\``, `In file: ${file.path}`],
535
+ recommendation: 'Verify the command. If the script was renamed, update the instruction file. ' +
536
+ 'If it is an illustrative example, wrap it in a placeholder like <script-name> to suppress this finding.',
537
+ confidence: 0.8,
538
+ });
539
+ }
540
+ }
541
+ return issues;
542
+ }
543
+ //# sourceMappingURL=command-validity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-validity.js","sourceRoot":"","sources":["../src/command-validity.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * Conflict detector for PromptCI.
3
+ *
4
+ * Looks for contradictory directive pairs within or across instruction files:
5
+ * "use X" vs "do not use X"
6
+ * "always X" vs "never X"
7
+ * "must X" vs "avoid X"
8
+ * "prefer X" vs "avoid X"
9
+ *
10
+ * Only flags pairs where the extracted subject noun/phrase is the same or
11
+ * highly similar — unrelated sentences that happen to contain "use" and
12
+ * "avoid" on different topics are NOT flagged.
13
+ *
14
+ * Wording is intentionally cautious — all findings are heuristic.
15
+ */
16
+ import type { InstructionFile, PromptCiIssue } from './types.js';
17
+ /**
18
+ * Detect conflicting directives across all instruction files.
19
+ *
20
+ * Confidence:
21
+ * 0.8 — subjects are identical after normalisation
22
+ * 0.5 — subjects share significant word overlap (Jaccard ≥ 0.5)
23
+ *
24
+ * Severity:
25
+ * confidence ≥ 0.7 → "high"
26
+ * confidence < 0.7 → "warning"
27
+ */
28
+ export declare function detectConflicts(files: InstructionFile[]): PromptCiIssue[];
29
+ /**
30
+ * Detect when different instruction files specify conflicting major versions of
31
+ * the same framework or runtime (e.g. CLAUDE.md says ".NET 8", AGENTS.md says ".NET 6").
32
+ *
33
+ * Only fires when at least two files carry DIFFERENT positively-stated versions for
34
+ * the same framework — negation references ("not .NET 8") are excluded.
35
+ *
36
+ * Confidence 0.75 → severity "high".
37
+ */
38
+ export declare function detectVersionConflicts(files: InstructionFile[]): PromptCiIssue[];
39
+ /**
40
+ * Detect conflicts where different instruction files recommend mutually-exclusive
41
+ * technologies or conventions for the same dimension.
42
+ *
43
+ * Fires only when at least one mention is in a directive context (use/prefer/must/…)
44
+ * to avoid false-positives on casual mentions.
45
+ *
46
+ * Confidence: 0.6 (warning).
47
+ */
48
+ export declare function detectCompetingTechConflicts(files: InstructionFile[]): PromptCiIssue[];
49
+ //# sourceMappingURL=conflicts.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"conflicts.d.ts","sourceRoot":"","sources":["../src/conflicts.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;GAcG;AAIH,OAAO,KAAK,EAAE,eAAe,EAAsB,aAAa,EAAE,MAAM,YAAY,CAAC;AAqfrF;;;;;;;;;;GAUG;AACH,wBAAgB,eAAe,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CAoNzE;AAoPD;;;;;;;;GAQG;AACH,wBAAgB,sBAAsB,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CAgEhF;AAoGD;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,eAAe,EAAE,GAAG,aAAa,EAAE,CA2DtF"}