pi-lens 4.4.2 → 4.4.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 (44) hide show
  1. package/CHANGELOG.md +25 -0
  2. package/dist/{chunk-2ZGIZPDG.js → chunk-2VUQMUMT.js} +6 -6
  3. package/dist/{chunk-ARJ6PLFH.js → chunk-3W7IEVVL.js} +1 -1
  4. package/dist/{chunk-5JM2524W.js → chunk-3YN6V5TV.js} +16 -15
  5. package/dist/{chunk-CF24OIYI.js → chunk-5UCAH366.js} +1 -1
  6. package/dist/{chunk-NW7BOILN.js → chunk-6STA6Z7I.js} +2 -2
  7. package/dist/{chunk-66SXUJCA.js → chunk-77M37OKR.js} +5 -3
  8. package/dist/{chunk-EETY4LF7.js → chunk-AB3YYG6N.js} +1 -1
  9. package/dist/{chunk-66VMUL7Q.js → chunk-ACXEQZOU.js} +3 -3
  10. package/dist/{chunk-3UUPUE3O.js → chunk-CMMHNUZ2.js} +31 -29
  11. package/dist/chunk-CSHFH5IN.js +17 -0
  12. package/dist/{chunk-3WA4HP4I.js → chunk-EC47DWFA.js} +6 -5
  13. package/dist/{chunk-ESBQHFMJ.js → chunk-EU63SDCG.js} +187 -79
  14. package/dist/{chunk-34WSVGEM.js → chunk-FCSOVF55.js} +78 -0
  15. package/dist/{chunk-IBRALRBR.js → chunk-FMSO6RDZ.js} +3 -2
  16. package/dist/{chunk-ODBNXWT4.js → chunk-H6MF6EVN.js} +81 -42
  17. package/dist/{chunk-XPZPXCBV.js → chunk-KDERNTCQ.js} +2 -2
  18. package/dist/chunk-KSX3TXSZ.js +69 -0
  19. package/dist/{chunk-PV6LR5P5.js → chunk-M6HSLBWY.js} +198 -4362
  20. package/dist/{chunk-XKIZ2HNN.js → chunk-MXGY6KPT.js} +6 -4
  21. package/dist/{chunk-GHB6AYCP.js → chunk-RXCOMYPY.js} +2 -2
  22. package/dist/{chunk-GZYBXISR.js → chunk-SQ4TVJBR.js} +3 -3
  23. package/dist/{chunk-VITUCP5A.js → chunk-SS36ZX4J.js} +5 -3
  24. package/dist/{chunk-PFNSLWU5.js → chunk-T6CPIZNT.js} +5 -4
  25. package/dist/{chunk-JWA5I3SR.js → chunk-VCO24T4L.js} +3 -5
  26. package/dist/{chunk-Q6ZWTCLY.js → chunk-XAGLWMJ4.js} +2 -3
  27. package/dist/{chunk-WOKKRCJ5.js → chunk-XIJZVPD5.js} +3 -2
  28. package/dist/{chunk-7ULNCDCO.js → chunk-YIUAVF7E.js} +5 -5
  29. package/dist/{chunk-GOYRYZ2R.js → chunk-YSZNHOBY.js} +63 -11
  30. package/dist/chunk-YYOIQFRS.js +4139 -0
  31. package/dist/{chunk-QZVW3AAK.js → chunk-ZWFS3OEF.js} +5 -4
  32. package/dist/index.js +1628 -1482
  33. package/dist/mcp/analyze-cli.js +1 -1
  34. package/dist/mcp/cli.js +6 -6
  35. package/dist/mcp/server.js +62 -61
  36. package/dist/mcp/worker.js +16 -15
  37. package/dist/probes/installer.js +1 -1
  38. package/docs/pi-lens-merge-policy.md +12 -4
  39. package/docs/pi-lens-reviewer.md +3 -0
  40. package/docs/pi-lens-subagent.md +5 -0
  41. package/package.json +1 -1
  42. package/dist/chunk-CO2G5PHH.js +0 -84
  43. package/dist/{chunk-IXXDFY73.js → chunk-3EFKIGZN.js} +0 -0
  44. package/dist/{chunk-OG5UUPN7.js → chunk-OCAGUNBC.js} +3 -3
