@herbertgao/pi-extensions 2026.9.2 → 2026.9.3

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 (221) hide show
  1. package/README.md +3 -2
  2. package/THIRD_PARTY_NOTICES.md +24 -0
  3. package/node_modules/@herbertgao/sol-pi/LICENSE +19 -0
  4. package/node_modules/@herbertgao/sol-pi/README.md +159 -0
  5. package/node_modules/@herbertgao/sol-pi/SECURITY.md +26 -0
  6. package/node_modules/@herbertgao/sol-pi/THIRD_PARTY_NOTICES.md +19 -0
  7. package/node_modules/@herbertgao/sol-pi/agents-install.md +150 -0
  8. package/node_modules/@herbertgao/sol-pi/assets/sol-pi-hero.png +0 -0
  9. package/node_modules/@herbertgao/sol-pi/docs/compatibility.md +69 -0
  10. package/node_modules/@herbertgao/sol-pi/docs/configuration.md +75 -0
  11. package/node_modules/@herbertgao/sol-pi/package.json +76 -0
  12. package/node_modules/@herbertgao/sol-pi/scripts/check-pi-compat.mjs +32 -0
  13. package/node_modules/@herbertgao/sol-pi/scripts/check-sol-pi-config.mjs +120 -0
  14. package/node_modules/@herbertgao/sol-pi/sol-pi.example.json +10 -0
  15. package/node_modules/@herbertgao/sol-pi/src/sol-pi/config.ts +135 -0
  16. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/file-queue.ts +74 -0
  17. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/index.ts +185 -0
  18. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/action-fusion/then-run.ts +128 -0
  19. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/archive.ts +53 -0
  20. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/candidate.ts +101 -0
  21. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/config.ts +71 -0
  22. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/index.ts +220 -0
  23. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/journal.ts +25 -0
  24. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/provider.ts +164 -0
  25. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/evidence-preserving-reducer/receipt.ts +177 -0
  26. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/index.ts +227 -0
  27. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/ledger.ts +20 -0
  28. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/observation-pack/observation.ts +252 -0
  29. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/economics.ts +237 -0
  30. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/extension.ts +455 -0
  31. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/index.ts +49 -0
  32. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/plan.ts +79 -0
  33. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/state.ts +208 -0
  34. package/node_modules/@herbertgao/sol-pi/src/sol-pi/extensions/online-context-compact/tools.ts +100 -0
  35. package/node_modules/@herbertgao/sol-pi/src/sol-pi/index.ts +42 -0
  36. package/node_modules/@herbertgao/sol-pi/src/sol-pi/runtime-paths.ts +17 -0
  37. package/node_modules/@herbertgao/sol-pi/src/sol-pi/tui.ts +71 -0
  38. package/node_modules/@narumitw/pi-btw/dist/index.ts +12 -2
  39. package/node_modules/@narumitw/pi-btw/dist/index.ts.map +2 -2
  40. package/node_modules/@narumitw/pi-btw/package.json +1 -1
  41. package/node_modules/@narumitw/pi-btw/src/btw.ts +13 -2
  42. package/node_modules/pi-lens/CHANGELOG.md +176 -0
  43. package/node_modules/pi-lens/README.md +13 -8
  44. package/node_modules/pi-lens/config/dependency-cruiser-eager-allowlist.json +3 -1
  45. package/node_modules/pi-lens/dist/clients/analysed-root.js +1 -0
  46. package/node_modules/pi-lens/dist/clients/ast-grep-tool-logger.js +1 -1
  47. package/node_modules/pi-lens/dist/clients/biome-client.js +13 -2
  48. package/node_modules/pi-lens/dist/clients/bounded-telemetry.js +2 -0
  49. package/node_modules/pi-lens/dist/clients/cache-observability.js +122 -1
  50. package/node_modules/pi-lens/dist/clients/complexity-client.js +5 -0
  51. package/node_modules/pi-lens/dist/clients/config-diagnostic-codes.js +2 -0
  52. package/node_modules/pi-lens/dist/clients/config-resolve.js +6 -3
  53. package/node_modules/pi-lens/dist/clients/config-schema.js +17 -0
  54. package/node_modules/pi-lens/dist/clients/config-warn.js +2 -2
  55. package/node_modules/pi-lens/dist/clients/dead-code-client.js +8 -1
  56. package/node_modules/pi-lens/dist/clients/dependency-checker.js +5 -1
  57. package/node_modules/pi-lens/dist/clients/dispatch/dispatcher.js +38 -15
  58. package/node_modules/pi-lens/dist/clients/dispatch/facts/function-facts.js +1 -1
  59. package/node_modules/pi-lens/dist/clients/dispatch/facts/import-facts.js +5 -1
  60. package/node_modules/pi-lens/dist/clients/dispatch/runners/actionlint.js +2 -1
  61. package/node_modules/pi-lens/dist/clients/dispatch/runners/biome-check.js +2 -3
  62. package/node_modules/pi-lens/dist/clients/dispatch/runners/cpp-check.js +4 -3
  63. package/node_modules/pi-lens/dist/clients/dispatch/runners/credo.js +2 -1
  64. package/node_modules/pi-lens/dist/clients/dispatch/runners/cue-vet.js +2 -1
  65. package/node_modules/pi-lens/dist/clients/dispatch/runners/dart-analyze.js +2 -1
  66. package/node_modules/pi-lens/dist/clients/dispatch/runners/detekt.js +2 -1
  67. package/node_modules/pi-lens/dist/clients/dispatch/runners/dotnet-build.js +2 -1
  68. package/node_modules/pi-lens/dist/clients/dispatch/runners/elixir-check.js +2 -1
  69. package/node_modules/pi-lens/dist/clients/dispatch/runners/eslint.js +2 -1
  70. package/node_modules/pi-lens/dist/clients/dispatch/runners/fish-indent.js +2 -1
  71. package/node_modules/pi-lens/dist/clients/dispatch/runners/gleam-check.js +2 -1
  72. package/node_modules/pi-lens/dist/clients/dispatch/runners/go-vet.js +2 -1
  73. package/node_modules/pi-lens/dist/clients/dispatch/runners/golangci-lint.js +2 -1
  74. package/node_modules/pi-lens/dist/clients/dispatch/runners/hadolint.js +2 -1
  75. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-lint.js +3 -1
  76. package/node_modules/pi-lens/dist/clients/dispatch/runners/helm-render.js +2 -1
  77. package/node_modules/pi-lens/dist/clients/dispatch/runners/htmlhint.js +2 -1
  78. package/node_modules/pi-lens/dist/clients/dispatch/runners/javac.js +2 -1
  79. package/node_modules/pi-lens/dist/clients/dispatch/runners/ktlint.js +2 -1
  80. package/node_modules/pi-lens/dist/clients/dispatch/runners/lsp.js +19 -1
  81. package/node_modules/pi-lens/dist/clients/dispatch/runners/markdownlint.js +3 -2
  82. package/node_modules/pi-lens/dist/clients/dispatch/runners/mypy.js +2 -1
  83. package/node_modules/pi-lens/dist/clients/dispatch/runners/oxlint.js +2 -1
  84. package/node_modules/pi-lens/dist/clients/dispatch/runners/php-lint.js +2 -1
  85. package/node_modules/pi-lens/dist/clients/dispatch/runners/phpstan.js +2 -1
  86. package/node_modules/pi-lens/dist/clients/dispatch/runners/prisma-validate.js +2 -1
  87. package/node_modules/pi-lens/dist/clients/dispatch/runners/psscriptanalyzer.js +12 -12
  88. package/node_modules/pi-lens/dist/clients/dispatch/runners/pyright.js +2 -1
  89. package/node_modules/pi-lens/dist/clients/dispatch/runners/rubocop.js +2 -1
  90. package/node_modules/pi-lens/dist/clients/dispatch/runners/ruff.js +2 -2
  91. package/node_modules/pi-lens/dist/clients/dispatch/runners/rust-clippy.js +12 -11
  92. package/node_modules/pi-lens/dist/clients/dispatch/runners/shellcheck.js +2 -1
  93. package/node_modules/pi-lens/dist/clients/dispatch/runners/shfmt.js +2 -1
  94. package/node_modules/pi-lens/dist/clients/dispatch/runners/spellcheck.js +2 -2
  95. package/node_modules/pi-lens/dist/clients/dispatch/runners/spotbugs.js +2 -1
  96. package/node_modules/pi-lens/dist/clients/dispatch/runners/sqlfluff.js +3 -2
  97. package/node_modules/pi-lens/dist/clients/dispatch/runners/stylelint.js +3 -2
  98. package/node_modules/pi-lens/dist/clients/dispatch/runners/swiftlint.js +2 -1
  99. package/node_modules/pi-lens/dist/clients/dispatch/runners/taplo.js +2 -1
  100. package/node_modules/pi-lens/dist/clients/dispatch/runners/terragrunt.js +2 -1
  101. package/node_modules/pi-lens/dist/clients/dispatch/runners/tflint.js +2 -1
  102. package/node_modules/pi-lens/dist/clients/dispatch/runners/trivy-config.js +2 -1
  103. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/availability-policy.js +5 -0
  104. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/candidate-probe.js +2 -2
  105. package/node_modules/pi-lens/dist/clients/dispatch/runners/utils/runner-helpers.js +8 -2
  106. package/node_modules/pi-lens/dist/clients/dispatch/runners/vale.js +2 -1
  107. package/node_modules/pi-lens/dist/clients/dispatch/runners/yamllint.js +4 -3
  108. package/node_modules/pi-lens/dist/clients/dispatch/runners/zig-check.js +2 -1
  109. package/node_modules/pi-lens/dist/clients/effective-config.js +12 -2
  110. package/node_modules/pi-lens/dist/clients/extension-log.js +2 -0
  111. package/node_modules/pi-lens/dist/clients/file-role.js +18 -1
  112. package/node_modules/pi-lens/dist/clients/finding-delivery-gate.js +4 -0
  113. package/node_modules/pi-lens/dist/clients/formatters.js +54 -188
  114. package/node_modules/pi-lens/dist/clients/generation-guard.js +4 -0
  115. package/node_modules/pi-lens/dist/clients/gitleaks-client.js +42 -6
  116. package/node_modules/pi-lens/dist/clients/govulncheck-client.js +48 -7
  117. package/node_modules/pi-lens/dist/clients/installer/index.js +196 -52
  118. package/node_modules/pi-lens/dist/clients/jscpd-client.js +9 -1
  119. package/node_modules/pi-lens/dist/clients/knip-client.js +9 -2
  120. package/node_modules/pi-lens/dist/clients/language-profile.js +12 -2
  121. package/node_modules/pi-lens/dist/clients/latency-logger.js +2 -0
  122. package/node_modules/pi-lens/dist/clients/lens-config.js +4 -0
  123. package/node_modules/pi-lens/dist/clients/lsp/config.js +36 -7
  124. package/node_modules/pi-lens/dist/clients/lsp/diagnostic-binding.js +24 -1
  125. package/node_modules/pi-lens/dist/clients/lsp/document-drift.js +78 -0
  126. package/node_modules/pi-lens/dist/clients/lsp/index.js +281 -45
  127. package/node_modules/pi-lens/dist/clients/lsp/server.js +62 -15
  128. package/node_modules/pi-lens/dist/clients/lsp/workspace-diagnostics-cache.js +37 -4
  129. package/node_modules/pi-lens/dist/clients/mcp/analyze.js +3 -0
  130. package/node_modules/pi-lens/dist/clients/mcp/session.js +2 -0
  131. package/node_modules/pi-lens/dist/clients/opengrep-client.js +2 -0
  132. package/node_modules/pi-lens/dist/clients/package-manager.js +2 -1
  133. package/node_modules/pi-lens/dist/clients/php-cs-fixer-config.js +8 -3
  134. package/node_modules/pi-lens/dist/clients/pipeline.js +3 -2
  135. package/node_modules/pi-lens/dist/clients/project-diagnostics/fresh-fetch.js +38 -10
  136. package/node_modules/pi-lens/dist/clients/project-diagnostics/runner-adapters/gitleaks.js +10 -9
  137. package/node_modules/pi-lens/dist/clients/project-lens-config.js +3 -0
  138. package/node_modules/pi-lens/dist/clients/read-guard-logger.js +2 -0
  139. package/node_modules/pi-lens/dist/clients/review-graph-logger.js +2 -0
  140. package/node_modules/pi-lens/dist/clients/ruff-client.js +18 -9
  141. package/node_modules/pi-lens/dist/clients/runtime-agent-end.js +9 -0
  142. package/node_modules/pi-lens/dist/clients/runtime-coordinator.js +5 -0
  143. package/node_modules/pi-lens/dist/clients/runtime-session.js +13 -4
  144. package/node_modules/pi-lens/dist/clients/runtime-tool-result.js +4 -1
  145. package/node_modules/pi-lens/dist/clients/runtime-turn.js +48 -1
  146. package/node_modules/pi-lens/dist/clients/security-scan-client.js +2 -2
  147. package/node_modules/pi-lens/dist/clients/session-event-guard.js +69 -1
  148. package/node_modules/pi-lens/dist/clients/sg-runner.js +2 -1
  149. package/node_modules/pi-lens/dist/clients/situational-tool-telemetry.js +108 -0
  150. package/node_modules/pi-lens/dist/clients/test-runner-client.js +291 -76
  151. package/node_modules/pi-lens/dist/clients/tool-config.js +199 -0
  152. package/node_modules/pi-lens/dist/clients/tool-cwd.js +299 -0
  153. package/node_modules/pi-lens/dist/clients/tool-probe.js +53 -0
  154. package/node_modules/pi-lens/dist/clients/tool-set-policy.js +42 -0
  155. package/node_modules/pi-lens/dist/clients/trivy-client.js +9 -1
  156. package/node_modules/pi-lens/dist/clients/turn-context.js +52 -0
  157. package/node_modules/pi-lens/dist/clients/widget-state.js +4 -3
  158. package/node_modules/pi-lens/dist/index.js +21969 -20005
  159. package/node_modules/pi-lens/dist/mcp/analyze-cli.js +3 -2
  160. package/node_modules/pi-lens/dist/mcp/server.js +135 -159
  161. package/node_modules/pi-lens/dist/tools/activate-tools.js +10 -7
  162. package/node_modules/pi-lens/dist/tools/ast-grep-outline.js +2 -13
  163. package/node_modules/pi-lens/dist/tools/ast-grep-replace.js +8 -13
  164. package/node_modules/pi-lens/dist/tools/ast-grep-search.js +83 -39
  165. package/node_modules/pi-lens/dist/tools/effective-config.js +4 -3
  166. package/node_modules/pi-lens/dist/tools/lens-diagnostic-mark.js +1 -10
  167. package/node_modules/pi-lens/dist/tools/lens-diagnostics.js +353 -85
  168. package/node_modules/pi-lens/dist/tools/lsp-diagnostics.js +21 -110
  169. package/node_modules/pi-lens/dist/tools/lsp-navigation.js +20 -44
  170. package/node_modules/pi-lens/dist/tools/module-report.js +5 -9
  171. package/node_modules/pi-lens/dist/tools/project-report.js +9 -17
  172. package/node_modules/pi-lens/dist/tools/render-compact.js +280 -1
  173. package/node_modules/pi-lens/dist/tools/symbol-search.js +2 -2
  174. package/node_modules/pi-lens/docs/agent-guide.md +3 -4
  175. package/node_modules/pi-lens/docs/agent-tools.md +46 -22
  176. package/node_modules/pi-lens/docs/configuration.md +9 -0
  177. package/node_modules/pi-lens/docs/environment-variables.md +0 -5
  178. package/node_modules/pi-lens/docs/features.md +5 -5
  179. package/node_modules/pi-lens/docs/globalconfig.md +11 -1
  180. package/node_modules/pi-lens/docs/mcp.md +13 -1
  181. package/node_modules/pi-lens/docs/pi-lens-fixer.md +71 -0
  182. package/node_modules/pi-lens/docs/pi-lens-investigator.md +15 -0
  183. package/node_modules/pi-lens/docs/pi-lens-monitor.md +88 -0
  184. package/node_modules/pi-lens/docs/pi-lens-reviewer.md +35 -0
  185. package/node_modules/pi-lens/docs/pi-lens-subagent.md +12 -4
  186. package/node_modules/pi-lens/docs/public-api-stability.md +1 -0
  187. package/node_modules/pi-lens/docs/real-harness.md +46 -0
  188. package/node_modules/pi-lens/docs/release-qa-baseline.md +5 -1
  189. package/node_modules/pi-lens/docs/servercapabilities.md +1 -6
  190. package/node_modules/pi-lens/docs/settings.md +37 -2
  191. package/node_modules/pi-lens/docs/tools_improvement2.md +4 -4
  192. package/node_modules/pi-lens/docs/tree-sitter_rules_catalog.md +1 -1
  193. package/node_modules/pi-lens/docs/usage.md +13 -3
  194. package/node_modules/pi-lens/package.json +10 -1
  195. package/node_modules/pi-lens/rules/tree-sitter-queries/typescript/sql-injection.yml +7 -3
  196. package/node_modules/pi-lens/skills/pi-lens-ast-grep/SKILL.md +8 -6
  197. package/node_modules/pi-lens/skills/pi-lens-lsp-navigation/SKILL.md +19 -9
  198. package/node_modules/pi-web-access/CHANGELOG.md +29 -0
  199. package/node_modules/pi-web-access/README.md +33 -22
  200. package/node_modules/pi-web-access/abortable.ts +17 -0
  201. package/node_modules/pi-web-access/crawl4ai.ts +204 -0
  202. package/node_modules/pi-web-access/credential-source.ts +1 -0
  203. package/node_modules/pi-web-access/curator-page.ts +20 -2
  204. package/node_modules/pi-web-access/curator-run.ts +44 -0
  205. package/node_modules/pi-web-access/curator-server.ts +3 -1
  206. package/node_modules/pi-web-access/duckduckgo.ts +1 -1
  207. package/node_modules/pi-web-access/extract.ts +57 -12
  208. package/node_modules/pi-web-access/fetch-params.ts +1 -1
  209. package/node_modules/pi-web-access/gemini-search.ts +9 -5
  210. package/node_modules/pi-web-access/index.ts +25 -18
  211. package/node_modules/pi-web-access/openai-search.ts +35 -13
  212. package/node_modules/pi-web-access/package.json +2 -2
  213. package/node_modules/pi-web-access/page-query.ts +5 -2
  214. package/node_modules/pi-web-access/query-rewrite.ts +5 -2
  215. package/node_modules/pi-web-access/serpapi.ts +220 -0
  216. package/node_modules/pi-web-access/ssrf-protection.ts +5 -1
  217. package/node_modules/pi-web-access/storage.ts +10 -0
  218. package/node_modules/pi-web-access/summary-review.ts +34 -21
  219. package/node_modules/pi-web-access/utils.ts +6 -4
  220. package/package.json +7 -4
  221. package/node_modules/pi-lens/dist/tools/ast-dump.js +0 -103
