bugproof 0.1.2 → 0.2.2

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 (69) hide show
  1. package/CHANGELOG.md +61 -5
  2. package/README.md +175 -4
  3. package/dist/capture/env-snapshot.d.ts +53 -0
  4. package/dist/capture/env-snapshot.d.ts.map +1 -0
  5. package/dist/capture/env-snapshot.js +122 -0
  6. package/dist/capture/env-snapshot.js.map +1 -0
  7. package/dist/capture/language-support.d.ts +55 -0
  8. package/dist/capture/language-support.d.ts.map +1 -0
  9. package/dist/capture/language-support.js +505 -0
  10. package/dist/capture/language-support.js.map +1 -0
  11. package/dist/capture/packager.d.ts +9 -0
  12. package/dist/capture/packager.d.ts.map +1 -1
  13. package/dist/capture/packager.js +23 -2
  14. package/dist/capture/packager.js.map +1 -1
  15. package/dist/capture/source-strategy.d.ts +52 -0
  16. package/dist/capture/source-strategy.d.ts.map +1 -0
  17. package/dist/capture/source-strategy.js +227 -0
  18. package/dist/capture/source-strategy.js.map +1 -0
  19. package/dist/cli.js +373 -12
  20. package/dist/cli.js.map +1 -1
  21. package/dist/config/loader.d.ts +44 -0
  22. package/dist/config/loader.d.ts.map +1 -0
  23. package/dist/config/loader.js +87 -0
  24. package/dist/config/loader.js.map +1 -0
  25. package/dist/replay/engine.d.ts +9 -0
  26. package/dist/replay/engine.d.ts.map +1 -1
  27. package/dist/replay/engine.js +29 -3
  28. package/dist/replay/engine.js.map +1 -1
  29. package/dist/replay/hints.d.ts +18 -0
  30. package/dist/replay/hints.d.ts.map +1 -0
  31. package/dist/replay/hints.js +138 -0
  32. package/dist/replay/hints.js.map +1 -0
  33. package/dist/replay/sandbox.js +41 -14
  34. package/dist/replay/sandbox.js.map +1 -1
  35. package/dist/replay/verdict.d.ts.map +1 -1
  36. package/dist/replay/verdict.js +41 -5
  37. package/dist/replay/verdict.js.map +1 -1
  38. package/dist/sandbox/bugbox.d.ts.map +1 -1
  39. package/dist/sandbox/bugbox.js +40 -6
  40. package/dist/sandbox/bugbox.js.map +1 -1
  41. package/dist/sandbox/container.d.ts +81 -0
  42. package/dist/sandbox/container.d.ts.map +1 -0
  43. package/dist/sandbox/container.js +343 -0
  44. package/dist/sandbox/container.js.map +1 -0
  45. package/dist/sandbox/cross-platform.d.ts +59 -0
  46. package/dist/sandbox/cross-platform.d.ts.map +1 -0
  47. package/dist/sandbox/cross-platform.js +330 -0
  48. package/dist/sandbox/cross-platform.js.map +1 -0
  49. package/dist/sandbox/network.d.ts.map +1 -1
  50. package/dist/sandbox/network.js +31 -2
  51. package/dist/sandbox/network.js.map +1 -1
  52. package/dist/share/gist.d.ts +21 -0
  53. package/dist/share/gist.d.ts.map +1 -0
  54. package/dist/share/gist.js +158 -0
  55. package/dist/share/gist.js.map +1 -0
  56. package/dist/utils/archive.d.ts +1 -0
  57. package/dist/utils/archive.d.ts.map +1 -1
  58. package/dist/utils/archive.js +42 -1
  59. package/dist/utils/archive.js.map +1 -1
  60. package/dist/utils/artifact-validation.d.ts +7 -0
  61. package/dist/utils/artifact-validation.d.ts.map +1 -0
  62. package/dist/utils/artifact-validation.js +212 -0
  63. package/dist/utils/artifact-validation.js.map +1 -0
  64. package/dist/utils/dependencies.d.ts +18 -0
  65. package/dist/utils/dependencies.d.ts.map +1 -0
  66. package/dist/utils/dependencies.js +218 -0
  67. package/dist/utils/dependencies.js.map +1 -0
  68. package/package.json +3 -2
  69. package/scripts/postinstall.cjs +38 -5
