# Path-leak fix — `--neutral-path` (item #6)

date: 2026-06-20 · file: `orchestrator/gate.py` · test: `tests/test_gate_neutral_path.py` (3/3 green) · memory: [[single-file-cell-path-leak]]

## The leak
The gate injects the target path into the prompt (`REVIEW TARGET: {{MODULE_PATH}}`) and the LLM agent reads the file from that path. Corpus cells live at `domains/security/corpus/<CELL-ID>/...` where `<CELL-ID>` names the defect (`S4-kb-spaceids-sqli`). So a measurement run **leaks the answer through the path string** — recall measured this way is inflated by a signal production never has (real repo dirs are not named after their bugs). Two injection sites confirmed: the single-file `module_path` (was the raw target) and the bundle's inner `// ===== REVIEW TARGET: <relpath> =====` header.

## The fix — opt-in, zero production regression
`gate.py --neutral-path` (default **OFF**):
- **single-file:** target CONTENT is copied to a generically-named temp file (`review_target_<rand>.ts`), reviewed with `cwd=/tmp` → no cell-id in the injected path AND none reachable by `pwd`.
- **bundle:** the TARGET header renders `review_target.ts` instead of the relpath; dep bodies keep their real import names (those are legit cross-file context, not the leak).
- **default path unchanged** — production keeps real repo paths as legitimate review context (a file in `auth/` legitimately signals auth code). The flag is a MEASUREMENT safety-net so a leaky corpus dir cannot prime even if a cell was not relocated to a neutral path by hand.

This is the "path-blind gate.py" the memory calls the real fix (vs. the fragile per-cell manual relocation).

## Conformance (deterministic, MEASURED)
`tests/test_gate_neutral_path.py`: `_neutral_label` strips dir+basename keeps ext; `build_bundle(neutral=True)` header carries no cell-id while `neutral=False` preserves the real relpath (no-regression); `write_neutral_file` copies exact body under a generic name. 3/3 green; `test_gate_emit.py`+`test_gate.py` 22/22 no-regression.

## Residual + RATE-PENDING (no-false-coverage)
- **Residual (documented, not closed):** the neutral BUNDLE keeps `cwd=dirname(target)` (the real cell dir) so dep imports resolve — an agent that runs `pwd` could still see the cell dir. The PRIMARY documented vector (the injected prompt string) is closed; single-file (the common corpus shape) has no residual (`cwd=/tmp`).
- **RATE-PENDING:** the recall change from removing the path signal is **UNMEASURED this session** (directive: do not roll). Blinding can only make recall HARDER (removes an unfair hint), so it cannot inflate — but the honest no-cheat recall RATE under `--neutral-path` requires k≥3 rolls and is NOT claimed here. Mechanism shipped + conformance-green; the re-measurement is the open follow-up.
