@promptci/core 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (179) hide show
  1. package/LICENSE +201 -0
  2. package/README.md +30 -0
  3. package/dist/agent-practices.d.ts +22 -0
  4. package/dist/agent-practices.d.ts.map +1 -0
  5. package/dist/agent-practices.js +582 -0
  6. package/dist/agent-practices.js.map +1 -0
  7. package/dist/baseline.d.ts +40 -0
  8. package/dist/baseline.d.ts.map +1 -0
  9. package/dist/baseline.js +172 -0
  10. package/dist/baseline.js.map +1 -0
  11. package/dist/canonical-owner.d.ts +3 -0
  12. package/dist/canonical-owner.d.ts.map +1 -0
  13. package/dist/canonical-owner.js +131 -0
  14. package/dist/canonical-owner.js.map +1 -0
  15. package/dist/cheap-model-routing.d.ts +4 -0
  16. package/dist/cheap-model-routing.d.ts.map +1 -0
  17. package/dist/cheap-model-routing.js +43 -0
  18. package/dist/cheap-model-routing.js.map +1 -0
  19. package/dist/ci-alignment.d.ts +10 -0
  20. package/dist/ci-alignment.d.ts.map +1 -0
  21. package/dist/ci-alignment.js +343 -0
  22. package/dist/ci-alignment.js.map +1 -0
  23. package/dist/cli-output-filter.d.ts +16 -0
  24. package/dist/cli-output-filter.d.ts.map +1 -0
  25. package/dist/cli-output-filter.js +88 -0
  26. package/dist/cli-output-filter.js.map +1 -0
  27. package/dist/command-validity.d.ts +12 -0
  28. package/dist/command-validity.d.ts.map +1 -0
  29. package/dist/command-validity.js +543 -0
  30. package/dist/command-validity.js.map +1 -0
  31. package/dist/conflicts.d.ts +49 -0
  32. package/dist/conflicts.d.ts.map +1 -0
  33. package/dist/conflicts.js +1065 -0
  34. package/dist/conflicts.js.map +1 -0
  35. package/dist/context-analysis.d.ts +15 -0
  36. package/dist/context-analysis.d.ts.map +1 -0
  37. package/dist/context-analysis.js +24 -0
  38. package/dist/context-analysis.js.map +1 -0
  39. package/dist/context-bloat.d.ts +17 -0
  40. package/dist/context-bloat.d.ts.map +1 -0
  41. package/dist/context-bloat.js +148 -0
  42. package/dist/context-bloat.js.map +1 -0
  43. package/dist/context-cost.d.ts +4 -0
  44. package/dist/context-cost.d.ts.map +1 -0
  45. package/dist/context-cost.js +70 -0
  46. package/dist/context-cost.js.map +1 -0
  47. package/dist/context-optimizer.d.ts +14 -0
  48. package/dist/context-optimizer.d.ts.map +1 -0
  49. package/dist/context-optimizer.js +219 -0
  50. package/dist/context-optimizer.js.map +1 -0
  51. package/dist/context-recommender.d.ts +3 -0
  52. package/dist/context-recommender.d.ts.map +1 -0
  53. package/dist/context-recommender.js +329 -0
  54. package/dist/context-recommender.js.map +1 -0
  55. package/dist/dead-references.d.ts +33 -0
  56. package/dist/dead-references.d.ts.map +1 -0
  57. package/dist/dead-references.js +607 -0
  58. package/dist/dead-references.js.map +1 -0
  59. package/dist/detectors.d.ts +11 -0
  60. package/dist/detectors.d.ts.map +1 -0
  61. package/dist/detectors.js +160 -0
  62. package/dist/detectors.js.map +1 -0
  63. package/dist/duplicates.d.ts +36 -0
  64. package/dist/duplicates.d.ts.map +1 -0
  65. package/dist/duplicates.js +436 -0
  66. package/dist/duplicates.js.map +1 -0
  67. package/dist/fix-engine.d.ts +16 -0
  68. package/dist/fix-engine.d.ts.map +1 -0
  69. package/dist/fix-engine.js +179 -0
  70. package/dist/fix-engine.js.map +1 -0
  71. package/dist/framework-packs.d.ts +8 -0
  72. package/dist/framework-packs.d.ts.map +1 -0
  73. package/dist/framework-packs.js +22 -0
  74. package/dist/framework-packs.js.map +1 -0
  75. package/dist/frameworks/dotnet.d.ts +4 -0
  76. package/dist/frameworks/dotnet.d.ts.map +1 -0
  77. package/dist/frameworks/dotnet.js +77 -0
  78. package/dist/frameworks/dotnet.js.map +1 -0
  79. package/dist/frameworks/go.d.ts +4 -0
  80. package/dist/frameworks/go.d.ts.map +1 -0
  81. package/dist/frameworks/go.js +39 -0
  82. package/dist/frameworks/go.js.map +1 -0
  83. package/dist/frameworks/nextjs.d.ts +4 -0
  84. package/dist/frameworks/nextjs.d.ts.map +1 -0
  85. package/dist/frameworks/nextjs.js +66 -0
  86. package/dist/frameworks/nextjs.js.map +1 -0
  87. package/dist/frameworks/python.d.ts +4 -0
  88. package/dist/frameworks/python.d.ts.map +1 -0
  89. package/dist/frameworks/python.js +66 -0
  90. package/dist/frameworks/python.js.map +1 -0
  91. package/dist/frameworks/rust.d.ts +4 -0
  92. package/dist/frameworks/rust.d.ts.map +1 -0
  93. package/dist/frameworks/rust.js +72 -0
  94. package/dist/frameworks/rust.js.map +1 -0
  95. package/dist/frameworks/unity.d.ts +4 -0
  96. package/dist/frameworks/unity.d.ts.map +1 -0
  97. package/dist/frameworks/unity.js +74 -0
  98. package/dist/frameworks/unity.js.map +1 -0
  99. package/dist/health-score.d.ts +37 -0
  100. package/dist/health-score.d.ts.map +1 -0
  101. package/dist/health-score.js +164 -0
  102. package/dist/health-score.js.map +1 -0
  103. package/dist/index.d.ts +31 -0
  104. package/dist/index.d.ts.map +1 -0
  105. package/dist/index.js +23 -0
  106. package/dist/index.js.map +1 -0
  107. package/dist/llm.d.ts +6 -0
  108. package/dist/llm.d.ts.map +1 -0
  109. package/dist/llm.js +67 -0
  110. package/dist/llm.js.map +1 -0
  111. package/dist/manifest-consistency.d.ts +37 -0
  112. package/dist/manifest-consistency.d.ts.map +1 -0
  113. package/dist/manifest-consistency.js +659 -0
  114. package/dist/manifest-consistency.js.map +1 -0
  115. package/dist/mcp-detector.d.ts +4 -0
  116. package/dist/mcp-detector.d.ts.map +1 -0
  117. package/dist/mcp-detector.js +131 -0
  118. package/dist/mcp-detector.js.map +1 -0
  119. package/dist/missing-context.d.ts +15 -0
  120. package/dist/missing-context.d.ts.map +1 -0
  121. package/dist/missing-context.js +517 -0
  122. package/dist/missing-context.js.map +1 -0
  123. package/dist/native-tool-preference.d.ts +20 -0
  124. package/dist/native-tool-preference.d.ts.map +1 -0
  125. package/dist/native-tool-preference.js +94 -0
  126. package/dist/native-tool-preference.js.map +1 -0
  127. package/dist/output-verbosity.d.ts +3 -0
  128. package/dist/output-verbosity.d.ts.map +1 -0
  129. package/dist/output-verbosity.js +83 -0
  130. package/dist/output-verbosity.js.map +1 -0
  131. package/dist/product-boundary.d.ts +11 -0
  132. package/dist/product-boundary.d.ts.map +1 -0
  133. package/dist/product-boundary.js +301 -0
  134. package/dist/product-boundary.js.map +1 -0
  135. package/dist/project-type.d.ts +15 -0
  136. package/dist/project-type.d.ts.map +1 -0
  137. package/dist/project-type.js +116 -0
  138. package/dist/project-type.js.map +1 -0
  139. package/dist/prompt-cache.d.ts +3 -0
  140. package/dist/prompt-cache.d.ts.map +1 -0
  141. package/dist/prompt-cache.js +151 -0
  142. package/dist/prompt-cache.js.map +1 -0
  143. package/dist/repo-context.d.ts +37 -0
  144. package/dist/repo-context.d.ts.map +1 -0
  145. package/dist/repo-context.js +221 -0
  146. package/dist/repo-context.js.map +1 -0
  147. package/dist/report.d.ts +87 -0
  148. package/dist/report.d.ts.map +1 -0
  149. package/dist/report.js +558 -0
  150. package/dist/report.js.map +1 -0
  151. package/dist/scan.d.ts +7 -0
  152. package/dist/scan.d.ts.map +1 -0
  153. package/dist/scan.js +43 -0
  154. package/dist/scan.js.map +1 -0
  155. package/dist/scanner.d.ts +3 -0
  156. package/dist/scanner.d.ts.map +1 -0
  157. package/dist/scanner.js +216 -0
  158. package/dist/scanner.js.map +1 -0
  159. package/dist/security-pack.d.ts +4 -0
  160. package/dist/security-pack.d.ts.map +1 -0
  161. package/dist/security-pack.js +403 -0
  162. package/dist/security-pack.js.map +1 -0
  163. package/dist/stale-instructions.d.ts +20 -0
  164. package/dist/stale-instructions.d.ts.map +1 -0
  165. package/dist/stale-instructions.js +269 -0
  166. package/dist/stale-instructions.js.map +1 -0
  167. package/dist/suppression.d.ts +64 -0
  168. package/dist/suppression.d.ts.map +1 -0
  169. package/dist/suppression.js +338 -0
  170. package/dist/suppression.js.map +1 -0
  171. package/dist/types.d.ts +128 -0
  172. package/dist/types.d.ts.map +1 -0
  173. package/dist/types.js +3 -0
  174. package/dist/types.js.map +1 -0
  175. package/dist/vague-guidance.d.ts +12 -0
  176. package/dist/vague-guidance.d.ts.map +1 -0
  177. package/dist/vague-guidance.js +235 -0
  178. package/dist/vague-guidance.js.map +1 -0
  179. package/package.json +54 -0
