pi-lens 4.4.3 → 4.4.4

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 (143) hide show
  1. package/CHANGELOG.md +281 -0
  2. package/README.md +13 -1
  3. package/dist/{chunk-SS36ZX4J.js → chunk-24AKHFGP.js} +6 -6
  4. package/dist/{chunk-JSQFTSC6.js → chunk-2FN63LPV.js} +11 -11
  5. package/dist/{chunk-5UCAH366.js → chunk-2KXTHF3M.js} +20 -20
  6. package/dist/{chunk-EU63SDCG.js → chunk-3DA2JDOL.js} +367 -281
  7. package/dist/{chunk-RWWYJ623.js → chunk-3KAZU3VR.js} +1 -1
  8. package/dist/chunk-3PTHXJXR.js +28 -0
  9. package/dist/chunk-3QED2P4V.js +31 -0
  10. package/dist/{chunk-N2H3ZPZY.js → chunk-3RKP3FMS.js} +1 -0
  11. package/dist/{chunk-XVF2VVXP.js → chunk-5HSRT26B.js} +2 -2
  12. package/dist/{chunk-MXGY6KPT.js → chunk-5IUSNGOC.js} +15 -15
  13. package/dist/{chunk-EJIUXPBX.js → chunk-5OFV52AM.js} +1 -1
  14. package/dist/{chunk-AW7R2GWG.js → chunk-5VSF4UUQ.js} +12 -7
  15. package/dist/{chunk-6STA6Z7I.js → chunk-5WRPDP2A.js} +18 -18
  16. package/dist/{chunk-YIUAVF7E.js → chunk-6DLWKFEX.js} +35 -34
  17. package/dist/{chunk-WOA4LN2R.js → chunk-7D6L4MTX.js} +2 -2
  18. package/dist/{chunk-GAEGEPOC.js → chunk-7HXE67BN.js} +2 -2
  19. package/dist/chunk-AGSS7277.js +84 -0
  20. package/dist/{chunk-R3PCY3YS.js → chunk-AMERCH6V.js} +13 -13
  21. package/dist/{chunk-WU567RSC.js → chunk-ATKJFDQN.js} +14 -10
  22. package/dist/{chunk-VSSBEUFT.js → chunk-AWSCPCN2.js} +16 -16
  23. package/dist/{chunk-VCHXCQFG.js → chunk-BWD5EPKO.js} +3 -3
  24. package/dist/{chunk-H6MF6EVN.js → chunk-CT4MN5IU.js} +1200 -230
  25. package/dist/{chunk-FCSOVF55.js → chunk-CUHSHSB6.js} +6 -6
  26. package/dist/{chunk-CHOW74WE.js → chunk-CYRKQRPM.js} +7 -10
  27. package/dist/{chunk-Q7DUK4LX.js → chunk-DEL2U6CM.js} +5 -5
  28. package/dist/{chunk-6C7JWPCP.js → chunk-DGUKIYSI.js} +26 -23
  29. package/dist/{chunk-PHDMFAKM.js → chunk-DUO2TU77.js} +2 -2
  30. package/dist/{chunk-MRXKYPCS.js → chunk-EBC36LNN.js} +2 -2
  31. package/dist/{chunk-CSHFH5IN.js → chunk-ED36RF6Y.js} +1 -1
  32. package/dist/{chunk-76MWC2K6.js → chunk-EUXZEFTV.js} +90 -97
  33. package/dist/{chunk-QOZXJ4NA.js → chunk-FM4RDMKT.js} +11 -8
  34. package/dist/{chunk-ACXEQZOU.js → chunk-GAQ7OQG6.js} +31 -28
  35. package/dist/{chunk-XAGLWMJ4.js → chunk-GL5LUMZE.js} +23 -23
  36. package/dist/{chunk-BKE7E7TC.js → chunk-GMX5OS7B.js} +9 -9
  37. package/dist/{chunk-ZHFZWTZV.js → chunk-GSLNCYGG.js} +11 -11
  38. package/dist/{chunk-3W7IEVVL.js → chunk-GSM5UU7A.js} +26 -34
  39. package/dist/{chunk-724UL2TJ.js → chunk-GXFV6MYU.js} +3 -3
  40. package/dist/chunk-HAD7QRQI.js +30 -0
  41. package/dist/{chunk-QOBUHWHX.js → chunk-HRNHZA3N.js} +6 -6
  42. package/dist/{chunk-VWCXW2E7.js → chunk-HWCCCQNX.js} +1 -1
  43. package/dist/{chunk-7DYBLXYA.js → chunk-HYGZEMX6.js} +3 -3
  44. package/dist/chunk-IJYGIDF4.js +186 -0
  45. package/dist/{chunk-4W4VLAPJ.js → chunk-IQWN5JCP.js} +11 -11
  46. package/dist/{chunk-SQ4TVJBR.js → chunk-IUE7SSKV.js} +7 -7
  47. package/dist/{chunk-IBGIOBEE.js → chunk-IWDLU6K3.js} +68 -5
  48. package/dist/{chunk-XCJN5IJU.js → chunk-IYNJ6YPZ.js} +4 -4
  49. package/dist/{chunk-JAU72XNY.js → chunk-J64T55EI.js} +3 -3
  50. package/dist/{chunk-2BBLFX75.js → chunk-J6MPGQTS.js} +5 -5
  51. package/dist/chunk-JORED7EX.js +44 -0
  52. package/dist/{chunk-6SDEP3AJ.js → chunk-JUKMK5Y4.js} +8 -8
  53. package/dist/{chunk-FMSO6RDZ.js → chunk-JW3YWBVB.js} +15 -15
  54. package/dist/{chunk-L3BLXZG7.js → chunk-KAPJINKN.js} +30 -69
  55. package/dist/{chunk-2B73ZPOK.js → chunk-KN35K52N.js} +3 -3
  56. package/dist/{chunk-C34ZXZ7O.js → chunk-KUA4OJ5Y.js} +24 -11
  57. package/dist/chunk-KYUB6QDC.js +72 -0
  58. package/dist/{chunk-67WMNWEE.js → chunk-LLJNQKQW.js} +12 -10
  59. package/dist/chunk-LZSEQW6A.js +57 -0
  60. package/dist/{chunk-ZANLILYD.js → chunk-M2IFVFWU.js} +2 -2
  61. package/dist/chunk-M2UD3LPU.js +88 -0
  62. package/dist/{chunk-XIJZVPD5.js → chunk-MBKQHGA7.js} +15 -15
  63. package/dist/{chunk-P7266HLM.js → chunk-MPNJLASA.js} +2 -2
  64. package/dist/{chunk-6GFRNVYR.js → chunk-MZGQNL3Y.js} +10 -10
  65. package/dist/{chunk-ZWFS3OEF.js → chunk-N5FLEO7W.js} +33 -32
  66. package/dist/{chunk-3JNKMP3B.js → chunk-O4NWQT6I.js} +4 -4
  67. package/dist/{chunk-T6CPIZNT.js → chunk-OHKJ7PQF.js} +33 -32
  68. package/dist/{chunk-VRZP76YM.js → chunk-P63GXC37.js} +4 -1
  69. package/dist/{chunk-XTMJ7XDT.js → chunk-POMLXPMY.js} +1 -1
  70. package/dist/{chunk-QQNQ7SJW.js → chunk-QBFBRV2B.js} +10 -4
  71. package/dist/{chunk-CMMHNUZ2.js → chunk-R3T7CLQ2.js} +60 -38
  72. package/dist/{chunk-23WOO7TX.js → chunk-R7YOCSNV.js} +10 -10
  73. package/dist/{chunk-2CD5RS6M.js → chunk-RKBXZN3A.js} +23 -2
  74. package/dist/{chunk-OCAGUNBC.js → chunk-RKKOYPRA.js} +12 -12
  75. package/dist/{chunk-52FUZI6K.js → chunk-RMLC67LF.js} +1 -1
  76. package/dist/{chunk-XMSXXAHW.js → chunk-ROYSX2S5.js} +2 -2
  77. package/dist/{chunk-M6HSLBWY.js → chunk-RVK72CZX.js} +6507 -7514
  78. package/dist/{chunk-FLKWCIZH.js → chunk-S2HEXIWI.js} +5 -5
  79. package/dist/{chunk-UZ3TUTRV.js → chunk-S67KYG37.js} +1 -1
  80. package/dist/{chunk-VCO24T4L.js → chunk-SD4I7ZO4.js} +14 -14
  81. package/dist/{chunk-Z527N6YQ.js → chunk-SKAMFC7A.js} +12 -12
  82. package/dist/{chunk-MQLUAEOC.js → chunk-SRYEJNES.js} +2 -2
  83. package/dist/{chunk-BRGDSBJE.js → chunk-SYE6T2EB.js} +12 -12
  84. package/dist/{chunk-GXW6K4YJ.js → chunk-T57LYLZT.js} +1 -1
  85. package/dist/{chunk-ZXYDQ3TZ.js → chunk-T7FEBKXN.js} +48 -15
  86. package/dist/{chunk-3EFKIGZN.js → chunk-TIQ2PKDW.js} +3 -3
  87. package/dist/{chunk-QILIYSJF.js → chunk-TLX72JTG.js} +1 -1
  88. package/dist/{chunk-TYM6OUIT.js → chunk-TOY6QKOH.js} +12 -12
  89. package/dist/{chunk-IZSHAIJ7.js → chunk-TRETHTQO.js} +12 -12
  90. package/dist/{chunk-3VPVG5SU.js → chunk-U44DJXQP.js} +10 -6
  91. package/dist/{chunk-PNQDPDRC.js → chunk-UA7ZXYDR.js} +1 -1
  92. package/dist/{chunk-OXXKQCSV.js → chunk-UBOQLVT2.js} +4 -4
  93. package/dist/{chunk-QGQ5CCCG.js → chunk-UMS2MFPZ.js} +2 -2
  94. package/dist/{chunk-QHJ6DQ2R.js → chunk-US7ECLD7.js} +55 -13
  95. package/dist/{chunk-AB3YYG6N.js → chunk-UZ2XCLYS.js} +8 -8
  96. package/dist/chunk-V35JG4JB.js +2667 -0
  97. package/dist/{chunk-N3X6Q4YT.js → chunk-VOOAPROD.js} +3 -3
  98. package/dist/{chunk-SAEFPSB6.js → chunk-W66O5E25.js} +21 -11
  99. package/dist/{chunk-KBG47GHP.js → chunk-WMYE35PX.js} +15 -11
  100. package/dist/{chunk-5NGR67U5.js → chunk-XBJVAEEO.js} +32 -5
  101. package/dist/{chunk-YYOIQFRS.js → chunk-XHJBS436.js} +122 -44
  102. package/dist/{chunk-GBPP5P7X.js → chunk-XTBDCR27.js} +4 -4
  103. package/dist/{chunk-4UNXBNE2.js → chunk-XTFDJI3T.js} +11 -11
  104. package/dist/{chunk-UXGETRP4.js → chunk-XYURS6EN.js} +13 -12
  105. package/dist/{chunk-RPLINGVB.js → chunk-Y6GZHWSJ.js} +6 -6
  106. package/dist/{chunk-2VUQMUMT.js → chunk-YCWYO6TQ.js} +41 -38
  107. package/dist/{chunk-77M37OKR.js → chunk-YH5MVY2U.js} +7 -7
  108. package/dist/{chunk-AOHZU2BM.js → chunk-YNE3RP52.js} +1 -1
  109. package/dist/{chunk-YSZNHOBY.js → chunk-ZHH37KZL.js} +12 -12
  110. package/dist/{chunk-ZGDGW2V3.js → chunk-ZIVJBOO3.js} +2 -2
  111. package/dist/{chunk-RXCOMYPY.js → chunk-ZVUL7QYY.js} +29 -28
  112. package/dist/index.js +11052 -5852
  113. package/dist/mcp/analyze-cli.js +10 -9
  114. package/dist/mcp/cli.js +41 -38
  115. package/dist/mcp/server.js +1120 -474
  116. package/dist/mcp/worker.js +61 -58
  117. package/dist/probes/installer.js +19 -19
  118. package/dist/workers/project-snapshot-persist-worker.js +28 -9
  119. package/dist/workers/review-graph-persist-worker.js +1 -1
  120. package/docs/configuration.md +11 -0
  121. package/docs/engineering-principles.md +32 -0
  122. package/docs/lsp-capability-matrix.md +1 -1
  123. package/docs/lsp-idle-eviction.md +15 -26
  124. package/docs/pi-lens-fixer.md +117 -13
  125. package/docs/pi-lens-merge-policy.md +97 -7
  126. package/docs/pi-lens-monitor.md +8 -2
  127. package/docs/pi-lens-retro.md +4 -1
  128. package/docs/pi-lens-reviewer.md +112 -4
  129. package/docs/pi-lens-subagent.md +22 -14
  130. package/docs/release-qa-baseline.md +3 -1
  131. package/docs/servercapabilities.md +9 -19
  132. package/package.json +7 -5
  133. package/scripts/download-grammars.js +40 -7
  134. package/scripts/lib/latency-log-phases.mjs +95 -0
  135. package/scripts/rpc-load-check.mjs +570 -81
  136. package/dist/chunk-3YN6V5TV.js +0 -85
  137. package/dist/chunk-466Z26MG.js +0 -30
  138. package/dist/chunk-EC47DWFA.js +0 -56
  139. package/dist/chunk-KDERNTCQ.js +0 -28
  140. package/dist/chunk-KSX3TXSZ.js +0 -69
  141. package/dist/chunk-LOP6GRPH.js +0 -31
  142. package/dist/chunk-UOPVJQ4N.js +0 -103
  143. /package/dist/{chunk-FC4RP4I2.js → chunk-6HWVI6MI.js} +0 -0
