pi-lens 4.4.0 → 4.4.2

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 (150) hide show
  1. package/CHANGELOG.md +158 -0
  2. package/README.md +1 -0
  3. package/config/dependency-cruiser-eager-allowlist.json +3 -1
  4. package/dist/{chunk-IXEBJSUE.js → chunk-23WOO7TX.js} +11 -10
  5. package/dist/{chunk-E2WFBRHM.js → chunk-2B73ZPOK.js} +3 -3
  6. package/dist/{chunk-DQ2NZ7C4.js → chunk-2BBLFX75.js} +139 -11
  7. package/dist/{chunk-ZMOL6RQC.js → chunk-2CD5RS6M.js} +2 -2
  8. package/dist/{chunk-VD4JQCQC.js → chunk-2ZGIZPDG.js} +38 -37
  9. package/dist/{chunk-DIULIWKU.js → chunk-34WSVGEM.js} +29 -3
  10. package/dist/chunk-3JNKMP3B.js +17 -0
  11. package/dist/{chunk-HVUZXSWK.js → chunk-3UUPUE3O.js} +45 -41
  12. package/dist/{chunk-5RXBNSW2.js → chunk-3VPVG5SU.js} +16 -8
  13. package/dist/chunk-3WA4HP4I.js +55 -0
  14. package/dist/chunk-466Z26MG.js +30 -0
  15. package/dist/{chunk-34U7PLGE.js → chunk-4UNXBNE2.js} +12 -11
  16. package/dist/{chunk-E4MAEDPM.js → chunk-4W4VLAPJ.js} +12 -11
  17. package/dist/{chunk-GUOGVTCQ.js → chunk-52FUZI6K.js} +4 -2
  18. package/dist/chunk-5JM2524W.js +84 -0
  19. package/dist/{chunk-VHQLPIRJ.js → chunk-5NGR67U5.js} +2 -2
  20. package/dist/{chunk-DFVMIKMQ.js → chunk-66SXUJCA.js} +45 -9
  21. package/dist/{chunk-OQGFCZJ4.js → chunk-66VMUL7Q.js} +16 -16
  22. package/dist/{chunk-HWBZIGMJ.js → chunk-67WMNWEE.js} +9 -8
  23. package/dist/{chunk-6QIUX4EP.js → chunk-6C7JWPCP.js} +7 -7
  24. package/dist/{chunk-47D2BO4S.js → chunk-6GFRNVYR.js} +11 -10
  25. package/dist/{chunk-ZAWW3AF6.js → chunk-6SDEP3AJ.js} +9 -8
  26. package/dist/{chunk-TGPXLY2J.js → chunk-724UL2TJ.js} +38 -2
  27. package/dist/{chunk-YLF3PPT5.js → chunk-76MWC2K6.js} +3 -3
  28. package/dist/{chunk-F3P7VQ7H.js → chunk-7DYBLXYA.js} +3 -3
  29. package/dist/{chunk-AJ3QXTRQ.js → chunk-7ULNCDCO.js} +37 -35
  30. package/dist/{chunk-UK3CMEAL.js → chunk-AOHZU2BM.js} +1 -1
  31. package/dist/{chunk-F3AU2TMM.js → chunk-ARJ6PLFH.js} +44 -28
  32. package/dist/{chunk-U3VGR4VU.js → chunk-AW7R2GWG.js} +65 -8
  33. package/dist/{chunk-FJNKANOS.js → chunk-BKE7E7TC.js} +10 -9
  34. package/dist/{chunk-4W2PLC4J.js → chunk-BRGDSBJE.js} +13 -12
  35. package/dist/{chunk-VN2AXLEX.js → chunk-C34ZXZ7O.js} +102 -16
  36. package/dist/{chunk-T4ERT73Y.js → chunk-CF24OIYI.js} +21 -20
  37. package/dist/{chunk-NMABWBZN.js → chunk-CHOW74WE.js} +1 -1
  38. package/dist/{chunk-ARFCXG7S.js → chunk-CO2G5PHH.js} +2 -2
  39. package/dist/{chunk-AS44CFQ4.js → chunk-EETY4LF7.js} +24 -10
  40. package/dist/{chunk-I3R7GKDR.js → chunk-EJIUXPBX.js} +1 -1
  41. package/dist/{chunk-B3I2UUT4.js → chunk-ESBQHFMJ.js} +653 -251
  42. package/dist/{chunk-O5WILGMI.js → chunk-FLKWCIZH.js} +8 -5
  43. package/dist/{chunk-LNAKEO63.js → chunk-GAEGEPOC.js} +4 -4
  44. package/dist/{chunk-V7R425XG.js → chunk-GBPP5P7X.js} +4 -4
  45. package/dist/{chunk-XK4CIILI.js → chunk-GHB6AYCP.js} +27 -26
  46. package/dist/{chunk-7FBF7NPR.js → chunk-GOYRYZ2R.js} +29 -26
  47. package/dist/{chunk-JOLITGCC.js → chunk-GXW6K4YJ.js} +1 -1
  48. package/dist/{chunk-NXPS2L6U.js → chunk-GZYBXISR.js} +9 -9
  49. package/dist/{chunk-OAXNDZJ7.js → chunk-IBGIOBEE.js} +8 -4
  50. package/dist/{chunk-IIXOAGHR.js → chunk-IBRALRBR.js} +19 -15
  51. package/dist/{chunk-7F72PXY2.js → chunk-IXXDFY73.js} +3 -3
  52. package/dist/chunk-IZSHAIJ7.js +26 -0
  53. package/dist/{chunk-N3YQJI6O.js → chunk-JAU72XNY.js} +20 -15
  54. package/dist/chunk-JMYYOTQG.js +77 -0
  55. package/dist/{chunk-NL5GLMFI.js → chunk-JSQFTSC6.js} +12 -11
  56. package/dist/{chunk-IVP5KAB7.js → chunk-JWA5I3SR.js} +35 -21
  57. package/dist/{chunk-Y4T27COV.js → chunk-KBG47GHP.js} +4 -4
  58. package/dist/{chunk-PWFHBTSF.js → chunk-L3BLXZG7.js} +2 -2
  59. package/dist/chunk-LOP6GRPH.js +31 -0
  60. package/dist/chunk-MQLUAEOC.js +162 -0
  61. package/dist/{chunk-RPD5K5NC.js → chunk-MRXKYPCS.js} +2 -2
  62. package/dist/{chunk-Q5U6FMDI.js → chunk-N2H3ZPZY.js} +59 -7
  63. package/dist/{chunk-27BBHSZC.js → chunk-N3X6Q4YT.js} +3 -3
  64. package/dist/{chunk-UY752QSN.js → chunk-NW7BOILN.js} +19 -17
  65. package/dist/{chunk-TLGFBM3F.js → chunk-ODBNXWT4.js} +302 -113
  66. package/dist/{chunk-TT22N74J.js → chunk-OG5UUPN7.js} +13 -13
  67. package/dist/{chunk-C2AUYXQH.js → chunk-OXXKQCSV.js} +6 -6
  68. package/dist/{chunk-PAK6IDME.js → chunk-P7266HLM.js} +2 -2
  69. package/dist/{chunk-52H5B5TC.js → chunk-PFNSLWU5.js} +31 -30
  70. package/dist/{chunk-5ZEJHV35.js → chunk-PHDMFAKM.js} +12 -2
  71. package/dist/{chunk-3I5QFT3N.js → chunk-PNQDPDRC.js} +6 -3
  72. package/dist/{chunk-TVN5N6GY.js → chunk-PV6LR5P5.js} +6057 -1311
  73. package/dist/{chunk-AHDW3GPE.js → chunk-Q6ZWTCLY.js} +24 -22
  74. package/dist/{chunk-RUOG5D2C.js → chunk-Q7DUK4LX.js} +5 -5
  75. package/dist/{chunk-YSNFMJKN.js → chunk-QGQ5CCCG.js} +2 -2
  76. package/dist/{chunk-LW6XKDZQ.js → chunk-QHJ6DQ2R.js} +287 -38
  77. package/dist/{chunk-GVXA6CCE.js → chunk-QILIYSJF.js} +1 -1
  78. package/dist/{chunk-22AVIGXS.js → chunk-QOBUHWHX.js} +12 -7
  79. package/dist/{chunk-5THXD6X5.js → chunk-QQNQ7SJW.js} +2 -75
  80. package/dist/{chunk-4RERDEXR.js → chunk-QZVW3AAK.js} +50 -41
  81. package/dist/{chunk-AWE5TMPO.js → chunk-R3PCY3YS.js} +14 -13
  82. package/dist/{chunk-HHYAELLJ.js → chunk-RPLINGVB.js} +7 -7
  83. package/dist/{chunk-EOKRQ3SA.js → chunk-RWWYJ623.js} +10 -1
  84. package/dist/{chunk-YGVYKNSN.js → chunk-SAEFPSB6.js} +59 -12
  85. package/dist/{chunk-K6VYLB2U.js → chunk-TYM6OUIT.js} +13 -12
  86. package/dist/{chunk-AJXODZY6.js → chunk-UXGETRP4.js} +13 -12
  87. package/dist/{chunk-I7SPGOWI.js → chunk-UZ3TUTRV.js} +1 -1
  88. package/dist/{chunk-TO6WL3GM.js → chunk-VCHXCQFG.js} +12 -2
  89. package/dist/{chunk-BRJKOBZP.js → chunk-VITUCP5A.js} +17 -6
  90. package/dist/{chunk-WONERJTP.js → chunk-VRZP76YM.js} +1 -1
  91. package/dist/{chunk-OS32RNR2.js → chunk-VSSBEUFT.js} +16 -15
  92. package/dist/{chunk-VDBPVIKD.js → chunk-VWCXW2E7.js} +1 -1
  93. package/dist/{chunk-NKOUFPQF.js → chunk-WOA4LN2R.js} +2 -2
  94. package/dist/{chunk-RIISMHKN.js → chunk-WOKKRCJ5.js} +15 -13
  95. package/dist/{chunk-XECLWQZN.js → chunk-WU567RSC.js} +13 -10
  96. package/dist/{chunk-V5PXFSZK.js → chunk-XCJN5IJU.js} +4 -4
  97. package/dist/{chunk-ORTMY4Q4.js → chunk-XKIZ2HNN.js} +22 -14
  98. package/dist/{chunk-6VCD4VKZ.js → chunk-XMSXXAHW.js} +2 -2
  99. package/dist/chunk-XPZPXCBV.js +28 -0
  100. package/dist/{chunk-O6TQT6RI.js → chunk-XTMJ7XDT.js} +1 -1
  101. package/dist/{chunk-VNMT7C64.js → chunk-XVF2VVXP.js} +5 -3
  102. package/dist/chunk-Z527N6YQ.js +28 -0
  103. package/dist/{chunk-NTUJEGDZ.js → chunk-ZANLILYD.js} +22 -2
  104. package/dist/{chunk-6P62QVEA.js → chunk-ZGDGW2V3.js} +2 -2
  105. package/dist/{chunk-ODEEOXPH.js → chunk-ZHFZWTZV.js} +12 -11
  106. package/dist/{chunk-AJVLWNFN.js → chunk-ZXYDQ3TZ.js} +5 -5
  107. package/dist/index.js +102097 -97778
  108. package/dist/mcp/analyze-cli.js +18 -8
  109. package/dist/mcp/cli.js +48 -37
  110. package/dist/mcp/server.js +695 -426
  111. package/dist/mcp/worker.js +66 -55
  112. package/dist/probes/installer.js +20 -19
  113. package/docs/ast-grep_rules_catalog.md +2 -2
  114. package/docs/astplayground.md +1 -1
  115. package/docs/configuration.md +38 -2
  116. package/docs/custom-rules.md +25 -2
  117. package/docs/dependencies.md +3 -0
  118. package/docs/environment-variables.md +34 -6
  119. package/docs/features.md +39 -3
  120. package/docs/globalconfig.md +3 -1
  121. package/docs/language-coverage.md +2 -1
  122. package/docs/lsp-capability-matrix.md +29 -6
  123. package/docs/lsp-idle-eviction.md +38 -47
  124. package/docs/pi-lens-fixer.md +13 -5
  125. package/docs/pi-lens-merge-policy.md +48 -1
  126. package/docs/pi-lens-monitor.md +3 -1
  127. package/docs/pi-lens-retro.md +2 -1
  128. package/docs/pi-lens-reviewer.md +19 -3
  129. package/docs/pi-lens-subagent.md +2 -0
  130. package/docs/real-harness.md +17 -0
  131. package/docs/schema/pi-lens-config-v1.json +565 -0
  132. package/docs/servercapabilities.md +18 -4
  133. package/docs/settings.md +2 -1
  134. package/docs/word-index.md +6 -0
  135. package/package.json +1 -1
  136. package/rules/ast-grep-rules/rule-tests/no-identity-operator-on-literals-test.yml +12 -2
  137. package/rules/ast-grep-rules/rule-tests/throw-new-error-js-test.yml +2 -0
  138. package/rules/ast-grep-rules/rule-tests/throw-new-error-test.yml +2 -0
  139. package/rules/ast-grep-rules/rules/no-identity-operator-on-literals.yml +20 -12
  140. package/rules/ast-grep-rules/rules/throw-new-error-js.yml +2 -2
  141. package/rules/ast-grep-rules/rules/throw-new-error.yml +2 -2
  142. package/dist/chunk-54B42YRX.js +0 -27
  143. package/dist/chunk-CGGAIP7J.js +0 -29
  144. package/dist/chunk-D6QS3U6M.js +0 -30
  145. package/dist/chunk-HMFXILPV.js +0 -83
  146. package/dist/chunk-LSMJ6KBE.js +0 -4139
  147. package/dist/chunk-NTHH2J74.js +0 -27
  148. package/dist/chunk-RPD4ZSB7.js +0 -25
  149. package/dist/chunk-T6D4Q4AQ.js +0 -54
  150. package/dist/chunk-VCSRSYLF.js +0 -81
