phantom-pr 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (159) hide show
  1. package/LICENSE.md +0 -0
  2. package/README.md +143 -0
  3. package/dist/adapters/git.d.ts +28 -0
  4. package/dist/adapters/git.js +112 -0
  5. package/dist/adapters/git.js.map +1 -0
  6. package/dist/adapters/github.d.ts +71 -0
  7. package/dist/adapters/github.js +194 -0
  8. package/dist/adapters/github.js.map +1 -0
  9. package/dist/cli.d.ts +47 -0
  10. package/dist/cli.js +201 -0
  11. package/dist/cli.js.map +1 -0
  12. package/dist/commands/context.d.ts +2 -0
  13. package/dist/commands/context.js +275 -0
  14. package/dist/commands/context.js.map +1 -0
  15. package/dist/commands/full.d.ts +13 -0
  16. package/dist/commands/full.js +590 -0
  17. package/dist/commands/full.js.map +1 -0
  18. package/dist/commands/gen_test.d.ts +2 -0
  19. package/dist/commands/gen_test.js +94 -0
  20. package/dist/commands/gen_test.js.map +1 -0
  21. package/dist/commands/index.d.ts +2 -0
  22. package/dist/commands/index.js +62 -0
  23. package/dist/commands/index.js.map +1 -0
  24. package/dist/commands/plan.d.ts +2 -0
  25. package/dist/commands/plan.js +107 -0
  26. package/dist/commands/plan.js.map +1 -0
  27. package/dist/commands/pr.d.ts +9 -0
  28. package/dist/commands/pr.js +400 -0
  29. package/dist/commands/pr.js.map +1 -0
  30. package/dist/commands/pr_list.d.ts +2 -0
  31. package/dist/commands/pr_list.js +158 -0
  32. package/dist/commands/pr_list.js.map +1 -0
  33. package/dist/commands/status.d.ts +6 -0
  34. package/dist/commands/status.js +132 -0
  35. package/dist/commands/status.js.map +1 -0
  36. package/dist/commands/test.d.ts +2 -0
  37. package/dist/commands/test.js +143 -0
  38. package/dist/commands/test.js.map +1 -0
  39. package/dist/commands/testability.d.ts +10 -0
  40. package/dist/commands/testability.js +406 -0
  41. package/dist/commands/testability.js.map +1 -0
  42. package/dist/commands/tests.d.ts +9 -0
  43. package/dist/commands/tests.js +801 -0
  44. package/dist/commands/tests.js.map +1 -0
  45. package/dist/core/code/exports.d.ts +5 -0
  46. package/dist/core/code/exports.js +68 -0
  47. package/dist/core/code/exports.js.map +1 -0
  48. package/dist/core/config/forkPolicy.d.ts +25 -0
  49. package/dist/core/config/forkPolicy.js +35 -0
  50. package/dist/core/config/forkPolicy.js.map +1 -0
  51. package/dist/core/config/load.d.ts +13 -0
  52. package/dist/core/config/load.js +35 -0
  53. package/dist/core/config/load.js.map +1 -0
  54. package/dist/core/config/types.d.ts +87 -0
  55. package/dist/core/config/types.js +2 -0
  56. package/dist/core/config/types.js.map +1 -0
  57. package/dist/core/config/validate.d.ts +4 -0
  58. package/dist/core/config/validate.js +246 -0
  59. package/dist/core/config/validate.js.map +1 -0
  60. package/dist/core/context/packer.d.ts +31 -0
  61. package/dist/core/context/packer.js +345 -0
  62. package/dist/core/context/packer.js.map +1 -0
  63. package/dist/core/context/types.d.ts +41 -0
  64. package/dist/core/context/types.js +2 -0
  65. package/dist/core/context/types.js.map +1 -0
  66. package/dist/core/converge/loop.d.ts +13 -0
  67. package/dist/core/converge/loop.js +35 -0
  68. package/dist/core/converge/loop.js.map +1 -0
  69. package/dist/core/converge/types.d.ts +15 -0
  70. package/dist/core/converge/types.js +2 -0
  71. package/dist/core/converge/types.js.map +1 -0
  72. package/dist/core/generator/llm/diffApply.d.ts +26 -0
  73. package/dist/core/generator/llm/diffApply.js +276 -0
  74. package/dist/core/generator/llm/diffApply.js.map +1 -0
  75. package/dist/core/generator/llm/qualityGate.d.ts +34 -0
  76. package/dist/core/generator/llm/qualityGate.js +324 -0
  77. package/dist/core/generator/llm/qualityGate.js.map +1 -0
  78. package/dist/core/generator/llmGenerator.d.ts +34 -0
  79. package/dist/core/generator/llmGenerator.js +245 -0
  80. package/dist/core/generator/llmGenerator.js.map +1 -0
  81. package/dist/core/generator/quality.d.ts +17 -0
  82. package/dist/core/generator/quality.js +31 -0
  83. package/dist/core/generator/quality.js.map +1 -0
  84. package/dist/core/generator/registry.d.ts +26 -0
  85. package/dist/core/generator/registry.js +29 -0
  86. package/dist/core/generator/registry.js.map +1 -0
  87. package/dist/core/generator/smokeGenerator.d.ts +11 -0
  88. package/dist/core/generator/smokeGenerator.js +27 -0
  89. package/dist/core/generator/smokeGenerator.js.map +1 -0
  90. package/dist/core/generator/types.d.ts +48 -0
  91. package/dist/core/generator/types.js +2 -0
  92. package/dist/core/generator/types.js.map +1 -0
  93. package/dist/core/index/indexer.d.ts +29 -0
  94. package/dist/core/index/indexer.js +167 -0
  95. package/dist/core/index/indexer.js.map +1 -0
  96. package/dist/core/jest/parser.d.ts +17 -0
  97. package/dist/core/jest/parser.js +90 -0
  98. package/dist/core/jest/parser.js.map +1 -0
  99. package/dist/core/llm/provider.d.ts +55 -0
  100. package/dist/core/llm/provider.js +105 -0
  101. package/dist/core/llm/provider.js.map +1 -0
  102. package/dist/core/logger.d.ts +19 -0
  103. package/dist/core/logger.js +44 -0
  104. package/dist/core/logger.js.map +1 -0
  105. package/dist/core/plan/planner.d.ts +16 -0
  106. package/dist/core/plan/planner.js +91 -0
  107. package/dist/core/plan/planner.js.map +1 -0
  108. package/dist/core/process/exec.d.ts +22 -0
  109. package/dist/core/process/exec.js +83 -0
  110. package/dist/core/process/exec.js.map +1 -0
  111. package/dist/core/redact.d.ts +6 -0
  112. package/dist/core/redact.js +49 -0
  113. package/dist/core/redact.js.map +1 -0
  114. package/dist/core/repo/boundary.d.ts +10 -0
  115. package/dist/core/repo/boundary.js +58 -0
  116. package/dist/core/repo/boundary.js.map +1 -0
  117. package/dist/core/stableJson.d.ts +1 -0
  118. package/dist/core/stableJson.js +32 -0
  119. package/dist/core/stableJson.js.map +1 -0
  120. package/dist/core/state/policy.d.ts +20 -0
  121. package/dist/core/state/policy.js +51 -0
  122. package/dist/core/state/policy.js.map +1 -0
  123. package/dist/core/state/state.d.ts +67 -0
  124. package/dist/core/state/state.js +142 -0
  125. package/dist/core/state/state.js.map +1 -0
  126. package/dist/core/state/storage.d.ts +9 -0
  127. package/dist/core/state/storage.js +25 -0
  128. package/dist/core/state/storage.js.map +1 -0
  129. package/dist/core/targets/resolve.d.ts +28 -0
  130. package/dist/core/targets/resolve.js +96 -0
  131. package/dist/core/targets/resolve.js.map +1 -0
  132. package/dist/core/testGenerator/conventions.d.ts +7 -0
  133. package/dist/core/testGenerator/conventions.js +29 -0
  134. package/dist/core/testGenerator/conventions.js.map +1 -0
  135. package/dist/core/testGenerator/generate.d.ts +35 -0
  136. package/dist/core/testGenerator/generate.js +127 -0
  137. package/dist/core/testGenerator/generate.js.map +1 -0
  138. package/dist/core/testRunner/hints.d.ts +12 -0
  139. package/dist/core/testRunner/hints.js +133 -0
  140. package/dist/core/testRunner/hints.js.map +1 -0
  141. package/dist/core/testRunner/infer.d.ts +24 -0
  142. package/dist/core/testRunner/infer.js +65 -0
  143. package/dist/core/testRunner/infer.js.map +1 -0
  144. package/dist/core/testRunner/resolve.d.ts +12 -0
  145. package/dist/core/testRunner/resolve.js +31 -0
  146. package/dist/core/testRunner/resolve.js.map +1 -0
  147. package/dist/core/testRunner/runner.d.ts +24 -0
  148. package/dist/core/testRunner/runner.js +145 -0
  149. package/dist/core/testRunner/runner.js.map +1 -0
  150. package/dist/core/testability/heuristics.d.ts +7 -0
  151. package/dist/core/testability/heuristics.js +35 -0
  152. package/dist/core/testability/heuristics.js.map +1 -0
  153. package/dist/core/tests/fixers.d.ts +14 -0
  154. package/dist/core/tests/fixers.js +59 -0
  155. package/dist/core/tests/fixers.js.map +1 -0
  156. package/dist/core/tests/types.d.ts +98 -0
  157. package/dist/core/tests/types.js +2 -0
  158. package/dist/core/tests/types.js.map +1 -0
  159. package/package.json +55 -0
