@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,151 @@
|
|
|
1
|
+
import * as path from 'node:path';
|
|
2
|
+
import * as crypto from 'node:crypto';
|
|
3
|
+
/**
|
|
4
|
+
* B4: every id in this file was keyed by `${file.fileType}` — two files
|
|
5
|
+
* sharing a fileType (e.g. CLAUDE.md and .claude/notes.md, both 'claude')
|
|
6
|
+
* collided on the same id for each of the 5 checks below.
|
|
7
|
+
*/
|
|
8
|
+
function promptCacheIssueId(kind, filePath) {
|
|
9
|
+
const hash = crypto.createHash('sha1').update(`prompt-cache-${kind}:${filePath}`).digest('hex').slice(0, 12);
|
|
10
|
+
return `prompt-cache-${kind}-${hash}`;
|
|
11
|
+
}
|
|
12
|
+
const DATE_PATTERNS = [
|
|
13
|
+
/\b(?:last\s+updated|last\s+modified|updated\s+at|modified\s+at|date)\b\s*:\s*\b\d{4}-\d{2}-\d{2}\b/i,
|
|
14
|
+
/\b\d{4}-\d{2}-\d{2}t\d{2}:\d{2}:\d{2}\b/i,
|
|
15
|
+
/\b(?:january|february|march|april|may|june|july|august|september|october|november|december)\s+\d{1,2}(?:st|nd|rd|th)?,\s+\d{4}\b/i,
|
|
16
|
+
];
|
|
17
|
+
const SCAN_REPORT_PATTERNS = [
|
|
18
|
+
/health\s+score\s*:\s*\d+/i,
|
|
19
|
+
/files\s+scanned\s*:\s*\d+/i,
|
|
20
|
+
/promptci\s+report/i,
|
|
21
|
+
/\bgenerated\s+by\s+promptci\b/i,
|
|
22
|
+
/latest\s+scan\s+results/i,
|
|
23
|
+
/scan\s+history/i,
|
|
24
|
+
];
|
|
25
|
+
const BRANCH_TASK_PATTERNS = [
|
|
26
|
+
/current\s+branch\s*:\s*\S+/i,
|
|
27
|
+
/git\s+branch\s*:\s*\S+/i,
|
|
28
|
+
/current\s+task\s*:\s*\S+/i,
|
|
29
|
+
];
|
|
30
|
+
const LOCAL_PATH_PATTERN = /(?:[a-zA-Z]:\\users\\[a-zA-Z0-9_-]+)|(?:\/users\/[a-zA-Z0-9_-]+\/)|(?:\/home\/(?!runner)[a-zA-Z0-9_-]+\/)/i;
|
|
31
|
+
export function detectPromptCacheFriendliness(files) {
|
|
32
|
+
const issues = [];
|
|
33
|
+
// Focus only on persistent, always-loaded instruction files
|
|
34
|
+
const targetFiles = files.filter((f) => ['claude', 'agents', 'cursor', 'copilot', 'prompt'].includes(f.fileType));
|
|
35
|
+
for (const file of targetFiles) {
|
|
36
|
+
const fileName = path.basename(file.path);
|
|
37
|
+
// 1. Timestamps and Dates
|
|
38
|
+
for (const pat of DATE_PATTERNS) {
|
|
39
|
+
if (pat.test(file.content)) {
|
|
40
|
+
issues.push({
|
|
41
|
+
id: promptCacheIssueId('volatile-timestamp', file.path),
|
|
42
|
+
severity: 'warning',
|
|
43
|
+
category: 'context_bloat',
|
|
44
|
+
title: 'Volatile timestamp in instruction file',
|
|
45
|
+
summary: `The instruction file "${fileName}" contains a volatile date or timestamp. Frequently changing dates in persistent instruction files invalidate prompt caches.`,
|
|
46
|
+
filePaths: [file.path],
|
|
47
|
+
locations: [],
|
|
48
|
+
evidence: [`Matched pattern: ${pat.toString()}`],
|
|
49
|
+
recommendation: 'Move volatile dates to a separate task-specific prompt or scratch file, or remove them from canonical instructions.',
|
|
50
|
+
fixRecipe: 'Remove the "Last updated: <date>" or timestamp line from the file.',
|
|
51
|
+
confidence: 0.85,
|
|
52
|
+
});
|
|
53
|
+
break; // one is enough
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
// 2. Pasted Scan Outputs/Reports
|
|
57
|
+
for (const pat of SCAN_REPORT_PATTERNS) {
|
|
58
|
+
if (pat.test(file.content)) {
|
|
59
|
+
issues.push({
|
|
60
|
+
id: promptCacheIssueId('pasted-report', file.path),
|
|
61
|
+
severity: 'warning',
|
|
62
|
+
category: 'context_bloat',
|
|
63
|
+
title: 'Pasted scan report or summary in instructions',
|
|
64
|
+
summary: `The instruction file "${fileName}" contains pasted scan results or reports. Committing generated reports into canonical instruction files breaks prompt caching and bloats context.`,
|
|
65
|
+
filePaths: [file.path],
|
|
66
|
+
locations: [],
|
|
67
|
+
evidence: [`Matched pattern: ${pat.toString()}`],
|
|
68
|
+
recommendation: 'Link to the generated report file or read it on-demand instead of pasting its contents into canonical instructions.',
|
|
69
|
+
fixRecipe: 'Delete the pasted report summary block and reference the report file path instead.',
|
|
70
|
+
confidence: 0.9,
|
|
71
|
+
});
|
|
72
|
+
break;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
// 3. Current Branch or Task status
|
|
76
|
+
for (const pat of BRANCH_TASK_PATTERNS) {
|
|
77
|
+
if (pat.test(file.content)) {
|
|
78
|
+
issues.push({
|
|
79
|
+
id: promptCacheIssueId('volatile-branch-task', file.path),
|
|
80
|
+
severity: 'warning',
|
|
81
|
+
category: 'context_bloat',
|
|
82
|
+
title: 'Volatile branch or task status in instructions',
|
|
83
|
+
summary: `The instruction file "${fileName}" contains active git branch or task details. Frequently updated task status or branch names break prompt caching.`,
|
|
84
|
+
filePaths: [file.path],
|
|
85
|
+
locations: [],
|
|
86
|
+
evidence: [`Matched pattern: ${pat.toString()}`],
|
|
87
|
+
recommendation: 'Move branch-specific notes and active task details to git commit messages, PR descriptions, or a temporary scratch file.',
|
|
88
|
+
fixRecipe: 'Remove active branch and task notes from the persistent instructions.',
|
|
89
|
+
confidence: 0.85,
|
|
90
|
+
});
|
|
91
|
+
break;
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
// 4. Local User Paths
|
|
95
|
+
if (LOCAL_PATH_PATTERN.test(file.content)) {
|
|
96
|
+
const match = file.content.match(LOCAL_PATH_PATTERN)?.[0] ?? '';
|
|
97
|
+
issues.push({
|
|
98
|
+
id: promptCacheIssueId('local-paths', file.path),
|
|
99
|
+
severity: 'warning',
|
|
100
|
+
category: 'context_bloat',
|
|
101
|
+
title: 'Local machine paths in instructions',
|
|
102
|
+
summary: `The instruction file "${fileName}" contains absolute local machine paths ("${match}"). These paths change per environment, preventing prompt caching and causing instruction drift.`,
|
|
103
|
+
filePaths: [file.path],
|
|
104
|
+
locations: [],
|
|
105
|
+
evidence: [`Found absolute local path: ${match}`],
|
|
106
|
+
recommendation: 'Use repository-relative paths instead of absolute local machine paths.',
|
|
107
|
+
fixRecipe: 'Replace absolute local paths with repository-relative paths.',
|
|
108
|
+
confidence: 0.8,
|
|
109
|
+
});
|
|
110
|
+
}
|
|
111
|
+
// 5. Large Tables (more than 15 rows)
|
|
112
|
+
const lines = file.content.split(/\r?\n/);
|
|
113
|
+
let maxTableRows = 0;
|
|
114
|
+
let currentTableRows = 0;
|
|
115
|
+
for (const line of lines) {
|
|
116
|
+
const trimmed = line.trim();
|
|
117
|
+
if (trimmed.startsWith('|') && trimmed.endsWith('|')) {
|
|
118
|
+
if (/^\|[-\s:|]+\|$/.test(trimmed)) {
|
|
119
|
+
continue;
|
|
120
|
+
}
|
|
121
|
+
currentTableRows++;
|
|
122
|
+
}
|
|
123
|
+
else {
|
|
124
|
+
if (currentTableRows > maxTableRows) {
|
|
125
|
+
maxTableRows = currentTableRows;
|
|
126
|
+
}
|
|
127
|
+
currentTableRows = 0;
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
if (currentTableRows > maxTableRows) {
|
|
131
|
+
maxTableRows = currentTableRows;
|
|
132
|
+
}
|
|
133
|
+
if (maxTableRows > 15) {
|
|
134
|
+
issues.push({
|
|
135
|
+
id: promptCacheIssueId('large-table', file.path),
|
|
136
|
+
severity: 'warning',
|
|
137
|
+
category: 'context_bloat',
|
|
138
|
+
title: 'Large table in instruction file',
|
|
139
|
+
summary: `The instruction file "${fileName}" contains a large Markdown table (${maxTableRows} rows). Large tables bloat prompt context and reduce caching friendliness.`,
|
|
140
|
+
filePaths: [file.path],
|
|
141
|
+
locations: [],
|
|
142
|
+
evidence: [`Markdown table with ${maxTableRows} rows found in ${fileName}.`],
|
|
143
|
+
recommendation: 'Move large tables to separate documentation files (e.g. under docs/) or load them on-demand via tools instead of keeping them in always-loaded instructions.',
|
|
144
|
+
fixRecipe: 'Extract the table to a separate document and link to it.',
|
|
145
|
+
confidence: 0.9,
|
|
146
|
+
});
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
return issues;
|
|
150
|
+
}
|
|
151
|
+
//# sourceMappingURL=prompt-cache.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"prompt-cache.js","sourceRoot":"","sources":["../src/prompt-cache.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import type { ManifestData } from './manifest-consistency.js';
|
|
2
|
+
import type { InstructionFile, ProjectType, ScanInput, ScanMetrics } from './types.js';
|
|
3
|
+
export type PackageManagerName = 'pnpm' | 'npm' | 'yarn' | 'bun' | 'unknown';
|
|
4
|
+
export type PackageJsonFacts = {
|
|
5
|
+
raw?: string;
|
|
6
|
+
packageManager?: string;
|
|
7
|
+
packageManagerName: PackageManagerName;
|
|
8
|
+
enginesNode?: string;
|
|
9
|
+
scripts: Record<string, string>;
|
|
10
|
+
dependencies: Record<string, string>;
|
|
11
|
+
devDependencies: Record<string, string>;
|
|
12
|
+
peerDependencies: Record<string, string>;
|
|
13
|
+
lockfiles: string[];
|
|
14
|
+
};
|
|
15
|
+
export type WorkflowCommand = {
|
|
16
|
+
filePath: string;
|
|
17
|
+
command: string;
|
|
18
|
+
line: number;
|
|
19
|
+
};
|
|
20
|
+
export type WorkflowFacts = {
|
|
21
|
+
files: string[];
|
|
22
|
+
commands: WorkflowCommand[];
|
|
23
|
+
};
|
|
24
|
+
export type RepoContext = {
|
|
25
|
+
repoRoot: string;
|
|
26
|
+
files: InstructionFile[];
|
|
27
|
+
projectType: ProjectType;
|
|
28
|
+
manifests: ManifestData;
|
|
29
|
+
packageJson: PackageJsonFacts;
|
|
30
|
+
workflows: WorkflowFacts;
|
|
31
|
+
metrics: ScanMetrics;
|
|
32
|
+
contextBudget?: number;
|
|
33
|
+
fileContextBudget?: number;
|
|
34
|
+
};
|
|
35
|
+
export declare function parsePackageJsonFacts(raw: string | undefined, lockfiles: string[]): PackageJsonFacts;
|
|
36
|
+
export declare function buildRepoContext(input: ScanInput): Promise<RepoContext>;
|
|
37
|
+
//# sourceMappingURL=repo-context.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-context.d.ts","sourceRoot":"","sources":["../src/repo-context.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAC9D,OAAO,KAAK,EAAE,eAAe,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAEvF,MAAM,MAAM,kBAAkB,GAAG,MAAM,GAAG,KAAK,GAAG,MAAM,GAAG,KAAK,GAAG,SAAS,CAAC;AAE7E,MAAM,MAAM,gBAAgB,GAAG;IAC7B,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,cAAc,CAAC,EAAE,MAAM,CAAC;IACxB,kBAAkB,EAAE,kBAAkB,CAAC;IACvC,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAChC,YAAY,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACrC,eAAe,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,gBAAgB,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,SAAS,EAAE,MAAM,EAAE,CAAC;CACrB,CAAC;AAEF,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,aAAa,GAAG;IAC1B,KAAK,EAAE,MAAM,EAAE,CAAC;IAChB,QAAQ,EAAE,eAAe,EAAE,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG;IACxB,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,eAAe,EAAE,CAAC;IACzB,WAAW,EAAE,WAAW,CAAC;IACzB,SAAS,EAAE,YAAY,CAAC;IACxB,WAAW,EAAE,gBAAgB,CAAC;IAC9B,SAAS,EAAE,aAAa,CAAC;IACzB,OAAO,EAAE,WAAW,CAAC;IACrB,aAAa,CAAC,EAAE,MAAM,CAAC;IACvB,iBAAiB,CAAC,EAAE,MAAM,CAAC;CAC5B,CAAC;AA8EF,wBAAgB,qBAAqB,CAAC,GAAG,EAAE,MAAM,GAAG,SAAS,EAAE,SAAS,EAAE,MAAM,EAAE,GAAG,gBAAgB,CAwCpG;AAyED,wBAAsB,gBAAgB,CAAC,KAAK,EAAE,SAAS,GAAG,OAAO,CAAC,WAAW,CAAC,CAmC7E"}
|
|
@@ -0,0 +1,221 @@
|
|
|
1
|
+
import * as fs from 'node:fs/promises';
|
|
2
|
+
import * as path from 'node:path';
|
|
3
|
+
import { detectProjectType, detectProjectTypeFromContent } from './project-type.js';
|
|
4
|
+
import { scanFiles } from './scanner.js';
|
|
5
|
+
const LOCKFILES = [
|
|
6
|
+
'pnpm-lock.yaml',
|
|
7
|
+
'package-lock.json',
|
|
8
|
+
'yarn.lock',
|
|
9
|
+
'bun.lockb',
|
|
10
|
+
'bun.lock',
|
|
11
|
+
];
|
|
12
|
+
function emptyPackageJsonFacts() {
|
|
13
|
+
return {
|
|
14
|
+
packageManagerName: 'unknown',
|
|
15
|
+
scripts: {},
|
|
16
|
+
dependencies: {},
|
|
17
|
+
devDependencies: {},
|
|
18
|
+
peerDependencies: {},
|
|
19
|
+
lockfiles: [],
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
function resolveWithinRoot(repoRoot, relativePath) {
|
|
23
|
+
const root = path.resolve(repoRoot);
|
|
24
|
+
const resolved = path.resolve(root, relativePath);
|
|
25
|
+
const relative = path.relative(root, resolved);
|
|
26
|
+
if (relative.startsWith('..') || path.isAbsolute(relative)) {
|
|
27
|
+
throw new Error(`Path escapes repo root: ${relativePath}`);
|
|
28
|
+
}
|
|
29
|
+
return resolved;
|
|
30
|
+
}
|
|
31
|
+
async function readRootFile(repoRoot, relativePath) {
|
|
32
|
+
try {
|
|
33
|
+
return await fs.readFile(resolveWithinRoot(repoRoot, relativePath), 'utf-8');
|
|
34
|
+
}
|
|
35
|
+
catch {
|
|
36
|
+
return undefined;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async function existingRootFiles(repoRoot, relativePaths) {
|
|
40
|
+
const found = [];
|
|
41
|
+
for (const rel of relativePaths) {
|
|
42
|
+
try {
|
|
43
|
+
const stat = await fs.stat(resolveWithinRoot(repoRoot, rel));
|
|
44
|
+
if (stat.isFile())
|
|
45
|
+
found.push(rel);
|
|
46
|
+
}
|
|
47
|
+
catch {
|
|
48
|
+
// absent file
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return found;
|
|
52
|
+
}
|
|
53
|
+
function packageManagerFromString(packageManager) {
|
|
54
|
+
if (!packageManager)
|
|
55
|
+
return 'unknown';
|
|
56
|
+
if (packageManager.startsWith('pnpm@'))
|
|
57
|
+
return 'pnpm';
|
|
58
|
+
if (packageManager.startsWith('npm@'))
|
|
59
|
+
return 'npm';
|
|
60
|
+
if (packageManager.startsWith('yarn@'))
|
|
61
|
+
return 'yarn';
|
|
62
|
+
if (packageManager.startsWith('bun@'))
|
|
63
|
+
return 'bun';
|
|
64
|
+
return 'unknown';
|
|
65
|
+
}
|
|
66
|
+
function packageManagerFromLockfiles(lockfiles) {
|
|
67
|
+
if (lockfiles.includes('pnpm-lock.yaml'))
|
|
68
|
+
return 'pnpm';
|
|
69
|
+
if (lockfiles.includes('package-lock.json'))
|
|
70
|
+
return 'npm';
|
|
71
|
+
if (lockfiles.includes('yarn.lock'))
|
|
72
|
+
return 'yarn';
|
|
73
|
+
if (lockfiles.some((f) => f.startsWith('bun.lock')))
|
|
74
|
+
return 'bun';
|
|
75
|
+
return 'unknown';
|
|
76
|
+
}
|
|
77
|
+
function stringRecord(value) {
|
|
78
|
+
if (typeof value !== 'object' || value === null || Array.isArray(value))
|
|
79
|
+
return {};
|
|
80
|
+
const out = {};
|
|
81
|
+
for (const [key, v] of Object.entries(value)) {
|
|
82
|
+
if (typeof v === 'string')
|
|
83
|
+
out[key] = v;
|
|
84
|
+
}
|
|
85
|
+
return out;
|
|
86
|
+
}
|
|
87
|
+
export function parsePackageJsonFacts(raw, lockfiles) {
|
|
88
|
+
const facts = emptyPackageJsonFacts();
|
|
89
|
+
facts.raw = raw;
|
|
90
|
+
facts.lockfiles = lockfiles;
|
|
91
|
+
if (!raw) {
|
|
92
|
+
facts.packageManagerName = packageManagerFromLockfiles(lockfiles);
|
|
93
|
+
return facts;
|
|
94
|
+
}
|
|
95
|
+
let parsed;
|
|
96
|
+
try {
|
|
97
|
+
parsed = JSON.parse(raw);
|
|
98
|
+
}
|
|
99
|
+
catch {
|
|
100
|
+
facts.packageManagerName = packageManagerFromLockfiles(lockfiles);
|
|
101
|
+
return facts;
|
|
102
|
+
}
|
|
103
|
+
if (typeof parsed !== 'object' || parsed === null || Array.isArray(parsed)) {
|
|
104
|
+
facts.packageManagerName = packageManagerFromLockfiles(lockfiles);
|
|
105
|
+
return facts;
|
|
106
|
+
}
|
|
107
|
+
const obj = parsed;
|
|
108
|
+
facts.packageManager = typeof obj.packageManager === 'string' ? obj.packageManager : undefined;
|
|
109
|
+
facts.packageManagerName =
|
|
110
|
+
packageManagerFromString(facts.packageManager) !== 'unknown'
|
|
111
|
+
? packageManagerFromString(facts.packageManager)
|
|
112
|
+
: packageManagerFromLockfiles(lockfiles);
|
|
113
|
+
facts.scripts = stringRecord(obj.scripts);
|
|
114
|
+
facts.dependencies = stringRecord(obj.dependencies);
|
|
115
|
+
facts.devDependencies = stringRecord(obj.devDependencies);
|
|
116
|
+
facts.peerDependencies = stringRecord(obj.peerDependencies);
|
|
117
|
+
if (typeof obj.engines === 'object' && obj.engines !== null && !Array.isArray(obj.engines)) {
|
|
118
|
+
const engines = obj.engines;
|
|
119
|
+
facts.enginesNode = typeof engines.node === 'string' ? engines.node : undefined;
|
|
120
|
+
}
|
|
121
|
+
return facts;
|
|
122
|
+
}
|
|
123
|
+
function extractWorkflowCommands(filePath, content) {
|
|
124
|
+
const lines = content.split(/\r?\n/);
|
|
125
|
+
const commands = [];
|
|
126
|
+
for (let i = 0; i < lines.length; i++) {
|
|
127
|
+
const line = lines[i];
|
|
128
|
+
const match = /^(\s*)(?:-\s*)?run:\s*(.*)$/.exec(line);
|
|
129
|
+
if (!match)
|
|
130
|
+
continue;
|
|
131
|
+
const indent = match[1].length;
|
|
132
|
+
const rest = match[2].trim();
|
|
133
|
+
if (rest && !/^[|>][+-]?$/.test(rest)) {
|
|
134
|
+
commands.push({ filePath, command: rest, line: i + 1 });
|
|
135
|
+
continue;
|
|
136
|
+
}
|
|
137
|
+
const block = [];
|
|
138
|
+
for (let j = i + 1; j < lines.length; j++) {
|
|
139
|
+
const next = lines[j];
|
|
140
|
+
if (next.trim() === '') {
|
|
141
|
+
block.push('');
|
|
142
|
+
continue;
|
|
143
|
+
}
|
|
144
|
+
const nextIndent = next.match(/^\s*/)?.[0].length ?? 0;
|
|
145
|
+
if (nextIndent <= indent)
|
|
146
|
+
break;
|
|
147
|
+
block.push(next.trim());
|
|
148
|
+
}
|
|
149
|
+
const command = block.filter(Boolean).join('\n').trim();
|
|
150
|
+
if (command)
|
|
151
|
+
commands.push({ filePath, command, line: i + 1 });
|
|
152
|
+
}
|
|
153
|
+
return commands;
|
|
154
|
+
}
|
|
155
|
+
async function readWorkflowFacts(repoRoot) {
|
|
156
|
+
const workflowDir = resolveWithinRoot(repoRoot, path.join('.github', 'workflows'));
|
|
157
|
+
let entries;
|
|
158
|
+
try {
|
|
159
|
+
entries = await fs.readdir(workflowDir, { withFileTypes: true });
|
|
160
|
+
}
|
|
161
|
+
catch {
|
|
162
|
+
return { files: [], commands: [] };
|
|
163
|
+
}
|
|
164
|
+
const files = entries
|
|
165
|
+
.filter((entry) => entry.isFile() && /\.(ya?ml)$/i.test(entry.name))
|
|
166
|
+
.map((entry) => path.join(workflowDir, entry.name))
|
|
167
|
+
.sort();
|
|
168
|
+
const commands = [];
|
|
169
|
+
for (const file of files) {
|
|
170
|
+
const relative = path.relative(repoRoot, file);
|
|
171
|
+
const content = await fs.readFile(file, 'utf-8');
|
|
172
|
+
commands.push(...extractWorkflowCommands(relative, content));
|
|
173
|
+
}
|
|
174
|
+
return {
|
|
175
|
+
files: files.map((file) => path.relative(repoRoot, file)),
|
|
176
|
+
commands,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
function buildMetrics(files) {
|
|
180
|
+
return {
|
|
181
|
+
estimatedInstructionTokens: files.reduce((sum, file) => sum + file.estimatedTokens, 0),
|
|
182
|
+
instructionFileCount: files.length,
|
|
183
|
+
largestInstructionFiles: [...files]
|
|
184
|
+
.sort((a, b) => b.estimatedTokens - a.estimatedTokens)
|
|
185
|
+
.slice(0, 5)
|
|
186
|
+
.map((file) => ({ path: file.path, estimatedTokens: file.estimatedTokens })),
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
export async function buildRepoContext(input) {
|
|
190
|
+
const repoRoot = path.resolve(input.repoPath);
|
|
191
|
+
const files = await scanFiles({ ...input, repoPath: repoRoot });
|
|
192
|
+
let projectType = input.projectType && input.projectType !== 'auto'
|
|
193
|
+
? input.projectType
|
|
194
|
+
: await detectProjectType(repoRoot);
|
|
195
|
+
if (projectType === 'unknown') {
|
|
196
|
+
projectType = detectProjectTypeFromContent(files);
|
|
197
|
+
}
|
|
198
|
+
const [packageJson, pyproject, lockfiles, workflows] = await Promise.all([
|
|
199
|
+
readRootFile(repoRoot, 'package.json'),
|
|
200
|
+
readRootFile(repoRoot, 'pyproject.toml'),
|
|
201
|
+
existingRootFiles(repoRoot, LOCKFILES),
|
|
202
|
+
readWorkflowFacts(repoRoot),
|
|
203
|
+
]);
|
|
204
|
+
const manifests = {};
|
|
205
|
+
if (packageJson)
|
|
206
|
+
manifests.packageJson = packageJson;
|
|
207
|
+
if (pyproject)
|
|
208
|
+
manifests.pyproject = pyproject;
|
|
209
|
+
return {
|
|
210
|
+
repoRoot,
|
|
211
|
+
files,
|
|
212
|
+
projectType,
|
|
213
|
+
manifests,
|
|
214
|
+
packageJson: parsePackageJsonFacts(packageJson, lockfiles),
|
|
215
|
+
workflows,
|
|
216
|
+
metrics: buildMetrics(files),
|
|
217
|
+
contextBudget: input.contextBudget,
|
|
218
|
+
fileContextBudget: input.fileContextBudget,
|
|
219
|
+
};
|
|
220
|
+
}
|
|
221
|
+
//# sourceMappingURL=repo-context.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"repo-context.js","sourceRoot":"","sources":["../src/repo-context.ts"],"names":[],"mappings":"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"}
|
package/dist/report.d.ts
ADDED
|
@@ -0,0 +1,87 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Markdown and JSON report generation for PromptCI scan results.
|
|
3
|
+
*/
|
|
4
|
+
import type { ScanReport, ScanTrend } from './types.js';
|
|
5
|
+
export type WriteReportOptions = {
|
|
6
|
+
/** Override path for the markdown report (default: <repoPath>/.promptci/latest.md) */
|
|
7
|
+
mdPath?: string;
|
|
8
|
+
/** Override path for the JSON report (default: <repoPath>/.promptci/report.json) */
|
|
9
|
+
jsonPath?: string;
|
|
10
|
+
/**
|
|
11
|
+
* If false, skip archiving the previous report before overwriting.
|
|
12
|
+
* Defaults to true. Set to false when writing to custom paths.
|
|
13
|
+
*/
|
|
14
|
+
archive?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* One entry in the history index — a compact summary of a single past scan.
|
|
18
|
+
* Stored in .promptci/history/index.json as an append-only array.
|
|
19
|
+
*/
|
|
20
|
+
export type HistoryEntry = {
|
|
21
|
+
/** ISO-8601 timestamp of when the scan was run. */
|
|
22
|
+
generatedAt: string;
|
|
23
|
+
/** Health score at time of scan (0–100). */
|
|
24
|
+
healthScore: number;
|
|
25
|
+
/** Issue counts by severity. */
|
|
26
|
+
issueCount: {
|
|
27
|
+
critical: number;
|
|
28
|
+
high: number;
|
|
29
|
+
warning: number;
|
|
30
|
+
info: number;
|
|
31
|
+
};
|
|
32
|
+
/** Path to the archived markdown report, relative to the repo root. */
|
|
33
|
+
archiveMdPath: string;
|
|
34
|
+
/** Path to the archived JSON report, relative to the repo root. */
|
|
35
|
+
archiveJsonPath: string;
|
|
36
|
+
};
|
|
37
|
+
/**
|
|
38
|
+
* Generate a Markdown-formatted scan report.
|
|
39
|
+
*/
|
|
40
|
+
export declare function generateMarkdownReport(report: ScanReport): string;
|
|
41
|
+
/**
|
|
42
|
+
* Serialize a ScanReport to JSON (schema v0.1).
|
|
43
|
+
*
|
|
44
|
+
* All file paths are repo-relative so reports are portable — the absolute
|
|
45
|
+
* repo root is preserved as `repoPath` so callers can reconstruct full paths.
|
|
46
|
+
* Verbose section content is excluded from filesScanned to keep output compact.
|
|
47
|
+
*/
|
|
48
|
+
export declare function generateJsonReport(report: ScanReport, pretty?: boolean): string;
|
|
49
|
+
/** Path to the history index file for a given repo. */
|
|
50
|
+
export declare function historyIndexPath(repoPath: string): string;
|
|
51
|
+
/**
|
|
52
|
+
* Read the history index for a repo, returning an empty array if it doesn't
|
|
53
|
+
* exist yet or cannot be parsed.
|
|
54
|
+
*/
|
|
55
|
+
export declare function readHistoryIndex(repoPath: string): Promise<HistoryEntry[]>;
|
|
56
|
+
/**
|
|
57
|
+
* Archive the current latest.md and report.json (if they exist) into
|
|
58
|
+
* .promptci/history/<slug>/ and append a compact entry to the history index.
|
|
59
|
+
*
|
|
60
|
+
* The slug is derived from the report's generatedAt timestamp so archives are
|
|
61
|
+
* human-readable on disk. Returns the new HistoryEntry, or null if there was
|
|
62
|
+
* nothing to archive.
|
|
63
|
+
*/
|
|
64
|
+
export declare function archiveExistingReport(repoPath: string, latestMdPath: string, latestJsonPath: string): Promise<HistoryEntry | null>;
|
|
65
|
+
/**
|
|
66
|
+
* Write markdown and JSON reports to disk.
|
|
67
|
+
*
|
|
68
|
+
* Default output paths (relative to the repo root):
|
|
69
|
+
* .promptci/latest.md
|
|
70
|
+
* .promptci/report.json
|
|
71
|
+
*
|
|
72
|
+
* Before overwriting, the previous reports are archived to:
|
|
73
|
+
* .promptci/history/<timestamp>/report.md
|
|
74
|
+
* .promptci/history/<timestamp>/report.json
|
|
75
|
+
*
|
|
76
|
+
* A compact history index is maintained at:
|
|
77
|
+
* .promptci/history/index.json
|
|
78
|
+
*
|
|
79
|
+
* The .promptci/ directory is created if it does not exist.
|
|
80
|
+
*/
|
|
81
|
+
export declare function writeReport(report: ScanReport, options?: WriteReportOptions): Promise<{
|
|
82
|
+
mdPath: string;
|
|
83
|
+
jsonPath: string;
|
|
84
|
+
archivedEntry: HistoryEntry | null;
|
|
85
|
+
}>;
|
|
86
|
+
export declare function computeTrend(report: ScanReport, previousReport: Record<string, unknown> | null, history: HistoryEntry[]): Promise<ScanTrend | null>;
|
|
87
|
+
//# sourceMappingURL=report.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"report.d.ts","sourceRoot":"","sources":["../src/report.ts"],"names":[],"mappings":"AAAA;;GAEG;AAKH,OAAO,KAAK,EAAgC,UAAU,EAAkB,SAAS,EAAE,MAAM,YAAY,CAAC;AAGtG,MAAM,MAAM,kBAAkB,GAAG;IAC/B,sFAAsF;IACtF,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,oFAAoF;IACpF,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB;;;OAGG;IACH,OAAO,CAAC,EAAE,OAAO,CAAC;CACnB,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,YAAY,GAAG;IACzB,mDAAmD;IACnD,WAAW,EAAE,MAAM,CAAC;IACpB,4CAA4C;IAC5C,WAAW,EAAE,MAAM,CAAC;IACpB,gCAAgC;IAChC,UAAU,EAAE;QACV,QAAQ,EAAE,MAAM,CAAC;QACjB,IAAI,EAAE,MAAM,CAAC;QACb,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,uEAAuE;IACvE,aAAa,EAAE,MAAM,CAAC;IACtB,mEAAmE;IACnE,eAAe,EAAE,MAAM,CAAC;CACzB,CAAC;AA0KF;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,UAAU,GAAG,MAAM,CAsJjE;AAED;;;;;;GAMG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,UAAU,EAAE,MAAM,UAAO,GAAG,MAAM,CA4C5E;AAID,uDAAuD;AACvD,wBAAgB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAEzD;AAED;;;GAGG;AACH,wBAAsB,gBAAgB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,YAAY,EAAE,CAAC,CAUhF;AAED;;;;;;;GAOG;AACH,wBAAsB,qBAAqB,CACzC,QAAQ,EAAE,MAAM,EAChB,YAAY,EAAE,MAAM,EACpB,cAAc,EAAE,MAAM,GACrB,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC,CA6D9B;AAID;;;;;;;;;;;;;;;GAeG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,UAAU,EAClB,OAAO,GAAE,kBAAuB,GAC/B,OAAO,CAAC;IAAE,MAAM,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,YAAY,GAAG,IAAI,CAAA;CAAE,CAAC,CA4BnF;AAWD,wBAAsB,YAAY,CAChC,MAAM,EAAE,UAAU,EAClB,cAAc,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI,EAC9C,OAAO,EAAE,YAAY,EAAE,GACtB,OAAO,CAAC,SAAS,GAAG,IAAI,CAAC,CAqF3B"}
|