@quickchatai/pi-quickreview 0.0.0-stage → 1.2.0

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 (697) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +75 -2
  3. package/assets/agents/pass-abstraction.md +64 -0
  4. package/assets/agents/pass-ask-human.md +134 -0
  5. package/assets/agents/pass-backcompat.md +67 -0
  6. package/assets/agents/pass-baseline.md +61 -0
  7. package/assets/agents/pass-behaviour-delta.md +64 -0
  8. package/assets/agents/pass-bounds.md +36 -0
  9. package/assets/agents/pass-claims.md +31 -0
  10. package/assets/agents/pass-concurrency.md +168 -0
  11. package/assets/agents/pass-consistency.md +57 -0
  12. package/assets/agents/pass-contracts.md +30 -0
  13. package/assets/agents/pass-data-safety.md +54 -0
  14. package/assets/agents/pass-deferred.md +35 -0
  15. package/assets/agents/pass-delivery.md +37 -0
  16. package/assets/agents/pass-duplication.md +60 -0
  17. package/assets/agents/pass-intent.md +63 -0
  18. package/assets/agents/pass-lint-conformance.md +46 -0
  19. package/assets/agents/pass-maintainability.md +67 -0
  20. package/assets/agents/pass-placement.md +68 -0
  21. package/assets/agents/pass-prod-risk.md +24 -0
  22. package/assets/agents/pass-rollout.md +32 -0
  23. package/assets/agents/pass-roundtrip.md +46 -0
  24. package/assets/agents/pass-security.md +31 -0
  25. package/assets/agents/pass-simplicity.md +68 -0
  26. package/assets/agents/pass-statelessness.md +27 -0
  27. package/assets/agents/pass-style.md +37 -0
  28. package/assets/agents/pass-sweep.md +57 -0
  29. package/assets/agents/pass-tests.md +58 -0
  30. package/assets/agents/pass-ui.md +23 -0
  31. package/assets/agents/pass-validate.md +50 -0
  32. package/assets/agents/pass-widened.md +46 -0
  33. package/assets/agents/scan/pass-scan.md +86 -0
  34. package/assets/config.example.toml +1099 -0
  35. package/assets/deploy/reviewer/AGENTS.override.md +12 -0
  36. package/assets/profiles/default/README.md +21 -0
  37. package/assets/profiles/default/addenda/.gitkeep +0 -0
  38. package/assets/profiles/default/profile.toml +17 -0
  39. package/assets/profiles/example-django/README.md +21 -0
  40. package/assets/profiles/example-django/addenda/10-migration-discipline.md +13 -0
  41. package/assets/profiles/example-django/addenda/20-new-column-nullability.md +12 -0
  42. package/assets/profiles/example-django/addenda/30-test-doctrine.md +12 -0
  43. package/assets/profiles/example-django/addenda/40-orm-usage.md +19 -0
  44. package/assets/profiles/example-django/addenda/50-declared-shape.md +10 -0
  45. package/assets/profiles/example-django/addenda/60-config-placement.md +14 -0
  46. package/assets/profiles/example-django/heuristics.toml +24 -0
  47. package/assets/profiles/example-django/profile.toml +9 -0
  48. package/assets/profiles/fast/README.md +24 -0
  49. package/assets/profiles/fast/profile.toml +59 -0
  50. package/assets/profiles/minimal/README.md +17 -0
  51. package/assets/profiles/minimal/addenda/.gitkeep +0 -0
  52. package/assets/profiles/minimal/profile.toml +8 -0
  53. package/assets/profiles/snappy/README.md +24 -0
  54. package/assets/profiles/snappy/addenda/10-race-as-question.md +6 -0
  55. package/assets/profiles/snappy/profile.toml +46 -0
  56. package/assets/prompts/companion-day-open.md +46 -0
  57. package/assets/prompts/companion-first-run.md +104 -0
  58. package/assets/prompts/companion.md +821 -0
  59. package/assets/prompts/conversation-system.md +117 -0
  60. package/assets/prompts/eod-sweep.md +120 -0
  61. package/assets/prompts/onboarding.md +113 -0
  62. package/assets/prompts/pass-common.md +52 -0
  63. package/assets/prompts/pass-quality-common.md +22 -0
  64. package/assets/prompts/round-first.md +874 -0
  65. package/assets/prompts/round-follow-up.md +991 -0
  66. package/assets/prompts/round-re-review.md +889 -0
  67. package/assets/prompts/round-recheck.md +196 -0
  68. package/assets/prompts/round-staleness.md +856 -0
  69. package/assets/schemas/review-result.v1.json +391 -0
  70. package/assets/schemas/scan-result.v1.json +421 -0
  71. package/assets/schemas/version.v1.json +57 -0
  72. package/assets/seed-manifest.json +19 -0
  73. package/assets/seeds/agents/pass-baseline.md +61 -0
  74. package/assets/seeds/agents/pass-contracts.md +30 -0
  75. package/assets/seeds/agents/pass-data-safety.md +54 -0
  76. package/assets/seeds/agents/pass-delivery.md +37 -0
  77. package/assets/seeds/agents/pass-prod-risk.md +24 -0
  78. package/assets/seeds/agents/pass-security.md +31 -0
  79. package/assets/seeds/agents/pass-statelessness.md +27 -0
  80. package/assets/seeds/agents/pass-ui.md +23 -0
  81. package/assets/seeds/agents/pass-validate.md +50 -0
  82. package/assets/seeds/prompts/conversation-system.md +117 -0
  83. package/assets/seeds/prompts/eod-sweep.md +120 -0
  84. package/assets/seeds/prompts/pass-common.md +52 -0
  85. package/dist/extensions/bash-guard.d.ts +467 -0
  86. package/dist/extensions/bash-guard.d.ts.map +1 -0
  87. package/dist/extensions/bash-guard.js +3058 -0
  88. package/dist/extensions/bash-guard.js.map +1 -0
  89. package/dist/extensions/finding-clusters.d.ts +33 -0
  90. package/dist/extensions/finding-clusters.d.ts.map +1 -0
  91. package/dist/extensions/finding-clusters.js +218 -0
  92. package/dist/extensions/finding-clusters.js.map +1 -0
  93. package/dist/extensions/ledger-pin.d.ts +76 -0
  94. package/dist/extensions/ledger-pin.d.ts.map +1 -0
  95. package/dist/extensions/ledger-pin.js +331 -0
  96. package/dist/extensions/ledger-pin.js.map +1 -0
  97. package/dist/extensions/lens.d.ts +43 -0
  98. package/dist/extensions/lens.d.ts.map +1 -0
  99. package/dist/extensions/lens.js +150 -0
  100. package/dist/extensions/lens.js.map +1 -0
  101. package/dist/extensions/pi-tool.d.ts +22 -0
  102. package/dist/extensions/pi-tool.d.ts.map +1 -0
  103. package/dist/extensions/pi-tool.js +20 -0
  104. package/dist/extensions/pi-tool.js.map +1 -0
  105. package/dist/extensions/quickreview.d.ts +21 -0
  106. package/dist/extensions/quickreview.d.ts.map +1 -0
  107. package/dist/extensions/quickreview.js +132 -0
  108. package/dist/extensions/quickreview.js.map +1 -0
  109. package/dist/src/anchors.d.ts +54 -0
  110. package/dist/src/anchors.d.ts.map +1 -0
  111. package/dist/src/anchors.js +127 -0
  112. package/dist/src/anchors.js.map +1 -0
  113. package/dist/src/assetroot.d.ts +16 -0
  114. package/dist/src/assetroot.d.ts.map +1 -0
  115. package/dist/src/assetroot.js +77 -0
  116. package/dist/src/assetroot.js.map +1 -0
  117. package/dist/src/authwatch.d.ts +61 -0
  118. package/dist/src/authwatch.d.ts.map +1 -0
  119. package/dist/src/authwatch.js +210 -0
  120. package/dist/src/authwatch.js.map +1 -0
  121. package/dist/src/budget.d.ts +15 -0
  122. package/dist/src/budget.d.ts.map +1 -0
  123. package/dist/src/budget.js +32 -0
  124. package/dist/src/budget.js.map +1 -0
  125. package/dist/src/casebudget.d.ts +3 -0
  126. package/dist/src/casebudget.d.ts.map +1 -0
  127. package/dist/src/casebudget.js +3 -0
  128. package/dist/src/casebudget.js.map +1 -0
  129. package/dist/src/cigate.d.ts +116 -0
  130. package/dist/src/cigate.d.ts.map +1 -0
  131. package/dist/src/cigate.js +176 -0
  132. package/dist/src/cigate.js.map +1 -0
  133. package/dist/src/codespan.d.ts +46 -0
  134. package/dist/src/codespan.d.ts.map +1 -0
  135. package/dist/src/codespan.js +75 -0
  136. package/dist/src/codespan.js.map +1 -0
  137. package/dist/src/contextpack.d.ts +56 -0
  138. package/dist/src/contextpack.d.ts.map +1 -0
  139. package/dist/src/contextpack.js +195 -0
  140. package/dist/src/contextpack.js.map +1 -0
  141. package/dist/src/contract.d.ts +8 -0
  142. package/dist/src/contract.d.ts.map +1 -0
  143. package/dist/src/contract.js +21 -0
  144. package/dist/src/contract.js.map +1 -0
  145. package/dist/src/coverage.d.ts +32 -0
  146. package/dist/src/coverage.d.ts.map +1 -0
  147. package/dist/src/coverage.js +85 -0
  148. package/dist/src/coverage.js.map +1 -0
  149. package/dist/src/datafence.d.ts +19 -0
  150. package/dist/src/datafence.d.ts.map +1 -0
  151. package/dist/src/datafence.js +60 -0
  152. package/dist/src/datafence.js.map +1 -0
  153. package/dist/src/dedup.d.ts +65 -0
  154. package/dist/src/dedup.d.ts.map +1 -0
  155. package/dist/src/dedup.js +459 -0
  156. package/dist/src/dedup.js.map +1 -0
  157. package/dist/src/depsources.d.ts +304 -0
  158. package/dist/src/depsources.d.ts.map +1 -0
  159. package/dist/src/depsources.js +3367 -0
  160. package/dist/src/depsources.js.map +1 -0
  161. package/dist/src/diffinput.d.ts +10 -0
  162. package/dist/src/diffinput.d.ts.map +1 -0
  163. package/dist/src/diffinput.js +172 -0
  164. package/dist/src/diffinput.js.map +1 -0
  165. package/dist/src/doubtwords.d.ts +10 -0
  166. package/dist/src/doubtwords.d.ts.map +1 -0
  167. package/dist/src/doubtwords.js +13 -0
  168. package/dist/src/doubtwords.js.map +1 -0
  169. package/dist/src/ecosystem.d.ts +148 -0
  170. package/dist/src/ecosystem.d.ts.map +1 -0
  171. package/dist/src/ecosystem.js +338 -0
  172. package/dist/src/ecosystem.js.map +1 -0
  173. package/dist/src/engine/agentdir.d.ts +5 -0
  174. package/dist/src/engine/agentdir.d.ts.map +1 -0
  175. package/dist/src/engine/agentdir.js +21 -0
  176. package/dist/src/engine/agentdir.js.map +1 -0
  177. package/dist/src/engine/auth.d.ts +214 -0
  178. package/dist/src/engine/auth.d.ts.map +1 -0
  179. package/dist/src/engine/auth.js +374 -0
  180. package/dist/src/engine/auth.js.map +1 -0
  181. package/dist/src/engine/budget.d.ts +60 -0
  182. package/dist/src/engine/budget.d.ts.map +1 -0
  183. package/dist/src/engine/budget.js +113 -0
  184. package/dist/src/engine/budget.js.map +1 -0
  185. package/dist/src/engine/capfd.d.ts +6 -0
  186. package/dist/src/engine/capfd.d.ts.map +1 -0
  187. package/dist/src/engine/capfd.js +21 -0
  188. package/dist/src/engine/capfd.js.map +1 -0
  189. package/dist/src/engine/caseout.d.ts +66 -0
  190. package/dist/src/engine/caseout.d.ts.map +1 -0
  191. package/dist/src/engine/caseout.js +107 -0
  192. package/dist/src/engine/caseout.js.map +1 -0
  193. package/dist/src/engine/context.d.ts +57 -0
  194. package/dist/src/engine/context.d.ts.map +1 -0
  195. package/dist/src/engine/context.js +212 -0
  196. package/dist/src/engine/context.js.map +1 -0
  197. package/dist/src/engine/envmap.d.ts +13 -0
  198. package/dist/src/engine/envmap.d.ts.map +1 -0
  199. package/dist/src/engine/envmap.js +377 -0
  200. package/dist/src/engine/envmap.js.map +1 -0
  201. package/dist/src/engine/extfiles.d.ts +7 -0
  202. package/dist/src/engine/extfiles.d.ts.map +1 -0
  203. package/dist/src/engine/extfiles.js +23 -0
  204. package/dist/src/engine/extfiles.js.map +1 -0
  205. package/dist/src/engine/keyroute.d.ts +21 -0
  206. package/dist/src/engine/keyroute.d.ts.map +1 -0
  207. package/dist/src/engine/keyroute.js +58 -0
  208. package/dist/src/engine/keyroute.js.map +1 -0
  209. package/dist/src/engine/lens/cache-group.d.ts +20 -0
  210. package/dist/src/engine/lens/cache-group.d.ts.map +1 -0
  211. package/dist/src/engine/lens/cache-group.js +31 -0
  212. package/dist/src/engine/lens/cache-group.js.map +1 -0
  213. package/dist/src/engine/lens/cache-run.d.ts +65 -0
  214. package/dist/src/engine/lens/cache-run.d.ts.map +1 -0
  215. package/dist/src/engine/lens/cache-run.js +159 -0
  216. package/dist/src/engine/lens/cache-run.js.map +1 -0
  217. package/dist/src/engine/lens/deadline.d.ts +54 -0
  218. package/dist/src/engine/lens/deadline.d.ts.map +1 -0
  219. package/dist/src/engine/lens/deadline.js +111 -0
  220. package/dist/src/engine/lens/deadline.js.map +1 -0
  221. package/dist/src/engine/lens/engine-tools.d.ts +13 -0
  222. package/dist/src/engine/lens/engine-tools.d.ts.map +1 -0
  223. package/dist/src/engine/lens/engine-tools.js +37 -0
  224. package/dist/src/engine/lens/engine-tools.js.map +1 -0
  225. package/dist/src/engine/lens/env.d.ts +23 -0
  226. package/dist/src/engine/lens/env.d.ts.map +1 -0
  227. package/dist/src/engine/lens/env.js +42 -0
  228. package/dist/src/engine/lens/env.js.map +1 -0
  229. package/dist/src/engine/lens/launch-plan.d.ts +63 -0
  230. package/dist/src/engine/lens/launch-plan.d.ts.map +1 -0
  231. package/dist/src/engine/lens/launch-plan.js +203 -0
  232. package/dist/src/engine/lens/launch-plan.js.map +1 -0
  233. package/dist/src/engine/lens/leaf-cache.d.ts +22 -0
  234. package/dist/src/engine/lens/leaf-cache.d.ts.map +1 -0
  235. package/dist/src/engine/lens/leaf-cache.js +115 -0
  236. package/dist/src/engine/lens/leaf-cache.js.map +1 -0
  237. package/dist/src/engine/lens/permits.d.ts +14 -0
  238. package/dist/src/engine/lens/permits.d.ts.map +1 -0
  239. package/dist/src/engine/lens/permits.js +18 -0
  240. package/dist/src/engine/lens/permits.js.map +1 -0
  241. package/dist/src/engine/lens/registry.d.ts +55 -0
  242. package/dist/src/engine/lens/registry.d.ts.map +1 -0
  243. package/dist/src/engine/lens/registry.js +140 -0
  244. package/dist/src/engine/lens/registry.js.map +1 -0
  245. package/dist/src/engine/lens/round-lens.d.ts +16 -0
  246. package/dist/src/engine/lens/round-lens.d.ts.map +1 -0
  247. package/dist/src/engine/lens/round-lens.js +46 -0
  248. package/dist/src/engine/lens/round-lens.js.map +1 -0
  249. package/dist/src/engine/lens/runlens.d.ts +103 -0
  250. package/dist/src/engine/lens/runlens.d.ts.map +1 -0
  251. package/dist/src/engine/lens/runlens.js +538 -0
  252. package/dist/src/engine/lens/runlens.js.map +1 -0
  253. package/dist/src/engine/lens/section.d.ts +19 -0
  254. package/dist/src/engine/lens/section.d.ts.map +1 -0
  255. package/dist/src/engine/lens/section.js +40 -0
  256. package/dist/src/engine/lens/section.js.map +1 -0
  257. package/dist/src/engine/lens/semaphore.d.ts +13 -0
  258. package/dist/src/engine/lens/semaphore.d.ts.map +1 -0
  259. package/dist/src/engine/lens/semaphore.js +44 -0
  260. package/dist/src/engine/lens/semaphore.js.map +1 -0
  261. package/dist/src/engine/lens/tool.d.ts +34 -0
  262. package/dist/src/engine/lens/tool.d.ts.map +1 -0
  263. package/dist/src/engine/lens/tool.js +345 -0
  264. package/dist/src/engine/lens/tool.js.map +1 -0
  265. package/dist/src/engine/lens/wave.d.ts +63 -0
  266. package/dist/src/engine/lens/wave.d.ts.map +1 -0
  267. package/dist/src/engine/lens/wave.js +95 -0
  268. package/dist/src/engine/lens/wave.js.map +1 -0
  269. package/dist/src/engine/livesessions.d.ts +21 -0
  270. package/dist/src/engine/livesessions.d.ts.map +1 -0
  271. package/dist/src/engine/livesessions.js +57 -0
  272. package/dist/src/engine/livesessions.js.map +1 -0
  273. package/dist/src/engine/livewire.d.ts +18 -0
  274. package/dist/src/engine/livewire.d.ts.map +1 -0
  275. package/dist/src/engine/livewire.js +31 -0
  276. package/dist/src/engine/livewire.js.map +1 -0
  277. package/dist/src/engine/openable.d.ts +37 -0
  278. package/dist/src/engine/openable.d.ts.map +1 -0
  279. package/dist/src/engine/openable.js +120 -0
  280. package/dist/src/engine/openable.js.map +1 -0
  281. package/dist/src/engine/pisdk.d.ts +235 -0
  282. package/dist/src/engine/pisdk.d.ts.map +1 -0
  283. package/dist/src/engine/pisdk.js +577 -0
  284. package/dist/src/engine/pisdk.js.map +1 -0
  285. package/dist/src/engine/port.d.ts +144 -0
  286. package/dist/src/engine/port.d.ts.map +1 -0
  287. package/dist/src/engine/port.js +16 -0
  288. package/dist/src/engine/port.js.map +1 -0
  289. package/dist/src/engine/prompts.d.ts +159 -0
  290. package/dist/src/engine/prompts.d.ts.map +1 -0
  291. package/dist/src/engine/prompts.js +339 -0
  292. package/dist/src/engine/prompts.js.map +1 -0
  293. package/dist/src/engine/render.d.ts +10 -0
  294. package/dist/src/engine/render.d.ts.map +1 -0
  295. package/dist/src/engine/render.js +23 -0
  296. package/dist/src/engine/render.js.map +1 -0
  297. package/dist/src/engine/reviewruntime.d.ts +13 -0
  298. package/dist/src/engine/reviewruntime.d.ts.map +1 -0
  299. package/dist/src/engine/reviewruntime.js +35 -0
  300. package/dist/src/engine/reviewruntime.js.map +1 -0
  301. package/dist/src/engine/reviewsdk.d.ts +75 -0
  302. package/dist/src/engine/reviewsdk.d.ts.map +1 -0
  303. package/dist/src/engine/reviewsdk.js +180 -0
  304. package/dist/src/engine/reviewsdk.js.map +1 -0
  305. package/dist/src/engine/round.d.ts +166 -0
  306. package/dist/src/engine/round.d.ts.map +1 -0
  307. package/dist/src/engine/round.js +543 -0
  308. package/dist/src/engine/round.js.map +1 -0
  309. package/dist/src/engine/roundagents.d.ts +17 -0
  310. package/dist/src/engine/roundagents.d.ts.map +1 -0
  311. package/dist/src/engine/roundagents.js +49 -0
  312. package/dist/src/engine/roundagents.js.map +1 -0
  313. package/dist/src/engine/roundevents.d.ts +110 -0
  314. package/dist/src/engine/roundevents.d.ts.map +1 -0
  315. package/dist/src/engine/roundevents.js +276 -0
  316. package/dist/src/engine/roundevents.js.map +1 -0
  317. package/dist/src/engine/roundsdk.d.ts +33 -0
  318. package/dist/src/engine/roundsdk.d.ts.map +1 -0
  319. package/dist/src/engine/roundsdk.js +76 -0
  320. package/dist/src/engine/roundsdk.js.map +1 -0
  321. package/dist/src/engine/sdkruntime.d.ts +23 -0
  322. package/dist/src/engine/sdkruntime.d.ts.map +1 -0
  323. package/dist/src/engine/sdkruntime.js +340 -0
  324. package/dist/src/engine/sdkruntime.js.map +1 -0
  325. package/dist/src/engine/select.d.ts +16 -0
  326. package/dist/src/engine/select.d.ts.map +1 -0
  327. package/dist/src/engine/select.js +32 -0
  328. package/dist/src/engine/select.js.map +1 -0
  329. package/dist/src/engine/sessionwrap.d.ts +4 -0
  330. package/dist/src/engine/sessionwrap.d.ts.map +1 -0
  331. package/dist/src/engine/sessionwrap.js +31 -0
  332. package/dist/src/engine/sessionwrap.js.map +1 -0
  333. package/dist/src/engine/toolfence.d.ts +90 -0
  334. package/dist/src/engine/toolfence.d.ts.map +1 -0
  335. package/dist/src/engine/toolfence.js +378 -0
  336. package/dist/src/engine/toolfence.js.map +1 -0
  337. package/dist/src/engine/tooluid.d.ts +128 -0
  338. package/dist/src/engine/tooluid.d.ts.map +1 -0
  339. package/dist/src/engine/tooluid.js +401 -0
  340. package/dist/src/engine/tooluid.js.map +1 -0
  341. package/dist/src/envstrip.d.ts +10 -0
  342. package/dist/src/envstrip.d.ts.map +1 -0
  343. package/dist/src/envstrip.js +15 -0
  344. package/dist/src/envstrip.js.map +1 -0
  345. package/dist/src/escalationprompt.d.ts +22 -0
  346. package/dist/src/escalationprompt.d.ts.map +1 -0
  347. package/dist/src/escalationprompt.js +54 -0
  348. package/dist/src/escalationprompt.js.map +1 -0
  349. package/dist/src/execfn.d.ts +29 -0
  350. package/dist/src/execfn.d.ts.map +1 -0
  351. package/dist/src/execfn.js +55 -0
  352. package/dist/src/execfn.js.map +1 -0
  353. package/dist/src/finding-chain.d.ts +40 -0
  354. package/dist/src/finding-chain.d.ts.map +1 -0
  355. package/dist/src/finding-chain.js +76 -0
  356. package/dist/src/finding-chain.js.map +1 -0
  357. package/dist/src/finding-row.d.ts +24 -0
  358. package/dist/src/finding-row.d.ts.map +1 -0
  359. package/dist/src/finding-row.js +26 -0
  360. package/dist/src/finding-row.js.map +1 -0
  361. package/dist/src/findingkey.d.ts +99 -0
  362. package/dist/src/findingkey.d.ts.map +1 -0
  363. package/dist/src/findingkey.js +210 -0
  364. package/dist/src/findingkey.js.map +1 -0
  365. package/dist/src/findingsrecord.d.ts +175 -0
  366. package/dist/src/findingsrecord.d.ts.map +1 -0
  367. package/dist/src/findingsrecord.js +410 -0
  368. package/dist/src/findingsrecord.js.map +1 -0
  369. package/dist/src/followup-mode.d.ts +4 -0
  370. package/dist/src/followup-mode.d.ts.map +1 -0
  371. package/dist/src/followup-mode.js +6 -0
  372. package/dist/src/followup-mode.js.map +1 -0
  373. package/dist/src/gate.d.ts +199 -0
  374. package/dist/src/gate.d.ts.map +1 -0
  375. package/dist/src/gate.js +315 -0
  376. package/dist/src/gate.js.map +1 -0
  377. package/dist/src/ghcred.d.ts +58 -0
  378. package/dist/src/ghcred.d.ts.map +1 -0
  379. package/dist/src/ghcred.js +139 -0
  380. package/dist/src/ghcred.js.map +1 -0
  381. package/dist/src/githubAuth.d.ts +70 -0
  382. package/dist/src/githubAuth.d.ts.map +1 -0
  383. package/dist/src/githubAuth.js +183 -0
  384. package/dist/src/githubAuth.js.map +1 -0
  385. package/dist/src/githubcore.d.ts +20 -0
  386. package/dist/src/githubcore.d.ts.map +1 -0
  387. package/dist/src/githubcore.js +20 -0
  388. package/dist/src/githubcore.js.map +1 -0
  389. package/dist/src/glob.d.ts +11 -0
  390. package/dist/src/glob.d.ts.map +1 -0
  391. package/dist/src/glob.js +69 -0
  392. package/dist/src/glob.js.map +1 -0
  393. package/dist/src/guards.d.ts +106 -0
  394. package/dist/src/guards.d.ts.map +1 -0
  395. package/dist/src/guards.js +365 -0
  396. package/dist/src/guards.js.map +1 -0
  397. package/dist/src/heartbeat.d.ts +29 -0
  398. package/dist/src/heartbeat.d.ts.map +1 -0
  399. package/dist/src/heartbeat.js +87 -0
  400. package/dist/src/heartbeat.js.map +1 -0
  401. package/dist/src/heuristics.d.ts +247 -0
  402. package/dist/src/heuristics.d.ts.map +1 -0
  403. package/dist/src/heuristics.js +927 -0
  404. package/dist/src/heuristics.js.map +1 -0
  405. package/dist/src/homes.d.ts +181 -0
  406. package/dist/src/homes.d.ts.map +1 -0
  407. package/dist/src/homes.js +242 -0
  408. package/dist/src/homes.js.map +1 -0
  409. package/dist/src/hunkheader.d.ts +11 -0
  410. package/dist/src/hunkheader.d.ts.map +1 -0
  411. package/dist/src/hunkheader.js +18 -0
  412. package/dist/src/hunkheader.js.map +1 -0
  413. package/dist/src/identity.d.ts +34 -0
  414. package/dist/src/identity.d.ts.map +1 -0
  415. package/dist/src/identity.js +67 -0
  416. package/dist/src/identity.js.map +1 -0
  417. package/dist/src/include.d.ts +435 -0
  418. package/dist/src/include.d.ts.map +1 -0
  419. package/dist/src/include.js +1692 -0
  420. package/dist/src/include.js.map +1 -0
  421. package/dist/src/launchvocab.d.ts +36 -0
  422. package/dist/src/launchvocab.d.ts.map +1 -0
  423. package/dist/src/launchvocab.js +59 -0
  424. package/dist/src/launchvocab.js.map +1 -0
  425. package/dist/src/ledgercarry.d.ts +24 -0
  426. package/dist/src/ledgercarry.d.ts.map +1 -0
  427. package/dist/src/ledgercarry.js +109 -0
  428. package/dist/src/ledgercarry.js.map +1 -0
  429. package/dist/src/lensids.d.ts +7 -0
  430. package/dist/src/lensids.d.ts.map +1 -0
  431. package/dist/src/lensids.js +53 -0
  432. package/dist/src/lensids.js.map +1 -0
  433. package/dist/src/lensplanning.d.ts +8 -0
  434. package/dist/src/lensplanning.d.ts.map +1 -0
  435. package/dist/src/lensplanning.js +126 -0
  436. package/dist/src/lensplanning.js.map +1 -0
  437. package/dist/src/lensresult.d.ts +94 -0
  438. package/dist/src/lensresult.d.ts.map +1 -0
  439. package/dist/src/lensresult.js +162 -0
  440. package/dist/src/lensresult.js.map +1 -0
  441. package/dist/src/lenstuning.d.ts +97 -0
  442. package/dist/src/lenstuning.d.ts.map +1 -0
  443. package/dist/src/lenstuning.js +326 -0
  444. package/dist/src/lenstuning.js.map +1 -0
  445. package/dist/src/lintconfig.d.ts +31 -0
  446. package/dist/src/lintconfig.d.ts.map +1 -0
  447. package/dist/src/lintconfig.js +543 -0
  448. package/dist/src/lintconfig.js.map +1 -0
  449. package/dist/src/live/events.d.ts +188 -0
  450. package/dist/src/live/events.d.ts.map +1 -0
  451. package/dist/src/live/events.js +136 -0
  452. package/dist/src/live/events.js.map +1 -0
  453. package/dist/src/live/writer.d.ts +54 -0
  454. package/dist/src/live/writer.d.ts.map +1 -0
  455. package/dist/src/live/writer.js +516 -0
  456. package/dist/src/live/writer.js.map +1 -0
  457. package/dist/src/localreview.d.ts +128 -0
  458. package/dist/src/localreview.d.ts.map +1 -0
  459. package/dist/src/localreview.js +426 -0
  460. package/dist/src/localreview.js.map +1 -0
  461. package/dist/src/loosenedtests.d.ts +13 -0
  462. package/dist/src/loosenedtests.d.ts.map +1 -0
  463. package/dist/src/loosenedtests.js +188 -0
  464. package/dist/src/loosenedtests.js.map +1 -0
  465. package/dist/src/memoryport.d.ts +264 -0
  466. package/dist/src/memoryport.d.ts.map +1 -0
  467. package/dist/src/memoryport.js +445 -0
  468. package/dist/src/memoryport.js.map +1 -0
  469. package/dist/src/migrations.d.ts +106 -0
  470. package/dist/src/migrations.d.ts.map +1 -0
  471. package/dist/src/migrations.js +373 -0
  472. package/dist/src/migrations.js.map +1 -0
  473. package/dist/src/modelroute.d.ts +38 -0
  474. package/dist/src/modelroute.d.ts.map +1 -0
  475. package/dist/src/modelroute.js +105 -0
  476. package/dist/src/modelroute.js.map +1 -0
  477. package/dist/src/oneshot.d.ts +12 -0
  478. package/dist/src/oneshot.d.ts.map +1 -0
  479. package/dist/src/oneshot.js +8 -0
  480. package/dist/src/oneshot.js.map +1 -0
  481. package/dist/src/packing.d.ts +11 -0
  482. package/dist/src/packing.d.ts.map +1 -0
  483. package/dist/src/packing.js +31 -0
  484. package/dist/src/packing.js.map +1 -0
  485. package/dist/src/passes.d.ts +16 -0
  486. package/dist/src/passes.d.ts.map +1 -0
  487. package/dist/src/passes.js +104 -0
  488. package/dist/src/passes.js.map +1 -0
  489. package/dist/src/passtasks.d.ts +68 -0
  490. package/dist/src/passtasks.d.ts.map +1 -0
  491. package/dist/src/passtasks.js +360 -0
  492. package/dist/src/passtasks.js.map +1 -0
  493. package/dist/src/pathinside.d.ts +5 -0
  494. package/dist/src/pathinside.d.ts.map +1 -0
  495. package/dist/src/pathinside.js +9 -0
  496. package/dist/src/pathinside.js.map +1 -0
  497. package/dist/src/pibuiltins.d.ts +36 -0
  498. package/dist/src/pibuiltins.d.ts.map +1 -0
  499. package/dist/src/pibuiltins.js +83 -0
  500. package/dist/src/pibuiltins.js.map +1 -0
  501. package/dist/src/plankey.d.ts +4 -0
  502. package/dist/src/plankey.d.ts.map +1 -0
  503. package/dist/src/plankey.js +10 -0
  504. package/dist/src/plankey.js.map +1 -0
  505. package/dist/src/planner.d.ts +375 -0
  506. package/dist/src/planner.d.ts.map +1 -0
  507. package/dist/src/planner.js +722 -0
  508. package/dist/src/planner.js.map +1 -0
  509. package/dist/src/plugin/args.d.ts +19 -0
  510. package/dist/src/plugin/args.d.ts.map +1 -0
  511. package/dist/src/plugin/args.js +107 -0
  512. package/dist/src/plugin/args.js.map +1 -0
  513. package/dist/src/plugin/index.d.ts +3 -0
  514. package/dist/src/plugin/index.d.ts.map +1 -0
  515. package/dist/src/plugin/index.js +14 -0
  516. package/dist/src/plugin/index.js.map +1 -0
  517. package/dist/src/plugin/login.d.ts +42 -0
  518. package/dist/src/plugin/login.d.ts.map +1 -0
  519. package/dist/src/plugin/login.js +82 -0
  520. package/dist/src/plugin/login.js.map +1 -0
  521. package/dist/src/plugin/review.d.ts +27 -0
  522. package/dist/src/plugin/review.d.ts.map +1 -0
  523. package/dist/src/plugin/review.js +302 -0
  524. package/dist/src/plugin/review.js.map +1 -0
  525. package/dist/src/plugin/runner.d.ts +6 -0
  526. package/dist/src/plugin/runner.d.ts.map +1 -0
  527. package/dist/src/plugin/runner.js +65 -0
  528. package/dist/src/plugin/runner.js.map +1 -0
  529. package/dist/src/plugin/scan.d.ts +79 -0
  530. package/dist/src/plugin/scan.d.ts.map +1 -0
  531. package/dist/src/plugin/scan.js +348 -0
  532. package/dist/src/plugin/scan.js.map +1 -0
  533. package/dist/src/plugin/session.d.ts +56 -0
  534. package/dist/src/plugin/session.d.ts.map +1 -0
  535. package/dist/src/plugin/session.js +2 -0
  536. package/dist/src/plugin/session.js.map +1 -0
  537. package/dist/src/plugin/setup.d.ts +19 -0
  538. package/dist/src/plugin/setup.d.ts.map +1 -0
  539. package/dist/src/plugin/setup.js +142 -0
  540. package/dist/src/plugin/setup.js.map +1 -0
  541. package/dist/src/plugin/versiongate.d.ts +26 -0
  542. package/dist/src/plugin/versiongate.d.ts.map +1 -0
  543. package/dist/src/plugin/versiongate.js +83 -0
  544. package/dist/src/plugin/versiongate.js.map +1 -0
  545. package/dist/src/postingkey.d.ts +8 -0
  546. package/dist/src/postingkey.d.ts.map +1 -0
  547. package/dist/src/postingkey.js +25 -0
  548. package/dist/src/postingkey.js.map +1 -0
  549. package/dist/src/postingpolicy.d.ts +108 -0
  550. package/dist/src/postingpolicy.d.ts.map +1 -0
  551. package/dist/src/postingpolicy.js +341 -0
  552. package/dist/src/postingpolicy.js.map +1 -0
  553. package/dist/src/pr-identity.d.ts +3 -0
  554. package/dist/src/pr-identity.d.ts.map +1 -0
  555. package/dist/src/pr-identity.js +9 -0
  556. package/dist/src/pr-identity.js.map +1 -0
  557. package/dist/src/prdelta.d.ts +181 -0
  558. package/dist/src/prdelta.d.ts.map +1 -0
  559. package/dist/src/prdelta.js +501 -0
  560. package/dist/src/prdelta.js.map +1 -0
  561. package/dist/src/pricing.d.ts +94 -0
  562. package/dist/src/pricing.d.ts.map +1 -0
  563. package/dist/src/pricing.js +209 -0
  564. package/dist/src/pricing.js.map +1 -0
  565. package/dist/src/priorfindings.d.ts +167 -0
  566. package/dist/src/priorfindings.d.ts.map +1 -0
  567. package/dist/src/priorfindings.js +445 -0
  568. package/dist/src/priorfindings.js.map +1 -0
  569. package/dist/src/priortasks.d.ts +31 -0
  570. package/dist/src/priortasks.d.ts.map +1 -0
  571. package/dist/src/priortasks.js +119 -0
  572. package/dist/src/priortasks.js.map +1 -0
  573. package/dist/src/profilelookup.d.ts +59 -0
  574. package/dist/src/profilelookup.d.ts.map +1 -0
  575. package/dist/src/profilelookup.js +98 -0
  576. package/dist/src/profilelookup.js.map +1 -0
  577. package/dist/src/profileoverrides.d.ts +91 -0
  578. package/dist/src/profileoverrides.d.ts.map +1 -0
  579. package/dist/src/profileoverrides.js +313 -0
  580. package/dist/src/profileoverrides.js.map +1 -0
  581. package/dist/src/profiles.d.ts +144 -0
  582. package/dist/src/profiles.d.ts.map +1 -0
  583. package/dist/src/profiles.js +604 -0
  584. package/dist/src/profiles.js.map +1 -0
  585. package/dist/src/promptdoc.d.ts +3 -0
  586. package/dist/src/promptdoc.d.ts.map +1 -0
  587. package/dist/src/promptdoc.js +18 -0
  588. package/dist/src/promptdoc.js.map +1 -0
  589. package/dist/src/prtarget.d.ts +70 -0
  590. package/dist/src/prtarget.d.ts.map +1 -0
  591. package/dist/src/prtarget.js +181 -0
  592. package/dist/src/prtarget.js.map +1 -0
  593. package/dist/src/recheckorder.d.ts +32 -0
  594. package/dist/src/recheckorder.d.ts.map +1 -0
  595. package/dist/src/recheckorder.js +5 -0
  596. package/dist/src/recheckorder.js.map +1 -0
  597. package/dist/src/reviewapi.d.ts +207 -0
  598. package/dist/src/reviewapi.d.ts.map +1 -0
  599. package/dist/src/reviewapi.js +939 -0
  600. package/dist/src/reviewapi.js.map +1 -0
  601. package/dist/src/reviewbotfindings.d.ts +33 -0
  602. package/dist/src/reviewbotfindings.d.ts.map +1 -0
  603. package/dist/src/reviewbotfindings.js +80 -0
  604. package/dist/src/reviewbotfindings.js.map +1 -0
  605. package/dist/src/reviewconfig.d.ts +753 -0
  606. package/dist/src/reviewconfig.d.ts.map +1 -0
  607. package/dist/src/reviewconfig.js +805 -0
  608. package/dist/src/reviewconfig.js.map +1 -0
  609. package/dist/src/reviewdelta.d.ts +51 -0
  610. package/dist/src/reviewdelta.d.ts.map +1 -0
  611. package/dist/src/reviewdelta.js +119 -0
  612. package/dist/src/reviewdelta.js.map +1 -0
  613. package/dist/src/reviewdest.d.ts +86 -0
  614. package/dist/src/reviewdest.d.ts.map +1 -0
  615. package/dist/src/reviewdest.js +142 -0
  616. package/dist/src/reviewdest.js.map +1 -0
  617. package/dist/src/reviewerstub.d.ts +12 -0
  618. package/dist/src/reviewerstub.d.ts.map +1 -0
  619. package/dist/src/reviewerstub.js +28 -0
  620. package/dist/src/reviewerstub.js.map +1 -0
  621. package/dist/src/reviewhost.d.ts +58 -0
  622. package/dist/src/reviewhost.d.ts.map +1 -0
  623. package/dist/src/reviewhost.js +135 -0
  624. package/dist/src/reviewhost.js.map +1 -0
  625. package/dist/src/reviewpost.d.ts +79 -0
  626. package/dist/src/reviewpost.d.ts.map +1 -0
  627. package/dist/src/reviewpost.js +233 -0
  628. package/dist/src/reviewpost.js.map +1 -0
  629. package/dist/src/reviewrender.d.ts +154 -0
  630. package/dist/src/reviewrender.d.ts.map +1 -0
  631. package/dist/src/reviewrender.js +480 -0
  632. package/dist/src/reviewrender.js.map +1 -0
  633. package/dist/src/reviewstate.d.ts +62 -0
  634. package/dist/src/reviewstate.d.ts.map +1 -0
  635. package/dist/src/reviewstate.js +167 -0
  636. package/dist/src/reviewstate.js.map +1 -0
  637. package/dist/src/reviewstore.d.ts +17 -0
  638. package/dist/src/reviewstore.d.ts.map +1 -0
  639. package/dist/src/reviewstore.js +105 -0
  640. package/dist/src/reviewstore.js.map +1 -0
  641. package/dist/src/round-progress.d.ts +120 -0
  642. package/dist/src/round-progress.d.ts.map +1 -0
  643. package/dist/src/round-progress.js +172 -0
  644. package/dist/src/round-progress.js.map +1 -0
  645. package/dist/src/round-stage-deadlines.d.ts +12 -0
  646. package/dist/src/round-stage-deadlines.d.ts.map +1 -0
  647. package/dist/src/round-stage-deadlines.js +10 -0
  648. package/dist/src/round-stage-deadlines.js.map +1 -0
  649. package/dist/src/session-command.d.ts +19 -0
  650. package/dist/src/session-command.d.ts.map +1 -0
  651. package/dist/src/session-command.js +20 -0
  652. package/dist/src/session-command.js.map +1 -0
  653. package/dist/src/settledread.d.ts +61 -0
  654. package/dist/src/settledread.d.ts.map +1 -0
  655. package/dist/src/settledread.js +135 -0
  656. package/dist/src/settledread.js.map +1 -0
  657. package/dist/src/severity.d.ts +167 -0
  658. package/dist/src/severity.d.ts.map +1 -0
  659. package/dist/src/severity.js +364 -0
  660. package/dist/src/severity.js.map +1 -0
  661. package/dist/src/severityrank.d.ts +8 -0
  662. package/dist/src/severityrank.d.ts.map +1 -0
  663. package/dist/src/severityrank.js +16 -0
  664. package/dist/src/severityrank.js.map +1 -0
  665. package/dist/src/standing-review.d.ts +45 -0
  666. package/dist/src/standing-review.d.ts.map +1 -0
  667. package/dist/src/standing-review.js +43 -0
  668. package/dist/src/standing-review.js.map +1 -0
  669. package/dist/src/storerows.d.ts +225 -0
  670. package/dist/src/storerows.d.ts.map +1 -0
  671. package/dist/src/storerows.js +7 -0
  672. package/dist/src/storerows.js.map +1 -0
  673. package/dist/src/styleguide.d.ts +25 -0
  674. package/dist/src/styleguide.d.ts.map +1 -0
  675. package/dist/src/styleguide.js +272 -0
  676. package/dist/src/styleguide.js.map +1 -0
  677. package/dist/src/sweepstatus.d.ts +42 -0
  678. package/dist/src/sweepstatus.d.ts.map +1 -0
  679. package/dist/src/sweepstatus.js +97 -0
  680. package/dist/src/sweepstatus.js.map +1 -0
  681. package/dist/src/templates.d.ts +243 -0
  682. package/dist/src/templates.d.ts.map +1 -0
  683. package/dist/src/templates.js +847 -0
  684. package/dist/src/templates.js.map +1 -0
  685. package/dist/src/types.d.ts +639 -0
  686. package/dist/src/types.d.ts.map +1 -0
  687. package/dist/src/types.js +90 -0
  688. package/dist/src/types.js.map +1 -0
  689. package/dist/src/unifieddiff.d.ts +22 -0
  690. package/dist/src/unifieddiff.d.ts.map +1 -0
  691. package/dist/src/unifieddiff.js +176 -0
  692. package/dist/src/unifieddiff.js.map +1 -0
  693. package/dist/src/yieldloop.d.ts +2 -0
  694. package/dist/src/yieldloop.d.ts.map +1 -0
  695. package/dist/src/yieldloop.js +14 -0
  696. package/dist/src/yieldloop.js.map +1 -0
  697. package/package.json +60 -4
