phantom-pr 0.4.19 β†’ 0.5.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 (47) hide show
  1. package/README.md +216 -80
  2. package/dist/core/analysis/astExtractor.d.ts +15 -0
  3. package/dist/core/analysis/astExtractor.js +354 -0
  4. package/dist/core/analysis/astExtractor.js.map +1 -0
  5. package/dist/core/analysis/index.d.ts +3 -0
  6. package/dist/core/analysis/index.js +3 -0
  7. package/dist/core/analysis/index.js.map +1 -0
  8. package/dist/core/analysis/types.d.ts +50 -0
  9. package/dist/core/analysis/types.js +16 -0
  10. package/dist/core/analysis/types.js.map +1 -0
  11. package/dist/core/context/contextSelector.d.ts +29 -0
  12. package/dist/core/context/contextSelector.js +293 -0
  13. package/dist/core/context/contextSelector.js.map +1 -0
  14. package/dist/core/context/index.d.ts +4 -0
  15. package/dist/core/context/index.js +3 -0
  16. package/dist/core/context/index.js.map +1 -0
  17. package/dist/core/generator/enhancedContext.d.ts +34 -0
  18. package/dist/core/generator/enhancedContext.js +144 -0
  19. package/dist/core/generator/enhancedContext.js.map +1 -0
  20. package/dist/core/generator/postValidation.d.ts +24 -0
  21. package/dist/core/generator/postValidation.js +57 -0
  22. package/dist/core/generator/postValidation.js.map +1 -0
  23. package/dist/core/retry/errorParser.d.ts +12 -0
  24. package/dist/core/retry/errorParser.js +264 -0
  25. package/dist/core/retry/errorParser.js.map +1 -0
  26. package/dist/core/retry/feedbackGenerator.d.ts +12 -0
  27. package/dist/core/retry/feedbackGenerator.js +164 -0
  28. package/dist/core/retry/feedbackGenerator.js.map +1 -0
  29. package/dist/core/retry/index.d.ts +3 -0
  30. package/dist/core/retry/index.js +3 -0
  31. package/dist/core/retry/index.js.map +1 -0
  32. package/dist/core/retry/types.d.ts +40 -0
  33. package/dist/core/retry/types.js +5 -0
  34. package/dist/core/retry/types.js.map +1 -0
  35. package/dist/core/testRunner/retryEnhancer.d.ts +32 -0
  36. package/dist/core/testRunner/retryEnhancer.js +58 -0
  37. package/dist/core/testRunner/retryEnhancer.js.map +1 -0
  38. package/dist/core/validation/coverageVerifier.d.ts +16 -0
  39. package/dist/core/validation/coverageVerifier.js +226 -0
  40. package/dist/core/validation/coverageVerifier.js.map +1 -0
  41. package/dist/core/validation/index.d.ts +2 -0
  42. package/dist/core/validation/index.js +2 -0
  43. package/dist/core/validation/index.js.map +1 -0
  44. package/dist/core/validation/types.d.ts +24 -0
  45. package/dist/core/validation/types.js +6 -0
  46. package/dist/core/validation/types.js.map +1 -0
  47. package/package.json +1 -1
package/README.md CHANGED
@@ -1,41 +1,99 @@
1
1
  # phantom-pr
2
2
 
3
- `phantom-pr` is a CI-friendly CLI that opens PRs with passing Jest unit tests (bounded + deterministic, PR-only, no auto-merge).
3
+ `phantom-pr` is a CI-friendly CLI that opens PRs with passing Jest/Vitest/pytest unit tests (bounded + deterministic, PR-only, no auto-merge).
4
4
 
5
- ## Quick start
5
+ ## Installation
6
6
 
7
- ### Using npm (PowerShell-friendly)
7
+ ```bash
8
+ npm install -g phantom-pr
9
+ ```
8
10
 
