@codexstar/bug-hunter 3.0.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 (51) hide show
  1. package/CHANGELOG.md +151 -0
  2. package/LICENSE +21 -0
  3. package/README.md +665 -0
  4. package/SKILL.md +624 -0
  5. package/bin/bug-hunter +222 -0
  6. package/evals/evals.json +362 -0
  7. package/modes/_dispatch.md +121 -0
  8. package/modes/extended.md +94 -0
  9. package/modes/fix-loop.md +115 -0
  10. package/modes/fix-pipeline.md +384 -0
  11. package/modes/large-codebase.md +212 -0
  12. package/modes/local-sequential.md +143 -0
  13. package/modes/loop.md +125 -0
  14. package/modes/parallel.md +113 -0
  15. package/modes/scaled.md +76 -0
  16. package/modes/single-file.md +38 -0
  17. package/modes/small.md +86 -0
  18. package/package.json +56 -0
  19. package/prompts/doc-lookup.md +44 -0
  20. package/prompts/examples/hunter-examples.md +131 -0
  21. package/prompts/examples/skeptic-examples.md +87 -0
  22. package/prompts/fixer.md +103 -0
  23. package/prompts/hunter.md +146 -0
  24. package/prompts/recon.md +159 -0
  25. package/prompts/referee.md +122 -0
  26. package/prompts/skeptic.md +143 -0
  27. package/prompts/threat-model.md +122 -0
  28. package/scripts/bug-hunter-state.cjs +537 -0
  29. package/scripts/code-index.cjs +541 -0
  30. package/scripts/context7-api.cjs +133 -0
  31. package/scripts/delta-mode.cjs +219 -0
  32. package/scripts/dep-scan.cjs +343 -0
  33. package/scripts/doc-lookup.cjs +316 -0
  34. package/scripts/fix-lock.cjs +167 -0
  35. package/scripts/init-test-fixture.sh +19 -0
  36. package/scripts/payload-guard.cjs +197 -0
  37. package/scripts/run-bug-hunter.cjs +892 -0
  38. package/scripts/tests/bug-hunter-state.test.cjs +87 -0
  39. package/scripts/tests/code-index.test.cjs +57 -0
  40. package/scripts/tests/delta-mode.test.cjs +47 -0
  41. package/scripts/tests/fix-lock.test.cjs +36 -0
  42. package/scripts/tests/fixtures/flaky-worker.cjs +63 -0
  43. package/scripts/tests/fixtures/low-confidence-worker.cjs +73 -0
  44. package/scripts/tests/fixtures/success-worker.cjs +42 -0
  45. package/scripts/tests/payload-guard.test.cjs +41 -0
  46. package/scripts/tests/run-bug-hunter.test.cjs +403 -0
  47. package/scripts/tests/test-utils.cjs +59 -0
  48. package/scripts/tests/worktree-harvest.test.cjs +297 -0
  49. package/scripts/triage.cjs +528 -0
  50. package/scripts/worktree-harvest.cjs +516 -0
  51. package/templates/subagent-wrapper.md +109 -0