@@ -0,0 +1,722 @@
1
+ import { REVIEW_DEFAULTS } from "./reviewconfig.js";
2
+ import { coverageEligible } from "./coverage.js";
3
+ import { DJANGO_ECOSYSTEM } from "./ecosystem.js";
4
+ import { promptTargetsFor } from "./escalationprompt.js";
5
+ import { deltaFollowUpEnabled } from "./followup-mode.js";
6
+ import { INTENT_PASS, passTier, selectLenses, selectSubLenses, SWEEP_PASS, sweepGroups, isLightSweepFile, baselineGroups, baselineSplitLines, BEHAVIOUR_DELTA_PASS, behaviourDeltaGroups, CODE_FILE_RE, TESTS_PASS, STYLE_PASS, LINT_CONFORMANCE_PASS, selectQualityLenses, QUALITY_PASSES, qualityReason, } from "./heuristics.js";
7
+ import { VALIDATE_PASS } from "./include.js";
8
+ import { LENS_PLANNING } from "./lensplanning.js";
9
+ import { flooredTier, lensEnabled } from "./lenstuning.js";
10
+ import { lintersForFiles } from "./lintconfig.js";
11
+ import { detectLoosenedAssertions, loosenedReason } from "./loosenedtests.js";
12
+ import { ALL_PASSES } from "./passes.js";
13
+ import { isDefaultPosting } from "./postingpolicy.js";
14
+ import { roundPostingKey } from "./postingkey.js";
15
+ import { deltaAsPrFiles } from "./prdelta.js";
16
+ import { assignPriorFindings } from "./priortasks.js";
17
+ import { PASS_TIER_ORDER } from "./types.js";
18
+ /** A plan's lens names, each once, in plan order — the compatibility list
19
+ * the rounds table, the event log and every order carry (a lens with several
20
+ * rows, the sweep, once). */
21
+ export function lensesOf(plan) {
22
+ return [...new Set(plan.map((p) => p.lens))];
23
+ }
24
+ /** The head a round reviews: the prepared tree's, else the PR row's (a
25
+ * caller with no worktree seam). The one rule the round row, the posting key
26
+ * and the prompt all name their head by. */
27
+ export function reviewedHeadOf(tree, row) {
28
+ return tree?.head_sha || row.head_sha;
29
+ }
30
+ /** raisable_to lists the higher rungs only — a session may raise a pass, never
31
+ * lower it. */
32
+ function raisableFrom(lens, tier) {
33
+ return PASS_TIER_ORDER.slice(PASS_TIER_ORDER.indexOf(tier) + 1).map((t) => `${lens}--${t}`);
34
+ }
35
+ /**
36
+ * The tier the round's validator runs at: its own tier, the configured
37
+ * `validate_tier` under the profile's `min_tier` for it, whatever tier or
38
+ * effort any lens runs at. It is never raised to match a lens: a finding the
39
+ * validator cannot stand behind is kept as `doubted` in the findings record
40
+ * (never posted, shown in the TUI), not discarded, so a cheaper validator
41
+ * cannot make a stronger lens's finding vanish. Lens tiers are deliberately
42
+ * not an input.
43
+ */
44
+ export function validatorTier(cfg) {
45
+ return flooredTier(cfg.lenses, VALIDATE_PASS, cfg.models.validate_tier);
46
+ }
47
+ /**
48
+ * The tier a lens ADDED by the session runs at (the round templates' add
49
+ * rule): a risk pass exists only as `sol-high`; every other lens at `sol-med`,
50
+ * or at the profile's `min_tier` for it when that is higher.
51
+ */
52
+ export function addTierOf(cfg, lens) {
53
+ return cfg.models.risk_passes.includes(lens)
54
+ ? "sol-high"
55
+ : flooredTier(cfg.lenses, lens, "sol-med");
56
+ }
57
+ /** Deterministic per-round pass plan (agent = `${lens}--${tier}`):
58
+ * - risk passes are always "sol-high", single variant, not raisable;
59
+ * - pass-validate runs at validatorTier() — its own configured tier, never
60
+ * raised to match a lens — is not raisable, and is always last;
61
+ * - every other selected lens gets the passTier() tier and may be raised to
62
+ * any higher tier's variant (ascending order).
63
+ * addable_lenses = every known pass not already in the plan.
64
+ * The rows come back in launch order, slowest first (`slowestFirst`).
65
+ *
66
+ * The profile's per-lens tuning (`cfg.lenses`) wins over all of
67
+ * that: a `min_tier` floors the lens's row (and so its `raisable_to`) and the
68
+ * sweep rows; `enabled = false` removes a lens from the plan AND the addable
69
+ * list whatever selected it — the validator included, when the round
70
+ * has no validator row at all; `enabled = true` on a lever-gated lens switches
71
+ * it on whatever its `[review]` lever says. */
72
+ export function buildPassPlan(cfg, files, intent,
73
+ /** Whose tier-forcing gate applies. Default Django; `none` never forces
74
+ * sol-med off a migrations path. */
75
+ ecosystem = DJANGO_ECOSYSTEM,
76
+ /** Profile lens-heuristics extension; absent ⇒ generic core. */
77
+ heuristics,
78
+ /** The repo's written style guide references (packages/pi-plugin/src/styleguide.ts); empty or
79
+ * absent ⇒ the style lens only on the profile's guide, if any. */
80
+ styleGuide = [],
81
+ /** The linters and formatters a CI job of the repo runs (packages/pi-plugin/src/lintconfig.ts);
82
+ * empty or absent ⇒ no lint-conformance row. */
83
+ ciLinters = [],
84
+ /** `tierFiles` — the files the round's default TIER is chosen from, when
85
+ * the plan is built over fewer files than the PR (a follow-up round plans
86
+ * from the delta, but a small fix push keeps the PR's tier and its
87
+ * migration floor). Absent ⇒ `files`. */
88
+ opts = {}) {
89
+ const tierBasis = opts.tierFiles ?? files;
90
+ const defaultTier = passTier(tierBasis, {
91
+ migrationGate: ecosystem.migrationGate(tierBasis),
92
+ smallDiffLines: cfg.models.small_diff_lines,
93
+ });
94
+ const risk = new Set(cfg.models.risk_passes);
95
+ // The profile's switch for one lens — explicit `enabled` wins,
96
+ // otherwise the `[review]` lever that gates it (true for an ungated lens).
97
+ const on = (lens, lever = true) => lensEnabled(cfg.lenses, lens, lever);
98
+ // The plan explains why each lens was chosen — the path-shaped lenses
99
+ // included, not only sub-lenses.
100
+ const reasons0 = new Map();
101
+ const selected0 = selectLenses(files, intent, heuristics, {
102
+ intentMinWords: cfg.review.intent_min_words,
103
+ placementMinCodeFiles: cfg.review.placement_min_code_files,
104
+ placementMinNewFileLines: cfg.review.placement_min_new_file_lines,
105
+ }, reasons0);
106
+ // Sub-lenses ride after the path-selected lenses, each with the reason its
107
+ // trigger fired (`[review] sublenses`).
108
+ const sub = selectSubLenses(files, intent).filter((s) => on(s.lens, cfg.review.sublenses) && !selected0.includes(s.lens));
109
+ const whyOf = new Map([
110
+ ...reasons0,
111
+ ...sub.map((s) => [s.lens, s.why]),
112
+ ]);
113
+ // Existing tests are consumers of every code change, and the PR's own
114
+ // tests are claims about the code — one lens reads both.
115
+ // The loosened-test hint: weakened assertions
116
+ // found deterministically in the PR's test files are handed to the lens.
117
+ const loosened = cfg.review.loosened_test_hint ? detectLoosenedAssertions(files) : [];
118
+ const tests = on(TESTS_PASS, cfg.review.tests_lens) &&
119
+ (files.some((f) => CODE_FILE_RE.test(f.filename)) || loosened.length > 0)
120
+ ? [TESTS_PASS]
121
+ : [];
122
+ // The code-quality lenses: maintainability, duplication, abstraction — never
123
+ // style, which rides only on the repo's own written guide.
124
+ const quality = selectQualityLenses(files, cfg.review.quality_min_added_lines).filter((l) => on(l, cfg.review.quality_lenses) && !selected0.includes(l));
125
+ if (tests.length)
126
+ whyOf.set(TESTS_PASS, "the PR changes code: existing tests are its consumers, and its own tests are claims" +
127
+ (loosened.length ? `; and ${loosenedReason(loosened)}` : ""));
128
+ for (const l of quality)
129
+ whyOf.set(l, qualityReason(files, cfg.review.quality_min_added_lines));
130
+ // A guide the repo writes wins; the profile's drafted guide is
131
+ // the standard only when the repo writes none.
132
+ const profileGuide = cfg.lenses?.[STYLE_PASS]?.guide;
133
+ const style = on(STYLE_PASS, cfg.review.style_lens) &&
134
+ (styleGuide.length > 0 || profileGuide !== undefined) &&
135
+ files.some((f) => CODE_FILE_RE.test(f.filename))
136
+ ? [STYLE_PASS]
137
+ : [];
138
+ if (style.length)
139
+ whyOf.set(STYLE_PASS, styleGuide.length > 0
140
+ ? `the repo's written style guide: ${styleGuide.join(", ")}`
141
+ : `this repo's profile style guide (\`${profileGuide.file}\`, in your instructions) — the repo writes none of its own`);
142
+ // Lint conformance only where a CI job runs a linter whose
143
+ // rules cover a changed file — the plan names the tools and their CI files.
144
+ const coveredLinters = lintersForFiles(ciLinters, files.filter((f) => f.status !== "removed").map((f) => f.filename));
145
+ const lint = on(LINT_CONFORMANCE_PASS, cfg.review.lint_conformance) && coveredLinters.length > 0
146
+ ? [LINT_CONFORMANCE_PASS]
147
+ : [];
148
+ if (lint.length)
149
+ whyOf.set(LINT_CONFORMANCE_PASS, `CI runs ${coveredLinters
150
+ .map((l) => `${l.tool} (${l.ci.join(", ")}${l.configs.length ? `; config ${l.configs.join(", ")}` : ""})`)
151
+ .join("; ")} on the changed files`);
152
+ // `[review] skip_lenses` (cost tuning): a listed lens is neither planned
153
+ // nor addable. pass-validate is refused at config parse, and is re-appended
154
+ // unconditionally here besides.
155
+ const skip = new Set((cfg.review.skip_lenses ?? []).filter((l) => l !== VALIDATE_PASS));
156
+ // `enabled = false` is the last word on every lens, whatever selected it —
157
+ // a profile-level subtraction, separate from the ADD-only heuristics.
158
+ const lenses = [
159
+ ...[...selected0, ...sub.map((s) => s.lens), ...tests, ...quality, ...style, ...lint].filter((l) => !skip.has(l)),
160
+ VALIDATE_PASS,
161
+ ].filter((l) => on(l));
162
+ // `[models.pass_tiers]`: a pinned lens runs at its pinned tier on every PR,
163
+ // whatever the diff size, and is not raisable (config refuses a pin on a
164
+ // risk pass or on pass-validate). A profile `min_tier` still floors it.
165
+ const pins = cfg.models.pass_tiers ?? {};
166
+ // pass-intent starts at terra-med whatever the round's default:
167
+ // reading comprehension over two short texts, not a judgment over production
168
+ // risk. It is NOT pinned — the session may raise it like any other lens.
169
+ // A profile `min_tier` floors whatever this picks (it never lowers one).
170
+ const tierOf = (lens) => flooredTier(cfg.lenses, lens, risk.has(lens)
171
+ ? "sol-high"
172
+ : (pins[lens] ?? (lens === INTENT_PASS ? "terra-med" : defaultTier)));
173
+ // The sweep's rows run at the cheapest tier unless pinned (`[models.pass_tiers]`)
174
+ // or floored by the profile.
175
+ const sweepOn = on(SWEEP_PASS, cfg.review.sweep) && !skip.has(SWEEP_PASS);
176
+ const sweepTier = flooredTier(cfg.lenses, SWEEP_PASS, pins[SWEEP_PASS] ?? "terra-med");
177
+ // The validator runs at its own tier — never raised to match a lens,
178
+ // pinned or not.
179
+ const validate = validatorTier(cfg);
180
+ const pass_plan = lenses.map((lens) => {
181
+ const pinned = lens === VALIDATE_PASS || risk.has(lens) || pins[lens] !== undefined;
182
+ const tier = lens === VALIDATE_PASS ? validate : tierOf(lens);
183
+ // Every planned lens says why: the signal that fired, else the lens's
184
+ // documented planning rule.
185
+ const why = whyOf.get(lens) ?? (lens !== VALIDATE_PASS ? LENS_PLANNING[lens]?.when : undefined);
186
+ return {
187
+ lens,
188
+ agent: `${lens}--${tier}`,
189
+ tier,
190
+ raisable_to: pinned ? [] : raisableFrom(lens, tier),
191
+ ...(why !== undefined ? { why } : {}),
192
+ ...(lens === BASELINE_PASS || risk.has(lens) ? { required: true } : {}),
193
+ };
194
+ });
195
+ // On a very large change pass-baseline — one row, and the round's
196
+ // critical path once the fan-out launches in one turn — is planned as 2–3
197
+ // rows, each STARTING from one group of the change's files; every row keeps
198
+ // the whole PR as its charter (`[review] baseline_split_lines`, 0 = never).
199
+ // At or under the threshold nothing here runs.
200
+ const baselineAt = pass_plan.findIndex((p) => p.lens === BASELINE_PASS);
201
+ const baselineSplit = baselineAt < 0
202
+ ? []
203
+ : baselineGroups(files, cfg.review.baseline_split_lines ?? REVIEW_DEFAULTS.baseline_split_lines);
204
+ if (baselineSplit.length > 1) {
205
+ const row = pass_plan[baselineAt];
206
+ const lines = baselineSplitLines(files);
207
+ pass_plan.splice(baselineAt, 1, ...baselineSplit.map((focus, i) => ({
208
+ ...row,
209
+ why: `pass-baseline split ${i + 1} of ${baselineSplit.length}: the change is ${lines} changed lines, over [review] baseline_split_lines (${cfg.review.baseline_split_lines}) — this row starts from its files; its charter stays whole`,
210
+ focus,
211
+ })));
212
+ }
213
+ // The sweep (`[review] sweep`): one row per group of
214
+ // changed files, at the cheapest tier — its job is attention, line by line,
215
+ // not deep reasoning. Appended: `slowestFirst` below puts the validator
216
+ // last whatever is appended after it.
217
+ let sweep_unswept = [];
218
+ if (sweepOn) {
219
+ const { groups, unswept } = sweepGroups(files, cfg.review.sweep_max_groups, cfg.review.sweep_group_files, cfg.review.sweep_group_lines, cfg.review.sweep_wide_files);
220
+ sweep_unswept = unswept;
221
+ // `[review] sweep_light_tier`: a row holding no production
222
+ // code — tests, prose, config/data only — runs at the light tier when it
223
+ // is below the sweep's own (the profile's floor still applies).
224
+ const light = cfg.review.sweep_light_tier
225
+ ? flooredTier(cfg.lenses, SWEEP_PASS, cfg.review.sweep_light_tier)
226
+ : undefined;
227
+ const lightApplies = light !== undefined && PASS_TIER_ORDER.indexOf(light) < PASS_TIER_ORDER.indexOf(sweepTier);
228
+ const rows = groups.map((focus) => {
229
+ const isLight = lightApplies && focus.every(isLightSweepFile);
230
+ const tier = isLight ? light : sweepTier;
231
+ return {
232
+ lens: SWEEP_PASS,
233
+ agent: `${SWEEP_PASS}--${tier}`,
234
+ tier,
235
+ raisable_to: pins[SWEEP_PASS] !== undefined && !isLight ? [] : raisableFrom(SWEEP_PASS, tier),
236
+ why: `every changed line of ${focus.length === 1 ? focus[0] : `${focus.length} changed files`}, read one by one${isLight ? " (tests, prose or config only: the light tier, [review] sweep_light_tier)" : ""}`,
237
+ focus,
238
+ };
239
+ });
240
+ pass_plan.push(...rows);
241
+ }
242
+ // The behaviour-delta lens: one row per group of files the
243
+ // PR modifies or deletes code in, at the round's tier — comparing base and
244
+ // head is reasoning, not attention. Appended, as the sweep's rows are.
245
+ let behaviour_unread = [];
246
+ if (on(BEHAVIOUR_DELTA_PASS, cfg.review.behaviour_delta) && !skip.has(BEHAVIOUR_DELTA_PASS)) {
247
+ const { groups, unread } = behaviourDeltaGroups(files, cfg.review.behaviour_delta_max_groups, cfg.review.sweep_group_lines);
248
+ const tier = tierOf(BEHAVIOUR_DELTA_PASS);
249
+ const rows = groups.map((focus) => ({
250
+ lens: BEHAVIOUR_DELTA_PASS,
251
+ agent: `${BEHAVIOUR_DELTA_PASS}--${tier}`,
252
+ tier,
253
+ raisable_to: pins[BEHAVIOUR_DELTA_PASS] !== undefined ? [] : raisableFrom(BEHAVIOUR_DELTA_PASS, tier),
254
+ why: `base behaviour is at risk in ${focus.length === 1 ? focus[0] : `${focus.length} files`}: removed or replaced guards, conditions, calls, returns or values, or existing code wrapped in a new branch`,
255
+ focus,
256
+ }));
257
+ pass_plan.push(...rows);
258
+ behaviour_unread = unread;
259
+ }
260
+ const selected = new Set(pass_plan.map((p) => p.lens));
261
+ const addable_lenses = [...new Set([...ALL_PASSES, ...cfg.models.risk_passes])].filter((l) => !selected.has(l) && on(l) && !skip.has(l));
262
+ return {
263
+ pass_plan: slowestFirst(pass_plan, files, risk),
264
+ addable_lenses,
265
+ sweep_unswept,
266
+ ...(behaviour_unread.length > 0 ? { behaviour_unread } : {}),
267
+ };
268
+ }
269
+ /** The lenses `slowestFirst` launches last within their tier: conditional
270
+ * lenses that read the change for one narrow concern. */
271
+ const CHEAP_LAST_PASSES = new Set([
272
+ INTENT_PASS,
273
+ ...QUALITY_PASSES,
274
+ STYLE_PASS,
275
+ LINT_CONFORMANCE_PASS,
276
+ ]);
277
+ /**
278
+ * The plan's rows in LAUNCH order — the expected-slowest first.
279
+ *
280
+ * The session launches a turn's rows in table order, and the lens runner
281
+ * (packages/pi-plugin/src/engine/lens/runlens.ts) runs them under a process-wide cap in that order,
282
+ * so a 15–27 row plan runs in waves: a slow row listed late starts in the
283
+ * last wave and sets the round's critical path (typically pass-baseline,
284
+ * sol-high sweep and behaviour-delta rows). The order:
285
+ * pass-baseline; then by tier, highest first; within a tier the risk passes,
286
+ * then the focused rows (behaviour-delta, then sweep) by the changed lines
287
+ * their focus covers, larger first, then every other lens, then the cheap
288
+ * conditional lenses (`CHEAP_LAST_PASSES`); pass-validate stays last. Ties
289
+ * keep their planned order (a stable sort).
290
+ *
291
+ * Only the ORDER moves — the same rows, each byte-identical. Every consumer
292
+ * that indexes rows (the task files, `lenses`, lesson rows, the recorded
293
+ * pass_plan) reads this one array, so they agree. Exported for
294
+ * `planFollowUp`, which splices a carried row into an already-ordered plan.
295
+ */
296
+ export function slowestFirst(rows, files, risk) {
297
+ const lines = new Map(files.map((f) => [f.filename, (f.additions ?? 0) + (f.deletions ?? 0)]));
298
+ const weight = (p) => (p.focus ?? []).reduce((n, f) => n + (lines.get(f) ?? 0), 0);
299
+ const cls = (p) => risk.has(p.lens)
300
+ ? 0
301
+ : p.lens === BEHAVIOUR_DELTA_PASS
302
+ ? 1
303
+ : p.lens === SWEEP_PASS
304
+ ? 2
305
+ : CHEAP_LAST_PASSES.has(p.lens)
306
+ ? 4
307
+ : 3;
308
+ const key = (p) => [
309
+ p.lens === VALIDATE_PASS ? 1 : 0,
310
+ p.lens === BASELINE_PASS ? 0 : 1,
311
+ -PASS_TIER_ORDER.indexOf(p.tier),
312
+ cls(p),
313
+ -weight(p),
314
+ ];
315
+ const keyed = rows.map((p, i) => ({ p, i, k: key(p) }));
316
+ keyed.sort((a, b) => {
317
+ for (let j = 0; j < a.k.length; j++)
318
+ if (a.k[j] !== b.k[j])
319
+ return a.k[j] - b.k[j];
320
+ return a.i - b.i;
321
+ });
322
+ return keyed.map((e) => e.p);
323
+ }
324
+ /**
325
+ * Decide whether a non-first round is a FOLLOW-UP round
326
+ * (docs/follow-up-rounds.md), and plan it. Total: any doubt — the knob, no
327
+ * reviewed-head mark, no git seam, a delta git could not compute, a delta
328
+ * above `follow_up_max_delta_ratio` of the PR's diff lines, a delta plan
329
+ * without pass-baseline — answers `{full: reason}`, and the caller runs a
330
+ * full re-review.
331
+ *
332
+ * The plan is built over the DELTA's files with the intent text arms off
333
+ * (the title and body did not change since the last review), its tier chosen
334
+ * from the WHOLE PR. The sweep is owed as `followUpSweepOwed` decides (the
335
+ * standing verdict not APPROVE and no full look since the first round, or a
336
+ * large enough post-approval delta); its plan is
337
+ * the whole PR's full plan, exactly as a full round would run it.
338
+ */
339
+ export async function decideFollowUp(deps, args) {
340
+ const { cfg, history } = deps;
341
+ const full = (reason, detail) => ({ kind: "full", reason, ...(detail ? { detail } : {}) });
342
+ if (!deltaFollowUpEnabled(cfg))
343
+ return full("follow_up_full");
344
+ if (!args.markHead)
345
+ return full("no-reviewed-head");
346
+ if (!args.tree || !args.tree.merge_base || !deps.prOwnedDelta)
347
+ return full("no-adapter");
348
+ // The merge base the reviewed head's round recorded (the latest live round
349
+ // dispatched to that head, a verdicted one first): a base force-pushed
350
+ // since then is caught by `prOwnedDelta` as `base-rewound`. Unknown (a
351
+ // round recorded before the column existed) ⇒ only the base-tip check runs.
352
+ const atMark = history
353
+ .roundsFor(args.pr)
354
+ .filter((r) => r.backfilled === 0 && r.head_sha === args.markHead && r.merge_base)
355
+ .sort((a, b) => Number(b.verdict !== null) - Number(a.verdict !== null) || b.round_no - a.round_no);
356
+ const fromMergeBase = atMark[0]?.merge_base ?? undefined;
357
+ let delta;
358
+ try {
359
+ delta = await deps.prOwnedDelta({
360
+ pr: args.pr,
361
+ from: args.markHead,
362
+ to: args.tree.head_sha,
363
+ mergeBase: args.tree.merge_base,
364
+ ...(args.tree.base_sha ? { baseSha: args.tree.base_sha } : {}),
365
+ ...(fromMergeBase ? { fromMergeBase } : {}),
366
+ });
367
+ }
368
+ catch (err) {
369
+ return full("delta-threw", { error: err instanceof Error ? err.message : String(err) });
370
+ }
371
+ if (!delta.ok)
372
+ return full(delta.reason, delta.detail ? { detail: delta.detail } : undefined);
373
+ return planFollowUp(cfg, deps.heuristics, {
374
+ delta,
375
+ fromSha: args.markHead,
376
+ files: args.files,
377
+ fullPlan: args.fullPlan,
378
+ ecosystem: args.ecosystem,
379
+ styleGuide: args.styleGuide,
380
+ ciLinters: args.ciLinters,
381
+ sweepOwed: (deltaLines) => followUpSweepOwed(cfg, {
382
+ standing: args.standing,
383
+ approvalWithheld: args.approvalWithheld === true,
384
+ fullLookSinceFirst: () => history.fullLookSinceFirst(args.pr),
385
+ deltaLines,
386
+ }),
387
+ });
388
+ }
389
+ /**
390
+ * Whether a follow-up round owes the pre-approval sweep, the
391
+ * `[review] follow_up_sweep` knob aside. Before a posted approval (a withheld
392
+ * one never reached GitHub, so it counts as none): owed until a full look has
393
+ * happened since the first round. After a posted approval: owed only when the
394
+ * change since it reaches `follow_up_post_approval_sweep_lines` — a large push
395
+ * onto an approved PR is where live re-reviews found blockers outside the
396
+ * change; a small one stays delta-only.
397
+ */
398
+ export function followUpSweepOwed(cfg, args) {
399
+ if (args.standing === "APPROVE" && !args.approvalWithheld) {
400
+ const floor = cfg.review.follow_up_post_approval_sweep_lines ??
401
+ REVIEW_DEFAULTS.follow_up_post_approval_sweep_lines;
402
+ return floor > 0 && args.deltaLines >= floor;
403
+ }
404
+ return !args.fullLookSinceFirst();
405
+ }
406
+ /**
407
+ * The PURE half of `decideFollowUp`: given a computed delta, plan
408
+ * the follow-up round — or answer `{full: reason}`. The daemon reaches it
409
+ * through `decideFollowUp`; the bench's follow-up replay (src/bench/
410
+ * followup.ts) calls it directly with a delta computed by the same
411
+ * `WorktreeManager.prOwnedDelta` over its replay tree, so the two never
412
+ * disagree about what a follow-up round plans.
413
+ *
414
+ * `sweepOwed` is consulted only when the `[review] follow_up_sweep` knob is on
415
+ * and the plan stands: the daemon's answer reads the standing verdict and the
416
+ * store; the bench's is the recorded case's.
417
+ */
418
+ export function planFollowUp(cfg, heuristics, args) {
419
+ const { delta } = args;
420
+ const prLines = args.files.reduce((n, f) => n + (f.additions ?? 0) + (f.deletions ?? 0), 0);
421
+ const ratio = cfg.review.follow_up_max_delta_ratio ?? REVIEW_DEFAULTS.follow_up_max_delta_ratio;
422
+ if (delta.lines > ratio * prLines)
423
+ return {
424
+ kind: "full",
425
+ reason: "delta-too-large",
426
+ detail: { delta_lines: delta.lines, pr_lines: prLines, ratio },
427
+ };
428
+ const deltaFiles = deltaAsPrFiles(delta.files);
429
+ let plan = buildPassPlan(cfg, deltaFiles, undefined, args.ecosystem, heuristics, args.styleGuide, args.ciLinters, { tierFiles: args.files });
430
+ // The migration gate and the pre-check read the WHOLE PR, and their notes
431
+ // name pass-data-safety (a degraded pre-check un-muzzles that lens, never
432
+ // goes quiet). A PR whose migrations sit outside the delta
433
+ // still gets the lens the gate names: the full plan's row rides the delta
434
+ // plan, before the validator.
435
+ if (args.ecosystem.migrationGate(args.files) &&
436
+ !plan.pass_plan.some((p) => p.lens === DATA_SAFETY_PASS)) {
437
+ const carried = args.fullPlan.pass_plan.filter((p) => p.lens === DATA_SAFETY_PASS);
438
+ if (carried.length > 0) {
439
+ const at = plan.pass_plan.findIndex((p) => p.lens === VALIDATE_PASS);
440
+ const rows = [...plan.pass_plan];
441
+ rows.splice(at < 0 ? rows.length : at, 0, ...carried);
442
+ plan = {
443
+ ...plan,
444
+ pass_plan: slowestFirst(rows, deltaFiles, new Set(cfg.models.risk_passes)),
445
+ addable_lenses: plan.addable_lenses.filter((l) => l !== DATA_SAFETY_PASS),
446
+ };
447
+ }
448
+ }
449
+ // A small delta gets the LEAN plan (`[review] follow_up_small_delta_lines`):
450
+ // pass-baseline reads it whole, so the per-file sweep rows add agents and
451
+ // no coverage, and the quality and style lenses — which judged the PR in
452
+ // round 1 — move to the addable list rather than leaving the round.
453
+ // Under `follow_up_extent = "session"` every follow-up round plans the
454
+ // lean core, and the rows it leaves out are offered as optional rows for
455
+ // the session to run, partly run or skip — the small-delta threshold is the
456
+ // session's call. Under `"rules"`, the lean plan at or under the threshold.
457
+ let optionalPlan = [];
458
+ if ((cfg.review.follow_up_extent ?? REVIEW_DEFAULTS.follow_up_extent) === "session") {
459
+ const lean = leanFollowUpPlan(plan);
460
+ const kept = new Set(lean.pass_plan);
461
+ optionalPlan = plan.pass_plan.filter((p) => !kept.has(p));
462
+ const optionalLenses = new Set(optionalPlan.map((p) => p.lens));
463
+ plan = {
464
+ ...lean,
465
+ sweep_unswept: plan.sweep_unswept,
466
+ addable_lenses: lean.addable_lenses.filter((l) => !optionalLenses.has(l)),
467
+ };
468
+ }
469
+ else {
470
+ const smallDelta = cfg.review.follow_up_small_delta_lines ?? REVIEW_DEFAULTS.follow_up_small_delta_lines;
471
+ if (smallDelta > 0 && delta.lines <= smallDelta)
472
+ plan = leanFollowUpPlan(plan);
473
+ }
474
+ // pass-baseline carries every prior finding no other planned lens owns: a
475
+ // follow-up plan without it (a profile switched it off) cannot verify them.
476
+ if (!plan.pass_plan.some((p) => p.lens === BASELINE_PASS))
477
+ return { kind: "full", reason: "baseline-unplanned" };
478
+ // An owed sweep needs a plan to run: an empty full plan records nothing
479
+ // owed rather than a sweep no round could ever satisfy.
480
+ const sweepOwed = (cfg.review.follow_up_sweep ?? REVIEW_DEFAULTS.follow_up_sweep) &&
481
+ args.fullPlan.pass_plan.length > 0 &&
482
+ args.sweepOwed(delta.lines);
483
+ return {
484
+ kind: "delta",
485
+ decision: {
486
+ delta,
487
+ fromSha: args.fromSha,
488
+ deltaFiles,
489
+ plan,
490
+ ...(optionalPlan.length > 0 ? { optionalPlan } : {}),
491
+ ...(sweepOwed
492
+ ? {
493
+ sweepPlan: args.fullPlan.pass_plan,
494
+ ...(args.fullPlan.sweep_unswept.length > 0
495
+ ? { sweepUnswept: args.fullPlan.sweep_unswept }
496
+ : {}),
497
+ ...(args.fullPlan.behaviour_unread?.length
498
+ ? { sweepBehaviourUnread: args.fullPlan.behaviour_unread }
499
+ : {}),
500
+ }
501
+ : {}),
502
+ },
503
+ };
504
+ }
505
+ const BASELINE_PASS = "pass-baseline";
506
+ const DATA_SAFETY_PASS = "pass-data-safety";
507
+ /** The lenses a lean follow-up plan offers as addable instead of planning. */
508
+ export const LEAN_ADDABLE_PASSES = [...QUALITY_PASSES, STYLE_PASS];
509
+ /**
510
+ * The LEAN follow-up plan: the plan without its per-file
511
+ * pass-sweep rows, and with the quality and style lenses moved to
512
+ * `addable_lenses`. Every other row — baseline, the triggered risk lenses,
513
+ * the validator — is kept as planned, and so is a quality or style row the
514
+ * plan marks `required` (one the operator made a risk pass): a required row
515
+ * is an obligation, never an offer. No lens leaves the round: a session that
516
+ * sees a quality or style question in the change adds the lens.
517
+ */
518
+ export function leanFollowUpPlan(plan) {
519
+ const movable = (p) => LEAN_ADDABLE_PASSES.includes(p.lens) && p.required !== true;
520
+ const moved = lensesOf(plan.pass_plan.filter(movable));
521
+ return {
522
+ ...plan,
523
+ pass_plan: plan.pass_plan.filter((p) => p.lens !== SWEEP_PASS && !movable(p)),
524
+ addable_lenses: [
525
+ ...plan.addable_lenses,
526
+ ...moved.filter((l) => !plan.addable_lenses.includes(l)),
527
+ ],
528
+ sweep_unswept: [],
529
+ };
530
+ }
531
+ /** A delta's files as one git-style patch (the hunks `prOwnedDelta` read,
532
+ * each under its file header). */
533
+ export function renderDeltaPatch(files) {
534
+ const out = [];
535
+ for (const f of files) {
536
+ const oldPath = f.old_path ?? f.path;
537
+ out.push(`diff --git a/${oldPath} b/${f.path}`);
538
+ if (f.conflict)
539
+ out.push("# CONFLICT: the replay of the reviewed head conflicted here; the PR's own hunks follow");
540
+ if (f.binary) {
541
+ out.push(`Binary files a/${oldPath} and b/${f.path} differ`);
542
+ continue;
543
+ }
544
+ out.push(f.status === "added" ? "--- /dev/null" : `--- a/${oldPath}`);
545
+ out.push(f.status === "removed" ? "+++ /dev/null" : `+++ b/${f.path}`);
546
+ if (f.patch)
547
+ out.push(f.patch.endsWith("\n") ? f.patch.slice(0, -1) : f.patch);
548
+ }
549
+ return out.length ? `${out.join("\n")}\n` : "";
550
+ }
551
+ /** The order's view of a delta (types.ts `RoundDelta`). */
552
+ export function roundDeltaOf(d, patchFile) {
553
+ return {
554
+ from_sha: d.fromSha,
555
+ tree: d.delta.tree,
556
+ lines: d.delta.lines,
557
+ files: d.delta.files.map((f) => ({
558
+ path: f.path,
559
+ ...(f.old_path !== undefined ? { old_path: f.old_path } : {}),
560
+ status: f.status,
561
+ ranges: f.ranges.map(([a, b]) => [a, b]),
562
+ ...(f.whole_file ? { whole_file: true } : {}),
563
+ ...(f.conflict ? { conflict: true } : {}),
564
+ })),
565
+ patch_file: patchFile,
566
+ };
567
+ }
568
+ /** The order the follow-up round's OPTIONAL rows render their task files
569
+ * from: the follow-up order itself — the change since the last
570
+ * review stays their scope — with `optional_plan` as its plan. Prior
571
+ * findings ride the core rows only (their assignment indexes `pass_plan`),
572
+ * so none ride here. Pure. */
573
+ export function optionalOrderOf(order, optionalPlan) {
574
+ const { prior_assignments: _p, optional_plan: _o, optional_task_files: _f, ...rest } = order;
575
+ return {
576
+ ...rest,
577
+ pass_plan: optionalPlan,
578
+ lenses: lensesOf(optionalPlan),
579
+ };
580
+ }
581
+ /** The order the pre-approval sweep's task files render from: the
582
+ * follow-up order minus its follow-up fields, planned with the whole PR's
583
+ * full plan — exactly the order a full round would hand its lenses. Pure;
584
+ * the daemon and the bench's follow-up replay render the sweep's tasks from
585
+ * it alike. */
586
+ export function sweepOrderOf(order, sweepPlan) {
587
+ const { scope: _s, delta: _d, prior_findings_note: _p, sweep_plan: _sp, sweep_plan_unswept: _su, sweep_plan_behaviour_unread: _bu, sweep_task_files: _st,
588
+ // The delta plan's facts, not the whole PR's: the sweep carries its own.
589
+ sweep_unswept: _du, behaviour_unread: _db, coverage_files: _cf, ...whole } = order;
590
+ return {
591
+ ...whole,
592
+ pass_plan: sweepPlan,
593
+ lenses: lensesOf(sweepPlan),
594
+ ...(order.sweep_plan_unswept && order.sweep_plan_unswept.length > 0
595
+ ? { sweep_unswept: order.sweep_plan_unswept }
596
+ : {}),
597
+ ...(order.sweep_plan_behaviour_unread?.length
598
+ ? { behaviour_unread: order.sweep_plan_behaviour_unread }
599
+ : {}),
600
+ };
601
+ }
602
+ /** Build the round order for one PR — pure once the files list is in hand. */
603
+ export function buildRoundOrder(args) {
604
+ const eco = args.ecosystem ?? DJANGO_ECOSYSTEM;
605
+ const { pass_plan, addable_lenses, sweep_unswept, behaviour_unread } = args.plan ??
606
+ buildPassPlan(args.cfg, args.files, { title: args.row.title, body: args.prBody }, eco, args.heuristics, args.styleGuide ?? [], args.ciLinters ?? []);
607
+ const headSha = reviewedHeadOf(args.tree, args.row);
608
+ // An addable lens the profile floors above the add rule's own
609
+ // variant is named with its variant in the prompt.
610
+ const addable_tiers = Object.fromEntries(addable_lenses
611
+ .filter((l) => !args.cfg.models.risk_passes.includes(l))
612
+ .map((l) => [l, addTierOf(args.cfg, l)])
613
+ .filter(([, t]) => t !== "sol-med"));
614
+ return {
615
+ pr: args.row.number,
616
+ title: args.row.title,
617
+ round_id: args.roundId,
618
+ round_no: args.roundNo,
619
+ posting_key: roundPostingKey(args.row.number, args.roundNo, headSha),
620
+ ...(args.reviewNo !== undefined ? { review_no: args.reviewNo } : {}),
621
+ round_type: args.roundType,
622
+ // Kept for compatibility with the rounds table / event log: always the
623
+ // pass_plan's lens names in plan order (a lens with several rows — the
624
+ // sweep — once).
625
+ lenses: lensesOf(pass_plan),
626
+ pass_plan,
627
+ addable_lenses,
628
+ ...(Object.keys(addable_tiers).length > 0 ? { addable_tiers } : {}),
629
+ ...(sweep_unswept.length > 0 ? { sweep_unswept } : {}),
630
+ ...(behaviour_unread && behaviour_unread.length > 0 ? { behaviour_unread } : {}),
631
+ ...(args.dependencyNote ? { dependency_note: args.dependencyNote } : {}),
632
+ ...(args.cfg.review.nits === "open" ? { nit_policy: "open" } : {}),
633
+ ...(isDefaultPosting(args.cfg.posting) ? {} : { posting_policy: args.cfg.posting }),
634
+ // `[review] render_outputs` (packages/pi-plugin/src/reviewrender.ts): the round renders its
635
+ // posted review from the findings record. Absent ⇒ the session writes
636
+ // both files itself.
637
+ ...(args.cfg.review?.render_outputs ? { render_outputs: true } : {}),
638
+ // `[review] dedup_merge` (packages/pi-plugin/src/templates.ts renderDedupNote): only when
639
+ // the plan has a validator to hand the groups to.
640
+ ...(args.cfg.review?.dedup_merge && pass_plan.some((p) => p.lens === "pass-validate")
641
+ ? { dedup_merge: true }
642
+ : {}),
643
+ // `[review] validate_compact` (packages/pi-plugin/src/templates.ts
644
+ // renderValidatorOutputNote): only when the plan has a validator.
645
+ ...(args.cfg.review?.validate_compact && pass_plan.some((p) => p.lens === "pass-validate")
646
+ ? { validate_compact: true }
647
+ : {}),
648
+ // `[review] coverage_check` (packages/pi-plugin/src/coverage.ts): only when the plan has a
649
+ // sweep to launch for the uncovered files and there is a file to hold it to.
650
+ ...(() => {
651
+ if (!args.cfg.review?.coverage_check || !pass_plan.some((p) => p.lens === "pass-sweep"))
652
+ return {};
653
+ // A follow-up round's coverage is the delta's — the rest of
654
+ // the PR was covered by the round that reviewed it.
655
+ const coverage_files = coverageEligible(args.followUp?.deltaFiles ?? args.files);
656
+ return coverage_files.length > 0 ? { coverage_files } : {};
657
+ })(),
658
+ // `[review] validator_shards` (templates.ts renderValidatorShardNote):
659
+ // only above 1, and only when the plan has a validator to shard.
660
+ ...((args.cfg.review?.validator_shards ?? 1) > 1
661
+ ? { validator_shards: args.cfg.review.validator_shards }
662
+ : {}),
663
+ migration_gate: eco.migrationGate(args.files),
664
+ migration_collisions: args.migrationCollisions ?? [],
665
+ ...(args.migrationCollisionsUndelivered && (args.migrationCollisions ?? []).length > 0
666
+ ? { migration_collisions_undelivered: true }
667
+ : {}),
668
+ migration_precheck_degraded: args.migrationPrecheckDegraded ?? false,
669
+ ...(args.firstPartyDirectives !== undefined
670
+ ? { first_party_directives: args.firstPartyDirectives }
671
+ : {}),
672
+ // Absent unless escalation is enabled AND session judgement is on, so the
673
+ // default install's order (and prompt) carries no escalation targets.
674
+ ...(() => {
675
+ const targets = promptTargetsFor(args.cfg.escalation);
676
+ return targets ? { escalation_targets: targets } : {};
677
+ })(),
678
+ ...(args.recovery?.target_head_sha === headSha ? { recovery: args.recovery } : {}),
679
+ head_sha: headSha,
680
+ base_ref: args.tree?.base_ref ?? "",
681
+ base_sha: args.tree?.base_sha ?? "",
682
+ merge_base: args.tree?.merge_base ?? "",
683
+ worktree: args.worktree,
684
+ settled_digest: args.settledDigest,
685
+ ...(args.ledgerCarry ? { ledger_carry: args.ledgerCarry } : {}),
686
+ issued_at: args.issuedAt,
687
+ ...(args.lensRuntime ? { lens_runtime: args.lensRuntime } : {}),
688
+ ...(args.prBody !== undefined ? { pr_body: args.prBody } : {}),
689
+ ...(args.followUp
690
+ ? {
691
+ scope: "delta",
692
+ delta: args.followUp.delta,
693
+ prior_findings_note: args.followUp.priorFindingsNote,
694
+ ...((args.cfg.review.follow_up_extent ?? REVIEW_DEFAULTS.follow_up_extent) === "session"
695
+ ? { follow_up_extent: "session" }
696
+ : {}),
697
+ ...(args.followUp.optionalPlan && args.followUp.optionalPlan.length > 0
698
+ ? { optional_plan: args.followUp.optionalPlan }
699
+ : {}),
700
+ ...(() => {
701
+ const list = args.followUp.priorFindings;
702
+ if (!list || list.findings.length === 0)
703
+ return {};
704
+ const assigned = assignPriorFindings(list, pass_plan, new Set(args.followUp.delta.files.map((f) => f.path)));
705
+ return assigned.length > 0 ? { prior_assignments: assigned } : {};
706
+ })(),
707
+ ...(args.followUp.sweepPlan && args.followUp.sweepPlan.length > 0
708
+ ? {
709
+ sweep_plan: args.followUp.sweepPlan,
710
+ ...(args.followUp.sweepUnswept && args.followUp.sweepUnswept.length > 0
711
+ ? { sweep_plan_unswept: args.followUp.sweepUnswept }
712
+ : {}),
713
+ ...(args.followUp.sweepBehaviourUnread?.length
714
+ ? { sweep_plan_behaviour_unread: args.followUp.sweepBehaviourUnread }
715
+ : {}),
716
+ }
717
+ : {}),
718
+ }
719
+ : {}),
720
+ };
721
+ }
722
+ //# sourceMappingURL=planner.js.map