@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.
- package/LICENSE +201 -0
- package/README.md +30 -0
- package/dist/agent-practices.d.ts +22 -0
- package/dist/agent-practices.d.ts.map +1 -0
- package/dist/agent-practices.js +582 -0
- package/dist/agent-practices.js.map +1 -0
- package/dist/baseline.d.ts +40 -0
- package/dist/baseline.d.ts.map +1 -0
- package/dist/baseline.js +172 -0
- package/dist/baseline.js.map +1 -0
- package/dist/canonical-owner.d.ts +3 -0
- package/dist/canonical-owner.d.ts.map +1 -0
- package/dist/canonical-owner.js +131 -0
- package/dist/canonical-owner.js.map +1 -0
- package/dist/cheap-model-routing.d.ts +4 -0
- package/dist/cheap-model-routing.d.ts.map +1 -0
- package/dist/cheap-model-routing.js +43 -0
- package/dist/cheap-model-routing.js.map +1 -0
- package/dist/ci-alignment.d.ts +10 -0
- package/dist/ci-alignment.d.ts.map +1 -0
- package/dist/ci-alignment.js +343 -0
- package/dist/ci-alignment.js.map +1 -0
- package/dist/cli-output-filter.d.ts +16 -0
- package/dist/cli-output-filter.d.ts.map +1 -0
- package/dist/cli-output-filter.js +88 -0
- package/dist/cli-output-filter.js.map +1 -0
- package/dist/command-validity.d.ts +12 -0
- package/dist/command-validity.d.ts.map +1 -0
- package/dist/command-validity.js +543 -0
- package/dist/command-validity.js.map +1 -0
- package/dist/conflicts.d.ts +49 -0
- package/dist/conflicts.d.ts.map +1 -0
- package/dist/conflicts.js +1065 -0
- package/dist/conflicts.js.map +1 -0
- package/dist/context-analysis.d.ts +15 -0
- package/dist/context-analysis.d.ts.map +1 -0
- package/dist/context-analysis.js +24 -0
- package/dist/context-analysis.js.map +1 -0
- package/dist/context-bloat.d.ts +17 -0
- package/dist/context-bloat.d.ts.map +1 -0
- package/dist/context-bloat.js +148 -0
- package/dist/context-bloat.js.map +1 -0
- package/dist/context-cost.d.ts +4 -0
- package/dist/context-cost.d.ts.map +1 -0
- package/dist/context-cost.js +70 -0
- package/dist/context-cost.js.map +1 -0
- package/dist/context-optimizer.d.ts +14 -0
- package/dist/context-optimizer.d.ts.map +1 -0
- package/dist/context-optimizer.js +219 -0
- package/dist/context-optimizer.js.map +1 -0
- package/dist/context-recommender.d.ts +3 -0
- package/dist/context-recommender.d.ts.map +1 -0
- package/dist/context-recommender.js +329 -0
- package/dist/context-recommender.js.map +1 -0
- package/dist/dead-references.d.ts +33 -0
- package/dist/dead-references.d.ts.map +1 -0
- package/dist/dead-references.js +607 -0
- package/dist/dead-references.js.map +1 -0
- package/dist/detectors.d.ts +11 -0
- package/dist/detectors.d.ts.map +1 -0
- package/dist/detectors.js +160 -0
- package/dist/detectors.js.map +1 -0
- package/dist/duplicates.d.ts +36 -0
- package/dist/duplicates.d.ts.map +1 -0
- package/dist/duplicates.js +436 -0
- package/dist/duplicates.js.map +1 -0
- package/dist/fix-engine.d.ts +16 -0
- package/dist/fix-engine.d.ts.map +1 -0
- package/dist/fix-engine.js +179 -0
- package/dist/fix-engine.js.map +1 -0
- package/dist/framework-packs.d.ts +8 -0
- package/dist/framework-packs.d.ts.map +1 -0
- package/dist/framework-packs.js +22 -0
- package/dist/framework-packs.js.map +1 -0
- package/dist/frameworks/dotnet.d.ts +4 -0
- package/dist/frameworks/dotnet.d.ts.map +1 -0
- package/dist/frameworks/dotnet.js +77 -0
- package/dist/frameworks/dotnet.js.map +1 -0
- package/dist/frameworks/go.d.ts +4 -0
- package/dist/frameworks/go.d.ts.map +1 -0
- package/dist/frameworks/go.js +39 -0
- package/dist/frameworks/go.js.map +1 -0
- package/dist/frameworks/nextjs.d.ts +4 -0
- package/dist/frameworks/nextjs.d.ts.map +1 -0
- package/dist/frameworks/nextjs.js +66 -0
- package/dist/frameworks/nextjs.js.map +1 -0
- package/dist/frameworks/python.d.ts +4 -0
- package/dist/frameworks/python.d.ts.map +1 -0
- package/dist/frameworks/python.js +66 -0
- package/dist/frameworks/python.js.map +1 -0
- package/dist/frameworks/rust.d.ts +4 -0
- package/dist/frameworks/rust.d.ts.map +1 -0
- package/dist/frameworks/rust.js +72 -0
- package/dist/frameworks/rust.js.map +1 -0
- package/dist/frameworks/unity.d.ts +4 -0
- package/dist/frameworks/unity.d.ts.map +1 -0
- package/dist/frameworks/unity.js +74 -0
- package/dist/frameworks/unity.js.map +1 -0
- package/dist/health-score.d.ts +37 -0
- package/dist/health-score.d.ts.map +1 -0
- package/dist/health-score.js +164 -0
- package/dist/health-score.js.map +1 -0
- package/dist/index.d.ts +31 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +23 -0
- package/dist/index.js.map +1 -0
- package/dist/llm.d.ts +6 -0
- package/dist/llm.d.ts.map +1 -0
- package/dist/llm.js +67 -0
- package/dist/llm.js.map +1 -0
- package/dist/manifest-consistency.d.ts +37 -0
- package/dist/manifest-consistency.d.ts.map +1 -0
- package/dist/manifest-consistency.js +659 -0
- package/dist/manifest-consistency.js.map +1 -0
- package/dist/mcp-detector.d.ts +4 -0
- package/dist/mcp-detector.d.ts.map +1 -0
- package/dist/mcp-detector.js +131 -0
- package/dist/mcp-detector.js.map +1 -0
- package/dist/missing-context.d.ts +15 -0
- package/dist/missing-context.d.ts.map +1 -0
- package/dist/missing-context.js +517 -0
- package/dist/missing-context.js.map +1 -0
- package/dist/native-tool-preference.d.ts +20 -0
- package/dist/native-tool-preference.d.ts.map +1 -0
- package/dist/native-tool-preference.js +94 -0
- package/dist/native-tool-preference.js.map +1 -0
- package/dist/output-verbosity.d.ts +3 -0
- package/dist/output-verbosity.d.ts.map +1 -0
- package/dist/output-verbosity.js +83 -0
- package/dist/output-verbosity.js.map +1 -0
- package/dist/product-boundary.d.ts +11 -0
- package/dist/product-boundary.d.ts.map +1 -0
- package/dist/product-boundary.js +301 -0
- package/dist/product-boundary.js.map +1 -0
- package/dist/project-type.d.ts +15 -0
- package/dist/project-type.d.ts.map +1 -0
- package/dist/project-type.js +116 -0
- package/dist/project-type.js.map +1 -0
- package/dist/prompt-cache.d.ts +3 -0
- package/dist/prompt-cache.d.ts.map +1 -0
- package/dist/prompt-cache.js +151 -0
- package/dist/prompt-cache.js.map +1 -0
- package/dist/repo-context.d.ts +37 -0
- package/dist/repo-context.d.ts.map +1 -0
- package/dist/repo-context.js +221 -0
- package/dist/repo-context.js.map +1 -0
- package/dist/report.d.ts +87 -0
- package/dist/report.d.ts.map +1 -0
- package/dist/report.js +558 -0
- package/dist/report.js.map +1 -0
- package/dist/scan.d.ts +7 -0
- package/dist/scan.d.ts.map +1 -0
- package/dist/scan.js +43 -0
- package/dist/scan.js.map +1 -0
- package/dist/scanner.d.ts +3 -0
- package/dist/scanner.d.ts.map +1 -0
- package/dist/scanner.js +216 -0
- package/dist/scanner.js.map +1 -0
- package/dist/security-pack.d.ts +4 -0
- package/dist/security-pack.d.ts.map +1 -0
- package/dist/security-pack.js +403 -0
- package/dist/security-pack.js.map +1 -0
- package/dist/stale-instructions.d.ts +20 -0
- package/dist/stale-instructions.d.ts.map +1 -0
- package/dist/stale-instructions.js +269 -0
- package/dist/stale-instructions.js.map +1 -0
- package/dist/suppression.d.ts +64 -0
- package/dist/suppression.d.ts.map +1 -0
- package/dist/suppression.js +338 -0
- package/dist/suppression.js.map +1 -0
- package/dist/types.d.ts +128 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +3 -0
- package/dist/types.js.map +1 -0
- package/dist/vague-guidance.d.ts +12 -0
- package/dist/vague-guidance.d.ts.map +1 -0
- package/dist/vague-guidance.js +235 -0
- package/dist/vague-guidance.js.map +1 -0
- 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"}
|