package/CHANGELOG.md CHANGED
@@ -16,6 +16,31 @@ All notable changes to pi-lens will be documented in this file.
16
16
 
17
17
  ### Security
18
18
 
19
+ ## [4.4.3] - 2026-10-11
20
+
21
+ ### Added
22
+
23
+ - **Adopted out-of-root projects now get global, config-free per-file linters** — when an edit lands in a marked project outside the session root, pi-lens admits only the explicit admission list of dispatch runners that read no project config and cannot execute project code (`php-lint`, `fish-indent`), and only from global or pi-lens-managed binaries; the advisory now says the LSP plus these per-file linters run. Executable paths inside the adopted or session root are refused, including PATH entries and symlink targets. Formatting, autofix, other dispatch runners, whole-project scanners, and automatic tests stay off (refs #4242).
24
+
25
+ ### Fixed
26
+
27
+ - **LSP warms again in the published package (closes #4314)** — 4.4.2 loaded the LSP stack through a computed `import()` that esbuild could not inline, so every session logged `LSP warm failed: Cannot find module './lsp/capabilities.js'` and the LSP-backed tools went dead. The import is a literal again, and a packaging test now fails the build if any shipped file dynamic-imports something the tarball does not carry.
28
+
29
+ ### Internal
30
+
31
+ <details>
32
+ <summary>4 internal changes: tests, CI, tooling, and refactors</summary>
33
+
34
+ - **tmp-hygiene attributes a leaked root to the test file that created it** — the tmp-root interposer records one creator per entry, the serialized owner's failure message names that file beside the prefix owner, and an entry with no observed creator is labelled `created outside the test process, or the creators record was unreadable` instead of taking a prefix owner's blame. (#2912)
35
+
36
+ - Add an end-to-end witness that a save-only LSP server's diagnostics reach pi-lens exactly when `textDocument/didSave` is sent: the fake stdio server publishes only from its `didSave` branch (`FAKE_LSP_PUBLISH_ON_SAVE`), and a real `createLSPClient` reads the seeded diagnostic after a save touch and none without one (refs #3405).
37
+
38
+ - Keep a killed scanner scan's report directory inside a harness-owned root: one shared seam (`PI_LENS_TEST_SCANNER_TMPDIR`, `clients/scanner-temp-root.ts`) now parents jscpd, gitleaks, opengrep, and trivy report directories, and the MCP and real-pi test harnesses apply owned scanner roots after caller environment overrides, so even a TMPDIR-overriding child SIGKILLed mid-scan no longer strands a `pi-lens-<scanner>-*` entry in the shared tmpdir and reds `tmp-fixture-hygiene` (refs #4133). The scan-setup cleanup guard is retained as defence-in-depth.
39
+
40
+ - Flake-shape ratchet: yield the event loop between files so `@ast-grep/napi` releases each parsed tree's native memory, cutting the test file's peak RSS from ~2,049 MB (over the 2,048 MB per-worker budget) to ~313 MB (refs #4292).
41
+
42
+ </details>
43
+
19
44
  ## [4.4.2] - 2026-10-10
20
45
 
21
46
  ### Added
@@ -54,15 +54,15 @@ import {
54
54
  reviewGraphCachePath,
55
55
  terminateReviewGraphPersistWorkerForTests,
56
56
  waitForReviewGraphPersistsForTests
57
- } from "./chunk-PV6LR5P5.js";
57
+ } from "./chunk-YYOIQFRS.js";
58
58
  import "./chunk-3MED75HT.js";
59
- import "./chunk-CO2G5PHH.js";
59
+ import "./chunk-M6HSLBWY.js";
60
60
  import "./chunk-IBGIOBEE.js";
61
- import "./chunk-PNQDPDRC.js";
62
61
  import "./chunk-XIMYZ3JA.js";
63
- import "./chunk-ESBQHFMJ.js";
64
- import "./chunk-34WSVGEM.js";
62
+ import "./chunk-EU63SDCG.js";
65
63
  import "./chunk-VWCXW2E7.js";
64
+ import "./chunk-FCSOVF55.js";
65
+ import "./chunk-PNQDPDRC.js";
66
66
  import "./chunk-ZXYDQ3TZ.js";
67
67
  import "./chunk-5W3R6LFT.js";
68
68
  import "./chunk-QHJ6DQ2R.js";
@@ -78,7 +78,7 @@ import "./chunk-GAEGEPOC.js";
78
78
  import "./chunk-Z3CCVDUB.js";
79
79
  import "./chunk-L3BLXZG7.js";
80
80
  import "./chunk-2BEMIWEW.js";
81
- import "./chunk-66VMUL7Q.js";
81
+ import "./chunk-ACXEQZOU.js";
82
82
  import "./chunk-Q7DUK4LX.js";
83
83
  import "./chunk-AW7R2GWG.js";
84
84
  import "./chunk-RWWYJ623.js";
@@ -56,7 +56,7 @@ import {
56
56
  } from "./chunk-P7266HLM.js";
57
57
  import {
58
58
  getToolPath
59
- } from "./chunk-66VMUL7Q.js";
59
+ } from "./chunk-ACXEQZOU.js";
60
60
  import {
61
61
  resolveToolCwd
62
62
  } from "./chunk-Q7DUK4LX.js";
@@ -5,34 +5,35 @@ import {
5
5
  acquireWarmWordIndex,
6
6
  analyzeFile,
7
7
  summarizeWarningTiers
8
- } from "./chunk-ODBNXWT4.js";
8
+ } from "./chunk-H6MF6EVN.js";
9
9
  import "./chunk-OXXKQCSV.js";
10
10
  import "./chunk-EJIUXPBX.js";
11
+ import "./chunk-2CD5RS6M.js";
11
12
  import "./chunk-FC4RP4I2.js";
12
- import "./chunk-66SXUJCA.js";
13
+ import "./chunk-UZ3TUTRV.js";
14
+ import "./chunk-XMSXXAHW.js";
15
+ import "./chunk-77M37OKR.js";
16
+ import "./chunk-CSHFH5IN.js";
13
17
  import "./chunk-VCHXCQFG.js";
14
- import "./chunk-IXXDFY73.js";
18
+ import "./chunk-3EFKIGZN.js";
15
19
  import "./chunk-MRXKYPCS.js";
16
- import "./chunk-2CD5RS6M.js";
17
- import "./chunk-UZ3TUTRV.js";
18
- import "./chunk-EETY4LF7.js";
19
- import "./chunk-GOYRYZ2R.js";
20
+ import "./chunk-7DYBLXYA.js";
21
+ import "./chunk-AB3YYG6N.js";
22
+ import "./chunk-YSZNHOBY.js";
20
23
  import "./chunk-RPLINGVB.js";
21
24
  import "./chunk-XCJN5IJU.js";
22
25
  import "./chunk-76MWC2K6.js";
23
26
  import "./chunk-GXW6K4YJ.js";
24
27
  import "./chunk-2B73ZPOK.js";
25
- import "./chunk-XMSXXAHW.js";
26
- import "./chunk-7DYBLXYA.js";
27
- import "./chunk-PV6LR5P5.js";
28
+ import "./chunk-YYOIQFRS.js";
28
29
  import "./chunk-3MED75HT.js";
29
- import "./chunk-CO2G5PHH.js";
30
+ import "./chunk-M6HSLBWY.js";
30
31
  import "./chunk-IBGIOBEE.js";
31
- import "./chunk-PNQDPDRC.js";
32
32
  import "./chunk-XIMYZ3JA.js";
33
- import "./chunk-ESBQHFMJ.js";
34
- import "./chunk-34WSVGEM.js";
33
+ import "./chunk-EU63SDCG.js";
35
34
  import "./chunk-VWCXW2E7.js";
35
+ import "./chunk-FCSOVF55.js";
36
+ import "./chunk-PNQDPDRC.js";
36
37
  import "./chunk-ZXYDQ3TZ.js";
37
38
  import "./chunk-5W3R6LFT.js";
38
39
  import "./chunk-QHJ6DQ2R.js";
@@ -48,7 +49,7 @@ import "./chunk-GAEGEPOC.js";
48
49
  import "./chunk-Z3CCVDUB.js";
49
50
  import "./chunk-L3BLXZG7.js";
50
51
  import "./chunk-2BEMIWEW.js";
51
- import "./chunk-66VMUL7Q.js";
52
+ import "./chunk-ACXEQZOU.js";
52
53
  import "./chunk-Q7DUK4LX.js";
53
54
  import "./chunk-AW7R2GWG.js";
54
55
  import "./chunk-RWWYJ623.js";
@@ -19,7 +19,7 @@ import {
19
19
  refreshManagedTool,
20
20
  resolveManagedNpmBinPath,
21
21
  verifyToolBinary
22
- } from "./chunk-66VMUL7Q.js";
22
+ } from "./chunk-ACXEQZOU.js";
23
23
  import "./chunk-Q7DUK4LX.js";