9
- ```powershell
10
- npm install
11
- npm run build
12
- npm run smoke
11
+ Or use directly with npx:
12
+
13
+ ```bash
14
+ npx phantom-pr --help
15
+ ```
16
+
17
+ ## Quick Start
18
+
19
+ ```bash
20
+ # 1. Create config file
21
+ cat > phantom-pr.yml << EOF
22
+ baseBranch: main
23
+ github:
24
+ owner: your-org
25
+ repo: your-repo
26
+ tokenEnvVar: GITHUB_TOKEN
27
+ mode:
28
+ dryRun: true
29
+ test:
30
+ command: npm test
31
+ EOF
32
+
33
+ # 2. Index your codebase
34
+ phantom-pr index --root .
35
+
36
+ # 3. Generate a plan
37
+ phantom-pr plan --root .
38
+
39
+ # 4. Run in dry mode first
40
+ phantom-pr full --root . --dryRun
41
+ ```
42
+
43
+ ## Features
44
+
45
+ ### πŸ§ͺ Automatic Test Generation
46
+
47
+ Generate unit tests for any file:
48
+
49
+ ```bash
50
+ phantom-pr tests src/components/Button.tsx --local
13
51
  ```
14
52
 
15
- ## What you get
53
+ ### πŸ” AST-Powered Analysis (New in 0.5.0)
54
+
55
+ The test generator now uses AST analysis to:
56
+
57
+ - **Detect branches** - Finds `if`, ternary, switch, and `&&`/`||` operators
58
+ - **Identify effects** - Detects `useEffect`, `useLayoutEffect` with cleanup detection
59
+ - **Map child components** - Finds components that need mocking
60
+ - **Track external calls** - Identifies imported functions being called
61
+
62
+ This enables smarter test generation with better branch coverage.
63
+
64
+ ### πŸ”„ Smart Retry with Error Parsing
16
65
 
17
- - **Strict TypeScript**: configured in `tsconfig.json`
18
- - **Minimal formatting**: Prettier config in `.prettierrc.json`
19
- - **CLI entrypoint**: `src/cli.ts` (prints `--help`, exits 0)
20
- - **Config MVP + status**: `phantom-pr status` loads `phantom-pr.yml` (or `--config <path>`) and prints resolved config + missing fields
21
- - **Full orchestration**: `phantom-pr full` is the β€œone safe unit of work” command for CI (caps + stale handling + deterministic target choice)
22
- - **Testability lane (MVP)**: `phantom-pr testability` can open a minimal β€œadd data-testid” PR for React targets
23
- - **Tests lane**: `phantom-pr tests` generates tests, runs the test command, and writes `.phantom-pr/report.json`
24
- - **Folder structure**:
25
- - `src/core/` (domain logic)
26
- - `src/adapters/` (IO boundaries: git hosting, filesystem, process, network)
27
- - `src/commands/` (CLI commands)
66
+ When tests fail, the retry system now:
28
67
 
29
- ## Scripts
68
+ - Parses Jest/Vitest error output
69
+ - Identifies specific error types (mock not called, assertion mismatch, import errors)
70
+ - Generates targeted fix suggestions
71
+ - Creates focused retry prompts
30
72
 
31
- - **build**: `tsc` compile to `dist/`
32
- - **test**: unit tests for the CLI itself (`node --test tests`)
33
- - **lint**: typecheck-only (`tsc --noEmit`)
34
- - **smoke**: build + run `--help`
73
+ ### πŸ“Š Post-Generation Validation
35
74
 
36
- ## Config (MVP)
75
+ After generating tests, validation checks:
37
76
 
38
- Create `phantom-pr.yml` at the repo root (or pass `--config path/to/phantom-pr.yml`):
77
+ - Branch coverage completeness
78
+ - Effect cleanup testing (for `useEffect` with cleanup)
79
+ - Child component mocking
80
+ - Returns specific `llm_reject_*` codes for failures
81
+
82
+ ## Commands
83
+
84
+ | Command | Description |
85
+ |---------|-------------|
86
+ | `phantom-pr status` | Show config and status |
87
+ | `phantom-pr index` | Index the codebase |
88
+ | `phantom-pr plan` | Generate test plan |
89
+ | `phantom-pr tests <file>` | Generate tests for a file |
90
+ | `phantom-pr full` | Full orchestration (CI mode) |
91
+ | `phantom-pr pr --prNumber <n>` | PR companion mode |
92
+ | `phantom-pr testability <file>` | Add data-testid attributes |
93
+
94
+ ## Configuration
95
+
96
+ Create `phantom-pr.yml` at repo root:
39
97
 
40
98
  ```yaml
