@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,343 @@
1
+ import * as crypto from 'node:crypto';
2
+ /**
3
+ * CI and Workflow Alignment Detector
4
+ *
5
+ * Compares what GitHub Actions workflows actually run against what instruction
6
+ * files tell agents to run locally. Surfaces drift between the CI gate and
7
+ * the agent verification loop so agents know which steps must pass before
8
+ * declaring work complete.
9
+ *
10
+ * Findings are heuristic — wording is intentionally cautious.
11
+ */
12
+ function issueId(key) {
13
+ const hash = crypto.createHash('sha1').update(key).digest('hex').slice(0, 12);
14
+ return `ci-align-${hash}`;
15
+ }
16
+ /**
17
+ * Split a raw CI command that may contain multiple sub-commands joined with
18
+ * `&&` or newlines (multi-line `run:` blocks) into individual segments.
19
+ */
20
+ function splitCommand(command) {
21
+ return command
22
+ .split(/&&|\n/)
23
+ .map((s) => s.trim())
24
+ .filter(Boolean);
25
+ }
26
+ /**
27
+ * Normalizes a single command segment to identify a CommonTask.
28
+ * Returns the task name if recognised, otherwise null.
29
+ */
30
+ function identifyTaskInSegment(segment) {
31
+ const cmd = segment.toLowerCase();
32
+ // Package-manager run patterns: "pnpm run lint", "npm test", "yarn build", etc.
33
+ const pmRunMatch = /\b(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?(test|lint|build|typecheck|format)\b/.exec(cmd);
34
+ if (pmRunMatch)
35
+ return pmRunMatch[1];
36
+ // Direct tool invocations
37
+ if (/\bjest\b|\bvitest\b|\bmocha\b|\bplaywright\s+test\b/.test(cmd))
38
+ return 'test';
39
+ if (/\beslint\b|\bprettier\s+--check\b/.test(cmd))
40
+ return 'lint';
41
+ // CI1: `\b` immediately before `--noemit` can never match — `\b` requires a
42
+ // word-char/non-word-char transition, but "--noemit" is always preceded by
43
+ // whitespace (non-word char before a non-word `-`), so `/\b--noemit\b/`
44
+ // never matched real input like "tsc --noEmit". This made `tsc --noEmit`
45
+ // in CI ALWAYS classify as 'build', never 'typecheck'. No leading boundary
46
+ // is needed — "--noemit" is unambiguous on its own.
47
+ if (/\btsc\b/.test(cmd) && /--noemit\b/i.test(cmd))
48
+ return 'typecheck';
49
+ if (/\btsc\b/.test(cmd) && !/--noemit\b/i.test(cmd))
50
+ return 'build';
51
+ if (/\bprettier\s+--write\b/.test(cmd))
52
+ return 'format';
53
+ return null;
54
+ }
55
+ /**
56
+ * Returns all CommonTasks found in a (possibly multi-command) CI run: string.
57
+ * Handles `&&`-joined lines and multi-line blocks.
58
+ */
59
+ function identifyTasksInCommand(command) {
60
+ const tasks = [];
61
+ for (const segment of splitCommand(command)) {
62
+ const t = identifyTaskInSegment(segment);
63
+ if (t && !tasks.includes(t))
64
+ tasks.push(t);
65
+ }
66
+ return tasks;
67
+ }
68
+ // ── Instruction-file task matching ────────────────────────────────────────────
69
+ /**
70
+ * Patterns that indicate an instruction file is actively directing the agent
71
+ * to run a given task. We look for command-like contexts to avoid matching
72
+ * the word "test" in prose like "make sure to test your assumptions".
73
+ *
74
+ * For each task we accept:
75
+ * - An explicit package-manager command (`pnpm lint`, `npm run lint`, …)
76
+ * - A heading or list item that names the task (## Lint, - Run lint)
77
+ * - The word in a run/execute/check context
78
+ */
79
+ const TASK_INSTRUCTION_PATTERNS = {
80
+ lint: /\b(?:(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?lint|eslint\b|run\s+lint|lint\s+the\s+code|linting)\b/i,
81
+ typecheck: /\b(?:(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?typecheck|tsc\b|type.?check|run\s+typecheck)\b/i,
82
+ test: /\b(?:(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?test|vitest\b|jest\b|run\s+(?:the\s+)?tests?|pnpm\s+test)\b/i,
83
+ build: /\b(?:(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?build|tsc\b(?!\s+--noemit)|run\s+(?:the\s+)?build)\b/i,
84
+ format: /\b(?:(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?format|prettier\b|run\s+format)\b/i,
85
+ };
86
+ /**
87
+ * Returns true when any scanned instruction file directs the agent to run the
88
+ * given task in a command-like context (not just mentions the word in prose).
89
+ */
90
+ function isTaskInstructed(task, files) {
91
+ const pattern = TASK_INSTRUCTION_PATTERNS[task];
92
+ return files.some((f) => pattern.test(f.content));
93
+ }
94
+ // ── Package manager extraction ────────────────────────────────────────────────
95
+ /** Returns the package manager name used in a single command segment, or null. */
96
+ function extractPackageManager(command) {
97
+ const match = /\b(pnpm|npm|yarn|bun)\b/.exec(command.toLowerCase());
98
+ return match ? match[1] : null;
99
+ }
100
+ /** Collects all distinct package managers mentioned across all CI commands. */
101
+ function collectCiPackageManagers(commands) {
102
+ const pms = new Set();
103
+ for (const wc of commands) {
104
+ for (const segment of splitCommand(wc.command)) {
105
+ const pm = extractPackageManager(segment);
106
+ if (pm)
107
+ pms.add(pm);
108
+ }
109
+ }
110
+ return pms;
111
+ }
112
+ // ── Script normalisation ──────────────────────────────────────────────────────
113
+ /** Standard pm subcommands that are not user-defined package scripts. */
114
+ const STANDARD_SUBCOMMANDS = new Set([
115
+ 'install', 'i', 'add', 'remove', 'uninstall', 'init', 'help',
116
+ 'test', 'start', 'stop', 'restart', 'exec', 'dlx', 'run',
117
+ 'workspace', 'workspaces',
118
+ ]);
119
+ /**
120
+ * CI2: common English words that follow a package-manager name in ordinary
121
+ * PROSE, not a command invocation — "use pnpm instead of npm" and "npm
122
+ * packages are pinned" both matched the extraction regex below (which
123
+ * accepts ANY following alphanumeric word as a candidate script name),
124
+ * producing bogus orphan-script findings for "instead" and "packages".
125
+ * pnpm/yarn support a real bare `pnpm <script>` invocation (no "run"
126
+ * needed), so this can't be fixed by requiring "run" — only by excluding
127
+ * words that are clearly prose continuations, not script names.
128
+ */
129
+ const ENGLISH_FILLER_WORDS = new Set([
130
+ 'instead', 'of', 'packages', 'package', 'are', 'is', 'the', 'a', 'an',
131
+ 'that', 'this', 'for', 'to', 'and', 'or', 'not', 'with', 'without', 'via',
132
+ 'because', 'since', 'before', 'after', 'than', 'as', 'like', 'but', 'so',
133
+ ]);
134
+ /** Extracts a user-defined script name from a pm run command, or null. */
135
+ function extractScriptName(command) {
136
+ const match = /\b(?:pnpm|npm|yarn|bun)\s+(?:run\s+)?([a-z0-9][a-z0-9:_-]*)\b/i.exec(command);
137
+ if (!match)
138
+ return null;
139
+ const name = match[1].toLowerCase();
140
+ if (STANDARD_SUBCOMMANDS.has(name) || ENGLISH_FILLER_WORDS.has(name))
141
+ return null;
142
+ return name;
143
+ }
144
+ // ── Check 1: CI runs a task that instructions do not mention ──────────────────
145
+ /**
146
+ * Flags tasks that CI enforces (lint, typecheck, test, build) but that no
147
+ * instruction file directs the agent to run.
148
+ *
149
+ * Only emits findings when at least one workflow file exists.
150
+ */
151
+ function checkMissingCiTasks(context) {
152
+ const { workflows, files } = context;
153
+ if (workflows.files.length === 0)
154
+ return [];
155
+ // Collect tasks from ALL CI commands, handling && and multi-line blocks.
156
+ const ciTasks = new Map();
157
+ for (const wc of workflows.commands) {
158
+ for (const task of identifyTasksInCommand(wc.command)) {
159
+ if (!ciTasks.has(task))
160
+ ciTasks.set(task, []);
161
+ ciTasks.get(task).push(wc);
162
+ }
163
+ }
164
+ const issues = [];
165
+ for (const [task, wcs] of ciTasks.entries()) {
166
+ if (isTaskInstructed(task, files))
167
+ continue;
168
+ const sourceFiles = [...new Set(wcs.map((wc) => wc.filePath))];
169
+ issues.push({
170
+ id: issueId(`missing-ci-task:${task}`),
171
+ severity: 'warning',
172
+ category: 'missing_context',
173
+ title: `CI runs \`${task}\` but no instruction file appears to include it`,
174
+ summary: `The GitHub workflow${sourceFiles.length > 1 ? 's' : ''} (${sourceFiles.join(', ')}) ` +
175
+ `run \`${task}\`, but no instruction file appears to direct the agent to run this step ` +
176
+ `locally. Agents that follow only the instruction files may skip \`${task}\` and miss ` +
177
+ `failures before declaring work complete.`,
178
+ filePaths: files.map((f) => f.path),
179
+ locations: wcs.map((wc) => ({ filePath: wc.filePath, startLine: wc.line })),
180
+ evidence: wcs.map((wc) => `CI command: \`${wc.command}\` in ${wc.filePath} (line ${wc.line})`),
181
+ recommendation: `Consider adding \`${task}\` to the verification loop in the relevant instruction ` +
182
+ `file (e.g., AGENTS.md or CLAUDE.md) so agents run the same checks as CI.`,
183
+ confidence: 0.8,
184
+ });
185
+ }
186
+ return issues;
187
+ }
188
+ // ── Check 2: CI uses a different package manager than instructions ─────────────
189
+ /**
190
+ * Flags when instruction files direct the agent to use a different package
191
+ * manager than the one CI workflows actually use.
192
+ *
193
+ * Only emits findings when at least one workflow file exists and CI commands
194
+ * mention a package manager.
195
+ */
196
+ function checkCiPackageManagerMismatch(context) {
197
+ const { workflows, files, packageJson } = context;
198
+ if (workflows.files.length === 0)
199
+ return [];
200
+ const ciPms = collectCiPackageManagers(workflows.commands);
201
+ if (ciPms.size === 0)
202
+ return [];
203
+ // Determine the project's preferred PM: package.json field > lockfile > CI
204
+ const preferredPm = packageJson.packageManagerName !== 'unknown'
205
+ ? packageJson.packageManagerName
206
+ : Array.from(ciPms)[0];
207
+ if (!ciPms.has(preferredPm))
208
+ return [];
209
+ const issues = [];
210
+ for (const file of files) {
211
+ for (const pm of ['npm', 'pnpm', 'yarn', 'bun']) {
212
+ if (pm === preferredPm)
213
+ continue;
214
+ // Only match positive command usage (not negation lines)
215
+ const re = new RegExp(`\\b${pm}\\s+(?:install|add|run|exec|dlx|i)\\b`, 'gi');
216
+ let match;
217
+ let positiveHit = false;
218
+ while ((match = re.exec(file.content)) !== null) {
219
+ const lineStart = file.content.lastIndexOf('\n', match.index - 1) + 1;
220
+ const lineEnd = file.content.indexOf('\n', match.index);
221
+ const line = file.content.slice(lineStart, lineEnd === -1 ? undefined : lineEnd);
222
+ const isNegation = /\b(?:do\s+not|don'?t|avoid|never|not\s+use|refrain)\b/i.test(line);
223
+ if (!isNegation) {
224
+ positiveHit = true;
225
+ break;
226
+ }
227
+ }
228
+ if (!positiveHit)
229
+ continue;
230
+ issues.push({
231
+ id: issueId(`pm-mismatch-ci:${file.path}:${pm}`),
232
+ severity: 'warning',
233
+ category: 'conflict',
234
+ title: `Possible package manager mismatch: instructions use \`${pm}\` but CI uses \`${preferredPm}\``,
235
+ summary: `The instruction file appears to direct the agent to use \`${pm}\`, but the CI ` +
236
+ `workflows use \`${preferredPm}\`. This may lead to lockfile conflicts or unexpected ` +
237
+ `installation behaviour. Consider reviewing whether the instructions match the CI setup.`,
238
+ filePaths: [file.path],
239
+ locations: [{ filePath: file.path }],
240
+ evidence: [
241
+ `CI workflows use: ${Array.from(ciPms).join(', ')}`,
242
+ `Instruction file appears to use \`${pm}\``,
243
+ ],
244
+ recommendation: `Update the instruction file to use \`${preferredPm}\` commands to align with CI.`,
245
+ confidence: 0.85,
246
+ });
247
+ }
248
+ }
249
+ return issues;
250
+ }
251
+ // ── Check 3: Instructions reference a script absent from CI and manifest ────────
252
+ /**
253
+ * Flags when an instruction file tells the agent to run a named package script
254
+ * that appears in neither package.json nor any CI workflow. These commands
255
+ * would fail immediately if executed.
256
+ *
257
+ * Only applied when at least one workflow file exists (otherwise the CI-absent
258
+ * half of the signal is meaningless).
259
+ */
260
+ function checkOrphanedInstructionScripts(context) {
261
+ const { workflows, files, packageJson, manifests } = context;
262
+ if (workflows.files.length === 0)
263
+ return [];
264
+ // CI3: manifest-consistency.ts's checkMissingScripts already flags any
265
+ // instruction reference to a script missing from package.json — regardless
266
+ // of whether the script is used in CI — and it runs whenever
267
+ // manifests.packageJson is present. Every finding THIS check produces
268
+ // requires that same "missing from package.json" condition (see the
269
+ // `!packageScripts.has(scriptName)` check below), so whenever
270
+ // manifest-consistency.ts is active, its check is a strict superset of
271
+ // this one — the same underlying gap was reported TWICE (different ids,
272
+ // both 'stale_instruction') whenever a workflow file also existed. Defer
273
+ // entirely to manifest-consistency.ts in that case; this check only adds
274
+ // value when there's no package.json for that detector to compare against.
275
+ if (manifests.packageJson)
276
+ return [];
277
+ const packageScripts = new Set(Object.keys(packageJson.scripts));
278
+ // Collect all script names CI actually runs
279
+ const ciScriptNames = new Set();
280
+ for (const wc of workflows.commands) {
281
+ for (const segment of splitCommand(wc.command)) {
282
+ const name = extractScriptName(segment);
283
+ if (name)
284
+ ciScriptNames.add(name);
285
+ }
286
+ }
287
+ const reported = new Set();
288
+ const issues = [];
289
+ for (const file of files) {
290
+ const runRe = /\b(?:npm|pnpm|yarn|bun)\s+(?:run\s+)?([a-z0-9][a-z0-9:_-]*)\b/gi;
291
+ let match;
292
+ while ((match = runRe.exec(file.content)) !== null) {
293
+ const scriptName = match[1].toLowerCase();
294
+ // CI2: also exclude common English prose continuations — see
295
+ // ENGLISH_FILLER_WORDS for why this can't be fixed by requiring "run".
296
+ if (STANDARD_SUBCOMMANDS.has(scriptName) || ENGLISH_FILLER_WORDS.has(scriptName))
297
+ continue;
298
+ if (!packageScripts.has(scriptName) && !ciScriptNames.has(scriptName)) {
299
+ const dedupeKey = `${file.path}:${scriptName}`;
300
+ if (reported.has(dedupeKey))
301
+ continue;
302
+ reported.add(dedupeKey);
303
+ issues.push({
304
+ id: issueId(`orphan-script:${file.path}:${scriptName}`),
305
+ severity: 'warning',
306
+ category: 'stale_instruction',
307
+ title: `Possible reference to missing script: \`${scriptName}\` (not in CI or package.json)`,
308
+ summary: `The instruction file appears to tell the agent to run \`${scriptName}\`, but this ` +
309
+ `script does not appear in package.json and is not used in any CI workflow. ` +
310
+ `This command may fail if executed. Consider reviewing whether the script name is current.`,
311
+ filePaths: [file.path],
312
+ locations: [{ filePath: file.path }],
313
+ evidence: [
314
+ `Found reference to \`${scriptName}\` in ${file.path}`,
315
+ `Script not found in package.json scripts`,
316
+ `Script not found in .github/workflows/*.yml`,
317
+ ],
318
+ recommendation: `Verify the script name. If it was renamed, update the instruction file. ` +
319
+ `If it is a new script, add it to package.json.`,
320
+ confidence: 0.8,
321
+ });
322
+ }
323
+ }
324
+ }
325
+ return issues;
326
+ }
327
+ // ── Public detector ───────────────────────────────────────────────────────────
328
+ /**
329
+ * Entry point for the CI and Workflow Alignment detector.
330
+ *
331
+ * Returns an empty array when no workflow files exist so the detector never
332
+ * creates noise in repos without GitHub Actions.
333
+ */
334
+ export function detectCiAlignment(context) {
335
+ if (context.workflows.files.length === 0)
336
+ return [];
337
+ return [
338
+ ...checkMissingCiTasks(context),
339
+ ...checkCiPackageManagerMismatch(context),
340
+ ...checkOrphanedInstructionScripts(context),
341
+ ];
342
+ }
343
+ //# sourceMappingURL=ci-alignment.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ci-alignment.js","sourceRoot":"","sources":["../src/ci-alignment.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ /**
2
+ * CLI output filter detector for PromptCI.
3
+ *
4
+ * Checks whether instruction files include guidance on filtering verbose CLI
5
+ * output before it reaches the LLM context. Tools like RTK (Rust Token Killer)
6
+ * transparently proxy commands such as `npm test`, `git diff`, and `cargo test`,
7
+ * stripping boilerplate and keeping only signal — typically 60-90% token reduction
8
+ * on those commands.
9
+ *
10
+ * Only fires for non-trivial projects (>500 estimated instruction tokens) that
11
+ * have no existing output-filter guidance in any instruction file.
12
+ */
13
+ import type { RepoContext } from './repo-context.js';
14
+ import type { PromptCiIssue } from './types.js';
15
+ export declare function detectCliOutputFilter(context: RepoContext): PromptCiIssue[];
16
+ //# sourceMappingURL=cli-output-filter.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-output-filter.d.ts","sourceRoot":"","sources":["../src/cli-output-filter.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA0BhD,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CA6D3E"}
@@ -0,0 +1,88 @@
1
+ /**
2
+ * CLI output filter detector for PromptCI.
3
+ *
4
+ * Checks whether instruction files include guidance on filtering verbose CLI
5
+ * output before it reaches the LLM context. Tools like RTK (Rust Token Killer)
6
+ * transparently proxy commands such as `npm test`, `git diff`, and `cargo test`,
7
+ * stripping boilerplate and keeping only signal — typically 60-90% token reduction
8
+ * on those commands.
9
+ *
10
+ * Only fires for non-trivial projects (>500 estimated instruction tokens) that
11
+ * have no existing output-filter guidance in any instruction file.
12
+ */
13
+ // Signals that output-filter guidance already exists somewhere in the instructions.
14
+ const FILTER_SIGNALS = [
15
+ /\brtk\b/i,
16
+ /rust\s+token\s+killer/i,
17
+ /output\s+filter/i,
18
+ /token[- ]optimized\s+(cli|command|output)/i,
19
+ /cli\s+proxy/i,
20
+ /filter.*command.*output/i,
21
+ /compact.*output/i,
22
+ /--failures[- ]only/i,
23
+ ];
24
+ // Commands that produce high-token output and benefit most from filtering.
25
+ // Used only to improve the evidence message — not a gate condition.
26
+ const NOISY_COMMANDS = [
27
+ 'npm test', 'npm run test', 'yarn test', 'pnpm test',
28
+ 'jest', 'vitest', 'pytest', 'cargo test', 'go test', 'rspec',
29
+ 'git diff', 'git log', 'git status',
30
+ 'next build', 'npm run build', 'tsc',
31
+ 'eslint', 'ruff check', 'cargo clippy', 'golangci-lint',
32
+ 'docker logs', 'kubectl logs',
33
+ 'gh pr list', 'gh run list',
34
+ ];
35
+ export function detectCliOutputFilter(context) {
36
+ const { files, metrics } = context;
37
+ if (files.length === 0)
38
+ return [];
39
+ // Skip trivially small instruction sets — not worth the noise.
40
+ if (metrics.estimatedInstructionTokens < 500)
41
+ return [];
42
+ const combinedContent = files.map((f) => f.content).join('\n');
43
+ const hasFilterGuidance = FILTER_SIGNALS.some((pat) => pat.test(combinedContent));
44
+ if (hasFilterGuidance)
45
+ return [];
46
+ // Surface whichever noisy commands are referenced in instructions (for evidence).
47
+ const referencedNoisyCommands = NOISY_COMMANDS.filter((cmd) => combinedContent.toLowerCase().includes(cmd.toLowerCase()));
48
+ const evidenceLine = referencedNoisyCommands.length > 0
49
+ ? `Noisy commands referenced in instructions: ${referencedNoisyCommands.slice(0, 5).join(', ')}${referencedNoisyCommands.length > 5 ? ` (+${referencedNoisyCommands.length - 5} more)` : ''}.`
50
+ : 'No output-filter signals found across all instruction files.';
51
+ return [
52
+ {
53
+ id: 'cli-output-filter-missing',
54
+ severity: 'info',
55
+ category: 'agent_practices',
56
+ title: 'No CLI output filtering guidance',
57
+ summary: 'Instruction files contain no guidance on filtering verbose CLI output before it reaches ' +
58
+ 'the LLM context. Commands like `npm test`, `git diff`, and `cargo test` can produce ' +
59
+ 'hundreds of boilerplate lines. A CLI proxy such as RTK (Rust Token Killer) intercepts ' +
60
+ 'these transparently and reduces token consumption by 60-90% on affected commands.',
61
+ filePaths: files.map((f) => f.path),
62
+ locations: [],
63
+ evidence: [evidenceLine],
64
+ recommendation: 'Install a CLI output filter (e.g. RTK: github.com/rtk-ai/rtk) and document it in your ' +
65
+ 'instruction files. For Claude Code, `rtk init -g` installs a PreToolUse hook that ' +
66
+ 'transparently rewrites Bash commands — no per-command changes needed.',
67
+ fixRecipe: [
68
+ '## CLI Output Filtering',
69
+ '',
70
+ 'Use [RTK](https://github.com/rtk-ai/rtk) to reduce token consumption from verbose commands:',
71
+ '',
72
+ '```bash',
73
+ 'brew install rtk # macOS',
74
+ '# or: cargo install --git https://github.com/rtk-ai/rtk',
75
+ 'rtk init -g # Claude Code (PreToolUse hook)',
76
+ 'rtk init -g --codex # Codex (AGENTS.md)',
77
+ 'rtk init --agent antigravity # Antigravity (project-scoped rules)',
78
+ '```',
79
+ '',
80
+ 'The hook transparently rewrites `npm test` → `rtk npm test` (failures only),',
81
+ '`git diff` → `rtk git diff` (condensed), etc. Run `rtk gain` to see token savings.',
82
+ ].join('\n'),
83
+ confidence: 0.75,
84
+ impact: 'medium',
85
+ },
86
+ ];
87
+ }
88
+ //# sourceMappingURL=cli-output-filter.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"cli-output-filter.js","sourceRoot":"","sources":["../src/cli-output-filter.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,12 @@
1
+ import type { RepoContext } from './repo-context.js';
2
+ import type { PromptCiIssue } from './types.js';
3
+ /**
4
+ * Validates commands documented in instruction files against the repository's
5
+ * actual scripts and file structure.
6
+ *
7
+ * Returns findings only for high-confidence breakages — missing package
8
+ * scripts and missing file references. Executable binary availability is
9
+ * out of scope.
10
+ */
11
+ export declare function detectCommandValidity(context: RepoContext): PromptCiIssue[];
12
+ //# sourceMappingURL=command-validity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"command-validity.d.ts","sourceRoot":"","sources":["../src/command-validity.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AA4hBhD;;;;;;;GAOG;AACH,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAkC3E"}