@@ -30,7 +30,9 @@ moved lines; include only structural views that changed.
30
30
  1. **Review.** Spawn `pi-lens-reviewer` (worktree isolation) with the PR
31
31
  number, a one-paragraph summary of the claim, and any PR-specific attack
32
32
  angles. Self-authored and small PRs get reviewed too — the depth follows
33
- the review tier below, never the priority label.
33
+ the review tier below, never the priority label. Bots review the PR as well:
34
+ every bot thread (Greptile and others) gets a disposition reply, `fixed in
35
+ <sha>`, `accepted and disclosed`, or `rejected because <reason>`.
34
36
  2. **Fix rounds.** Send findings back to the PR's original author agent when
35
37
  its worktree survives (SendMessage — cheapest context); otherwise spawn
36
38
  `pi-lens-fixer` on the branch with the findings inlined.
@@ -75,7 +77,8 @@ moved lines; include only structural views that changed.
75
77
  sweeps is not green — run the sweep on the merge before merging. Apply
76
78
  AGENTS.md's one mutation layer (#4005): new-guard proof and demonstrated
77
79
  correctness gaps gate the merge. `ci-verdict` prints no mutation line, and
78
- the nightly Stryker report is not a merge input.
80
+ the nightly Stryker report is not a merge input. Every bot review thread
81
+ carries its disposition reply and is resolved before the merge.
79
82
  5. **Merge.** `gh pr merge <N> --merge` (merge commit, repo convention).
80
83
  If "not up to date", `gh api -X PUT .../pulls/<N>/update-branch`, wait for
81
84
  CI, re-gate, merge. On GitHub 503s: retry with backoff, never switch to