@@ -15,7 +15,7 @@ respawned server reports every finding it reported before eviction; the
15
15
  content-bound coverage check the auxiliary freeze depends on. A server that
16
16
  cannot demonstrate it is never proposed for eviction on perf grounds alone.
17
17
 
18
- _Last generated: 2026-10-07 on linux; 48 registry servers: 32 eligible, 0 vetoed, 2 inconclusive, 14 unavailable (0 not reached: budget)._
18
+ _Last generated: 2026-10-10 on linux; 48 registry servers: 8 eligible, 0 vetoed, 16 inconclusive, 24 unavailable (0 not reached: budget)._
19
19
 
20
20
  ## Per-server rows
21
21
 
@@ -35,54 +35,54 @@ step log only, because it flaps.
35
35
 
36
36
  | server | role | declared | result | reason | respawn | coverage |
37
37
  |---|---|---|---|---|---|---|
38
- | ast-grep | auxiliary | unmeasured | eligible | · | ok | preserved |
39
- | bash | primary | transparent | eligible | · | ok | preserved |
38
+ | ast-grep | auxiliary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
39
+ | bash | primary | transparent | unavailable | server-not-started | n/a | n/a |
40
40
  | clojure | primary | transparent | eligible | · | ok | preserved |
41
41
  | cmake | primary | unmeasured | inconclusive | no-baseline | n/a | unproven |