24
24
  import {
25
25
  pmBinary,
@@ -9,11 +9,11 @@ import {
9
9
  getDeadCodeClients,
10
10
  parseVultureOutput,
11
11
  stableFindingKey
12
- } from "./chunk-OG5UUPN7.js";
12
+ } from "./chunk-OCAGUNBC.js";
13
13
  import "./chunk-7U2IDNXN.js";
14
- import "./chunk-VCHXCQFG.js";
15
14
  import "./chunk-2CD5RS6M.js";
16
15
  import "./chunk-UZ3TUTRV.js";
16
+ import "./chunk-VCHXCQFG.js";
17
17
  import "./chunk-PNQDPDRC.js";
18
18
  import "./chunk-P7266HLM.js";
19
19
  import "./chunk-AW7R2GWG.js";
@@ -1,11 +1,14 @@
1
1
  import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
2
+ import {
3
+ scannerReportParentDir
4
+ } from "./chunk-CSHFH5IN.js";
2
5
  import {
3
6
  getScratchTreeGlobPatterns,
4
7
  nestedWorktreeOffsets
5
8
  } from "./chunk-VCHXCQFG.js";
6
9
  import {
7
10
  SecurityScanClient
8
- } from "./chunk-IXXDFY73.js";
11
+ } from "./chunk-3EFKIGZN.js";
9
12
  import {
10
13
  safeSpawnAsync
11
14
  } from "./chunk-C34ZXZ7O.js";