@@ -1,6 +1,20 @@
1
1
  import * as fs from 'fs';
2
+ import * as path from 'path';
2
3
  import archiver from 'archiver';
3
4
  import extract from 'extract-zip';
5
+ import { isPathWithinBoundary } from './security.js';
6
+ const MAX_ARCHIVE_FILES = 10000;
7
+ const MAX_ARCHIVE_UNCOMPRESSED_BYTES = 500 * 1024 * 1024;
8
+ const MAX_SINGLE_FILE_UNCOMPRESSED_BYTES = 100 * 1024 * 1024;
9
+ export function validateArchiveEntryPath(entryName, destDir) {
10
+ if (!entryName || path.isAbsolute(entryName) || entryName.includes('\0')) {
11
+ throw new Error(`Invalid archive entry path: ${entryName}`);
12
+ }
13
+ const normalized = path.resolve(destDir, entryName);
14
+ if (!isPathWithinBoundary(normalized, destDir)) {
15
+ throw new Error(`Path traversal attempt detected: ${entryName}`);
16
+ }
17
+ }
4
18
  /**
5
19
  * Compresses a directory into a ZIP archive.
6
20
  * @param sourceDir The directory to compress.
@@ -30,7 +44,34 @@ export async function zipDirectory(sourceDir, outPath) {
30
44
  */