41
99
  baseBranch: main
@@ -43,8 +101,7 @@ github:
43
101
  owner: your-org
44
102
  repo: your-repo
45
103
  tokenEnvVar: GITHUB_TOKEN
46
- # Safety default: fork PRs are denied unless explicitly allowed.
47
- allowForkPrs: false
104
+ allowForkPrs: false # Safety default
48
105
  limits:
49
106
  maxFilesChanged: 50
50
107
  maxLinesChanged: 5000
@@ -52,92 +109,171 @@ limits:
52
109
  maxOpenBotPRs: 3
53
110
  maxPRsPerRun: 1
54
111
  mode:
55
- dryRun: true
112
+ dryRun: true # Set false for real PRs
56
113
  test:
57
114
  command: npm test
58
115
  ```
59
116
 
60
- Check config resolution (never prints token values):
117
+ ### Config Options
118
+
119
+ | Option | Description | Default |
120
+ |--------|-------------|---------|
121
+ | `baseBranch` | Target branch for PRs | `main` |
122
+ | `limits.maxIterations` | Max test retry attempts | `5` |
123
+ | `limits.maxPRsPerRun` | Max PRs per CI run | `1` |
124
+ | `mode.dryRun` | Disable real Git/GitHub operations | `true` |
125
+ | `test.command` | Test command to run | `npm test` |
126
+
127
+ ## CI Integration
61
128
 
62
- ```powershell
63
- node dist/cli.js status
64
- node dist/cli.js status --config path/to/phantom-pr.yml
129
+ ### Scheduled Runs (Recommended: 4x/day)
130
+
131
+ ```yaml
132
+ # GitHub Actions example
133
+ on:
134
+ schedule:
135
+ - cron: '0 1,7,13,19 * * *'
136
+
137
+ jobs:
138
+ phantom-pr:
139
+ runs-on: ubuntu-latest
140
+ steps:
141
+ - uses: actions/checkout@v4
142
+ - uses: actions/setup-node@v4
143
+ - run: npm ci
144
+ - run: npx phantom-pr full --root .
145
+ env:
146
+ GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
65
147
  ```
66
148
 
67
- ## Local run
149
+ ### Jenkins
150
+
151
+ See `docs/jenkins.md` for Pipeline examples.
152
+
153
+ ## Understanding Reports
154
+
155
+ ### `tests` command β†’ `.phantom-pr/report.json`
156
+
157
+ See `docs/report-json.md` for schema details.
158
+
159
+ Key fields:
160
+ - `finalOutcome`: `pass` | `fail` | `timeout`
161
+ - `attempts`: Array of test run attempts
162
+ - `generatorWarnings`: Any validation issues
68
163
 
69
- Recommended β€œsafe first run” in a real repo (no network side effects):
164
+ ### `full` command β†’ `.phantom-pr/full.json`
70
165
 
71
- ```powershell
166
+ - `caps`: Open PR count and limits
167
+ - `chosenTarget`: What file was selected
168
+ - `lane`: `tests` | `testability` | `skipped`
169
+
170
+ ## Contributing
171
+
172
+ ### Development Setup
173
+
174
+ ```bash
175
+ git clone https://github.com/norralak/blacksand-phantom-pr.git
176
+ cd blacksand-phantom-pr
177
+ npm install
72
178
  npm run build
