# newinspiration.md — peer-extension inspiration notes (validated against pi-lens code)

> Status: **draft notes, untracked** (matches the `docs/inspiration_*` pattern — gitignored under `.gitignore:50`, see also `docs/inspiration_gograph.md`, `docs/inspiration_neovim.md`, `docs/inspiration_neovim2.md`).
> Source set: [gjczone/pi-shazam](https://github.com/gjczone/pi-shazam), [YuGiMob/pi-hashline-edit-pro](https://github.com/YuGiMob/pi-hashline-edit-pro), [ZachDreamZ/pi-dep-audit](https://github.com/ZachDreamZ/pi-dep-audit), [heyhuynhgiabuu/pi-search](https://github.com/heyhuynhgiabuu/pi-search), [yandy/pi-packages/pi-coding-tools](https://github.com/yandy/pi-packages/tree/main/pi-coding-tools), [EstebanForge/pi-{ts,rust,php,js}-review](https://github.com/orgs/EstebanForge/repositories), [axsapronov/pi-extensions](https://github.com/axsapronov/pi-extensions).
> All "borrowed from" claims below were validated against the real pi-lens code on disk (paths/line numbers noted where relevant). Anything that didn't survive validation is marked **CLAIM CORRECTED** or **DEFERRED**.

## How this is organized

1. **Validations & corrections** — claims from the initial sketch that I checked against the actual code. The interesting ones (where my prior mental model was off) are called out.
2. **Repo-by-repo takeaways** — what's worth lifting, with concrete pi-lens target paths and current-state evidence.
3. **Prioritized port backlog** — effort/value matrix, with "what's already done in pi-lens" explicitly factored in.
4. **Explicit non-ports** — patterns that *look* useful but would be regressions if copied.

---

## 1. Validations & corrections

This section exists because the initial sketch made several claims I needed to verify. Where I was wrong, the correction is here with evidence.

### 1.1 What I was right about

| Claim | Evidence (real pi-lens code) |
|---|---|
| 8 registered tools (5 agent-facing + 3 support) | `tools/ast-dump.ts`, `ast-grep-search.ts`, `ast-grep-replace.ts`, `lens-diagnostics.ts`, `lsp-diagnostics.ts`, `lsp-navigation.ts`, `module-report.ts` + `shared.ts`. Matches `tools/` listing. |
| Pre-compiled `dist/` ship | `package.json:21` `"main": "./dist/index.js"`, `"prepare": "npm run build:dist"`. |
| Hand-rolled MCP, no SDK | `mcp/server.ts` exists; no `@modelcontextprotocol/sdk` in `package.json`. |
| Word-index is BM25-only, no embeddings | `clients/word-index.ts:11-14` "no embeddings, no native deps, no daemon — pure in-process TypeScript". |
| `module_report` supports blast radius | `clients/module-report.ts:58` `blastRadius?: boolean`, `:149` returns `BlastRadius`. |
| `setActiveTools` available on host SDK | `node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts:893` `setActiveTools(toolNames: string[]): void`. |
| Repeat-failure escalation uses 300 s TTL | `clients/read-guard-tool-lines.ts:31` `const REPEAT_FAILURE_TTL_MS = 300_000;` |
| Already uses 🔴/🟡/ℹ️/📜/🛑/🔄 taxonomy widely | `clients/runtime-turn.ts`, `clients/pipeline.ts:928-943`, `clients/git-guard.ts:39`, `clients/agent-behavior-client.ts:85`, `tools/lens-diagnostics.ts`, etc. |
| `getPackageRoot` is already a memoized walker | `clients/package-root.ts:5` `packageRootCache = new Map<string, string>()`. |
| Safe-spawn is async, ambient abort signal | AGENTS.md confirms; `clients/safe-spawn.ts` is the canonical site. |

### 1.2 What I was wrong about (or underspecified)

#### CLAIM CORRECTED — "context-injection.ts" doesn't exist
The sketch said "the existing `clients/context-injection.ts` is the natural home." It doesn't exist. The actual file is **`clients/runtime-context.ts`** (80 LOC, 3 exports: `consumeTurnEndFindings`, `consumeTestFindings`, `consumeSessionStartGuidance`). Shape:

```ts
export function consumeTurnEndFindings(cacheManager, cwd) {
    const findings = cacheManager.readCache<{content: string}>("turn-end-findings", cwd);
    if (!findings?.data?.content) return;
    cacheManager.writeCache("turn-end-findings", null as ..., cwd);  // consume-once
    return {
        messages: [{
            role: "user",
            content: `[pi-lens automated check — not a user request] Address 🔴 blockers before continuing; ℹ️ advisories are informational only.\n\n${findings.data.content}`,
        }],
    };
}
```

Three implications:
- It's a **consume-once** cache read, not an additive "build up a list" surface.
- The injection is **advisory text** with a fixed prefix. A "Next: also try running `module_report blastRadius:true`" suggestion fits cleanly *inside* the `content` field at `clients/runtime-turn.ts:810` (the `ℹ️ Advisory` block), not at this layer.
- AGENTS.md confirms "raw `{role:"user"}` message on the `context` hook on purpose (keeps the user's prompt as the trailing message)". Don't try to migrate this to `before_agent_start`.

#### CLAIM CORRECTED — hashline integration is already live in pi-lens
The sketch said "pi-hashline-edit-pro is a different edit model; pi-lens keeps native edit." That's wrong. pi-lens already **deeply integrates** the hashline protocol:

- `clients/read-guard-tool-lines.ts:135-249` — `resolveHashlineEditInput` parses hashline inputs (`getHashlineOperations`, `parseHashlineAnchor`, `combineRanges`) and routes them through read-guard.
- It detects `hash_range_incl`-style inputs and treats them as native-ranged edits.
- `clients/read-guard-tool-lines.ts:226` emits a `🔴 BLOCKED — Unsupported hashline edit target` for malformed hashline payloads.

So when I talk about "porting the error-message-with-next-action discipline" from pi-hashline-edit-pro, I should actually call it "what the **pi-lens** hashline integration already does (see `unsupported_hashline_edit_target`) — extend the same pattern to non-hashline failures." Concrete target: `clients/read-guard.ts:441-559` already uses `🔄 RETRYABLE — <reason>\n\n<next action>`; the improvement is to make *every* error path emit a concrete next-action line, not just the existing few.

#### CLAIM CORRECTED — `/lens-verify` is partially redundant
The sketch proposed `/lens-verify` as a new command using shazam's `assessRisk`. But pi-lens already has **`/lens-booboo`** (`commands/booboo.ts:653` `pi.registerCommand("lens-booboo", …)`) which is "full-codebase review" and runs all dispatch runners project-wide. `commands/booboo.ts:110` even has "Centralized test file exclusion for booboo runners." The right framing for the shazam `assessRisk` borrow is **not** a new top-level command but a **verdict block at the top of the turn-end findings message** (`clients/runtime-turn.ts:810` `ℹ️ Advisory` block), produced when `assessRisk({gitFileCount, lspErrors, lspWarnings, …})` returns `level: "high"`. Lower-cost, no new command.

#### CLAIM CORRECTED — log redaction is a real gap, but pi-lens has 3 log writers
The sketch said "pi-lens's `~/.pi-lens/*.log` files contain tool output and could leak secrets via `lens_diagnostics` text dumps." Real evidence:

- `clients/read-guard-logger.ts:7-12` writes `~/.pi-lens/read-guard.log` (1 MiB rotation, env-overridable).
- `clients/actionable-warnings-logger.ts:7-12` writes `~/.pi-lens/actionable-warnings.log` (same shape).
- AGENTS.md mentions `latency.log`, `cascade.log`, `tree-sitter.log`, `sessionstart.log` — those are also writers.

`grep -rn "redact\|secret-pattern\|ghp_\|AKIA" --include="*.ts" clients/` returns **zero** hits in the log-writer paths. The shazam `redact.ts` pattern (PEM, GitHub tokens, AWS keys, JWT, etc.) is a real additive value, not redundant with `gitleaks` (which detects in source) or `fact-rules` (which gates dispatch). The redactor would apply at the **log write boundary** (logger.append()) — single integration point per log.

#### DEFERRED — claims I couldn't fully validate without deeper reading

- **"pi-lens's tool-toggle shape"** for `setActiveTools` (drawing on pi-coding-tools' `search-tools.ts:syncToolsStatus`): pi-lens doesn't currently use `setActiveTools`; it always exposes all tools. Adding it requires deciding which tools are togglable. **Defer to a real proposal.** Not a blocker.
- **"shazam's whole 9-tool surface area is bloated — don't expand pi-lens's surface"**: pi-lens has 5 agent-facing tools (`lens_diagnostics`, `module_report`, `read_symbol`, `ast_grep_search`, `ast_grep_replace`); the sketch's "8 tools" was off. Either way, the conclusion (don't bloat the surface) stands.
- **"tool-toggle for `lens_diagnostics mode=full` being opt-in"**: `mode=full` is described as "EXPENSIVE" in `tools/lens-diagnostics.ts`. A toggle is conceivable but the current `mode=delta|all|full` parameter is the right knob. **Skip.**

#### Things in the sketch that *are* correct but I now have better evidence for

- **"Single 'seam' file: `clients/lens-engine.ts`"**: 159 LOC, 8 exports, used by `mcp/server.ts` exclusively. Confirmed — this IS the seam. Any new cross-feature method belongs here.
- **"Word-index is lexical only, no embeddings, persisted in project snapshot"**: `clients/word-index.ts:11-14` confirms; consumed via `lens-engine.ts:symbolSearch`. The `RetrievalReason[]` idea from `axsapronov/pi-extensions` (`fts_match|same_package|current_file|changed_file|...`) is real lift but pi-lens would need to add path/context metadata to `WordHit` to support it. Easy, low-risk.
- **"`Symbol.for` for cross-extension status-card cooperation"**: not used in pi-lens today. The idea of `Symbol.for('pi-lens.statusCards')` is sound but `widget-state.ts:380-470 renderWidget` currently owns its own layout (file-tier sort, horizontal packing). Adopting this would mean rewriting `renderWidget` to a registry-merge pattern. Real effort; defer unless asked.

---

## 2. Repo-by-repo takeaways

### 2.1 `gjczone/pi-shazam` ★★★★★

Closest peer — tree-sitter + LSP + lifecycle hooks + MCP. Different niche (project-structure-as-query vs per-edit dispatch) but several liftable patterns.

**Concrete borrows:**

| Pattern | Pi-lens target | Why it fits |
|---|---|---|
| `core/baseline.ts:SessionBaseline` (lspErrors / lspWarnings / orphanSymbols / graphEdges / symbolCount / fileCount + newOrphans[] captured at session start, delta'd at turn end) | Extend `clients/project-snapshot.ts` with a `baseline: SessionBaseline` field; emit delta in `clients/runtime-turn.ts:810` advisory block | pi-lens already has turn-to-turn diff but not session-to-turn. A "session start: 0 errors → now: 3 errors" delta is real value. |
| `core/output.ts:NEXT_RULES` (declarative `forTools + condition + factory` engine for "after tool X, suggest tool Y") | New `clients/recommendations/next-rules.ts`; emit inside `runtime-turn.ts:810` advisory | Already has a single-shot advisory text path. Adds intra-message structure ("also try `pilens_module_report blastRadius:true`"). |
| `core/risk.ts:assessRisk({gitFileCount, newOrphanCount, orphanDelta, lspErrors?, lspWarnings?, preCommit?})` returning `{level: "low"|"medium"|"high", reason}` with preCommit vs normal thresholds | New `clients/verdict/assess-risk.ts`; verdict block at top of `runtime-turn.ts:810` | Pre-commit stricter; normal looser. Note: pi-lens's `/lens-booboo` (`commands/booboo.ts`) already groups errors; we just need the verdict prepended to turn-end. **No new command needed.** |
| `hooks/safety.ts:HIGHRISKPATTERNS` (17-entry regex table: `rm -rf`, `dd if=`, `mkfs`, `> /dev/sd`, fork-bomb, `curl|sh`, `base64|sh`, etc., whitespace-bypass aware) | New `clients/safety/dangerous-bash.ts` advisory-only | pi-lens has **zero** bash gating. The `extractReadPathsFromCommand`/`extractWrittenPathsFromCommand` in `clients/bash-file-access.ts:84,332` already tokenize the command — bolt-on path. |
| `hooks/_bash-utils.ts:tokenizeCommand` (quote/substitution/pipe-aware shell tokenizer) | New `clients/bash-tokens.ts`; refactor `clients/bash-file-access.ts` to use it | Currently `bash-file-access.ts` has its own ad-hoc tokenizer (fanout 25, complexity 32 in `extractReadPathsFromCommand`). Real consolidation win. |
| `hooks/pre-edit.ts:GLOBALCONFIGFILENAMES` (the "editing `package.json`/`tsconfig.json`/`Cargo.lock`/etc. affects the whole project" set) + multi-file edit threshold + 5-min TTL warned-groups cache | New advisory injection in `index.ts` `tool_call` (write/edit) path | pi-lens's read-guard blocks under-reads but never surfaces blast radius. `module_report blastRadius:true` is the recovery tool — cite it in the advisory. |
| `hooks/failure-recovery.ts` per-tool consecutive-failure tracker (3 fails → suggest alt; 5 fails → suggest overview; 1h TTL, eviction-on-write) | Extend `clients/runtime-tool-result.ts` | pi-lens has read-guard's repeat-failure escalation (`🔄 RETRYABLE` → `🛑 RE-READ REQUIRED` at 300s TTL, `read-guard-tool-lines.ts:31`) but doesn't propose alternatives. The "5 fails → suggest reorient" pattern is the lift. |
| `core/redact.ts` (PEM, GitHub `ghp_/gho_/ghu_/ghs_/ghr_`, AWS `AKIA…`, Slack `xox*`, Stripe `sk_/rk_`, JWT `eyJ…`, GitLab PAT, Google API, SendGrid, OpenAI; PEM line-by-line accumulator) | New `clients/redact/secrets.ts`; apply at log-write boundaries in `clients/read-guard-logger.ts`, `clients/actionable-warnings-logger.ts`, latency-logger, cascade-logger, sessionstart-log | Real gap. `gitleaks`/`fact-rules` cover source; this covers logs. AGENTS.md "Reproduce then re-read" guidance already implies log hygiene matters. |
| `core/audit-log.ts:rotateAuditLog` (10 MB / 5 archives / 30d age / cascade rename `.4→.5 … .log→.log.1`) | Update existing 1-MiB rotations in `read-guard-logger.ts:11`, `actionable-warnings-logger.ts:11` | Trivial. Default values: keep `1048576` (1 MiB); the rotation logic is the reusable bit. |
| `mcp/tools.ts` async-mutex pattern (`let _writeLock: Promise = Promise.resolve(); withLogLock(fn) => prev.then(fn, fn)`) | `clients/redact/secrets.ts` writer | Pi-lens log writers currently use `fs.appendFileSync` (sync in log path); the shazam chained-promise pattern is the async equivalent. |
| `core/encoding.ts:FileTooLargeError` (custom error with `path`/`size`/`limit`) | Audit file-read sites for size guards | Most pi-lens paths are bounded already (lsp wait budgets); minor. |
| `core/graph.ts:RepoGraph.targetToSources` reverse index for O(1) edge cleanup | Additive field on `clients/review-graph/` types | pi-lens's review-graph has `computeImpactCascade` (one-hop, AGENTS.md) and `computeTransitiveImpact` (depth-bounded BFS for `module_report`'s blastRadius). A `targetToSources` map on the graph would speed the *cleanup* path when files are removed. Low priority — only matters at >5k-file scale. |
| `core/treesitter.ts` runtime type stubs (because `@types/tree-sitter` doesn't cover web-tree-sitter 0.25) | Cross-check against pi-lens's `clients/tree-sitter-client.ts` | Real divergence risk per AGENTS.md on the lua-grammar corruption gotcha — only matters if adding a grammar. |

**Explicit non-ports (called out so future contributors don't re-propose them):**

- pi-shazam's **MCP stack using `@modelcontextprotocol/sdk`** (`mcp/entry.ts:6-7`) — pi-lens deliberately hand-rolls the JSON-RPC transport because the SDK would weigh every install (`mcp.md` + AGENTS.md on `--omit=dev`).
- pi-shazam's **9-tool agent surface** (`shazam_overview`/`shazam_lookup`/`shazam_impact`/`shazam_verify`/`shazam_format`/`shazam_rename_symbol`/`shazam_safe_delete`/…) — pi-lens has 5 agent-facing tools, all with purpose.
- pi-shazam's **`core/git-hooks.ts` pre-commit-hook installer** — writes a bash script into `.git/hooks/pre-commit` and calls `npx shazam_verify` via the MCP bin. pi-lens has `commands/booboo.ts` for user-invoked full-codebase review; auto-installing git hooks is out of scope.
- pi-shazam's **`lsp/setup.ts` install-instructions table** — pi-lens has a much richer installer (`clients/installer/index.ts` with npm/pip/gem/github/maven/archive strategies + tool-registry-consistency tests).

### 2.2 `YuGiMob/pi-hashline-edit-pro` ★★★ (mostly orthogonal)

Strict-semantics hashline edit dialect. Pi-lens **already** integrates hashline via `read-guard-tool-lines.ts:135-249` (`resolveHashlineEditInput`), so the protocol itself is in-house. The interesting bits are the *patterns*, not the implementation:

- **Error-code discipline with next-action** (`[E_BAD_SHAPE]`/`[E_BAD_REF]`/`[E_LEGACY_SHAPE]`/`[E_INVALID_PATCH]`/`[E_BARE_HASH_PREFIX]`/`[E_STALE_ANCHOR]`/`[E_AMBIGUOUS_ANCHOR]`). Each error carries an explicit recovery instruction. Pi-lens's read-guard already does this for some paths (`read-guard.ts:441` `🔄 RETRYABLE — Edit without read\n\nYou are trying to edit…\n\nRead the file first, then retry the edit: \`read path="${filePath}"\``); the lift is **applying the discipline uniformly** to the `out_of_range` / `unsupported_hashline_edit_target` paths that don't yet include a recovery hint.
- **`src/snapshot.ts` — file snapshot ID = `v1|{canonicalPath}|{mtimeMs}|{size}`.** Pi-lens already has stronger content-hash identity for LSP cache (AGENTS.md "LSP last-known cache is content-hash guarded"). Strict superset — no port.
- **`src/fs-write.ts:resolveTarget`** — full symlink-chain walker with `ELOOP` detection. pi-lens's `normalizeFilePath` (`clients/path-utils.ts`) is sufficient for read-guard; this is overkill for our use case.
- **`index.ts:pi.setActiveTools(active.filter(t => t !== "edit"))`** — strict semantics by removing native edit. **Not the pi-lens approach** (we layer advisory lint, not edit-replacement).

**Concrete lift:** Standardize error-message-with-next-action across all read-guard verdicts. Pattern source: `clients/read-guard-tool-lines.ts:577-578` already shows the pattern; expand it.

### 2.3 `axsapronov/pi-extensions` (code-intelligence) ★★★★

The most ambitious of the 9 repos. SQLite-backed local code graph + hybrid lexical+semantic retrieval + chokidar file-watching + embeddings + `corrections-as-learnings` pipeline + `/plan`-mode context pack + diff-review engine. Pi-lens deliberately doesn't ship an embedding service or a SQLite schema, but the **patterns** are real lifts.

**Concrete borrows:**

| Pattern | Pi-lens target | Why it fits |
|---|---|---|
| `src/pi/correctionCapture.ts` + `learnings/{extractLearning,scopeLearning,detectCorrection}.ts` (correct signal → extract via direct or model-rewrite → scope to path glob → persist with confidence/status/event-log) | **New `clients/learnings/` directory** | **Biggest single feature gap across all 9 repos.** Pi-lens has no learnings. The user-preference data exists implicitly (read-guard repeat-failures, autofix rejections, /lens-booboo interventions) but isn't captured or replayed. |
| `src/retrieval/retrieveCode.ts:RetrievalReason` taxonomy (`fts_match\|same_package\|current_file\|changed_file\|visible_file\|generated_file\|semantic_match\|sourcetestcounterpart`) | Extend `clients/word-index.ts:WordHit` with `reasons: RetrievalReason[]`; populate in `buildWordIndex` / `searchWordIndex` | Pi-lens is lexical-only today; pi-shazam/code-intel both show that *why a result matched* is high-leverage for the LLM. The same-package + changed-file + current-file boosts are deterministic from pi-lens's existing data (snapshot + reverse-deps + project-changes). |
| `src/retrieval/hybridRank.ts:mergeHybridResults` (FTS × 0.45 + vector × 0.55 score merge; reasons unioned on overlap) | New `clients/word-index/merge-hybrid.ts` or inline into `searchWordIndex` | Without embeddings the "vector" half is just `centrality` (already supported via `centralityFromReverseDeps`). Two-way merge (lexical × 0.45 + centrality × 0.55) is a real lift. |
| `src/retrieval/contextPack.ts` + `src/pi/planCommand.ts:buildPlanCommandPrompt` (research → interview → stress-test plan → commit; inject relevant context) | New `clients/context-pack/` + a `/lens-plan` command or `/lens-context` variant | Lower priority than `corrections-as-learnings`; same shape as `consumeSessionStartGuidance` but injected on a **task-content trigger** rather than just session start. |
| `src/review/{diffParser,machineChecks}.ts` (`parseUnifiedDiff` + 5 `MachineRule` kinds: `forbidden_import`, `forbidden_dependency`, `forbidden_path_edit`, `required_test_path`, intrinsic `duplicate_added_text`) | New `clients/diff-parser.ts` + `clients/diff-review/` | Pi-lens already has `parseDiffRanges` in `clients/runtime-tool-result.ts:63` (line-range diff, not full unified diff). A real `parseUnifiedDiff` + a small rules engine is a clean add. |
| `src/embeddings/EmbeddingService.ts:buildChunkEmbeddingText` (metadata-first ordering: `Path / Language / Symbol / Kind / Chunk kind / Graph context` + blank-line + `Code:`) | Skip — embeddings are out of scope | Noted as a template for *if* we ever add embeddings. |
| `src/indexing/fileWatcher.ts` chokidar with `awaitWriteFinish: {stabilityThreshold: 300, pollInterval: 100}` | Skip — pi-lens reacts to `tool_result` events, not fs-watch | Useful pattern if we ever want out-of-band "repo changed under us" detection. |
| `src/pi/progressWidget.ts` (single `Component` with width cache, layered `indexStatus / embeddingStatus / embeddingStats / indexingState`) | Skip — pi-lens has `clients/widget-state.ts` with a richer renderWidget | Different model; pi-lens renders per-file-diagnostic rows, not single-line status. |
| `src/repo/storage.ts` XDG-compliant root (`$XDG_DATA_HOME/pi-code-intelligence`) | Skip — pi-lens intentionally hardcodes `~/.pi-lens/` for global state | AGENTS.md "intentionally hardcoded" — not a regression. |
| `src/lib/changeScope.ts:ReviewSelectedScope = { mode: 'gitchanges'\|'branchdiff'\|'whole_directory', repoRoot?, branch?, baseRef?, warning?, summary, details }` | Adapt for `/lens-booboo` scope selection (`commands/booboo.ts` currently has only diff-vs-HEAD) | Pi-lens already has the diff data via `project-changes.ts`; scope selection just needs to grow. |
| `packages/sidebar/src/index.ts:STATUS_CARD_STATE_KEY = Symbol.for('pi.agent.statusCards.state')` (cross-extension cooperation via global symbol) | Add `Symbol.for('pi-lens.statusCards')` registry in `clients/widget-state.ts`; merge in `renderWidget` | Defer unless asked. Real effort: rewrite `renderWidget` (currently 91 LOC, fanout 35, complexity 27) to merge a registry. |
| `packages/subagents/src/piSubagents.ts` (persistent subagent storage, `MAX_CONCURRENCY = 4`, `MAX_TASKS = 8`, `TOOL_UPDATE_THROTTLE_MS = 150`, reuses `createAgentSession` / `withFileMutationQueue` / `serializeConversation` from host SDK) | Reference only — if pi-lens grows a delegated-verification subagent | Real reference but out of scope now. |
| `packages/cmux/src/cmux.ts:runCmux` (`isCmuxEnvironment` env-var probe + `pi.exec('cmux', args, {signal, timeout: 3000})` thin wrapper) | Skip — cmux-specific | Pattern (env-probe + thin wrapper) is reusable for any future external-binary integration. |
| `src/lifecycle/serviceRegistry.ts:ServiceRegistry` (Map-based service locator with `set/get/require/clear/keys`) | Reference for any future `serviceRegistry` need | Currently pi-lens has `clients/runtime-coordinator.ts` and `clients/lsp/index.ts` as the closest thing. |

**Explicit non-ports:**

- **SQLite schema (`db/migrations.ts` + 13 repository files).** Pi-lens is deliberately file-based (NDJSON + JSON snapshots); SQLite adds a non-Node-runtime dep and a migration system we don't need.
- **`indexWorker.ts` subprocess worker + parent-monitor pattern.** Pi-lens has `setImmediate`-deferred background work; a child process is overkill.
- **`transformersEmbeddingService.ts`** — pulls `@huggingface/transformers`, heavy.

### 2.4 `EstebanForge/pi-{ts,rust,php,js}-review` ★★★

Four near-identical packages. Each registers one `{lang}_review` tool that runs `git diff` in 5 modes (`working`/`staged`/`all`/`commit`/`range`), loads a sibling `extensions/{lang}-flaws.md` rubric, and asks the LLM to return findings with corrected snippets + a verdict (Approve / Request Changes / Needs Discussion).

**Concrete borrows:**

| Pattern | Pi-lens target | Why it fits |
|---|---|---|
| "diff + rubric → LLM judge" workflow | **New `/lens-review-diff <mode>` slash command** (`index.ts:599-985` registers 9 existing slash commands; this would be the 10th) | Pi-lens currently emits *machine-checked* findings (LSP, biome, ruff, ast-grep, …); it does not emit *LLM-judged* findings from a curated rubric. The 4 reviews prove the pattern is cheap (~300 LOC + a ~150-line `.md`). The right rubric for pi-lens would target mistakes pi-lens's dispatch misses: read-guard autopatches that silently changed semantics, file-sequence mismatches across multi-file edits, the `@ts-expect-error`-without-expect-error antipattern, etc. |
| Sibling-asset lazy load: `import.meta.url` + `fileURLToPath` + memoize-only-on-success | New `clients/lazy-asset.ts`; audit existing lazy loaders (e.g. `clients/package-root.ts` already memoizes but doesn't retry-on-failure) | The "memoize only on success so a transient read failure doesn't pin a degraded message for the process lifetime" comment in pi-ts-review's `extensions/index.ts` is the right discipline. |
| Severity schema `StringEnum(['Bug/Critical', 'Suggestion', 'Nit', 'Good pattern'])` | Skip | Semantically different from pi-lens's `actionable-warnings` vs `code-quality-warnings` split. Don't try to unify. |

**Explicit non-ports:**

- The **full review tool itself** (one tool per language × 4 packages). Pi-lens's per-edit dispatch is the right architecture for that niche; the rubric pattern is the lift, not the package.
- The **"focus on what static analyzers miss"** framing. Apply it to the pi-lens rubric but don't replicate the per-language taxonomy.

### 2.5 `heyhuynhgiabuu/pi-search` ★★★

Five research tools (`websearch`/`codesearch`/`context7`/`deepwiki`/`web_fetch`) backed by Exa MCP (no key) or direct REST (`EXA_API_KEY` set). Clean separation: provider clients + per-tool files + `config.ts` (env > `~/.pi/pi-search.json` > defaults) + `errors.ts` (coded errors).

**Concrete borrows:**

| Pattern | Pi-lens target | Why it fits |
|---|---|---|
| `src/errors.ts` coded-error taxonomy (19 codes, kebab-style, **stable across versions**; adding a new code is non-breaking, changing/removing is breaking) | Adopt for model-visible error surfaces in pi-lens | Pi-lens's read-guard already uses the 🔄/🛑 headers but the *codes* aren't formalized. A small enum of `code: "edit_underread" \| "edit_stale" \| "edit_outofrange" \| "hashline_unsupported_target" \| …` would let the LLM branch on stable strings across versions. |
| `src/config.ts` env > `~/.pi/{name}.json` (or `PI_*_CONFIG_PATH`) > defaults | Add `PI_LENS_CONFIG_PATH` env override | Currently pi-lens resolves project config via `findPiLensProjectConfig`; global config path is hardcoded in `getPiLensGlobalConfigPath`. Allowing an override is useful for tests + multi-user machines. |
| `src/mcp/client.ts` JSON-RPC-over-HTTP with SSE parsing | Skip — pi-lens is an MCP **server**, not a client | Reusable *if* pi-lens ever needs to consume an MCP server (e.g. to talk to another extension's MCP). Noted as a template. |
| Dual-provider pattern (key-set → REST, else MCP fallback) | Skip for now | Could apply to pi-lens's lazy install path (private mirror vs public installer). Out of scope. |

**Explicit non-ports:**

- The **tools themselves** (`websearch`/`codesearch`/`context7`/`deepwiki`/`web_fetch`) — pi has built-in equivalents and the host SDK exposes `aio-webfetch`/`aio-websearch`/`aio-webmap`/etc.

### 2.6 `yandy/pi-packages/pi-coding-tools` ★★

Token-efficient code-understanding tools. Adds `astgrepsearch`/`astgrepreplace`/`lsp_symbols`/`lsp_hover`/`lsp_navigate` and enables pi's `ls`/`find`/`grep` (off by default).

**Concrete borrows:**

| Pattern | Pi-lens target | Why it fits |
|---|---|---|
| `src/search-tools.ts:syncToolsStatus` (computed set diff against `pi.getActiveTools()`, then `pi.setActiveTools([...current])`) | Reference for if/when `pilens_diagnostics mode=full` becomes opt-in | Pattern is clean but pi-lens doesn't currently need it. |
| `src/config.ts:loadConfig` 3-level fallback (`project ?? global ?? DEFAULT`) | Already in pi-lens (e.g. `loadPiLensProjectConfig`) — no port | Same shape, already present. |

**Explicit non-ports:**

- `astgrepsearch`/`astgrepreplace` (pi-lens has `clients/dispatch/runners/ast-grep-napi.ts`).
- `lsp_symbols`/`lsp_hover`/`lsp_navigate` (pi-lens has `tools/lsp-navigation.ts` and `clients/module-report.ts`; `module_report` is strictly richer than `lsp_symbols`).

### 2.7 `ZachDreamZ/pi-dep-audit` ★

`/audit` slash command + `dep-audit`/`dep-fix` tools querying OSV.dev, `npm outdated --json`, license copyleft detection.

**Concrete borrows:** None. Pi-lens has strictly more:

- `trivy fs --scanners vuln,secret,license` is a session-scan runner + per-edit dispatch runner (`clients/dispatch/runners/trivy-config.ts` for IaC).
- `govulncheck` for Go CVEs reachable from code (`clients/govulncheck-client.ts`).
- `gitleaks` for committed secrets (`clients/gitleaks-client.ts`).
- Trivy license risk as a 📜 advisory (`clients/runtime-turn.ts:505`).
- Trivy CRITICAL CVEs as 🔴 blockers (`clients/runtime-turn.ts:479`).
- Auto-install of all three binaries.

The `dep-fix --dry-run` parameter is consistent with pi-lens's `runAutofix` shape — note that, no port.

### 2.8 `axsapronov/pi-extensions` (other 5 packages) ★

- **`pi-sidebar`** — TUI status-card pattern with `Symbol.for('pi.agent.statusCards.state')`. Noted; defer.
- **`pi-todos`** — `TodoWrite` tool + sidebar status card. Out of scope (pi-lens doesn't have a todo concept).
- **`pi-subagents`** — durable subagent sessions, `MAX_CONCURRENCY=4`. Out of scope now.
- **`pi-cmux`** — cmux-specific `pi.exec` wrapper. Out of scope.
- **`pi-web-tools`** — couldn't read (`src/` 404 in tree map). Likely web search/fetch duplicates of host SDK equivalents. Skip.

---

## 3. Prioritized port backlog

Sorted by `value × (1 / effort)`. "Already done" column says which ideas are partially or fully in pi-lens today (so the new effort is "extend", not "create").

| # | Source | Idea | Effort | Value | Already in pi-lens? |
|---|---|---|---|---|---|
| 1 | code-intel `correctionCapture.ts` | **New `clients/learnings/`** (signal detect → extract → scope → persist) | L | High | None |
| 2 | shazam `core/baseline.ts` | Session-start `SessionBaseline` field on `project-snapshot.json`; turn-end delta in advisory block | M | High | Turn-to-turn diff exists; not session-to-turn |
| 3 | shazam `core/output.ts:NEXT_RULES` | New `clients/recommendations/next-rules.ts`; emit inside `runtime-turn.ts:810` ℹ️ advisory | M | High | Single-shot advisory text path exists |
| 4 | shazam `core/risk.ts:assessRisk` | New `clients/verdict/assess-risk.ts`; verdict block at top of `runtime-turn.ts:810` advisory | M | Med | `/lens-booboo` (`commands/booboo.ts`) already groups errors; just prepend a verdict line |
| 5 | shazam `hooks/safety.ts:HIGHRISKPATTERNS` | New `clients/safety/dangerous-bash.ts` advisory-only (no blocking) | S | Med | Zero bash gating today |
| 6 | shazam `hooks/_bash-utils.ts:tokenizeCommand` | New `clients/bash-tokens.ts`; refactor `clients/bash-file-access.ts` (fanout 25, complexity 32) to use it | M | Med | `bash-file-access.ts` has its own ad-hoc tokenizer |
| 7 | shazam `hooks/pre-edit.ts:GLOBALCONFIGFILENAMES` | New advisory injection in `index.ts` `tool_call` (write/edit) for multi-file or global-config edits | S | Med | Read-guard blocks under-reads; never surfaces blast radius |
| 8 | shazam `hooks/failure-recovery.ts` | Per-tool consecutive-failure tracker in `runtime-tool-result.ts`; suggest reorient after 5× | S | Med | `read-guard-tool-lines.ts:31` has 300s TTL; doesn't propose alternatives |
| 9 | shazam `core/redact.ts` | New `clients/redact/secrets.ts`; apply at log-write boundaries (`read-guard-logger.ts`, `actionable-warnings-logger.ts`, latency/cascade/sessionstart loggers) | S | Med | Zero log redaction today (gitleaks covers source only) |
| 10 | code-intel `RetrievalReason[]` taxonomy | Extend `clients/word-index.ts:WordHit` with `reasons: RetrievalReason[]`; populate from snapshot + reverse-deps + project-changes | M | Med | Pure lexical ranking today |
| 11 | code-intel `hybridRank.ts:mergeHybridResults` | FTS × 0.45 + centrality × 0.55 score merge inside `searchWordIndex` | S | Med | Centrality already supported (`centralityFromReverseDeps`); no merge step |
| 12 | code-intel `parseUnifiedDiff` + `MachineRule` engine | New `clients/diff-parser.ts` + `clients/diff-review/` | M | Med | `parseDiffRanges` exists (`runtime-tool-result.ts:63`) — line-ranges only |
| 13 | pi-search `errors.ts` coded taxonomy | Adopt stable kebab-style codes for model-visible error surfaces | M | Med | 🔄/🛑 headers exist; codes are ad-hoc strings |
| 14 | hashline error-message-with-next-action discipline | Standardize recovery hint at end of every read-guard verdict | S | Med | Partially done in `read-guard.ts:441,470,513,559` |
| 15 | pi-coding-tools `syncToolsStatus` | Defer — needs a real "togglable tools" proposal | M | Low | Not currently needed |
| 16 | shazam `RepoGraph.targetToSources` | Additive reverse-index field on review-graph | S | Low | Only matters at >5k-file scale |
| 17 | EstebanForge `lazy-asset` | New `clients/lazy-asset.ts`; memoize-only-on-success discipline | S | Low | `clients/package-root.ts:5` already memoizes (without retry-on-failure) |
| 18 | shazam `core/audit-log.ts` rotation policy | Bump `MAX_LOG_BYTES` from 1 MiB to 10 MiB; cascade rename `.1→.2 → log→.1` | XS | Low | Both loggers rotate but at 1 MiB |
| 19 | pi-search `PI_*_CONFIG_PATH` env | Add `PI_LENS_CONFIG_PATH` env override on global config path | XS | Low | `getPiLensGlobalConfigPath` is hardcoded |
| 20 | EstebanForge "diff + rubric → LLM judge" | New `/lens-review-diff <mode>` slash command + a pi-lens-specific rubric | M | Med | Pi-lens has machine-checked findings only; no LLM-judged |
| 21 | code-intel `planCommand.ts` `/plan` mode | New `/lens-plan` slash command that injects a `ContextPack` (module-report outlines + blast radius for files mentioned in the task) | M | Med | `consumeSessionStartGuidance` injects on session start; not on task content |
| 22 | pi-sidebar `Symbol.for` registry | Add `Symbol.for('pi-lens.statusCards')` shared registry; rewrite `widget-state.ts:renderWidget` (fanout 35, complexity 27) to merge | L | Low | Defer unless explicitly asked |
| 23 | pi-dep-audit (whole repo) | None | — | — | Strictly subsumed by `trivy` + `govulncheck` + `gitleaks` |

---

## 4. Explicit non-ports (avoid re-litigating)

These were considered and dropped. Listed here so future contributors don't re-propose them.

| Pattern from | Reason not to port |
|---|---|
| pi-shazam's `@modelcontextprotocol/sdk` MCP server | Pi-lens deliberately hand-rolls (AGENTS.md "MCP mirror" + `--omit=dev` rationale). The SDK would weigh every install. |
| pi-shazam's 9-tool surface (overview/lookup/impact/verify/changes/format/find_tests/rename/safe_delete) | Pi-lens has 5 agent-facing tools with purpose; bloating it would dilute the LLM's tool choice. |
| pi-shazam's `.git/hooks/pre-commit` installer | Out of scope; user-invoked `/lens-booboo` is the equivalent. |
| pi-shazam's `lsp/setup.ts` install-instructions table | Pi-lens has a much richer installer (`clients/installer/index.ts`) with tool-registry-consistency tests. |
| pi-shazam's PageRank computation | Not currently needed (pi-lens has reverse-dep centrality + BM25). |
| pi-hashline-edit-pro's hashline protocol itself | Already integrated (`clients/read-guard-tool-lines.ts:135-249`). Only the error-message discipline is reusable. |
| pi-hashline-edit-pro's `pi.setActiveTools(active.filter(t => t !== "edit"))` strict-semantics stance | Contradicts pi-lens's "layer advisory lint, don't replace the edit tool" model. |
| pi-extensions code-intel's SQLite schema + 13 repository files | Pi-lens is deliberately file-based; SQLite adds a runtime dep + migration system. |
| pi-extensions code-intel's `indexWorker.ts` subprocess worker | Pi-lens has `setImmediate`-deferred background work; child process is overkill. |
| pi-extensions code-intel's `@huggingface/transformers` embedding service | Heavy; embeddings are explicitly out of scope per `clients/word-index.ts:11-14`. |
| pi-extensions code-intel's `XDG_DATA_HOME` data dir | AGENTS.md "intentionally hardcoded" `~/.pi-lens/` for global state. |
| EstebanForge's 4-package "one tool per language" structure | Pi-lens's per-edit dispatch is the right architecture for the rubric niche; the rubric pattern is the lift, not the package. |
| EstebanForge's `StringEnum(['Bug/Critical', 'Suggestion', 'Nit', 'Good pattern'])` severity schema | Semantically different from pi-lens's `actionable-warnings` vs `code-quality-warnings` split. Don't unify. |
| pi-coding-tools' `astgrepsearch`/`astgrepreplace` | Pi-lens has `clients/dispatch/runners/ast-grep-napi.ts` as a per-edit runner. |
| pi-coding-tools' `lsp_symbols`/`lsp_hover`/`lsp_navigate` | Pi-lens has `tools/lsp-navigation.ts` and `clients/module-report.ts`; `module_report` is strictly richer than `lsp_symbols`. |
| pi-search's research tools | Pi has host SDK equivalents + `aio-webfetch`/`aio-websearch`/etc. |
| pi-dep-audit's OSV.dev wrapper | Strictly subsumed by `trivy` + `govulncheck`. |

---

## 5. Sequencing suggestion

If acting on this backlog in order, the natural batches are:

**Batch A (small, low risk, high learning):** items 5, 6, 8, 9, 14, 17, 18, 19 — all S-effort, all in the read-guard / log / bash-token seams that already have test coverage. Net new files: 1 (`bash-tokens.ts`), 1 (`dangerous-bash.ts`), 1 (`redact/secrets.ts`), 1 (`lazy-asset.ts`). Modifications to existing files are surgical.

**Batch B (medium effort, advisory/text-content only):** items 3, 4, 13, 20 — all emit text into `runtime-turn.ts:810` advisory block or as new slash-command output. No new abstractions, just disciplined text generation. Highest "density of value per line of code."

**Batch C (medium-large, requires testing on real projects):** items 2, 7, 10, 11, 12, 21 — touch `project-snapshot.ts`, `index.ts` `tool_call`, `word-index.ts`, new diff-parser/review dir. Need project-scale tests (the `tests/fixtures/tool-smoke/` pattern from AGENTS.md would apply).

**Batch D (large, deferred):** items 1, 16, 22 — `clients/learnings/` is a multi-week effort (correctness on real user corrections is hard); `targetToSources` is only worth it at scale; `Symbol.for` status-card registry requires rewriting `renderWidget`.

---

## Appendix A — pi-lens file paths referenced

For grep-ability:
- Read-guard + tool-lines: `clients/read-guard.ts`, `clients/read-guard-tool-lines.ts`, `clients/read-guard-logger.ts`
- Bash hooks: `clients/bash-file-access.ts`
- Word index: `clients/word-index.ts`
- Widget: `clients/widget-state.ts`
- Context injection: `clients/runtime-context.ts`
- Turn-end: `clients/runtime-turn.ts`, `clients/runtime-tool-result.ts`
- Slash commands: `index.ts:599-985`
- Lens engine seam: `clients/lens-engine.ts`
- MCP mirror: `mcp/server.ts`, `mcp/analyze-cli.ts`, `mcp/worker.ts`, `clients/mcp/{analyze,host-shim,ipc,review,session}.ts`
- Dispatch runners: `clients/dispatch/runners/*.ts` (47 total per AGENTS.md; 107 entries in `clients/dispatch/runners/`)
- Project snapshot / project changes / reverse deps: `clients/{project-snapshot,project-changes,reverse-deps}.ts`
- Logs: `clients/read-guard-logger.ts`, `clients/actionable-warnings-logger.ts`, `clients/latency-logger.ts`, `clients/cascade-logger.ts`, `clients/ast-grep-tool-logger.ts`
- Tools: `tools/{lens-diagnostics,lsp-navigation,lsp-diagnostics,module-report,ast-dump,ast-grep-search,ast-grep-replace,shared,lsp-structured-output}.ts`
- Commands: `commands/booboo.ts`

## Appendix B — corrections vs initial sketch (TL;DR)

1. **"context-injection.ts" → it's `clients/runtime-context.ts`** (80 LOC, consume-once cache read, fixed `[pi-lens automated check]` prefix).
2. **Hashline integration is already live** — `clients/read-guard-tool-lines.ts:135-249`. Error-discipline pattern is in-house; lift to non-hashline paths.
3. **`/lens-verify` is redundant with `/lens-booboo`** — emit a verdict line at the top of the turn-end advisory instead.
4. **Log redaction is a real gap** but bounded — 3 main log writers (`read-guard`, `actionable-warnings`, latency/cascade/sessionstart), zero redaction today.
5. **Pi-lens has 5 agent-facing tools, not 8** — counting was off. Tool surface is already right-sized.
6. **`setActiveTools` IS on the host SDK** — `node_modules/@earendil-works/pi-coding-agent/dist/core/extensions/types.d.ts:893`. The "togglable tools" idea is feasible; just not currently needed.
7. **Word-index is "the lexical half of hybrid ranking"** — `clients/word-index.ts:11-14`. The author already framed it for the merge step; we just need to do it.