@@ -21,7 +24,6 @@ import {
21
24
 
22
25
  // dist/clients/trivy-client.js
23
26
  import * as fs from "node:fs";
24
- import * as os from "node:os";
25
27
  import * as path from "node:path";
26
28
  import { mkdtempSync } from "node:fs";
27
29
  var EMPTY_RESULT = {
@@ -178,7 +180,7 @@ var TrivyClient = class extends SecurityScanClient {
178
180
  const scannedAt = (/* @__PURE__ */ new Date()).toISOString();
179
181
  const bin = this.binaryPath ?? "trivy";
180
182
  const severities = resolveSeverityFloor(cwd);
181
- const outDir = mkdtempSync(path.join(os.tmpdir(), "pi-lens-trivy-"));
183
+ const outDir = mkdtempSync(path.join(scannerReportParentDir(), "pi-lens-trivy-"));
182
184
  const reportPath = path.join(outDir, "trivy-report.json");
183
185
  try {
184
186
  const result = await safeSpawnAsync(bin, [
@@ -4,7 +4,7 @@ import {
4
4
  discoverManagedTool,
5
5
  getManagedToolEnvironment,
6
6
  resolveAvailableOrInstall
7
- } from "./chunk-GOYRYZ2R.js";
7
+ } from "./chunk-YSZNHOBY.js";
8
8
  import {
9
9
  mapWithConcurrency
10
10
  } from "./chunk-XIMYZ3JA.js";
@@ -4057,7 +4057,7 @@ async function stampInstallResolution(toolId) {
4057
4057
  return;
4058
4058
  try {
4059
4059
  const resolutionId = lastInstallResolutionId.get(toolId);
4060
- const refresh = await import("./chunk-CF24OIYI.js");
4060
+ const refresh = await import("./chunk-5UCAH366.js");
4061
4061
  await refresh.stampManagedToolInstall(toolId, resolutionId);
4062
4062
  } catch {
4063
4063
  }
@@ -4070,7 +4070,7 @@ async function finishInstallAttempt(toolId, ok, startedAt) {
4070
4070
  if (ok) {
4071
4071
  resetSafeSpawnWindowsCommandCache();
4072
4072
  try {
4073
- const { resetMadgeManagedPathMemo } = await import("./chunk-3WA4HP4I.js");
4073
+ const { resetMadgeManagedPathMemo } = await import("./chunk-EC47DWFA.js");
4074
4074
  resetMadgeManagedPathMemo();
4075
4075
  } catch (err) {
4076
4076
  logSessionStart(`auto-install ${toolId}: madge memo reset failed: ${err.message}`);
@@ -4100,7 +4100,7 @@ async function installTool(toolId, ownsLock) {
4100
4100
  return false;
4101
4101
  const npmPath = await installNpmTool(tool.id, tool.packageName, tool.binaryName, tool.checkArgs, getToolVerificationTimeout(tool), packageEntryVerification(tool), ownsLock);
4102
4102
  if (npmPath !== void 0) {
4103
- await import("./chunk-CF24OIYI.js").then((m) => m.stampManagedToolInstalled(tool.id, tool.packageName)).catch(() => {
4103
+ await import("./chunk-5UCAH366.js").then((m) => m.stampManagedToolInstalled(tool.id, tool.packageName)).catch(() => {
4104
4104
  });
4105
4105
  }
4106
4106
  return finishInstallAttempt(tool.id, npmPath !== void 0, startedAt);
@@ -1,21 +1,24 @@
1
1
  import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
2
- import {
3
- nestedWorktreeOffsets
4
- } from "./chunk-VCHXCQFG.js";
5
2
  import {
6
3
  formatToolFailure
7
4
  } from "./chunk-2CD5RS6M.js";
8
5
  import "./chunk-UZ3TUTRV.js";
6
+ import {
7
+ scannerReportParentDir
8
+ } from "./chunk-CSHFH5IN.js";
9
+ import {
10
+ nestedWorktreeOffsets
11
+ } from "./chunk-VCHXCQFG.js";
9
12
  import {
10
13
  createAvailabilityChecker,
11
14
  findManagedNodeToolBinary,
12
15
  resolveAvailableOrInstall
13
- } from "./chunk-GOYRYZ2R.js";
16
+ } from "./chunk-YSZNHOBY.js";
14
17
  import "./chunk-RPLINGVB.js";
15
- import "./chunk-PNQDPDRC.js";
16
- import "./chunk-ESBQHFMJ.js";
17
- import "./chunk-34WSVGEM.js";
18
+ import "./chunk-EU63SDCG.js";
18
19
  import "./chunk-VWCXW2E7.js";
20
+ import "./chunk-FCSOVF55.js";
21
+ import "./chunk-PNQDPDRC.js";
19
22
  import "./chunk-ZXYDQ3TZ.js";
20
23
  import "./chunk-724UL2TJ.js";
21
24
  import "./chunk-QOZXJ4NA.js";
@@ -27,7 +30,7 @@ import {
27
30
  } from "./chunk-GAEGEPOC.js";
28
31
  import "./chunk-Z3CCVDUB.js";
29
32
  import "./chunk-2BEMIWEW.js";
30
- import "./chunk-66VMUL7Q.js";
33
+ import "./chunk-ACXEQZOU.js";
31
34
  import "./chunk-Q7DUK4LX.js";
32
35
  import {
33
36
  findNodeToolBinary
@@ -77,7 +80,6 @@ import "./chunk-NXL4FFQQ.js";
77
80
  // dist/clients/jscpd-client.js
78
81
  import * as fs from "node:fs";
79
82
  import { mkdtempSync } from "node:fs";
80
- import * as os from "node:os";
81
83
  import * as path from "node:path";
82
84
  var EMPTY_RESULT = {
83
85
  success: false,
@@ -268,27 +270,27 @@ var JscpdClient = class {
268
270
  }
269
271
  async runScan(cwd, minLines, minTokens, isTsProject) {
270
272
  const scannedAt = (/* @__PURE__ */ new Date()).toISOString();
271
- const outDir = mkdtempSync(`${os.tmpdir()}${path.sep}pi-lens-jscpd-`);
272
- const baseIgnores = [
273
- ...getExcludedDirGlobs(),
274
- ...getProjectIgnoreGlobs(cwd),
275
- "**/*.md",
276
- "**/*.txt",
277
- "**/*.json",
278
- "**/*.yaml",
279
- "**/*.yml",
280
- "**/*.toml",
281
- "**/*.lock",
282
- "**/*.test.*",
283
- "**/*.spec.*",
284
- "**/*.poc.test.*",
285
- "**/__tests__/**",
286
- "**/tests/**"
287
- ];
288
- if (isTsProject) {
289
- baseIgnores.push("**/*.js", "**/*.jsx");
290
- }
273
+ const outDir = mkdtempSync(path.join(scannerReportParentDir(), "pi-lens-jscpd-"));
291
274
  try {
275
+ const baseIgnores = [
276
+ ...getExcludedDirGlobs(),
277
+ ...getProjectIgnoreGlobs(cwd),
278
+ "**/*.md",
279
+ "**/*.txt",
280
+ "**/*.json",
281
+ "**/*.yaml",
282
+ "**/*.yml",
283
+ "**/*.toml",
284
+ "**/*.lock",
285
+ "**/*.test.*",
286
+ "**/*.spec.*",
287
+ "**/*.poc.test.*",
288
+ "**/__tests__/**",
289
+ "**/tests/**"
290
+ ];
291
+ if (isTsProject) {
292
+ baseIgnores.push("**/*.js", "**/*.jsx");
293
+ }
292
294
  const bin = await findNodeToolBinary("jscpd", cwd);
293
295
  const { cmd, prefix } = bin ? { cmd: bin, prefix: [] } : this.jscpdManagedPath ? { cmd: this.jscpdManagedPath, prefix: [] } : { cmd: "npx", prefix: ["jscpd"] };
294
296
  const config = readProjectJscpdConfig(cwd);
@@ -0,0 +1,17 @@
1
+ import { createRequire as __pilensCreateRequire } from "node:module"; const require = __pilensCreateRequire(import.meta.url);
2
+ import {
3
+ isTestMode
4
+ } from "./chunk-AOHZU2BM.js";
5
+
6
+ // dist/clients/scanner-temp-root.js
7
+ import * as os from "node:os";
8
+ function scannerReportParentDir() {
9
+ if (!isTestMode() && process.env.PI_LENS_TEST_SCANNER_HARNESS !== "1")
10
+ return os.tmpdir();
11
+ const override = process.env.PI_LENS_TEST_SCANNER_TMPDIR?.trim();
12
+ return override && override.length > 0 ? override : os.tmpdir();
13
+ }
14
+
15
+ export {
16
+ scannerReportParentDir
17
+ };
@@ -3,15 +3,16 @@ import {
3
3
  DependencyChecker,
4
4
  buildMadgeArgs,
5
5
  resetMadgeManagedPathMemo
6
- } from "./chunk-EETY4LF7.js";
7
- import "./chunk-GOYRYZ2R.js";
6
+ } from "./chunk-AB3YYG6N.js";
7
+ import "./chunk-YSZNHOBY.js";
8
8
  import "./chunk-RPLINGVB.js";
9
9
  import {
10
10
  mapWithConcurrency
11
11
  } from "./chunk-XIMYZ3JA.js";
12
- import "./chunk-ESBQHFMJ.js";
13
- import "./chunk-34WSVGEM.js";
12
+ import "./chunk-EU63SDCG.js";
14
13
  import "./chunk-VWCXW2E7.js";
14
+ import "./chunk-FCSOVF55.js";
15
+ import "./chunk-PNQDPDRC.js";
15
16
  import "./chunk-ZXYDQ3TZ.js";
16
17
  import "./chunk-724UL2TJ.js";
17
18
  import "./chunk-QOZXJ4NA.js";
@@ -21,7 +22,7 @@ import "./chunk-SAEFPSB6.js";
21
22
  import "./chunk-GAEGEPOC.js";
22
23
  import "./chunk-Z3CCVDUB.js";
23
24
  import "./chunk-2BEMIWEW.js";
24
- import "./chunk-66VMUL7Q.js";
25
+ import "./chunk-ACXEQZOU.js";
25
26
  import "./chunk-Q7DUK4LX.js";
26
27
  import "./chunk-AW7R2GWG.js";
27
28
  import "./chunk-RWWYJ623.js";