@@ -160,6 +163,18 @@ blocks dispatch above the thresholds (no hand-written fallback;
160
163
  every refill; state them in the lane ledger. Standing rule from
161
164
  2026-09-03, lifted only when the maintainer says so.
162
165
 
166
+ ## Host capacity (orchestrator)
167
+
168
+ The maintainer may cap how many subagents run at once, for example when RAM is
169
+ shared with a local model. This is a machine-load cap, separate from
170
+ `PI_LENS_TEST_MAX_WORKERS` and from Git authority. A lane counts by what it
171
+ runs, not by its role or brief wording: any agent that runs a build, Vitest, a
172
+ language server or a probe counts, including an investigator that reproduces
173
+ through a probe and a Git-read-only reviewer. Agents that only read files and
174
+ call `gh`, grep or Explore never count and run in parallel with the capped
175
+ lanes; their brief says "no builds, no tests, no language servers, no probes"
176
+ (maintainer, 2026-10-14).
177
+
163
178
  ## Brief contract (orchestrator)
164
179
 
165
180
  Before dispatching any issue that adds a shared helper or seam: grep for
@@ -191,8 +206,27 @@ exactly one `priority:p1|p2|p3` (AGENTS.md #1676 rubric). The priority labels
191
206
  were found deleted from the repo on 2026-09-03 and recreated (#2553); an
192
207
  issue filed without one is a triage defect, not a shortcut.
193
208
 
194
- Every reviewer **follow-up issue** generalization verdict is filed and assigned
195
- to a seam group on the tracking queue in the same turn. At each regroup, scan
209
+ **Merge bar (user, 2026-10-18).** A PR merges when no HIGH finding is open and
210
+ every gating check is green on the exact head. Each MEDIUM or LOW finding
211
+ either folds into the same PR or becomes an accepted residual: the PR body
212
+ lists it under `## Accepted residuals`, named `p3` with its severity and live
213
+ population (for example `p3 (MEDIUM, live 0): <the gap>`), so the gap keeps a
214
+ priority without an issue.
215
+ A residual never becomes a follow-up issue. File an issue only for p2 or
216
+ higher work that cannot ride the PR: a HIGH outside the PR's scope, or a
217
+ MEDIUM with a live population. Before a final round, the brief says "final
218
+ round" and names what it fixes; a residual of MEDIUM or below after it does not
219
+ reopen the round.
220
+
221
+ **Known gaps (user, 2026-10-19).** An open p3 issue is an accepted known gap,
222
+ not backlog. The orchestrator closes it as not planned with the `known-gap`
223
+ label and lists it under its seam on the pinned tracker #4626. When a PR
224
+ merges, its `## Accepted residuals` lines join the same tracker under their
225
+ seam. A known gap reopens as p2 when it turns material: a live wrong result,
226
+ data loss, a hang, or a leak with no bound.
227
+
228
+ Every reviewer **follow-up issue** generalization verdict that meets that bar is
229
+ filed and assigned to a seam group on the tracking queue in the same turn. At each regroup, scan
196
230
  merged PRs for subset-shaped changes that lack a generalization verdict.
197
231
 
198
232
  Before filing a review follow-up, apply the standing fold rule: fold same-seam
@@ -202,6 +236,13 @@ re-verification; small code folds carry a red-first test and return to the same
202
236
  reviewer. File only different-seam, blocked, decision-dependent, untouched
203
237
  pre-existing, or risk-class-changing items, as one consolidated issue per PR.
204
238
 
239
+ A brief carries the lane's facts and the task, and points at the role
240
+ contract for everything else. Lane facts are the worktree, branch, base,
241
+ TMPDIR, test-worker cap, Git grant, and deliverable path. It never restates
242
+ contract rules such as hooks, trailers, stash, PR-body lint or summary
243
+ shape, because the role wrapper loads them. `bin/claude-lane.sh` prints
244
+ exactly the lane facts.
245
+
205
246
  ## Round-count rail (orchestrator)
206
247
 
207
248
  When a verify round reports that a fix round introduced a NEW defect on the
@@ -334,7 +375,16 @@ operator's private notes, so a different orchestrator can run the same train.
334
375
  round 1.** Their correctness lives in parsing edge cases, exactly where the
335
376
  smaller model loses: #2693 took two Sonnet rounds (~720k tokens) on a text
336
377
  scanner before the rail sent round 3 to Opus, which rewrote it on the AST
337
- and closed in two rounds.
378
+ and closed in two rounds. The rule covers checks that scan source text or
379
+ its AST. A plain assertion over config or workflow data (two pins match, a
380
+ key exists) goes to Sonnet, or to Haiku when mechanical (#4350).
381
+ - **Haiku 5.5 is the orchestrator's cheap lane.** The orchestrator uses it
382
+ without asking for read-only locate and premise-pointer passes, CI-red and
383
+ nightly investigations (`pi-lens-investigator`), and mechanical lanes
384
+ through `pi-lens-fixer-light`. Mechanical lanes include trailing folds,
385
+ dependabot pin and allowlist moves, and reviewer-prescribed test rows. It
386
+ never authors detectors or governance sweeps (the Opus rule above), and
387
+ never takes lifecycle or identity seams or reviews of runtime diffs.
338
388
  - **Brief shape for a fixer.** Issue/PR number and head; the checked-out
339
389
  branch; the exact findings with file:line, the reviewer's probe to reproduce
340
390
  FIRST, and the remedy shape the maintainer chose; what to fold (net-count)
@@ -501,8 +551,18 @@ operator's private notes, so a different orchestrator can run the same train.
501
551
  layer SHOULD have caught it earlier and at what cost. The accepted layer
502
552
  words are the `DETECTION_LAYERS` list exported by `scripts/check-pr-body.mjs`,
503
553
  which the `## Detection` body check reads; the prose does not restate them.
554
+ `nightly` may carry its workflow as `nightly:<workflow>`, and a bug-closing
555
+ PR is refused when `Caught by:`, `Should have been caught by:`, the reason
556
+ after `Gap: none:`, the `Shape: new:` name or the `Enforcer: none:` reason is
557
+ a placeholder (starts with `unknown`, or is exactly `n/a`, `tbd` or `?`)
558
+ (#4519: 139 of 363 closed bugs read unknown in the 2026-10-16 retro).
504
559
  If that layer does not exist, file it as an issue with the bug as
505
- its named recurrence — the same standard shapes are held to. The ledger
560
+ its named recurrence — the same standard shapes are held to. The lesson
561
+ names the defect SHAPE and its tree-wide enforcer, not only a test for the
562
+ instance: the Gap names the `AGENTS.md` catalog shape (or a new shape) and
563
+ either a test that scans the whole population, an issue to build one, or
564
+ `judgment-only` with the reason. A one-bug test is the fix's regression
565
+ test, not the closed gap (lint half: #4439). The ledger
506
566
  carries a `caught by / should have been caught by` column. Record: #2587's
507
567
  manifest entry escaped the package for four releases; a second registration
508
568
  path masked it, so the shipped defect was foreign-tree adoption, not absence
@@ -722,8 +782,10 @@ Each row cost a lane at least once; the prose above carries the record.
722
782
  | 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 |
723
783
  | 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 |
724
784
  | 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 |
785
+ | Quoting a closing keyword in a commit message | #4375's commit f40ac6c28 quoted `not fixed: #4346` and `Whether this closes #1513` as lint examples; GitHub acts on commit-message keywords that reach the default branch, so the merge closed both (2026-10-14). `closingIssuesReferences` omits them. Commit messages get the same keyword rules as the body; quote examples as `#N` without the keyword |
786
+ | Merging a contract-doc edit on an orchestrator read alone | #4379's seven-line host-cap section used "read-only" for the opposite of its meaning in `docs/pi-lens-subagent.md`, and left probe-running investigators unclassified; a scoped review caught both (2026-10-14). An edit to `docs/pi-lens-*.md` or AGENTS.md gets one scoped reviewer pass |
725
787
  | 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 |
726
- | 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" |
788
+ | 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 what the merge bar admits (p2 or higher that cannot ride the PR), and give each group a "done when" |
727
789
  | 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 |
728
790
  | 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 |
729
791
  | 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). |
@@ -747,3 +809,31 @@ Each row cost a lane at least once; the prose above carries the record.
747
809
  | 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. |
748
810
  | 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. |
749
811
  | 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. |
812
+ | Asking the maintainer whether to build or file a missing detection layer | The orchestrator owns the detection retrospective: it files the layer issue, or folds it into the same-seam PR, the same day, and tells the maintainer (maintainer, 2026-10-13). |
813
+ | Sending a detector or governance-test round to a cheap model | The #4341 npx-pin scanner went to a Haiku round before the Opus-from-round-1 rule was re-read; check the routing bullets before every detector brief. |
814
+ | Routing on the word "governance" instead of the risk | #4350 (a CodeQL pin-equality test) went to Opus as "governance authoring"; the Opus rule is for source-scanning detectors only. |
815
+ | Leaving the `dist/` precondition undeclared | At least 5 lanes (#4417, #4418, the #4422 verify, the #4410 r1 review, the #4423 review F5) each ruled out the same 3 census reds that need `npm run build:dist` (2026-10-14). Mechanical: fail fast when a selected test needs `dist/` and it is missing or stale (#4436); `CLAUDE.md` names `npm run build:dist` for those files meanwhile |
816
+ | A wait helper with a fixed wall-clock budget | `interleaving-kit` `waitFor` ran out at 3000 ms under CI load (run 38618401454, `tests/clients/fix-run-restore.test.ts:378`); the file passed alone and under 3 shuffle seeds, so the red read as a flake. Mechanical, filed as #4437 |
817
+ | Briefing a worker to "report the size first" before a large migration | A worker cannot wait for a reply, so the #4432 fixer did the migration anyway (2026-10-14). A brief authorizes the conditional branch with its bound, or tells the worker to stop and hand back; `AGENTS.md` "Orchestration and delegated work" |
818
+ | Naming a file by basename in a brief | "index.ts" meant `clients/lsp/index.ts`; a Haiku measurement pass searched the root `index.ts` and reported the #2052 comment missing (2026-10-14). Name every file by its repo path |
819
+ | Sending a lane that must find its own failure space to Haiku | #4342 rounds 1 and 2 left three review findings (a wall-clock bound, a wrong offline premise, a 13-vs-20 population); a fresh Opus round with a state table passed verify first time (#4410 round 3). Haiku folds with a prescribed remedy (#4340, #4341, #4345, #4356, #4368, #4372, #4374, #4417) landed first try. Haiku takes only a prescribed change; `AGENTS.md` "Orchestration and delegated work" |
820
+ | Listing a blast radius without the changed result's callers | #4411 round 3 changed `touchFile`'s result and the body omitted the cascade neighbour caller (`clients/dispatch/integration.ts:2139`), which then printed an uncaused "inconclusive" line every turn (review N2). `AGENTS.md` already requires `module_report` with `blastRadius: true` before and after; run it for the changed result and quote every caller, then read each one |
821
+ | Leaving a ledger row reading as a remainder after a PR flips from `refs` to `closes` | The orchestrator's closes-check refused two lands (#4422, #4409) because the row still named a remainder after verify confirmed every criterion (2026-10-14). Mechanical, orchestrator tooling outside this repo: to be fixed in the orchestrator's land tooling, not by a repo check |
822
+ | Linting the PR body only at the end of a round | #4423's advisory `PR body` check went red on 5 consecutive pushes in round 2 with the same passive-voice findings (2026-10-14); a push does not change the body, so the check re-read the unfixed one each time. Lint the body with `--lint-local` before the first push of a round (`docs/pi-lens-fixer.md` "Fix rounds") |
823
+ | Concluding "no existing seam does this" from a search of your own call names | #4528 searched `notifyExternalFileChange\(` and missed six freshness modules in `clients/`; five detectors ended up wiring their own consumers (#4535). Search by primitive (`docs/pi-lens-fixer.md` "Before code"); the reviewer widens the query (`docs/pi-lens-reviewer.md`, #4536) |
824
+ | Importing `dist/` from a script a workflow runs before any build | #4525's `scripts/assert-evaluated.mjs` reached `dist/` through `lib/clean-signal.mjs`, so `tool-smoke-prs` would fail on every refresh PR. #4531 pins the import graph with a test and plants |
825
+ | Pinning workflow step shell as text instead of running it | #4531 r1: four mutations of the Swift, APFS and handshake shell survived, including deleting `set +e`. Run the extracted step shell against stubs in a test |
826
+ | Filing gap after gap on one mechanism without an audit | Eleven freshness gaps went into #4532 before anyone asked why there were eleven; the cause was one missing fan-out (#4535). Three issues on one mechanism open a consolidation audit (`AGENTS.md` "Orchestration and delegated work") |
827
+ | Landing with an unresolved bot review thread | #4548 and #4558 merged with open Greptile threads (2026-10-17); each one's disposition arrived or never did, and nothing held the land. Every bot thread gets a disposition reply and is resolved before the merge (step 1 and step 4 of "The loop, per PR") |
828
+ | Pushing a worker tree on a stale "failed" settlement | The #4575 r5 settlement read as failed while its resumed turn was live and about to push (plegma #752). The orchestrator's push-verify now refuses a tree with a live agent process, and its wait loop takes a `turnId`. |
829
+ | Settling a fix round with unpushed commits | #4582 r1 settled with the commits still local and nobody noticed (plegma #753). The settlement hook now prints `UNPUSHED` or `DIRTY` for the tree it just settled. |
830
+ | Switching `closes` to `refs` through a raw `gh pr edit` body edit | The #4581 land was refused because commit `d068be947` still closed #4488. `pr-body.sh` now refuses a body that drops a commit's close keyword, and the orchestrator guard denies raw body edits. |
831
+ | Reading an empty DeepSeek turn as a worker stall and resuming it | Four resumes on one backend exhausted the balance (plegma #751). Two empty turns on one backend mean check the backend or the quota before any resume. |
832
+ | Proving a workflow floor with a test that matched the step's shell text | The step's exit code was never checked, and the body claimed a shared helper had not landed (#4584 review F1/F3). The reviewer caught both under the existing tautological-test and reuse-the-seam rules, and the round moves the case to `tests/scripts/floor-steps-executed.test.ts`. |
833
+ | Taking a local `vitest --shard=3/5` soak as CI's shard 3 | The shard never contained the target file, so four runs were wasted (#4488). The soak now asserts the target is in the set it recovered from CI's own job log before it runs. |
834
+ | Trusting fixers and reviewers to read the bot threads on their own | Greptile threads and code-scanning alerts reached a round only when the orchestrator relayed them (#4566, #4575). The role contracts now carry a conditional read-and-dispose rule; a missing bot review is never evidence, and the reviewer's own pass stands alone. |
835
+ | Leaving the PR watcher down after a context compaction | #4594 sat conflicting with nobody told (2026-10-18). An orchestrator hook now marks a compacted or resumed session and denies tool calls until the watcher runs again. |
836
+ | Resuming a review or fix round without `passthrough: ["gh"]` | A workspace override drops the inherited passthrough (plegma #762), so the #4593 verifier ran with `gh` unauthenticated and could not read CI or threads. The orchestrator's delegate guard refuses such a round. |
837
+ | Pushing to a PR branch while a fix round is queued against its old head | Merging master into #4594 staled the queued round's lease; the worker pushed a diverged copy to its handle branch (plegma #723). The orchestrator's push-verify refuses while a round still publishes to that branch. |
838
+ | Resuming a reviewer without naming the deliverable | The resumed verifies of #4575 and #4593 inherited report names that did not match the brief, so the hand-back missed the report. Every resumed round names its `deliverables` explicitly. |
839
+ | Calling an issue "blocked on a release" without reproducing it on master | #4554 waited on a release; 58 runs on master did not reproduce it, and it closed crediting #4563. Reproduce on master before naming a blocker. |
@@ -76,7 +76,11 @@ snapshots; no additional telemetry sink is created.
76
76
  re-activates and uses them. MCP remains connection-scoped and owns the
77
77
  terminal latch.
78
78
  6. **Backlogs**: `lsp_document_drift` rows by disposition, files affected,
79
- `driftAgeMs` p50/p95/max; `agent_end_deferred_mutation_drain` durations and
79
+ `driftAgeMs` p50/p95/max; `lsp_document_drift_cap` rows (at most one per
80
+ session) with `tracked` and `cap` when the tracked-document set stands above
81
+ `DRIFT_TRACK_CAP` because every record belongs to a document a live server
82
+ still holds (#4503) — `tracked - cap` is the excess at the first crossing,
83
+ not the held-document count or later growth; `agent_end_deferred_mutation_drain` durations and
80
84
  coalesced path counts; `deferred_format_file` runs with `changed:true`
81
85
  versus total. A formatter that never settles is visible only as an
82
86
  anti-join (#3828): a `deferred_format_post_exit_resync` row with
@@ -109,7 +113,9 @@ snapshots; no additional telemetry sink is created.
109
113
  displaced is another; a subagent beside a live primary writes none)
110
114
  transitions,
111
115
  `session_end_fence_rollup` (one per primary shutdown: `sources[]` with
112
- `guarded` and `dropped`, plus totals). Read `read_guard_branch_retained` with
116
+ `guarded` and `dropped`, plus totals), `lsp_created_import_scan_rollup`
117
+ (one per primary shutdown when the created-module producer ran: `calls`,
118
+ `importers`, `targets`, `capped`, `oversized`, `totalMs`, `maxMs`). Read `read_guard_branch_retained` with
113
119
  `payloadReads`: `kept 0, dropped 0` is a missing payload when `payloadReads`
114
120
  is `null`, an empty read set at `0`, and an ignored payload when it is above
115
121
  0 beside a `payloadVersion` that is not the current one.
@@ -62,7 +62,10 @@ is involved. Every finding cites the source it came from.
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
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
+ examples go to `HISTORY.md`, under a heading that names the shape, such as
66
+ `## 2026-10-14 - title (shape N)`: a lean entry cites no issue, and
67
+ `tests/config/shape-history-governance.test.ts` finds the record by that
68
+ heading or by one of the entry's own issue numbers. A reviewer duty goes
66
69
  into `docs/pi-lens-reviewer.md`; a fixer duty goes into `docs/pi-lens-fixer.md`
67
70
  only when the fixer is the sole actor who can honour it. Standards are
68
71
  enforced by the reviewer, whose context pressure is lowest; fixers get
@@ -50,6 +50,53 @@ a brief supplies only `lane=<name>`, scope, and the grant.
50
50
  7. Clean up: revert mutations, delete probes, and leave
51
51
  `git status --porcelain` empty.
52
52
 
53
+ ## Compliance pass
54
+
55
+ Run this over the merge-base diff at step 2, before the adversarial probes in
56
+ step 4. Each row is a rule a bot can decide from what the diff touches; the
57
+ probes still prove behaviour. Quote the named evidence in the review, and name
58
+ the anchor in the finding so the fixer can route it. A row with no recurrence
59
+ does not ship.
60
+
61
+ | Diff touches | Check | Evidence to quote | Recurrence |
62
+ | --- | --- | --- | --- |
63
+ | A new `it(` or `test(` title, or a case added to a table test | Red first: the case fails on the pre-fix source, with the failure the defect names (principles §2 "Red first") | The pre-fix transcript, with its `Tests N failed` line naming the new titles | #4577 (Greptile, 2026-10-17: round-4 cases shipped with no red) |
64
+ | A new guard, branch, filter, cap or fallback | Mutation red on that predicate, both directions, in a compile-valid change (principles §2 "Mutation output is quoted") | The `scripts/mutate.mjs` transcript and its `RED` status line, with the one test it reds | #4575 (Greptile r4304045025: no mutation red for the saveOnly rule) |
65
+ | A file under `clients/lsp/`, `formal/`, or any path `formal/switch-pins.json` names | The model moves with the code: a `.tla`/`.cfg` hunk and its TLC verdict, or a `TLA+ unaffected:` line; a flipped constant flips its config and its pin (AGENTS shape 68) | The line, or the model diff plus the verdict, and the pin's test name for a flipped constant | #4575 (Greptile r4304045020: the model did not move with the code), #4387, #4393 |
66
+ | A spawn, shell or path seam: `clients/package-manager.ts`, `clients/lsp/launch.ts`, `clients/path-utils.ts`, `clients/safe-spawn.ts`, or any `trySpawn` caller | Read the Windows lane, and keep a shim cell that asserts the platform command (AGENTS "Test requirements"; "Dispatch, runners, formatters, and installers") | The `Unit tests Windows` row on the head, or the shim cell's platform assertion | #4566 (Greptile r4304149666: the `.cmd` cells), #4356, #4263 |
67
+ | A rung that can execute project code | Judge the rung by the resolved target under every trust state, never by the name it was called with (AGENTS "LSP, trust, and process execution") | The target table: each spelling, its resolved path, and the verdict under trusted, unknown and denied | #4566 (an empty `PATH` and a global link each ran project code), #4530 |
68
+ | A new shared helper | Net-count rule: delete a same-shape sibling in this change (principles §1 "Net-count rule for shared helpers") | The deleted sibling in `Change outline`, or the unsafe-to-fold reason with its follow-up link | #2585 r1, #2617 r1 (an existing override and scan set bypassed or recopied), #3064, #3065, #3066, #3068 (a fold's newly sole predicate left untested) |
69
+ | A second writer, reader or mirror of one shared record | Design shared state once, with a reason or kind discriminator per writer (principles §1 "Design shared state once"; AGENTS shape 24) | The writers-by-axis table, and the discriminator each writer carries | #1631/#1641 (the `stale` collision that was green alone), #1633, #1703 |
70
+ | A durable record whose shape changes, or a new version of one | Keep the fixture corpus: every version that produced the record still parses (principles §2 "Keep fixture corpora") | The fixture path and the parser test that replays it | #3594 R2-F1 (AGENTS shape 57) |
71
+ | A cache or memo key | Key every input the value depends on, trust scope and install state included (AGENTS shape 6) | The key's input list beside the value's dependencies, and the mutation that changes one input | #4562 (a large update left a cached answer), #4566 (a trust change left tools missing) |
72
+ | A test-side source scan, census, ratchet or detector | Detectors match code, not prose, and fail closed on an unlisted spelling (principles §2 "Detectors match code"; AGENTS shape 69) | The blanked-source read, and three plants the author did not design for: an alias, an indirect call, a value through another binding | #2693 (a ratchet counted four sites where six existed), #4439 |
73
+ | A workflow, action or job | The edited lane runs on a pull request, or a branch run is quoted with its run id (AGENTS "Commands and gates") | `gh workflow run <file> --ref <branch>` with its run id, or the PR-eligible cell's name | #3043, #3085 |
74
+ | A `continue-on-error` producer or a nightly floor | The producer reports to `scripts/assert-evaluated.mjs`, and its floor reds below the measured count (AGENTS "LSP, trust, and process execution") | The floor value beside the run's evaluated count | #4518 |
75
+ | A path a host tool was given (a `~`, an `@` prefix, a `file://` URL), or a path re-resolved after it left disk | Resolve by provenance, one seam per provenance; a generated or recovered path is never re-resolved (AGENTS shape 74) | The resolver the caller uses, and the path form it accepts, before and after | #4576, #4577 (a bash operand resolved on the host-argument ladder, then an absolute spelling rewritten) |
76
+ | A path recovered from disk, a synthetic write event, or a path pi-lens generates | The path carries its provenance, host argument, shell token, recovered or generated, and nothing re-derives it (AGENTS shape 58) | The provenance the caller states at the injection point, and the resolver it therefore skips | #4577 (a recovered name was re-folded), #4558 |
77
+ | A path-keyed map, normalizer or path comparison | Normalize on write, read, delete and rehydrate, and test Windows separators and casing (AGENTS shape 1) | The writer and reader table, with the normalizer each one calls | #3178 (four rounds, two inverted arms, one unmeasured swap) |
78
+ | A session, lifecycle, generation or turn-end seam | Capture the generation before the await, and key the state by the session that owns it (AGENTS shapes 21 and 22; "Session, telemetry, and delivery") | The captured scope or generation the write checks, and the test that races it | #4258 (a stale activation rebinding a held bridge), #4154 |
79
+ | A lifecycle, ownership or queue-ordering change | Name a cell and a mutation per axis: owner and identity, last leave, and queue ordering (principles §1 "Identity and lifecycle rules"; AGENTS shapes 21 and 22) | The state table with one row per axis, and the mutation transcript for each cell | #4563 (seven lifecycle findings), #4575 (a slow send overwrote a newer edit), #4562 |
80
+ | A lifecycle change | The TLA+ model moves with the code, and `docs/pi-lens-monitor.md` gains the row for a new store or hand-off branch (AGENTS shape 68; "Session, telemetry, and delivery") | The model diff or `TLA+ unaffected:` line, and the monitor-doc row | #4563, #4569 (held documents undercounted), #4575 |
81
+ | A delivery surface, or a bound on findings that reach the model | A bound discloses its truncation on the rendered surface, and a skipped or unavailable result is not clean (AGENTS shape 10) | The rendered truncation line, or the skip reason from `RUNNER_SKIP_REASONS` | #3166 r2 (an 80-finding input bound zeroed a neighbour's errors) |
82
+ | A relaxed or rewritten existing assertion | Mutate the behaviour the test is named for; a rewrite that stays green is a deleted test (AGENTS "Issue and PR design contract"; principles §2) | The red on the new assertion, with that behaviour broken | #4390 (the eviction smoke's rewrite passed with root re-registration broken) |
83
+ | A new decision branch on a session, lifecycle or delivery seam | Name its record, sink plus kind, and read it back through the real seam (AGENTS "Session, telemetry, and delivery"; shape 31) | The record literal, and the test that reads it back | #3873 (a fix that could not be shown to fire live), #3875 |
84
+ | A new failure path, catch or silent return | One bounded record per distinct event, in a stream a monitor reads without asking (principles §1 "Every new failure path gets bounded observability"; shape 31) | The record literal and its sink, or `none:` with its reason | #4562 (a failed log write stayed silent), #4575 (a failed save left no trace) |
85
+ | Every diff, every changed file, tests included | Read the whole diff file by file. Check each PR-body claim against the diff, and look in the body for proof before calling it missing (principles §3 "Reviewing and delegating") | The body line or transcript quoted beside a claim the diff cannot show, or the finding names the body line that lacks it | #4574 F2, #4582 F1; 3 of Greptile's 4 false positives were a transcript already in the body (#4572, #4573, #4577) |
86
+
87
+ Rows 1, 2 and 4 are mechanical from #4585: `scripts/check-pr-body.mjs`
88
+ (`lintDiffCompliance`, wired into both entry points) reds a body that omits
89
+ their evidence, and it keys each item to the diff: a red belongs to the title
90
+ its table names and to the file whose path it spells, and a Windows read
91
+ belongs to the seam file it names or to a diff with exactly one seam file.
92
+ Row 1 is file-level: a changed test file owes one fenced red-first transcript
93
+ that names it and shows a failure from it, or a Controls row naming it with a
94
+ reason. The lint does not read a title, a table row or a suite chain, so a red
95
+ from the file proves the file whatever the new case is called (#4605). Row 3
96
+ stays a reviewer judgement row; the lint never decides what a model means. Confirm the lint passed on the head, then spend
97
+ this pass on the rest — a quoted mutation-table red is not a red-first
98
+ transcript, and a body that names the right file is still yours to judge.
99
+
53
100
  ## Verification
54
101
 
55
102
  For each new or changed `vi.mock` or hand-built double of a `clients/` module,
@@ -61,10 +108,20 @@ real seam. Check that every gate the diff adds is exercised through that path.
61
108
  a lifecycle, dispatch, or ownership seam, run EVERY suite that exercises the
62
109
  behaviour the seam governs and name the list; a curated file set cannot
63
110
  clear what it omits (#3622).
111
+ - **Challenge the population query.** Re-run the fixer's sibling search with
112
+ a wider query of your own, by primitive or mechanism instead of the fixer's
113
+ call names. Report what the fixer's query missed; a population that a wider
114
+ query extends is a finding (#4536).
115
+ - **Severity and live population.** Every finding carries HIGH, MEDIUM or LOW
116
+ and its live population (how many sites in the tree hit it today). The
117
+ verdict follows the merge bar in `docs/pi-lens-merge-policy.md` "Filing
118
+ issues": no HIGH plus green gating checks is merge-ready, and a MEDIUM or
119
+ LOW names whether it folds or stays an accepted residual.
64
120
  - **Generalization verdict.** When a mechanism, policy, guard, or optimisation
65
121
  targets N of M members (registry entries, servers, tools, languages,
66
122
  stores), name M, why the others are excluded, and their default, and end
67
- with *widen in this PR*, *follow-up issue* (with its seam group), or *stay
123
+ with *widen in this PR*, *accepted residual* (named `p3`, with its live population),
124
+ *follow-up issue* (p2 or higher only, with its seam group), or *stay
68
125
  specific* (with the reason). A missing verdict is a finding (#3622; the
69
126
  optional ast-grep assist is #3684).
70
127
  - Review the pre-push self-scan with `npm run astgrep:self-scan`; `pr-preflight`
@@ -76,13 +133,20 @@ real seam. Check that every gate the diff adds is exercised through that path.
76
133
  fixer's hand mutations. There is no per-PR Stryker comment or `MUTATION`
77
134
  line to read; the nightly Stryker report on master is exploratory and is not
78
135
  a review input.
136
+ - For every relaxed or rewritten existing assertion, mutate the behaviour the
137
+ test is named for; a rewrite that stays green is a finding (#4390). This is
138
+ the exception to the one-spot-check cap above.
79
139
  - Repeat the pattern and population sweeps. Check blast radius, bounded
80
140
  observability, changelog, commit, and PR-body requirements.
81
141
  - Re-run the PR's `## Class sweep` search yourself and widen it when the
82
142
  named shape is broader than the touched seam (#4273, #4268).
83
143
  - On a bug-closing PR, check the `## Detection` lesson: the layer named under
84
144
  `Should have been caught by:` must be one that would actually have caught
85
- the bug, and `Gap:` must be a real issue, test, or reason (#4288).
145
+ the bug, and `Gap:` must be a real issue, test, or reason (#4288). Judge
146
+ `Shape:` and `Enforcer:` too: the lint checks the catalog number and that the
147
+ path is on the base and named by the entry, not that the test scans the
148
+ shape's whole population, so open the enforcer and decide whether it does
149
+ (#4439).
86
150
  - For LSP, dispatch, cache, runner, or tool changes, test one non-TypeScript
87
151
  registry entry through the same seam.
88
152
  - On a net-count fold, mutate every predicate the deleted sibling used to
@@ -95,6 +159,9 @@ real seam. Check that every gate the diff adds is exercised through that path.
95
159
  ## Standing probes
96
160
 
97
161
  Run every probe the diff can trip and say which ran and what each returned.
162
+ For LSP diagnostics, the formatter, the review graph and `rename_file`, start
163
+ from the `verify-pi-lens` skill (`.claude/skills/verify-pi-lens/SKILL.md`)
164
+ instead of rebuilding the probe.
98
165
 
99
166
  - **Ladder and deletion sweep.** Every ask names the ladder rung it serves. An
100
167
  ask that adds a guard names its recurrence; an ask that deletes a defensive
@@ -114,6 +181,12 @@ Run every probe the diff can trip and say which ran and what each returned.
114
181
  except `index.ts`, which gates on the lifecycle hook handler a hunk lands in.
115
182
  A green `TLA+ models` run over an unchanged model proves nothing about the
116
183
  new code.
184
+ For a `TLA+ unaffected` line, read the family's as-built config constants:
185
+ a diff that changes a behaviour one of them encodes refutes the line and is
186
+ a finding (#4387: #4235 changed read-guard authorship while the as-built
187
+ switches kept the old behaviour). `formal/switch-pins.json` names each
188
+ pinned constant's test (#4393); a changed behaviour with no flipped value
189
+ and pin is the same finding.
117
190
  - **Red-proof audit.** A claimed red without its quoted transcript is a finding
118
191
  of its own; reproduce it (step 3).
119
192
  - **Quoted-evidence audit.** Diff every CI line the body quotes against the job
@@ -151,6 +224,26 @@ Run every probe the diff can trip and say which ran and what each returned.
151
224
  `// flake-shape: <detector> — <reason>` header and `wallClockBudgetInclude`
152
225
  membership (#2547). A pinned file whose count falls below its pin needs its
153
226
  baseline tightened; a stale ceiling re-admits regrowth.
227
+ - **Hot-path timing.** When the diff touches dispatch, `session_start`, LSP
228
+ diagnostics, a cache lookup or turn-end, re-run the body's before/after
229
+ timing on the real path, at a small and a large input (file size, file
230
+ count). A regression the body does not name and justify is a finding (#4344
231
+ r1: replay went from 6 ms to 321 ms; #4368 r1: import extraction took 190 ms
232
+ at 1.6k lines and 9.2 s at 12k). Read the `Hot-path latency (advisory)` job
233
+ summary on the head (#4363) first; it covers `session_start`, dispatch and
234
+ replay, and a red there is a finding unless the body justifies it. Green
235
+ means no regression of 1.25x and 5 ms; a "slower, below threshold" row is
236
+ still a number to read.
237
+ - **Shutdown-path parity.** When the diff moves or rewraps code that stops a
238
+ child (a server, a client, a spawned tool), compare the stop path before and
239
+ after: does the child still get its graceful signal (stdin end, shutdown
240
+ request) before any kill, and do its exit-time records and files still
241
+ appear? Count them over a few runs on both heads. A green suite proves
242
+ nothing here (#4366 r2: a shared-client fold swapped stdin end for SIGTERM;
243
+ the shutdown record went from 3/3 to 0/12 and 11 sockets leaked).
244
+ - **Windows path shapes.** A new test or runtime comparison of paths goes
245
+ through `toPosix` or `path.win32` (`AGENTS.md`). A host-default separator is
246
+ a finding even when Linux CI is green (#4356: Windows advisory red).
154
247
  - **Platform skips and session-start resets.** Apply the `AGENTS.md` test
155
248
  screens and the `SessionStartClassification` invariant.
156
249
 
@@ -198,8 +291,10 @@ the rate they remove them.
198
291
 
199
292
  ## Findings and verdict
200
293
 
201
- Classify every finding as **fold** or **file** with a one-word reason
202
- (`docs/pi-lens-subagent.md` "Follow-ups"). Order findings `CRITICAL`, `HIGH`,
294
+ Classify every finding as **fold**, **accepted residual** (named `p3`) or
295
+ **file** with a one-word reason and its live population (`docs/pi-lens-subagent.md`
296
+ "Follow-ups"; the merge bar is in `docs/pi-lens-merge-policy.md` "Filing
297
+ issues"). Order findings `CRITICAL`, `HIGH`,
203
298
  `MEDIUM`, `LOW`, `NITPICK`. Each carries a stable id, a file or symbol anchor,
204
299
  the reproduction command or probe output, expected and observed behaviour, the
205
300
  root cause, cost, and a concrete remedy, and whether it is an
@@ -218,6 +313,19 @@ merge-order interactions with other open PRs, plus:
218
313
  - `Disposition table`: each prior finding as `fixed`, `not fixed`,
219
314
  `new defect`, or `withdrawn (reason)`.
220
315
  - Cleared categories (one compact list) and exact-head identity.
316
+ - **Bot threads and code-scanning alerts.** When bot threads or code-scanning
317
+ alerts exist, read and dispose of each one: list every unresolved review
318
+ thread on the PR (`reviewThreads`, `isResolved == false`) and every open
319
+ code-scanning alert on the branch, both read at the exact head with the
320
+ commands in `docs/pi-lens-fixer.md` "Fix rounds". Rate each one as a
321
+ finding with its probe, or `refuted` with the probe that refutes it, so an
322
+ item nobody probed cannot read as cleared. A missing bot review is never
323
+ evidence of anything: never wait for one, never read its absence as a clear
324
+ signal, and let your own pass stand alone. No `merge-ready` verdict while
325
+ any thread or alert stays undisposed; the merge condition is
326
+ `docs/pi-lens-merge-policy.md` "The loop, per PR" step 1 and step 4
327
+ (`:34`, `:81`). Recurrence: #4566 and #4575 (2026-10-17), where the threads
328
+ outlived the rounds that should have read them.
221
329
 
222
330
  Use short, active, plain prose.
223
331
 
@@ -58,9 +58,11 @@ explicit orchestrator authorization for
58
58
  `--force-with-lease=<branch>:<sha>`.
59
59
 
60
60
  Push forms are in "Orchestrator lane mechanics". Before `gh pr create` or `gh pr edit`, lint the body with
61
- `node scripts/check-pr-body.mjs --lint-local <body-file> "<title>"`. Multiline
62
- text (bodies, commit messages, comments) goes through a file (`--body-file`,
63
- `git commit -F`); re-read what GitHub stored and check the newlines survived.
61
+ `node scripts/check-pr-body.mjs --lint-local <body-file> "<title>"`. Read the
62
+ lint's exit code directly, never through a pipe, before `gh pr create` or
63
+ `gh pr edit`: a piped status is the last command's, and a failing lint opened a
64
+ PR (#4348). Multiline text (bodies, commit messages, comments) goes through a
65
+ file (`--body-file`, `git commit -F`); re-read what GitHub stored and check the newlines survived.
64
66
 
65
67
  ## Orchestrator lane mechanics
66
68
 
@@ -130,8 +132,11 @@ the brief gives.
130
132
  ("Worktree and Git"). A reviewer is always `none` and read-only.
131
133
  GitHub comments and issue edits are separate: only a brief that grants them
132
134
  allows them.
133
- - **Deliverable.** The report opens with an `ORCHESTRATOR SUMMARY` of at most
134
- 30 lines: the PR (or branch), the head SHA, the change or verdict in a few
135
+ - **Deliverable.** The report opens with an `ORCHESTRATOR SUMMARY`. Its cap
136
+ follows the lane kind: at most 6 lines for a mechanical lane (trailing fold,
137
+ pin or allowlist move, merge-and-resolve), 20 for a locate or investigation
138
+ pass, and 30 for a fix or review round. The summary carries the PR (or
139
+ branch), the head SHA, the change or verdict in a few
135
140
  lines, red and green evidence as counts with the quoted transcript below it,
136
141
  every skipped check or environment block, and what the orchestrator must
137
142
  decide. The RETURNED message (the agent's final reply, or the plegma answer)
@@ -169,8 +174,9 @@ sets the exit code and only `clean` exits 0:
169
174
  file is tracked.
170
175
  - `unproven` (3): a step failed or a red could not be attributed (the build, a
171
176
  run with no named failing file, an `INCONCLUSIVE` red-on-base verdict, a
172
- failed lint or format check, a selection over the 25-file cap where only
173
- governance suites ran). That is not evidence of unrelated: report it and
177
+ failed lint or format check, a selection over the 25-file cap, where the
178
+ change's own tests, the governance suites and the best 25 import matches ran
179
+ and the rest did not). That is not evidence of unrelated: report it and
174
180
  stop, or fix the cause. The summary prints `selection: selected S, matched
175
181
  M, capped C`.
176
182
  - `2`: usage error (`--body <path>` or `--body=<path>` missing, unknown, or the
@@ -193,9 +199,9 @@ change adds or removes a pinned use, run it on the head and on the merge of
193
199
 
194
200
  Each pre-push head has a durable result record at
195
201
  `$(git rev-parse --git-common-dir)/pi-lens-prepush/<sha>.json`. It contains the
196
- head/base, timestamp, selected test files and their `import`, `history`, or
197
- `governance` reason, plus passed/failed/skipped counts, the Vitest exit code,
198
- and wall time. Re-pushes overwrite that head's record; writes prune records
202
+ head/base, timestamp, selected test files and their `changed`, `mirror`,
203
+ `import`, `history`, or `governance` reason, plus passed/failed/skipped
204
+ counts, the Vitest exit code, and wall time. Re-pushes overwrite that head's record; writes prune records
199
205
  older than fourteen days. The provisional record is written before build and
200
206
  self-scan work with outcome `tests-not-started`; preparation failures update it
201
207
  to `build-failed` or `self-scan-failed`. The write uses a same-directory
@@ -234,10 +240,12 @@ of fixture tests, and a real red hidden among them reaches CI (#4308).
234
240
  Fold a review follow-up into the same PR when it shares the seam or files, is
235
241
  about one commit, and needs no maintainer decision. Contract-only folds (body,
236
242
  comments, wording) are trailing commits; small code folds carry a red-first
237
- test and are routed per principles §3 "Round routing". File only
238
- different-seam, blocked, decision-dependent, untouched pre-existing, or
239
- risk-class-changing residuals (for example lifecycle work on a tooling PR), as
240
- one consolidated issue per PR.
243
+ test and are routed per principles §3 "Round routing". A MEDIUM or LOW that
244
+ does not fold is an accepted residual: list it under `## Accepted residuals`,
245
+ named `p3` with its severity and live population, and file nothing. File only p2 or
246
+ higher work that cannot ride the PR (a HIGH outside its scope, or a MEDIUM
247
+ with a live population), as one consolidated issue per PR. The merge bar is in
248
+ `docs/pi-lens-merge-policy.md` "Filing issues".
241
249
 
242
250
  ## Evidence and reporting
243
251
 
@@ -161,7 +161,7 @@ admitted lines explicitly.
161
161
 
162
162
  ### Verified hosts
163
163
 
164
- The certified policy is `>=0.80.10 <1.2.0`. Each listed minor line has a
164
+ The certified policy is `>=0.80.10 <1.4.0`. Each listed minor line has a
165
165
  release-QA witness; the workflow ceiling and `tests/packaging.test.ts` list are
166
166
  updated together.
167
167
 
@@ -172,6 +172,8 @@ updated together.
172
172
  | 0.99.2 | 2026-10-08 | 08abd60e193e5a17ea28dd4fbf3603cc9a0cdbe0 | 15 pass / 1 skipped (git-install-loads) |
173
173
  | 1.0.4 | 2026-10-08 | 08abd60e193e5a17ea28dd4fbf3603cc9a0cdbe0 | 15 pass / 1 skipped (git-install-loads) |
174
174
  | 1.1.0 | 2026-10-08 | 2fda17a53d62267cd9035fa04380bbf0e2de4318 | 15 pass / 1 skipped (git-install-loads) |
175
+ | 1.2.0 | 2026-10-16 | 9400454891d5a1beb0a4d2d9452dece276e22e71 | 15 pass / 1 skipped (git-install-loads) |
176
+ | 1.3.0 | 2026-10-16 | 9400454891d5a1beb0a4d2d9452dece276e22e71 | 15 pass / 1 skipped (git-install-loads) |
175
177
 
176
178
  Re-run any row with `node scripts/release-qa.mjs --pi <host>` at the listed commit.
177
179
 
@@ -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-10-10 on linux; 29 servers captured, 19 unavailable._
9
+ _Last generated: 2026-10-18 on linux; 41 servers captured, 9 unavailable._
10
10
 
11
11
  ## Diagnostic mode + navigation/edit operations
12
12
 
@@ -16,7 +16,7 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
16
16
  |---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
17
17
  | ast-grep | push-only | · | · | · | · | · | · | ✓ | · | · | · | ✓ | · | · | · | 1 |
18
18
  | bash | push-only | · | · | ✓ | · | · | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | · | · | 0 |
19
- | clojure | push-only | · | save+text | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 62 |
19
+ | clojure | push-only | · | save+text | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 64 |
20
20
  | cmake | push-only | · | save | · | · | · | · | ✓ | · | · | · | · | · | · | · | 0 |
21
21
  | cpp | push-only | · | save | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 3 |
22
22
  | csharp | pull | ✓ | save+text | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
@@ -31,7 +31,7 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
31
31
  | fish | push-only | · | save+text | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | 23 |
32
32
  | fsharp | push-only | · | save+text | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 0 |
33
33
  | gleam | push-only | · | save | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | · | ✓ | ✓ | · | · | 0 |
34
- | go | push-only | · | save | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 47 |
34
+ | go | push-only | · | save | ✓ | ✓ | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | 50 |
35
35
  | html | pull | · | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | · | · | ✓ | · | · | 0 |
36
36
  | json | pull | · | · | · | · | · | · | ✓ | · | ✓ | · | ✓ | · | · | · | 0 |
37
37
  | kotlin | push-only | · | · | ✓ | · | · | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | ✓ | · | · | 1 |
@@ -58,6 +58,9 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
58
58
 
59
59
  ## Raw advertised capability keys
60
60
 
61
+ Top-level keys of each server's `ServerCapabilities` — the full advertised
62
+ surface, including providers pi-lens does not yet consume.
63
+
61
64
  - **ast-grep**: codeActionProvider, executeCommandProvider, hoverProvider, textDocumentSync
62
65
  - **bash**: codeActionProvider, completionProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentSymbolProvider, hoverProvider, referencesProvider, renameProvider, textDocumentSync, workspaceSymbolProvider
63
66
  - **clojure**: callHierarchyProvider, codeActionProvider, codeLensProvider, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, experimental, foldingRangeProvider, hoverProvider, implementationProvider, linkedEditingRangeProvider, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, workspace, workspaceSymbolProvider
@@ -99,14 +102,11 @@ Legend: ✓ advertised, · not. **mode** = document diagnostics (`pull` = `textD
99
102
  - **yaml**: codeActionProvider, codeLensProvider, completionProvider, definitionProvider, documentFormattingProvider, documentLinkProvider, documentOnTypeFormattingProvider, documentRangeFormattingProvider, documentSymbolProvider, executeCommandProvider, foldingRangeProvider, hoverProvider, renameProvider, selectionRangeProvider, textDocumentSync, workspace
100
103
  - **zig**: codeActionProvider, colorProvider, completionProvider, declarationProvider, definitionProvider, documentFormattingProvider, documentHighlightProvider, documentRangeFormattingProvider, documentSymbolProvider, foldingRangeProvider, hoverProvider, implementationProvider, inlayHintProvider, positionEncoding, referencesProvider, renameProvider, selectionRangeProvider, semanticTokensProvider, signatureHelpProvider, textDocumentSync, typeDefinitionProvider, workspace, workspaceSymbolProvider
101
104
  - **zizmor**: textDocumentSync
102
- Top-level keys of each server's `ServerCapabilities` — the full advertised
103
- surface, including providers pi-lens does not yet consume.
104
-
105
105
 
106
106
  ## Advertised executeCommand allowlists
107
107
 
108
108
  - **ast-grep** (1): ast-grep.applyAllFixes
109
- - **clojure** (62): add-import-to-namespace, add-missing-import, add-missing-libspec, add-require-suggestion, as-to-refer, backward, backward-barf, backward-select, backward-slurp, change-coll, clean-ns, cond->if-refactor, create-function, create-test, cursor-info, cycle-coll, cycle-keyword-auto-resolve, cycle-privacy, demote-fn, destructure-keys, drag-backward, drag-forward, drag-param-backward, drag-param-forward, expand-let, extract-function, extract-to-def, forward, forward-barf, forward-select, forward-slurp, get-in-all, get-in-less, get-in-more, get-in-none, if->cond-refactor, inline-function, inline-symbol, introduce-let, kill-sexp, …
109
+ - **clojure** (64): add-import-to-namespace, add-missing-import, add-missing-libspec, add-require-suggestion, as-to-refer, backward, backward-barf, backward-select, backward-slurp, change-coll, clean-ns, cond->if-refactor, create-function, create-test, cursor-info, cycle-coll, cycle-keyword-auto-resolve, cycle-namespaced-map, cycle-privacy, demote-fn, destructure-keys, drag-backward, drag-forward, drag-param-backward, drag-param-forward, expand-let, extract-function, extract-to-def, forward, forward-barf, forward-select, forward-slurp, get-in-all, get-in-less, get-in-more, get-in-none, if->cond-refactor, inline-function, inline-symbol, introduce-let, …
110
110
  - **cpp** (3): clangd.applyFix, clangd.applyRename, clangd.applyTweak
111
111
  - **cue** (1): cuelsp.externalvalidate
112
112
  - **dart** (18): dart.edit.codeAction.apply, dart.edit.fixAll, dart.edit.fixAllInWorkspace, dart.edit.fixAllInWorkspace.preview, dart.edit.organizeImports, dart.edit.sendWorkspaceEdit, dart.edit.sortMembers, dart.logAction, dart.refactor.add_constructor_name, dart.refactor.convert_all_formal_parameters_to_named, dart.refactor.convert_selected_formal_parameters_to_named, dart.refactor.move_selected_formal_parameters_left, dart.refactor.move_top_level_to_file, dart.refactor.remove_constructor_name, dart.refactor.remove_import_prefix, dart.refactor_add.import_prefix, refactor.perform, refactor.validate
@@ -115,7 +115,7 @@ surface, including providers pi-lens does not yet consume.
115
115
  - **emmylua** (4): fake.applyEdit, fake.applyEditDeferred, fake.doThing, fake.releaseDeferredApplyEdit
116
116
  - **expert** (2): Reindex, connectionDetails
117
117
  - **fish** (23): fish-lsp.checkHealth, fish-lsp.createTheme, fish-lsp.execute, fish-lsp.executeBuffer, fish-lsp.executeLine, fish-lsp.executeRange, fish-lsp.fixAll, fish-lsp.generateEnvVariables, fish-lsp.selectQuickFixPosition, fish-lsp.showEnvVariables, fish-lsp.showInfo, fish-lsp.showReferences, fish-lsp.showStatusDocs, fish-lsp.showWorkspaceMessage, fish-lsp.toggleSingleWorkspaceSupport, fish-lsp.updateWorkspace, quickfix.delete, quickfix.disable, quickfix.fix, quickfix.fixAll, refactor.extract, refactor.rewrite, source.rename
118
- - **go** (47): gopls.add_dependency, gopls.add_import, gopls.add_telemetry_counters, gopls.add_test, gopls.apply_fix, gopls.assembly, gopls.change_signature, gopls.check_upgrades, gopls.client_open_url, gopls.diagnose_files, gopls.doc, gopls.edit_go_directive, gopls.extract_to_new_file, gopls.fetch_vulncheck_result, gopls.free_symbols, gopls.gc_details, gopls.generate, gopls.go_get_package, gopls.implement_interface, gopls.list_imports, gopls.list_known_packages, gopls.lsp, gopls.maybe_prompt_for_telemetry, gopls.mem_stats, gopls.modify_tags, gopls.modules, gopls.move_type, gopls.package_symbols, gopls.packages, gopls.regenerate_cgo, gopls.remove_dependency, gopls.reset_go_mod_diagnostics, gopls.run_go_work_command, gopls.run_govulncheck, gopls.run_tests, gopls.scan_imports, gopls.split_package, gopls.start_debugging, gopls.start_profile, gopls.stop_profile, …
118
+ - **go** (50): gopls.add_dependency, gopls.add_import, gopls.add_telemetry_counters, gopls.add_test, gopls.apply_fix, gopls.assembly, gopls.change_signature, gopls.check_upgrades, gopls.client_open_url, gopls.diagnose_files, gopls.doc, gopls.dragon_slayer, gopls.edit_go_directive, gopls.extract_to_new_file, gopls.fetch_vulncheck_result, gopls.free_symbols, gopls.gc_details, gopls.generate, gopls.go_get_package, gopls.implement_interface, gopls.list_imports, gopls.list_known_packages, gopls.lsp, gopls.maybe_prompt_for_telemetry, gopls.mem_stats, gopls.modify_tags, gopls.modules, gopls.move_declaration, gopls.move_type, gopls.package_symbols, gopls.packages, gopls.regenerate_cgo, gopls.remove_dependency, gopls.reset_go_mod_diagnostics, gopls.resolve_target, gopls.run_go_work_command, gopls.run_govulncheck, gopls.run_tests, gopls.scan_imports, gopls.split_package, …
119
119
  - **kotlin** (1): convertJavaToKotlin
120
120
  - **lua** (6): lua.autoRequire, lua.getConfig, lua.jsonToLua, lua.removeSpace, lua.setConfig, lua.solve
121
121
  - **opengrep** (2): semgrep/autofix, semgrep/ignore
@@ -130,22 +130,12 @@ surface, including providers pi-lens does not yet consume.
130
130
  Toolchain/binary not installed here, so capabilities weren't captured
131
131
  (many are the toolchain-gated family tracked in #241):
132
132
 
133
- - @prisma/language-server
134
- - @vue/language-server
135
- - bash-language-server
136
133
  - elixir-ls
137
- - fake custom lua server
138
- - fish-lsp
139
134
  - haskell-language-server
140
- - intelephense
141
135
  - jdtls
142
136
  - jdtls + lombok javaagent
137
+ - lake serve (Lean 4)
143
138
  - nixd
144
139
  - ocamllsp
145
- - pyright
146
140
  - shuck
147
141
  - sourcekit-lsp
148
- - svelte-language-server
149
- - vscode-css-language-server
150
- - vscode-html-language-server
151
- - yaml-language-server