42
42
  | cpp | primary | transparent | eligible | · | ok | preserved |
43
43
  | csharp | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
44
- | css | primary | transparent | eligible | · | ok | preserved |
45
- | cue | primary | unmeasured | eligible | · | ok | preserved |
44
+ | css | primary | transparent | unavailable | server-not-started | n/a | n/a |
45
+ | cue | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
46
46
  | dart | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
47
47
  | deno | primary | transparent | eligible | · | ok | preserved |
48
- | docker | primary | unmeasured | eligible | · | ok | preserved |
49
- | docker-official | primary | unmeasured | unavailable | no-fixture | n/a | n/a |
48
+ | docker | primary | transparent | unavailable | server-not-started | n/a | n/a |
49
+ | docker-official | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
50
50
  | elixir | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
51
- | expert | primary | unmeasured | eligible | · | ok | preserved |
52
- | fish | primary | transparent | eligible | · | ok | preserved |
51
+ | expert | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
52
+ | fish | primary | transparent | unavailable | server-not-started | n/a | n/a |
53
53
  | fsharp | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
54
- | gleam | primary | unmeasured | eligible | · | ok | preserved |
54
+ | gleam | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
55
55
  | go | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
56
56
  | haskell | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
57
- | html | primary | transparent | eligible | · | ok | preserved |
57
+ | html | primary | transparent | unavailable | server-not-started | n/a | n/a |
58
58
  | java | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
59
- | json | primary | unmeasured | eligible | · | ok | preserved |
60
- | kotlin | primary | unmeasured | eligible | · | ok | preserved |
61
- | lua | primary | unmeasured | eligible | · | ok | preserved |
59
+ | json | primary | transparent | eligible | · | ok | preserved |
60
+ | kotlin | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
61
+ | lua | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
62
62
  | marksman | primary | transparent | eligible | · | ok | preserved |
63
63
  | nix | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
64
64
  | ocaml | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
65
65
  | omnisharp | primary | unmeasured | unavailable | no-fixture | n/a | n/a |
66
66
  | opengrep | auxiliary | transparent | eligible | · | ok | preserved |
67
- | php | primary | transparent | eligible | · | ok | preserved |
68
- | powershell | primary | unmeasured | eligible | · | ok | preserved |
69
- | prisma | primary | transparent | eligible | · | ok | preserved |
70
- | python | primary | transparent | eligible | · | ok | preserved |
71
- | python-jedi | primary | unmeasured | eligible | · | ok | preserved |
67
+ | php | primary | transparent | unavailable | server-not-started | n/a | n/a |
68
+ | powershell | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
69
+ | prisma | primary | transparent | unavailable | server-not-started | n/a | n/a |
70
+ | python | primary | transparent | unavailable | server-not-started | n/a | n/a |
71
+ | python-jedi | primary | transparent | eligible | · | ok | preserved |
72
72
  | ruby | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