@@ -0,0 +1,384 @@
1
+ # Phase 2: Fix Pipeline (default; also via `--fix`/`--autonomous`)
2
+
3
+ This phase takes the Referee's confirmed bug report and implements fixes. It runs when `FIX_MODE=true` and the Referee confirmed at least one real bug.
4
+ All Fixer launches in this file must use `AGENT_BACKEND` selected during SKILL preflight.
5
+
6
+ **If `DRY_RUN_MODE=true`:** execute Steps 8a–8d only (no git branch, no edits, no lock). The Fixer reads code and outputs planned changes as unified diff previews without calling the Edit tool. Skip to Step 12 after producing the dry-run report.
7
+
8
+ ### Step 8: Prepare for fixing (single-writer model)
9
+
10
+ **8a. Git safety + baseline refs**
11
+
12
+ Before touching code:
13
+ 1. Run `git rev-parse --is-inside-work-tree`:
14
+ - If not a git repo, warn and continue without rollback features.
15
+ 2. If in git (skip branching and stash if `DRY_RUN_MODE=true`):
16
+ - Capture `ORIGINAL_BRANCH=$(git rev-parse --abbrev-ref HEAD)`
17
+ - Capture `FIX_BASE_COMMIT=$(git rev-parse HEAD)` (used later for exact post-fix diff)
18
+ - Run `git status --porcelain`
19
+ - If dirty working tree, run `git stash push -m "bug-hunter-pre-fix-$(date +%s)"` and record `STASH_CREATED=true`
20
+ - Create fix branch: `git checkout -b bug-hunter-fix-$(date +%Y%m%d-%H%M%S)`
21
+ - Record `FIX_BRANCH` = the branch name
22
+
23
+ Report:
24
+ - Fix branch name
25
+ - Base commit hash (`FIX_BASE_COMMIT`)
26
+ - Whether stash was created
27
+
28
+ **8a-wt. Worktree isolation setup (subagent/teams backends only)**
29
+
30
+ If `AGENT_BACKEND` is `subagent` or `teams` and `worktree-harvest.cjs` exists:
31
+ 1. Clean up any stale worktrees from previous failed runs:
32
+ ```
33
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" cleanup-all ".bug-hunter/worktrees"
34
+ ```
35
+ 2. Set `WORKTREE_MODE=true`.
36
+
37
+ If `AGENT_BACKEND` is `local-sequential` or `interactive_shell`, or `worktree-harvest.cjs` is missing:
38
+ - Set `WORKTREE_MODE=false`. No worktree setup needed — Fixer edits directly.
39
+
40
+ **IMPORTANT:** Do NOT use the Agent tool's built-in `isolation: "worktree"` parameter for Fixer dispatch. That creates an ephemeral branch and auto-cleans on exit, losing commits. We manage our own worktrees via `worktree-harvest.cjs` which keeps the Fixer on the same fix branch.
41
+
42
+ Acquire single-writer lock before edits (skip if `DRY_RUN_MODE=true`):
43
+
44
+ Compute dynamic TTL based on the number of eligible bugs:
45
+ ```
46
+ ELIGIBLE_COUNT = <number of bugs with Referee confidence >= 75%>
47
+ DYNAMIC_TTL = max(1800, ELIGIBLE_COUNT * 600) # 10 min per bug, minimum 30 min
48
+ ```
49
+
50
+ ```
51
+ node "$SKILL_DIR/scripts/fix-lock.cjs" acquire ".bug-hunter/fix.lock" $DYNAMIC_TTL
52
+ ```
53
+ If lock cannot be acquired, stop Phase 2 to avoid concurrent mutation.
54
+
55
+ **Lock renewal:** During Step 9 execution, renew the lock after each bug fix to prevent TTL expiry on long runs:
56
+ ```
57
+ node "$SKILL_DIR/scripts/fix-lock.cjs" renew ".bug-hunter/fix.lock"
58
+ ```
59
+
60
+ **8b. Detect verification commands**
61
+
62
+ Detect and store:
63
+ - `TEST_COMMAND`
64
+ - `TYPECHECK_COMMAND`
65
+ - `BUILD_COMMAND`
66
+
67
+ Use the same detection order as before. Missing commands should be stored as `null`.
68
+
69
+ **8c. Capture pre-fix baseline (flaky test detection)**
70
+
71
+ If `TEST_COMMAND` is not null:
72
+ 1. Run it once (timeout 5 minutes). Record pass/fail counts and failure identifiers.
73
+ 2. Run it a **second time** (timeout 5 minutes). Record pass/fail counts and failure identifiers.
74
+ 3. Compare the two runs:
75
+ - Tests that **failed in both** runs → `BASELINE_FAILURES` (stable failures, pre-existing)
76
+ - Tests that **failed in only one** run → `FLAKY_TESTS` (non-deterministic)
77
+ - Tests that **passed in both** runs → reliable tests
78
+ 4. Store both `BASELINE_FAILURES` and `FLAKY_TESTS` as separate sets.
79
+
80
+ **Flaky test rule (applies in Steps 10a, 10b, 10c):** When checking for new failures after a fix, a test failure that matches `FLAKY_TESTS` does NOT count as a new failure. Only failures on tests NOT in `FLAKY_TESTS` and NOT in `BASELINE_FAILURES` trigger revert decisions.
81
+
82
+ If baseline cannot run, set `BASELINE=null` and `FLAKY_TESTS={}` and continue with manual-verification warning.
83
+
84
+ **8d. Build sequential fix plan**
85
+
86
+ Prepare bug queue:
87
+ 1. Apply confidence gate:
88
+ - `ELIGIBLE` for auto-fix when Referee confidence >= 75%.
89
+ - `MANUAL_REVIEW` when confidence < 75% or missing confidence.
90
+ 2. Run global consistency pass on merged findings:
91
+ - Detect reused BUG-ID collisions.
92
+ - Detect conflicting claims on the same file/line range.
93
+ - Resolve conflicts before edits.
94
+ 3. Auto-fix queue contains `ELIGIBLE` bugs only.
95
+ 4. Sort by severity: Critical → High → Medium → Low.
96
+ 5. **Cross-file dependency ordering** (when `code-index.cjs` is available):
97
+ - Build import graph from `.bug-hunter/index.json` (or run `code-index.cjs build` if index doesn't exist).
98
+ - For each bug pair (A, B): if A's file imports B's file, B must be fixed before A (fix dependencies first).
99
+ - Within the same dependency level, maintain severity order.
100
+ - Fallback: if no index is available, keep severity-only ordering.
101
+ 6. **Dynamic canary sizing:**
102
+ ```
103
+ CANARY_SIZE = max(1, min(3, ceil(ELIGIBLE_COUNT * 0.2)))
104
+ ```
105
+ - 1–5 eligible bugs → canary 1
106
+ - 6–10 eligible bugs → canary 2
107
+ - 11+ eligible bugs → canary 3
108
+ - Build canary subset from the top `CANARY_SIZE` highest-severity eligible bugs.
109
+ 7. Keep same-file bugs adjacent.
110
+ 8. **Fixer batch sizing:**
111
+ ```
112
+ MAX_BUGS_PER_FIXER = 5
113
+ ```
114
+ - If a cluster or rollout batch exceeds 5 bugs, split into sequential fixer dispatches of at most 5 bugs each.
115
+ - Each batch gets its own dispatch → verify → checkpoint cycle.
116
+ - State persists between batches via the fix ledger.
117
+ 9. Group into small clusters (max 3 bugs per cluster) for checkpoint commits.
118
+
119
+ Report: `Fix plan: [N] eligible bugs, canary=[K], rollout=[R], manual-review=[M], fixer-batches=[B].`
120
+
121
+ ### Step 9: Execute fixes (sequential fixer)
122
+
123
+ Single writer rule: run one Fixer at a time. No parallel worktrees by default.
124
+
125
+ **Global Phase 2 timeout:** Set `PHASE2_DEADLINE` to 30 minutes from the start of Step 9. If the deadline is reached, halt remaining fixes, mark all unprocessed bugs as `SKIPPED` with reason "phase-2-timeout", and proceed to Step 10.
126
+
127
+ **Circuit breaker:** After each fix attempt (success or failure), check:
128
+ ```
129
+ FAILURE_RATE = (count of FIX_REVERTED + FIX_FAILED) / total_attempted
130
+ ```
131
+ If `FAILURE_RATE > 0.5` AND `total_attempted >= 3`:
132
+ - Halt remaining fixes immediately.
133
+ - Mark all remaining bugs as `SKIPPED` with reason "circuit-breaker-tripped".
134
+ - Report: `⚠️ Circuit breaker tripped — [X]/[Y] fixes failed. Codebase may be too unstable for auto-fix.`
135
+ - Proceed to Step 10.
136
+
137
+ Execution order:
138
+ 1. Canary batches first.
139
+ 2. Verify canary results.
140
+ 3. Continue rollout batches only if canary verification passes.
141
+
142
+ For each batch in order:
143
+ 1. Check Phase 2 timeout and circuit breaker before launching.
144
+ 2. Validate Fixer payload before launch:
145
+ ```
146
+ node "$SKILL_DIR/scripts/payload-guard.cjs" validate fixer ".bug-hunter/payloads/fixer-batch-<id>.json"
147
+ ```
148
+ 3. Permission mode:
149
+ - `APPROVE_MODE=true` → `mode: "default"`
150
+ - `APPROVE_MODE=false` → `mode: "auto"`
151
+ - `DRY_RUN_MODE=true` → Fixer reads code and outputs planned diff only, no Edit tool calls
152
+
153
+ **Path A — Worktree mode (`WORKTREE_MODE=true`):**
154
+
155
+ 4a. Prepare isolated worktree:
156
+ ```
157
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" prepare "$FIX_BRANCH" ".bug-hunter/worktrees/fixer-batch-<id>"
158
+ ```
159
+ Record `PRE_HARVEST_HEAD` from the output.
160
+
161
+ 5a. Dispatch Fixer subagent with worktree CWD:
162
+ - Compute `WORKTREE_ABS` (absolute path of the worktree directory).
163
+ - In the Fixer task instructions, include:
164
+ - `"Your working directory is: $WORKTREE_ABS"`
165
+ - `"You MUST git add + git commit each fix: fix(bug-hunter): BUG-N — [description]"`
166
+ - `"Do NOT use EnterWorktree/ExitWorktree — you are already in an isolated worktree"`
167
+ - `"Do NOT switch branches or run git checkout"`
168
+ - Do NOT set `isolation: "worktree"` on the Agent tool — we manage worktrees ourselves.
169
+ - Launch one Fixer with: `prompts/fixer.md`, batch bug subset, recon tech stack context.
170
+
171
+ 6a. After Fixer completes (or crashes), harvest commits:
172
+ ```
173
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" harvest ".bug-hunter/worktrees/fixer-batch-<id>"
174
+ ```
175
+ Read harvest result:
176
+ - If `harvestedCount > 0`: record commit hashes per BUG-ID in fix ledger.
177
+ - If `uncommittedStashed: true`: mark those bugs as `FIX_FAILED` with reason "fixer-did-not-commit".
178
+ - If `branchSwitched: true`: mark all bugs in batch as `FIX_FAILED` with reason "branch-switched".
179
+ - If `noChanges: true`: mark all bugs in batch as `SKIPPED`.
180
+
181
+ 7a. Clean up worktree:
182
+ ```
183
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" cleanup ".bug-hunter/worktrees/fixer-batch-<id>"
184
+ ```
185
+
186
+ 8a. Renew lock after each batch:
187
+ ```
188
+ node "$SKILL_DIR/scripts/fix-lock.cjs" renew ".bug-hunter/fix.lock"
189
+ ```
190
+
191
+ **Path B — Direct mode (`WORKTREE_MODE=false`):**
192
+
193
+ 4b. Launch one Fixer with:
194
+ - `prompts/fixer.md`
195
+ - Batch bug subset (max `MAX_BUGS_PER_FIXER` bugs)
196
+ - Recon tech stack context
197
+ 5b. Apply returned changes (skip if dry-run).
198
+ 6b. Commit checkpoint — **one commit per bug** (mandatory):
199
+ - `fix(bug-hunter): BUG-N — [short description]`
200
+ - Exception: if two bugs touch the same lines and cannot be separated, combine into a single commit with both BUG-IDs.
201
+ 7b. Record commit hash per BUG-ID in a fix ledger.
202
+ 8b. **Renew lock** after each bug fix:
203
+ ```
204
+ node "$SKILL_DIR/scripts/fix-lock.cjs" renew ".bug-hunter/fix.lock"
205
+ ```
206
+
207
+ If a bug cannot be fixed, mark `SKIPPED` and continue.
208
+
209
+ ### Step 10: Verify and auto-revert
210
+
211
+ **10-pre. Rejoin fix branch (worktree mode only)**
212
+
213
+ If `WORKTREE_MODE=true`:
214
+ 1. Ensure all worktrees are cleaned up:
215
+ ```
216
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" cleanup-all ".bug-hunter/worktrees"
217
+ ```
218
+ 2. Return main working tree to the fix branch:
219
+ ```
220
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" checkout-fix "$FIX_BRANCH"
221
+ ```
222
+ 3. The main working tree now has all Fixer commits. Proceed with verification.
223
+
224
+ **10a. Fast checks after each checkpoint**
225
+
226
+ After each bug commit:
227
+ - Run nearest/impacted checks first (targeted tests or module typecheck).
228
+ - If targeted checks fail with **new failures** (excluding `FLAKY_TESTS` and `BASELINE_FAILURES`), revert that bug commit immediately.
229
+
230
+ **10b. End-of-run full verification**
231
+
232
+ After all batches:
233
+ 1. Run full `TEST_COMMAND` (if available).
234
+ 2. Compare with baseline (applying flaky test exclusion):
235
+ - **New failures**: failures not in `BASELINE_FAILURES` and not in `FLAKY_TESTS`
236
+ - Unchanged pre-existing failures
237
+ - Resolved failures
238
+ 3. Run `TYPECHECK_COMMAND` and `BUILD_COMMAND` when available.
239
+
240
+ **10c. Auto-revert failing bug commits**
241
+
242
+ For each BUG-ID linked to new failures (excluding flaky tests):
243
+ 1. Revert its checkpoint commit with a **60-second timeout**:
244
+ ```
245
+ timeout 60 git revert --no-edit <hash>
246
+ ```
247
+ 2. If the revert completes successfully:
248
+ - Re-run the smallest relevant check.
249
+ - If failures clear: mark `FIX_REVERTED`.
250
+ - If failures persist: mark `FIX_FAILED`.
251
+ 3. If the revert **times out or conflicts** (exit code ≠ 0):
252
+ - Run `git revert --abort` to clean up.
253
+ - Mark `FIX_FAILED`.
254
+ - Continue to the next BUG-ID.
255
+
256
+ **10d. Post-fix targeted re-scan (severity-gated)**
257
+
258
+ Use exact fixed scope from the real base commit:
259
+ 1. Run `git diff --unified=0 "$FIX_BASE_COMMIT"..HEAD`.
260
+ 2. Build changed hunks list.
261
+ 3. Run one lightweight Hunter on changed hunks only with a **severity floor of MEDIUM**:
262
+ - Only report fixer-introduced bugs at MEDIUM severity or above.
263
+ - LOW-severity issues from the fixer are logged to `.bug-hunter/fix-report.md` as informational notes but do NOT trigger `FIXER_BUG` status.
264
+
265
+ This removes ambiguity from `<base-branch>` and works for path scans, staged scans, and branch scans.
266
+
267
+ ### Step 11: Determine final bug status
268
+
269
+ | Status | Criteria |
270
+ |--------|----------|
271
+ | FIXED | Fix landed, checks pass, no fixer-introduced issue |
272
+ | FIX_REVERTED | Fix introduced regression and was cleanly reverted |
273
+ | FIX_FAILED | Regression introduced and could not be cleanly reverted |
274
+ | PARTIAL | Minimal patch landed, larger refactor still required |
275
+ | SKIPPED | Fix not implemented (or circuit-breaker/timeout halted) |
276
+ | FIXER_BUG | Post-fix re-scan found a MEDIUM+ bug introduced by the fix |
277
+
278
+ ### Step 12: Restore user state and report
279
+
280
+ **12-pre. Worktree cleanup (safety net)**
281
+
282
+ If `WORKTREE_MODE=true`:
283
+ ```
284
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" cleanup-all ".bug-hunter/worktrees"
285
+ ```
286
+ If main tree is still detached, restore to fix branch:
287
+ ```
288
+ node "$SKILL_DIR/scripts/worktree-harvest.cjs" checkout-fix "$FIX_BRANCH"
289
+ ```
290
+ If checkout-fix fails, fall back to `ORIGINAL_BRANCH`:
291
+ ```
292
+ git checkout "$ORIGINAL_BRANCH"
293
+ ```
294
+
295
+ **12a. Stash restore**
296
+
297
+ If stash was created (not applicable in dry-run mode):
298
+ 1. Attempt automatic restore (`git stash pop`).
299
+ 2. If restore succeeds, report `stash_restored=true`.
300
+ 3. If restore conflicts, stop and report clear conflict instructions; do not discard stash.
301
+
302
+ Always release single-writer lock at the end (success or failure path):
303
+ ```
304
+ node "$SKILL_DIR/scripts/fix-lock.cjs" release ".bug-hunter/fix.lock"
305
+ ```
306
+ If an earlier step aborts Phase 2, run the same release command AND worktree cleanup-all in best-effort cleanup before returning.
307
+
308
+ Present:
309
+ - Fix summary by status
310
+ - Verification summary (baseline vs final, including flaky test exclusions)
311
+ - Circuit breaker status (tripped or not)
312
+ - Files modified
313
+ - Fix details per BUG-ID
314
+ - Git info:
315
+ - Fix branch
316
+ - Base commit (`FIX_BASE_COMMIT`)
317
+ - Review command: `git diff "$FIX_BASE_COMMIT"..HEAD`
318
+ - Stash restore outcome
319
+
320
+ **12a. Write machine-readable fix report**
321
+
322
+ Write `.bug-hunter/fix-report.json` alongside the markdown report:
323
+
324
+ ```json
325
+ {
326
+ "version": "3.0.0",
327
+ "fix_branch": "<branch name>",
328
+ "base_commit": "<FIX_BASE_COMMIT>",
329
+ "dry_run": false,
330
+ "circuit_breaker_tripped": false,
331
+ "phase2_timeout_hit": false,
332
+ "fixes": [
333
+ {
334
+ "bugId": "BUG-1",
335
+ "severity": "CRITICAL",
336
+ "status": "FIXED",
337
+ "files": ["src/api/users.ts"],
338
+ "lines": "45-49",
339
+ "commit": "<commit hash>",
340
+ "description": "SQL injection via unsanitized query parameter"
341
+ },
342
+ {
343
+ "bugId": "BUG-4",
344
+ "severity": "MEDIUM",
345
+ "status": "FIX_REVERTED",
346
+ "files": ["src/queue.ts"],
347
+ "lines": "112-118",
348
+ "commit": "<reverted commit hash>",
349
+ "reason": "test regression in queue.test.ts"
350
+ }
351
+ ],
352
+ "verification": {
353
+ "baseline_pass": 45,
354
+ "baseline_fail": 3,
355
+ "flaky_tests": 2,
356
+ "final_pass": 47,
357
+ "final_fail": 1,
358
+ "new_failures": 0,
359
+ "resolved_failures": 2,
360
+ "typecheck_pass": true,
361
+ "build_pass": true,
362
+ "fixer_bugs_found": 0
363
+ },
364
+ "summary": {
365
+ "total_confirmed": 10,
366
+ "eligible": 7,
367
+ "manual_review": 3,
368
+ "fixed": 5,
369
+ "fix_reverted": 1,
370
+ "fix_failed": 0,
371
+ "skipped": 1,
372
+ "fixer_bug": 0,
373
+ "partial": 0
374
+ }
375
+ }
376
+ ```
377
+
378
+ Rules:
379
+ - `dry_run: true` when `DRY_RUN_MODE=true` — the `fixes` array contains planned diffs instead of commit hashes.
380
+ - `circuit_breaker_tripped: true` when the circuit breaker halted the pipeline.
381
+ - `phase2_timeout_hit: true` when the 30-minute deadline was reached.
382
+ - This JSON enables CI/CD gating, dashboard ingestion, and automated ticket creation.
383
+
384
+ If `LOOP_MODE=true`, continue to fix-loop rules for unresolved bugs.
@@ -0,0 +1,212 @@
1
+ # Large Codebase Strategy (> FILE_BUDGET×3 files)
2
+
3
+ This mode handles truly large codebases (monorepos, enterprise apps, 200+ source files) that cannot be audited in a single pass or even a single `--loop` run. It replaces the naive "flat chunk by position" approach with domain-aware, multi-tier scanning.
4
+
5
+ ## Why the standard modes fail at scale
6
+
7
+ 1. **Recon overflows**: Classifying 1,000+ files in one pass exhausts context before scanning starts.
8
+ 2. **Flat chunking loses domain context**: A Hunter scanning `auth/login.ts` + `billing/invoice.ts` in the same chunk has no coherent understanding of either domain.
9
+ 3. **Cross-service bugs are invisible**: The most dangerous bugs live at service boundaries (auth → payments, orders → inventory), but flat chunks never group these together.
10
+ 4. **Skeptic/Referee see everything at once**: Merging 50+ findings into one Skeptic pass is itself a context overflow.
11
+
12
+ ## The Strategic Approach: Domain-First, Tiered Scanning
13
+
14
+ ### Tier 0: Rapid Recon (already done by triage)
15
+
16
+ **If triage was run (Step 1)**, Tier 0 is already complete. The triage JSON at `.bug-hunter/triage.json` contains:
17
+ - `domains`: all domains with tier classification, file counts, and risk breakdown
18
+ - `domainFileLists`: per-domain file paths — use these directly as the file list for each Tier 1 domain audit
19
+ - `fileBudget`, `scanOrder`, `tokenEstimate`
20
+
21
+ Read the triage JSON and proceed directly to Tier 1. Do NOT re-scan the filesystem.
22
+
23
+ **If triage was NOT run** (e.g., Recon was invoked directly), do a structural scan:
24
+
25
+ 1. **Discover the domain map** using directory structure:
26
+ ```bash
27
+ # Use whichever tool is available:
28
+ # fd: fd -t d --max-depth 2 . <target> | head -50
29
+ # find: find <target> -maxdepth 2 -type d | head -50
30
+ # ls: ls -d <target>/*/ <target>/*/*/ 2>/dev/null | head -50
31
+ ```
32
+ 2. **Count files per domain**:
33
+ ```bash
34
+ # fd: fd -e ts -e js -e py -e go -e rs . "$dir" | wc -l
35
+ # find: find "$dir" -type f \( -name '*.ts' -o -name '*.js' \) | wc -l
36
+ # ls -R: ls -R "$dir" | wc -l (rough estimate)
37
+ ```
38
+ 3. **Classify domains (not files) by risk**:
39
+ - CRITICAL domains: auth, payments, security, API gateways, middleware
40
+ - HIGH domains: core business logic, database models, state management
41
+ - MEDIUM domains: utilities, helpers, formatting, UI components
42
+ - LOW domains: tests, docs, config, scripts, migrations
43
+
44
+ 4. **Write the domain map** to `.bug-hunter/domain-map.json`:
45
+ ```json
46
+ {
47
+ "domains": [
48
+ { "path": "packages/auth", "tier": "CRITICAL", "fileCount": 42 },
49
+ { "path": "packages/billing", "tier": "CRITICAL", "fileCount": 38 },
50
+ { "path": "packages/api-gateway", "tier": "CRITICAL", "fileCount": 25 },
51
+ { "path": "packages/orders", "tier": "HIGH", "fileCount": 56 },
52
+ { "path": "packages/notifications", "tier": "MEDIUM", "fileCount": 31 },
53
+ { "path": "packages/ui-components", "tier": "LOW", "fileCount": 120 }
54
+ ],
55
+ "totalFiles": 512,
56
+ "criticalFiles": 105,
57
+ "highFiles": 156,
58
+ "mediumFiles": 131,
59
+ "lowFiles": 120
60
+ }
61
+ ```
62
+
63
+ This is fast — no file reading, just directory listing and heuristic classification.
64
+
65
+ ### Tier 1: Domain-Scoped Deep Audits
66
+
67
+ Process ONE domain at a time, running the **full pipeline** (Recon → Hunter → Skeptic → Referee) within each domain:
68
+
69
+ ```
70
+ For each domain (CRITICAL first, then HIGH, then MEDIUM):
71
+ 1. Get this domain's file list:
72
+ - If triage exists: use triage.domainFileLists[domainPath]
73
+ - If no triage: use fd/find to list files in this domain's directory
74
+ 2. Run Recon on THIS domain only → domain-specific risk map and tech stack
75
+ 3. Run Hunter on THIS domain only → domain-specific findings
76
+ 4. Run Skeptic on THIS domain's findings only → challenges
77
+ 5. Run Referee on THIS domain only → confirmed bugs
78
+
79
+ Write domain results to:
80
+ .bug-hunter/domains/<domain-name>/recon.md
81
+ .bug-hunter/domains/<domain-name>/findings.md
82
+ .bug-hunter/domains/<domain-name>/skeptic.md
83
+ .bug-hunter/domains/<domain-name>/referee.md
84
+
85
+ Record in state:
86
+ node "$SKILL_DIR/scripts/bug-hunter-state.cjs" record-findings ...
87
+ ```
88
+
89
+ **Why this works**: Each domain audit is self-contained. The Hunter scanning `packages/auth` has full context of the auth domain — middleware, models, routes, utils — all in one coherent pass. The Skeptic only has to validate 3-8 findings from that domain, not 50 from everywhere.
90
+
91
+ **Domain size handling**: If a single domain exceeds FILE_BUDGET, chunk it using the existing Extended mode chunking, but WITHIN the domain boundary. This keeps domain coherence even when chunking.
92
+
93
+ ### Tier 2: Cross-Domain Boundary Audit
94
+
95
+ After all individual domains are audited, run a **boundary-focused pass** that specifically targets service interaction points:
96
+
97
+ 1. **Identify boundary files**: Files that import from or are imported by other domains.
98
+ Use whichever search tool is available:
99
+ ```bash
100
+ # rg: rg -l "from ['\"]\.\./(auth|billing|orders)" packages/api-gateway/
101
+ # grep: grep -rl "from.*\.\./auth\|from.*\.\./billing" packages/api-gateway/
102
+ # Read: manually read entry files of each domain and trace cross-domain imports
103
+ ```
104
+
105
+ 2. **Build boundary pairs**: Group files by the domains they connect:
106
+ ```
107
+ auth ↔ api-gateway: [gateway/auth-middleware.ts, auth/token-service.ts]
108
+ billing ↔ orders: [orders/checkout.ts, billing/charge.ts]
109
+ auth ↔ billing: [billing/subscription-guard.ts, auth/permissions.ts]
110
+ ```
111
+
112
+ 3. **For each boundary pair**: Run a focused Hunter scan that reads files from BOTH domains simultaneously. The Hunter prompt should emphasize:
113
+ - Trust boundary violations (does domain A trust unvalidated data from domain B?)
114
+ - Contract mismatches (does the caller assume a return type the callee doesn't guarantee?)
115
+ - Race conditions across domain boundaries
116
+ - Auth/permission gaps between services
117
+
118
+ 4. **Challenge + Verify** boundary findings through the normal Skeptic → Referee pipeline.
119
+
120
+ Write boundary results to `.bug-hunter/domains/_boundaries/`.
121
+
122
+ ### Tier 3: Merge and Report
123
+
124
+ After all domains + boundaries are audited:
125
+
126
+ 1. Read all domain `referee.md` files and boundary results.
127
+ 2. Merge findings, deduplicate by file + line + claim.
128
+ 3. Renumber BUG-IDs globally.
129
+ 4. Build the final report per Step 7 in SKILL.md.
130
+
131
+ ## State Management for Large Codebases
132
+
133
+ Use `.bug-hunter/state.json` with domain-aware structure:
134
+
135
+ ```json
136
+ {
137
+ "mode": "large-codebase",
138
+ "domainMap": ".bug-hunter/domain-map.json",
139
+ "domains": {
140
+ "packages-auth": { "status": "done", "findings": 5, "confirmed": 3 },
141
+ "packages-billing": { "status": "in_progress", "findings": 0, "confirmed": 0 },
142
+ "packages-orders": { "status": "pending", "findings": 0, "confirmed": 0 }
143
+ },
144
+ "boundaries": {
145
+ "auth-billing": { "status": "pending" },
146
+ "auth-api-gateway": { "status": "pending" }
147
+ },
148
+ "totalConfirmed": 3,
149
+ "lastUpdated": "2026-03-10T00:00:00Z"
150
+ }
151
+ ```
152
+
153
+ **Resume**: If the process is interrupted, read state and skip domains with status `done`. Resume from the first `pending` or `in_progress` domain.
154
+
155
+ ## When to use `--loop` with large-codebase mode
156
+
157
+ `--loop` wraps the domain iteration in a ralph-loop. Each loop iteration processes ONE domain (or one boundary pair). This means:
158
+ - Iteration 1: Tier 0 (rapid recon + domain map)
159
+ - Iteration 2: Tier 1 domain "auth" (full pipeline)
160
+ - Iteration 3: Tier 1 domain "billing" (full pipeline)
161
+ - ...
162
+ - Iteration N-2: Tier 2 boundary audits
163
+ - Iteration N-1: Tier 3 merge and report
164
+ - Iteration N: Coverage check → DONE or continue with missed domains
165
+
166
+ The ralph-loop's coverage check reads the state file and only marks DONE when all CRITICAL and HIGH domains show status `done`.
167
+
168
+ ## Optimization: Skip LOW domains
169
+
170
+ For truly huge codebases (1,000+ files), skip LOW-tier domains entirely unless `--exhaustive` is specified. UI components, test utilities, and formatting helpers rarely contain runtime bugs worth the context cost.
171
+
172
+ Report skipped domains in the final report:
173
+ ```
174
+ ℹ️ Skipped [N] LOW-tier domains ([M] files) for efficiency.
175
+ Use `--exhaustive` to include all domains.
176
+ ```
177
+
178
+ ## Optimization: Delta-first for repeat scans
179
+
180
+ If `.bug-hunter/state.json` exists from a previous run AND `--delta` is specified:
181
+ 1. Run `git diff --name-only <last-commit>` to find changed files.
182
+ 2. Map changed files to their domains.
183
+ 3. Re-audit ONLY the affected domains (not the whole codebase).
184
+ 4. Re-run boundary audit only for boundaries involving affected domains.
185
+
186
+ This makes repeat scans on large codebases take minutes instead of hours.
187
+
188
+ ## Context Budget for Large Codebases
189
+
190
+ Each domain audit uses its own context budget independently:
191
+ - Domain Recon: lightweight (just this domain's files)
192
+ - Domain Hunter: FILE_BUDGET applies to this domain's files only
193
+ - Domain Skeptic: only this domain's findings
194
+ - Domain Referee: only this domain's findings + challenges
195
+
196
+ If a single domain exceeds FILE_BUDGET, it gets its own Extended-mode chunking within the domain boundary. The key insight is: **chunking happens within domains, not across them**.
197
+
198
+ ## Checklist for the Orchestrator
199
+
200
+ When executing large-codebase mode:
201
+
202
+ - [ ] Tier 0: Run rapid recon, produce domain map
203
+ - [ ] Tier 1: For each CRITICAL domain, run full pipeline
204
+ - [ ] Tier 1: For each HIGH domain, run full pipeline
205
+ - [ ] Tier 1: For each MEDIUM domain, run full pipeline (or skip if --fast)
206
+ - [ ] Tier 2: Identify boundary pairs from cross-domain imports
207
+ - [ ] Tier 2: Run boundary-focused Hunter on each pair
208
+ - [ ] Tier 2: Challenge + verify boundary findings
209
+ - [ ] Tier 3: Merge all domain + boundary findings
210
+ - [ ] Tier 3: Deduplicate and renumber
211
+ - [ ] Tier 3: Build final report with per-domain breakdown
212
+ - [ ] Coverage: All CRITICAL/HIGH domains done? If not, continue.