@@ -0,0 +1,216 @@
1
+ import fg from 'fast-glob';
2
+ import * as fs from 'node:fs/promises';
3
+ import * as path from 'node:path';
4
+ const DEFAULT_PATTERNS = [
5
+ // Core AI instruction files
6
+ 'CLAUDE.md',
7
+ 'AGENTS.md',
8
+ '.cursorrules',
9
+ '.windsurfrules',
10
+ // Cursor IDE rules
11
+ '.cursor/rules/**',
12
+ // GitHub Copilot instructions (legacy + new per-file format)
13
+ '.github/copilot-instructions.md',
14
+ '.github/instructions/**/*.md',
15
+ // Claude memory / settings directory
16
+ '.claude/**/*.md',
17
+ // README is often the only context file in small repos
18
+ 'README.md',
19
+ // BUG-I1: Additional root-level instruction files that agents commonly read.
20
+ // Explicit names only — keeps the set narrow enough to avoid scanning docs/
21
+ // but broad enough to catch QA.md, CONTRIBUTING.md, and similar convention files.
22
+ 'QA.md',
23
+ 'CONTRIBUTING.md',
24
+ 'ARCHITECTURE.md',
25
+ 'DEVELOPMENT.md',
26
+ 'CODING_STANDARDS.md',
27
+ 'CONVENTIONS.md',
28
+ 'GUIDELINES.md',
29
+ // Explicit AI/prompt directories only — not generic docs/
30
+ 'ai/**/*.md',
31
+ 'ai-instructions/**/*.md',
32
+ 'prompts/**/*.md',
33
+ 'system-prompts/**/*.md',
34
+ ];
35
+ // NOTE: docs/**/*.md is intentionally excluded — docs directories typically
36
+ // contain project documentation (QA reports, plans, guides) that are not AI
37
+ // instruction files and cause false positive context-bloat and conflict findings.
38
+ // 'worktrees'/'.worktrees' covers git worktree checkouts nested anywhere in the
39
+ // tree (e.g. Claude Code's .claude/worktrees/<name>/, or a top-level worktrees/
40
+ // dir used by other agent tooling) — these are full copies of the repo and
41
+ // would otherwise be scanned as duplicate instruction-file trees.
42
+ const IGNORE_DIRS = ['.git', 'node_modules', 'Library', 'Temp', 'bin', 'obj', 'dist', 'build', 'worktrees', '.worktrees'];
43
+ const MAX_FILE_SIZE = 500 * 1024;
44
+ const BINARY_CHECK_BYTES = 512;
45
+ function deriveFileType(absPath) {
46
+ const base = path.basename(absPath);
47
+ const norm = absPath.replace(/\\/g, '/');
48
+ if (base === 'AGENTS.md')
49
+ return 'agents';
50
+ if (base === '.cursorrules' || norm.includes('/.cursor/rules/'))
51
+ return 'cursor';
52
+ if (base === 'copilot-instructions.md' || norm.includes('/.github/instructions/'))
53
+ return 'copilot';
54
+ if (base === 'CLAUDE.md' || norm.includes('/.claude/'))
55
+ return 'claude';
56
+ if (base === 'README.md')
57
+ return 'readme';
58
+ if (norm.includes('/docs/') && base.endsWith('.md'))
59
+ return 'docs';
60
+ if ((norm.includes('/ai/') || norm.includes('/prompts/')) && base.endsWith('.md'))
61
+ return 'prompt';
62
+ return 'unknown';
63
+ }
64
+ function slugify(text) {
65
+ return text
66
+ .toLowerCase()
67
+ .replace(/[^\w\s-]/g, '')
68
+ .replace(/[\s_]+/g, '-')
69
+ .replace(/^-+|-+$/g, '');
70
+ }
71
+ // `content.split('\n')` produces a phantom trailing empty element whenever the
72
+ // file ends with a newline (the common case). Drop it so line counts/endLine
73
+ // values refer to real lines, not one past EOF.
74
+ function splitLines(content) {
75
+ const rawLines = content.split('\n');
76
+ if (content.length > 0 && content.endsWith('\n')) {
77
+ rawLines.pop();
78
+ }
79
+ return rawLines;
80
+ }
81
+ function parseSections(content, filePath) {
82
+ const lines = splitLines(content);
83
+ const sections = [];
84
+ let currentHeading = undefined;
85
+ let currentStartLine = 1;
86
+ let currentLines = [];
87
+ const flush = (endLine) => {
88
+ const text = currentLines.join('\n');
89
+ const id = currentHeading !== undefined ? slugify(currentHeading) : `${filePath}:0`;
90
+ sections.push({
91
+ id,
92
+ filePath,
93
+ heading: currentHeading,
94
+ startLine: currentStartLine,
95
+ endLine,
96
+ text,
97
+ normalizedText: text.toLowerCase().trim(),
98
+ });
99
+ };
100
+ let inCodeBlock = false;
101
+ let fenceChar = null;
102
+ let fenceLen = 0;
103
+ for (let i = 0; i < lines.length; i++) {
104
+ const lineNum = i + 1;
105
+ const line = lines[i] ?? '';
106
+ // Track fenced code blocks so bash comments (`# text`) are not treated as
107
+ // headings. A closing fence must use the same fence character (``` vs ~~~
108
+ // are not interchangeable) and be at least as long as the opening fence,
109
+ // per CommonMark. Up to 3 leading spaces are allowed on either fence.
110
+ if (!inCodeBlock) {
111
+ const openMatch = /^ {0,3}([`~]{3,})/.exec(line);
112
+ if (openMatch) {
113
+ inCodeBlock = true;
114
+ fenceChar = openMatch[1][0] ?? null;
115
+ fenceLen = openMatch[1].length;
116
+ currentLines.push(line);
117
+ continue;
118
+ }
119
+ }
120
+ else {
121
+ const closeMatch = /^ {0,3}([`~]{3,})\s*$/.exec(line);
122
+ if (closeMatch && closeMatch[1][0] === fenceChar && closeMatch[1].length >= fenceLen) {
123
+ inCodeBlock = false;
124
+ fenceChar = null;
125
+ fenceLen = 0;
126
+ currentLines.push(line);
127
+ continue;
128
+ }
129
+ currentLines.push(line);
130
+ continue;
131
+ }
132
+ const headingMatch = /^ {0,3}(#{1,3})\s+(.+)/.exec(line);
133
+ if (headingMatch) {
134
+ if (currentLines.length > 0 || currentHeading !== undefined) {
135
+ flush(lineNum - 1);
136
+ }
137
+ currentHeading = headingMatch[2].trim();
138
+ currentStartLine = lineNum;
139
+ currentLines = [line];
140
+ }
141
+ else {
142
+ currentLines.push(line);
143
+ }
144
+ }
145
+ if (currentLines.length > 0 || currentHeading !== undefined) {
146
+ flush(lines.length);
147
+ }
148
+ return sections;
149
+ }
150
+ function isBinary(buffer) {
151
+ const end = Math.min(buffer.length, BINARY_CHECK_BYTES);
152
+ for (let i = 0; i < end; i++) {
153
+ if (buffer[i] === 0)
154
+ return true;
155
+ }
156
+ return false;
157
+ }
158
+ export async function scanFiles(input) {
159
+ const repoRoot = path.resolve(input.repoPath);
160
+ const patterns = (input.include && input.include.length > 0) ? input.include : DEFAULT_PATTERNS;
161
+ const ignorePatterns = [
162
+ ...IGNORE_DIRS.map((d) => `**/${d}/**`),
163
+ ...(input.exclude ?? []),
164
+ ];
165
+ let relativePaths;
166
+ try {
167
+ relativePaths = await fg(patterns, {
168
+ cwd: repoRoot,
169
+ ignore: ignorePatterns,
170
+ dot: true,
171
+ absolute: false,
172
+ followSymbolicLinks: false,
173
+ });
174
+ }
175
+ catch {
176
+ return [];
177
+ }
178
+ const results = [];
179
+ for (const relPath of relativePaths) {
180
+ const absPath = path.resolve(repoRoot, relPath);
181
+ // Path traversal guard
182
+ const relative = path.relative(repoRoot, absPath);
183
+ if (relative.startsWith('..') || path.isAbsolute(relative)) {
184
+ continue;
185
+ }
186
+ try {
187
+ const stat = await fs.stat(absPath);
188
+ if (!stat.isFile())
189
+ continue;
190
+ if (stat.size > MAX_FILE_SIZE)
191
+ continue;
192
+ const buffer = await fs.readFile(absPath);
193
+ if (isBinary(buffer))
194
+ continue;
195
+ const content = buffer.toString('utf-8');
196
+ const sections = parseSections(content, absPath);
197
+ const lineCount = splitLines(content).length;
198
+ const charCount = content.length;
199
+ results.push({
200
+ path: absPath,
201
+ fileType: deriveFileType(absPath),
202
+ content,
203
+ sections,
204
+ lineCount,
205
+ charCount,
206
+ estimatedTokens: Math.round(charCount / 4),
207
+ });
208
+ }
209
+ catch {
210
+ // skip unreadable files
211
+ }
212
+ }
213
+ results.sort((a, b) => a.path.localeCompare(b.path));
214
+ return results;
215
+ }
216
+ //# sourceMappingURL=scanner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"scanner.js","sourceRoot":"","sources":["../src/scanner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { PromptCiIssue } from './types.js';
2
+ import type { RepoContext } from './repo-context.js';
3
+ export declare function detectSecurityPack(context: RepoContext): PromptCiIssue[];
4
+ //# sourceMappingURL=security-pack.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-pack.d.ts","sourceRoot":"","sources":["../src/security-pack.ts"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAChD,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAyJrD,wBAAgB,kBAAkB,CAAC,OAAO,EAAE,WAAW,GAAG,aAAa,EAAE,CA6SxE"}
@@ -0,0 +1,403 @@
1
+ import * as crypto from 'node:crypto';
2
+ import * as path from 'node:path';
3
+ import * as fs from 'node:fs';
4
+ const SECURITY_CHECKS = [
5
+ {
6
+ id: 'no-secret-safeguard',
7
+ title: 'Missing secret safeguard instruction',
8
+ summary: 'Environment variables are used in this repository, but no instruction found ' +
9
+ 'warning the agent never to print or commit secrets.',
10
+ patterns: [
11
+ /never\s+.*(print|commit|log|expose)\s+.*(secret|password|token|key|credential)/i,
12
+ /do\s+not\s+.*(print|commit|log|expose)\s+.*(secret|password|token|key|credential)/i,
13
+ /secrets?\s+must\s+never\s+be/i,
14
+ /keep\s+secrets?\s+secure/i,
15
+ ],
16
+ recommendation: 'Add a rule such as: "Never print or commit secrets, API keys, or credentials. ' +
17
+ 'If you need to use an environment variable, use it silently without echoing its value."',
18
+ severity: 'warning',
19
+ confidence: 0.8,
20
+ fixRecipe: 'Never print or commit secrets, API keys, or credentials. If you need to use an environment variable, use it silently without echoing its value.',
21
+ },
22
+ {
23
+ id: 'no-supabase-service-role-rule',
24
+ title: 'Missing Supabase service role safeguard',
25
+ summary: 'Supabase is used in this repository, but no instruction found warning that ' +
26
+ 'the service role key must only be used server-side.',
27
+ patterns: [
28
+ /service\s+role\s+key\s+must\s+(stay|only\s+be\s+used)\s+server-side/i,
29
+ /never\s+expose\s+supabase\s+service\s+role/i,
30
+ /supabase\s+service\s+role\s+key.*server-side/i,
31
+ ],
32
+ recommendation: 'Add a rule such as: "The Supabase service role key must stay server-side and never be exposed to the client."',
33
+ severity: 'warning',
34
+ confidence: 0.85,
35
+ fixRecipe: 'Keep SUPABASE_SERVICE_ROLE_KEY server-side only. Never expose it in browser code, logs, or committed files.',
36
+ },
37
+ {
38
+ id: 'no-upload-boundary-docs',
39
+ title: 'Missing data boundary documentation for uploads',
40
+ summary: 'Upload features detected, but no instruction found defining data boundaries ' +
41
+ 'or validation requirements for user-provided files.',
42
+ patterns: [
43
+ /validate\s+user\s+(provided|uploaded)\s+files/i,
44
+ /data\s+boundary\s+for\s+uploads/i,
45
+ /upload\s+validation/i,
46
+ /limit\s+upload\s+size/i,
47
+ ],
48
+ recommendation: 'Add guidance on how to safely handle and validate user uploads to prevent security risks.',
49
+ severity: 'info',
50
+ confidence: 0.7,
51
+ fixRecipe: 'Before handling user uploads, document what file types are allowed, the max file size, and the sanitization steps required.',
52
+ },
53
+ {
54
+ id: 'no-promptci-report-safeguard',
55
+ title: 'Missing safeguard for .promptci/ reports',
56
+ summary: '.promptci/ folder exists, but no instruction found warning the agent ' +
57
+ 'not to commit generated reports to the repository.',
58
+ patterns: [
59
+ /do\s+not\s+commit\s+\.promptci/i,
60
+ /never\s+commit\s+\.promptci/i,
61
+ /\.promptci\/\s+reports\s+should\s+not\s+be\s+committed/i,
62
+ ],
63
+ recommendation: 'Add a rule such as: "Do not commit .promptci/ reports to the repository."',
64
+ severity: 'info',
65
+ confidence: 0.8,
66
+ fixRecipe: 'Do not commit .promptci/ reports to the repository.',
67
+ },
68
+ ];
69
+ const DESTRUCTIVE_COMMANDS = [
70
+ {
71
+ // SP2: no longer requires TRAILING whitespace — `rm\s+-rf\s+` missed
72
+ // "...never run rm -rf" (end of sentence) and backticked "`rm -rf`" (end
73
+ // of span, followed by a backtick, not whitespace). `\b` handles both.
74
+ // Also covers the equivalent flag order `rm -fr`.
75
+ pattern: /\brm\s+-(?:rf|fr)\b/i,
76
+ name: 'rm -rf',
77
+ },
78
+ {
79
+ pattern: /drop\s+table/i,
80
+ name: 'drop table',
81
+ },
82
+ {
83
+ pattern: /git\s+push\s+--force/i,
84
+ name: 'git push --force',
85
+ },
86
+ ];
87
+ function issueId(checkId) {
88
+ const hash = crypto.createHash('sha1').update(checkId).digest('hex').slice(0, 12);
89
+ return `security-pack-${hash}`;
90
+ }
91
+ function destructiveCommandIssueId(filePath, command) {
92
+ const hash = crypto.createHash('sha1').update(`destructive-command:${filePath}:${command}`).digest('hex').slice(0, 12);
93
+ return `destructive-command-${hash}`;
94
+ }
95
+ /** SP1 / B3: per-FILE id — see call site for why this replaced a constant id. */
96
+ function inspectReportsFirstIssueId(filePath) {
97
+ const hash = crypto.createHash('sha1').update(`inspect-reports-first:${filePath}`).digest('hex').slice(0, 12);
98
+ return `security-pack-inspect-reports-first-${hash}`;
99
+ }
100
+ function matchesAny(text, patterns) {
101
+ return patterns.some((p) => p.test(text));
102
+ }
103
+ /**
104
+ * SP3: does this .gitignore LINE actually ignore `target` (a bare directory
105
+ * or dotfile name, no slashes)?
106
+ *
107
+ * Old behavior used `clean.includes(target)` as a catch-all fallback, which
108
+ * was wrong two ways:
109
+ * 1. A NEGATION line ("!.promptci/") re-includes a path (un-ignores it) in
110
+ * gitignore syntax, but `"!.promptci".includes(".promptci")` is true, so
111
+ * the negation was misread as "yes, this is ignored".
112
+ * 2. Substring matching let an unrelated entry satisfy the check —
113
+ * "distribution.md".includes("dist") and "builds-notes/".includes("build")
114
+ * are both true, so those unrelated lines were misread as ignoring
115
+ * "dist"/"build", masking a real unignored-directory finding (FN).
116
+ *
117
+ * Fixed by rejecting negation lines outright, then requiring an EXACT path
118
+ * SEGMENT match (splitting on '/' so a leading globstar segment doesn't
119
+ * block the match, but a differently-named file/dir never accidentally
120
+ * satisfies it).
121
+ */
122
+ function gitignoreLineMatchesTarget(line, target) {
123
+ if (line.startsWith('!'))
124
+ return false;
125
+ const clean = line.replace(/^\/+|\/+$/g, '');
126
+ const segments = clean.split('/');
127
+ return segments.includes(target);
128
+ }
129
+ export function detectSecurityPack(context) {
130
+ const { files, repoRoot } = context;
131
+ if (files.length === 0)
132
+ return [];
133
+ const issues = [];
134
+ const combinedContent = files.map((f) => f.content).join('\n');
135
+ const allFilePaths = files.map((f) => f.path);
136
+ // 1. Secret Safeguard Signal
137
+ const envFiles = ['.env', '.env.example', '.env.local', '.env.development', '.env.production'];
138
+ const hasEnvVars = envFiles.some(f => fs.existsSync(path.join(/*turbopackIgnore: true*/ repoRoot, f))) ||
139
+ context.files.some(f => /env\s+vars|environment\s+variables/i.test(f.content));
140
+ if (hasEnvVars) {
141
+ const check = SECURITY_CHECKS.find(c => c.id === 'no-secret-safeguard');
142
+ if (!matchesAny(combinedContent, check.patterns)) {
143
+ issues.push({
144
+ id: issueId(check.id),
145
+ severity: check.severity,
146
+ category: 'security',
147
+ title: check.title,
148
+ summary: check.summary,
149
+ filePaths: allFilePaths,
150
+ locations: [],
151
+ evidence: ['Environment variables detected but no safeguard instruction found.'],
152
+ recommendation: check.recommendation,
153
+ fixRecipe: check.fixRecipe,
154
+ confidence: check.confidence,
155
+ });
156
+ }
157
+ }
158
+ // 2. Supabase Signal
159
+ const supabaseDeps = {
160
+ ...context.packageJson.dependencies,
161
+ ...context.packageJson.devDependencies,
162
+ ...context.packageJson.peerDependencies,
163
+ };
164
+ const hasSupabase = fs.existsSync(path.join(/*turbopackIgnore: true*/ repoRoot, 'supabase/migrations')) ||
165
+ Object.keys(supabaseDeps).some((dep) => dep === '@supabase/supabase-js' || dep.startsWith('@supabase/'));
166
+ if (hasSupabase) {
167
+ const check = SECURITY_CHECKS.find(c => c.id === 'no-supabase-service-role-rule');
168
+ if (!matchesAny(combinedContent, check.patterns)) {
169
+ issues.push({
170
+ id: issueId(check.id),
171
+ severity: check.severity,
172
+ category: 'security',
173
+ title: check.title,
174
+ summary: check.summary,
175
+ filePaths: allFilePaths,
176
+ locations: [],
177
+ evidence: ['Supabase detected but no service role safeguard instruction found.'],
178
+ recommendation: check.recommendation,
179
+ fixRecipe: check.fixRecipe,
180
+ confidence: check.confidence,
181
+ });
182
+ }
183
+ }
184
+ // 3. Upload Signal
185
+ // Basic heuristic: look for common upload-related paths or keywords in file paths
186
+ // SP4: normalize backslashes first — on win32, f.path uses `\`, so a bare
187
+ // `/api/upload` substring check never matched an absolute Windows path.
188
+ const hasUploadFeatures = context.files.some(f => {
189
+ const normalizedPath = f.path.replace(/\\/g, '/');
190
+ return (normalizedPath.includes('/api/upload') ||
191
+ normalizedPath.includes('/uploads/') ||
192
+ /multer|busboy|formidable/i.test(f.content));
193
+ });
194
+ if (hasUploadFeatures) {
195
+ const check = SECURITY_CHECKS.find(c => c.id === 'no-upload-boundary-docs');
196
+ if (!matchesAny(combinedContent, check.patterns)) {
197
+ issues.push({
198
+ id: issueId(check.id),
199
+ severity: check.severity,
200
+ category: 'security',
201
+ title: check.title,
202
+ summary: check.summary,
203
+ filePaths: allFilePaths,
204
+ locations: [],
205
+ evidence: ['Upload features detected but no data boundary documentation found.'],
206
+ recommendation: check.recommendation,
207
+ fixRecipe: check.fixRecipe,
208
+ confidence: check.confidence,
209
+ });
210
+ }
211
+ }
212
+ // 4. .promptci/ Signal
213
+ const hasPromptCiFolder = fs.existsSync(path.join(/*turbopackIgnore: true*/ repoRoot, '.promptci'));
214
+ if (hasPromptCiFolder) {
215
+ const check = SECURITY_CHECKS.find(c => c.id === 'no-promptci-report-safeguard');
216
+ if (!matchesAny(combinedContent, check.patterns)) {
217
+ issues.push({
218
+ id: issueId(check.id),
219
+ severity: check.severity,
220
+ category: 'security',
221
+ title: check.title,
222
+ summary: check.summary,
223
+ filePaths: allFilePaths,
224
+ locations: [],
225
+ evidence: ['.promptci/ folder detected but no report safeguard instruction found.'],
226
+ recommendation: check.recommendation,
227
+ fixRecipe: check.fixRecipe,
228
+ confidence: check.confidence,
229
+ });
230
+ }
231
+ }
232
+ // 5. Destructive Commands in instructions
233
+ for (const file of files) {
234
+ for (const cmd of DESTRUCTIVE_COMMANDS) {
235
+ if (cmd.pattern.test(file.content)) {
236
+ // Check if there is safety language nearby or in the same file
237
+ const safetyPatterns = [
238
+ /ask\s+(before|for\s+approval)/i,
239
+ /confirm\s+before/i,
240
+ /be\s+careful\s+with/i,
241
+ /destructive\s+operation/i,
242
+ /\bdanger(?:ous)?\b/i,
243
+ ];
244
+ if (!matchesAny(file.content, safetyPatterns)) {
245
+ issues.push({
246
+ id: destructiveCommandIssueId(file.path, cmd.name),
247
+ severity: 'warning',
248
+ category: 'security',
249
+ title: `Destructive command "${cmd.name}" without safety language`,
250
+ summary: `Instruction file contains a destructive command "${cmd.name}" but lacks ` +
251
+ `safety language (e.g., "Ask before running").`,
252
+ filePaths: [file.path],
253
+ locations: [], // Could be improved with line numbers
254
+ evidence: [`Destructive command "${cmd.name}" found in ${path.basename(file.path)} without safety language.`],
255
+ recommendation: `Add safety language such as "Ask for confirmation before running ${cmd.name}" ` +
256
+ `to ensure destructive operations are not performed accidentally.`,
257
+ confidence: 0.7,
258
+ });
259
+ }
260
+ }
261
+ }
262
+ }
263
+ // 6. .gitignore Checks (Cost 9)
264
+ const gitignorePath = path.join(/*turbopackIgnore: true*/ repoRoot, '.gitignore');
265
+ let gitignoreContent = '';
266
+ try {
267
+ if (fs.existsSync(gitignorePath)) {
268
+ gitignoreContent = fs.readFileSync(gitignorePath, 'utf8');
269
+ }
270
+ }
271
+ catch {
272
+ // ignore
273
+ }
274
+ const gitignoreLines = gitignoreContent
275
+ .split(/\r?\n/)
276
+ .map((l) => l.trim())
277
+ .filter((l) => l && !l.startsWith('#'));
278
+ const hasPromptCiGitignore = gitignoreLines.some((line) => gitignoreLineMatchesTarget(line, '.promptci'));
279
+ if (!hasPromptCiGitignore) {
280
+ issues.push({
281
+ id: 'security-pack-no-promptci-gitignore',
282
+ severity: 'info',
283
+ category: 'security',
284
+ title: 'Missing .promptci/ ignore in .gitignore',
285
+ summary: 'The .promptci/ directory is not ignored in .gitignore, which may lead to ' +
286
+ 'committing large generated scan reports to the repository.',
287
+ filePaths: ['.gitignore'],
288
+ locations: [],
289
+ evidence: ['.promptci/ entry not found in .gitignore'],
290
+ recommendation: 'Add `.promptci/` to your `.gitignore` file to prevent committing generated reports.',
291
+ fixRecipe: 'echo ".promptci/" >> .gitignore',
292
+ confidence: 0.9,
293
+ });
294
+ }
295
+ // 7. Unignored build, output, or coverage directories (Cost 9)
296
+ const commonDirs = ['coverage', 'dist', 'build', '.next', 'bin', 'obj', 'temp', 'tmp', 'logs'];
297
+ const unignoredDirs = commonDirs.filter((d) => {
298
+ const fullPath = path.join(/*turbopackIgnore: true*/ repoRoot, d);
299
+ try {
300
+ if (fs.existsSync(fullPath)) {
301
+ const stat = fs.statSync(fullPath);
302
+ if (stat.isDirectory()) {
303
+ const isIgnored = gitignoreLines.some((line) => gitignoreLineMatchesTarget(line, d));
304
+ return !isIgnored;
305
+ }
306
+ }
307
+ }
308
+ catch {
309
+ // ignore
310
+ }
311
+ return false;
312
+ });
313
+ if (unignoredDirs.length > 0) {
314
+ issues.push({
315
+ id: 'security-pack-unignored-dirs',
316
+ severity: 'warning',
317
+ category: 'context_bloat',
318
+ title: 'Unignored build, output, or coverage directories',
319
+ summary: `The repository contains directory/directories (${unignoredDirs.join(', ')}) that are ` +
320
+ `commonly generated but not ignored in .gitignore. AI tools may ingest these, ` +
321
+ `inflating token costs.`,
322
+ filePaths: ['.gitignore'],
323
+ locations: [],
324
+ evidence: unignoredDirs.map((d) => `Directory "${d}" exists but is not ignored in .gitignore.`),
325
+ recommendation: `Add generated directories to .gitignore. For example: "${unignoredDirs.map((d) => `${d}/`).join(', ')}"`,
326
+ fixRecipe: unignoredDirs.map((d) => `echo "${d}/" >> .gitignore`).join('\n'),
327
+ confidence: 0.8,
328
+ });
329
+ }
330
+ // 8. Broad include patterns scanning generated directories (Cost 9)
331
+ let hasBroadInclude = false;
332
+ try {
333
+ const configPath = path.join(/*turbopackIgnore: true*/ repoRoot, '.promptci', 'config.json');
334
+ if (fs.existsSync(configPath)) {
335
+ const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
336
+ if (Array.isArray(config.include)) {
337
+ const broadPatterns = ['**/*', '**/*.md', '*', '*.*', '**'];
338
+ hasBroadInclude = config.include.some((p) => broadPatterns.includes(p.trim()));
339
+ }
340
+ }
341
+ }
342
+ catch {
343
+ // ignore
344
+ }
345
+ if (hasBroadInclude) {
346
+ const scannedGenerated = files.filter((f) => {
347
+ const rel = path.relative(/*turbopackIgnore: true*/ repoRoot, f.path).replace(/\\/g, '/');
348
+ return (rel.includes('.promptci/') ||
349
+ rel.includes('coverage/') ||
350
+ rel.includes('.next/'));
351
+ });
352
+ if (scannedGenerated.length > 0) {
353
+ issues.push({
354
+ id: 'security-pack-broad-include',
355
+ severity: 'warning',
356
+ category: 'context_bloat',
357
+ title: 'Broad include pattern scanning generated directories',
358
+ summary: 'PromptCI configuration has a broad include pattern that matches generated directories ' +
359
+ 'such as .promptci/ or coverage/, causing them to be unnecessarily scanned.',
360
+ filePaths: ['.promptci/config.json'],
361
+ locations: [],
362
+ evidence: scannedGenerated.map((f) => `Scanned generated file: ${path.relative(/*turbopackIgnore: true*/ repoRoot, f.path).replace(/\\/g, '/')}`),
363
+ recommendation: 'Refine the include patterns in .promptci/config.json or add exclusions to avoid scanning generated/temporary documents.',
364
+ fixRecipe: 'Modify .promptci/config.json to restrict "include" to specific instruction files, or add exclusions to "exclude".',
365
+ confidence: 0.95,
366
+ });
367
+ }
368
+ }
369
+ // 9. Inspect generated reports before source docs (Cost 9)
370
+ for (const file of files) {
371
+ const inspectBeforePatterns = [
372
+ /read\s+.*\.promptci\s+before/i,
373
+ /inspect\s+.*\.promptci\s+before/i,
374
+ /check\s+.*\.promptci\s+before/i,
375
+ /read\s+.*report.*\s+before\s+.*(source|docs|code)/i,
376
+ /inspect\s+.*report.*\s+before\s+.*(source|docs|code)/i,
377
+ ];
378
+ for (const pat of inspectBeforePatterns) {
379
+ if (pat.test(file.content)) {
380
+ issues.push({
381
+ // SP1 / B3: was a constant id inside this per-file loop — the
382
+ // `break` below only exits the pattern loop, not the file loop, so
383
+ // two matching files produced two issues sharing ONE id.
384
+ id: inspectReportsFirstIssueId(file.path),
385
+ severity: 'info',
386
+ category: 'context_bloat',
387
+ title: 'Instruction prioritizing generated reports over source docs',
388
+ summary: `Instruction file "${path.basename(file.path)}" tells the agent to inspect ` +
389
+ `generated reports before source files, which can cause circular or outdated guidance ingestion.`,
390
+ filePaths: [file.path],
391
+ locations: [],
392
+ evidence: [`Matched pattern: ${pat.toString()}`],
393
+ recommendation: 'Recommend linking to latest reports or directing the agent to read source documents first instead of generated reports.',
394
+ fixRecipe: 'Update the instruction to prioritize reading source files and configuration rather than relying on generated reports.',
395
+ confidence: 0.7,
396
+ });
397
+ break; // one issue per file
398
+ }
399
+ }
400
+ }
401
+ return issues;
402
+ }
403
+ //# sourceMappingURL=security-pack.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"security-pack.js","sourceRoot":"","sources":["../src/security-pack.ts"],"names":[],"mappings":"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"}