73
- | rust | primary | unmeasured | eligible | · | ok | preserved |
73
+ | rust | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
74
74
  | shuck | primary | unmeasured | unavailable | server-not-started | n/a | n/a |
75
- | svelte | primary | unmeasured | eligible | · | ok | preserved |
75
+ | svelte | primary | unmeasured | unavailable | server-not-started | n/a | n/a |
76
76
  | swift | primary | unmeasured | unavailable | tool-unavailable | n/a | n/a |
77
- | terraform | primary | unmeasured | eligible | · | ok | preserved |
78
- | tinymist | primary | unmeasured | eligible | · | ok | preserved |
79
- | toml | primary | unmeasured | eligible | · | ok | preserved |
77
+ | terraform | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
78
+ | tinymist | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
79
+ | toml | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
80
80
  | typescript | primary | transparent | eligible | · | ok | preserved |
81
- | typos | auxiliary | unmeasured | eligible | · | ok | preserved |
82
- | vue | primary | unmeasured | inconclusive | no-baseline | n/a | unproven |
83
- | yaml | primary | transparent | eligible | · | ok | preserved |
84
- | zig | primary | unmeasured | eligible | · | ok | preserved |
85
- | zizmor | auxiliary | unmeasured | eligible | · | ok | preserved |
81
+ | typos | auxiliary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
82
+ | vue | primary | unmeasured | unavailable | server-not-started | n/a | n/a |
83
+ | yaml | primary | transparent | unavailable | server-not-started | n/a | n/a |
84
+ | zig | primary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
85
+ | zizmor | auxiliary | unmeasured | inconclusive | not-evicted | not-evicted | n/a |
86
86
 
87
87
  ## Declared versus measured
88
88
 
@@ -90,24 +90,15 @@ step log only, because it flaps.
90
90
  or `info` line is for a maintainer to act on in a follow-up; this run changed
91
91
  nothing.
92
92
 
93
- - **ast-grep** [proposal] declared unmeasured but eviction and respawn preserved its findings
94
- - **cue** [proposal] declared unmeasured but eviction and respawn preserved its findings
95
- - **docker** [proposal] declared unmeasured but eviction and respawn preserved its findings
96
- - **expert** [proposal] declared unmeasured but eviction and respawn preserved its findings
97
- - **gleam** [proposal] declared unmeasured but eviction and respawn preserved its findings
98
- - **json** [proposal] declared unmeasured but eviction and respawn preserved its findings
99
- - **kotlin** [proposal] declared unmeasured but eviction and respawn preserved its findings
100
- - **lua** [proposal] declared unmeasured but eviction and respawn preserved its findings
101
- - **powershell** [proposal] declared unmeasured but eviction and respawn preserved its findings
102
- - **python-jedi** [proposal] declared unmeasured but eviction and respawn preserved its findings
103
- - **rust** [proposal] declared unmeasured but eviction and respawn preserved its findings
104
- - **svelte** [proposal] declared unmeasured but eviction and respawn preserved its findings
105
- - **terraform** [proposal] declared unmeasured but eviction and respawn preserved its findings
106
- - **tinymist** [proposal] declared unmeasured but eviction and respawn preserved its findings
107
- - **toml** [proposal] declared unmeasured but eviction and respawn preserved its findings
108
- - **typos** [proposal] declared unmeasured but eviction and respawn preserved its findings
109
- - **zig** [proposal] declared unmeasured but eviction and respawn preserved its findings
110
- - **zizmor** [proposal] declared unmeasured but eviction and respawn preserved its findings
93
+ - **bash** [info] declared transparent with no evidence this run: unavailable (server-not-started)
94
+ - **css** [info] declared transparent with no evidence this run: unavailable (server-not-started)
95
+ - **docker** [info] declared transparent with no evidence this run: unavailable (server-not-started)
96
+ - **fish** [info] declared transparent with no evidence this run: unavailable (server-not-started)
97
+ - **html** [info] declared transparent with no evidence this run: unavailable (server-not-started)
98
+ - **php** [info] declared transparent with no evidence this run: unavailable (server-not-started)
99
+ - **prisma** [info] declared transparent with no evidence this run: unavailable (server-not-started)
100
+ - **python** [info] declared transparent with no evidence this run: unavailable (server-not-started)
101
+ - **yaml** [info] declared transparent with no evidence this run: unavailable (server-not-started)
111
102
 
112
103
  ## Reasons
113
104
 
@@ -10,6 +10,10 @@ mechanics"; a brief supplies only `lane=<name>`, scope, and the grant.
10
10
 
11
11
  ## Before code
12
12
 
13
+ Before mocking a `clients/` module, look for its test seam (`set*`, `adopt*`, or
14
+ `reset*`). The pre-flight must list the mock dependents of any module whose
15
+ exports change.
16
+
13
17
  - Trace the production entry point and reproduce the defect through it
14
18
  (principles §1, "Premise first"). Name no seam before the reproduction; the
15
19
  red reproduction is your feedback loop, built before any theory of the fix.
@@ -34,10 +38,11 @@ mechanics"; a brief supplies only `lane=<name>`, scope, and the grant.
34
38
  preserves or tightens, and show the violating config red on the pre-fix model
35
39
  and green after, or carry `TLA+ unaffected: <family> — <reason>` in the PR