31
45
  export async function extractZip(zipPath, destDir) {
32
46
  try {
33
- await extract(zipPath, { dir: destDir });
47
+ const resolvedDest = path.resolve(destDir);
48
+ let fileCount = 0;
49
+ let totalSize = 0;
50
+ await extract(zipPath, {
51
+ dir: resolvedDest,
52
+ onEntry: (entry) => {
53
+ fileCount += 1;
54
+ if (fileCount > MAX_ARCHIVE_FILES) {
55
+ throw new Error('Archive contains too many files');
56
+ }
57
+ const entryName = entry.fileName || '';
58
+ validateArchiveEntryPath(entryName, resolvedDest);
59
+ const size = typeof entry.uncompressedSize === 'number' ? entry.uncompressedSize : 0;
60
+ if (size > MAX_SINGLE_FILE_UNCOMPRESSED_BYTES) {
61
+ throw new Error(`Archive entry too large: ${entryName}`);
62
+ }
63
+ totalSize += size;
64
+ if (totalSize > MAX_ARCHIVE_UNCOMPRESSED_BYTES) {
65
+ throw new Error('Archive uncompressed size limit exceeded');
66
+ }
67
+ if (entry.externalFileAttributes !== undefined) {
68
+ const mode = (entry.externalFileAttributes >> 16) & 0o170000;
69
+ if (mode === 0o120000) {
70
+ throw new Error(`Symbolic links are not allowed in archives: ${entryName}`);
71
+ }
72
+ }
73
+ },
74
+ });
34
75
  }
35
76
  catch (err) {
36
77
  throw new Error(`Failed to extract artifact: ${err instanceof Error ? err.message : err}`);
@@ -1 +1 @@
1
- {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,QAAQ,MAAM,UAAU,CAAC;AAChC,OAAO,OAAO,MAAM,aAAa,CAAC;AAElC;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,YAAY,CAAC,SAAiB,EAAE,OAAe;IACnE,OAAO,IAAI,OAAO,CAAC,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;QACrC,MAAM,OAAO,GAAG,QAAQ,CAAC,KAAK,EAAE;YAC9B,IAAI,EAAE,EAAE,KAAK,EAAE,CAAC,EAAE,EAAE,sBAAsB;SAC3C,CAAC,CAAC;QAEH,MAAM,MAAM,GAAG,EAAE,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC;QAE7C,MAAM,CAAC,EAAE,CAAC,OAAO,EAAE,GAAG,EAAE;YACtB,OAAO,EAAE,CAAC;QACZ,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,EAAE,CAAC,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;YAC1B,MAAM,CAAC,GAAG,CAAC,CAAC;QACd,CAAC,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACrB,OAAO,CAAC,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC,CAAC,0CAA0C;QAC/E,OAAO,CAAC,QAAQ,EAAE,CAAC;IACrB,CAAC,CAAC,CAAC;AACL,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,KAAK,UAAU,UAAU,CAAC,OAAe,EAAE,OAAe;IAC/D,IAAI,CAAC;QACH,MAAM,OAAO,CAAC,OAAO,EAAE,EAAE,GAAG,EAAE,OAAO,EAAE,CAAC,CAAC;IAC3C,CAAC;IAAC,OAAO,GAAG,EAAE,CAAC;QACb,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC;IAC7F,CAAC;AACH,CAAC"}
1
+ {"version":3,"file":"archive.js","sourceRoot":"","sources":["../../src/utils/archive.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ import { ArtifactManifest, RunConfig } from '../types/artifact.js';
2
+ import { FailureRecord } from '../types/failure.js';
3
+ export declare function secureJsonParse(raw: string, label: string): unknown;
4
+ export declare function validateArtifactManifest(value: unknown): ArtifactManifest;
5
+ export declare function validateRunConfig(value: unknown): RunConfig;
6
+ export declare function validateFailureRecord(value: unknown): FailureRecord;
7
+ //# sourceMappingURL=artifact-validation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-validation.d.ts","sourceRoot":"","sources":["../../src/utils/artifact-validation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,gBAAgB,EAAE,SAAS,EAAE,MAAM,sBAAsB,CAAC;AACnE,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AAsJpD,wBAAgB,eAAe,CAAC,GAAG,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,GAAG,OAAO,CAcnE;AAED,wBAAgB,wBAAwB,CAAC,KAAK,EAAE,OAAO,GAAG,gBAAgB,CAgCzE;AAED,wBAAgB,iBAAiB,CAAC,KAAK,EAAE,OAAO,GAAG,SAAS,CAgB3D;AAED,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,OAAO,GAAG,aAAa,CAoBnE"}
@@ -0,0 +1,212 @@
1
+ const MAX_JSON_BYTES = 1024 * 1024;
2
+ const MAX_JSON_DEPTH = 32;
3
+ const MAX_COMMAND_ARGS = 256;
4
+ const MAX_STRING_LENGTH = 8192;
5
+ const MANIFEST_KEYS = new Set([
6
+ 'version',
7
+ 'bugproof_version',
8
+ 'name',
9
+ 'description',
10
+ 'captured_at',
11
+ 'captured_on',
12
+ 'command',
13
+ 'working_directory',
14
+ 'exit_code',
15
+ 'duration_ms',
16
+ 'files_count',
17
+ 'files_size_bytes',
18
+ 'secrets_detected',
19
+ 'secrets_skipped',
20
+ ]);
21
+ const CAPTURED_ON_KEYS = new Set([
22
+ 'os',
23
+ 'arch',
24
+ 'node_version',
25
+ 'git_commit',
26
+ 'git_branch',
27
+ 'git_dirty',
28
+ ]);
29
+ const RUN_CONFIG_KEYS = new Set([
30
+ 'command',
31
+ 'working_directory',
32
+ 'environment',
33
+ 'timeout_ms',
34
+ 'capture_output',
35
+ ]);
36
+ const FAILURE_KEYS = new Set([
37
+ 'exit_code',
38
+ 'signal',
39
+ 'stdout_lines',
40
+ 'stderr_lines',
41
+ 'stderr_snippet',
42
+ 'fingerprint',
43
+ 'error_patterns',
44
+ 'duration_ms',
45
+ 'timeout',
46
+ ]);
47
+ function ensureObject(value, label) {
48
+ if (!value || typeof value !== 'object' || Array.isArray(value)) {
49
+ throw new Error(`${label} must be an object`);
50
+ }
51
+ return value;
52
+ }
53
+ function ensureNoUnknownKeys(value, allowed, label) {
54
+ for (const key of Object.keys(value)) {
55
+ if (!allowed.has(key)) {
56
+ throw new Error(`${label} contains unknown field: ${key}`);
57
+ }
58
+ }
59
+ }
60
+ function ensureString(value, label) {
61
+ if (typeof value !== 'string') {
62
+ throw new Error(`${label} must be a string`);
63
+ }
64
+ if (value.length > MAX_STRING_LENGTH) {
65
+ throw new Error(`${label} exceeds maximum length`);
66
+ }
67
+ return value;
68
+ }
69
+ function ensureOptionalString(value, label) {
70
+ if (value === undefined) {
71
+ return undefined;
72
+ }
73
+ return ensureString(value, label);
74
+ }
75
+ function ensureNumber(value, label) {
76
+ if (typeof value !== 'number' || !Number.isFinite(value)) {
77
+ throw new Error(`${label} must be a finite number`);
78
+ }
79
+ return value;
80
+ }
81
+ function ensureBoolean(value, label) {
82
+ if (typeof value !== 'boolean') {
83
+ throw new Error(`${label} must be a boolean`);
84
+ }
85
+ return value;
86
+ }
87
+ function ensureStringArray(value, label, maxItems = MAX_COMMAND_ARGS) {
88
+ if (!Array.isArray(value)) {
89
+ throw new Error(`${label} must be an array`);
90
+ }
91
+ if (value.length === 0 || value.length > maxItems) {
92
+ throw new Error(`${label} has invalid number of items`);
93
+ }
94
+ return value.map((item, index) => ensureString(item, `${label}[${index}]`));
95
+ }
96
+ function ensureOptionalStringArray(value, label, maxItems = MAX_COMMAND_ARGS) {
97
+ if (value === undefined) {
98
+ return [];
99
+ }
100
+ if (!Array.isArray(value)) {
101
+ throw new Error(`${label} must be an array`);
102
+ }
103
+ if (value.length > maxItems) {
104
+ throw new Error(`${label} has too many items`);
105
+ }
106
+ return value.map((item, index) => ensureString(item, `${label}[${index}]`));
107
+ }
108
+ function ensurePlainEnvironment(value) {
109
+ const env = ensureObject(value, 'run.environment');
110
+ const safe = {};
111
+ for (const [key, raw] of Object.entries(env)) {
112
+ if (!key || key.length > 128 || /[\r\n\0]/.test(key)) {
113
+ throw new Error(`run.environment contains invalid key: ${key}`);
114
+ }
115
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
116
+ throw new Error(`run.environment contains disallowed key: ${key}`);
117
+ }
118
+ safe[key] = ensureString(raw, `run.environment.${key}`);
119
+ }
120
+ return safe;
121
+ }
122
+ function assertMaxDepth(value, depth = 0) {
123
+ if (depth > MAX_JSON_DEPTH) {
124
+ throw new Error('JSON exceeds maximum nesting depth');
125
+ }
126
+ if (Array.isArray(value)) {
127
+ value.forEach((item) => assertMaxDepth(item, depth + 1));
128
+ return;
129
+ }
130
+ if (value && typeof value === 'object') {
131
+ Object.values(value).forEach((item) => assertMaxDepth(item, depth + 1));
132
+ }
133
+ }
134
+ export function secureJsonParse(raw, label) {
135
+ if (raw.length > MAX_JSON_BYTES) {
136
+ throw new Error(`${label} exceeds maximum size`);
137
+ }
138
+ const parsed = JSON.parse(raw, (key, value) => {
139
+ if (key === '__proto__' || key === 'constructor' || key === 'prototype') {
140
+ throw new Error(`${label} contains disallowed key: ${key}`);
141
+ }
142
+ return value;
143
+ });
144
+ assertMaxDepth(parsed);
145
+ return parsed;
146
+ }
147
+ export function validateArtifactManifest(value) {
148
+ const manifest = ensureObject(value, 'manifest');
149
+ ensureNoUnknownKeys(manifest, MANIFEST_KEYS, 'manifest');
150
+ const capturedOnRaw = ensureObject(manifest.captured_on, 'manifest.captured_on');
151
+ ensureNoUnknownKeys(capturedOnRaw, CAPTURED_ON_KEYS, 'manifest.captured_on');
152
+ return {
153
+ version: ensureString(manifest.version, 'manifest.version'),
154
+ bugproof_version: ensureString(manifest.bugproof_version, 'manifest.bugproof_version'),
155
+ name: ensureString(manifest.name, 'manifest.name'),
156
+ description: ensureString(manifest.description, 'manifest.description'),
157
+ captured_at: ensureString(manifest.captured_at, 'manifest.captured_at'),
158
+ captured_on: {
159
+ os: ensureString(capturedOnRaw.os, 'manifest.captured_on.os'),
160
+ arch: ensureString(capturedOnRaw.arch, 'manifest.captured_on.arch'),
161
+ node_version: ensureString(capturedOnRaw.node_version, 'manifest.captured_on.node_version'),
162
+ git_commit: ensureOptionalString(capturedOnRaw.git_commit, 'manifest.captured_on.git_commit'),
163
+ git_branch: ensureOptionalString(capturedOnRaw.git_branch, 'manifest.captured_on.git_branch'),
164
+ git_dirty: capturedOnRaw.git_dirty === undefined
165
+ ? undefined
166
+ : ensureBoolean(capturedOnRaw.git_dirty, 'manifest.captured_on.git_dirty'),
167
+ },
168
+ command: ensureStringArray(manifest.command, 'manifest.command'),
169
+ working_directory: ensureString(manifest.working_directory, 'manifest.working_directory'),
170
+ exit_code: ensureNumber(manifest.exit_code, 'manifest.exit_code'),
171
+ duration_ms: ensureNumber(manifest.duration_ms, 'manifest.duration_ms'),
172
+ files_count: ensureNumber(manifest.files_count, 'manifest.files_count'),
173
+ files_size_bytes: ensureNumber(manifest.files_size_bytes, 'manifest.files_size_bytes'),
174
+ secrets_detected: ensureBoolean(manifest.secrets_detected, 'manifest.secrets_detected'),
175
+ secrets_skipped: ensureOptionalStringArray(manifest.secrets_skipped, 'manifest.secrets_skipped'),
176
+ };
177
+ }
178
+ export function validateRunConfig(value) {
179
+ const run = ensureObject(value, 'run');
180
+ ensureNoUnknownKeys(run, RUN_CONFIG_KEYS, 'run');
181
+ const timeoutMs = ensureNumber(run.timeout_ms, 'run.timeout_ms');
182
+ if (timeoutMs <= 0 || timeoutMs > 60 * 60 * 1000) {
183
+ throw new Error('run.timeout_ms out of range');
184
+ }
185
+ return {
186
+ command: ensureStringArray(run.command, 'run.command'),
187
+ working_directory: ensureString(run.working_directory, 'run.working_directory'),
188
+ environment: ensurePlainEnvironment(run.environment),
189
+ timeout_ms: timeoutMs,
190
+ capture_output: ensureBoolean(run.capture_output, 'run.capture_output'),
191
+ };
192
+ }
193
+ export function validateFailureRecord(value) {
194
+ const failure = ensureObject(value, 'failure');
195
+ ensureNoUnknownKeys(failure, FAILURE_KEYS, 'failure');
196
+ const signal = failure.signal;
197
+ if (!(signal === null || typeof signal === 'string')) {
198
+ throw new Error('failure.signal must be null or string');
199
+ }
200
+ return {
201
+ exit_code: ensureNumber(failure.exit_code, 'failure.exit_code'),
202
+ signal,
203
+ stdout_lines: ensureNumber(failure.stdout_lines, 'failure.stdout_lines'),
204
+ stderr_lines: ensureNumber(failure.stderr_lines, 'failure.stderr_lines'),
205
+ stderr_snippet: ensureString(failure.stderr_snippet, 'failure.stderr_snippet'),
206
+ fingerprint: ensureString(failure.fingerprint, 'failure.fingerprint'),
207
+ error_patterns: ensureOptionalStringArray(failure.error_patterns, 'failure.error_patterns'),
208
+ duration_ms: ensureNumber(failure.duration_ms, 'failure.duration_ms'),
209
+ timeout: ensureBoolean(failure.timeout, 'failure.timeout'),
210
+ };
211
+ }
212
+ //# sourceMappingURL=artifact-validation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"artifact-validation.js","sourceRoot":"","sources":["../../src/utils/artifact-validation.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ /**
2
+ * Dependency Detection Engine
3
+ *
4
+ * Analyzes stderr output to detect missing dependencies and suggest
5
+ * installation commands. Works across Node.js, Python, Ruby, Go, Rust, and more.
6
+ */
7
+ export interface MissingDependency {
8
+ name: string;
9
+ language: string;
10
+ installCommand: string;
11
+ confidence: 'high' | 'medium' | 'low';
12
+ }
13
+ /**
14
+ * Scans stderr output and detects missing dependencies.
15
+ * Returns a deduplicated list of dependencies with install commands.
16
+ */
17
+ export declare function detectMissingDependencies(stderr: string): MissingDependency[];
18
+ //# sourceMappingURL=dependencies.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.d.ts","sourceRoot":"","sources":["../../src/utils/dependencies.ts"],"names":[],"mappings":"AAAA;;;;;GAKG;AAEH,MAAM,WAAW,iBAAiB;IAChC,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,MAAM,CAAC;IACjB,cAAc,EAAE,MAAM,CAAC;IACvB,UAAU,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,CAAC;CACvC;AAmMD;;;GAGG;AACH,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,MAAM,GAAG,iBAAiB,EAAE,CAwB7E"}
@@ -0,0 +1,218 @@
1
+ /**
2
+ * Dependency Detection Engine
3
+ *
4
+ * Analyzes stderr output to detect missing dependencies and suggest
5
+ * installation commands. Works across Node.js, Python, Ruby, Go, Rust, and more.
6
+ */
7
+ const DETECTION_RULES = [
8
+ // Node.js / npm
9
+ {
10
+ pattern: /Cannot find module ['"]([^'"]+)['"]/g,
11
+ language: 'node',
12
+ extractName: (m) => {
13
+ const mod = m[1];
14
+ if (mod.startsWith('.') || mod.startsWith('/'))
15
+ return '';
16
+ // Handle scoped packages: @scope/name
17
+ if (mod.startsWith('@')) {
18
+ const parts = mod.split('/');
19
+ return parts.length >= 2 ? `${parts[0]}/${parts[1]}` : parts[0];
20
+ }
21
+ return mod.split('/')[0];
22
+ },
23
+ installCommand: (name) => `npm install ${name}`,
24
+ confidence: 'high',
25
+ },
26
+ {
27
+ pattern: /Error \[ERR_MODULE_NOT_FOUND\]: Cannot find package '([^']+)'/g,
28
+ language: 'node',
29
+ extractName: (m) => m[1],
30
+ installCommand: (name) => `npm install ${name}`,
31
+ confidence: 'high',
32
+ },
33
+ // Python
34
+ {
35
+ pattern: /ModuleNotFoundError: No module named '([^']+)'/g,
36
+ language: 'python',
37
+ extractName: (m) => m[1].split('.')[0],
38
+ installCommand: (name) => `pip install ${name}`,
39
+ confidence: 'high',
40
+ },
41
+ {
42
+ pattern: /ImportError: No module named (\S+)/g,
43
+ language: 'python',
44
+ extractName: (m) => m[1].split('.')[0],
45
+ installCommand: (name) => `pip install ${name}`,
46
+ confidence: 'high',
47
+ },
48
+ // Ruby
49
+ {
50
+ pattern: /cannot load such file -- ([^\s(]+)/g,
51
+ language: 'ruby',
52
+ extractName: (m) => m[1],
53
+ installCommand: (name) => `gem install ${name}`,
54
+ confidence: 'medium',
55
+ },
56
+ {
57
+ pattern: /Could not find gem '([^']+)'/g,
58
+ language: 'ruby',
59
+ extractName: (m) => m[1].split(' ')[0],
60
+ installCommand: (name) => `gem install ${name}`,
61
+ confidence: 'high',
62
+ },
63
+ // Go
64
+ {
65
+ pattern: /cannot find package "([^"]+)"/g,
66
+ language: 'go',
67
+ extractName: (m) => m[1],
68
+ installCommand: (name) => `go get ${name}`,
69
+ confidence: 'high',
70
+ },
71
+ // Rust / Cargo
72
+ {
73
+ pattern: /error\[E0433\]: failed to resolve:.*`([^`]+)`/g,
74
+ language: 'rust',
75
+ extractName: (m) => m[1],
76
+ installCommand: (name) => `cargo add ${name}`,
77
+ confidence: 'medium',
78
+ },
79
+ // Java — ClassNotFoundException
80
+ {
81
+ pattern: /ClassNotFoundException:\s+([\w.]+)/g,
82
+ language: 'java',
83
+ extractName: (m) => m[1],
84
+ installCommand: (name) => `# Add '${name}' to classpath or pom.xml/build.gradle`,
85
+ confidence: 'high',
86
+ },
87
+ // Java — NoClassDefFoundError
88
+ {
89
+ pattern: /NoClassDefFoundError:\s+([\w/$]+)/g,
90
+ language: 'java',
91
+ extractName: (m) => m[1].replace(/\//g, '.').replace(/\$$/, ''),
92
+ installCommand: (name) => `# Missing class: ${name}. Check dependencies and classpath.`,
93
+ confidence: 'high',
94
+ },
95
+ // Java/Maven — dependency resolution failure
96
+ {
97
+ pattern: /Could not find artifact ([\w.:-]+)/g,
98
+ language: 'java',
99
+ extractName: (m) => m[1],
100
+ installCommand: (name) => `# Maven: add <dependency> for ${name} to pom.xml`,
101
+ confidence: 'high',
102
+ },
103
+ // Java/Gradle — dependency not found
104
+ {
105
+ pattern: /Could not resolve (?:all )?(?:dependencies|artifacts).*?>([\w.:-]+)/g,
106
+ language: 'java',
107
+ extractName: (m) => m[1],
108
+ installCommand: (name) => `# Gradle: add implementation("${name}") to build.gradle`,
109
+ confidence: 'medium',
110
+ },
111
+ // C/C++ — missing header
112
+ {
113
+ pattern: /fatal error:\s+([^\s:]+\.h):\s*No such file/g,
114
+ language: 'cpp',
115
+ extractName: (m) => m[1],
116
+ installCommand: (name) => `# Install dev package for ${name}. Try: apt install lib*-dev`,
117
+ confidence: 'high',
118
+ },
119
+ // C/C++ — undefined reference (linker)
120
+ {
121
+ pattern: /undefined reference to [`']([^'`]+)[`']/g,
122
+ language: 'cpp',
123
+ extractName: (m) => m[1],
124
+ installCommand: (name) => `# Linker: missing symbol '${name}'. Add the library with -l flag.`,
125
+ confidence: 'medium',
126
+ },
127
+ // C/C++ — cannot find -l (linker library)
128
+ {
129
+ pattern: /cannot find -l(\w+)/g,
130
+ language: 'cpp',
131
+ extractName: (m) => m[1],
132
+ installCommand: (name) => `apt install lib${name}-dev # (Debian/Ubuntu)`,
133
+ confidence: 'high',
134
+ },
135
+ // .NET — package not found
136
+ {
137
+ pattern: /error NU1101: Unable to find package (\S+)/g,
138
+ language: 'dotnet',
139
+ extractName: (m) => m[1],
140
+ installCommand: (name) => `dotnet add package ${name}`,
141
+ confidence: 'high',
142
+ },
143
+ // .NET — assembly not found
144
+ {
145
+ pattern: /Could not load file or assembly '([^']+)'/g,
146
+ language: 'dotnet',
147
+ extractName: (m) => m[1].split(',')[0],
148
+ installCommand: (name) => `dotnet add package ${name}`,
149
+ confidence: 'medium',
150
+ },
151
+ // Kotlin — unresolved reference
152
+ {
153
+ pattern: /Unresolved reference: (\w+)/g,
154
+ language: 'kotlin',
155
+ extractName: (m) => m[1],
156
+ installCommand: (name) => `# Kotlin: add dependency for '${name}' to build.gradle.kts`,
157
+ confidence: 'medium',
158
+ },
159
+ // System libraries
160
+ {
161
+ pattern: /error while loading shared libraries: lib([^.]+)\.so/g,
162
+ language: 'system',
163
+ extractName: (m) => m[1],
164
+ installCommand: (name) => `apt install lib${name}-dev # (Debian/Ubuntu)`,
165
+ confidence: 'medium',
166
+ },
167
+ // Windows DLL not found
168
+ {
169
+ pattern: /The specified module could not be found.*?(\w+\.dll)/gi,
170
+ language: 'system',
171
+ extractName: (m) => m[1],
172
+ installCommand: (name) => `# Missing DLL: ${name}. Install the required runtime or library.`,
173
+ confidence: 'medium',
174
+ },
175
+ // macOS — dylib not found
176
+ {
177
+ pattern: /Library not loaded:\s+.*?lib(\w+)\.dylib/g,
178
+ language: 'system',
179
+ extractName: (m) => m[1],
180
+ installCommand: (name) => `brew install ${name} # (macOS via Homebrew)`,
181
+ confidence: 'medium',
182
+ },
183
+ // Generic "command not found"
184
+ {
185
+ pattern: /(?:command not found|not recognized as .* command)[:\s]+['"]?(\S+)/gi,
186
+ language: 'system',
187
+ extractName: (m) => m[1].replace(/['"]/g, ''),
188
+ installCommand: (name) => `# Install '${name}' — check your package manager`,
189
+ confidence: 'medium',
190
+ },
191
+ ];
192
+ /**
193
+ * Scans stderr output and detects missing dependencies.
194
+ * Returns a deduplicated list of dependencies with install commands.
195
+ */
196
+ export function detectMissingDependencies(stderr) {
197
+ const seen = new Set();
198
+ const deps = [];
199
+ for (const rule of DETECTION_RULES) {
200
+ // Reset regex lastIndex for global patterns
201
+ rule.pattern.lastIndex = 0;
202
+ let match;
203
+ while ((match = rule.pattern.exec(stderr)) !== null) {
204
+ const name = rule.extractName(match);
205
+ if (!name || seen.has(`${rule.language}:${name}`))
206
+ continue;
207
+ seen.add(`${rule.language}:${name}`);
208
+ deps.push({
209
+ name,
210
+ language: rule.language,
211
+ installCommand: rule.installCommand(name),
212
+ confidence: rule.confidence,
213
+ });
214
+ }
215
+ }
216
+ return deps;
217
+ }
218
+ //# sourceMappingURL=dependencies.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"dependencies.js","sourceRoot":"","sources":["../../src/utils/dependencies.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "bugproof",
3
- "version": "0.1.2",
3
+ "version": "0.2.2",
4
4
  "description": "Executable bug artifacts — portable, reproducible bug reports",
5
5
  "main": "dist/cli.js",
6
6
  "type": "module",
@@ -12,13 +12,14 @@
12
12
  "postinstall": "node scripts/postinstall.cjs",
13
13
  "prepublishOnly": "npm run build && npm run test && npm run lint",
14
14
  "dev": "tsx watch src/index.ts",
15
- "test": "jest",
15
+ "test": "npm run build && jest",
16
16
  "test:watch": "jest --watch",
17
17
  "test:coverage": "jest --coverage",
18
18
  "lint": "eslint src --ext .ts",
19
19
  "format": "prettier --write 'src/**/*.ts'",
20
20
  "cli": "tsx src/cli.ts",
21
21
  "test:e2e": "node scripts/e2e-matrix.js",
22
+ "test:matrix": "node scripts/multi-language-matrix.cjs",
22
23
  "test:comprehensive": "node scripts/comprehensive-test.js",
23
24
  "release": "node scripts/release.cjs"
24
25
  },