@promptci/core 0.0.1 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +201 -201
- package/README.md +29 -30
- package/dist/action-pinning.d.ts +37 -0
- package/dist/action-pinning.d.ts.map +1 -0
- package/dist/action-pinning.js +277 -0
- package/dist/action-pinning.js.map +1 -0
- package/dist/agent-practices.d.ts +3 -1
- package/dist/agent-practices.d.ts.map +1 -1
- package/dist/agent-practices.js +198 -94
- package/dist/agent-practices.js.map +1 -1
- package/dist/ai-config.d.ts +178 -0
- package/dist/ai-config.d.ts.map +1 -0
- package/dist/ai-config.js +721 -0
- package/dist/ai-config.js.map +1 -0
- package/dist/alias-files.d.ts +33 -0
- package/dist/alias-files.d.ts.map +1 -0
- package/dist/alias-files.js +60 -0
- package/dist/alias-files.js.map +1 -0
- package/dist/baseline.d.ts +17 -1
- package/dist/baseline.d.ts.map +1 -1
- package/dist/baseline.js +5 -1
- package/dist/baseline.js.map +1 -1
- package/dist/buried-critical.d.ts +17 -0
- package/dist/buried-critical.d.ts.map +1 -0
- package/dist/buried-critical.js +107 -0
- package/dist/buried-critical.js.map +1 -0
- package/dist/canonical-owner.d.ts.map +1 -1
- package/dist/canonical-owner.js +60 -30
- package/dist/canonical-owner.js.map +1 -1
- package/dist/ci-alignment.d.ts.map +1 -1
- package/dist/ci-alignment.js +3 -2
- package/dist/ci-alignment.js.map +1 -1
- package/dist/command-validity.d.ts +16 -0
- package/dist/command-validity.d.ts.map +1 -1
- package/dist/command-validity.js +387 -134
- package/dist/command-validity.js.map +1 -1
- package/dist/conflicts.d.ts.map +1 -1
- package/dist/conflicts.js +4 -44
- package/dist/conflicts.js.map +1 -1
- package/dist/context-analysis.d.ts.map +1 -1
- package/dist/context-analysis.js +13 -2
- package/dist/context-analysis.js.map +1 -1
- package/dist/context-bloat.d.ts +20 -1
- package/dist/context-bloat.d.ts.map +1 -1
- package/dist/context-bloat.js +99 -15
- package/dist/context-bloat.js.map +1 -1
- package/dist/context-optimizer.d.ts.map +1 -1
- package/dist/context-optimizer.js +18 -54
- package/dist/context-optimizer.js.map +1 -1
- package/dist/copilot-instructions-detector.d.ts +24 -0
- package/dist/copilot-instructions-detector.d.ts.map +1 -0
- package/dist/copilot-instructions-detector.js +145 -0
- package/dist/copilot-instructions-detector.js.map +1 -0
- package/dist/cursor-rules-detector.d.ts +17 -0
- package/dist/cursor-rules-detector.d.ts.map +1 -0
- package/dist/cursor-rules-detector.js +110 -0
- package/dist/cursor-rules-detector.js.map +1 -0
- package/dist/custom-rules.d.ts +52 -0
- package/dist/custom-rules.d.ts.map +1 -0
- package/dist/custom-rules.js +303 -0
- package/dist/custom-rules.js.map +1 -0
- package/dist/dead-references.d.ts +8 -2
- package/dist/dead-references.d.ts.map +1 -1
- package/dist/dead-references.js +315 -68
- package/dist/dead-references.js.map +1 -1
- package/dist/dependency-staleness.d.ts +35 -0
- package/dist/dependency-staleness.d.ts.map +1 -0
- package/dist/dependency-staleness.js +1001 -0
- package/dist/dependency-staleness.js.map +1 -0
- package/dist/detectors.d.ts +1 -3
- package/dist/detectors.d.ts.map +1 -1
- package/dist/detectors.js +74 -56
- package/dist/detectors.js.map +1 -1
- package/dist/duplicates.d.ts.map +1 -1
- package/dist/duplicates.js +15 -9
- package/dist/duplicates.js.map +1 -1
- package/dist/evidence.d.ts +39 -0
- package/dist/evidence.d.ts.map +1 -0
- package/dist/evidence.js +78 -0
- package/dist/evidence.js.map +1 -0
- package/dist/finding-id.d.ts +21 -0
- package/dist/finding-id.d.ts.map +1 -0
- package/dist/finding-id.js +31 -0
- package/dist/finding-id.js.map +1 -0
- package/dist/fix-engine.d.ts +11 -0
- package/dist/fix-engine.d.ts.map +1 -1
- package/dist/fix-engine.js +88 -71
- package/dist/fix-engine.js.map +1 -1
- package/dist/frameworks/dotnet.js +2 -2
- package/dist/frameworks/dotnet.js.map +1 -1
- package/dist/frameworks/python.d.ts.map +1 -1
- package/dist/frameworks/python.js +5 -2
- package/dist/frameworks/python.js.map +1 -1
- package/dist/frameworks/rust.d.ts.map +1 -1
- package/dist/frameworks/rust.js +2 -1
- package/dist/frameworks/rust.js.map +1 -1
- package/dist/git-symlinks.d.ts +30 -0
- package/dist/git-symlinks.d.ts.map +1 -0
- package/dist/git-symlinks.js +161 -0
- package/dist/git-symlinks.js.map +1 -0
- package/dist/gitignore.d.ts +22 -0
- package/dist/gitignore.d.ts.map +1 -0
- package/dist/gitignore.js +157 -0
- package/dist/gitignore.js.map +1 -0
- package/dist/health-score.d.ts.map +1 -1
- package/dist/health-score.js +35 -5
- package/dist/health-score.js.map +1 -1
- package/dist/hooks-settings-detector.d.ts +17 -0
- package/dist/hooks-settings-detector.d.ts.map +1 -0
- package/dist/hooks-settings-detector.js +228 -0
- package/dist/hooks-settings-detector.js.map +1 -0
- package/dist/index.d.ts +29 -8
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +21 -6
- package/dist/index.js.map +1 -1
- package/dist/makefile.d.ts +37 -0
- package/dist/makefile.d.ts.map +1 -0
- package/dist/makefile.js +156 -0
- package/dist/makefile.js.map +1 -0
- package/dist/manifest-consistency.d.ts +6 -0
- package/dist/manifest-consistency.d.ts.map +1 -1
- package/dist/manifest-consistency.js +75 -10
- package/dist/manifest-consistency.js.map +1 -1
- package/dist/markdown-fences.d.ts +112 -0
- package/dist/markdown-fences.d.ts.map +1 -0
- package/dist/markdown-fences.js +174 -0
- package/dist/markdown-fences.js.map +1 -0
- package/dist/mcp-config-detector.d.ts +20 -0
- package/dist/mcp-config-detector.d.ts.map +1 -0
- package/dist/mcp-config-detector.js +237 -0
- package/dist/mcp-config-detector.js.map +1 -0
- package/dist/missing-context.d.ts.map +1 -1
- package/dist/missing-context.js +2 -52
- package/dist/missing-context.js.map +1 -1
- package/dist/model-budgets.d.ts +69 -0
- package/dist/model-budgets.d.ts.map +1 -0
- package/dist/model-budgets.js +110 -0
- package/dist/model-budgets.js.map +1 -0
- package/dist/negative-instructions.d.ts +26 -0
- package/dist/negative-instructions.d.ts.map +1 -0
- package/dist/negative-instructions.js +169 -0
- package/dist/negative-instructions.js.map +1 -0
- package/dist/path-containment.d.ts +41 -0
- package/dist/path-containment.d.ts.map +1 -0
- package/dist/path-containment.js +123 -0
- package/dist/path-containment.js.map +1 -0
- package/dist/project-type.d.ts +12 -2
- package/dist/project-type.d.ts.map +1 -1
- package/dist/project-type.js +25 -12
- package/dist/project-type.js.map +1 -1
- package/dist/prompt-cache.d.ts.map +1 -1
- package/dist/prompt-cache.js +33 -24
- package/dist/prompt-cache.js.map +1 -1
- package/dist/promptci-gitignore.d.ts +34 -0
- package/dist/promptci-gitignore.d.ts.map +1 -0
- package/dist/promptci-gitignore.js +42 -0
- package/dist/promptci-gitignore.js.map +1 -0
- package/dist/repo-context.d.ts +80 -0
- package/dist/repo-context.d.ts.map +1 -1
- package/dist/repo-context.js +170 -16
- package/dist/repo-context.js.map +1 -1
- package/dist/report.d.ts +8 -0
- package/dist/report.d.ts.map +1 -1
- package/dist/report.js +163 -63
- package/dist/report.js.map +1 -1
- package/dist/scan.d.ts.map +1 -1
- package/dist/scan.js +47 -4
- package/dist/scan.js.map +1 -1
- package/dist/scanner.d.ts +61 -1
- package/dist/scanner.d.ts.map +1 -1
- package/dist/scanner.js +367 -70
- package/dist/scanner.js.map +1 -1
- package/dist/security-pack.d.ts +20 -0
- package/dist/security-pack.d.ts.map +1 -1
- package/dist/security-pack.js +33 -14
- package/dist/security-pack.js.map +1 -1
- package/dist/skill-supply-chain.d.ts +132 -0
- package/dist/skill-supply-chain.d.ts.map +1 -0
- package/dist/skill-supply-chain.js +2954 -0
- package/dist/skill-supply-chain.js.map +1 -0
- package/dist/skills-detector.d.ts +23 -0
- package/dist/skills-detector.d.ts.map +1 -0
- package/dist/skills-detector.js +279 -0
- package/dist/skills-detector.js.map +1 -0
- package/dist/stale-instructions.d.ts +4 -1
- package/dist/stale-instructions.d.ts.map +1 -1
- package/dist/stale-instructions.js +53 -55
- package/dist/stale-instructions.js.map +1 -1
- package/dist/subagents-detector.d.ts +19 -0
- package/dist/subagents-detector.d.ts.map +1 -0
- package/dist/subagents-detector.js +155 -0
- package/dist/subagents-detector.js.map +1 -0
- package/dist/suppression.d.ts +2 -0
- package/dist/suppression.d.ts.map +1 -1
- package/dist/suppression.js +16 -47
- package/dist/suppression.js.map +1 -1
- package/dist/types.d.ts +62 -4
- package/dist/types.d.ts.map +1 -1
- package/dist/types.js +47 -1
- package/dist/types.js.map +1 -1
- package/dist/vague-guidance.d.ts +15 -2
- package/dist/vague-guidance.d.ts.map +1 -1
- package/dist/vague-guidance.js +44 -41
- package/dist/vague-guidance.js.map +1 -1
- package/dist/windsurf-detector.d.ts +22 -0
- package/dist/windsurf-detector.d.ts.map +1 -0
- package/dist/windsurf-detector.js +96 -0
- package/dist/windsurf-detector.js.map +1 -0
- package/dist/within-section-dedup.d.ts +16 -0
- package/dist/within-section-dedup.d.ts.map +1 -0
- package/dist/within-section-dedup.js +148 -0
- package/dist/within-section-dedup.js.map +1 -0
- package/dist/workspace-manifests.d.ts +80 -0
- package/dist/workspace-manifests.d.ts.map +1 -0
- package/dist/workspace-manifests.js +333 -0
- package/dist/workspace-manifests.js.map +1 -0
- package/package.json +11 -8
- package/dist/cheap-model-routing.d.ts +0 -4
- package/dist/cheap-model-routing.d.ts.map +0 -1
- package/dist/cheap-model-routing.js +0 -43
- package/dist/cheap-model-routing.js.map +0 -1
- package/dist/cli-output-filter.d.ts +0 -16
- package/dist/cli-output-filter.d.ts.map +0 -1
- package/dist/cli-output-filter.js +0 -88
- package/dist/cli-output-filter.js.map +0 -1
- package/dist/context-cost.d.ts +0 -4
- package/dist/context-cost.d.ts.map +0 -1
- package/dist/context-cost.js +0 -70
- package/dist/context-cost.js.map +0 -1
- package/dist/context-recommender.d.ts +0 -3
- package/dist/context-recommender.d.ts.map +0 -1
- package/dist/context-recommender.js +0 -329
- package/dist/context-recommender.js.map +0 -1
- package/dist/llm.d.ts +0 -6
- package/dist/llm.d.ts.map +0 -1
- package/dist/llm.js +0 -67
- package/dist/llm.js.map +0 -1
- package/dist/mcp-detector.d.ts +0 -4
- package/dist/mcp-detector.d.ts.map +0 -1
- package/dist/mcp-detector.js +0 -131
- package/dist/mcp-detector.js.map +0 -1
- package/dist/native-tool-preference.d.ts +0 -20
- package/dist/native-tool-preference.d.ts.map +0 -1
- package/dist/native-tool-preference.js +0 -94
- package/dist/native-tool-preference.js.map +0 -1
- package/dist/output-verbosity.d.ts +0 -3
- package/dist/output-verbosity.d.ts.map +0 -1
- package/dist/output-verbosity.js +0 -83
- package/dist/output-verbosity.js.map +0 -1
- package/dist/product-boundary.d.ts +0 -11
- package/dist/product-boundary.d.ts.map +0 -1
- package/dist/product-boundary.js +0 -301
- package/dist/product-boundary.js.map +0 -1
|
@@ -0,0 +1,148 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Within-section semantic dedup detector (FEAT-013).
|
|
3
|
+
*
|
|
4
|
+
* The cross-file `detectDuplicates` detector works at section granularity and
|
|
5
|
+
* misses a single section that restates the same point several ways. This
|
|
6
|
+
* detector looks *inside* a section: for sections with more than five
|
|
7
|
+
* paragraphs, it computes pairwise Jaccard similarity on the paragraphs and
|
|
8
|
+
* flags any pair that is ≥ 0.65 similar, naming the paragraph numbers.
|
|
9
|
+
*
|
|
10
|
+
* Info severity only — near-duplicate prose within one section is worth a
|
|
11
|
+
* gentle nudge, not a hard failure. Deterministic: no clock, network, or
|
|
12
|
+
* randomness.
|
|
13
|
+
*/
|
|
14
|
+
import * as crypto from 'node:crypto';
|
|
15
|
+
import { INSTRUCTION_FILE_TYPES } from './types.js';
|
|
16
|
+
import { snippet } from './evidence.js';
|
|
17
|
+
import { fileIdPath } from './finding-id.js';
|
|
18
|
+
/** Persistent, always-loaded instruction files this detector applies to. */
|
|
19
|
+
const TARGET_FILE_TYPES = INSTRUCTION_FILE_TYPES;
|
|
20
|
+
const MIN_PARAGRAPHS = 6; // "> 5 paragraphs"
|
|
21
|
+
const PARAGRAPH_JACCARD_THRESHOLD = 0.65;
|
|
22
|
+
const MIN_PARAGRAPH_CHARS = 40; // normalised; shorter paragraphs are too noisy
|
|
23
|
+
const MIN_PARAGRAPH_TOKENS = 8;
|
|
24
|
+
/** Normalise paragraph text for comparison: lowercase, strip markdown, collapse ws. */
|
|
25
|
+
function normalize(text) {
|
|
26
|
+
return text
|
|
27
|
+
.toLowerCase()
|
|
28
|
+
.replace(/^#{1,6}\s+/gm, '')
|
|
29
|
+
.replace(/^[\s]*[-*+]\s+/gm, '')
|
|
30
|
+
.replace(/^[\s]*\d+[.)]\s+/gm, '')
|
|
31
|
+
.replace(/\s+/g, ' ')
|
|
32
|
+
.trim();
|
|
33
|
+
}
|
|
34
|
+
function tokenize(text) {
|
|
35
|
+
return new Set(text.match(/\b\w+\b/g) ?? []);
|
|
36
|
+
}
|
|
37
|
+
function jaccard(a, b) {
|
|
38
|
+
if (a.size === 0 || b.size === 0)
|
|
39
|
+
return 0;
|
|
40
|
+
let intersection = 0;
|
|
41
|
+
for (const t of a)
|
|
42
|
+
if (b.has(t))
|
|
43
|
+
intersection++;
|
|
44
|
+
return intersection / (a.size + b.size - intersection);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* Split a section into paragraphs (blank-line separated), tracking each
|
|
48
|
+
* paragraph's 1-based number and its start line within the file. Code-fence
|
|
49
|
+
* paragraphs are skipped entirely — a repeated code block is the concern of the
|
|
50
|
+
* duplicate-section detector, not prose dedup.
|
|
51
|
+
*/
|
|
52
|
+
function splitParagraphs(section) {
|
|
53
|
+
const lines = section.text.split('\n');
|
|
54
|
+
const paragraphs = [];
|
|
55
|
+
let current = [];
|
|
56
|
+
let currentStart = section.startLine;
|
|
57
|
+
let paragraphNumber = 0;
|
|
58
|
+
const flush = () => {
|
|
59
|
+
if (current.length === 0)
|
|
60
|
+
return;
|
|
61
|
+
paragraphNumber++;
|
|
62
|
+
const text = current.join('\n');
|
|
63
|
+
if (!text.includes('```') && !text.includes('~~~')) {
|
|
64
|
+
const norm = normalize(text);
|
|
65
|
+
const tokens = tokenize(norm);
|
|
66
|
+
if (norm.length >= MIN_PARAGRAPH_CHARS && tokens.size >= MIN_PARAGRAPH_TOKENS) {
|
|
67
|
+
paragraphs.push({ number: paragraphNumber, text, startLine: currentStart, tokens });
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
current = [];
|
|
71
|
+
};
|
|
72
|
+
for (let i = 0; i < lines.length; i++) {
|
|
73
|
+
const line = lines[i] ?? '';
|
|
74
|
+
if (line.trim() === '') {
|
|
75
|
+
flush();
|
|
76
|
+
}
|
|
77
|
+
else {
|
|
78
|
+
if (current.length === 0)
|
|
79
|
+
currentStart = section.startLine + i;
|
|
80
|
+
current.push(line);
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
flush();
|
|
84
|
+
return paragraphs;
|
|
85
|
+
}
|
|
86
|
+
function issueId(filePath, startLine) {
|
|
87
|
+
const hash = crypto
|
|
88
|
+
.createHash('sha1')
|
|
89
|
+
.update(`within-section-dup:${filePath}:${startLine}`)
|
|
90
|
+
.digest('hex')
|
|
91
|
+
.slice(0, 12);
|
|
92
|
+
return `within-section-dup-${hash}`;
|
|
93
|
+
}
|
|
94
|
+
export function detectWithinSectionDedup(files) {
|
|
95
|
+
const issues = [];
|
|
96
|
+
for (const file of files) {
|
|
97
|
+
if (!TARGET_FILE_TYPES.has(file.fileType))
|
|
98
|
+
continue;
|
|
99
|
+
for (const section of file.sections) {
|
|
100
|
+
const paragraphs = splitParagraphs(section);
|
|
101
|
+
// "> 5 paragraphs" is measured against the qualifying (comparable)
|
|
102
|
+
// paragraphs — trivial one-liners never counted toward the section total.
|
|
103
|
+
if (paragraphs.length < MIN_PARAGRAPHS)
|
|
104
|
+
continue;
|
|
105
|
+
// Find the single strongest similar pair (and how many pairs cross the bar).
|
|
106
|
+
let best = null;
|
|
107
|
+
let pairCount = 0;
|
|
108
|
+
for (let i = 0; i < paragraphs.length; i++) {
|
|
109
|
+
for (let j = i + 1; j < paragraphs.length; j++) {
|
|
110
|
+
const sim = jaccard(paragraphs[i].tokens, paragraphs[j].tokens);
|
|
111
|
+
if (sim >= PARAGRAPH_JACCARD_THRESHOLD) {
|
|
112
|
+
pairCount++;
|
|
113
|
+
if (!best || sim > best.sim)
|
|
114
|
+
best = { a: paragraphs[i], b: paragraphs[j], sim };
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (!best)
|
|
119
|
+
continue;
|
|
120
|
+
const heading = section.heading ?? '(untitled section)';
|
|
121
|
+
const pct = Math.round(best.sim * 100);
|
|
122
|
+
const morePairs = pairCount > 1 ? ` (${pairCount} similar pairs in total)` : '';
|
|
123
|
+
issues.push({
|
|
124
|
+
id: issueId(fileIdPath(file), section.startLine),
|
|
125
|
+
severity: 'info',
|
|
126
|
+
category: 'duplicate',
|
|
127
|
+
title: `Possible repetition within section: ${heading}`,
|
|
128
|
+
summary: `Within "${heading}", paragraphs ${best.a.number} and ${best.b.number} are about ` +
|
|
129
|
+
`${pct}% similar${morePairs}. The section may be restating the same point several ` +
|
|
130
|
+
`ways — consider consolidating.`,
|
|
131
|
+
filePaths: [file.path],
|
|
132
|
+
locations: [
|
|
133
|
+
{ filePath: file.path, startLine: best.a.startLine, endLine: best.a.startLine },
|
|
134
|
+
{ filePath: file.path, startLine: best.b.startLine, endLine: best.b.startLine },
|
|
135
|
+
],
|
|
136
|
+
evidence: [
|
|
137
|
+
`Paragraph ${best.a.number}: "${snippet(best.a.text, 120)}"`,
|
|
138
|
+
`Paragraph ${best.b.number}: "${snippet(best.b.text, 120)}"`,
|
|
139
|
+
],
|
|
140
|
+
recommendation: 'Merge the near-duplicate paragraphs into one clear statement. If both are ' +
|
|
141
|
+
'intentional (e.g. a summary and a detailed version), make the distinction explicit.',
|
|
142
|
+
confidence: 0.5,
|
|
143
|
+
});
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return issues;
|
|
147
|
+
}
|
|
148
|
+
//# sourceMappingURL=within-section-dedup.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"within-section-dedup.js","sourceRoot":"","sources":["../src/within-section-dedup.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace package.json facts shared by the script-validity checks
|
|
3
|
+
* (command-validity and manifest-consistency).
|
|
4
|
+
*
|
|
5
|
+
* A package-manager command is only a "missing script" when nothing the repo
|
|
6
|
+
* can run under that name exists. Two kinds of names are never scripts and must
|
|
7
|
+
* not be reported as missing:
|
|
8
|
+
*
|
|
9
|
+
* - Dependencies and their binaries: `pnpm vitest run` and `yarn tsc --noEmit`
|
|
10
|
+
* fall through to the installed binary when no script of that name exists.
|
|
11
|
+
* - Scripts defined by a workspace package rather than the root manifest:
|
|
12
|
+
* `pnpm --filter web dev` or `pnpm -r build` in a monorepo.
|
|
13
|
+
*
|
|
14
|
+
* `node_modules/.bin` is not available when scanning a checkout, so a binary is
|
|
15
|
+
* accepted only when a package that provides it is declared in some workspace
|
|
16
|
+
* manifest (or, for a dependency whose name IS the command, the dependency
|
|
17
|
+
* itself). Everything here is deterministic and offline.
|
|
18
|
+
*/
|
|
19
|
+
import type { RepoContext } from './repo-context.js';
|
|
20
|
+
export type WorkspaceManifest = {
|
|
21
|
+
/** Repo-relative POSIX directory of the package ('.' = repo root). */
|
|
22
|
+
dir: string;
|
|
23
|
+
name?: string;
|
|
24
|
+
scripts: Record<string, string>;
|
|
25
|
+
/**
|
|
26
|
+
* Names from dependencies, devDependencies, peerDependencies and
|
|
27
|
+
* optionalDependencies, minus `workspace:` links to sibling packages (those
|
|
28
|
+
* are packages of this repo, not installed tools).
|
|
29
|
+
*/
|
|
30
|
+
dependencies: string[];
|
|
31
|
+
/**
|
|
32
|
+
* Version spec per dependency named in `dependencies` (first block wins:
|
|
33
|
+
* dependencies, devDependencies, peerDependencies, optionalDependencies).
|
|
34
|
+
* Optional so hand-built manifests keep type-checking.
|
|
35
|
+
*/
|
|
36
|
+
versions?: Record<string, string>;
|
|
37
|
+
/** Binary names the package itself exposes (`bin`). */
|
|
38
|
+
bins: string[];
|
|
39
|
+
};
|
|
40
|
+
export type WorkspaceDiscovery = {
|
|
41
|
+
manifests: WorkspaceManifest[];
|
|
42
|
+
/** More manifests matched than were read: the list is a sample, not the whole workspace. */
|
|
43
|
+
truncated: boolean;
|
|
44
|
+
};
|
|
45
|
+
export declare function parseWorkspaceManifest(dir: string, raw: string): WorkspaceManifest | undefined;
|
|
46
|
+
/**
|
|
47
|
+
* `packages:` entries of pnpm-workspace.yaml — the small subset of YAML it
|
|
48
|
+
* uses: a block list (indented or not) or a flow list (`['a/*', "b/*"]`,
|
|
49
|
+
* possibly across lines).
|
|
50
|
+
*/
|
|
51
|
+
export declare function pnpmWorkspaceGlobs(rawYaml: string | undefined): string[];
|
|
52
|
+
/**
|
|
53
|
+
* Read the root manifest and every workspace package manifest. Workspace
|
|
54
|
+
* directories come from the declared `workspaces` globs (package.json or
|
|
55
|
+
* pnpm-workspace.yaml) or, when none are declared, the conventional
|
|
56
|
+
* `apps/`, `packages/` and `libs/` roots. Only dependency trees and VCS
|
|
57
|
+
* directories are ignored — a declared glob may legitimately reach
|
|
58
|
+
* `tools/build/`. Paths the scan's `exclude` patterns cover (`isExcluded`) are
|
|
59
|
+
* never read.
|
|
60
|
+
*/
|
|
61
|
+
export declare function discoverWorkspaceManifests(repoRoot: string, rawRootPackageJson: string | undefined, isExcluded?: (posixPath: string) => boolean): Promise<WorkspaceDiscovery>;
|
|
62
|
+
/**
|
|
63
|
+
* True when `pnpm|yarn|bun <name>` would run an installed binary:
|
|
64
|
+
* - a workspace package exposes it (`bin`);
|
|
65
|
+
* - a dependency is literally named `<name>`; or
|
|
66
|
+
* - `<name>` is a well-known tool binary AND a package providing it is declared.
|
|
67
|
+
*
|
|
68
|
+
* When workspace discovery is absent or was truncated the declared packages are
|
|
69
|
+
* not the whole picture, so a well-known tool binary is accepted unconditionally.
|
|
70
|
+
*/
|
|
71
|
+
export declare function isKnownBinary(context: RepoContext, name: string): boolean;
|
|
72
|
+
/** True when the root manifest or any workspace package defines the script. */
|
|
73
|
+
export declare function anyWorkspaceHasScript(context: RepoContext, name: string): boolean;
|
|
74
|
+
/**
|
|
75
|
+
* Workspaces a pnpm/npm/yarn selector (package name, path, or glob) refers to.
|
|
76
|
+
* `*`, `**` and exclusion/dependents selectors (`!web`, `[origin/main]`) select
|
|
77
|
+
* every workspace — they cannot be evaluated statically, so stay permissive.
|
|
78
|
+
*/
|
|
79
|
+
export declare function selectWorkspaces(context: RepoContext, selector: string): WorkspaceManifest[];
|
|
80
|
+
//# sourceMappingURL=workspace-manifests.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-manifests.d.ts","sourceRoot":"","sources":["../src/workspace-manifests.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAOH,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,sEAAsE;IACtE,GAAG,EAAE,MAAM,CAAC;IACZ,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC;;;;OAIG;IACH,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB;;;;OAIG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAClC,uDAAuD;IACvD,IAAI,EAAE,MAAM,EAAE,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,kBAAkB,GAAG;IAC/B,SAAS,EAAE,iBAAiB,EAAE,CAAC;IAC/B,4FAA4F;IAC5F,SAAS,EAAE,OAAO,CAAC;CACpB,CAAC;AAgFF,wBAAgB,sBAAsB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,MAAM,GAAG,iBAAiB,GAAG,SAAS,CA2B9F;AA0BD;;;;GAIG;AACH,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,MAAM,GAAG,SAAS,GAAG,MAAM,EAAE,CAiCxE;AAkBD;;;;;;;;GAQG;AACH,wBAAsB,0BAA0B,CAC9C,QAAQ,EAAE,MAAM,EAChB,kBAAkB,EAAE,MAAM,GAAG,SAAS,EACtC,UAAU,GAAE,CAAC,SAAS,EAAE,MAAM,KAAK,OAAqB,GACvD,OAAO,CAAC,kBAAkB,CAAC,CAuC7B;AAmBD;;;;;;;;GAQG;AACH,wBAAgB,aAAa,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAQzE;AAED,+EAA+E;AAC/E,wBAAgB,qBAAqB,CAAC,OAAO,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAGjF;AAED;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,OAAO,EAAE,WAAW,EAAE,QAAQ,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAgB5F"}
|
|
@@ -0,0 +1,333 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Workspace package.json facts shared by the script-validity checks
|
|
3
|
+
* (command-validity and manifest-consistency).
|
|
4
|
+
*
|
|
5
|
+
* A package-manager command is only a "missing script" when nothing the repo
|
|
6
|
+
* can run under that name exists. Two kinds of names are never scripts and must
|
|
7
|
+
* not be reported as missing:
|
|
8
|
+
*
|
|
9
|
+
* - Dependencies and their binaries: `pnpm vitest run` and `yarn tsc --noEmit`
|
|
10
|
+
* fall through to the installed binary when no script of that name exists.
|
|
11
|
+
* - Scripts defined by a workspace package rather than the root manifest:
|
|
12
|
+
* `pnpm --filter web dev` or `pnpm -r build` in a monorepo.
|
|
13
|
+
*
|
|
14
|
+
* `node_modules/.bin` is not available when scanning a checkout, so a binary is
|
|
15
|
+
* accepted only when a package that provides it is declared in some workspace
|
|
16
|
+
* manifest (or, for a dependency whose name IS the command, the dependency
|
|
17
|
+
* itself). Everything here is deterministic and offline.
|
|
18
|
+
*/
|
|
19
|
+
import * as fs from 'node:fs/promises';
|
|
20
|
+
import * as path from 'node:path';
|
|
21
|
+
import micromatch from 'micromatch';
|
|
22
|
+
import { listFiles, resolveReadableWithinRoot, resolveWithinRoot } from './ai-config.js';
|
|
23
|
+
import { MAX_FILE_SIZE } from './scanner.js';
|
|
24
|
+
/** Upper bound on workspace manifests read, so a huge repo cannot stall a scan. */
|
|
25
|
+
const MAX_WORKSPACE_MANIFESTS = 200;
|
|
26
|
+
/** Conventional workspace roots, used when no `workspaces` globs are declared. */
|
|
27
|
+
const CONVENTIONAL_WORKSPACE_GLOBS = ['apps/*', 'packages/*', 'libs/*'];
|
|
28
|
+
const DEPENDENCY_BLOCKS = ['dependencies', 'devDependencies', 'peerDependencies', 'optionalDependencies'];
|
|
29
|
+
// ── Well-known binaries ───────────────────────────────────────────────────────
|
|
30
|
+
/**
|
|
31
|
+
* Common JS/TS tool binaries and the packages that install them. A bare
|
|
32
|
+
* `pnpm <bin>` / `yarn <bin>` runs the installed binary, so `pnpm prisma
|
|
33
|
+
* migrate` is valid when `prisma` is a dependency somewhere in the workspace —
|
|
34
|
+
* and a missing script when nothing installs it.
|
|
35
|
+
*/
|
|
36
|
+
const BIN_PROVIDERS = {
|
|
37
|
+
// compilers / bundlers / transpilers
|
|
38
|
+
tsc: ['typescript'], tsserver: ['typescript'], tsx: ['tsx'], 'ts-node': ['ts-node'],
|
|
39
|
+
tsup: ['tsup'], 'tsc-alias': ['tsc-alias'], 'vue-tsc': ['vue-tsc'], esbuild: ['esbuild'],
|
|
40
|
+
rollup: ['rollup'], webpack: ['webpack-cli', 'webpack'], vite: ['vite'], swc: ['@swc/cli'],
|
|
41
|
+
babel: ['@babel/cli'], parcel: ['parcel'], rspack: ['@rspack/cli'], unbuild: ['unbuild'],
|
|
42
|
+
bunchee: ['bunchee'],
|
|
43
|
+
// lint / format / type tools
|
|
44
|
+
eslint: ['eslint'], prettier: ['prettier'], biome: ['@biomejs/biome'], oxlint: ['oxlint'],
|
|
45
|
+
stylelint: ['stylelint'], knip: ['knip'], depcheck: ['depcheck'], madge: ['madge'],
|
|
46
|
+
commitlint: ['@commitlint/cli'], 'svelte-check': ['svelte-check'], typedoc: ['typedoc'],
|
|
47
|
+
'size-limit': ['size-limit'],
|
|
48
|
+
// test runners
|
|
49
|
+
vitest: ['vitest'], jest: ['jest'], mocha: ['mocha'], ava: ['ava'],
|
|
50
|
+
playwright: ['@playwright/test', 'playwright'], cypress: ['cypress'],
|
|
51
|
+
storybook: ['storybook', '@storybook/cli'], msw: ['msw'],
|
|
52
|
+
// monorepo / release
|
|
53
|
+
turbo: ['turbo'], nx: ['nx'], lerna: ['lerna'], changeset: ['@changesets/cli'],
|
|
54
|
+
'semantic-release': ['semantic-release'], husky: ['husky'], 'lint-staged': ['lint-staged'],
|
|
55
|
+
// frameworks
|
|
56
|
+
next: ['next'], nuxt: ['nuxt'], nuxi: ['nuxt', 'nuxi'], astro: ['astro'], remix: ['@remix-run/dev'],
|
|
57
|
+
expo: ['expo'], eas: ['eas-cli'], 'react-native': ['react-native'], ng: ['@angular/cli'],
|
|
58
|
+
nest: ['@nestjs/cli'], gatsby: ['gatsby'], docusaurus: ['@docusaurus/core'], vitepress: ['vitepress'],
|
|
59
|
+
tauri: ['@tauri-apps/cli'], electron: ['electron'], 'electron-builder': ['electron-builder'],
|
|
60
|
+
sanity: ['sanity', '@sanity/cli'], strapi: ['@strapi/strapi'],
|
|
61
|
+
// data / infra / deploy
|
|
62
|
+
prisma: ['prisma'], 'drizzle-kit': ['drizzle-kit'], knex: ['knex'], typeorm: ['typeorm'],
|
|
63
|
+
sequelize: ['sequelize-cli'], supabase: ['supabase'], wrangler: ['wrangler'], vercel: ['vercel'],
|
|
64
|
+
netlify: ['netlify-cli'], firebase: ['firebase-tools'], sst: ['sst'], cdk: ['aws-cdk'],
|
|
65
|
+
serverless: ['serverless'],
|
|
66
|
+
// process / shell helpers
|
|
67
|
+
nodemon: ['nodemon'], concurrently: ['concurrently'], 'cross-env': ['cross-env'], rimraf: ['rimraf'],
|
|
68
|
+
dotenv: ['dotenv-cli', 'dotenv'], 'npm-run-all': ['npm-run-all', 'npm-run-all2'],
|
|
69
|
+
'run-s': ['npm-run-all', 'npm-run-all2'], 'run-p': ['npm-run-all', 'npm-run-all2'],
|
|
70
|
+
// css / codegen
|
|
71
|
+
tailwindcss: ['tailwindcss', '@tailwindcss/cli'], postcss: ['postcss-cli'],
|
|
72
|
+
'graphql-codegen': ['@graphql-codegen/cli'], 'openapi-typescript': ['openapi-typescript'],
|
|
73
|
+
};
|
|
74
|
+
// ── Discovery (async; called once while building the RepoContext) ─────────────
|
|
75
|
+
function stringKeys(value) {
|
|
76
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
77
|
+
return [];
|
|
78
|
+
return Object.keys(value);
|
|
79
|
+
}
|
|
80
|
+
function stringRecord(value) {
|
|
81
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
82
|
+
return {};
|
|
83
|
+
const out = {};
|
|
84
|
+
for (const [key, v] of Object.entries(value)) {
|
|
85
|
+
if (typeof v === 'string')
|
|
86
|
+
out[key] = v;
|
|
87
|
+
}
|
|
88
|
+
return out;
|
|
89
|
+
}
|
|
90
|
+
/** Bin names a manifest exposes: a string `bin` is named after the (unscoped) package. */
|
|
91
|
+
function binNames(parsed) {
|
|
92
|
+
const { bin, name } = parsed;
|
|
93
|
+
if (typeof bin === 'string' && typeof name === 'string')
|
|
94
|
+
return [name.split('/').pop()];
|
|
95
|
+
return stringKeys(bin);
|
|
96
|
+
}
|
|
97
|
+
export function parseWorkspaceManifest(dir, raw) {
|
|
98
|
+
let parsed;
|
|
99
|
+
try {
|
|
100
|
+
parsed = JSON.parse(raw);
|
|
101
|
+
}
|
|
102
|
+
catch {
|
|
103
|
+
return undefined;
|
|
104
|
+
}
|
|
105
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed))
|
|
106
|
+
return undefined;
|
|
107
|
+
const obj = parsed;
|
|
108
|
+
const dependencies = new Set();
|
|
109
|
+
const versions = {};
|
|
110
|
+
for (const block of DEPENDENCY_BLOCKS) {
|
|
111
|
+
const specs = stringRecord(obj[block]);
|
|
112
|
+
for (const dep of Object.keys(specs)) {
|
|
113
|
+
if (specs[dep].startsWith('workspace:'))
|
|
114
|
+
continue;
|
|
115
|
+
dependencies.add(dep);
|
|
116
|
+
if (!(dep in versions))
|
|
117
|
+
versions[dep] = specs[dep];
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
return {
|
|
121
|
+
dir,
|
|
122
|
+
name: typeof obj.name === 'string' ? obj.name : undefined,
|
|
123
|
+
scripts: stringRecord(obj.scripts),
|
|
124
|
+
dependencies: [...dependencies].sort(),
|
|
125
|
+
versions,
|
|
126
|
+
bins: binNames(obj),
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
/** `workspaces` globs from package.json (array form, or yarn's `{ packages: [...] }`). */
|
|
130
|
+
function packageJsonWorkspaceGlobs(rawPackageJson) {
|
|
131
|
+
if (!rawPackageJson)
|
|
132
|
+
return [];
|
|
133
|
+
try {
|
|
134
|
+
const parsed = JSON.parse(rawPackageJson);
|
|
135
|
+
const ws = parsed.workspaces;
|
|
136
|
+
const list = Array.isArray(ws)
|
|
137
|
+
? ws
|
|
138
|
+
: typeof ws === 'object' && ws !== null && Array.isArray(ws.packages)
|
|
139
|
+
? ws.packages
|
|
140
|
+
: [];
|
|
141
|
+
return list.filter((g) => typeof g === 'string');
|
|
142
|
+
}
|
|
143
|
+
catch {
|
|
144
|
+
return [];
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function unquoteYamlScalar(raw) {
|
|
148
|
+
const trimmed = raw.trim();
|
|
149
|
+
const quoted = /^(?:"([^"]*)"|'([^']*)')/.exec(trimmed);
|
|
150
|
+
if (quoted)
|
|
151
|
+
return quoted[1] ?? quoted[2] ?? '';
|
|
152
|
+
return trimmed.replace(/\s+#.*$/, '');
|
|
153
|
+
}
|
|
154
|
+
/**
|
|
155
|
+
* `packages:` entries of pnpm-workspace.yaml — the small subset of YAML it
|
|
156
|
+
* uses: a block list (indented or not) or a flow list (`['a/*', "b/*"]`,
|
|
157
|
+
* possibly across lines).
|
|
158
|
+
*/
|
|
159
|
+
export function pnpmWorkspaceGlobs(rawYaml) {
|
|
160
|
+
if (!rawYaml)
|
|
161
|
+
return [];
|
|
162
|
+
const lines = rawYaml.split(/\r?\n/);
|
|
163
|
+
const globs = [];
|
|
164
|
+
for (let i = 0; i < lines.length; i++) {
|
|
165
|
+
const header = /^packages\s*:\s*(.*)$/.exec(lines[i]);
|
|
166
|
+
if (!header)
|
|
167
|
+
continue;
|
|
168
|
+
const rest = header[1].trim();
|
|
169
|
+
if (rest.startsWith('[')) {
|
|
170
|
+
let flow = rest;
|
|
171
|
+
for (let j = i + 1; !flow.includes(']') && j < lines.length; j++)
|
|
172
|
+
flow += ` ${lines[j].trim()}`;
|
|
173
|
+
const inner = flow.slice(1, flow.includes(']') ? flow.indexOf(']') : undefined);
|
|
174
|
+
for (const item of inner.split(',')) {
|
|
175
|
+
const glob = unquoteYamlScalar(item);
|
|
176
|
+
if (glob)
|
|
177
|
+
globs.push(glob);
|
|
178
|
+
}
|
|
179
|
+
break;
|
|
180
|
+
}
|
|
181
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
182
|
+
const line = lines[j];
|
|
183
|
+
const item = /^\s*-\s+(.*)$/.exec(line); // `- x` at any indent, including column 0
|
|
184
|
+
if (item) {
|
|
185
|
+
const glob = unquoteYamlScalar(item[1]);
|
|
186
|
+
if (glob)
|
|
187
|
+
globs.push(glob);
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// Blank lines and comments continue the list; the next top-level key ends it.
|
|
191
|
+
if (line.trim() === '' || /^\s*#/.test(line) || /^\s/.test(line))
|
|
192
|
+
continue;
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
break;
|
|
196
|
+
}
|
|
197
|
+
return globs;
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* A workspace glob is only followed when it stays inside the repository: an
|
|
201
|
+
* absolute path or a `..` segment would let a hostile `workspaces` entry read
|
|
202
|
+
* package.json files of sibling directories.
|
|
203
|
+
*/
|
|
204
|
+
function isContainedGlob(glob) {
|
|
205
|
+
const posix = glob.replace(/\\/g, '/');
|
|
206
|
+
if (posix.startsWith('/') || /^[a-zA-Z]:/.test(posix))
|
|
207
|
+
return false;
|
|
208
|
+
return !posix.split('/').includes('..');
|
|
209
|
+
}
|
|
210
|
+
function toManifestGlob(workspaceGlob) {
|
|
211
|
+
const trimmed = workspaceGlob.replace(/^\.\//, '').replace(/\/+$/, '');
|
|
212
|
+
return `${trimmed}/package.json`;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Read the root manifest and every workspace package manifest. Workspace
|
|
216
|
+
* directories come from the declared `workspaces` globs (package.json or
|
|
217
|
+
* pnpm-workspace.yaml) or, when none are declared, the conventional
|
|
218
|
+
* `apps/`, `packages/` and `libs/` roots. Only dependency trees and VCS
|
|
219
|
+
* directories are ignored — a declared glob may legitimately reach
|
|
220
|
+
* `tools/build/`. Paths the scan's `exclude` patterns cover (`isExcluded`) are
|
|
221
|
+
* never read.
|
|
222
|
+
*/
|
|
223
|
+
export async function discoverWorkspaceManifests(repoRoot, rawRootPackageJson, isExcluded = () => false) {
|
|
224
|
+
let pnpmYaml;
|
|
225
|
+
try {
|
|
226
|
+
const abs = resolveReadableWithinRoot(repoRoot, 'pnpm-workspace.yaml');
|
|
227
|
+
pnpmYaml = abs ? await fs.readFile(abs, 'utf-8') : undefined;
|
|
228
|
+
}
|
|
229
|
+
catch {
|
|
230
|
+
pnpmYaml = undefined;
|
|
231
|
+
}
|
|
232
|
+
const declared = [...packageJsonWorkspaceGlobs(rawRootPackageJson), ...pnpmWorkspaceGlobs(pnpmYaml)];
|
|
233
|
+
const positive = declared.filter((g) => !g.startsWith('!') && isContainedGlob(g));
|
|
234
|
+
const negative = declared.filter((g) => g.startsWith('!')).map((g) => g.slice(1));
|
|
235
|
+
const globs = positive.length > 0 ? positive : CONVENTIONAL_WORKSPACE_GLOBS;
|
|
236
|
+
const ignore = [
|
|
237
|
+
'**/node_modules/**', '**/.git/**',
|
|
238
|
+
...negative.filter(isContainedGlob).map((g) => `${g.replace(/\/+$/, '')}/**`),
|
|
239
|
+
];
|
|
240
|
+
const matched = listFiles(repoRoot, globs.map(toManifestGlob), ignore)
|
|
241
|
+
.filter((rel) => resolveWithinRoot(repoRoot, rel) !== null && !isExcluded(rel));
|
|
242
|
+
const truncated = matched.length > MAX_WORKSPACE_MANIFESTS;
|
|
243
|
+
const manifests = [];
|
|
244
|
+
const rootManifest = rawRootPackageJson ? parseWorkspaceManifest('.', rawRootPackageJson) : undefined;
|
|
245
|
+
if (rootManifest)
|
|
246
|
+
manifests.push(rootManifest);
|
|
247
|
+
for (const rel of matched.slice(0, MAX_WORKSPACE_MANIFESTS)) {
|
|
248
|
+
if (rel === 'package.json')
|
|
249
|
+
continue;
|
|
250
|
+
try {
|
|
251
|
+
const abs = resolveReadableWithinRoot(repoRoot, rel);
|
|
252
|
+
if (!abs)
|
|
253
|
+
continue;
|
|
254
|
+
const stat = await fs.stat(abs);
|
|
255
|
+
if (!stat.isFile() || stat.size > MAX_FILE_SIZE)
|
|
256
|
+
continue;
|
|
257
|
+
const manifest = parseWorkspaceManifest(path.posix.dirname(rel), await fs.readFile(abs, 'utf-8'));
|
|
258
|
+
if (manifest)
|
|
259
|
+
manifests.push(manifest);
|
|
260
|
+
}
|
|
261
|
+
catch {
|
|
262
|
+
// unreadable — skip
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
return { manifests, truncated };
|
|
266
|
+
}
|
|
267
|
+
// ── Queries (pure; used by the detectors) ─────────────────────────────────────
|
|
268
|
+
/** Dependency names declared anywhere in the workspace, without @types and sibling-package links. */
|
|
269
|
+
function installedPackages(context) {
|
|
270
|
+
const localNames = new Set((context.workspaces ?? []).map((ws) => ws.name).filter((n) => !!n));
|
|
271
|
+
const names = new Set();
|
|
272
|
+
const add = (dep) => {
|
|
273
|
+
if (!dep.startsWith('@types/') && !localNames.has(dep))
|
|
274
|
+
names.add(dep);
|
|
275
|
+
};
|
|
276
|
+
const { dependencies, devDependencies, peerDependencies } = context.packageJson;
|
|
277
|
+
for (const block of [dependencies, devDependencies, peerDependencies]) {
|
|
278
|
+
for (const [dep, spec] of Object.entries(block))
|
|
279
|
+
if (!spec.startsWith('workspace:'))
|
|
280
|
+
add(dep);
|
|
281
|
+
}
|
|
282
|
+
for (const ws of context.workspaces ?? [])
|
|
283
|
+
ws.dependencies.forEach(add);
|
|
284
|
+
return names;
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* True when `pnpm|yarn|bun <name>` would run an installed binary:
|
|
288
|
+
* - a workspace package exposes it (`bin`);
|
|
289
|
+
* - a dependency is literally named `<name>`; or
|
|
290
|
+
* - `<name>` is a well-known tool binary AND a package providing it is declared.
|
|
291
|
+
*
|
|
292
|
+
* When workspace discovery is absent or was truncated the declared packages are
|
|
293
|
+
* not the whole picture, so a well-known tool binary is accepted unconditionally.
|
|
294
|
+
*/
|
|
295
|
+
export function isKnownBinary(context, name) {
|
|
296
|
+
if ((context.workspaces ?? []).some((ws) => ws.bins.includes(name)))
|
|
297
|
+
return true;
|
|
298
|
+
const installed = installedPackages(context);
|
|
299
|
+
if (installed.has(name))
|
|
300
|
+
return true;
|
|
301
|
+
const providers = BIN_PROVIDERS[name];
|
|
302
|
+
if (!providers)
|
|
303
|
+
return false;
|
|
304
|
+
if (context.workspaces === undefined || context.workspacesTruncated)
|
|
305
|
+
return true;
|
|
306
|
+
return providers.some((provider) => installed.has(provider));
|
|
307
|
+
}
|
|
308
|
+
/** True when the root manifest or any workspace package defines the script. */
|
|
309
|
+
export function anyWorkspaceHasScript(context, name) {
|
|
310
|
+
if (context.packageJson.scripts[name])
|
|
311
|
+
return true;
|
|
312
|
+
return (context.workspaces ?? []).some((ws) => !!ws.scripts[name]);
|
|
313
|
+
}
|
|
314
|
+
/**
|
|
315
|
+
* Workspaces a pnpm/npm/yarn selector (package name, path, or glob) refers to.
|
|
316
|
+
* `*`, `**` and exclusion/dependents selectors (`!web`, `[origin/main]`) select
|
|
317
|
+
* every workspace — they cannot be evaluated statically, so stay permissive.
|
|
318
|
+
*/
|
|
319
|
+
export function selectWorkspaces(context, selector) {
|
|
320
|
+
const workspaces = context.workspaces ?? [];
|
|
321
|
+
if (selector === '*' || selector === '**' || selector.startsWith('!') || selector.startsWith('[')) {
|
|
322
|
+
return workspaces;
|
|
323
|
+
}
|
|
324
|
+
const posix = selector.replace(/\\/g, '/').replace(/^\.\//, '').replace(/\/+$/, '');
|
|
325
|
+
const options = { dot: true };
|
|
326
|
+
return workspaces.filter((ws) => ws.name === selector ||
|
|
327
|
+
ws.dir === posix ||
|
|
328
|
+
ws.dir.endsWith(`/${posix}`) ||
|
|
329
|
+
(/[*?[{]/.test(selector) &&
|
|
330
|
+
((ws.name !== undefined && micromatch.isMatch(ws.name, selector, options)) ||
|
|
331
|
+
micromatch.isMatch(ws.dir, posix, options))));
|
|
332
|
+
}
|
|
333
|
+
//# sourceMappingURL=workspace-manifests.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"workspace-manifests.js","sourceRoot":"","sources":["../src/workspace-manifests.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@promptci/core",
|
|
3
|
-
"version": "0.0
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"description": "Deterministic scanner for AI coding instruction files (CLAUDE.md, AGENTS.md, .cursorrules) — detectors, scoring, and report generation",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"type": "module",
|
|
@@ -40,15 +40,18 @@
|
|
|
40
40
|
"prompt",
|
|
41
41
|
"scanner"
|
|
42
42
|
],
|
|
43
|
+
"scripts": {
|
|
44
|
+
"build": "tsc -p tsconfig.json",
|
|
45
|
+
"typecheck": "tsc -p tsconfig.json --noEmit",
|
|
46
|
+
"prepublishOnly": "pnpm run build"
|
|
47
|
+
},
|
|
43
48
|
"devDependencies": {
|
|
44
49
|
"@types/node": "*",
|
|
45
|
-
"typescript": "*"
|
|
50
|
+
"typescript": "*",
|
|
51
|
+
"@types/micromatch": "*"
|
|
46
52
|
},
|
|
47
53
|
"dependencies": {
|
|
48
|
-
"fast-glob": "^3.3.3"
|
|
49
|
-
|
|
50
|
-
"scripts": {
|
|
51
|
-
"build": "tsc -p tsconfig.json",
|
|
52
|
-
"typecheck": "tsc -p tsconfig.json --noEmit"
|
|
54
|
+
"fast-glob": "^3.3.3",
|
|
55
|
+
"micromatch": "^4.0.8"
|
|
53
56
|
}
|
|
54
|
-
}
|
|
57
|
+
}
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"cheap-model-routing.d.ts","sourceRoot":"","sources":["../src/cheap-model-routing.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAWhD,wBAAgB,uBAAuB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CAsC7E"}
|