@@ -0,0 +1 @@
1
+ {"version":3,"file":"resolve.js","sourceRoot":"","sources":["../../../src/core/testRunner/resolve.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,EAAE,yBAAyB,EAAE,MAAM,YAAY,CAAC;AAUvD,SAAS,eAAe,CAAC,IAAY;IACnC,MAAM,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,cAAc,CAAC,CAAC;IAC1C,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,CAAC;QACH,OAAO,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,YAAY,CAAC,CAAC,EAAE,MAAM,CAAC,CAAgB,CAAC;IAC/D,CAAC;IAAC,MAAM,CAAC;QACP,OAAO,IAAI,CAAC;IACd,CAAC;AACH,CAAC;AAED,MAAM,UAAU,kBAAkB,CAAC,IAMlC;IACC,MAAM,GAAG,GAAG,eAAe,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IACvC,MAAM,QAAQ,GAAG,yBAAyB,CAAC;QACzC,OAAO,EAAE,IAAI,CAAC,IAAI;QAClB,WAAW,EAAE,GAAG;QAChB,cAAc,EAAE,IAAI,CAAC,YAAY,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,eAAe,EAAE,IAAI,CAAC,eAAe,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI;QACrG,MAAM,EAAE,EAAE,WAAW,EAAE,IAAI,CAAC,iBAAiB,EAAE;QAC/C,MAAM,EAAE,EAAE,kBAAkB,EAAE,IAAI,CAAC,wBAAwB,EAAE;KAC9D,CAAC,CAAC;IAEH,IAAI,CAAC,QAAQ,CAAC,OAAO;QAAE,OAAO,IAAI,CAAC;IACnC,IAAI,QAAQ,CAAC,MAAM,KAAK,MAAM;QAAE,OAAO,IAAI,CAAC;IAC5C,+FAA+F;IAC/F,OAAO,EAAE,OAAO,EAAE,QAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,KAAK,cAAc,CAAC,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;AAC/I,CAAC"}
@@ -0,0 +1,24 @@
1
+ export type TestRunResult = {
2
+ command: string;
3
+ cwd: string;
4
+ timedOut: boolean;
5
+ exitCode: number | null;
6
+ durationMs: number;
7
+ stdout: string;
8
+ stderr: string;
9
+ rawOutput: string;
10
+ runner: 'jest' | 'vitest' | 'pytest' | 'unknown';
11
+ hints: {
12
+ failingFiles: string[];
13
+ failingTests: string[];
14
+ };
15
+ parsedFailures: string[];
16
+ };
17
+ export declare function runTestCommand(opts: {
18
+ command: string;
19
+ cwd: string;
20
+ timeoutMs: number;
21
+ maxLineLen?: number;
22
+ maxLines?: number;
23
+ env?: NodeJS.ProcessEnv;
24
+ }): Promise<TestRunResult>;
@@ -0,0 +1,145 @@
1
+ import { spawn } from 'node:child_process';
2
+ import { redactText, truncateText } from '../redact.js';
3
+ import { extractRunnerHints } from './hints.js';
4
+ function sanitize(text, opts) {
5
+ return truncateText(redactText(text), opts);
6
+ }
7
+ function nowMs() {
8
+ return Date.now();
9
+ }
10
+ function killProcessTree(pid) {
11
+ if (!Number.isFinite(pid) || pid <= 0)
12
+ return;
13
+ if (process.platform === 'win32') {
14
+ // Best-effort: terminate the process tree on Windows.
15
+ try {
16
+ const killer = spawn('taskkill', ['/PID', String(pid), '/T', '/F'], { stdio: 'ignore', windowsHide: true });
17
+ killer.unref();
18
+ }
19
+ catch {
20
+ // ignore
21
+ }
22
+ return;
23
+ }
24
+ try {
25
+ process.kill(pid, 'SIGTERM');
26
+ }
27
+ catch {
28
+ // ignore
29
+ }
30
+ // Escalate shortly after.
31
+ const t = setTimeout(() => {
32
+ try {
33
+ process.kill(pid, 'SIGKILL');
34
+ }
35
+ catch {
36
+ // ignore
37
+ }
38
+ }, 250);
39
+ t.unref();
40
+ }
41
+ function appendCapped(current, chunk, maxChars) {
42
+ if (current.length >= maxChars)
43
+ return current;
44
+ const remaining = maxChars - current.length;
45
+ return current + chunk.slice(0, remaining);
46
+ }
47
+ export async function runTestCommand(opts) {
48
+ const started = nowMs();
49
+ const maxLineLen = opts.maxLineLen ?? 400;
50
+ const maxLines = opts.maxLines ?? 200;
51
+ const maxCaptureChars = 1_000_000; // hard cap to keep memory bounded
52
+ // Run through the platform shell so `npm run ...` and simple commands work.
53
+ const child = spawn(opts.command, {
54
+ cwd: opts.cwd,
55
+ env: opts.env ?? process.env,
56
+ shell: true,
57
+ stdio: ['ignore', 'pipe', 'pipe'],
58
+ windowsHide: true,
59
+ });
60
+ // NOTE: Do not `unref()` this child process. In Node's test runner, unref'ing the only
61
+ // active handles can cause "Promise resolution is still pending but the event loop has already resolved".
62
+ // Do NOT unref stdout/stderr: Node's test runner can treat the event loop as idle if we unref everything,
63
+ // which can cancel pending async tests. We still destroy streams in cleanup.
64
+ let stdoutRaw = '';
65
+ let stderrRaw = '';
66
+ let timedOut = false;
67
+ child.stdout?.setEncoding('utf8');
68
+ child.stderr?.setEncoding('utf8');
69
+ const onStdout = (chunk) => {
70
+ stdoutRaw = appendCapped(stdoutRaw, chunk, maxCaptureChars);
71
+ };
72
+ const onStderr = (chunk) => {
73
+ stderrRaw = appendCapped(stderrRaw, chunk, maxCaptureChars);
74
+ };
75
+ child.stdout?.on('data', onStdout);
76
+ child.stderr?.on('data', onStderr);
77
+ const durationMs = () => nowMs() - started;
78
+ return await new Promise((resolve) => {
79
+ let settled = false;
80
+ let timeoutTimer = null;
81
+ let giveUpTimer = null;
82
+ const cleanup = () => {
83
+ if (timeoutTimer)
84
+ clearTimeout(timeoutTimer);
85
+ if (giveUpTimer)
86
+ clearTimeout(giveUpTimer);
87
+ child.off('exit', onExit);
88
+ child.off('close', onClose);
89
+ child.off('error', onError);
90
+ child.stdout?.off?.('data', onStdout);
91
+ child.stderr?.off?.('data', onStderr);
92
+ try {
93
+ child.stdout?.destroy?.();
94
+ }
95
+ catch { }
96
+ try {
97
+ child.stderr?.destroy?.();
98
+ }
99
+ catch { }
100
+ };
101
+ const settleOnce = (exitCode) => {
102
+ if (settled)
103
+ return;
104
+ settled = true;
105
+ cleanup();
106
+ const stdout = sanitize(stdoutRaw, { maxLineLen, maxLines });
107
+ const stderr = sanitize(stderrRaw, { maxLineLen, maxLines });
108
+ const rawOutput = sanitize([stdoutRaw, stderrRaw].filter(Boolean).join('\n'), { maxLineLen, maxLines });
109
+ const extracted = extractRunnerHints({ command: opts.command, rawOutput });
110
+ resolve({
111
+ command: opts.command,
112
+ cwd: opts.cwd,
113
+ timedOut,
114
+ exitCode,
115
+ durationMs: durationMs(),
116
+ stdout,
117
+ stderr,
118
+ rawOutput,
119
+ runner: extracted.runner,
120
+ hints: extracted.hints,
121
+ parsedFailures: [],
122
+ });
123
+ };
124
+ const onExit = (code) => settleOnce(code);
125
+ const onClose = (code) => settleOnce(code);
126
+ const onError = () => settleOnce(null);
127
+ child.once('exit', onExit);
128
+ child.once('close', onClose);
129
+ child.once('error', onError);
130
+ timeoutTimer = setTimeout(() => {
131
+ timedOut = true;
132
+ try {
133
+ killProcessTree(child.pid ?? 0);
134
+ }
135
+ catch { }
136
+ // Settle immediately; do not wait for child to exit to keep CI deterministic.
137
+ settleOnce(null);
138
+ }, Math.max(1, opts.timeoutMs));
139
+ timeoutTimer.unref();
140
+ // Hard give-up: if the child refuses to die, still settle (idempotent).
141
+ giveUpTimer = setTimeout(() => settleOnce(null), Math.max(1, opts.timeoutMs) + 2_250);
142
+ giveUpTimer.unref();
143
+ });
144
+ }
145
+ //# sourceMappingURL=runner.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"runner.js","sourceRoot":"","sources":["../../../src/core/testRunner/runner.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,7 @@
1
+ export declare function isReactTestabilityCandidatePath(p: string): boolean;
2
+ export declare function needsTestabilityByHeuristic(contents: string): boolean;
3
+ export declare function deriveTestId(targetId: string | null, targetPath: string): string;
4
+ export declare function insertDataTestId(contents: string, testId: string): {
5
+ changed: boolean;
6
+ next: string;
7
+ };
@@ -0,0 +1,35 @@
1
+ import path from 'node:path';
2
+ function toPosix(p) {
3
+ return p.replace(/\\/g, '/');
4
+ }
5
+ export function isReactTestabilityCandidatePath(p) {
6
+ const ext = path.posix.extname(toPosix(p)).toLowerCase();
7
+ return ext === '.tsx' || ext === '.jsx';
8
+ }
9
+ export function needsTestabilityByHeuristic(contents) {
10
+ // MVP (no AST): interactive hint + missing data-testid.
11
+ if (contents.includes('data-testid'))
12
+ return false;
13
+ return contents.includes('<button') || contents.includes('onClick');
14
+ }
15
+ export function deriveTestId(targetId, targetPath) {
16
+ if (targetId && targetId.trim() !== '')
17
+ return `ta-${targetId}`;
18
+ const base = path.posix.basename(toPosix(targetPath), path.posix.extname(toPosix(targetPath)));
19
+ const safe = base.replace(/[^a-zA-Z0-9_-]+/g, '-').replace(/^-+|-+$/g, '');
20
+ return `ta-${safe || 'target'}`;
21
+ }
22
+ export function insertDataTestId(contents, testId) {
23
+ // MVP (no AST): add to the first interactive element found.
24
+ const re = /<(button|input|select)\b/;
25
+ const m = re.exec(contents);
26
+ if (!m || m.index == null)
27
+ return { changed: false, next: contents };
28
+ const idx = m.index;
29
+ const tag = m[1] ?? '';
30
+ const before = contents.slice(0, idx);
31
+ const after = contents.slice(idx + 1 + tag.length);
32
+ const injected = `<${tag} data-testid="${testId}"`;
33
+ return { changed: true, next: before + injected + after };
34
+ }
35
+ //# sourceMappingURL=heuristics.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"heuristics.js","sourceRoot":"","sources":["../../../src/core/testability/heuristics.ts"],"names":[],"mappings":"AAAA,OAAO,IAAI,MAAM,WAAW,CAAC;AAE7B,SAAS,OAAO,CAAC,CAAS;IACxB,OAAO,CAAC,CAAC,OAAO,CAAC,KAAK,EAAE,GAAG,CAAC,CAAC;AAC/B,CAAC;AAED,MAAM,UAAU,+BAA+B,CAAC,CAAS;IACvD,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;IACzD,OAAO,GAAG,KAAK,MAAM,IAAI,GAAG,KAAK,MAAM,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,2BAA2B,CAAC,QAAgB;IAC1D,wDAAwD;IACxD,IAAI,QAAQ,CAAC,QAAQ,CAAC,aAAa,CAAC;QAAE,OAAO,KAAK,CAAC;IACnD,OAAO,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,QAAQ,CAAC,QAAQ,CAAC,SAAS,CAAC,CAAC;AACtE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,QAAuB,EAAE,UAAkB;IACtE,IAAI,QAAQ,IAAI,QAAQ,CAAC,IAAI,EAAE,KAAK,EAAE;QAAE,OAAO,MAAM,QAAQ,EAAE,CAAC;IAChE,MAAM,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,OAAO,CAAC,UAAU,CAAC,EAAE,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC;IAC/F,MAAM,IAAI,GAAG,IAAI,CAAC,OAAO,CAAC,kBAAkB,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC;IAC3E,OAAO,MAAM,IAAI,IAAI,QAAQ,EAAE,CAAC;AAClC,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,QAAgB,EAAE,MAAc;IAC/D,4DAA4D;IAC5D,MAAM,EAAE,GAAG,0BAA0B,CAAC;IACtC,MAAM,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,IAAI,IAAI;QAAE,OAAO,EAAE,OAAO,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,EAAE,CAAC;IACrE,MAAM,GAAG,GAAG,CAAC,CAAC,KAAK,CAAC;IACpB,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;IACvB,MAAM,MAAM,GAAG,QAAQ,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IACtC,MAAM,KAAK,GAAG,QAAQ,CAAC,KAAK,CAAC,GAAG,GAAG,CAAC,GAAG,GAAG,CAAC,MAAM,CAAC,CAAC;IACnD,MAAM,QAAQ,GAAG,IAAI,GAAG,iBAAiB,MAAM,GAAG,CAAC;IACnD,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,IAAI,EAAE,MAAM,GAAG,QAAQ,GAAG,KAAK,EAAE,CAAC;AAC5D,CAAC"}
@@ -0,0 +1,14 @@
1
+ import type { JestFailure } from '../jest/parser.js';
2
+ export type FixContext = {
3
+ rootAbs: string;
4
+ testFiles: string[];
5
+ targetPaths: string[];
6
+ };
7
+ export type FixResult = {
8
+ applied: string[];
9
+ warnings: string[];
10
+ };
11
+ export declare function applyFixers(opts: {
12
+ failures: JestFailure[];
13
+ ctx: FixContext;
14
+ }): FixResult;
@@ -0,0 +1,59 @@
1
+ import fs from 'node:fs';
2
+ import path from 'node:path';
3
+ function readText(absPath) {
4
+ return fs.readFileSync(absPath, 'utf8');
5
+ }
6
+ function writeText(absPath, content) {
7
+ fs.mkdirSync(path.dirname(absPath), { recursive: true });
8
+ fs.writeFileSync(absPath, content, 'utf8');
9
+ }
10
+ function toAbs(rootAbs, relPosix) {
11
+ return path.join(rootAbs, ...relPosix.split('/'));
12
+ }
13
+ // Fixer 1 (safe): if our generated test imports/requires the target without extension and Jest can't resolve it,
14
+ // try adding an explicit `.js` extension (only for `.js` targets).
15
+ function applyAddJsExtensionFix(ctx) {
16
+ const jsTargets = ctx.targetPaths.filter((p) => p.endsWith('.js') || p.endsWith('.cjs') || p.endsWith('.mjs'));
17
+ if (jsTargets.length === 0)
18
+ return { applied: false };
19
+ for (const testFile of ctx.testFiles) {
20
+ if (!testFile.endsWith('.js'))
21
+ continue;
22
+ const abs = toAbs(ctx.rootAbs, testFile);
23
+ if (!fs.existsSync(abs))
24
+ continue;
25
+ const before = readText(abs);
26
+ // Only touch require('./x') style that generator emits.
27
+ const after = before.replace(/require\((['"])(\.[^'"]+)\1\)/g, (_m, q, pth) => {
28
+ if (pth.endsWith('.js'))
29
+ return `require(${q}${pth}${q})`;
30
+ return `require(${q}${pth}.js${q})`;
31
+ });
32
+ if (after !== before) {
33
+ writeText(abs, after);
34
+ return { applied: true };
35
+ }
36
+ }
37
+ return { applied: false };
38
+ }
39
+ // Fixer 2 (policy-only marker): if failures show missing DOM libs, record a warning so later commits can skip FE.
40
+ function hasMissingDomLib(failures) {
41
+ return failures.some((f) => f.kind === 'missing_dom_testing_libs');
42
+ }
43
+ export function applyFixers(opts) {
44
+ const applied = [];
45
+ const warnings = [];
46
+ const r1 = applyAddJsExtensionFix(opts.ctx);
47
+ if (r1.applied)
48
+ applied.push('add_js_extension_to_require');
49
+ if (r1.warning)
50
+ warnings.push(r1.warning);
51
+ if (hasMissingDomLib(opts.failures)) {
52
+ warnings.push('Detected missing DOM testing libs; frontend tests may need to be skipped in a later commit.');
53
+ applied.push('detected_missing_dom_libs');
54
+ }
55
+ applied.sort((a, b) => a.localeCompare(b));
56
+ warnings.sort((a, b) => a.localeCompare(b));
57
+ return { applied, warnings };
58
+ }
59
+ //# sourceMappingURL=fixers.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fixers.js","sourceRoot":"","sources":["../../../src/core/tests/fixers.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,98 @@
1
+ import type { JestFailure } from '../jest/parser.js';
2
+ export type FinalOutcome = 'pass' | 'fail' | 'timeout';
3
+ export type AttemptReport = {
4
+ attempt: number;
5
+ exitCode: number | null;
6
+ timedOut: boolean;
7
+ durationMs: number;
8
+ rawOutput: string;
9
+ failures: JestFailure[];
10
+ fixersApplied: string[];
11
+ /** True if this attempt was preceded by regeneration due to a previous failure. */
12
+ regenerated: boolean;
13
+ };
14
+ /** Crisp audit summary for operators: what happened and why (bounded, deterministic). */
15
+ export type DecisionSummary = {
16
+ lane: 'tests' | 'skipped';
17
+ skipReason: string | null;
18
+ caps: {
19
+ maxIterations: {
20
+ limit: number;
21
+ used: number;
22
+ };
23
+ maxPRsPerRun: {
24
+ limit: number | null;
25
+ used: number | null;
26
+ };
27
+ };
28
+ llm: {
29
+ enabled: boolean;
30
+ reason: string;
31
+ generatorWarnings: string[];
32
+ };
33
+ };
34
+ export type TestsReport = {
35
+ schemaVersion: 1;
36
+ command: 'tests';
37
+ dryRun: boolean;
38
+ noPr: boolean;
39
+ inferOnly: boolean;
40
+ remote: string;
41
+ /** Crisp audit summary: what happened and why. */
42
+ decision: DecisionSummary;
43
+ generatorKind: 'smoke' | 'llm';
44
+ generatorSummary: string;
45
+ generatorWarnings: string[];
46
+ llmAccess: {
47
+ invoker: 'tests' | 'full' | 'unknown';
48
+ allowCommands: string[];
49
+ allowed: boolean;
50
+ denylistHits: string[];
51
+ };
52
+ llmContext: {
53
+ sha256_8: string;
54
+ filesUsed: number;
55
+ charsUsed: number;
56
+ hitMaxFiles: boolean;
57
+ hitMaxChars: boolean;
58
+ } | null;
59
+ runner: 'jest' | 'vitest' | 'pytest' | 'unknown';
60
+ runnerInferred: 'jest' | 'vitest' | 'pytest' | 'unknown';
61
+ runnerObserved: 'jest' | 'vitest' | 'pytest' | 'unknown';
62
+ boundary: {
63
+ kind: 'js' | 'py' | 'unknown';
64
+ boundaryFileRel: string | null;
65
+ packageRootAbs: string;
66
+ packageRootRel: string;
67
+ };
68
+ reportPath: string;
69
+ planPath: string;
70
+ indexPath: string;
71
+ targetInput: string;
72
+ targetId: string | null;
73
+ targetPath: string | null;
74
+ generatedFiles: string[];
75
+ testCommandUsed: string | null;
76
+ testCommandSource: 'config' | 'policy' | 'package_json' | 'inferred' | 'none';
77
+ testCommandReason: string | null;
78
+ mustPassConsecutiveRuns: number;
79
+ maxIterations: number;
80
+ finalOutcome: FinalOutcome | null;
81
+ git: {
82
+ branch: string | null;
83
+ pushed: boolean;
84
+ };
85
+ pr: {
86
+ created: boolean;
87
+ url: string | null;
88
+ skippedReason: string | null;
89
+ };
90
+ attempts: AttemptReport[];
91
+ suggestions: Array<{
92
+ id: string;
93
+ rootPath: string;
94
+ paths: string[];
95
+ }>;
96
+ warnings: string[];
97
+ errors: string[];
98
+ };
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../../src/core/tests/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,55 @@
1
+ {
2
+ "name": "phantom-pr",
3
+ "version": "0.1.0",
4
+ "private": false,
5
+ "description": "CI-friendly CLI that opens PRs with passing Jest unit tests.",
6
+ "keywords": [
7
+ "test",
8
+ "cli"
9
+ ],
10
+ "homepage": "https://github.com/norralak/blacksand-phantom-pr#readme",
11
+ "bugs": {
12
+ "url": "https://github.com/norralak/blacksand-phantom-pr/issues"
13
+ },
14
+ "repository": {
15
+ "type": "git",
16
+ "url": "git+https://github.com/norralak/blacksand-phantom-pr.git"
17
+ },
18
+ "license": "UNLICENSED",
19
+ "author": "Norralak Sukaram",
20
+ "type": "module",
21
+ "main": "./dist/cli.js",
22
+ "types": "./dist/cli.d.ts",
23
+ "bin": {
24
+ "phantom-pr": "dist/cli.js"
25
+ },
26
+ "directories": {
27
+ "doc": "docs",
28
+ "test": "tests"
29
+ },
30
+ "files": ["dist", "README.md", "LICENSE", "LICENSE.md"],
31
+ "scripts": {
32
+ "build": "tsc -p tsconfig.json",
33
+ "test": "npm run build && node --test tests",
34
+ "lint": "tsc -p tsconfig.json --noEmit",
35
+ "format": "prettier --write .",
36
+ "format:check": "prettier --check .",
37
+ "smoke": "npm run build && node scripts/smoke.mjs",
38
+ "prepack": "npm run build",
39
+ "...": "..."
40
+ },
41
+ "dependencies": {
42
+ "ignore": "7.0.5",
43
+ "yaml": "2.8.2"
44
+ },
45
+ "devDependencies": {
46
+ "@types/node": "20.19.27",
47
+ "nock": "13.5.6",
48
+ "prettier": "3.7.4",
49
+ "typescript": "5.9.3"
50
+ },
51
+ "engines": {
52
+ "node": ">=20"
53
+ },
54
+ "packageManager": "pnpm@10.27.0"
55
+ }