36
40
  body. A row is any-of (one listed family's model move or declaration
37
- satisfies it); a row of 4+ families only prints a note until hunk-level
38
- matching exists (#3878). The map owner is the lane that adds a
39
- `formal/<family>/`: it adds the family and its map row in the same PR, and
40
- `validateCoverageMap` reds the Unit tests lane otherwise.
41
+ satisfies it); a row of 4+ families only prints a note, except `index.ts`,
42
+ whose row gates on the lifecycle hook handler a hunk lands in (#3878). The
43
+ map owner is the lane that adds a `formal/<family>/`: it adds the family and
44
+ its map row in the same PR, and `validateCoverageMap` reds the Unit tests lane
45
+ otherwise.
41
46
  - Seams are named in the brief before the round. A fixer that needs an
42
47
  unconfirmed seam stops and reports it as a finding, not as a test.
43
48
 
@@ -158,7 +163,10 @@ rigor (#2599).
158
163
  must pass, and the hand-back quotes them. A red `PR body (advisory)` check is
159
164
  a fix-before-review item. A changelog fragment is `---` /
160
165
  `section: <Added|Changed|Deprecated|Removed|Fixed|Security>` /
161
- `audience: <user|internal>` / `---` / blank / one `- ` bullet. `audience` is
166
+ `audience: <user|internal>` / `---` / blank / one `- ` bullet. New
167
+ `audience: user` fragments must begin with a bold lead of at most 100
168
+ characters, excluding issue references; internal fragments are exempt.
169
+ `audience` is
162
170
  required: `user` is anything a pi-lens user or agent can observe (tools,
163
171
  diagnostics, messages, config, install, performance, a fixed bug they could
164
172
  hit); `internal` is CI, tests, `formal/`, contributor docs, orchestration, and
@@ -267,7 +267,7 @@ operator's private notes, so a different orchestrator can run the same train.
267
267
  | a new fixture under `tests/fixtures/` | the fixture-contract sweeps for that directory (style-preserving, population guards) — #2782 r2 |
268
268
  | a change that touches identifier uses of a glossary-retired synonym | run `tests/config/glossary-synonym-sweep.test.ts` on the head AND on the merge with `origin/master`, then re-pin in the PR from the sweep's own `UNPINNED`/`STALE` output — #3279, #3283, #3284, #3288 |
269
269
  | a new `vi.mock` in a test file | run `tests/config/vi-mock-export-sweep.test.ts`; whole-module mocks of a production module must spread `importOriginal` — PR #3268's CI red, fixed by trailing commit `621d61c5c` |
270
- | a changelog fragment | front matter `section: <Section>` plus `audience: user` or `audience: internal` and exactly one top-level `- **Title (refs #N)** —` entry, never `CHANGELOG.md`, validated by `node scripts/check-changelog-fragments.mjs` — PR #3268 r1 shipped `category:` and a paragraph |
270
+ | a changelog fragment | front matter `section: <Section>` plus `audience: user` or `audience: internal` and exactly one top-level entry; new user entries open with a bold lead of at most 100 characters (refs excluded), never `CHANGELOG.md`, validated by `node scripts/check-changelog-fragments.mjs` — PR #3268 r1 shipped `category:` and a paragraph |
271
271
  | a PR body | the header gate: exactly one-sentence `## Why`, `## Notes for the reviewer`, `## Change outline`, plus Summary / Tests with `### Test assessment` / Blast radius / Class sweep / Observability; run `node scripts/check-pr-body.mjs --lint-local` before pushing — three PRs this week needed orchestrator body edits |
272
272
  | a whole-tree docs restructure of `AGENTS.md` | every governance test that reads `AGENTS.md`, with markers on their own lines — PR #3265 r1 |
273
273
  | a raw poll in a test | the flake-shape ratchet; the fix is the governed wait, never a header admission — #2781 r1 |
@@ -611,6 +611,11 @@ Each row cost a lane at least once; the prose above carries the record.
611
611
 
612
612
  | Mistake | Fix |
613
613
  |---------|-----|
614
+ | Writing incident numbers and examples into an `AGENTS.md` rule | AGENTS.md stays lean; issues, PRs and examples go to `HISTORY.md` (maintainer, 2026-10-10). `tests/config/agents-governance.test.ts` ratchets the reference count down only |
615
+ | Routing a review finding as one PR's bug when it is a member of a class | Name the shape, grep for members, and record the verdict before the fix round; `plegma-delegate-guard` refuses a fix brief with a HIGH/MEDIUM finding and no `Shape:` line |
616
+ | Taking a causal premise ("a later merge dropped X") from a hand-back into a PR body or brief | Bisect before writing it: `git show <sha>:<file>` along the path from the fix commit to master. A lane round can revert its own earlier round, and that is not a merge drop |
617
+ | Trusting a wrapper script's exit status when it echoes a check's result | `pr-body.sh lint` printed `lint-exit=1` and exited 0, so a failing body went live; the wrapper now exits with the check's status. Read the check's own result line |
618
+ | Hand-rolling the governance suite in a fresh worktree | `npm run build` alone left `dist/` missing and three census suites red; use the orchestrator's `gov-check.sh <tree>`, which builds both outputs and keeps the `node_modules` link for the commit hook |
614
619
  | Reading a CI verdict without checking the SHA it judged | `ci-verdict --wait` returned exit 0 for the PREVIOUS head seconds after a push (#2878 trailing, 2026-09-10); compare the verdict's SHA with `gh pr view --json headRefOid` before merging |
615
620
  | Reporting "pushed" before `git log -1` shows the commit | Two trailing commits failed the pre-commit hook (changelog one-entry rule, unused vars) and the ledger/body already said pushed; verify the head, then write the row |
616
621
  | Folding a worker's extra changelog fragment into an existing one | One fragment = one top-level entry (`rollup-changelog --check`); keep a second fragment separate or drop it |
@@ -692,3 +697,45 @@ Each row cost a lane at least once; the prose above carries the record.
692
697
  | Enabling auto-merge before local HEAD equals the pushed SHA | Verify the pushed SHA before enabling auto-merge (#3671) |
693
698
  | Waiting for CI after retargeting a base without a push | Push after a base retarget to re-arm CI (#3679) |
694
699
  | Leaving fork-PR `action_required` runs unapproved | Approve the runs after pushing to a fork PR (#3656) |
700
+ | Writing a closing keyword on a partial delivery | #4021's title said "closes #1513" while its notes said the global-bin walk remained; the merge auto-closed #1513 and it was reopened by hand (2026-10-07). Close only when every acceptance criterion is met; otherwise write `Refs #N` and post the remainder before merging. Title and body must agree |
701
+ | Two writers doing read-modify-write on one shared record without a lock | The orchestrator ledger lost a freshly written row: a sync script read the file, a row was appended, the sync wrote back its stale copy (2026-10-07). Every writer of a shared record holds one lock across the whole read-modify-write (principles §1, "Design shared state once") |
702
+ | Paraphrasing an acceptance criterion into a review brief | A combination-review brief for #3997 said substituted labels "must reject" where they must be accepted when they form an identifier (2026-10-06). Quote the criterion from the PR body or issue; never restate its polarity from memory |
703
+ | Treating a `completed` settlement as delivered when its declared report is missing | Two codex settlements in one batch wrote `REVIEW.md` instead of the declared `REVIEW_4024.md`, or only a GitHub comment (plegma #689; 2026-10-07). Check the declared file exists; else read the file the worker's final line links, and release by hand |
704
+ | Assuming a hook added mid-session is live | A `SubagentStop` hook added to `.claude/settings.local.json` mid-session never fired and did not show under `/hooks` (2026-10-07). Hooks load at session start: confirm under `/hooks` after adding one, or restart before relying on it |
705
+ | Leaving a lane's report inside the checkout that gets torn down | Closing a reviewer's worktree deleted its `REVIEW_4028.md`; the fix round worked from a relayed list (2026-10-07). Reports go outside worktrees (the handbacks directory), and teardown copies any root report out first |
706
+ | Relying on a declared deliverable name the worker never sees | plegma does not pass `deliverables:` into the delivered task; 4 of 4 briefs that omitted the file name got `REVIEW.md` or no file, 2 of 2 that named it were followed (plegma #689; 2026-10-07). Name every declared file in the brief text |
707
+ | Telling a worker to dispatch a workflow without checking what it publishes | A brief asked a fixer to `gh workflow run` its branch; the job publishes `data/test-history` with no ref guard, and the queued run would have pushed unreviewed rollup output with an oldest-row eviction (#4037, cancelled; 2026-10-07). Read the workflow's push and publish steps and their `if:` guards before asking for a branch dispatch |
708
+ | Trusting a `completed` fix round without checking the PR head moved | The #3997 maintainer round settled `completed` while its lease push to the base repo was rejected; the commit sat in the worker tree (plegma #692; 2026-10-07). After each fix round, compare `gh pr view --json headRefOid` with the worker's commit |
709
+ | Raising a timing budget without proving the guard still reds | A request to widen a 300 ms occupancy budget to 500 ms; the yield-removal mutation measured 220 ms locally while healthy CI measured 324–520 ms, so the guard was vacuous at either value (2026-10-07). Mutate the regression the budget exists for before moving the number |
710
+ | Re-running a broad suite after a one-file conflict resolution | A census-conflict merge on #4013 re-ran `tests/scripts` plus governance (~240 files) the reviewer had just run green on the prior head; the 4 affected files already passed (2026-10-07). Run the files the resolution touches; CI runs the rest |
711
+ | Claiming a measured fact from a partial grep | The orchestrator told the maintainer the merge-train warden's last 20 runs "took zero actions"; the grep had counted only update-branch, rerun and cancel calls, and the runs had posted 24 PR comments and 37 label changes (#4105, 2026-10-07). The maintainer decided on the wrong number and had to re-confirm. Count every effect a component can have before calling it inert |
712
+ | Letting one transient backend error re-route a whole day | A single Luna `Selected model is at capacity` failure moved about 15 later fix lanes to Claude Sonnet while codex had 80% weekly budget and 4 free slots; Claude's weekly budget reached 50% (2026-10-07/08). Treat a capacity error as transient, retry on the next dispatch, and check `plegma_quota` before every Claude fixer |
713
+ | Reading CI in a chain whose push silently did nothing | A background chain gated its push on `&&` after a build that never ran, then read the unchanged head's red Windows job as the "fixed head" result and wrote it into #4111's body (2026-10-07). After every push, compare `gh pr view --json headRefOid` with the pushed commit before reading any CI |
714
+ | Diagnosing a red from the first `##[error]` line | #4054's shard-5 red was called "npm registry unreachable"; that line came from a passing stubbed test, and the real failure was a 5 s timeout in check-pr-body.test.ts (#4088, 2026-10-07). Read the FAIL lines; treat annotation lines from stubbed tests as noise |
715
+ | Triggering CI on a bot PR before checking whether a run already exists | land.sh closed and reopened #4084 30 s after an update-branch, before the new run registered, which cancelled the run, and the cancelled aggregate read red (2026-10-07). Reopen only when no run exists for the head after a real wait |
716
+ | Writing a closing keyword where GitHub does not honour it, or by accident | #4121's title said `closes #3873`, which fails the close-keyword check (titles are never honoured); #4094's body said "then fixed #4080", an accidental closing keyword (2026-10-07). Put closing keywords in the body only, and reread the body for `fix(es\|ed) #N` prose |
717
+ | Seeding a group list from the active queue instead of the tracker | The orchestrator's session group held 3 issues while `area:session` had 8 more open p2s, so "is the session group done?" was answered from an incomplete list (2026-10-08). Build a group from the label and the tracker, then subtract what is out of scope |
718
+ | Filing every LOW review finding as an issue | Each review spawned about one follow-up, so the CI group stayed at about 36 open after 16 closures (2026-10-07). Fold or drop LOW findings; file only MEDIUM and above or a reproduced sibling, and give each group a "done when" |
719
+ | No cleanup when lanes end | 78 GB of finished lane trees and a 22 GB leaking test TMPDIR filled the root disk twice; two reviewers lost probe runs and one fixer's test file was truncated (2026-10-07). Remove a lane's trees and TMPDIR when its PR merges, and keep a disk alarm |
720
+ | Deriving the next round from a stale brief or a stale premise | #3871's brief asked for a selection fix #3903 had already shipped, and #3813's assumed every producer was unfixed; both fixers correctly refused to rebuild merged work (2026-10-07). Re-check the premise on current master when a lane starts, not when the issue was filed |
721
+ | Calling a PR-owned hygiene leak pre-existing because the same files fail on a later run | The PR's own CI run exposed the leak, but the reviewer classified it as a flake and fixed an unreachable injected path; the PR review and red-on-base comparison should have owned the finding. The hygiene check now treats a new leak on a green-master PR as CAUSED-BY-PR until red-on-base proves otherwise, and harness children receive a private `TMPDIR` (#4133, #4128). |
722
+ | Passing a commit SHA where a command expected wait seconds | The shell invocation was caught by the command's outcome review; argument-shape validation should have caught it before execution. `land.sh` now validates the wait argument and prints its outcome line. |
723
+ | Losing executable mode in an atomic `.new` to `mv` replacement | The next invocation caught the non-executable script; the file-install check should have compared mode as well as bytes. The replacement now preserves the executable bit. |
724
+ | Reusing a finished PR row for `lane-set --new` | The lane ledger exposed the wrong PR identity; the row allocator should have rejected terminal rows before allocation. New rows now require an unused active identity. |
725
+ | Matching a flake on text that CI never prints | The unmatched CI output was noticed during review; the matcher test should have used a captured CI transcript. The flake matcher now keys on the classifier's actual output. |
726
+ | Letting keyword-title lint contradict the repository convention | The title gate review found the contradiction; the title-convention test should have pinned the accepted form. The lint rule now follows the repository's title convention. |
727
+ | Relaying a shard failure to a fixer without mirroring it on the PR | The fixer noticed the missing scope record; the scope-mirror hook should have rejected the handoff. The handoff path now records the scope on the PR before dispatch. |
728
+ | Treating a repeatedly red advisory lane as harmless | The maintainer's retrospective found the 21% flake after a misleading PR draw; the advisory policy and newest-master comparison should have held the PR. `land.sh` now holds a PR-red/master-green advisory unless `ADVISORY_OK=1`. |
729
+ | Forgetting to arm the landing chain after a trailing fix | A later PR-GREEN event exposed that the fix was waiting unarmed; the trailing-fix command should have verified arming. Rule: after a trailing fix, arm `land.sh` in the same step (not yet mechanised). |
730
+ | Accepting an identity trade-off without a complete timing-cell table | Cloud verification found primary-item loss after the trade-off was accepted from prose; the fixer's state table and review should have enumerated every timing cell. The brief now requires the complete state table before accepting the trade-off. |
731
+ | Letting a scoped test exceed Vitest's default timeout | A repeated cloud review caught the timeout; the local targeted run should have exercised the test under its default timeout. Rule: a scoped review runs new tests under the default Vitest timeout before passing them (not yet mechanised). |
732
+ | Specifying a truncation mechanism instead of an output acceptance criterion | The orchestrator's output read found cut lines after the worker followed the brief; the brief should have stated the required output (complete first sentence, no ellipsis). Rule: acceptance names the required output, not only the mechanism. |
733
+ | Adding a second idle timer without naming the probe consumer | The nightly eviction probe caught the missing configuration coverage; the change's call-tree diff should have listed every idle-timer environment setter. The configuration test now requires every client-read idle timer to be armed by the probe. |
734
+ | Reproducing only one step of a multi-step release-body producer | A user noticed the missing Thanks section; the release-body test should have run the complete producer chain. `bin/relnotes-regen.sh` now runs both steps and refuses to lose the section. |
735
+ | Basing a real-pi premise on an unavailable maintainer-machine probe | The fixer could not rerun the stale probe and the recurrence was found in review; the premise check should have required a repository witness. Fix briefs now require a `tests/real-harness` witness using `withRealPi` and a scripted provider. |
736
+ | Sending a sandboxed verifier a brief path instead of its contents | The verifier reported that the brief was unreadable; the dispatch smoke test should have inspected the delivered argument. Verification now inlines file arguments. |
737
+ | Allowing a mocked handler to throw so every assertion passes vacuously | Verify found the non-blocking degradation; the test double should have failed explicitly when the handler throws. Rule: a test asserting a handler verdict must also assert that no handler-throw degradation was recorded; a shared helper is a candidate, not yet built. |
738
+ | Trusting a worker hand-back that omitted exact test summaries and misreported fixes | Review found nine CAUSED-BY-CHANGE failures and unsupported “fixed” and TLA+ claims; the hand-back check should have required exact summary lines and reviewer red-on-base reruns. Fix lanes now paste the named Vitest summaries and verify identity claims. |
739
+ | Adapting repository fixtures to a Plegma guard failure | Verify caught the harness-specific workaround; the fixture lane should have reported the environment block without changing repository tests. Plegma-guard fixture failures are now reported as environmental. |
740
+ | Reading a piped command's exit status instead of its outcome record | A pending chain was reported as successful because `tail` returned zero; the landing check should have read the chain's own result. `land.sh` now prints `LAND-RESULT #N: <state> (rc=N)`, which callers must read. |
741
+ | Routing a same-seam new defect to a weaker fixer after a prior round | The next verify found the same-seam defect after a Luna-high assignment; round routing should have selected Opus from the seam and round count. Rule: a new same-seam defect after two rounds goes to Opus (cloud fixer when the subscription is short) with the state table and model step first. |
@@ -29,7 +29,9 @@ memory growth:
29
29
  process.externalNonBufferBytes; no tree-count estimate is emitted.
30
30
  - subsystems.wordIndex.wireBytes is the UTF-8 length of the word index's JSON,
31
31
  taken natively while the snapshot persist encodes the body, and is null
32
- until that index's current serialized form is persisted.
32
+ until that index's current serialized form is persisted, and again once the
33
+ serialized form is released at `agent_settled` (the `word_index_memo_released`
34
+ row in latency.log records the release and its trigger).
33
35
  - samplerDurationMs measures the sampler's own record-assembly wall time,
34
36
  excluding the surrounding turn.
35
37
 
@@ -61,7 +61,8 @@ is involved. Every finding cites the source it came from.
61
61
  exactly as a regression test would; a check without a red is a proposal and
62
62
  is filed as an issue naming the incident as its recurrence, not merged.
63
63
  4. **Judgement candidates become one line in the right place.** A defect shape
64
- goes into the `AGENTS.md` catalog with the reference; a reviewer duty goes
64
+ goes into the `AGENTS.md` catalog as a lean screen, and its issues, PRs and
65
+ examples go to `HISTORY.md`; a reviewer duty goes
65
66
  into `docs/pi-lens-reviewer.md`; a fixer duty goes into `docs/pi-lens-fixer.md`
66
67
  only when the fixer is the sole actor who can honour it. Standards are
67
68
  enforced by the reviewer, whose context pressure is lowest; fixers get
@@ -52,6 +52,11 @@ a brief supplies only `lane=<name>`, scope, and the grant.
52
52
 
53
53
  ## Verification
54
54
 
55
+ For each new or changed `vi.mock` or hand-built double of a `clients/` module,
56
+ check whether a real test seam exists (`set*`, `adopt*`, or `reset*`). If it
57
+ does, treat the double as a finding and require the behavior to run through the
58
+ real seam. Check that every gate the diff adds is exercised through that path.
59
+
55
60
  - **Name the behaviour population.** When a change replaces, moves, or widens
56
61
  a lifecycle, dispatch, or ownership seam, run EVERY suite that exercises the
57
62
  behaviour the seam governs and name the list; a curated file set cannot
@@ -73,6 +78,8 @@ a brief supplies only `lane=<name>`, scope, and the grant.
73
78
  a review input.
74
79
  - Repeat the pattern and population sweeps. Check blast radius, bounded
75
80
  observability, changelog, commit, and PR-body requirements.
81
+ - Re-run the PR's `## Class sweep` search yourself and widen it when the
82
+ named shape is broader than the touched seam (#4273, #4268).
76
83
  - For LSP, dispatch, cache, runner, or tool changes, test one non-TypeScript
77
84
  registry entry through the same seam.
78
85
  - On a net-count fold, mutate every predicate the deleted sibling used to
@@ -100,9 +107,10 @@ Run every probe the diff can trip and say which ran and what each returned.
100
107
  - **Model covers the change, not only TLC green (#3802).** When the diff
101
108
  touches a file mapped in `formal/coverage-map.json`, require a `.tla`/`.cfg`
102
109
  change under any one of the row's families or a `TLA+ unaffected: <family> —
103
- <reason>` line for any one of them; rows of 4+ families only print a note. A
104
- green `TLA+ models` run over an unchanged model proves nothing about the new
105
- code.
110
+ <reason>` line for any one of them; rows of 4+ families only print a note,
111
+ except `index.ts`, which gates on the lifecycle hook handler a hunk lands in.
112
+ A green `TLA+ models` run over an unchanged model proves nothing about the
113
+ new code.
106
114
  - **Red-proof audit.** A claimed red without its quoted transcript is a finding
107
115
  of its own; reproduce it (step 3).
108
116
  - **Quoted-evidence audit.** Diff every CI line the body quotes against the job
@@ -209,3 +217,11 @@ merge-order interactions with other open PRs, plus:
209
217
  - Cleared categories (one compact list) and exact-head identity.
210
218
 
211
219
  Use short, active, plain prose.
220
+
221
+ ## Documentation and prose standard
222
+
223
+ Apply this standard to PR and issue bodies, review comments, commit messages, documentation, and changelog entries. Lead with the outcome. Remove words that do no work. Use active voice and present tense. Use second person for instructions, and use the imperative for steps. Keep one idea per sentence, with about 20–25 words and no more than 30 words. Use consistent terminology and sentence-case headings. Define acronyms on first use. Prefer plain words over jargon. Avoid `please`, filler, noun piles, nested parentheticals, and em-dash chains. Use the Oxford comma.
224
+
225
+ The mechanical rules are checked by `scripts/check-prose.mjs`. The checker ignores fenced code, inline code, URLs, quoted log lines, blockquotes, and tables. It blocks long sentences, filler, and title-case headings. It warns on passive voice. The CLI accepts a body file or standard input and supports `--json`.
226
+
227
+ Reviewers judge clarity, terminology, active voice, sentence structure, and whether each list uses parallel grammar. Treat a mechanically clean result as necessary, not sufficient. Report prose that obscures the outcome or makes a user infer the action.
@@ -8,6 +8,8 @@ holds the pi-lens rules every role shares, for every runner and model. The
8
8
  principles apply throughout and are not restated; project files win on
9
9
  conflict.
10
10
 
11
+ User-facing prose follows the live standard in `docs/pi-lens-reviewer.md`.
12
+
11
13
  ## Worktree and Git
12
14
 
13
15
  Work only in the assigned worktree. Before editing, verify its absolute path,
@@ -12,6 +12,23 @@ process boundary that an in-process test cannot observe.
12
12
  4. Call `awaitToolResult("<tool>")` for every expected tool result.
13
13
  5. Add the test to `realHarnessInclude` and the real-process-spawn ratchet.
14
14
 
15
+ ## Persisted-session restart
16
+
17
+ Pass `persistedSession: true` when a scenario must cross a process boundary.
18
+ The harness creates `--session-dir <home>/sessions` and exposes `pi.resume()`;
19
+ that operation closes stdin on the first child and starts a second child with
20
+ the installed pi CLI's `--continue` flag. The RPC documentation defines
21
+ `new_session` and `clone`, but no resume RPC; `--continue` is therefore the
22
+ authoritative resume operation for this lane. `pi.quit()` closes stdin without
23
+ removing the probe home, so final shutdown records can be read before the
24
+ `withRealPi` cleanup.
25
+
26
+ Before either orderly stdin close, the harness waits for `latency.log` to keep
27
+ the same size and mtime for 250 ms, bounded by 5 seconds. This protects the
28
+ logger's intentional exit-flush replay trade (#935): closing while its last
29
+ async append is in flight can duplicate that final lifecycle row. A timeout is
30
+ an explicit harness failure, not a reason to proceed with an unstable log.
31
+
15
32
  Scripts contain turns. Each turn contains text or typed tool-call actions.
16
33
  Malformed scripts fail validation before the child starts.
17
34