@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,805 @@
1
+ // The review config: the config.toml sections the review core reads, their
2
+ // defaults and their parsers. The schema of every other surface (ops,
3
+ // ingress, Slack, TUI, companion, memory, archive, …) and the install's homes
4
+ // stay in src/config.ts, which re-exports everything here and parses the
5
+ // whole file through these same section parsers.
6
+ //
7
+ // `parseCoreConfig` reads just these sections: what a one-shot review needs,
8
+ // with no install home, no secrets lookup and no app section. Where a caller
9
+ // wants the located secrets dir or a deprecation said, it does that itself.
10
+ import { parse } from "smol-toml";
11
+ import { globProblem } from "./glob.js";
12
+ import { INTENT_MIN_SUBSTANCE_WORDS, PLACEMENT_MIN_NEW_FILE_LINES, PLACEMENT_MIN_PROD_FILES, QUALITY_MIN_ADDED_LINES, SWEEP_MAX_FILES_PER_GROUP, SWEEP_MAX_LINES_PER_GROUP, SWEEP_WIDE_FILES_PER_GROUP, } from "./heuristics.js";
13
+ import { ALL_PASSES, SCAN_DEEP_FLOOR_LENSES, SCAN_DEEP_LENSES } from "./passes.js";
14
+ import { PASS_TIER_ORDER } from "./types.js";
15
+ export const GITHUB_AUTH_MODES = ["app", "user"];
16
+ export const GUARDS_DEFAULTS = {
17
+ downgrade_on_human_approval: true,
18
+ skip_unchanged_head: true,
19
+ recheck_pr_state_before_post: true,
20
+ block_approve_on_red_ci: true,
21
+ no_checks_is_red: false,
22
+ refuse_on_head_drift: true,
23
+ };
24
+ export const REVIEW_DIRECTIVES_DEFAULTS = {
25
+ extra_vendored_segments: [],
26
+ extra_basenames: [],
27
+ extra_dir_segments: [],
28
+ extra_root_dirs: [],
29
+ extra_files: [],
30
+ };
31
+ /** The lean lever plan — `default` and `low` share it. Its thresholds are the
32
+ * selection's own defaults (packages/pi-plugin/src/heuristics.ts), named once there. */
33
+ const LEAN_LEVERS = {
34
+ sublenses: true,
35
+ sweep: true,
36
+ sweep_max_groups: 6,
37
+ // 8 files, so the 500-line budget binds first on most groups: a 5-file cap
38
+ // cut nearly half the sweep rows at a median of 78 changed lines, and 8
39
+ // plans ~17% fewer rows with none unswept.
40
+ sweep_group_files: SWEEP_MAX_FILES_PER_GROUP,
41
+ sweep_group_lines: SWEEP_MAX_LINES_PER_GROUP,
42
+ sweep_wide_files: SWEEP_WIDE_FILES_PER_GROUP,
43
+ behaviour_delta: true,
44
+ behaviour_delta_max_groups: 3,
45
+ loosened_test_hint: true,
46
+ intent_min_words: INTENT_MIN_SUBSTANCE_WORDS,
47
+ placement_min_code_files: PLACEMENT_MIN_PROD_FILES,
48
+ placement_min_new_file_lines: PLACEMENT_MIN_NEW_FILE_LINES,
49
+ dependency_sources: true,
50
+ tests_lens: true,
51
+ quality_lenses: true,
52
+ quality_min_added_lines: QUALITY_MIN_ADDED_LINES,
53
+ style_lens: true,
54
+ lint_conformance: true,
55
+ };
56
+ export const REVIEW_PRESETS = {
57
+ default: { effort: "", levers: LEAN_LEVERS },
58
+ low: { effort: "low", levers: LEAN_LEVERS },
59
+ max: {
60
+ effort: "high",
61
+ levers: {
62
+ ...LEAN_LEVERS,
63
+ sweep_max_groups: 8,
64
+ sweep_group_files: 3,
65
+ sweep_group_lines: 400,
66
+ behaviour_delta_max_groups: 4,
67
+ intent_min_words: 20,
68
+ placement_min_code_files: 4,
69
+ placement_min_new_file_lines: 0,
70
+ },
71
+ },
72
+ };
73
+ export function parsePreset(raw) {
74
+ const v = String(raw ?? "default")
75
+ .trim()
76
+ .toLowerCase();
77
+ if (v === "low" || v === "default" || v === "max")
78
+ return v;
79
+ throw new Error(`config.toml [review] preset must be "low", "default" or "max" (got "${v}")`);
80
+ }
81
+ export const REVIEW_DEFAULTS = {
82
+ escalation_mention_default: "",
83
+ profile: "",
84
+ directives: REVIEW_DIRECTIVES_DEFAULTS,
85
+ preset: "default",
86
+ ...LEAN_LEVERS,
87
+ nits: "strict",
88
+ validate_demote: true,
89
+ skip_lenses: [],
90
+ validate_consequence_rule: false,
91
+ wide_lens_fanout: true,
92
+ task_files: true,
93
+ render_outputs: true,
94
+ validator_shards: 1,
95
+ dedup_merge: true,
96
+ coverage_check: true,
97
+ follow_up: "delta",
98
+ follow_up_max_delta_ratio: 0.6,
99
+ follow_up_sweep: true,
100
+ follow_up_post_approval_sweep_lines: 500,
101
+ follow_up_small_delta_lines: 150,
102
+ baseline_split_lines: 2000,
103
+ context_pack: "pack-first",
104
+ context_pack_max_tokens: 40000,
105
+ sweep_light_tier: "",
106
+ validate_compact: true,
107
+ follow_up_extent: "session",
108
+ };
109
+ export const ESCALATION_RULE_DEFAULTS = {
110
+ name: "",
111
+ to: "",
112
+ why: "",
113
+ paths: [],
114
+ labels: [],
115
+ min_severity: "",
116
+ failing_checks: [],
117
+ };
118
+ export const ESCALATION_DEFAULTS = {
119
+ enabled: false,
120
+ shape: "comment",
121
+ targets: [],
122
+ session_judgement: false,
123
+ max_per_pr: 2,
124
+ rules: [],
125
+ };
126
+ export const ESCALATION_SEVERITY_FLOORS = ["P0", "P1", "P2", "P3"];
127
+ /** A GitHub login: letters, digits and single inner dashes, at most 39. */
128
+ export const ESCALATION_LOGIN_RE = /^[A-Za-z0-9](?:[A-Za-z0-9]|-(?=[A-Za-z0-9])){0,38}$/;
129
+ /**
130
+ * Parse and VALIDATE `[escalation]`.
131
+ *
132
+ * A half-configured live state is made unrepresentable here
133
+ * rather than only in the wizard: a config with the feature on and no target,
134
+ * or with a rule pointing at a login that is not a target, or with a rule that
135
+ * declares no condition, fails to LOAD. A hand-edited config gets the same
136
+ * refusal the interview does.
137
+ *
138
+ * With `enabled = false` NOTHING below the early return is checked, so a
139
+ * half-filled table that is switched off really is a draft — it cannot wedge
140
+ * daemon startup. The whole validation set fires the moment the operator
141
+ * flips the switch.
142
+ */
143
+ export function parseEscalation(raw) {
144
+ const rawRules = Array.isArray(raw.rules) ? raw.rules : [];
145
+ const cfg = {
146
+ ...ESCALATION_DEFAULTS,
147
+ ...raw,
148
+ targets: (Array.isArray(raw.targets) ? raw.targets : [])
149
+ .map((t) => String(t).trim().replace(/^@/, ""))
150
+ .filter(Boolean),
151
+ rules: rawRules.map((r) => ({
152
+ ...ESCALATION_RULE_DEFAULTS,
153
+ ...r,
154
+ to: String(r.to ?? "")
155
+ .trim()
156
+ .replace(/^@/, ""),
157
+ name: String(r.name ?? "").trim(),
158
+ why: String(r.why ?? "").trim(),
159
+ paths: (Array.isArray(r.paths) ? r.paths : [])
160
+ .map((p) => String(p).trim())
161
+ .filter(Boolean),
162
+ labels: (Array.isArray(r.labels) ? r.labels : [])
163
+ .map((l) => String(l).trim())
164
+ .filter(Boolean),
165
+ failing_checks: (Array.isArray(r.failing_checks) ? r.failing_checks : [])
166
+ .map((c) => String(c).trim())
167
+ .filter(Boolean),
168
+ min_severity: String(r.min_severity ?? "")
169
+ .trim()
170
+ .toUpperCase(),
171
+ })),
172
+ };
173
+ // Switched off is a draft — checked FIRST, before any shape rule, because
174
+ // "draft" has to mean it. Nothing below
175
+ // this line is read while the feature is off, so a half-written rule an
176
+ // operator is still thinking about must not wedge daemon startup. Every one
177
+ // of these checks fires the moment they flip `enabled = true`, and the
178
+ // onboarding step runs the real parser over the text it is about to write,
179
+ // so a draft is never a way to smuggle a broken live config past validation.
180
+ if (!cfg.enabled)
181
+ return cfg;
182
+ if (cfg.shape !== "comment" && cfg.shape !== "review_request") {
183
+ throw new Error(`config.toml [escalation]: shape must be "comment" or "review_request" (got ${JSON.stringify(cfg.shape)})`);
184
+ }
185
+ if (!Number.isInteger(cfg.max_per_pr) || cfg.max_per_pr < 1) {
186
+ throw new Error(`config.toml [escalation]: max_per_pr must be a positive integer (got ${JSON.stringify(cfg.max_per_pr)})`);
187
+ }
188
+ for (const t of cfg.targets) {
189
+ if (!ESCALATION_LOGIN_RE.test(t)) {
190
+ throw new Error(`config.toml [escalation]: targets entry ${JSON.stringify(t)} is not a GitHub login`);
191
+ }
192
+ }
193
+ const seenNames = new Set();
194
+ for (const r of cfg.rules) {
195
+ if (!r.name)
196
+ throw new Error("config.toml [[escalation.rules]]: every rule needs a `name`");
197
+ if (seenNames.has(r.name))
198
+ throw new Error(`config.toml [[escalation.rules]]: duplicate rule name ${JSON.stringify(r.name)}`);
199
+ seenNames.add(r.name);
200
+ if (r.min_severity && !ESCALATION_SEVERITY_FLOORS.includes(r.min_severity)) {
201
+ throw new Error(`config.toml [[escalation.rules]] ${r.name}: min_severity must be P0, P1, P2 or P3 (got ${JSON.stringify(r.min_severity)})`);
202
+ }
203
+ if (r.paths.length + r.labels.length + r.failing_checks.length === 0 && !r.min_severity) {
204
+ throw new Error(`config.toml [[escalation.rules]] ${r.name}: declares no condition — it could never fire`);
205
+ }
206
+ if (!r.why)
207
+ throw new Error(`config.toml [[escalation.rules]] ${r.name}: needs a \`why\` saying why this person`);
208
+ }
209
+ if (cfg.targets.length === 0) {
210
+ throw new Error("config.toml [escalation]: enabled = true with no `targets` — escalation on with nobody to escalate to is not a configuration");
211
+ }
212
+ if (cfg.rules.length === 0 && !cfg.session_judgement) {
213
+ throw new Error("config.toml [escalation]: enabled = true with no rules and session_judgement = false — nothing could ever escalate");
214
+ }
215
+ for (const r of cfg.rules) {
216
+ if (!cfg.targets.includes(r.to)) {
217
+ throw new Error(`config.toml [[escalation.rules]] ${r.name}: to = ${JSON.stringify(r.to)} is not in [escalation] targets — every escalation target is declared once, in one place`);
218
+ }
219
+ }
220
+ return cfg;
221
+ }
222
+ export const OWNER_DEFAULTS = {
223
+ name: "",
224
+ slack_id: "",
225
+ github_login: "",
226
+ };
227
+ /** pi's thinking levels, ascending (pi 0.87.1, unchanged at 0.99.1 and 1.0.0 — VERIFY-ON-PIN). */
228
+ export const THINKING_LEVELS = ["off", "minimal", "low", "medium", "high", "xhigh", "max"];
229
+ /** "provider/model:thinking" → its model and its pi thinking level, or a
230
+ * null level when the spec carries no suffix. */
231
+ export function splitModelSpec(spec) {
232
+ const m = new RegExp(`^(.+):(${THINKING_LEVELS.join("|")})$`).exec(spec);
233
+ return m ? { model: m[1], thinking: m[2] } : { model: spec, thinking: null };
234
+ }
235
+ /** Replace (or add) the `:thinking` suffix of one model spec. */
236
+ export function withThinking(spec, level) {
237
+ return `${splitModelSpec(spec).model}:${level}`;
238
+ }
239
+ /** The thinking level an effort setting names: `high` is the model's
240
+ * ceiling (`[models] effort_max`) — the one reading of `[models] effort`, a
241
+ * lens's profile `effort` and `[scan] effort` alike. */
242
+ export function effortLevel(effort, effortMax) {
243
+ return effort === "high" ? effortMax : effort;
244
+ }
245
+ /** Apply `[models] effort` to every spec the review runs on. Pure. */
246
+ export function applyReviewEffort(models) {
247
+ if (models.effort === "")
248
+ return models;
249
+ const level = effortLevel(models.effort, models.effort_max);
250
+ const tiers = Object.fromEntries(Object.entries(models.tiers).map(([t, spec]) => [t, withThinking(spec, level)]));
251
+ return {
252
+ ...models,
253
+ default: withThinking(models.default, level),
254
+ conversation: withThinking(models.conversation, level),
255
+ tiers,
256
+ };
257
+ }
258
+ export function parseEffort(raw) {
259
+ const v = String(raw ?? "")
260
+ .trim()
261
+ .toLowerCase();
262
+ if (v === "")
263
+ return "";
264
+ const effort = normalizeEffort(v);
265
+ if (effort !== null)
266
+ return effort;
267
+ throw new Error(`config.toml [models] effort must be "", "low", "medium" or "high" (got "${v}")`);
268
+ }
269
+ /** The nonempty effort vocabulary every effort knob shares — `low`,
270
+ * `medium` (alias `med`) and `high`, case- and space-insensitive — or null for
271
+ * anything else. What an empty value means is each knob's own call. */
272
+ export function normalizeEffort(raw) {
273
+ if (typeof raw !== "string")
274
+ return null;
275
+ const v = raw.trim().toLowerCase();
276
+ if (v === "low" || v === "medium" || v === "high")
277
+ return v;
278
+ return v === "med" ? "medium" : null;
279
+ }
280
+ function parseEffortMax(raw) {
281
+ const v = String(raw ?? "max")
282
+ .trim()
283
+ .toLowerCase();
284
+ if (THINKING_LEVELS.includes(v) && v !== "off")
285
+ return v;
286
+ throw new Error(`config.toml [models] effort_max must be a pi thinking level (got "${v}")`);
287
+ }
288
+ /**
289
+ * The shipped per-lens tier pins (measured: high effort on these lenses found
290
+ * more defects with no high-severity loss, for ~18% more cost per PR). The
291
+ * three lenses that read the whole diff line by line run at
292
+ * the `sol-high` tier — gpt-6.1-sol at high effort — on every PR; every other
293
+ * lens keeps its planned tier. A config's own `[models.pass_tiers]` entry for
294
+ * one of them replaces its pin (e.g. `"pass-baseline" = "sol-med"`), and a
295
+ * profile lowers its thinking with `[lenses.<pass>] effort = "medium"`.
296
+ */
297
+ export const DEFAULT_PASS_TIERS = Object.freeze({
298
+ "pass-baseline": "sol-high",
299
+ "pass-sweep": "sol-high",
300
+ "pass-behaviour-delta": "sol-high",
301
+ });
302
+ /** `[engine] lens_pass_deadline_min` when the file does not set it: a
303
+ * healthy pass takes 20-100 s and the slowest about 4 min, so 8 min only
304
+ * ever cuts a stalled one. */
305
+ export const DEFAULT_LENS_PASS_DEADLINE_MIN = 8;
306
+ /** `[engine] lens_cache_stagger_ms`'s default — every reader's fallback too
307
+ * (`packages/pi-plugin/src/engine/lens/env.ts` keeps the env reader's copy, pinned equal by a
308
+ * test). */
309
+ export const DEFAULT_LENS_CACHE_STAGGER_MS = 2500;
310
+ /** `[engine] lens_max_concurrency` when the file does not set it: the
311
+ * companion's desktop number. */
312
+ export const DEFAULT_LENS_MAX_CONCURRENCY = 4;
313
+ /** `[engine] lens_cache_group` when the file does not set it. */
314
+ export const DEFAULT_LENS_CACHE_GROUP = 5;
315
+ export const ENGINE_RUNTIME_KINDS = ["sdk"];
316
+ export const LENS_RUNTIME_KINDS = ["engine"];
317
+ export const ENGINE_DEFAULTS = {
318
+ runtime: "sdk",
319
+ lens_max_concurrency: DEFAULT_LENS_MAX_CONCURRENCY,
320
+ lens_cache_group: DEFAULT_LENS_CACHE_GROUP,
321
+ lens_cache_stagger_ms: DEFAULT_LENS_CACHE_STAGGER_MS,
322
+ lens_pass_deadline_min: DEFAULT_LENS_PASS_DEADLINE_MIN,
323
+ };
324
+ /** The `[pi]` lens default: the engine's planned wave is on. */
325
+ function piLensDefaults() {
326
+ return { lens_runtime: "engine", engine_wave: true };
327
+ }
328
+ /** The `[pi]` keys that moved to `[engine]` and are refused where they stand. */
329
+ const RETIRED_PI_KEYS = {
330
+ subagent_max_concurrency: "lens_max_concurrency",
331
+ subagent_cache_group: "lens_cache_group",
332
+ subagent_cache_stagger_ms: "lens_cache_stagger_ms",
333
+ subagent_pass_deadline_min: "lens_pass_deadline_min",
334
+ };
335
+ /** Refuse a value outside a closed set. A typo must not silently become the
336
+ * default runtime. */
337
+ function oneOf(where, v, allowed) {
338
+ if (typeof v !== "string" || !allowed.includes(v))
339
+ throw new Error(`config.toml ${where} must be one of ${allowed.join(" | ")} (got ${JSON.stringify(v)})`);
340
+ return v;
341
+ }
342
+ export function parseEngine(raw) {
343
+ const e = { ...ENGINE_DEFAULTS, ...raw };
344
+ if (e.runtime === "proc")
345
+ throw new Error('config.toml [engine] runtime = "proc" is retired: pi runs in-process on the SDK (the one adapter); delete the key or set it to "sdk"');
346
+ const runtime = oneOf("[engine] runtime", e.runtime, ENGINE_RUNTIME_KINDS);
347
+ const whole = (key, min, max) => {
348
+ const v = e[key];
349
+ if (typeof v !== "number" || !Number.isInteger(v) || v < min || v > max)
350
+ throw new Error(`config.toml [engine] ${key} must be a whole number ${min}-${max} (got ${JSON.stringify(v)})`);
351
+ return v;
352
+ };
353
+ return {
354
+ runtime,
355
+ lens_max_concurrency: whole("lens_max_concurrency", 1, 64),
356
+ lens_cache_group: whole("lens_cache_group", 0, 1000),
357
+ lens_cache_stagger_ms: whole("lens_cache_stagger_ms", 0, 600_000),
358
+ lens_pass_deadline_min: whole("lens_pass_deadline_min", 0, 240),
359
+ };
360
+ }
361
+ /** Refuse the `[pi]` keys the lens settings left behind, naming where they went. */
362
+ function refuseRetiredPiKeys(pi) {
363
+ for (const [key, to] of Object.entries(RETIRED_PI_KEYS))
364
+ if (key in pi)
365
+ throw new Error(`config.toml [pi] ${key} is retired with pi's native subagent glue: delete it, and set [engine] ${to} if the default does not suit`);
366
+ }
367
+ function parsePiLensRuntime(pi) {
368
+ if (pi.lens_runtime === "native")
369
+ throw new Error('config.toml [pi] lens_runtime = "native" is retired: pi\'s own subagent glue is gone and the engine\'s lens tool is the only one; delete the key or set it to "engine"');
370
+ oneOf("[pi] lens_runtime", pi.lens_runtime, LENS_RUNTIME_KINDS);
371
+ if (typeof pi.engine_wave !== "boolean")
372
+ throw new Error(`config.toml [pi] engine_wave must be true or false (got ${JSON.stringify(pi.engine_wave)})`);
373
+ // A wave only the engine route can launch: a typo must not run the main
374
+ // session's own launch while the config says the engine's.
375
+ if (pi.engine_wave && pi.lens_runtime !== "engine")
376
+ throw new Error('config.toml [pi] engine_wave = true needs lens_runtime = "engine"');
377
+ return pi;
378
+ }
379
+ /** Defaults for the tiered [models] knobs — older configs keep parsing. */
380
+ export const MODELS_TIER_DEFAULTS = {
381
+ pass_tiers: { ...DEFAULT_PASS_TIERS },
382
+ pass_models: {},
383
+ effort: "",
384
+ effort_max: "max",
385
+ tiers: {
386
+ "terra-med": "openai-codex/gpt-6.1-sol:medium",
387
+ "sol-med": "openai-codex/gpt-6.1-sol:medium",
388
+ "sol-high": "openai-codex/gpt-6.1-sol:high",
389
+ },
390
+ risk_passes: ["pass-security", "pass-prod-risk", "pass-data-safety"],
391
+ validate_tier: "sol-high",
392
+ small_diff_lines: 150,
393
+ pricing: {},
394
+ };
395
+ /** The values `[memory] delivery` takes. */
396
+ export const MEMORY_DELIVERY_MODES = ["off", "shadow", "on"];
397
+ /** How hard a scan looks — `[scan] depth`. */
398
+ export const SCAN_DEPTHS = ["standard", "deep"];
399
+ export const SCAN_DEFAULTS = {
400
+ effort: "low",
401
+ tier: "sol-med",
402
+ validator: true,
403
+ exclude: [],
404
+ calibration_units: 3,
405
+ calibration_max_usd: 3,
406
+ concurrency: 8,
407
+ case_max_files: 30,
408
+ case_max_lines: 3000,
409
+ unmeasured_rate_factor: 4,
410
+ depth: "standard",
411
+ deep_lenses: [...SCAN_DEEP_FLOOR_LENSES],
412
+ };
413
+ /** The `[scan]` keys a repo profile may override — what is about THIS repo
414
+ * (how hard to look, whether to validate, what is not worth reading), never
415
+ * the install's operating limits. */
416
+ export const SCAN_PROFILE_KEYS = [
417
+ "effort",
418
+ "tier",
419
+ "validator",
420
+ "exclude",
421
+ "depth",
422
+ "deep_lenses",
423
+ ];
424
+ /**
425
+ * Validate one `[scan]` table — config.toml's (every key) or a profile's
426
+ * (`SCAN_PROFILE_KEYS` only). Returns just the keys it set; an unknown key or
427
+ * a bad value throws naming `where`.
428
+ */
429
+ export function parseScanTable(where, raw, allowed = Object.keys(SCAN_DEFAULTS)) {
430
+ if (typeof raw !== "object" || raw === null || Array.isArray(raw)) {
431
+ throw new Error(`${where} [scan] must be a table`);
432
+ }
433
+ const out = {};
434
+ const fail = (key, what, v) => {
435
+ throw new Error(`${where} [scan] ${key} ${what} (got ${JSON.stringify(v)})`);
436
+ };
437
+ for (const [key, v] of Object.entries(raw)) {
438
+ if (!allowed.includes(key)) {
439
+ throw new Error(`${where} [scan] unknown key "${key}" — allowed here: ${allowed.join(", ")}`);
440
+ }
441
+ switch (key) {
442
+ case "effort": {
443
+ const e = normalizeEffort(v);
444
+ if (e)
445
+ out.effort = e;
446
+ else
447
+ fail(key, 'must be "low", "medium" or "high"', v);
448
+ break;
449
+ }
450
+ case "tier":
451
+ if (typeof v === "string" && PASS_TIER_ORDER.includes(v))
452
+ out.tier = v;
453
+ else
454
+ fail(key, `must be one of ${PASS_TIER_ORDER.join(", ")}`, v);
455
+ break;
456
+ case "validator":
457
+ if (typeof v === "boolean")
458
+ out.validator = v;
459
+ else
460
+ fail(key, "must be true or false", v);
461
+ break;
462
+ case "exclude": {
463
+ if (!Array.isArray(v))
464
+ fail(key, "must be an array of globs", v);
465
+ for (const g of v) {
466
+ const problem = globProblem(g);
467
+ if (problem !== null)
468
+ fail(key, `entry ${JSON.stringify(g)} ${problem}`, v);
469
+ }
470
+ out.exclude = [...v];
471
+ break;
472
+ }
473
+ case "calibration_max_usd":
474
+ if (typeof v === "number" && Number.isFinite(v) && v > 0)
475
+ out.calibration_max_usd = v;
476
+ else
477
+ fail(key, "must be a positive number of dollars", v);
478
+ break;
479
+ case "unmeasured_rate_factor":
480
+ if (typeof v === "number" && Number.isFinite(v) && v >= 1)
481
+ out.unmeasured_rate_factor = v;
482
+ else
483
+ fail(key, "must be a number of at least 1", v);
484
+ break;
485
+ case "depth":
486
+ if (typeof v === "string" && SCAN_DEPTHS.includes(v))
487
+ out.depth = v;
488
+ else
489
+ fail(key, `must be ${SCAN_DEPTHS.map((d) => `"${d}"`).join(" or ")}`, v);
490
+ break;
491
+ case "deep_lenses": {
492
+ if (!Array.isArray(v) || v.length === 0)
493
+ fail(key, "must be a non-empty array of lens names", v);
494
+ for (const l of v) {
495
+ if (typeof l !== "string" || !SCAN_DEEP_LENSES.includes(l))
496
+ fail(key, `entry ${JSON.stringify(l)} is not a lens a scan can run (one of: ${SCAN_DEEP_LENSES.join(", ")})`, v);
497
+ }
498
+ out.deep_lenses = [...new Set(v)];
499
+ break;
500
+ }
501
+ default: {
502
+ // The integer knobs.
503
+ if (typeof v === "number" && Number.isInteger(v) && v >= 1) {
504
+ out[key] = v;
505
+ }
506
+ else
507
+ fail(key, "must be a positive integer", v);
508
+ }
509
+ }
510
+ }
511
+ return out;
512
+ }
513
+ /** The `[scan]` keys that say where a run is driven, not how it scans. */
514
+ export const SCAN_SANDBOX_KEYS = ["sandbox", "pihome_volume", "image"];
515
+ /** `[scan]` from config.toml: the defaults, overlaid by what it sets. The
516
+ * sandbox keys are parsed apart (`parseScanSandbox`). */
517
+ export function parseScan(raw) {
518
+ const table = typeof raw === "object" && raw !== null && !Array.isArray(raw)
519
+ ? Object.fromEntries(Object.entries(raw).filter(([k]) => !SCAN_SANDBOX_KEYS.includes(k)))
520
+ : (raw ?? {});
521
+ return { ...SCAN_DEFAULTS, ...parseScanTable("config.toml", table) };
522
+ }
523
+ /** A key the table must have: its value, or a throw naming it. */
524
+ export function req(obj, key) {
525
+ const v = obj[key];
526
+ if (v === undefined)
527
+ throw new Error(`config.toml: missing key '${key}'`);
528
+ return v;
529
+ }
530
+ /** The overseer session is gone: its two knobs are still ACCEPTED so a
531
+ * live config does not break, read by nothing, and named here once at parse. */
532
+ export function configDeprecations(raw) {
533
+ const out = [];
534
+ if (raw.models?.overseer !== undefined)
535
+ out.push("config.toml [models] overseer is deprecated and ignored: the overseer session was deleted. Remove the key.");
536
+ if (raw.daemon?.overseer_rotation_days !== undefined)
537
+ out.push("config.toml [daemon] overseer_rotation_days is deprecated and ignored: the overseer session was deleted. Remove the key.");
538
+ return out;
539
+ }
540
+ export function parseModels(raw, presetEffort = "") {
541
+ return applyReviewEffort({
542
+ // `[models] effort` set explicitly wins over the preset's level.
543
+ effort: raw.effort !== undefined ? parseEffort(raw.effort) : presetEffort,
544
+ effort_max: parseEffortMax(raw.effort_max),
545
+ default: String(req(raw, "default")),
546
+ conversation: String(req(raw, "conversation")),
547
+ tiers: {
548
+ ...MODELS_TIER_DEFAULTS.tiers,
549
+ ...(raw.tiers ?? {}),
550
+ },
551
+ risk_passes: (raw.risk_passes ?? MODELS_TIER_DEFAULTS.risk_passes),
552
+ validate_tier: (raw.validate_tier ?? MODELS_TIER_DEFAULTS.validate_tier),
553
+ small_diff_lines: Number(raw.small_diff_lines ?? MODELS_TIER_DEFAULTS.small_diff_lines),
554
+ pricing: (raw.pricing ?? {}),
555
+ pass_tiers: { ...DEFAULT_PASS_TIERS, ...(raw.pass_tiers ?? {}) },
556
+ pass_models: { ...(raw.pass_models ?? {}) },
557
+ });
558
+ }
559
+ /**
560
+ * Validate the per-lens knobs — `[review] skip_lenses`,
561
+ * `[review] validate_consequence_rule`, `[models.pass_tiers]` and
562
+ * `[models.pass_models]`. Called by
563
+ * `parseConfig` and again by the bench's `--config` overrides (which write
564
+ * past the parser), so both routes refuse the same things.
565
+ */
566
+ export function validateLensKnobs(cfg) {
567
+ const known = new Set(ALL_PASSES);
568
+ const skip = cfg.review.skip_lenses ?? [];
569
+ if (!Array.isArray(skip) || skip.some((s) => typeof s !== "string"))
570
+ throw new Error(`config.toml [review] skip_lenses must be an array of pass names (got ${JSON.stringify(skip)})`);
571
+ for (const s of skip) {
572
+ if (s === "pass-validate")
573
+ throw new Error("config.toml [review] skip_lenses may not name pass-validate — switch the validator off in the profile ([lenses.pass-validate] enabled = false)");
574
+ if (!known.has(s))
575
+ throw new Error(`config.toml [review] skip_lenses: unknown pass "${s}"`);
576
+ }
577
+ if (cfg.review.validate_consequence_rule !== undefined &&
578
+ typeof cfg.review.validate_consequence_rule !== "boolean")
579
+ throw new Error(`config.toml [review] validate_consequence_rule must be true or false (got ${JSON.stringify(cfg.review.validate_consequence_rule)})`);
580
+ if (!PASS_TIER_ORDER.includes(cfg.models.validate_tier))
581
+ throw new Error(`config.toml [models] validate_tier: unknown tier ${JSON.stringify(cfg.models.validate_tier)} (one of ${PASS_TIER_ORDER.join(", ")})`);
582
+ const pins = cfg.models.pass_tiers ?? {};
583
+ if (typeof pins !== "object" || pins === null || Array.isArray(pins))
584
+ throw new Error("config.toml [models.pass_tiers] must be a table of pass = tier");
585
+ const risk = new Set(cfg.models.risk_passes ?? []);
586
+ if (risk.has("pass-validate"))
587
+ throw new Error("config.toml [models] risk_passes may not name pass-validate — use validate_tier");
588
+ for (const [pass, tier] of Object.entries(pins)) {
589
+ if (!known.has(pass))
590
+ throw new Error(`config.toml [models.pass_tiers]: unknown pass "${pass}"`);
591
+ if (pass === "pass-validate")
592
+ throw new Error("config.toml [models.pass_tiers] may not pin pass-validate — use [models] validate_tier");
593
+ if (risk.has(pass))
594
+ throw new Error(`config.toml [models.pass_tiers]: ${pass} is a risk pass (always sol-high) — remove it from [models] risk_passes first`);
595
+ if (!PASS_TIER_ORDER.includes(tier))
596
+ throw new Error(`config.toml [models.pass_tiers] ${pass}: unknown tier ${JSON.stringify(tier)} (one of ${PASS_TIER_ORDER.join(", ")})`);
597
+ }
598
+ const moved = cfg.models.pass_models ?? {};
599
+ if (typeof moved !== "object" || moved === null || Array.isArray(moved))
600
+ throw new Error("config.toml [models.pass_models] must be a table of pass = model spec");
601
+ for (const [pass, model] of Object.entries(moved)) {
602
+ if (!known.has(pass))
603
+ throw new Error(`config.toml [models.pass_models]: unknown pass "${pass}"`);
604
+ if (pass === "pass-validate")
605
+ throw new Error("config.toml [models.pass_models] may not move pass-validate — the validator's model is its tier's");
606
+ if (risk.has(pass))
607
+ throw new Error(`config.toml [models.pass_models]: ${pass} is a risk pass — it always runs on the sol-high tier's model`);
608
+ if (typeof model !== "string" || !/^[\w.-]+\/[\w.:-]+$/.test(model))
609
+ throw new Error(`config.toml [models.pass_models] ${pass}: ${JSON.stringify(model)} is not a "provider/model[:thinking]" spec`);
610
+ }
611
+ }
612
+ /** Full model spec ("provider/model:thinking") for a pass tier. */
613
+ export function tierModel(cfg, tier) {
614
+ return cfg.models.tiers[tier];
615
+ }
616
+ /** `[github]`: base_branch/clone_dir default so older configs keep parsing.
617
+ * `secrets_dir` is as written; the reader that needs the secrets locates
618
+ * them (src/homes.ts `locateSecrets`). */
619
+ export function parseGithubSection(raw) {
620
+ const given = req(raw, "github");
621
+ const auth = given.auth ?? "app";
622
+ if (!GITHUB_AUTH_MODES.includes(auth))
623
+ throw new Error(`config.toml [github]: auth must be "app" or "user" (got ${JSON.stringify(auth)})`);
624
+ return {
625
+ base_branch: "main",
626
+ clone_dir: "",
627
+ // No App under the person's own credential: its slug may be left out.
628
+ ...(auth === "user" ? { app_slug: "" } : {}),
629
+ ...given,
630
+ auth,
631
+ };
632
+ }
633
+ /** The `[github]` keys every config names. */
634
+ const REQUIRED_GITHUB_KEYS = [
635
+ "repo",
636
+ "app_slug",
637
+ "bot_login",
638
+ "review_team",
639
+ "trigger_label",
640
+ "in_progress_label",
641
+ "reviewed_label",
642
+ "improvement_label",
643
+ "issue_label",
644
+ ];
645
+ /** Refuse a `[github]` table that leaves out a key every config names. */
646
+ export function requireGithubKeys(github) {
647
+ for (const k of REQUIRED_GITHUB_KEYS)
648
+ req(github, k);
649
+ }
650
+ /** `[review] preset`. It shapes both [models] (reasoning level) and [review]
651
+ * (the levers), so it is read before either is parsed. */
652
+ export function presetOf(raw) {
653
+ return parsePreset(raw.review?.preset);
654
+ }
655
+ /** `[pi]`, with the lens runtime defaulted and checked and the retired keys refused. */
656
+ export function parsePiSection(raw) {
657
+ const pi = req(raw, "pi");
658
+ refuseRetiredPiKeys(pi);
659
+ return parsePiLensRuntime({
660
+ ...piLensDefaults(),
661
+ ...pi,
662
+ });
663
+ }
664
+ /** `[guards]` over its defaults. */
665
+ export function parseGuardsSection(raw) {
666
+ return { ...GUARDS_DEFAULTS, ...(raw.guards ?? {}) };
667
+ }
668
+ /** `[owner]` over its defaults (the legacy Slack alias folds in later,
669
+ * `foldLegacyOwnerSlackId`). */
670
+ export function parseOwnerSection(raw) {
671
+ return { ...OWNER_DEFAULTS, ...(raw.owner ?? {}) };
672
+ }
673
+ /** `[review]`. [review.directives] merges under its own spread so a partial
674
+ * table extends the defaults instead of clobbering the sibling keys. The
675
+ * preset fills every lever the file does not set itself; an explicit key
676
+ * always wins, so `preset = "max"` + `sweep = false` means exactly that. */
677
+ export function parseReviewSection(raw, preset) {
678
+ return {
679
+ ...REVIEW_DEFAULTS,
680
+ ...REVIEW_PRESETS[preset].levers,
681
+ ...(raw.review ?? {}),
682
+ preset,
683
+ directives: {
684
+ ...REVIEW_DIRECTIVES_DEFAULTS,
685
+ ...(raw.review?.directives ??
686
+ {}),
687
+ },
688
+ };
689
+ }
690
+ /** The checks on a parsed `[review]` (and the per-lens knobs), run once the
691
+ * whole config is built. */
692
+ export function validateReviewSection(cfg) {
693
+ validateLensKnobs(cfg);
694
+ const shards = cfg.review.validator_shards;
695
+ if (!Number.isInteger(shards) || shards < 1 || shards > 4) {
696
+ throw new Error(`config.toml [review]: validator_shards must be an integer 1-4 (got ${JSON.stringify(shards)})`);
697
+ }
698
+ if (typeof cfg.review.loosened_test_hint !== "boolean") {
699
+ throw new Error(`config.toml [review]: loosened_test_hint must be true or false (got ${JSON.stringify(cfg.review.loosened_test_hint)})`);
700
+ }
701
+ if (typeof cfg.review.coverage_check !== "boolean") {
702
+ throw new Error(`config.toml [review]: coverage_check must be true or false (got ${JSON.stringify(cfg.review.coverage_check)})`);
703
+ }
704
+ if (typeof cfg.review.dedup_merge !== "boolean") {
705
+ throw new Error(`config.toml [review]: dedup_merge must be true or false (got ${JSON.stringify(cfg.review.dedup_merge)})`);
706
+ }
707
+ if (cfg.review.follow_up !== "delta" && cfg.review.follow_up !== "full") {
708
+ throw new Error(`config.toml [review]: follow_up must be "delta" or "full" (got ${JSON.stringify(cfg.review.follow_up)})`);
709
+ }
710
+ {
711
+ const ratio = cfg.review.follow_up_max_delta_ratio;
712
+ if (!(typeof ratio === "number" && Number.isFinite(ratio) && ratio > 0 && ratio <= 1)) {
713
+ throw new Error(`config.toml [review]: follow_up_max_delta_ratio must be a number in (0, 1] (got ${JSON.stringify(ratio)})`);
714
+ }
715
+ }
716
+ if (typeof cfg.review.follow_up_sweep !== "boolean") {
717
+ throw new Error(`config.toml [review]: follow_up_sweep must be true or false (got ${JSON.stringify(cfg.review.follow_up_sweep)})`);
718
+ }
719
+ {
720
+ const n = cfg.review.follow_up_post_approval_sweep_lines;
721
+ if (!(typeof n === "number" && Number.isInteger(n) && n >= 0)) {
722
+ throw new Error(`config.toml [review]: follow_up_post_approval_sweep_lines must be a whole number >= 0 (got ${JSON.stringify(n)})`);
723
+ }
724
+ }
725
+ {
726
+ const n = cfg.review.baseline_split_lines;
727
+ if (!(typeof n === "number" && Number.isInteger(n) && n >= 0)) {
728
+ throw new Error(`config.toml [review]: baseline_split_lines must be a whole number >= 0 (got ${JSON.stringify(n)})`);
729
+ }
730
+ }
731
+ if (cfg.review.sweep_light_tier !== "" &&
732
+ !PASS_TIER_ORDER.includes(cfg.review.sweep_light_tier)) {
733
+ throw new Error(`config.toml [review]: sweep_light_tier must be "" or a tier (${PASS_TIER_ORDER.join(", ")}) (got ${JSON.stringify(cfg.review.sweep_light_tier)})`);
734
+ }
735
+ if (cfg.review.follow_up_extent !== "session" && cfg.review.follow_up_extent !== "rules") {
736
+ throw new Error(`config.toml [review]: follow_up_extent must be "session" or "rules" (got ${JSON.stringify(cfg.review.follow_up_extent)})`);
737
+ }
738
+ if (typeof cfg.review.validate_compact !== "boolean") {
739
+ throw new Error(`config.toml [review]: validate_compact must be true or false (got ${JSON.stringify(cfg.review.validate_compact)})`);
740
+ }
741
+ if (cfg.review.context_pack !== "off" && cfg.review.context_pack !== "pack-first") {
742
+ throw new Error(`config.toml [review]: context_pack must be "off" or "pack-first" (got ${JSON.stringify(cfg.review.context_pack)})`);
743
+ }
744
+ for (const [key, n, min] of [
745
+ ["[review] context_pack_max_tokens", cfg.review.context_pack_max_tokens, 1000],
746
+ ]) {
747
+ if (!(typeof n === "number" && Number.isInteger(n) && n >= min))
748
+ throw new Error(`config.toml ${key} must be a whole number >= ${min} (got ${JSON.stringify(n)})`);
749
+ }
750
+ {
751
+ const n = cfg.review.follow_up_small_delta_lines;
752
+ if (!(typeof n === "number" && Number.isInteger(n) && n >= 0)) {
753
+ throw new Error(`config.toml [review]: follow_up_small_delta_lines must be a whole number >= 0 (got ${JSON.stringify(n)})`);
754
+ }
755
+ }
756
+ if (cfg.review.nits !== "strict" && cfg.review.nits !== "open") {
757
+ throw new Error(`config.toml [review]: nits must be "strict" or "open" (got ${JSON.stringify(cfg.review.nits)})`);
758
+ }
759
+ }
760
+ /** Legacy alias: a set `[slack] legacy_owner_slack_id` feeds [owner] slack_id when
761
+ * that is empty; a conflicting pair is an error that names the NEW key. After
762
+ * this fold nothing reads the legacy key. */
763
+ export function foldLegacyOwnerSlackId(raw, owner) {
764
+ const legacyOwnerSlackId = String(raw.slack?.legacy_owner_slack_id ?? "").trim();
765
+ if (legacyOwnerSlackId) {
766
+ if (!owner.slack_id.trim()) {
767
+ owner.slack_id = legacyOwnerSlackId;
768
+ }
769
+ else if (owner.slack_id.trim() !== legacyOwnerSlackId) {
770
+ throw new Error("config.toml: legacy [slack] legacy_owner_slack_id and [owner] slack_id are both set and differ — set `[owner] slack_id` only");
771
+ }
772
+ }
773
+ }
774
+ /**
775
+ * The review sections of a config.toml, parsed and checked exactly as the
776
+ * whole-file parser (`parseConfig`, src/config.ts) parses them. The other
777
+ * sections are not read, so a file that only names the review's sections is
778
+ * a whole review config. `[github] secrets_dir` stays as written. `warn`
779
+ * hears each deprecated key once.
780
+ */
781
+ export function parseCoreConfig(toml, opts = {}) {
782
+ const raw = parse(toml);
783
+ for (const line of configDeprecations(raw))
784
+ opts.warn?.(`[quickreviewd] ${line}`);
785
+ const github = parseGithubSection(raw);
786
+ const preset = presetOf(raw);
787
+ const engine = parseEngine((raw.engine ?? {}));
788
+ const cfg = {
789
+ dry_run: Boolean(req(raw, "dry_run")),
790
+ github,
791
+ models: parseModels(req(raw, "models"), REVIEW_PRESETS[preset].effort),
792
+ engine,
793
+ pi: parsePiSection(raw),
794
+ guards: parseGuardsSection(raw),
795
+ review: parseReviewSection(raw, preset),
796
+ escalation: parseEscalation((raw.escalation ?? {})),
797
+ owner: parseOwnerSection(raw),
798
+ scan: parseScan(raw.scan),
799
+ };
800
+ validateReviewSection(cfg);
801
+ foldLegacyOwnerSlackId(raw, cfg.owner);
802
+ requireGithubKeys(cfg.github);
803
+ return cfg;
804
+ }
805
+ //# sourceMappingURL=reviewconfig.js.map