73
- node dist/cli.js index --root .
74
- node dist/cli.js plan --root .
75
- node dist/cli.js full --root . --dryRun --report .phantom-pr/full.json
179
+ npm test
76
180
  ```
77
181
 
78
- What β€œsuccess” looks like:
79
- - `full` exits `0` and prints a stable JSON object to stdout.
80
- - In dryRun, it never opens/closes/comments on PRs and may set `refreshSkippedReason` (e.g. `dryrun_no_github_token`).
182
+ ### Project Structure
81
183
 
82
- ## Scheduled CI run (4x/day)
184
+ ```
185
+ src/
186
+ β”œβ”€β”€ cli.ts # CLI entrypoint
187
+ β”œβ”€β”€ commands/ # Command implementations
188
+ β”œβ”€β”€ adapters/ # IO boundaries (git, github, fs)
189
+ └── core/
190
+ β”œβ”€β”€ analysis/ # AST extraction (NEW)
191
+ β”œβ”€β”€ context/ # Context packing & selection
192
+ β”œβ”€β”€ validation/ # Post-generation validation (NEW)
193
+ β”œβ”€β”€ retry/ # Error parsing & feedback (NEW)
194
+ β”œβ”€β”€ generator/ # Test generators (LLM, smoke)
195
+ β”œβ”€β”€ testRunner/ # Test execution
196
+ └── ...
197
+ ```
83
198
 
84
- Minimal pattern: install deps, build, then run `full` (the orchestrator). Schedule it **4 times/day** in your CI system:
199
+ ### Running Tests
85
200
 
86
- - Example cron (works for Jenkins β€œBuild periodically”, and similarly in other systems): `H 1,7,13,19 * * *`
201
+ ```bash
202
+ # All tests
203
+ npm test
87
204
 
88
- Jenkins notes and a Pipeline example: see `docs/jenkins.md`.
205
+ # Specific test file
206
+ npm test -- tests/ast-extractor.test.mjs
89
207
 