@@ -23,3 +23,74 @@ redesigned before the fix is complete.
23
23
  Verify the build and every targeted or sibling suite required by repository
24
24
  policy. Follow the shared contract's Git authority. Report what ran, what was
25
25
  skipped, and why. Use active, plain prose.
26
+
27
+ ## Standard mechanics (apply unless the brief overrides)
28
+
29
+ A fix on `clients/lsp/`, the read guard, tool registration, or session lifecycle adds or updates a real-harness scenario when the defect is only observable through the host; the scenario is the red-first proof where a unit seam cannot show it.
30
+
31
+ - Every language pi-lens supports (`LANGUAGES` in `clients/language-registry.ts`),
32
+ never one: a fix on an LSP, dispatch, cache or tool seam is stated in
33
+ language-neutral terms, names which registry entries carry the facts it
34
+ needs and which fall to the honest fallback, and its test matrix has at
35
+ least one non-TypeScript row (catalog shape 42).
36
+ - `npm run build` before any test run; rebuild between mutations. Tests run as
37
+ `PI_LENS_HOME=$PWD/.probe-home node_modules/.bin/vitest run <files> --configLoader runner`
38
+ (sweeps get `30_000`). A CI-only red is reproduced in the job's shape first
39
+ (`npm test` PATH prefix, pinned `HOME`, no `PI_LENS_HOME`).
40
+ - When a task regenerates `package-lock.json`, use the exact npm version in
41
+ `package.json`'s `packageManager` field, which is also the CI production-install pin.
42
+ - Required test set = the named files + every test that mocks (`vi.mock`) or
43
+ deep-equals a module or record you touched + `tests/config/` when you add a
44
+ real-spawn test or a fixture + the flake-shape ratchet when you touch waits.
45
+ - Never `vi.waitFor` with real timers; never a `// flake-shape` admission for
46
+ a test you wrote; never `git stash`; never edit `CHANGELOG.md` (one fragment
47
+ under `.changelog/`, exactly one top-level entry).
48
+ - Every test id, probe id or fixture name you write into a PR-body table
49
+ (state-space, writers-by-axis, population) must exist as a grep-able `it(`
50
+ title or file name in the tree at handoff. The orchestrator greps each id
51
+ before accepting the round; a table whose ids do not exist is a fabricated
52
+ claim and fails the round (2026-09-10: #2877 r3 and #2868 r3 each shipped a
53
+ 48- to 72-cell table with zero real ids).
54
+ - A claim about the HOST or the ENVIRONMENT is a transcript, not a sentence.
55
+ "pi does not re-run the factory on resume", "this failure is pre-existing on
56
+ master", "the harness cannot fire that event" — each carries the command and
57
+ output that measured it in the same environment (a probe extension against
58
+ real pi in rpc mode; the same test file run on origin/master in the same
59
+ tree). 2026-09-10: three rounds on #2866 and #2878 were built on unmeasured
60
+ host claims the verify overturned, and "pre-existing analyze-cli red" was
61
+ reported by four workers whose sandbox differed from CI and master.
62
+ - When a fix is a RULE (a scanner's scope rule, a lifecycle rule, a
63
+ classification), derive it from the source of truth and enumerate from
64
+ there — the tree-sitter grammar table, pi's pinned event types measured
65
+ live, the client's real return sites — never from a hand-written list of
66
+ the cases the reviewer named. Seven rounds on #2877 each closed the named
67
+ launderer and left the next scope kind open until round 4 generated the
68
+ scope table from the grammar.
69
+ - A change to a release-QA row (`docs/release-qa-baseline.md` +
70
+ `scripts/release-qa.mjs`) runs `node scripts/release-qa.mjs` end to end
71
+ once on the pushed head and quotes the verdict line in the body; the
72
+ row↔probe tie test cannot see a row that never passes (#2893).
73
+ - Before handoff, run `npm run preflight` last and paste its table in
74
+ `PR_BODY.md` — a handoff without it is incomplete.
75
+ - One set of template headings per PR. A fix round APPENDS `## Round N` and
76
+ edits the existing `## Observability` / `## Tests` sections in place; it
77
+ never adds a second `## Observability` (the lint reads the first one, and a
78
+ stale first section was the most common `PR body` red on 2026-09-10). Lint
79
+ the FULL body you will publish (`gh pr view <n> --json body -q .body` plus
80
+ your round), against the real `origin/master...HEAD` diff (fetch first),
81
+ not a hand-shaped diff.
82
+ - `PR_BODY.md` passes `node scripts/check-pr-body.mjs --lint-local PR_BODY.md`
83
+ before handoff. The gate requires the headings `## Summary`, `## Tests`,
84
+ `## Blast radius`, `## Class sweep`, `## Observability`, and
85
+ `## Test assessment` whenever the diff touches `tests/`; Observability
86
+ names a record literal that appears in the runtime diff, and may say
87
+ exactly "No new failure path; no record added." only when the diff adds no
88
+ failure path (no new catch, fallback or degradation branch). Record: on
89
+ 2026-09-10 most open PRs failed the PR-body check on one of these two rules.
90
+ - No Git authority unless granted: leave changes uncommitted; hand off
91
+ `PR_BODY.md` (template headings, every red and mutation quoted in ≤5 lines)
92
+ plus two optional one-liners the reviewer reads first: `Operating rule:`
93
+ (the one sentence the change enforces) and `Kept:` (what was deliberately
94
+ not changed, so a reviewer does not re-litigate it);
95
+ and `COMMIT_MSG.txt` at the worktree root. Final message: verdict line, files
96
+ changed, test totals, what could not be verified.
@@ -1,5 +1,8 @@
1
1
  # Investigator contract
2
2
 
3
+ Grep the `turnId` first when correlating rows across telemetry sinks.
4
+ Premise-first reproductions of dogfood reports go through the harness with a fixture built from the reporter's shape, before any seam is named.
5
+
3
6
  Root-cause runtime behavior from reproducible and durable evidence.
4
7
 
5
8
  Define the symptom as a question that evidence can answer. Name the time window,
@@ -13,6 +16,18 @@ and against each hypothesis and the observation that would settle it. Sweep the
13
16
  tree for the root-cause pattern and every member of the affected population.
14
17
  State the blast radius and any missing or unbounded observability.
15
18
 
19
+ For a reported defect, the first deliverable is the reporter's symptom
20
+ reproduced through the production entry point (the tool handler or host
21
+ command the reporter used), red on the current code; a seam named before
22
+ that reproduction is a hypothesis and is labelled as one. Write the report
23
+ to a file at the worktree root AND, when the delegation grants issue
24
+ access, post it on the tracking issue: a file left in a worktree is not a
25
+ durable deliverable until it is posted or committed.
26
+ When the symptom involves a language server, runner or formatter, say which
27
+ registry entries (`clients/language-registry.ts`) the diagnosis covers and
28
+ whether the reporter's language is special or merely the one observed; the
29
+ fix lane inherits that scope (catalog shape 42).
30
+
16
31
  Deliver a proven diagnosis and a concrete next step. If the task expands to an
17
32
  implementation, stop and return it to the orchestrator for a fixer delegation.
18
33
  Use concise, active, plain prose.
@@ -0,0 +1,88 @@
1
+ # pi-lens monitor — role contract
2
+
3
+ Read a LIVE pi-lens session's logs and report what the numbers say, so the
4
+ maintainer does not have to. The monitor observes; it never edits code,
5
+ never restarts anything, and never touches the session it is reading.
6
+
7
+ Read first: `AGENTS.md` (the "Recurring defect shapes" catalog, especially
8
+ shape 41: a fixed bound reached at p50 is a design defect), then
9
+ `docs/pi-lens-investigator.md` for the forensics conventions this role
10
+ inherits. This contract adds the standing readout.
11
+
12
+ ## Inputs
13
+
14
+ - `~/.pi-lens/latency.log` and `~/.pi-lens/extension.log` (JSON lines; every
15
+ row carries `pid` and `ts`). The session is the `pid` the brief names, or the
16
+ newest pid with rows in the last hour when the brief says "live".
17
+ - The previous readout for the same project when one exists (an issue comment
18
+ the brief links, or a file under the scratch directory). Every number is
19
+ reported as a delta against it when available.
20
+
21
+ ## The readout (fixed shape, one comment or file, never stdout to the session)
22
+
23
+ 1. **Session line**: pid, project root, first/last row timestamps, row count,
24
+ pi-lens version if a session-start row carries it.
25
+ 2. **Phase table**: for every `type:"phase"` value, `n | p50 | p95 | max |
26
+ total_ms`, sorted by total, top 15. Durations in ms, from `durationMs`.
27
+ 3. **Bounds reached at p50** (shape 41): every phase whose p50 is within 10%
28
+ of a declared budget or timeout in its metadata (`budgetMs`, `timeoutMs`,
29
+ `elapsedMs` ≈ budget). Name the constant when it is known
30
+ (`PI_LENS_AUX_GRACE_MS`, `TOUCH_DEBOUNCE_MS`, drift batch) and the awaited
31
+ path it sits on (tool_result, agent_end, background).
32
+ 4. **Per-server auxiliary outcomes**: from `lsp_aux_wait_outcome.metadata.outcomes[]`,
33
+ one row per `serverId | outcome | publishedThisContent`, with n and p50/p95
34
+ `elapsedMs` versus `budgetMs`.
35
+ 5. **Degradation and error lines**: counts by `kind` from the degradation
36
+ records and by `message` from `extension.log` at `level:"error"`; any
37
+ message that repeats per file or per occurrence is flagged as catalog
38
+ shape 10 with the emit site if it can be found by grep.
39
+ Also report `Situational dead weight` from the `tools` extension-log row,
40
+ including its bounded `metadata.tools` list; `[]` means every situational
41
+ tool was activated or called in the conversation. A shutdown with
42
+ `targetSessionFile` emits the ending conversation's row before a new set
43
+ opens for new, resume, or fork. Reload re-runs the extension factory but
44
+ keeps the same session file, so it preserves one conversation row. Caveat: resuming into the session you are already in still carries `targetSessionFile`, so one conversation is split into two rows and a tool activated before the resume is listed as dead weight in the second (pi exposes no current-session-file accessor; not fixed). A process restart (`pi --continue`) recovers
45
+ nothing — the restore deactivates every situational tool — so the first row
46
+ after one legitimately lists all five, and shrinks only as the model
47
+ re-activates and uses them. MCP remains connection-scoped and owns the
48
+ terminal latch.
49
+ 6. **Backlogs**: `lsp_document_drift` rows by disposition, files affected,
50
+ `driftAgeMs` p50/p95/max; `agent_end_deferred_mutation_drain` durations and
51
+ coalesced path counts; `deferred_format_file` runs with `changed:true`
52
+ versus total.
53
+ 7. **Timeouts**: `lsp_diagnostics_timeout`, `lsp_nav_request_timeout`,
54
+ `lsp_client_wait_timeout` counts with `serverIds`/`source`.
55
+ 8. **Delta**: for each of the above, the change since the previous readout,
56
+ one line each, only where the number moved by more than 20% or a new
57
+ kind appeared.
58
+ 9. **Injected context**: report injected bytes per source per turn
59
+ (`sessionGuidance`, `turnFindings`, `testFindings`, `agentNudge`,
60
+ `turnEndAdvisory`, `other`) at p50/p95, plus the repeated-findings ratio
61
+ (`injectedFindingsRepeated` divided by injected finding observations).
62
+ 10. **Findings**: at most five, each with the number that proves it, the seam
63
+ (file:line when found), and one of: `already filed #N` (search open issues
64
+ first: `gh issue list --search "<phase or kind>"`), `new`, or
65
+ `expected` (with the rule that makes it expected). A finding without a
66
+ number is not a finding.
67
+
68
+ ## Rules
69
+
70
+ - Premise first: before naming a constant or a seam, read the code that owns
71
+ it (`clients/lsp/index.ts`, `clients/pipeline.ts`, `clients/runtime-agent-end.ts`,
72
+ `clients/lsp/document-drift.ts`). The 2026-09-09 readout mis-named a
73
+ suppression window as a trailing debounce; the correction cost a round.
74
+ - Bounded output: the readout is one comment or one file. Never one line per
75
+ row of the log. Quote at most three raw rows, each cut at 300 characters.
76
+ - No repo edits, no Git commands, no restarts, no writes under `~/.pi-lens`.
77
+ Scratch files go under the working tree's `.probe-home/` or the scratch
78
+ directory the brief names.
79
+ - File nothing yourself unless the brief grants `gh`; then one comment on the
80
+ issue the brief names, never a new issue: the orchestrator decides what
81
+ becomes a lane.
82
+ - A worker that finds the logs empty or the pid absent reports exactly that
83
+ with the `ls -la` of the two files and stops.
84
+
85
+ ## Deliverable
86
+
87
+ `MONITOR.md` at the worktree root with the readout, and when `gh` is granted,
88
+ the same text as a comment on the issue the brief names (today: #2809).
@@ -1,5 +1,7 @@
1
1
  # Reviewer contract
2
2
 
3
+ Reviewers run the relevant scenario as a probe and may add a throwaway scenario directory to reproduce a finding through the real host; quote the RPC event or tool result.
4
+
3
5
  Adversarially verify a change before merge and report proven findings.
4
6
 
5
7
  Assume the implementation's claims are incomplete. Read the issue, full diff,
@@ -31,3 +33,36 @@ Check that each regression test reaches the real seam and observes an independen
31
33
  effect. Remove or mutate the claimed guard and require the test to fail for the
32
34
  intended reason. Flag tests that restate the implementation, assert setup data,
33
35
  or swap a real in-process store, sink, coordinator, or registry for a fake.
36
+
37
+ ## Language coverage is a standing attack
38
+
39
+ For any diff on an LSP, dispatch, cache, runner or tool seam, ask whether the
40
+ rule holds for every entry in `clients/language-registry.ts` or only for the
41
+ language the fixer tested. A rule keyed on `.ts`/tsserver where rust-analyzer,
42
+ pyright or gopls behave the same is a finding (catalog shape 42); probe it
43
+ with one non-TypeScript fixture through the same seam and quote the result.
44
+
45
+ ## Finding shape and disposition
46
+
47
+ Every finding is written in four moves, in this order: the smallest concrete
48
+ instance (the probe command and its output, or the failing scenario) with the
49
+ expected value beside it; one plain-language sentence saying what is wrong;
50
+ the cause and its cost in prose; the remedy, with options labelled A/B when
51
+ more than one is defensible. Symbols and `file:line` anchor the prose and
52
+ never replace it. Severity is earned by the instance: a CRITICAL or HIGH
53
+ without a reproduced failure scenario is a MEDIUM at most.
54
+
55
+ The verdict line comes first. After the findings, two fixed sections:
56
+ "Could not verify" (what was blocked and why, never implied green) and
57
+ "Named output" (the structural insight the probes could not close). A Named
58
+ output entry may carry an advisory strength — Strong, Worth exploring, or
59
+ Speculative — judged by the deletion test alone (would removing the shared
60
+ module concentrate complexity back into callers, or merely relocate it); it is
61
+ a triage aid for the orchestrator, never a severity, and never substitutes for
62
+ a reproduced instance on a finding. A verify
63
+ round ends with a disposition table for the previous round's findings —
64
+ `fixed | not fixed | new defect | withdrawn` per finding id — so the
65
+ orchestrator reads outcomes, not prose. Safe deltas (a body sentence, a
66
+ comment, a literal, a doc line) are reported as such and never counted as
67
+ actionable rounds. Borrowed shape: p3bot/library `tasks/review/pre-commit`
68
+ (finding IDs, per-item template, remediation summary), 2026-09-09.
@@ -16,7 +16,10 @@ and every member of any enumerable population. Record both sweeps.
16
16
 
17
17
  State the blast radius, including callers, durable shapes, strict parsers, and
18
18
  tool surfaces. Add bounded observability for every new failure path. Include the
19
- required changelog fragment for a code change. Report verification honestly.
19
+ required changelog fragment for a code change: ONE file under `.changelog/`;
20
+ never edit `CHANGELOG.md` itself (it is generated at release; two fixers
21
+ hand-edited it on 2026-09-09 and the orchestrator had to revert both).
22
+ Report verification honestly.
20
23
  Write active, direct prose with short sentences and consistent terms.
21
24
 
22
25
  ## Tautological tests considered harmful
@@ -26,6 +29,7 @@ or feed the expected answer in through setup. Keep the red-first failure tied to
26
29
  the defect, and mutate the guard or filter to prove the test can detect its loss.
27
30
  Mocks belong only at true process or host boundaries. When a test can use the
28
31
  real store, sink, coordinator, or registry, use it and assert the durable result.
32
+ For a whole-module mock, prefer `vi.mock("./module.js", async (importOriginal) => ({ ...(await importOriginal()), override }))` so new exports pass through by default; annotate dynamic imports as `typeof import(spec)` when needed.
29
33
 
30
34
  Git authority is separate from the role. Commit, push, or open a PR only when
31
35
  the delegation explicitly grants that authority after worktree verification.
@@ -34,11 +38,15 @@ directory, leave every change uncommitted, and write two handoff files at the
34
38
  worktree root: `PR_BODY.md` (the full PR body, transcripts pasted) and
35
39
  `COMMIT_MSG.txt` (subject, body, issue ref, trailers). Name any path inside the
36
40
  worktree that must not be committed. The orchestrator commits from those files;
37
- they are never committed themselves. Never merge.
41
+ they are never committed themselves. Never merge. Every report or artifact
42
+ the delegation asks for lives at the worktree root under the name the brief
43
+ gives it; nothing else at the root is assumed to matter. When the brief
44
+ names findings by id, the handoff answers each id with one of
45
+ `fixed | not fixed | withdrawn (why)` before any prose.
38
46
 
39
47
  A sandboxed worker may find the shared `.git` and the linked `node_modules`
40
- read-only and the network absent (the codex `workspace-write` sandbox does
41
- this; see plegma#311). Run Vitest as
48
+ read-only and the network absent (a write-confined sandbox does this; the
49
+ runner's own notes say which mode lifts it). Run Vitest as
42
50
  `node_modules/.bin/vitest run <files> --configLoader runner`, and if the
43
51
  tree-sitter grammar prefetch hangs offline, verify through direct probes of the
44
52
  built code and say so; the orchestrator re-runs the files outside the sandbox.
@@ -107,6 +107,7 @@ this policy explicitly reserves the right to change.
107
107
  | `PILENS_CFG_0006` | A config key that would modify an object's prototype (`__proto__`, `constructor`, `prototype`) was refused. | Both halves of the config core, through the shared policy in `clients/config-core/safe-object.ts`. |
108
108
  | `PILENS_CFG_0007` | Further config notices were suppressed by a bound, and this one carries the count — the WHOLE count, including anything an earlier bound in the same pipeline dropped. Nothing about the config is wrong; the notice list was truncated. | `MigrationRecordCollector.finalize` (`clients/config-core/records.ts`) — the ONE producer, reached through `finalizeRecords` by every record list: the shared resolution, the global loader's unknown-key scan, the project loader's unknown-key scan, and its legacy-document enumeration. Rendered with neutral prose and recorded under the `config-notice-suppressed` degradation kind, never `config-ignored`. |
109
109
  | `PILENS_CFG_0008` | Resolving a config failed internally, so the WHOLE file was ignored and pi-lens ran on defaults. | The two guards under the pipeline: `resolveConfig` (`clients/config-core/resolve.ts`) and the global loader's post-parse catch (`clients/lens-config.ts`). Carries the error class only, never its message. |
110
+ | `PILENS_CFG_0009` | A tool config key is unknown or names a required, non-disableable tool. | The shared model-facing tool registry (`clients/tool-config.ts`) and both pi/MCP registration surfaces. |
110
111
 
111
112
  A reserved code is registered and referenced by the deprecation registry, but
112
113
  nothing emits it today. That is deliberate: the number must be pinned before the
@@ -0,0 +1,46 @@
1
+ # Real pi harness
2
+
3
+ The real-harness lane runs the built extension inside a real `pi --mode rpc`
4
+ process. Use it when a host event, provider turn, or tool handler crosses a
5
+ process boundary that an in-process test cannot observe.
6
+
7
+ ## Five-minute scenario recipe
8
+
9
+ 1. Add `tests/fixtures/real-harness/<name>/project/` and a `script.json`.
10
+ 2. Use `withRealPi({ fixture: "<name>", script: "script.json" }, ...)`.
11
+ 3. Call `awaitAssistantTurn()` after each prompt.
12
+ 4. Call `awaitToolResult("<tool>")` for every expected tool result.
13
+ 5. Add the test to `realHarnessInclude` and the real-process-spawn ratchet.
14
+
15
+ Scripts contain turns. Each turn contains text or typed tool-call actions.
16
+ Malformed scripts fail validation before the child starts.
17
+
18
+ ## Run one file
19
+
20
+ Build first, then run one serialized file with the pinned probe home:
21
+
22
+ `PI_LENS_HOME=$PWD/.probe-home npm run test:real-harness -- tests/real-harness/scenario-1.test.ts`
23
+
24
+ The lane has a 60-second wall budget and one worker. Do not use it for tests
25
+ that can assert the same behavior through an in-process seam.
26
+
27
+ ## Hermetic home contents
28
+
29
+ The harness pins `HOME`, `PI_LENS_HOME`, and the provider observation log to a
30
+ claimed scratch directory. It copies only the scenario project fixture. The
31
+ scratch seam records an owner PID, sweeps dead entries when a run starts, and
32
+ removes the project and home in `finally`. A killed run is therefore cleaned
33
+ by the next run before it claims new directories.
34
+
35
+ ## Wall budget
36
+
37
+ Real provider startup, RPC traffic, tool execution, and teardown share the
38
+ 60-second test budget. Keep assertions on events and durable sink rows. Avoid
39
+ elapsed-time assertions inside scenarios; scheduler-sensitive timing belongs
40
+ in the serialized wall-clock lane.
41
+
42
+ ## Live mode
43
+
44
+ Live-provider mode remains a placeholder for #2826. The scripted provider is
45
+ hermetic and is the only supported provider for this lane until that issue
46
+ defines credentials, redaction, and replay rules.
@@ -17,7 +17,9 @@ first six runs — which pinned the pi-lens home but passed no environment to
17
17
  `npm` at all — put 41 records into the maintainer's real
18
18
  `~/.pi-lens/install.log` (#2619 review F1). The pack runs in a
19
19
  `git archive HEAD` export, never the live checkout, because `npm pack` fires our
20
- own `prepack` (rewrites `package.json` + `package-lock.json`) and `prepare`
20
+ own `prepack` (rewrites `package.json` + `package-lock.json`) and `prepare`.
21
+ When regenerating the lockfile, use the exact npm version in `package.json`'s
22
+ `packageManager` field (`npm@11.18.0`), matching the production-install CI job.
21
23
  (rebuilds `dist/`, downloads grammars, reinstalls git hooks).
22
24
 
23
25
  Why it exists: #2587. The four shipped skills were suspected of never
@@ -84,6 +86,7 @@ PR's packed tarball (#2700, the check #2587 was missing). `attw`
84
86
  | config-provenance | a project config is LOADED and its provenance is reportable | mcp-stdio | `tools/call` `pilens_effective_config` with the fixture file | result names the fixture's `.pi-lens.json` as a contributing document | tool result text | new — `tests/config/pi-lens-config-schema.test.ts` covers the schema, not the packaged load | — |
85
87
  | degradation-visible | a silently-ignored input is RECORDED as a degradation instead of vanishing | mcp-stdio | `tools/call` `pilens_health` with the fixture's project-tier `lsp.enabled` (a global-only setting) loaded | health text carries a `config-ignored` degradation line naming the fixture's `.pi-lens.json` | health tool result text | `clients/degradation-ledger.ts` is the reused machinery; no smoke asserts it end to end | #1605 lane 2 (availability-lifecycle): the degradation-recorded half; #1605 additionally asserts RECOVERY, which this row does not |
86
88
  | git-install-loads | a `git:` install of a pushed ref builds and loads in a real pi | git-install | `pi install git:github.com/apmantza/pi-lens@<ref>` then `get_commands` | at least 1 `lens-*` command and at least 4 skills | get_commands response JSON | `scripts/rpc-load-check.mjs` assertion, re-run against the git layout | — |
89
+ | tool-smoke-install | every npm/pip entry in the installer registry resolves on a real install | npm-install | `node <export>/scripts/smoke-tools.mjs --install --install-registry --installer-root=<installed>/` (registry `<installed>/dist/clients/installer/index.js`; about 1m 29s cold on this box for 33 entries; harness from export root) | the report shows every npm/pip entry resolved or a named legitimate skip (toolchain absent, declined), and no genuine install failure; a registry-unreachable classification leaves the lane UNMEASURED; requires network access to the npm and pip registries | install-registry JSON report | `classifyInstallOutcome` from the #2661 fixture lanes — this lane sweeps the whole npm/pip registry, where fixture lanes exercise only the entries their fixtures name | — |
87
90
 
88
91
  ## Why `skills-registered` pins the registrar
89
92
 
@@ -150,6 +153,7 @@ Ship line, from the outcomes:
150
153
  | pi did not boot with NO candidate installed | BLOCKED — no verdict | 3 | 0 |
151
154
  | pi booted, the candidate would not install or activate | do not ship, cause named on the verdict | 1 | 0 |
152
155
  | any row FAILED | do not ship | 1 | N |
156
+ | any row classified registry-unreachable (its lane UNMEASURED) | INCONCLUSIVE — no verdict, the skips are not green | 3 | N |
153
157
  | pi booted but zero rows PASSED | INCONCLUSIVE — no verdict | 3 | N |
154
158
  | any UNTESTED or SKIPPED, at least one PASS | ship with caveats, each named | 2 | N |
155
159
  | all PASS | ship | 0 | N |
@@ -6,7 +6,7 @@ server's `initialize` handshake. Generated by `node scripts/server-capabilities.
6
6
  absent on the generating host are listed under *Unavailable* — run in a
7
7
  provisioned environment (the nightly) to capture those rows.
8
8
 
9
- _Last generated: 2026-09-08 on linux; 30 servers captured, 18 unavailable._
9
+ _Last generated: 2026-09-09 on linux; 31 servers captured, 13 unavailable._
10
10
 
11
11
  ## Diagnostic mode + navigation/edit operations
12
12
 
@@ -109,7 +109,6 @@ Toolchain/binary not installed here, so capabilities weren't captured
109
109
  (many are the toolchain-gated family tracked in #241):
110
110
 
111
111
  - @prisma/language-server
112
- - @vue/language-server
113
112
  - PowerShell Editor Services (pwsh Start-EditorServices.ps1 -Stdio)
114
113
  - clangd
115
114
  - cmake-language-server
@@ -122,7 +121,3 @@ Toolchain/binary not installed here, so capabilities weren't captured
122
121
  - ocamllsp
123
122
  - rust-analyzer
124
123
  - sourcekit-lsp
125
- - typescript native (clean file)
126
- - typescript native (tsc --lsp --stdio, TS7+)
127
- - typescript-language-server
128
- - typescript-language-server (clean file)
@@ -9,6 +9,19 @@ flags in context, see [Usage](./usage.md).
9
9
  pi-lens ships with sensible defaults, so **zero configuration is needed** — it
10
10
  works out of the box. Everything below is optional tuning.
11
11
 
12
+ Tool root resolution is recorded in the pi-lens extension log as one bounded
13
+ line per session key: `cwd <kind> <tool> cwd=<path>
14
+ reason=<dispatch-root|marker:<name>|git-root|file-dir-fallback|home-cap>`.
15
+ Fallbacks also create one `tool-cwd-resolution` degradation record per tool and
16
+ session, so repeated files do not create unbounded health or log rows.
17
+
18
+ Complete MCP tool results use `COMPLETE_MCP_RESULT_INPUT_BUDGET_BYTES` (8 MiB) as
19
+ their input budget. Results above this budget
20
+ write a bounded head, an `[incomplete: N bytes omitted, budget M]` marker, and a
21
+ tail to the session log, and record one `mcp-complete-result-budget-exceeded`
22
+ degradation per session. Results at or below the budget keep the complete-log
23
+ contract.
24
+
12
25
  ## The three ways to configure pi-lens
13
26
 
14
27
  1. **Environment variables** (`PI_LENS_*`) — read at process start; set them in
@@ -60,7 +73,7 @@ column is the effective behavior when nothing is set.
60
73
  | `--no-tests` | `tests.enabled` | global | test runner **on** |
61
74
  | `--no-delta` | `delta.enabled` | global | delta mode **on** (new diagnostics only) |
62
75
  | `--lens-guard` | `guard.enabled` | global | **off** |
63
-
76
+ | `--lens-checkout-guard` | `guard.sharedCheckout` | global | **off** |
64
77
  | `--no-opengrep` | `opengrep.enabled` | global | Opengrep scanner **on** |
65
78
  | `--no-read-guard` | `readGuard.enabled` | global | read-before-edit monitor **on** |
66
79
  | `--no-lens-context` | `contextInjection.enabled` | global | context injection **on** |
@@ -70,14 +83,36 @@ column is the effective behavior when nothing is set.
70
83
  | `--lens-actionable-warning-autofix` | `actionableWarnings.autoFix.enabled` | project | **off** |
71
84
  | `--lens-actionable-warning-all` | `actionableWarnings.deltaOnly` (`false`) | global | `deltaOnly` **on** (report this turn only) |
72
85
  | `--lens-compact-tool-line` | `ui.compactToolLine` | global | **off** (two-row tool rendering) |
73
- | `--no-lazy-tools` | `tools.lazy` | global | lazy tools **on** (six situational tools start inactive) |
86
+ | `--no-lazy-tools` | `tools.lazy` | global | lazy tools **on** (five situational tools start inactive) |
87
+ | `--no-tool=<name>` | `tools.<name>.enabled` | project | every lens tool **on** |
74
88
  | `--lens-turn-end-madge` | `turnEnd.madge.enabled` | global | **off** (madge runs at session start, not per turn) |
89
+ | `--no-knip` | `knip.enabled` | project | knip analyzer **on** |
90
+ | `--no-jscpd` | `jscpd.enabled` | project | jscpd analyzer **on** |
91
+ | `--no-madge` | `madge.enabled` | project | madge analyzer **on** |
92
+ | `--no-gitleaks` | `gitleaks.enabled` | project | gitleaks analyzer **on** |
93
+ | `--no-govulncheck` | `govulncheck.enabled` | project | govulncheck analyzer **on** |
94
+ | `--no-dead-code` | `deadCode.enabled` | project | dead-code analyzer **on** |
95
+ | `--no-complexity` | `complexity.enabled` | project | complexity analyzer **on** |
75
96
 
76
97
  `--no-lazy-tools` keeps every pi-lens tool active for the whole session, so the
77
98
  advertised tool list never changes. The `pi_lens_activate_tools` loader stays
78
99
  registered and keeps its usual description; under this flag the tools it names
79
100
  are already active, so calling it is a no-op.
80
101
 
102
+ The `tools.<name>.enabled` population covers every model-facing pi and MCP
103
+ tool. The loader `pi_lens_activate_tools` and MCP lifecycle tools
104
+ `pilens_session_start`, `pilens_turn_end`, and `pilens_session_end` are
105
+ required by their host protocols and cannot be disabled. Unknown or
106
+ non-disableable names emit `PILENS_CFG_0009`.
107
+
108
+ Valid names for `tools.<name>.enabled` include `ast_grep_search`,
109
+ `ast_grep_replace`, `ast_grep_outline`, `lsp_navigation`,
110
+ `lens_diagnostics`, `lens_diagnostic_mark`, `symbol_search`,
111
+ `module_report`, `project_report`, `read_symbol`, `read_enclosing`,
112
+ `effective_config`, `analyze`, `health`, `latency`, `project_scan`, and
113
+ `rebuild`. The activation loader and MCP lifecycle tools `session_start`,
114
+ `turn_end`, and `session_end` cannot be disabled.
115
+
81
116
  `--lens-guard` is **EXPERIMENTAL and strictly opt-in**. When enabled, actual
82
117
  `git commit`/`git push` commands are blocked only for current, structured
83
118
  blocking findings (including blocking test failures); advisory/no-action-required
@@ -276,7 +276,7 @@ These categories are language-agnostic at the tool UX level even if implementati
276
276
  - Keep `items: "exports"` prominent in the docs; it is much more usable than `items: "all"` on configuration-heavy modules.
277
277
  - Include a clear `syntaxOnly: true` and “does not satisfy read guard” note in the main text, not only details.
278
278
 
279
- ## `ast_grep_dump` / `ast_dump`
279
+ ## `ast_grep_search` dump mode
280
280
 
281
281
  ### What works well
282
282
 
@@ -322,12 +322,12 @@ These categories are language-agnostic at the tool UX level even if implementati
322
322
  - For `codeAction`, include whether diagnostics were present at the requested range; an empty result is more useful if it says “no diagnostic at range” vs “server has no quickfix.”
323
323
  - For rename previews, the current summary is useful; consider adding a `filesTouched` / `editsCount` top-level summary for easier scanning.
324
324
 
325
- ## `lsp_diagnostics` and `lens_diagnostics`
325
+ ## `lens_diagnostics` (`source=session` / `source=lsp`)
326
326
 
327
327
  ### What works well
328
328
 
329
- - `lsp_diagnostics` is good for file-scoped type/error checks before builds.
330
- - `lens_diagnostics` is valuable because it includes non-LSP runners.
329
+ - `source=lsp` is good for file-scoped type/error checks before builds.
330
+ - `source=session` is valuable because it includes non-LSP runners.
331
331
 
332
332
  ### Proposed improvements
333
333
 
@@ -218,7 +218,7 @@ Rule source: `rules/tree-sitter-queries/<language>/`.
218
218
  | `no-eval` | error | security | eval() detected — security risk, never use eval |
219
219
  | `no-jump-in-finally` | warning | bug | return/break/continue/throw in finally overrides the try/catch result and silently swallows exceptions |
220
220
  | `self-assignment` | error | reliability | '{{VAR}}' is assigned to itself |
221
- | `sql-injection` | error | security | SQL injection risk — use parameterized queries, never interpolate into SQL |
221
+ | `sql-injection` | warning | security | SQL injection risk — use parameterized queries, never interpolate into SQL |
222
222
  | `switch-case-termination` | error | reliability | Switch case should end with break, return, throw, or continue |
223
223
  | `switch-non-case-labels-ts` | error | reliability | switch statements should not contain non-case labels |
224
224
  | `ts-command-injection` | error | security | Potential command injection sink — avoid child_process command execution with untrusted input |
@@ -50,9 +50,11 @@ for the consumer-facing version of this routing.
50
50
 
51
51
  pi-lens exposes these high-value tools to agents:
52
52
 
53
- - `lens_diagnostics` — cached diagnostic state; use `mode=all` before declaring
54
- work complete, and `mode=full` for an expensive project-wide LSP scan.
55
- - `lsp_navigation` / `lsp_diagnostics` — IDE-style navigation and diagnostics.
53
+ - `lens_diagnostics` — `source=session` (default) reports cached findings; an
54
+ empty cache is not proof of a clean file. If changed files have no cached
55
+ diagnostics or stale findings, use `source=lsp scope=paths` for targeted
56
+ active verification (or `scope=workspace` to sweep a whole directory/project).
57
+ - `lsp_navigation` — IDE-style code navigation (definition/references/etc.).
56
58
  - `ast_grep_search` / `ast_grep_replace` — AST-aware structural search/replace.
57
59
  - `module_report` / `read_symbol` — navigable outline and targeted symbol-body
58
60
  reads; prefer these before broad full-file reads.
@@ -105,12 +107,20 @@ pi --no-autofix # Skip auto-fix (Biome, Ruff, ESLint, stylelint, sqlflu
105
107
  pi --no-tests # Skip test runner
106
108
  pi --no-delta # Disable delta mode (show all diagnostics, not just new ones)
107
109
  pi --lens-guard # Block git commit/push when unresolved blockers exist (experimental)
110
+ pi --lens-checkout-guard # Decline git commands that rewrite the working tree while another live pi-lens session shares this dirty checkout (experimental)
108
111
  pi --no-opengrep # Disable the Opengrep security scanner (default-on auxiliary LSP)
109
112
  pi --no-read-guard # Disable the read-before-edit behavior monitor
110
113
  pi --lens-turn-summary # Persist a per-turn summary of diagnostics, autofixes, and autoformats
111
114
  pi --lens-compact-tool-line # Render tool results as one compact, theme-aware line (closes #1327)
112
115
  pi --no-lazy-tools # Keep every pi-lens tool active instead of activating the situational ones on demand
113
116
  pi --lens-turn-end-madge # Run the madge circular-dependency check at every turn end, not just at session start
117
+ pi --no-knip # Disable the knip session-start analyzer
118
+ pi --no-jscpd # Disable the jscpd session-start analyzer
119
+ pi --no-madge # Disable the madge session-start analyzer
120
+ pi --no-gitleaks # Disable the gitleaks session-start analyzer
121
+ pi --no-govulncheck # Disable the govulncheck session-start analyzer
122
+ pi --no-dead-code # Disable the dead-code session-start analyzer
123
+ pi --no-complexity # Disable the complexity session-start analyzer
114
124
 
115
125
  # Actionable warnings (all default off)
116
126
  pi --lens-actionable-warnings # Report fixable warnings at turn end
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pi-lens",
3
- "version": "4.1.5",
3
+ "version": "4.1.6",
4
4
  "type": "module",
5
5
  "description": "Real-time code feedback for pi — LSP, linters, formatters, type-checking, structural analysis & booboo",
6
6
  "repository": {
@@ -33,10 +33,13 @@
33
33
  "test:integration": "node scripts/with-test-lock.mjs -- vitest run tests/index-integration.test.ts tests/clients/lsp/integration.test.ts",
34
34
  "test:targeted": "node scripts/with-test-lock.mjs --shared -- vitest run",
35
35
  "test:watch": "vitest",
36
+ "test:real-harness": "node scripts/with-test-lock.mjs --shared -- vitest run",
37
+ "mutation:diff": "node scripts/stryker-diff.mjs --base origin/master --max-files 6",
36
38
  "hygiene": "node scripts/prune-agent-worktrees.mjs",
37
39
  "check": "node scripts/check-extensions.mjs",
38
40
  "selftest:install": "node scripts/install-selftest.mjs",
39
41
  "check:lockfile": "node scripts/check-lockfile-sync.mjs",
42
+ "preflight": "node scripts/pr-preflight.mjs",
40
43
  "knip": "node scripts/run-knip.mjs",
41
44
  "check:grammars": "node scripts/check-grammar-provenance.mjs",
42
45
  "check:grammar-load": "node scripts/check-grammar-load.mjs",
@@ -49,7 +52,9 @@
49
52
  "bench:cascade-budget": "node scripts/bench-cascade-budget.mjs",
50
53
  "bench:word-index-replacement": "node scripts/bench-word-index-replacement.mjs",
51
54
  "logs:smells": "node scripts/analyze-pi-lens-logs.mjs",
55
+ "complexity": "node scripts/complexity-report.mjs",
52
56
  "changelog:check": "node scripts/rollup-changelog.mjs --check",
57
+ "test:regen": "node scripts/regen-test-baseline.mjs",
53
58
  "changelog:release": "node scripts/changelog-release.mjs",
54
59
  "changelog:extract": "node scripts/changelog-extract.mjs",
55
60
  "release:backfill-notes": "node scripts/backfill-github-releases.mjs",
@@ -83,6 +88,7 @@
83
88
  "engines": {
84
89
  "node": ">=22.19.0"
85
90
  },
91
+ "packageManager": "npm@11.18.0",
86
92
  "files": [
87
93
  "dist/",
88
94
  "docs/",
@@ -145,5 +151,8 @@
145
151
  "@ast-grep/cli@0.45.3": true,
146
152
  "@google/genai@1.52.0": true,
147
153
  "protobufjs@7.6.5": true
154
+ },
155
+ "overrides": {
156
+ "qs": "^6.15.4"
148
157
  }
149
158
  }
@@ -1,11 +1,15 @@
1
1
  # SQL Injection Detection
2
- # Detects unsafe interpolation in SQL-like template literals
2
+ # Detects unsafe interpolation in SQL-like template literals.
3
+ # Demoted from error/blocking to warning on 2026-09-10 (maintainer): the
4
+ # query keys on the callee NAME only (query|execute|exec|run), so any
5
+ # `run(`…${x}…`)` / `exec(`…`)` in non-SQL code fires — too many false
6
+ # positives to block on. A real SQL sink needs a receiver/type signal.
3
7
  id: sql-injection
4
8
  name: SQL Injection Risk
5
- severity: error
9
+ severity: warning
6
10
  category: security
7
11
  defect_class: injection
8
- inline_tier: blocking
12
+ inline_tier: warning
9
13
  language: typescript
10
14
 
11
15
  message: "SQL injection risk — use parameterized queries, never interpolate into SQL"