@quickchatai/quickreview 1.1.0 → 1.3.1

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 (471) hide show
  1. package/README.md +137 -57
  2. package/bin/qcr.js +1 -1
  3. package/config.example.toml +60 -14
  4. package/deploy/ansible/README.md +20 -12
  5. package/deploy/ansible/inventory.example.ini +1 -1
  6. package/deploy/collect-secrets.sh +1 -1
  7. package/deploy/qcr-update.sh +1 -1
  8. package/dist/extensions/cli/home.js +14 -0
  9. package/dist/extensions/cli/home.js.map +1 -0
  10. package/dist/extensions/cli/login-route.js +5 -0
  11. package/dist/extensions/cli/login-route.js.map +1 -0
  12. package/dist/extensions/cli/selfimprove.js +18 -0
  13. package/dist/extensions/cli/selfimprove.js.map +1 -0
  14. package/dist/extensions/home.js +350 -0
  15. package/dist/extensions/home.js.map +1 -0
  16. package/dist/extensions/login-route.js +180 -0
  17. package/dist/extensions/login-route.js.map +1 -0
  18. package/dist/extensions/onboarding.js +35 -11
  19. package/dist/extensions/onboarding.js.map +1 -1
  20. package/dist/extensions/selfimprove.js +49 -0
  21. package/dist/extensions/selfimprove.js.map +1 -0
  22. package/dist/extensions/setup-scan.js +23 -592
  23. package/dist/extensions/setup-scan.js.map +1 -1
  24. package/dist/extensions/setup.js +2 -47
  25. package/dist/extensions/setup.js.map +1 -1
  26. package/dist/src/archive/restore.js +18 -15
  27. package/dist/src/archive/restore.js.map +1 -1
  28. package/dist/src/botworker.js +13 -2
  29. package/dist/src/botworker.js.map +1 -1
  30. package/dist/src/channelfs.js +3 -26
  31. package/dist/src/channelfs.js.map +1 -1
  32. package/dist/src/ciretry.js +2 -1
  33. package/dist/src/ciretry.js.map +1 -1
  34. package/dist/src/cli.js +54 -61
  35. package/dist/src/cli.js.map +1 -1
  36. package/dist/src/cliops.js +3 -2
  37. package/dist/src/cliops.js.map +1 -1
  38. package/dist/src/commands.js +25 -2
  39. package/dist/src/commands.js.map +1 -1
  40. package/dist/src/config.js +32 -2
  41. package/dist/src/config.js.map +1 -1
  42. package/dist/src/daemon.js +50 -8
  43. package/dist/src/daemon.js.map +1 -1
  44. package/dist/src/debuground.js +1 -0
  45. package/dist/src/debuground.js.map +1 -1
  46. package/dist/src/debugroundpi.js +6 -1
  47. package/dist/src/debugroundpi.js.map +1 -1
  48. package/dist/src/dispatch.js +5 -4
  49. package/dist/src/dispatch.js.map +1 -1
  50. package/dist/src/engine/caserunner-sdk.js +15 -251
  51. package/dist/src/engine/caserunner-sdk.js.map +1 -1
  52. package/dist/src/engine/debugpi.js +17 -5
  53. package/dist/src/engine/debugpi.js.map +1 -1
  54. package/dist/src/execboundary.js +10 -3
  55. package/dist/src/execboundary.js.map +1 -1
  56. package/dist/src/github.js +51 -16
  57. package/dist/src/github.js.map +1 -1
  58. package/dist/src/githubtoken.js +346 -0
  59. package/dist/src/githubtoken.js.map +1 -0
  60. package/dist/src/home/adapters.js +349 -0
  61. package/dist/src/home/adapters.js.map +1 -0
  62. package/dist/src/home/advanced.js +318 -0
  63. package/dist/src/home/advanced.js.map +1 -0
  64. package/dist/src/home/advancedtools.js +57 -0
  65. package/dist/src/home/advancedtools.js.map +1 -0
  66. package/dist/src/home/autoreview.js +325 -0
  67. package/dist/src/home/autoreview.js.map +1 -0
  68. package/dist/src/home/daemonstatus.js +32 -0
  69. package/dist/src/home/daemonstatus.js.map +1 -0
  70. package/dist/src/home/devicelogin.js +61 -0
  71. package/dist/src/home/devicelogin.js.map +1 -0
  72. package/dist/src/home/launch.js +202 -0
  73. package/dist/src/home/launch.js.map +1 -0
  74. package/dist/src/home/loginowner.js +205 -0
  75. package/dist/src/home/loginowner.js.map +1 -0
  76. package/dist/src/home/memory.js +122 -0
  77. package/dist/src/home/memory.js.map +1 -0
  78. package/dist/src/home/model.js +811 -0
  79. package/dist/src/home/model.js.map +1 -0
  80. package/dist/src/home/panel.js +520 -0
  81. package/dist/src/home/panel.js.map +1 -0
  82. package/dist/src/home/ports.js +19 -0
  83. package/dist/src/home/ports.js.map +1 -0
  84. package/dist/src/home/review.js +163 -0
  85. package/dist/src/home/review.js.map +1 -0
  86. package/dist/src/home/reviews.js +478 -0
  87. package/dist/src/home/reviews.js.map +1 -0
  88. package/dist/src/home/setup.js +507 -0
  89. package/dist/src/home/setup.js.map +1 -0
  90. package/dist/src/home/setupadapters.js +214 -0
  91. package/dist/src/home/setupadapters.js.map +1 -0
  92. package/dist/src/home/setupcard.js +199 -0
  93. package/dist/src/home/setupcard.js.map +1 -0
  94. package/dist/src/home/setuptools.js +45 -0
  95. package/dist/src/home/setuptools.js.map +1 -0
  96. package/dist/src/home/spend.js +160 -0
  97. package/dist/src/home/spend.js.map +1 -0
  98. package/dist/src/home/switches.js +209 -0
  99. package/dist/src/home/switches.js.map +1 -0
  100. package/dist/src/home/switchon.js +439 -0
  101. package/dist/src/home/switchon.js.map +1 -0
  102. package/dist/src/home/toolnames.js +41 -0
  103. package/dist/src/home/toolnames.js.map +1 -0
  104. package/dist/src/home/tune.js +341 -0
  105. package/dist/src/home/tune.js.map +1 -0
  106. package/dist/src/home/words.js +7 -0
  107. package/dist/src/home/words.js.map +1 -0
  108. package/dist/src/homes.js +14 -0
  109. package/dist/src/homes.js.map +1 -1
  110. package/dist/src/install.js +1 -1
  111. package/dist/src/install.js.map +1 -1
  112. package/dist/src/ipc/workerspec.js +8 -0
  113. package/dist/src/ipc/workerspec.js.map +1 -1
  114. package/dist/src/live/publish.js +1 -1
  115. package/dist/src/live/publish.js.map +1 -1
  116. package/dist/src/livecli.js +1 -1
  117. package/dist/src/livecli.js.map +1 -1
  118. package/dist/src/loginhint.js +8 -3
  119. package/dist/src/loginhint.js.map +1 -1
  120. package/dist/src/loginrefresh/handover.js +121 -0
  121. package/dist/src/loginrefresh/handover.js.map +1 -0
  122. package/dist/src/loginrefresh/lock.js +54 -3
  123. package/dist/src/loginrefresh/lock.js.map +1 -1
  124. package/dist/src/loginrefresh/pirefresh.js +3 -0
  125. package/dist/src/loginrefresh/pirefresh.js.map +1 -1
  126. package/dist/src/loginrefresh/refresher.js +33 -5
  127. package/dist/src/loginrefresh/refresher.js.map +1 -1
  128. package/dist/src/loginrefresh/supervisor.js +18 -1
  129. package/dist/src/loginrefresh/supervisor.js.map +1 -1
  130. package/dist/src/npmverbs.js +46 -14
  131. package/dist/src/npmverbs.js.map +1 -1
  132. package/dist/src/onboard/choices.js +35 -4
  133. package/dist/src/onboard/choices.js.map +1 -1
  134. package/dist/src/onboard/engine.js +32 -306
  135. package/dist/src/onboard/engine.js.map +1 -1
  136. package/dist/src/onboard/pipin.js +22 -0
  137. package/dist/src/onboard/pipin.js.map +1 -0
  138. package/dist/src/onboard/stepforward.js +41 -0
  139. package/dist/src/onboard/stepforward.js.map +1 -0
  140. package/dist/src/onboard/steps/appslug.js +4 -1
  141. package/dist/src/onboard/steps/appslug.js.map +1 -1
  142. package/dist/src/onboard/steps/bringup.js +3 -2
  143. package/dist/src/onboard/steps/bringup.js.map +1 -1
  144. package/dist/src/onboard/steps/compose.js +29 -0
  145. package/dist/src/onboard/steps/compose.js.map +1 -1
  146. package/dist/src/onboard/steps/configfill.js +120 -39
  147. package/dist/src/onboard/steps/configfill.js.map +1 -1
  148. package/dist/src/onboard/steps/githubaccount.js +595 -0
  149. package/dist/src/onboard/steps/githubaccount.js.map +1 -0
  150. package/dist/src/onboard/steps/githubapp.js +65 -7
  151. package/dist/src/onboard/steps/githubapp.js.map +1 -1
  152. package/dist/src/onboard/steps/golive.js +2 -0
  153. package/dist/src/onboard/steps/golive.js.map +1 -1
  154. package/dist/src/onboard/steps/index.js +11 -0
  155. package/dist/src/onboard/steps/index.js.map +1 -1
  156. package/dist/src/onboard/steps/ingress.js +80 -25
  157. package/dist/src/onboard/steps/ingress.js.map +1 -1
  158. package/dist/src/onboard/steps/llmauth.js +103 -30
  159. package/dist/src/onboard/steps/llmauth.js.map +1 -1
  160. package/dist/src/onboard/steps/loginshare.js +213 -0
  161. package/dist/src/onboard/steps/loginshare.js.map +1 -0
  162. package/dist/src/onboard/steps/memory.js +67 -3
  163. package/dist/src/onboard/steps/memory.js.map +1 -1
  164. package/dist/src/onboard/steps/proof.js +366 -56
  165. package/dist/src/onboard/steps/proof.js.map +1 -1
  166. package/dist/src/onboard/steps/repoconfig.js +72 -0
  167. package/dist/src/onboard/steps/repoconfig.js.map +1 -0
  168. package/dist/src/onboard/steps/topology.js +6 -6
  169. package/dist/src/onboard/steps/topology.js.map +1 -1
  170. package/dist/src/onboard/steps/transport.js +9 -1
  171. package/dist/src/onboard/steps/transport.js.map +1 -1
  172. package/dist/src/onboard/steps/tuiroute.js +102 -0
  173. package/dist/src/onboard/steps/tuiroute.js.map +1 -0
  174. package/dist/src/onboard/steps/verifyup.js +17 -1
  175. package/dist/src/onboard/steps/verifyup.js.map +1 -1
  176. package/dist/src/onboard/toolnames.js +30 -0
  177. package/dist/src/onboard/toolnames.js.map +1 -0
  178. package/dist/src/operatorwrite.js +23 -0
  179. package/dist/src/operatorwrite.js.map +1 -0
  180. package/dist/src/outcomes.js +4 -1
  181. package/dist/src/outcomes.js.map +1 -1
  182. package/dist/src/piagentdir.js +13 -0
  183. package/dist/src/piagentdir.js.map +1 -0
  184. package/dist/src/pilogin.js +31 -16
  185. package/dist/src/pilogin.js.map +1 -1
  186. package/dist/src/posting-journal.js +2 -1
  187. package/dist/src/posting-journal.js.map +1 -1
  188. package/dist/src/posting-outbox.js +6 -2
  189. package/dist/src/posting-outbox.js.map +1 -1
  190. package/dist/src/posting-receipt.js +14 -1
  191. package/dist/src/posting-receipt.js.map +1 -1
  192. package/dist/src/qcrbin.js +16 -11
  193. package/dist/src/qcrbin.js.map +1 -1
  194. package/dist/src/recheck.js +2 -1
  195. package/dist/src/recheck.js.map +1 -1
  196. package/dist/src/reconcile.js +22 -2
  197. package/dist/src/reconcile.js.map +1 -1
  198. package/dist/src/reviewargs.js +122 -0
  199. package/dist/src/reviewargs.js.map +1 -0
  200. package/dist/src/reviewcli.js +7 -161
  201. package/dist/src/reviewcli.js.map +1 -1
  202. package/dist/src/reviewdetach.js +76 -11
  203. package/dist/src/reviewdetach.js.map +1 -1
  204. package/dist/src/reviewhistory.js +32 -6
  205. package/dist/src/reviewhistory.js.map +1 -1
  206. package/dist/src/reviewnow.js +45 -0
  207. package/dist/src/reviewnow.js.map +1 -0
  208. package/dist/src/scancli.js +39 -691
  209. package/dist/src/scancli.js.map +1 -1
  210. package/dist/src/selfimprove.js +66 -0
  211. package/dist/src/selfimprove.js.map +1 -0
  212. package/dist/src/setup/adapters.js +5 -223
  213. package/dist/src/setup/adapters.js.map +1 -1
  214. package/dist/src/setup/caserunner.js +15 -249
  215. package/dist/src/setup/caserunner.js.map +1 -1
  216. package/dist/src/setup/engine.js +32 -341
  217. package/dist/src/setup/engine.js.map +1 -1
  218. package/dist/src/setup/facts.js +3 -592
  219. package/dist/src/setup/facts.js.map +1 -1
  220. package/dist/src/setup/findings.js +3 -947
  221. package/dist/src/setup/findings.js.map +1 -1
  222. package/dist/src/setup/presentation.js +3 -8
  223. package/dist/src/setup/presentation.js.map +1 -1
  224. package/dist/src/setup/scan.js +3 -724
  225. package/dist/src/setup/scan.js.map +1 -1
  226. package/dist/src/setup/scanbuild.js +9 -92
  227. package/dist/src/setup/scanbuild.js.map +1 -1
  228. package/dist/src/setup/scanlease.js +3 -250
  229. package/dist/src/setup/scanlease.js.map +1 -1
  230. package/dist/src/setup/scanreport.js +3 -288
  231. package/dist/src/setup/scanreport.js.map +1 -1
  232. package/dist/src/setup/scanrun.js +3 -1732
  233. package/dist/src/setup/scanrun.js.map +1 -1
  234. package/dist/src/setup/scantree.js +3 -256
  235. package/dist/src/setup/scantree.js.map +1 -1
  236. package/dist/src/setup/stage2request.js +3 -258
  237. package/dist/src/setup/stage2request.js.map +1 -1
  238. package/dist/src/setup/unitcut.js +3 -436
  239. package/dist/src/setup/unitcut.js.map +1 -1
  240. package/dist/src/state.js +2 -0
  241. package/dist/src/state.js.map +1 -1
  242. package/dist/src/statemachine.js +4 -1
  243. package/dist/src/statemachine.js.map +1 -1
  244. package/dist/src/takeover.js +1 -0
  245. package/dist/src/takeover.js.map +1 -1
  246. package/dist/src/takeoverpi.js +15 -1
  247. package/dist/src/takeoverpi.js.map +1 -1
  248. package/dist/src/tui/app.js +49 -0
  249. package/dist/src/tui/app.js.map +1 -1
  250. package/dist/src/tui/board.js +88 -12
  251. package/dist/src/tui/board.js.map +1 -1
  252. package/dist/src/tui/cmdbar.js +4 -1
  253. package/dist/src/tui/cmdbar.js.map +1 -1
  254. package/dist/src/tui/companion.js +76 -11
  255. package/dist/src/tui/companion.js.map +1 -1
  256. package/dist/src/tui/connect.js +7 -1
  257. package/dist/src/tui/connect.js.map +1 -1
  258. package/dist/src/tui/deploytab.js +2 -2
  259. package/dist/src/tui/deploytab.js.map +1 -1
  260. package/dist/src/tui/filters.js +5 -2
  261. package/dist/src/tui/filters.js.map +1 -1
  262. package/dist/src/tui/ghread.js +61 -5
  263. package/dist/src/tui/ghread.js.map +1 -1
  264. package/dist/src/tui/index.js +109 -20
  265. package/dist/src/tui/index.js.map +1 -1
  266. package/dist/src/tui/memforward.js +39 -2
  267. package/dist/src/tui/memforward.js.map +1 -1
  268. package/dist/src/tui/memory.js +3 -16
  269. package/dist/src/tui/memory.js.map +1 -1
  270. package/dist/src/tui/memoryurl.js +22 -0
  271. package/dist/src/tui/memoryurl.js.map +1 -0
  272. package/dist/src/tui/model.js +25 -0
  273. package/dist/src/tui/model.js.map +1 -1
  274. package/dist/src/tui/prpause.js +7 -0
  275. package/dist/src/tui/prpause.js.map +1 -1
  276. package/dist/src/tui/remote.js +7 -1
  277. package/dist/src/tui/remote.js.map +1 -1
  278. package/dist/src/tui/route.js +143 -0
  279. package/dist/src/tui/route.js.map +1 -0
  280. package/dist/src/tui/setupstate.js +32 -0
  281. package/dist/src/tui/setupstate.js.map +1 -0
  282. package/dist/src/tui/sshtriage.js +102 -5
  283. package/dist/src/tui/sshtriage.js.map +1 -1
  284. package/dist/src/tui/theme.js +2 -1
  285. package/dist/src/tui/theme.js.map +1 -1
  286. package/dist/src/tui/unwedge.js +2 -12
  287. package/dist/src/tui/unwedge.js.map +1 -1
  288. package/dist/src/verdicts.js +17 -5
  289. package/dist/src/verdicts.js.map +1 -1
  290. package/dist/src/version.js +1 -1
  291. package/dist/src/version.js.map +1 -1
  292. package/dist/src/webhook.js +12 -1
  293. package/dist/src/webhook.js.map +1 -1
  294. package/dist/src/wire.js +34 -8
  295. package/dist/src/wire.js.map +1 -1
  296. package/dist/src/workerworld.js +11 -1
  297. package/dist/src/workerworld.js.map +1 -1
  298. package/docker/README.md +1 -1
  299. package/docker/companion/entrypoint.sh +20 -1
  300. package/docker/entrypoint.sh +57 -6
  301. package/docker-compose.yml +16 -1
  302. package/extensions/cli/home.ts +14 -0
  303. package/extensions/cli/login-route.ts +10 -0
  304. package/extensions/cli/selfimprove.ts +18 -0
  305. package/extensions/home.ts +484 -0
  306. package/extensions/login-route.ts +220 -0
  307. package/extensions/onboarding.ts +41 -11
  308. package/extensions/selfimprove.ts +65 -0
  309. package/extensions/setup-scan.ts +79 -766
  310. package/extensions/setup.ts +14 -70
  311. package/package.json +6 -4
  312. package/prompts/onboarding.md +58 -18
  313. package/schemas/review-result.v1.json +60 -0
  314. package/scripts/deploy.sh +8 -6
  315. package/scripts/mint-token.sh +25 -4
  316. package/scripts/qcr-host.sh +28 -5
  317. package/scripts/vm-ghcr-login.sh +7 -4
  318. package/src/archive/restore.ts +18 -21
  319. package/src/botworker.ts +13 -2
  320. package/src/channelfs.ts +3 -26
  321. package/src/ciretry.ts +2 -1
  322. package/src/cli.ts +59 -67
  323. package/src/cliops.ts +3 -2
  324. package/src/commands.ts +28 -2
  325. package/src/config.ts +62 -4
  326. package/src/daemon.ts +58 -7
  327. package/src/debuground.ts +3 -0
  328. package/src/debugroundpi.ts +12 -1
  329. package/src/dispatch.ts +5 -4
  330. package/src/engine/caserunner-sdk.ts +29 -314
  331. package/src/engine/debugpi.ts +17 -5
  332. package/src/execboundary.ts +16 -4
  333. package/src/github.ts +57 -15
  334. package/src/githubtoken.ts +435 -0
  335. package/src/home/adapters.ts +418 -0
  336. package/src/home/advanced.ts +421 -0
  337. package/src/home/advancedtools.ts +96 -0
  338. package/src/home/autoreview.ts +385 -0
  339. package/src/home/daemonstatus.ts +55 -0
  340. package/src/home/devicelogin.ts +107 -0
  341. package/src/home/launch.ts +257 -0
  342. package/src/home/loginowner.ts +248 -0
  343. package/src/home/memory.ts +176 -0
  344. package/src/home/model.ts +965 -0
  345. package/src/home/panel.ts +666 -0
  346. package/src/home/ports.ts +338 -0
  347. package/src/home/review.ts +206 -0
  348. package/src/home/reviews.ts +565 -0
  349. package/src/home/setup.ts +689 -0
  350. package/src/home/setupadapters.ts +217 -0
  351. package/src/home/setupcard.ts +288 -0
  352. package/src/home/setuptools.ts +57 -0
  353. package/src/home/spend.ts +194 -0
  354. package/src/home/switches.ts +293 -0
  355. package/src/home/switchon.ts +554 -0
  356. package/src/home/toolnames.ts +46 -0
  357. package/src/home/tune.ts +405 -0
  358. package/src/home/words.ts +8 -0
  359. package/src/homes.ts +17 -0
  360. package/src/install.ts +1 -1
  361. package/src/ipc/workerspec.ts +15 -0
  362. package/src/live/publish.ts +4 -1
  363. package/src/livecli.ts +6 -1
  364. package/src/loginhint.ts +8 -3
  365. package/src/loginrefresh/handover.ts +138 -0
  366. package/src/loginrefresh/lock.ts +72 -3
  367. package/src/loginrefresh/pirefresh.ts +3 -0
  368. package/src/loginrefresh/refresher.ts +34 -5
  369. package/src/loginrefresh/supervisor.ts +25 -2
  370. package/src/npmverbs.ts +55 -13
  371. package/src/onboard/choices.ts +40 -4
  372. package/src/onboard/engine.ts +70 -421
  373. package/src/onboard/pipin.ts +31 -0
  374. package/src/onboard/stepforward.ts +61 -0
  375. package/src/onboard/steps/appslug.ts +4 -1
  376. package/src/onboard/steps/bringup.ts +3 -2
  377. package/src/onboard/steps/compose.ts +31 -0
  378. package/src/onboard/steps/configfill.ts +144 -40
  379. package/src/onboard/steps/githubaccount.ts +716 -0
  380. package/src/onboard/steps/githubapp.ts +92 -8
  381. package/src/onboard/steps/golive.ts +2 -0
  382. package/src/onboard/steps/index.ts +11 -0
  383. package/src/onboard/steps/ingress.ts +98 -31
  384. package/src/onboard/steps/llmauth.ts +114 -29
  385. package/src/onboard/steps/loginshare.ts +258 -0
  386. package/src/onboard/steps/memory.ts +76 -3
  387. package/src/onboard/steps/proof.ts +473 -55
  388. package/src/onboard/steps/repoconfig.ts +85 -0
  389. package/src/onboard/steps/topology.ts +7 -6
  390. package/src/onboard/steps/transport.ts +15 -0
  391. package/src/onboard/steps/tuiroute.ts +119 -0
  392. package/src/onboard/steps/verifyup.ts +20 -1
  393. package/src/onboard/toolnames.ts +34 -0
  394. package/src/operatorwrite.ts +25 -0
  395. package/src/outcomes.ts +8 -1
  396. package/src/piagentdir.ts +12 -0
  397. package/src/pilogin.ts +32 -16
  398. package/src/posting-journal.ts +6 -1
  399. package/src/posting-outbox.ts +10 -2
  400. package/src/posting-receipt.ts +17 -0
  401. package/src/qcrbin.ts +16 -11
  402. package/src/recheck.ts +2 -1
  403. package/src/reconcile.ts +29 -3
  404. package/src/reviewargs.ts +119 -0
  405. package/src/reviewcli.ts +6 -167
  406. package/src/reviewdetach.ts +107 -13
  407. package/src/reviewhistory.ts +20 -6
  408. package/src/reviewnow.ts +76 -0
  409. package/src/scancli.ts +75 -826
  410. package/src/selfimprove.ts +90 -0
  411. package/src/setup/adapters.ts +13 -221
  412. package/src/setup/caserunner.ts +34 -273
  413. package/src/setup/engine.ts +62 -496
  414. package/src/setup/facts.ts +3 -627
  415. package/src/setup/findings.ts +3 -1264
  416. package/src/setup/presentation.ts +3 -18
  417. package/src/setup/scan.ts +3 -1033
  418. package/src/setup/scanbuild.ts +20 -114
  419. package/src/setup/scanlease.ts +3 -297
  420. package/src/setup/scanreport.ts +3 -373
  421. package/src/setup/scanrun.ts +3 -2268
  422. package/src/setup/scantree.ts +3 -259
  423. package/src/setup/stage2request.ts +3 -347
  424. package/src/setup/unitcut.ts +3 -523
  425. package/src/state.ts +43 -0
  426. package/src/statemachine.ts +4 -1
  427. package/src/takeover.ts +5 -0
  428. package/src/takeoverpi.ts +16 -2
  429. package/src/tui/app.ts +47 -0
  430. package/src/tui/board.ts +111 -14
  431. package/src/tui/cmdbar.ts +4 -1
  432. package/src/tui/companion.ts +80 -11
  433. package/src/tui/connect.ts +7 -1
  434. package/src/tui/deploytab.ts +2 -2
  435. package/src/tui/filters.ts +7 -3
  436. package/src/tui/ghread.ts +74 -7
  437. package/src/tui/index.ts +117 -23
  438. package/src/tui/memforward.ts +52 -3
  439. package/src/tui/memory.ts +3 -15
  440. package/src/tui/memoryurl.ts +22 -0
  441. package/src/tui/model.ts +36 -2
  442. package/src/tui/prpause.ts +11 -2
  443. package/src/tui/remote.ts +9 -1
  444. package/src/tui/route.ts +173 -0
  445. package/src/tui/setupstate.ts +56 -0
  446. package/src/tui/sshtriage.ts +127 -6
  447. package/src/tui/theme.ts +2 -1
  448. package/src/tui/unwedge.ts +2 -14
  449. package/src/verdicts.ts +23 -5
  450. package/src/version.ts +1 -1
  451. package/src/webhook.ts +10 -1
  452. package/src/wire.ts +42 -9
  453. package/src/workerworld.ts +16 -2
  454. package/dist/src/live/projection.js +0 -450
  455. package/dist/src/live/projection.js.map +0 -1
  456. package/dist/src/live/read.js +0 -60
  457. package/dist/src/live/read.js.map +0 -1
  458. package/dist/src/onboard/launch.js +0 -83
  459. package/dist/src/onboard/launch.js.map +0 -1
  460. package/dist/src/setup/ledger.js +0 -207
  461. package/dist/src/setup/ledger.js.map +0 -1
  462. package/dist/src/setup/stage2.js +0 -617
  463. package/dist/src/setup/stage2.js.map +0 -1
  464. package/dist/src/setup/textsniff.js +0 -89
  465. package/dist/src/setup/textsniff.js.map +0 -1
  466. package/src/live/projection.ts +0 -491
  467. package/src/live/read.ts +0 -86
  468. package/src/onboard/launch.ts +0 -115
  469. package/src/setup/ledger.ts +0 -324
  470. package/src/setup/stage2.ts +0 -926
  471. package/src/setup/textsniff.ts +0 -95