90
- Notes:
91
- - Prefer running `full` on a clean workspace with the repo checked out and a configured Git remote.
92
- - Keep `mode.dryRun: true` until you verify behavior on your repo and CI environment.
93
- - `limits.maxPRsPerRun` is enforced (default `1`): one run does at most one unit of work.
208
+ # With verbose output
209
+ npm test -- --test-reporter=spec
210
+ ```
94
211
 
95
- ## Required permissions
212
+ ### Code Style
96
213
 
97
- ### Git permissions (for real mode PR workflows)
98
- - The CI checkout must be able to create branches and push (e.g. SSH deploy key or HTTPS token configured for `git push`).
214
+ - **TypeScript**: Strict mode enabled
215
+ - **Formatting**: Prettier (run `npm run format`)
216
+ - **Linting**: TypeScript compiler (`npm run lint`)
99
217
 
100
- ### GitHub API permissions (for real mode PR workflows)
101
- `phantom-pr` uses the env var named by `github.tokenEnvVar` from `phantom-pr.yml` (and never prints its value).
218
+ ### Adding New Features
102
219
 
103
- For a GitHub Fine-grained token, the minimum typically needed:
104
- - **Contents**: Read & Write (push branches)
105
- - **Pull requests**: Read & Write (open PRs, read PR status)
106
- - **Issues**: Read & Write (comment on PRs / add labels)
107
- - **Metadata**: Read
220
+ 1. **Create types first** in `types.ts`
221
+ 2. **Implement with tests** - follow TDD
222
+ 3. **Add barrel export** in `index.ts`
223
+ 4. **Update README** if user-facing
224
+
225
+ ### Risk Register
226
+
227
+ When adding features with heuristics (parsing, detection), document risks:
108
228
 
109
- For a classic PAT, this is commonly covered by `repo` scope, but prefer fine-grained when possible.
229
+ | When to add risk | Example |
230
+ |------------------|---------|
231
+ | Regex-based parsing | Error parser patterns |
232
+ | Static lists | External package detection |
233
+ | Heuristic detection | Branch/effect identification |
110
234
 
111
- ## How to interpret `.phantom-pr/report.json` (tests command)
235
+ ### Pull Request Guidelines
112
236
 
113
- See `docs/report-json.md`.
237
+ - One feature per PR
238
+ - Include tests for new functionality
239
+ - Update documentation
240
+ - Run `npm test` before submitting
114
241
 
115
- ## How to interpret `.phantom-pr/full.json` (full command)
242
+ ## Required Permissions
116
243
 
117
- `phantom-pr full` writes a small orchestration report (default: `<root>/.phantom-pr/full.json`):
118
- - **`caps`** shows open PR count and whether the cap was hit
119
- - **`refreshSkippedReason`** explains why GitHub refresh wasn’t attempted (dryRun safety)
120
- - **`stale`** summarizes stale PR consideration and actions
121
- - **`chosenTarget`** and **`lane`** show what it decided to do
244
+ ### Git
245
+ - Create branches
246
+ - Push commits
122
247
 
123
- ## Logging
248
+ ### GitHub API (via `tokenEnvVar`)
249
+ - **Contents**: Read & Write
250
+ - **Pull requests**: Read & Write
251
+ - **Issues**: Read & Write (for comments)
252
+ - **Metadata**: Read
253
+
254
+ ## Troubleshooting
124
255
 
125
- Commands use a structured logger with levels (**debug/info/warn/error**). Logs go to **stderr** to keep command output clean.
256
+ ### "Cannot find module" errors
126
257
 
127
- - Enable debug logs:
258
+ The test generator mocks child components. If you see import errors:
128
259
 
129
- ```powershell
130
- node dist/cli.js status --verbose
260
+ ```typescript
261
+ // Add to test file
262
+ jest.mock('./ChildComponent');
131
263
  ```
132
264
 
133
- ## Golden demo (real PRs)
265
+ ### Tests timing out
266
+
267
+ - Check for async operations without proper `await`
268
+ - Use `waitFor()` from testing-library
269
+ - Increase timeout in jest config
134
270
 
135
- There is a PowerShell-friendly script that runs both modes (scheduled + PR companion) in **real mode**:
136
- - Scheduled: `full` (opens/updates a bot PR on `baseBranch`)
137
- - PR companion: `pr --prNumber <n>` (opens/updates a companion PR)
271
+ ### LLM not generating tests
138
272
 
139
- See `DEMO.md` and run `scripts/golden-demo.ps1`.
273
+ Check `.phantom-pr/report.json` for:
274
+ - `llm.allowed`: Must be `true`
275
+ - `generatorWarnings`: Shows rejection reasons
140
276
 
141
277
  ## License
142
- Proprietary β€” All Rights Reserved. See LICENSE.
143
278
 
279
+ Proprietary β€” All Rights Reserved. See LICENSE.md.
@@ -0,0 +1,15 @@
1
+ /**
2
+ * AST extractor that analyzes React/TypeScript component files.
3
+ * Uses TypeScript's built-in compiler API (no external parser dependency).
4
+ *
5
+ * Pure function: parse file β†’ return ComponentAnalysis.
6
+ * Handles parse errors gracefully (returns partial analysis, doesn't throw).
7
+ */
8
+ import type { ComponentAnalysis } from './types.js';
9
+ /**
10
+ * Extract component analysis from a React/TypeScript file.
11
+ * @param filePath - Path to the file (for reference in output)
12
+ * @param fileContent - Source code content
13
+ * @returns ComponentAnalysis with extracted structure info
14
+ */
15
+ export declare function extractComponentAnalysis(filePath: string, fileContent: string): ComponentAnalysis;