package/README.md CHANGED
@@ -18,17 +18,27 @@ for one kind of problem and never see each other's output. It merges their
18
18
  findings so one root cause gets one comment, and an **adversarial validator
19
19
  re-derives every candidate from the code** before one review is posted.
20
20
 
21
+ <picture>
22
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-hero-dark.png">
23
+ <img src="docs/media/bench-hero.png" alt="AACR-Bench, 185 real PRs, 520 verified defects, QuickReview on GPT-6.1 Sol against six other reviewers, share found at each severity. High (90 defects): QuickReview 97%, next best Codex CLI 90%. Medium (145): QuickReview 93%, next best pi-review panel 82%. Low (285): QuickReview 84%, next best pi-review panel 52%.">
24
+ </picture>
25
+
26
+ On 185 real PRs with 520 defects each verified in the code, QuickReview on
27
+ GPT-6.1 Sol finds **97% of the high-severity defects, 93% of the medium and
28
+ 84% of the low**; at each severity the best of the six other reviewers we ran
29
+ finds 90%, 82% and 52%. On the same model it also finds more than the model
30
+ maker's own reviewer at every severity: against Claude Code's `/code-review`
31
+ on Claude Opus 5.5 and against Codex CLI on GPT-6.1 Sol. Its last changes were
32
+ mined from its misses on 145 of the 185 PRs; on the 20 kept out, it finds 83%
33
+ of all defects and the next best 72%. That recall costs more: about $2 and
34
+ 17.5 minutes per PR, where the other tools take $0.07–0.53 and 0.7–2.3
35
+ minutes ([Benchmarks](#benchmarks)).
36
+
21
37
  <p align="center">
22
38
  <img src="docs/media/lenses.gif" width="800"
23
39
  alt="Animation: nine lens passes sweep the same diff in parallel, each marking the lines where it finds a problem; findings that share a root cause merge, eight candidates into six causes; the validator re-derives each from the code, keeps four and strikes two with a reason (below the bar; refuted); the four survivors become one posted review, three blockers and one question, marked REQUEST_CHANGES.">
24
40
  </p>
25
41
 
26
- On 185 real PRs with 520 defects each verified in the code, it finds
27
- **97% of the high-severity defects and 89% of all of them**; the strongest
28
- third-party configuration we measured finds 67%. That recall costs more:
29
- about $2 and 17 minutes per PR, where the other tools take $0.07–0.53 and
30
- 0.7–2.3 minutes ([Benchmarks](#benchmarks)).
31
-
32
42
  Around the review sits a small, deterministic TypeScript daemon with no LLM
33
43
  in its decision path. It takes GitHub App webhooks, runs an authoritative
34
44
  reconcile poll, keeps one sticky [pi](https://github.com/earendil-works/pi)
@@ -70,22 +80,37 @@ The lens catalogue, with each lens's trigger and severity cap, is §3.3 of the
70
80
 
71
81
  Recall is the headline: a review that misses the defect has failed, whatever
72
82
  else it does. Precision, cost and time are shown beside it, because that is
73
- where QuickReview pays. Its results are the frozen build of 2026-10-04 on
74
- `gpt-6.1-sol`, shipped defaults, one review per PR. The third-party tools we
75
- ran used the best configuration we found for each, the OpenAI-based ones on
76
- the same model, under the same judge on the same PRs.
83
+ where QuickReview pays. Unless a chart or table names another build or model,
84
+ its results are the frozen build of 2026-10-04 on `gpt-6.1-sol`, shipped
85
+ defaults, one review per PR. The third-party tools we ran used the best
86
+ configuration we found for each (except Claude Code, which ran `/code-review`
87
+ at its default effort and was not varied), the OpenAI-based ones on the same
88
+ model, under the same judge on the same PRs.
89
+
90
+ **AACR-Bench, verified defects.** AACR-Bench's own reference comments are
91
+ mostly not real problems, so we built a key of 520 defects, each verified in
92
+ the code and graded by its consequence: **high** would block a merge (a
93
+ user-visible bug on a normal path, a crash, data loss, a security hole, a
94
+ broken build), **medium** should be fixed before merge, **low** is real but
95
+ fine as a follow-up. The chart at the top is this key. QuickReview misses 2.5
96
+ of the 90 high-severity defects, 10.5 of the 145 medium and 46 of the 285 low
97
+ (a partly found defect counts as half); the best other reviewer at each
98
+ severity misses 9, 26 and 136.5. Over the panel and Codex CLI the
99
+ high-severity lead holds under a paired bootstrap (+8.3 points [+1.9, +14.6]
100
+ over the panel). The price: 6.9 comments per PR, 42% of them true but minor.
77
101
 
78
102
  <picture>
79
- <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-aacr-dark.png">
80
- <img src="docs/media/bench-aacr.png" alt="AACR-Bench, 185 PRs, 520 verified defects. Share of high-severity defects found: QuickReview 97%, Codex CLI 90%, pi-review panel 89%, OpenCode 84%, Claude Code 81%, open-code-review 71%, PR-Agent 62%. Share of all defects found: QuickReview 89%, pi-review panel 67%, Claude Code 62%, open-code-review 57%, Codex CLI 55%, OpenCode 51%, PR-Agent 37%.">
103
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-same-model-dark.png">
104
+ <img src="docs/media/bench-same-model.png" alt="AACR-Bench, the same base model in two reviewers, one judge, share found at high, medium and low severity. Claude Opus 5.5, 40 PRs: QuickReview 94%, 98%, 93%; Claude Code /code-review 75%, 71%, 45%. GPT-6.1 Sol, 185 PRs: QuickReview 97%, 93%, 84%; Codex CLI at high 90%, 70%, 37%. GPT-6 Sol, 185 PRs: QuickReview 96%, 86%, 80%; Codex CLI as shipped 78%, 61%, 31%.">
81
105
  </picture>
82
106
 
83
- **AACR-Bench, verified defects.** AACR-Bench's own reference comments are
84
- mostly not real problems, so we built a key of 520 defects, each verified in
85
- the code, and a judge for it. Over the panel and Codex CLI the lead holds
86
- under a paired bootstrap on high and on high + medium defects (+8.3 points
87
- [+1.9, +14.6] on high over the panel). The price: 6.9 comments per PR, 42%
88
- of them true but minor.
107
+ **Same model, two reviewers.** With the model held fixed, QuickReview still
108
+ finds more than the model maker's own reviewer on each of the three models
109
+ where we ran both, at 11 to 20 times the cost ($3.24 against $0.16 per PR on
110
+ Opus). This contrasts two tools, not a measured design effect: they also
111
+ differ in budget and inputs, Claude Code ran `/code-review` at its default
112
+ effort, the Opus and GPT-6 Sol rows are September builds of QuickReview, and
113
+ the 40 Opus PRs are all PRs QuickReview was tuned on.
89
114
 
90
115
  <picture>
91
116
  <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-martian-dark.png">
@@ -97,7 +122,7 @@ per PR and counts every other comment as a false positive. It extracts about
97
122
  12.8 issues per PR from QuickReview's reviews, so QuickReview has the highest
98
123
  recall and the lowest precision. We
99
124
  audited the goldens: of the 86 that describe a real defect the PR
100
- introduces, it finds 75 (87%), the most of any tool.
125
+ introduces, it finds 75 (87%), the most of the seven reviewers judged alike.
101
126
 
102
127
  <picture>
103
128
  <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-qodo-dark.png">
@@ -109,20 +134,57 @@ and 271 violations of rules written in the repo. QuickReview finds the most
109
134
  functional bugs of the thirteen tools (52.1%) and the second-most issues
110
135
  overall, at the lowest precision; it is fourth on F1.
111
136
 
137
+ <picture>
138
+ <source media="(prefers-color-scheme: dark)" srcset="docs/media/bench-elo-dark.png">
139
+ <img src="docs/media/bench-elo.png" alt="Pairwise Elo on the 20 Martian PRs where QuickReview on GPT-6.1 Sol or DeepSeek did worst, two judges pooled, with 95% intervals. Claude Code max, Opus 5.5 directing Sonnet 5.5 agents, 1666, QuickReview on Opus 5.5 1628, QuickReview on GPT-6.1 Sol 1566, Claude Code high on Opus 5.5 1518, QuickReview on Sonnet 5.5 1489, QuickReview on DeepSeek V4.1 Flash 1406, Claude Code high on Sonnet 5.5 1398, QuickReview on GLM-5.3 Flash 1329.">
140
+ </picture>
141
+
142
+ **Judged side by side.** A pairwise judge reads two reviews of the same PR
143
+ blind and picks the better one. GPT-6.1 Sol and Claude Opus 5.5 both judged,
144
+ and a Bradley-Terry fit over their 596 verdicts gives Elo; alone, the two
145
+ judges pick the same winner only 56% of the time, which is why they are
146
+ pooled. On the 20 Martian PRs where QuickReview on GPT-6.1 Sol or DeepSeek did
147
+ worst, QuickReview on Opus 5.5 (six of its lenses on GPT-6 Luna) beat Claude
148
+ Code's `/code-review` at high effort on Opus 5.5 in 29 of 40 verdicts, at more
149
+ than ten times its cost (about $4 per PR). Only Claude Code's max mode (Opus
150
+ 5.5 directing Sonnet 5.5 agents, about $20 per PR) ranks higher, by a margin
151
+ inside the intervals.
152
+
153
+ **Other models.** QuickReview's models are configurable. On AACR-Bench
154
+ it holds most of its recall on cheap open models, and it falls apart on a
155
+ weak one:
156
+
157
+ | QuickReview on | PRs | High (90) | Medium (145) | Low (285) | All (520) | $/PR | Judge |
158
+ |---|---|---|---|---|---|---|---|
159
+ | GPT-6.1 Sol (frozen build) | 185 | 87.5 (97%) | 134.5 (93%) | 239 (84%) | 461 (89%) | 2.06 | gpt-6-sol |
160
+ | DeepSeek V4.1 Flash (mostly low effort) | 185 | 83 (92%) | 131 (90%) | 237.5 (83%) | 451.5 (87%) | 0.74 | gpt-6.1-sol |
161
+ | GLM-5.3 Flash | 185 | 83 (92%) | 120.5 (83%) | 231.5 (81%) | 435 (84%) | 0.52 | gpt-6.1-sol |
162
+ | GPT-6 Luna | 185 | 39 (43%) | 44 (30%) | 64 (22%) | 147 (28%) | 0.04 | gpt-6-sol |
163
+ | Claude Opus 5.5 | 40 | 32/34 (94%) | 30.5/31 (98%) | 57/61 (93%) | 119.5/126 (95%) | 3.24 | gpt-6-sol |
164
+
165
+ The best third-party reviewer at each severity finds 81 of 90 high (Codex
166
+ CLI), 119 of 145 medium and 148.5 of 285 low (both the pi-review panel). The
167
+ open-model rows ran a later build (mid-October, with cost changes made after
168
+ the freeze) and a later judge; DeepSeek ran at low reasoning effort on 143 of
169
+ its PRs, and GLM's review was missing a lens pass on 7. The GPT-6 Luna and
170
+ Opus rows ran a September build; on the same 40 PRs as Opus, the frozen
171
+ GPT-6.1 Sol build finds 33 of 34 high, 28 of 31 medium and 44 of 61 low. Read
172
+ the table as directional.
173
+
112
174
  <details>
113
175
  <summary>The full tables</summary>
114
176
 
115
177
  **AACR-Bench** (185 PRs, 10 languages, 520 verified defects; a partly found defect counts ½)
116
178
 
117
- | Reviewer | High (90) | High + medium (235) | All (520) | Comments correct | $/PR | Median min/PR |
118
- |---|---|---|---|---|---|---|
119
- | **QuickReview** | **87.5 (97%)** | **222 (94.5%)** | **461 (89%)** | 92% | 2.06 | 17.5 |
120
- | pi-review panel (high) | 80 (89%) | 199 (85%) | 347.5 (67%) | 89% | 0.27 | 1.8 |
121
- | Claude Code (Opus 5.5) | 72.5 (81%) | 177.5 (76%) | 324.5 (62%) | 81% | 0.20 | 0.7 |
122
- | open-code-review (high) | 63.5 (71%) | 165.5 (70%) | 298.5 (57%) | 86% | 0.53 | 1.8 |
123
- | Codex CLI (high) | 81 (90%) | 182.5 (78%) | 287 (55%) | 93% | 0.14 | 2.1 |
124
- | OpenCode (+ PR text) | 76 (84%) | 175 (74%) | 263.5 (51%) | 93% | 0.17 | 2.3 |
125
- | PR-Agent | 55.5 (62%) | 125.5 (53%) | 194 (37%) | 76% | 0.07 | 1.9 |
179
+ | Reviewer | High (90) | Medium (145) | Low (285) | All (520) | Comments correct | $/PR | Median min/PR |
180
+ |---|---|---|---|---|---|---|---|
181
+ | **QuickReview** | **87.5 (97%)** | **134.5 (93%)** | **239 (84%)** | **461 (89%)** | 92% | 2.06 | 17.5 |
182
+ | pi-review panel (high) | 80 (89%) | 119 (82%) | 148.5 (52%) | 347.5 (67%) | 89% | 0.27 | 1.8 |
183
+ | Claude Code (Opus 5.5) | 72.5 (81%) | 105 (72%) | 147 (52%) | 324.5 (62%) | 81% | 0.20 | 0.7 |
184
+ | open-code-review (high) | 63.5 (71%) | 102 (70%) | 133 (47%) | 298.5 (57%) | 86% | 0.53 | 1.8 |
185
+ | Codex CLI (high) | 81 (90%) | 101.5 (70%) | 104.5 (37%) | 287 (55%) | 93% | 0.14 | 2.1 |
186
+ | OpenCode (+ PR text) | 76 (84%) | 99 (68%) | 88.5 (31%) | 263.5 (51%) | 93% | 0.17 | 2.3 |
187
+ | PR-Agent | 55.5 (62%) | 70 (48%) | 68.5 (24%) | 194 (37%) | 76% | 0.07 | 1.9 |
126
188
 
127
189
  **Martian** (50 PRs, Core; one `gpt-6.1-sol` judge for every row, the vendor rows re-judged from their published comments)
128
190
 
@@ -154,8 +216,8 @@ overall, at the lowest precision; it is fourth on F1.
154
216
  **Held-out PRs.** The last tuning round was mined from misses on part of
155
217
  each benchmark. On the PRs kept out of it, the frozen build finds 83% of
156
218
  AACR-Bench's defects (20 PRs), ties qodo-extended-v2 on Martian's real
157
- goldens (43 of 52, 30 PRs), and reaches 60.3% recall and F1 53.0 on Qodo
158
- (31 PRs), against 51.3 for qodo-exhaustive.
219
+ goldens (43 of 52, 30 PRs), and on Qodo (31 PRs) reaches 60.3% recall and
220
+ F1 53.0, level with qodo-exhaustive's 51.3.
159
221
 
160
222
  **Read more.** Two papers carry the method, every table and the threats to
161
223
  validity: [*Measuring whether a code review finds the real
@@ -223,9 +285,19 @@ Slack concierge, a local companion session, opt-in escalation notes, and the
223
285
 
224
286
  ## Quickstart
225
287
 
226
- You need **Docker** with Compose v2 and **a GitHub account that can create an
227
- App** on the repository to review. No personal access token is used. On
228
- Windows, run everything inside **WSL2**.
288
+ You need **Docker** with Compose v2, a model login, and either `gh` signed in
289
+ to your own GitHub account or **a GitHub account that can create an App** on
290
+ the repository to review. On Windows, run everything inside **WSL2**.
291
+
292
+ There is a second route that needs no App: `[github] auth = "user"` runs the
293
+ reviewer on **your own GitHub account**. Use it on one box where `gh` is
294
+ already signed in. It is polling-only, with no webhooks and no tunnel. Every
295
+ review it posts is a COMMENT that states its verdict, because an automated
296
+ verdict must never count as your approval and GitHub refuses either on your own
297
+ PR. Your token reaches the daemon only as the 0600 file
298
+ `<secrets dir>/github_token`, which `qcr github-token sync` refreshes from
299
+ `gh`. It never comes from the environment or a command line. On the App route
300
+ no personal access token is used.
229
301
 
230
302
  ```sh
231
303
  # once: install `qcr`, the host wrapper the image writes (docs/host-wrapper.md);
@@ -233,32 +305,38 @@ Windows, run everything inside **WSL2**.
233
305
  docker run --rm --user "$(id -u):$(id -g)" -v ~/.local/bin:/out \
234
306
  ghcr.io/quickchatai/quickreview:<version> install
235
307
 
236
- qcr onboard # the whole setup, guided
308
+ qcr # the home: sign in, connect GitHub, choose a repository
237
309
  ```
238
310
 
239
- `qcr onboard` is a pi agent that walks you through setup using named,
240
- deterministic tools whose results you see. It checks the machine, asks where
241
- the reviewer lives and which LLM route you use (a ChatGPT subscription or an
242
- OpenAI API key, [docs/llm-setup.md](docs/llm-setup.md)), **creates your
243
- GitHub App in one click** from a pinned manifest, wires the webhook ingress,
244
- mints the memory keys, brings the stack up, and then **watches a real review
245
- land in the dry-run record** on a PR you label. Only then does it offer to go
246
- live. It is resumable, and re-running it on a working install is a
247
- diagnostic. Every step: [docs/onboarding.md](docs/onboarding.md).
311
+ A bare `qcr` opens the **home**: QuickReview's own pi, with the plugin loaded
312
+ and a panel of your repository's open pull requests. On a first run the panel
313
+ is a short setup checklist, and anything already set up is found and skipped:
314
+ sign in to OpenAI with pi's device code (device-code login must be on in
315
+ ChatGPT → Settings → Security), check that `gh` is signed in, and choose a
316
+ repository from your recently pushed ones or paste any `owner/name` or URL.
317
+ `alt+n` runs the next step. The home then lists the pull requests, "To review"
318
+ and "Reviewed". `qcr tui` opens the admin TUI, and only it starts the
319
+ companion. Through the Docker wrapper the home runs in a container of its own:
320
+ its login is kept in the `qcr-login` volume, its config and sessions in the
321
+ `qcr-state` volume, and its `gh` uses the token the wrapper finds on this
322
+ machine (`GITHUB_TOKEN`, `GH_TOKEN` or `gh auth token`). The always-on daemon, a GitHub App, webhooks and a server over ssh
323
+ are the setup wizard's steps: [docs/onboarding.md](docs/onboarding.md).
248
324
 
249
325
  ### Where the reviewer lives
250
326
 
251
- - **A server over ssh (recommended)**, because a reviewer that is asleep
252
- reviews nothing. Setup rides the Ansible deploy
327
+ - **This computer**, in Docker ([docker/README.md](docker/README.md)): the
328
+ pick when the machine is itself an always-on server, such as a cloud VM;
329
+ on a laptop it reviews only while the machine is awake.
330
+ - **A server over ssh**, recommended when your own computer sleeps. Setup
331
+ rides the Ansible deploy
253
332
  ([deploy/ansible/README.md](deploy/ansible/README.md)); it needs
254
333
  passwordless sudo there and `ansible-playbook` on your machine.
255
- - **This computer**, in Docker, reviewing while the machine is awake
256
- ([docker/README.md](docker/README.md)).
257
334
 
258
- GitHub needs an HTTPS URL to deliver webhooks to: a Cloudflare quick tunnel,
259
- ngrok, your own named Cloudflare tunnel, or polling only, which exposes
260
- nothing but delays triggers by up to one poll interval and silences
261
- author-reply routing and the `[feedback]` loop. The trade-offs are in
335
+ Polling is the default: the daemon checks GitHub every few minutes and
336
+ exposes nothing, at the cost of trigger latency up to one poll interval and
337
+ quiet author-reply routing and `[feedback]` loop. Webhooks need an HTTPS URL:
338
+ a Cloudflare quick tunnel, ngrok or your own named Cloudflare tunnel, on the
339
+ App route only. The trade-offs are in
262
340
  [docker/README.md](docker/README.md).
263
341
 
264
342
  `dry_run = true` stays on until you flip it, through the wizard's go-live
@@ -279,9 +357,10 @@ npm i -g @quickchatai/quickreview
279
357
  qcr login # pi's own /login, for the review's models
280
358
  qcr review # review this branch against its base, with no daemon
281
359
  qcr review 123 # review a pull request (or pass its URL)
282
- qcr pi # pi with the QuickReview plugin: /review /scan /selfimprove /qcr-setup
360
+ qcr pi # pi with the plugin (/qcr-review /qcr-scan /qcr-setup) and /selfimprove
283
361
  qcr update # update qcr with the package manager that installed it
284
- qcr # the admin TUI
362
+ qcr # the home: pi on your own login, with your repo's pull requests
363
+ qcr tui # the admin TUI
285
364
  ```
286
365
 
287
366
  `qcr review` asks where the result goes (shown, saved as markdown and JSON,
@@ -337,8 +416,9 @@ never the same system ([MANIFESTO.md](MANIFESTO.md)).
337
416
 
338
417
  ## Appendix — setting up by hand
339
418
 
340
- `qcr onboard` composes these tools rather than replacing them; re-running it
341
- afterwards re-checks every step without rewriting what already holds.
419
+ The setup wizard's steps ([docs/onboarding.md](docs/onboarding.md)) compose
420
+ these tools rather than replacing them; re-running one afterwards re-checks it
421
+ without rewriting what already holds.
342
422
 
343
423
  ```sh
344
424
  IMG=ghcr.io/quickchatai/quickreview:<version>
@@ -355,8 +435,8 @@ curl -s http://127.0.0.1:8787/health
355
435
 
356
436
  Then point your HTTPS ingress at the webhook port, install the App, create
357
437
  the trigger label and label a PR: `state/dryrun/` fills up. The memory keys
358
- are minted by the running server, so run `qcr onboard` for that step even if
359
- you did the rest by hand; declining memory is supported.
438
+ are minted by the running server (the wizard's memory-keys steps, 60 and 72,
439
+ in [docs/onboarding.md](docs/onboarding.md)); declining memory is supported.
360
440
 
361
441
  ## Star history
362
442
 
package/bin/qcr.js CHANGED
@@ -3,7 +3,7 @@
3
3
  // name `qcr`, so the CLI module cannot recognise itself by its file name: this
4
4
  // file imports the bin's front door and calls it explicitly. The front door
5
5
  // (src/qcrbin.ts) runs the verbs an npm install needs without the state
6
- // database's native driver, opens the admin TUI on a bare `qcr`, and hands
6
+ // database's native driver, opens the home on a bare `qcr`, and hands
7
7
  // every other verb to the app's `main` (src/cli.ts). The image's
8
8
  // `node /opt/qcr/dist/src/cli.js` is the app's entry, run directly.
9
9
  import { runBin } from "../dist/src/qcrbin.js";
@@ -6,10 +6,11 @@
6
6
  # supply are marked "← FILL (n)" — grep for FILL. Flip dry_run to false only
7
7
  # as a deliberate cutover act, never as part of setup.
8
8
  #
9
- # YOU DO NOT HAVE TO FILL THIS BY HAND: `scripts/qcr onboard` interviews you
10
- # for the few values only you can answer, derives the rest, and patches this
11
- # file in place — every comment survives, and a re-run edits only what changed.
12
- # It never writes dry_run in either direction; going live is its own explicit
9
+ # YOU DO NOT HAVE TO FILL THIS BY HAND: a bare `qcr` (the home) writes the
10
+ # repository you choose and its defaults, and the setup wizard's steps
11
+ # interview you for the rest, derive what they can, and patch this file in
12
+ # place — every comment survives, and a re-run edits only what changed.
13
+ # Neither writes dry_run in either direction; going live is its own explicit
13
14
  # step. See docs/onboarding.md.
14
15
  # ONE mutation class is exempt and executes for real even here: the App
15
16
  # re-pointing its OWN webhook URL (see [ingress] below) — it can never touch
@@ -27,8 +28,22 @@ timezone = "UTC" # ← FILL: your IANA timezone, e.g
27
28
 
28
29
  [github]
29
30
  repo = "" # ← FILL (1): the repo to review, "owner/name"
30
- app_slug = "" # ← FILL (2): your GitHub App slug
31
- bot_login = "" # ← FILL (3): the App bot login, "<app_slug>[bot]"
31
+ # Whose GitHub credential the daemon runs on:
32
+ # "app" (the default; a missing key means "app") — a GitHub App: its
33
+ # installation token, webhooks, APPROVE / REQUEST_CHANGES reviews.
34
+ # "user" — your OWN GitHub account, no App. Polling only: [ingress] shape
35
+ # must be "polling" (config load refuses anything else), no webhooks,
36
+ # no webhook self-heal. Every review posts as a COMMENT whose body
37
+ # states the verdict (an automated verdict never counts as your
38
+ # approval, and GitHub refuses either on your own PR). The token is
39
+ # read from the FILE <secrets dir>/github_token (0600, the token
40
+ # alone), which `qcr github-token sync` writes from your `gh` login;
41
+ # never from the environment or a command line. app_slug may be "";
42
+ # bot_login is your own GitHub login. The App secrets (app_id,
43
+ # app.pem, webhook_secret) are not needed.
44
+ #auth = "app"
45
+ app_slug = "" # ← FILL (2): your GitHub App slug ("" under auth = "user")
46
+ bot_login = "" # ← FILL (3): the App bot login, "<app_slug>[bot]" (your login under auth = "user")
32
47
  review_team = "" # ← FILL (4): "org/team" whose review request triggers
33
48
  # There is no reviewer knob here. The reviewer never hands a PR back: it always
34
49
  # decides on the merits and posts a verdict. If you want a named person told
@@ -39,7 +54,8 @@ in_progress_label = "AI review in progress"
39
54
  reviewed_label = "Automatic Review"
40
55
  improvement_label = "Bot improvement"
41
56
  issue_label = "bot-filed"
42
- # secrets dir: app_id, app.pem, webhook_secret, tunnel_token; optional openai_api_key (pi, API-key
57
+ # secrets dir: app_id, app.pem, webhook_secret, tunnel_token (auth = "user": github_token instead
58
+ # of the first three); optional openai_api_key (pi, API-key
43
59
  # route) and openai_embeddings_api_key (only with embedding_provider = "openai" in the openviking table)
44
60
  # "" (recommended) = the install's config home, $XDG_CONFIG_HOME/qcr/<install>/secrets (the old
45
61
  # ~/.config/quickreview-bot is never read — `qcr install migrate` moves it). A path here wins.
@@ -81,8 +97,12 @@ port = 8787 # loopback only; your HTTPS ingress
81
97
  # touches only the App's own configuration, never the reviewed repo. Off by
82
98
  # default: with the section absent (or shape = "none") no watcher ever starts —
83
99
  # a stable hostname (named tunnel, VM route) needs none of this.
100
+ # shape = "polling" takes no webhooks at all: the daemon's /webhook route
101
+ # refuses every delivery, no webhook_secret is read, and the reconcile poll
102
+ # (poll_interval_s, below) is the only trigger. [github] auth = "user"
103
+ # requires it.
84
104
  #[ingress]
85
- #shape = "tunnel-file" # "none" (default) | "tunnel-file"
105
+ #shape = "tunnel-file" # "none" (default) | "tunnel-file" | "polling"
86
106
  #hostname_file = "" # "" ⇒ <root>/state/ingress/hostname
87
107
  #debounce_ms = 3000 # settle time after a file change
88
108
  #sweep_interval_s = 300 # polling backstop behind fs.watch
@@ -204,7 +224,9 @@ improvement_pr_deny_prefixes = ["migrations/", "infra/", "ansible/", ".github/wo
204
224
  [models]
205
225
  # default for every role; tiered pass models below
206
226
  # Provider prefix is `openai-codex/` — the ChatGPT-OAuth route's provider key
207
- # in pi's auth.json (direct `openai/` needs an API key we don't ship).
227
+ # in pi's auth.json. Any OpenAI login serves it: when pi holds no
228
+ # `openai-codex` login but an `openai` one (pi 1.4's Sign in with ChatGPT, or
229
+ # an OpenAI API key), the same model runs on `openai` (docs/llm-setup.md).
208
230
  default = "openai-codex/gpt-6.1-sol"
209
231
  conversation = "openai-codex/gpt-6.1-sol"
210
232
  # Passes always run at sol-high — single variant, not raisable (already top).
@@ -261,7 +283,11 @@ small_diff_lines = 150
261
283
  # memory forward follows this knob too — it reaches the daemon
262
284
  # container's loopback memory engine with a plain `docker exec`
263
285
  # (the forward script's --local mode) instead of the ssh hop.
264
- # Always explicit: an empty ssh_host does NOT mean local.
286
+ # Onboarding writes this from the recorded topology. Until it has (ssh with an
287
+ # EMPTY ssh_host), the TUI never runs `ssh ""`: on a compose project (the
288
+ # checklist recorded the local topology, or the project .env pins
289
+ # QCR_VERSION) it reads the local stack and says so once; otherwise every
290
+ # surface says "ssh_host is empty — set it to the VM's ssh alias".
265
291
  target = "ssh"
266
292
  ssh_host = "" # ← FILL (7): ssh alias of the VM running the container
267
293
  # (leave "" when target = "local" — it is unused)
@@ -270,10 +296,14 @@ memory_container = "" # the container the memory forward relays into
270
296
  # (OpenViking is the daemon container's child). On a VM running
271
297
  # the memory sidecar (the openviking table's endpoint =
272
298
  # "remote") set "quickreview-memory"; flip it back with the endpoint.
273
- remote_state_dir = "/opt/quickreview/state" # host path on ssh; inside the daemon container on local
299
+ remote_state_dir = "/opt/quickreview/state" # host path on ssh; inside the daemon container on local,
300
+ # where this default reads as the release image's /opt/qcr/state
301
+ # (the compose state volume; onboarding writes it for local)
274
302
  remote_sandbox_root = "" # "" = read the container's qcr.layout label (release: /opt/qcr, legacy: /opt/quickreview/sandbox);
275
303
  # a value here wins and is never probed
276
- sudo_docker = true # docker on the VM needs sudo (root-owned socket)
304
+ sudo_docker = true # docker on the VM needs sudo (root-owned socket). On local, onboarding
305
+ # writes false, and the TUI drops sudo by itself when this user can open
306
+ # the docker socket (a sudo prompt behind the TUI can only fail)
277
307
  poll_interval_s = 3
278
308
  stale_after_s = 90 # DATA STALE banner past this written_at age
279
309
  # (the daemon rewrites status.json every ~30s)
@@ -338,6 +368,19 @@ session_dir = "state/pi-sessions"
338
368
  # lens_cache_stagger_ms = 2500
339
369
  # lens_pass_deadline_min = 8
340
370
 
371
+ [home]
372
+ # The home: a bare `qcr` opens the app's own pinned pi, on your own pi login
373
+ # ($PI_CODING_AGENT_DIR, default ~/.pi/agent), with a panel of the
374
+ # repository's pull requests. Every key is optional.
375
+ # model — the chat's model, "provider/id". The panel counts only this
376
+ # model's provider as signed in: a login under another provider
377
+ # cannot run the chat.
378
+ # tools — "reviewer": the model may call the plugin's tools, the home's
379
+ # own home_* tools and pi's read tools (read, grep, find, ls), and
380
+ # no MCP server starts. "full": every tool pi has.
381
+ model = "openai-codex/gpt-6.1-sol"
382
+ tools = "reviewer"
383
+
341
384
  [memory]
342
385
  # Round seeding — how much memory rides each round prompt and how
343
386
  # long the daemon waits for it. Memory NEVER blocks or delays a round: past
@@ -594,7 +637,10 @@ local_embedder_threads = 1
594
637
  # (COMPANION_DEFAULTS) are the shipped configuration; uncomment to override.
595
638
  # enabled = true # `qcr tui` starts it unless --no-companion
596
639
  # container_name = "qcr-companion"
597
- # image = "qcr-companion:release" # the release image (docker/Dockerfile) in companion mode, built from the app root: qcr companion rebuild
640
+ # image = "qcr-companion:release" # the release image (docker/Dockerfile) in companion mode, built from the app root: qcr companion rebuild.
641
+ # # Left unset on a compose box (the project .env pins QCR_VERSION), a first start runs the
642
+ # # already-pulled ghcr.io/quickchatai/quickreview:<QCR_VERSION> instead of building, unless a
643
+ # # local build exists; a ghcr.io/quickchatai/quickreview tag set here is pulled, never built over
598
644
  # pihome_volume = "companion-pihome" # its OWN pi auth — never the VM's auth.json
599
645
  # session = "companion" # tmux session inside the container
600
646
  # model = "openai-codex/gpt-6.1-sol:medium"
@@ -859,7 +905,7 @@ extra_vendored_segments = [] # extra third-party markers (case-insensitive)
859
905
  # whatever — the system BEHAVES exactly as a build without the feature.
860
906
  # (The placeholder that renders empty leaves a blank line in the prompt, like
861
907
  # the sibling notes beside it.)
862
- # `qcr onboard`'s escalation step writes this section.
908
+ # The setup wizard's escalation step writes this section.
863
909
  #
864
910
  # The configuration cannot be half-done: `enabled = true` with no `targets`,
865
911
  # or a rule pointing at a login that is not a target, or a rule that declares
@@ -12,7 +12,7 @@ once (`deploy.sh provision`, this playbook), which installs a thin updater,
12
12
  `qcr-update`, and its run spec; every deploy after that is
13
13
  `deploy.sh release <version>`, which runs `ssh vm sudo qcr-update ...`.
14
14
 
15
- > **`qcr onboard` drives this route for you.** The wizard's
15
+ > **The setup wizard's steps drive this route.** The wizard's
16
16
  > **topology** step offers it as one of two first-class answers — advertised as
17
17
  > the always-on recommendation, because a reviewer that is asleep reviews
18
18
  > nothing — then checks your ssh alias and agent *before* anything is built
@@ -40,7 +40,7 @@ having no built-in permission system.
40
40
 
41
41
  ## Prerequisites (once, manual)
42
42
 
43
- Items 2–4 are what `qcr onboard` fills in for you on this route; item 1 is
43
+ Items 2–4 are what the setup wizard fills in for you on this route; item 1 is
44
44
  yours either way — the wizard never creates a machine.
45
45
 
46
46
  1. **A VM you can reach over ssh by an alias**, with passwordless sudo for your
@@ -198,14 +198,20 @@ when one names another root. `remote_state_dir` stays the host path.
198
198
 
199
199
  ### Pulling the release
200
200
 
201
- The images are private and are pulled BY the updater, on the VM, by digest. The VM pulls them with ONE credential: your own CLASSIC
202
- personal access token, scoped `read:packages` and nothing else, stored by
203
- `docker login` in root's docker config on the VM host (never in a container,
204
- env, argv or the secrets directory: the daemon holds only the App credential). Not the token `gh auth
205
- token` prints: that one carries the full scopes of your gh login.
206
-
207
- A deploy needs this login to exist before the first `release` (the pull is the
208
- updater's first step, and a lapsed login fails there with nothing changed).
201
+ The images are public on ghcr.io and are pulled BY the updater, on the VM, by
202
+ digest. A public pull needs no login, so a VM that pulls the release images
203
+ needs no registry credential at all; `deploy.sh verify` and `release` then say
204
+ `no ghcr login recorded` and nothing more.
205
+
206
+ **A private mirror.** Images that are not public (`QC_RELEASE_IMAGE` and
207
+ `QC_RELEASE_MEMORY_IMAGE` naming another package) need the VM logged in, with
208
+ ONE credential: your own CLASSIC personal access token, scoped `read:packages`
209
+ and nothing else, stored by `docker login` in root's docker config on the VM
210
+ host (never in a container, env, argv or the secrets directory: the daemon
211
+ holds only the App credential). Not the token `gh auth token` prints: that one
212
+ carries the full scopes of your gh login. The login must exist before the
213
+ first `release` from the mirror (the pull is the updater's first step, and a
214
+ lapsed login fails there with nothing changed).
209
215
 
210
216
  Once per VM, and again when the token is renewed (it expires after one year):
211
217
 
@@ -227,7 +233,9 @@ idempotent, and the token is never an argument or an environment variable.
227
233
 
228
234
  A lapsed login fails the updater's pull before anything on the VM changes
229
235
  (`qcr-update` refuses at its `pull` step). `scripts/deploy.sh verify` and
230
- `release` warn 14 days before the recorded expiry. `ssh <vm> sudo docker logout ghcr.io` removes the login.
236
+ `release` warn 14 days before the recorded expiry. `ssh <vm> sudo docker logout ghcr.io` removes the login;
237
+ a VM back on the public images can drop it, and the recorded expiry with it
238
+ (`<state home>/ghcr-token-expiry`), so the warning stops.
231
239
 
232
240
  ### The cutover (legacy image to release image)
233
241
 
@@ -307,7 +315,7 @@ ssh <vm> docker exec quickreview-sandbox tmux ls
307
315
  ssh <vm> curl -sS http://127.0.0.1:8787/health # loopback-only by design
308
316
  ```
309
317
 
310
- That is the same layering `qcr onboard`'s verification step runs — containers,
318
+ That is the same layering the setup wizard's verification step runs — containers,
311
319
  then the health endpoint, then GitHub's own webhook delivery log — and the
312
320
  order matters: a container that is not up cannot answer a health probe, and a
313
321
  daemon that is not answering cannot accept a delivery. While the tunnel is up
@@ -1,7 +1,7 @@
1
1
  # Copy to inventory.ini and fill in — inventory.ini is gitignored:
2
2
  # it carries YOUR real hostnames and stays local to the controller machine.
3
3
  #
4
- # `scripts/qcr onboard` writes inventory.ini for you on the server route, from
4
+ # The setup wizard writes inventory.ini for you on the server route, from
5
5
  # answers you have already given (the ssh alias, the login user your ssh config
6
6
  # resolves, and whether the playbook should install cloudflared). This file
7
7
  # documents what it writes, and what to fill if you do it by hand.
@@ -7,7 +7,7 @@
7
7
  # Values are read with hidden input and NEVER printed back. Re-run any time —
8
8
  # existing files are kept unless you choose to replace them.
9
9
  #
10
- # `scripts/qcr onboard` writes app_id / app.pem / webhook_secret itself, from
10
+ # The setup wizard writes app_id / app.pem / webhook_secret itself, from
11
11
  # the GitHub App manifest exchange, and mints the OpenViking keys — so on the
12
12
  # guided path you only reach for this script for the values it points you at
13
13
  # (the OpenAI key, a tunnel token, an ngrok authtoken, the hosted-embeddings
@@ -535,7 +535,7 @@ fi
535
535
  # ---- 4. pull both images by digest, check them ----------------------------------------------------------
536
536
 
537
537
  step pull
538
- d pull "$DAEMON_REF" >/dev/null || die "could not pull $DAEMON_REF (is the VM logged in to ghcr.io? scripts/vm-ghcr-login.sh)"
538
+ d pull "$DAEMON_REF" >/dev/null || die "could not pull $DAEMON_REF (the release images are public: check the VM reaches ghcr.io and the digest is published; a private mirror needs the VM logged in, scripts/vm-ghcr-login.sh)"
539
539
  d pull "$MEMORY_REF" >/dev/null || die "could not pull $MEMORY_REF"
540
540
 
541
541
  step check-images
@@ -0,0 +1,14 @@
1
+ // The env shim for the home's extension: the one place the process's env
2
+ // becomes its options (extensions/home.ts). A bare `qcr` loads it by path
3
+ // (src/home/launch.ts), with the model and tool set it launched on in the env.
4
+ import { VERSION } from "@earendil-works/pi-coding-agent";
5
+ import { homeOptionsFromEnv } from "../../src/home/adapters.js";
6
+ import { homeSetupFromEnv } from "../../src/home/setupadapters.js";
7
+ import { createHome } from "../home.js";
8
+ export default function activate(pi) {
9
+ void createHome({
10
+ ...homeOptionsFromEnv(process.env),
11
+ setup: homeSetupFromEnv(process.env, VERSION),
12
+ })(pi);
13
+ }
14
+ //# sourceMappingURL=home.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"home.js","sourceRoot":"","sources":["../../../extensions/cli/home.ts"],"names":[],"mappings":"AAAA,yEAAyE;AACzE,0EAA0E;AAC1E,+EAA+E;AAC/E,OAAO,EAAE,OAAO,EAAqB,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,kBAAkB,EAAE,MAAM,4BAA4B,CAAC;AAChE,OAAO,EAAE,gBAAgB,EAAE,MAAM,iCAAiC,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAExC,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAgB;IAC/C,KAAK,UAAU,CAAC;QACd,GAAG,kBAAkB,CAAC,OAAO,CAAC,GAAG,CAAC;QAClC,KAAK,EAAE,gBAAgB,CAAC,OAAO,CAAC,GAAG,EAAE,OAAO,CAAC;KAC9C,CAAC,CAAC,EAAE,CAAC,CAAC;AACT,CAAC"}
@@ -0,0 +1,5 @@
1
+ import { createLoginRoute, loginRouteConfigFromEnv } from "../login-route.js";
2
+ export default function activate(pi) {
3
+ void createLoginRoute(loginRouteConfigFromEnv(process.env))(pi);
4
+ }
5
+ //# sourceMappingURL=login-route.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"login-route.js","sourceRoot":"","sources":["../../../extensions/cli/login-route.ts"],"names":[],"mappings":"AAKA,OAAO,EAAE,gBAAgB,EAAE,uBAAuB,EAAE,MAAM,mBAAmB,CAAC;AAE9E,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAgB;IAC/C,KAAK,gBAAgB,CAAC,uBAAuB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;AAClE,CAAC"}
@@ -0,0 +1,18 @@
1
+ // The env shim for the app's /selfimprove (extensions/selfimprove.ts): the
2
+ // one place the process's env, home and standard output become its config.
3
+ // `qcr pi` loads this file beside the plugin.
4
+ import { homedir } from "node:os";
5
+ import { VERSION } from "@earendil-works/pi-coding-agent";
6
+ import { nodeRunner } from "@quickchatai/pi-quickreview/src/plugin/runner.js";
7
+ import { createSelfImprove } from "../selfimprove.js";
8
+ export default function activate(pi) {
9
+ const env = process.env;
10
+ createSelfImprove({
11
+ env,
12
+ home: (env["HOME"] ?? "").trim() || homedir(),
13
+ runner: nodeRunner(env),
14
+ print: (text) => void process.stdout.write(text.endsWith("\n") ? text : `${text}\n`),
15
+ piVersion: VERSION,
16
+ })(pi);
17
+ }
18
+ //# sourceMappingURL=selfimprove.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"selfimprove.js","sourceRoot":"","sources":["../../../extensions/cli/selfimprove.ts"],"names":[],"mappings":"AAAA,2EAA2E;AAC3E,2EAA2E;AAC3E,8CAA8C;AAC9C,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAqB,MAAM,iCAAiC,CAAC;AAC7E,OAAO,EAAE,UAAU,EAAE,MAAM,kDAAkD,CAAC;AAC9E,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AAEtD,MAAM,CAAC,OAAO,UAAU,QAAQ,CAAC,EAAgB;IAC/C,MAAM,GAAG,GAAG,OAAO,CAAC,GAAG,CAAC;IACxB,iBAAiB,CAAC;QAChB,GAAG;QACH,IAAI,EAAE,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,OAAO,EAAE;QAC7C,MAAM,EAAE,UAAU,CAAC,GAAG,CAAC;QACvB,KAAK,EAAE,CAAC,IAAI,EAAE,EAAE,CAAC,KAAK,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,CAAC;QACpF,SAAS,EAAE,OAAO;KACnB,CAAC,CAAC,EAAE,CAAC,CAAC;AACT,CAAC"}