@quickchatai/quickreview 0.0.0-stage → 1.1.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 (1443) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +385 -2
  3. package/THIRD-PARTY-NOTICES.md +134 -0
  4. package/agents/pass-abstraction.md +64 -0
  5. package/agents/pass-ask-human.md +134 -0
  6. package/agents/pass-backcompat.md +67 -0
  7. package/agents/pass-baseline.md +61 -0
  8. package/agents/pass-behaviour-delta.md +64 -0
  9. package/agents/pass-bounds.md +36 -0
  10. package/agents/pass-claims.md +31 -0
  11. package/agents/pass-concurrency.md +168 -0
  12. package/agents/pass-consistency.md +57 -0
  13. package/agents/pass-contracts.md +30 -0
  14. package/agents/pass-data-safety.md +54 -0
  15. package/agents/pass-deferred.md +35 -0
  16. package/agents/pass-delivery.md +37 -0
  17. package/agents/pass-duplication.md +60 -0
  18. package/agents/pass-intent.md +63 -0
  19. package/agents/pass-lint-conformance.md +46 -0
  20. package/agents/pass-maintainability.md +67 -0
  21. package/agents/pass-placement.md +68 -0
  22. package/agents/pass-prod-risk.md +24 -0
  23. package/agents/pass-rollout.md +32 -0
  24. package/agents/pass-roundtrip.md +46 -0
  25. package/agents/pass-security.md +31 -0
  26. package/agents/pass-simplicity.md +68 -0
  27. package/agents/pass-statelessness.md +27 -0
  28. package/agents/pass-style.md +37 -0
  29. package/agents/pass-sweep.md +57 -0
  30. package/agents/pass-tests.md +58 -0
  31. package/agents/pass-ui.md +23 -0
  32. package/agents/pass-validate.md +50 -0
  33. package/agents/pass-widened.md +46 -0
  34. package/agents/scan/pass-scan.md +86 -0
  35. package/bin/qcr.js +11 -0
  36. package/config.example.toml +1067 -0
  37. package/deploy/ansible/README.md +356 -0
  38. package/deploy/ansible/group_vars/all.yml +212 -0
  39. package/deploy/ansible/inventory.example.ini +25 -0
  40. package/deploy/ansible/playbook.yml +360 -0
  41. package/deploy/collect-secrets.sh +289 -0
  42. package/deploy/collect-slack-secrets.mjs +1190 -0
  43. package/deploy/github-app-manifest.json +31 -0
  44. package/deploy/manifest.schema.json +75 -0
  45. package/deploy/qcr-update.sh +803 -0
  46. package/deploy/reviewer/AGENTS.override.md +12 -0
  47. package/dist/extensions/cli/bash-guard-ambient.js +42 -0
  48. package/dist/extensions/cli/bash-guard-ambient.js.map +1 -0
  49. package/dist/extensions/cli/bash-guard.js +5 -0
  50. package/dist/extensions/cli/bash-guard.js.map +1 -0
  51. package/dist/extensions/cli/companion-guard.js +5 -0
  52. package/dist/extensions/cli/companion-guard.js.map +1 -0
  53. package/dist/extensions/cli/debug-round.js +8 -0
  54. package/dist/extensions/cli/debug-round.js.map +1 -0
  55. package/dist/extensions/cli/inject-bridge.js +5 -0
  56. package/dist/extensions/cli/inject-bridge.js.map +1 -0
  57. package/dist/extensions/cli/ledger-pin.js +5 -0
  58. package/dist/extensions/cli/ledger-pin.js.map +1 -0
  59. package/dist/extensions/cli/lens.js +13 -0
  60. package/dist/extensions/cli/lens.js.map +1 -0
  61. package/dist/extensions/cli/muted-theme.js +5 -0
  62. package/dist/extensions/cli/muted-theme.js.map +1 -0
  63. package/dist/extensions/cli/onboarding.js +5 -0
  64. package/dist/extensions/cli/onboarding.js.map +1 -0
  65. package/dist/extensions/cli/setup.js +5 -0
  66. package/dist/extensions/cli/setup.js.map +1 -0
  67. package/dist/extensions/cli/tui-view.js +5 -0
  68. package/dist/extensions/cli/tui-view.js.map +1 -0
  69. package/dist/extensions/companion-guard.js +361 -0
  70. package/dist/extensions/companion-guard.js.map +1 -0
  71. package/dist/extensions/debug-round.js +204 -0
  72. package/dist/extensions/debug-round.js.map +1 -0
  73. package/dist/extensions/inject-bridge.js +603 -0
  74. package/dist/extensions/inject-bridge.js.map +1 -0
  75. package/dist/extensions/muted-theme.js +12 -0
  76. package/dist/extensions/muted-theme.js.map +1 -0
  77. package/dist/extensions/onboarding.js +175 -0
  78. package/dist/extensions/onboarding.js.map +1 -0
  79. package/dist/extensions/setup-replay.js +269 -0
  80. package/dist/extensions/setup-replay.js.map +1 -0
  81. package/dist/extensions/setup-scan.js +998 -0
  82. package/dist/extensions/setup-scan.js.map +1 -0
  83. package/dist/extensions/setup-triage.js +175 -0
  84. package/dist/extensions/setup-triage.js.map +1 -0
  85. package/dist/extensions/setup.js +1160 -0
  86. package/dist/extensions/setup.js.map +1 -0
  87. package/dist/extensions/tui-view.js +389 -0
  88. package/dist/extensions/tui-view.js.map +1 -0
  89. package/dist/extensions/vendor/openviking-pi/client.js +376 -0
  90. package/dist/extensions/vendor/openviking-pi/client.js.map +1 -0
  91. package/dist/extensions/vendor/openviking-pi/config.js +189 -0
  92. package/dist/extensions/vendor/openviking-pi/config.js.map +1 -0
  93. package/dist/extensions/vendor/openviking-pi/index.js +421 -0
  94. package/dist/extensions/vendor/openviking-pi/index.js.map +1 -0
  95. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +86 -0
  96. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs.map +1 -0
  97. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs +408 -0
  98. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs.map +1 -0
  99. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +41 -0
  100. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs.map +1 -0
  101. package/dist/extensions/vendor/openviking-pi/qcr-hint.js +290 -0
  102. package/dist/extensions/vendor/openviking-pi/qcr-hint.js.map +1 -0
  103. package/dist/extensions/vendor/openviking-pi/qcr-honest.js +148 -0
  104. package/dist/extensions/vendor/openviking-pi/qcr-honest.js.map +1 -0
  105. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js +68 -0
  106. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js.map +1 -0
  107. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js +77 -0
  108. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js.map +1 -0
  109. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js +216 -0
  110. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js.map +1 -0
  111. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js +154 -0
  112. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js.map +1 -0
  113. package/dist/extensions/vendor/openviking-pi/qcr-recall.js +254 -0
  114. package/dist/extensions/vendor/openviking-pi/qcr-recall.js.map +1 -0
  115. package/dist/extensions/vendor/openviking-pi/qcr-shim.js +94 -0
  116. package/dist/extensions/vendor/openviking-pi/qcr-shim.js.map +1 -0
  117. package/dist/extensions/vendor/openviking-pi/qcr-write.js +333 -0
  118. package/dist/extensions/vendor/openviking-pi/qcr-write.js.map +1 -0
  119. package/dist/extensions/vendor/openviking-pi/recall.js +108 -0
  120. package/dist/extensions/vendor/openviking-pi/recall.js.map +1 -0
  121. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs +529 -0
  122. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs.map +1 -0
  123. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs +205 -0
  124. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs.map +1 -0
  125. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs +442 -0
  126. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs.map +1 -0
  127. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs +286 -0
  128. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs.map +1 -0
  129. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +189 -0
  130. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs.map +1 -0
  131. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs +580 -0
  132. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs.map +1 -0
  133. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs +11 -0
  134. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs.map +1 -0
  135. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs +63 -0
  136. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs.map +1 -0
  137. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs +58 -0
  138. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs.map +1 -0
  139. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  140. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs.map +1 -0
  141. package/dist/extensions/vendor/openviking-pi/sync.js +127 -0
  142. package/dist/extensions/vendor/openviking-pi/sync.js.map +1 -0
  143. package/dist/extensions/vendor/openviking-pi/takeover.js +25 -0
  144. package/dist/extensions/vendor/openviking-pi/takeover.js.map +1 -0
  145. package/dist/extensions/vendor/openviking-pi/tools.js +417 -0
  146. package/dist/extensions/vendor/openviking-pi/tools.js.map +1 -0
  147. package/dist/src/anomalies.js +483 -0
  148. package/dist/src/anomalies.js.map +1 -0
  149. package/dist/src/answerworker.js +180 -0
  150. package/dist/src/answerworker.js.map +1 -0
  151. package/dist/src/appstamp.js +68 -0
  152. package/dist/src/appstamp.js.map +1 -0
  153. package/dist/src/archive/admission.js +3 -0
  154. package/dist/src/archive/admission.js.map +1 -0
  155. package/dist/src/archive/archivedb.js +474 -0
  156. package/dist/src/archive/archivedb.js.map +1 -0
  157. package/dist/src/archive/archiver.js +1770 -0
  158. package/dist/src/archive/archiver.js.map +1 -0
  159. package/dist/src/archive/archivewrite.js +198 -0
  160. package/dist/src/archive/archivewrite.js.map +1 -0
  161. package/dist/src/archive/bundle.js +266 -0
  162. package/dist/src/archive/bundle.js.map +1 -0
  163. package/dist/src/archive/dbmove.js +638 -0
  164. package/dist/src/archive/dbmove.js.map +1 -0
  165. package/dist/src/archive/duplicatecounts.js +80 -0
  166. package/dist/src/archive/duplicatecounts.js.map +1 -0
  167. package/dist/src/archive/eligibility.js +113 -0
  168. package/dist/src/archive/eligibility.js.map +1 -0
  169. package/dist/src/archive/extract.js +288 -0
  170. package/dist/src/archive/extract.js.map +1 -0
  171. package/dist/src/archive/fsutil.js +330 -0
  172. package/dist/src/archive/fsutil.js.map +1 -0
  173. package/dist/src/archive/gzfile.js +277 -0
  174. package/dist/src/archive/gzfile.js.map +1 -0
  175. package/dist/src/archive/kinds.js +22 -0
  176. package/dist/src/archive/kinds.js.map +1 -0
  177. package/dist/src/archive/livecheckpoint.js +178 -0
  178. package/dist/src/archive/livecheckpoint.js.map +1 -0
  179. package/dist/src/archive/liveretention.js +145 -0
  180. package/dist/src/archive/liveretention.js.map +1 -0
  181. package/dist/src/archive/manifest.js +284 -0
  182. package/dist/src/archive/manifest.js.map +1 -0
  183. package/dist/src/archive/overseer.js +283 -0
  184. package/dist/src/archive/overseer.js.map +1 -0
  185. package/dist/src/archive/piglobal.js +129 -0
  186. package/dist/src/archive/piglobal.js.map +1 -0
  187. package/dist/src/archive/plan.js +398 -0
  188. package/dist/src/archive/plan.js.map +1 -0
  189. package/dist/src/archive/prarchive.js +831 -0
  190. package/dist/src/archive/prarchive.js.map +1 -0
  191. package/dist/src/archive/prfiles.js +303 -0
  192. package/dist/src/archive/prfiles.js.map +1 -0
  193. package/dist/src/archive/report.js +169 -0
  194. package/dist/src/archive/report.js.map +1 -0
  195. package/dist/src/archive/restore.js +276 -0
  196. package/dist/src/archive/restore.js.map +1 -0
  197. package/dist/src/archive/rows.js +106 -0
  198. package/dist/src/archive/rows.js.map +1 -0
  199. package/dist/src/archive/seal.js +480 -0
  200. package/dist/src/archive/seal.js.map +1 -0
  201. package/dist/src/archive/status.js +528 -0
  202. package/dist/src/archive/status.js.map +1 -0
  203. package/dist/src/archive/storepass.js +409 -0
  204. package/dist/src/archive/storepass.js.map +1 -0
  205. package/dist/src/backfill.js +217 -0
  206. package/dist/src/backfill.js.map +1 -0
  207. package/dist/src/bench/cost.js +87 -0
  208. package/dist/src/bench/exec.js +76 -0
  209. package/dist/src/bench/values.js +14 -0
  210. package/dist/src/botcontrol.js +127 -0
  211. package/dist/src/botcontrol.js.map +1 -0
  212. package/dist/src/botworker.js +805 -0
  213. package/dist/src/botworker.js.map +1 -0
  214. package/dist/src/capture.js +234 -0
  215. package/dist/src/capture.js.map +1 -0
  216. package/dist/src/cases.js +1491 -0
  217. package/dist/src/cases.js.map +1 -0
  218. package/dist/src/channelfs.js +27 -0
  219. package/dist/src/channelfs.js.map +1 -0
  220. package/dist/src/checklist.js +312 -0
  221. package/dist/src/checklist.js.map +1 -0
  222. package/dist/src/ciretry.js +91 -0
  223. package/dist/src/ciretry.js.map +1 -0
  224. package/dist/src/cli.js +1916 -0
  225. package/dist/src/cli.js.map +1 -0
  226. package/dist/src/cliops.js +333 -0
  227. package/dist/src/cliops.js.map +1 -0
  228. package/dist/src/clonedir.js +15 -0
  229. package/dist/src/clonedir.js.map +1 -0
  230. package/dist/src/commandeffects.js +43 -0
  231. package/dist/src/commandeffects.js.map +1 -0
  232. package/dist/src/commands.js +1312 -0
  233. package/dist/src/commands.js.map +1 -0
  234. package/dist/src/companioninbox.js +203 -0
  235. package/dist/src/companioninbox.js.map +1 -0
  236. package/dist/src/compare.js +673 -0
  237. package/dist/src/compare.js.map +1 -0
  238. package/dist/src/config.js +1027 -0
  239. package/dist/src/config.js.map +1 -0
  240. package/dist/src/configcheck.js +111 -0
  241. package/dist/src/configcheck.js.map +1 -0
  242. package/dist/src/coreext.js +43 -0
  243. package/dist/src/coreext.js.map +1 -0
  244. package/dist/src/daemon.js +929 -0
  245. package/dist/src/daemon.js.map +1 -0
  246. package/dist/src/debuground.js +731 -0
  247. package/dist/src/debuground.js.map +1 -0
  248. package/dist/src/debugroundpi.js +219 -0
  249. package/dist/src/debugroundpi.js.map +1 -0
  250. package/dist/src/diagnostics.js +14 -0
  251. package/dist/src/diagnostics.js.map +1 -0
  252. package/dist/src/digest.js +139 -0
  253. package/dist/src/digest.js.map +1 -0
  254. package/dist/src/dispatch.js +1726 -0
  255. package/dist/src/dispatch.js.map +1 -0
  256. package/dist/src/engine/answerguard.js +18 -0
  257. package/dist/src/engine/answerguard.js.map +1 -0
  258. package/dist/src/engine/botsdk.js +262 -0
  259. package/dist/src/engine/botsdk.js.map +1 -0
  260. package/dist/src/engine/caserunner-sdk.js +332 -0
  261. package/dist/src/engine/caserunner-sdk.js.map +1 -0
  262. package/dist/src/engine/debugpi.js +194 -0
  263. package/dist/src/engine/debugpi.js.map +1 -0
  264. package/dist/src/eod.js +473 -0
  265. package/dist/src/eod.js.map +1 -0
  266. package/dist/src/eodpinwatch.js +391 -0
  267. package/dist/src/eodpinwatch.js.map +1 -0
  268. package/dist/src/escalation.js +1009 -0
  269. package/dist/src/escalation.js.map +1 -0
  270. package/dist/src/eventloop.js +779 -0
  271. package/dist/src/eventloop.js.map +1 -0
  272. package/dist/src/execboundary.js +430 -0
  273. package/dist/src/execboundary.js.map +1 -0
  274. package/dist/src/feedback.js +915 -0
  275. package/dist/src/feedback.js.map +1 -0
  276. package/dist/src/findingscheck.js +200 -0
  277. package/dist/src/findingscheck.js.map +1 -0
  278. package/dist/src/fsdenied.js +26 -0
  279. package/dist/src/fsdenied.js.map +1 -0
  280. package/dist/src/ghread.js +181 -0
  281. package/dist/src/ghread.js.map +1 -0
  282. package/dist/src/github.js +1063 -0
  283. package/dist/src/github.js.map +1 -0
  284. package/dist/src/homes.js +103 -0
  285. package/dist/src/homes.js.map +1 -0
  286. package/dist/src/hostroute.js +24 -0
  287. package/dist/src/hostroute.js.map +1 -0
  288. package/dist/src/improvements.js +625 -0
  289. package/dist/src/improvements.js.map +1 -0
  290. package/dist/src/install.js +946 -0
  291. package/dist/src/install.js.map +1 -0
  292. package/dist/src/installkind.js +40 -0
  293. package/dist/src/installkind.js.map +1 -0
  294. package/dist/src/ipc/capability.js +286 -0
  295. package/dist/src/ipc/capability.js.map +1 -0
  296. package/dist/src/ipc/client.js +226 -0
  297. package/dist/src/ipc/client.js.map +1 -0
  298. package/dist/src/ipc/control.js +70 -0
  299. package/dist/src/ipc/control.js.map +1 -0
  300. package/dist/src/ipc/ghreadshim.js +77 -0
  301. package/dist/src/ipc/ghreadshim.js.map +1 -0
  302. package/dist/src/ipc/launcher.js +65 -0
  303. package/dist/src/ipc/launcher.js.map +1 -0
  304. package/dist/src/ipc/permits.js +293 -0
  305. package/dist/src/ipc/permits.js.map +1 -0
  306. package/dist/src/ipc/postshim.js +137 -0
  307. package/dist/src/ipc/postshim.js.map +1 -0
  308. package/dist/src/ipc/protocol.js +239 -0
  309. package/dist/src/ipc/protocol.js.map +1 -0
  310. package/dist/src/ipc/server.js +312 -0
  311. package/dist/src/ipc/server.js.map +1 -0
  312. package/dist/src/ipc/workerspec.js +148 -0
  313. package/dist/src/ipc/workerspec.js.map +1 -0
  314. package/dist/src/learner/learner.js +1272 -0
  315. package/dist/src/learner/learner.js.map +1 -0
  316. package/dist/src/learner/miner.js +948 -0
  317. package/dist/src/learner/miner.js.map +1 -0
  318. package/dist/src/learner/packet.js +216 -0
  319. package/dist/src/learner/packet.js.map +1 -0
  320. package/dist/src/learner/receipt.js +135 -0
  321. package/dist/src/learner/receipt.js.map +1 -0
  322. package/dist/src/learner/status.js +38 -0
  323. package/dist/src/learner/status.js.map +1 -0
  324. package/dist/src/ledgercheck.js +120 -0
  325. package/dist/src/ledgercheck.js.map +1 -0
  326. package/dist/src/lessonledger.js +451 -0
  327. package/dist/src/lessonledger.js.map +1 -0
  328. package/dist/src/lessonselect.js +639 -0
  329. package/dist/src/lessonselect.js.map +1 -0
  330. package/dist/src/lessonshadow.js +540 -0
  331. package/dist/src/lessonshadow.js.map +1 -0
  332. package/dist/src/levers.js +302 -0
  333. package/dist/src/levers.js.map +1 -0
  334. package/dist/src/live/projection.js +450 -0
  335. package/dist/src/live/projection.js.map +1 -0
  336. package/dist/src/live/publish.js +83 -0
  337. package/dist/src/live/publish.js.map +1 -0
  338. package/dist/src/live/read.js +60 -0
  339. package/dist/src/live/read.js.map +1 -0
  340. package/dist/src/livecli.js +288 -0
  341. package/dist/src/livecli.js.map +1 -0
  342. package/dist/src/loginhint.js +42 -0
  343. package/dist/src/loginhint.js.map +1 -0
  344. package/dist/src/loginrefresh/atomic.js +66 -0
  345. package/dist/src/loginrefresh/atomic.js.map +1 -0
  346. package/dist/src/loginrefresh/lock.js +93 -0
  347. package/dist/src/loginrefresh/lock.js.map +1 -0
  348. package/dist/src/loginrefresh/main.js +58 -0
  349. package/dist/src/loginrefresh/main.js.map +1 -0
  350. package/dist/src/loginrefresh/pirefresh.js +49 -0
  351. package/dist/src/loginrefresh/pirefresh.js.map +1 -0
  352. package/dist/src/loginrefresh/refresher.js +286 -0
  353. package/dist/src/loginrefresh/refresher.js.map +1 -0
  354. package/dist/src/loginrefresh/supervisor.js +253 -0
  355. package/dist/src/loginrefresh/supervisor.js.map +1 -0
  356. package/dist/src/loginrefresh/types.js +4 -0
  357. package/dist/src/loginrefresh/types.js.map +1 -0
  358. package/dist/src/memory/context.js +251 -0
  359. package/dist/src/memory/context.js.map +1 -0
  360. package/dist/src/memory/datafence.js +5 -0
  361. package/dist/src/memory/datafence.js.map +1 -0
  362. package/dist/src/memory/delivery.js +131 -0
  363. package/dist/src/memory/delivery.js.map +1 -0
  364. package/dist/src/memory/eventtags.js +81 -0
  365. package/dist/src/memory/eventtags.js.map +1 -0
  366. package/dist/src/memory/health.js +713 -0
  367. package/dist/src/memory/health.js.map +1 -0
  368. package/dist/src/memory/import.js +504 -0
  369. package/dist/src/memory/import.js.map +1 -0
  370. package/dist/src/memory/layout.js +252 -0
  371. package/dist/src/memory/layout.js.map +1 -0
  372. package/dist/src/memory/legacy-file.js +100 -0
  373. package/dist/src/memory/legacy-file.js.map +1 -0
  374. package/dist/src/memory/lessons.js +370 -0
  375. package/dist/src/memory/lessons.js.map +1 -0
  376. package/dist/src/memory/ovsession.js +449 -0
  377. package/dist/src/memory/ovsession.js.map +1 -0
  378. package/dist/src/memory/relayout.js +259 -0
  379. package/dist/src/memory/relayout.js.map +1 -0
  380. package/dist/src/memory/roundactivity.js +180 -0
  381. package/dist/src/memory/roundactivity.js.map +1 -0
  382. package/dist/src/memory/selection.js +690 -0
  383. package/dist/src/memory/selection.js.map +1 -0
  384. package/dist/src/memory/shadowstatus.js +69 -0
  385. package/dist/src/memory/shadowstatus.js.map +1 -0
  386. package/dist/src/memory/store.js +83 -0
  387. package/dist/src/memory/store.js.map +1 -0
  388. package/dist/src/memory/textidentity.js +8 -0
  389. package/dist/src/memory/textidentity.js.map +1 -0
  390. package/dist/src/metrics.js +773 -0
  391. package/dist/src/metrics.js.map +1 -0
  392. package/dist/src/missingconfig.js +8 -0
  393. package/dist/src/missingconfig.js.map +1 -0
  394. package/dist/src/npmverbs.js +226 -0
  395. package/dist/src/npmverbs.js.map +1 -0
  396. package/dist/src/onboard/choices.js +191 -0
  397. package/dist/src/onboard/choices.js.map +1 -0
  398. package/dist/src/onboard/engine.js +344 -0
  399. package/dist/src/onboard/engine.js.map +1 -0
  400. package/dist/src/onboard/launch.js +83 -0
  401. package/dist/src/onboard/launch.js.map +1 -0
  402. package/dist/src/onboard/steps/appslug.js +211 -0
  403. package/dist/src/onboard/steps/appslug.js.map +1 -0
  404. package/dist/src/onboard/steps/bringup.js +408 -0
  405. package/dist/src/onboard/steps/bringup.js.map +1 -0
  406. package/dist/src/onboard/steps/compose.js +343 -0
  407. package/dist/src/onboard/steps/compose.js.map +1 -0
  408. package/dist/src/onboard/steps/configdelivery.js +50 -0
  409. package/dist/src/onboard/steps/configdelivery.js.map +1 -0
  410. package/dist/src/onboard/steps/configfill.js +1148 -0
  411. package/dist/src/onboard/steps/configfill.js.map +1 -0
  412. package/dist/src/onboard/steps/deploysh.js +80 -0
  413. package/dist/src/onboard/steps/deploysh.js.map +1 -0
  414. package/dist/src/onboard/steps/embeddings.js +472 -0
  415. package/dist/src/onboard/steps/embeddings.js.map +1 -0
  416. package/dist/src/onboard/steps/escalation.js +571 -0
  417. package/dist/src/onboard/steps/escalation.js.map +1 -0
  418. package/dist/src/onboard/steps/githubapp.js +1092 -0
  419. package/dist/src/onboard/steps/githubapp.js.map +1 -0
  420. package/dist/src/onboard/steps/golive.js +506 -0
  421. package/dist/src/onboard/steps/golive.js.map +1 -0
  422. package/dist/src/onboard/steps/index.js +67 -0
  423. package/dist/src/onboard/steps/index.js.map +1 -0
  424. package/dist/src/onboard/steps/ingress.js +762 -0
  425. package/dist/src/onboard/steps/ingress.js.map +1 -0
  426. package/dist/src/onboard/steps/inventory.js +420 -0
  427. package/dist/src/onboard/steps/inventory.js.map +1 -0
  428. package/dist/src/onboard/steps/llmauth.js +893 -0
  429. package/dist/src/onboard/steps/llmauth.js.map +1 -0
  430. package/dist/src/onboard/steps/memory.js +1060 -0
  431. package/dist/src/onboard/steps/memory.js.map +1 -0
  432. package/dist/src/onboard/steps/memorykeys.js +43 -0
  433. package/dist/src/onboard/steps/memorykeys.js.map +1 -0
  434. package/dist/src/onboard/steps/preflight.js +172 -0
  435. package/dist/src/onboard/steps/preflight.js.map +1 -0
  436. package/dist/src/onboard/steps/proof.js +502 -0
  437. package/dist/src/onboard/steps/proof.js.map +1 -0
  438. package/dist/src/onboard/steps/ssh.js +300 -0
  439. package/dist/src/onboard/steps/ssh.js.map +1 -0
  440. package/dist/src/onboard/steps/topology.js +291 -0
  441. package/dist/src/onboard/steps/topology.js.map +1 -0
  442. package/dist/src/onboard/steps/transport.js +511 -0
  443. package/dist/src/onboard/steps/transport.js.map +1 -0
  444. package/dist/src/onboard/steps/verifyup.js +362 -0
  445. package/dist/src/onboard/steps/verifyup.js.map +1 -0
  446. package/dist/src/onboard/steps/vmdeploy.js +368 -0
  447. package/dist/src/onboard/steps/vmdeploy.js.map +1 -0
  448. package/dist/src/onboard/toml.js +53 -0
  449. package/dist/src/onboard/toml.js.map +1 -0
  450. package/dist/src/opencli.js +508 -0
  451. package/dist/src/opencli.js.map +1 -0
  452. package/dist/src/openpr.js +457 -0
  453. package/dist/src/openpr.js.map +1 -0
  454. package/dist/src/openviking/client.js +821 -0
  455. package/dist/src/openviking/client.js.map +1 -0
  456. package/dist/src/openviking/context.js +218 -0
  457. package/dist/src/openviking/context.js.map +1 -0
  458. package/dist/src/openviking/embedder.js +457 -0
  459. package/dist/src/openviking/embedder.js.map +1 -0
  460. package/dist/src/openviking/gapsink.js +38 -0
  461. package/dist/src/openviking/gapsink.js.map +1 -0
  462. package/dist/src/openviking/health.js +69 -0
  463. package/dist/src/openviking/health.js.map +1 -0
  464. package/dist/src/openviking/index.js +24 -0
  465. package/dist/src/openviking/index.js.map +1 -0
  466. package/dist/src/openviking/lessonfind.js +54 -0
  467. package/dist/src/openviking/lessonfind.js.map +1 -0
  468. package/dist/src/openviking/probe.js +89 -0
  469. package/dist/src/openviking/probe.js.map +1 -0
  470. package/dist/src/openviking/proc.js +95 -0
  471. package/dist/src/openviking/proc.js.map +1 -0
  472. package/dist/src/openviking/provisionreport.js +144 -0
  473. package/dist/src/openviking/provisionreport.js.map +1 -0
  474. package/dist/src/openviking/reembed.js +317 -0
  475. package/dist/src/openviking/reembed.js.map +1 -0
  476. package/dist/src/openviking/relayout.js +153 -0
  477. package/dist/src/openviking/relayout.js.map +1 -0
  478. package/dist/src/openviking/sidecar-main.js +39 -0
  479. package/dist/src/openviking/sidecar-main.js.map +1 -0
  480. package/dist/src/openviking/sidecar.js +79 -0
  481. package/dist/src/openviking/sidecar.js.map +1 -0
  482. package/dist/src/openviking/store.js +1758 -0
  483. package/dist/src/openviking/store.js.map +1 -0
  484. package/dist/src/openviking/supervisor.js +422 -0
  485. package/dist/src/openviking/supervisor.js.map +1 -0
  486. package/dist/src/openviking/types.js +5 -0
  487. package/dist/src/openviking/types.js.map +1 -0
  488. package/dist/src/operator-recovery.js +172 -0
  489. package/dist/src/operator-recovery.js.map +1 -0
  490. package/dist/src/operatormessage.js +44 -0
  491. package/dist/src/operatormessage.js.map +1 -0
  492. package/dist/src/outcomes.js +1361 -0
  493. package/dist/src/outcomes.js.map +1 -0
  494. package/dist/src/piauthcopy.js +5 -0
  495. package/dist/src/piauthcopy.js.map +1 -0
  496. package/dist/src/picli.js +45 -0
  497. package/dist/src/picli.js.map +1 -0
  498. package/dist/src/picwd.js +25 -0
  499. package/dist/src/picwd.js.map +1 -0
  500. package/dist/src/pilogin.js +35 -0
  501. package/dist/src/pilogin.js.map +1 -0
  502. package/dist/src/pingpong.js +1028 -0
  503. package/dist/src/pingpong.js.map +1 -0
  504. package/dist/src/posting-journal.js +441 -0
  505. package/dist/src/posting-journal.js.map +1 -0
  506. package/dist/src/posting-outbox.js +662 -0
  507. package/dist/src/posting-outbox.js.map +1 -0
  508. package/dist/src/posting-receipt.js +203 -0
  509. package/dist/src/posting-receipt.js.map +1 -0
  510. package/dist/src/posting.js +348 -0
  511. package/dist/src/posting.js.map +1 -0
  512. package/dist/src/postops.js +637 -0
  513. package/dist/src/postops.js.map +1 -0
  514. package/dist/src/pr-activity.js +11 -0
  515. package/dist/src/pr-activity.js.map +1 -0
  516. package/dist/src/pr-author.js +5 -0
  517. package/dist/src/pr-author.js.map +1 -0
  518. package/dist/src/pr-conversation.js +355 -0
  519. package/dist/src/pr-conversation.js.map +1 -0
  520. package/dist/src/pr-session-lifecycle.js +542 -0
  521. package/dist/src/pr-session-lifecycle.js.map +1 -0
  522. package/dist/src/preflight.js +341 -0
  523. package/dist/src/preflight.js.map +1 -0
  524. package/dist/src/priorresolve.js +275 -0
  525. package/dist/src/priorresolve.js.map +1 -0
  526. package/dist/src/qcrbin.js +180 -0
  527. package/dist/src/qcrbin.js.map +1 -0
  528. package/dist/src/recheck.js +1398 -0
  529. package/dist/src/recheck.js.map +1 -0
  530. package/dist/src/reconcile.js +820 -0
  531. package/dist/src/reconcile.js.map +1 -0
  532. package/dist/src/recordedfindings.js +15 -0
  533. package/dist/src/recordedfindings.js.map +1 -0
  534. package/dist/src/regression.js +546 -0
  535. package/dist/src/regression.js.map +1 -0
  536. package/dist/src/replay.js +598 -0
  537. package/dist/src/replay.js.map +1 -0
  538. package/dist/src/requiredpasses.js +113 -0
  539. package/dist/src/requiredpasses.js.map +1 -0
  540. package/dist/src/resumecheck.js +168 -0
  541. package/dist/src/resumecheck.js.map +1 -0
  542. package/dist/src/reviewcli.js +671 -0
  543. package/dist/src/reviewcli.js.map +1 -0
  544. package/dist/src/reviewcontext.js +22 -0
  545. package/dist/src/reviewcontext.js.map +1 -0
  546. package/dist/src/reviewdetach.js +574 -0
  547. package/dist/src/reviewdetach.js.map +1 -0
  548. package/dist/src/reviewhistory.js +284 -0
  549. package/dist/src/reviewhistory.js.map +1 -0
  550. package/dist/src/reviewhome.js +26 -0
  551. package/dist/src/reviewhome.js.map +1 -0
  552. package/dist/src/reviewmemory.js +110 -0
  553. package/dist/src/reviewmemory.js.map +1 -0
  554. package/dist/src/reviewrendercli.js +104 -0
  555. package/dist/src/reviewrendercli.js.map +1 -0
  556. package/dist/src/round-work.js +20 -0
  557. package/dist/src/round-work.js.map +1 -0
  558. package/dist/src/runhost.js +72 -0
  559. package/dist/src/runhost.js.map +1 -0
  560. package/dist/src/scanauth.js +25 -0
  561. package/dist/src/scanauth.js.map +1 -0
  562. package/dist/src/scanbox.js +846 -0
  563. package/dist/src/scanbox.js.map +1 -0
  564. package/dist/src/scancli.js +1074 -0
  565. package/dist/src/scancli.js.map +1 -0
  566. package/dist/src/scandriverlog.js +30 -0
  567. package/dist/src/scandriverlog.js.map +1 -0
  568. package/dist/src/session-bridge.js +75 -0
  569. package/dist/src/session-bridge.js.map +1 -0
  570. package/dist/src/session-command-payload.js +29 -0
  571. package/dist/src/session-command-payload.js.map +1 -0
  572. package/dist/src/session-command-supervisor.js +939 -0
  573. package/dist/src/session-command-supervisor.js.map +1 -0
  574. package/dist/src/sessionjsonl.js +85 -0
  575. package/dist/src/sessionjsonl.js.map +1 -0
  576. package/dist/src/sessions.js +541 -0
  577. package/dist/src/sessions.js.map +1 -0
  578. package/dist/src/setup/adapters.js +330 -0
  579. package/dist/src/setup/adapters.js.map +1 -0
  580. package/dist/src/setup/baselines.js +64 -0
  581. package/dist/src/setup/baselines.js.map +1 -0
  582. package/dist/src/setup/caserunner.js +554 -0
  583. package/dist/src/setup/caserunner.js.map +1 -0
  584. package/dist/src/setup/configcommit.js +358 -0
  585. package/dist/src/setup/configcommit.js.map +1 -0
  586. package/dist/src/setup/engine.js +672 -0
  587. package/dist/src/setup/engine.js.map +1 -0
  588. package/dist/src/setup/facts.js +593 -0
  589. package/dist/src/setup/facts.js.map +1 -0
  590. package/dist/src/setup/findings.js +948 -0
  591. package/dist/src/setup/findings.js.map +1 -0
  592. package/dist/src/setup/history.js +338 -0
  593. package/dist/src/setup/history.js.map +1 -0
  594. package/dist/src/setup/interview.js +185 -0
  595. package/dist/src/setup/interview.js.map +1 -0
  596. package/dist/src/setup/ledger.js +207 -0
  597. package/dist/src/setup/ledger.js.map +1 -0
  598. package/dist/src/setup/pins.js +43 -0
  599. package/dist/src/setup/pins.js.map +1 -0
  600. package/dist/src/setup/portrait.js +432 -0
  601. package/dist/src/setup/portrait.js.map +1 -0
  602. package/dist/src/setup/presentation.js +9 -0
  603. package/dist/src/setup/presentation.js.map +1 -0
  604. package/dist/src/setup/profile.js +417 -0
  605. package/dist/src/setup/profile.js.map +1 -0
  606. package/dist/src/setup/replay.js +240 -0
  607. package/dist/src/setup/replay.js.map +1 -0
  608. package/dist/src/setup/replaybuild.js +311 -0
  609. package/dist/src/setup/replaybuild.js.map +1 -0
  610. package/dist/src/setup/replayrun.js +806 -0
  611. package/dist/src/setup/replayrun.js.map +1 -0
  612. package/dist/src/setup/replaysource.js +169 -0
  613. package/dist/src/setup/replaysource.js.map +1 -0
  614. package/dist/src/setup/retune.js +333 -0
  615. package/dist/src/setup/retune.js.map +1 -0
  616. package/dist/src/setup/retunelog.js +51 -0
  617. package/dist/src/setup/retunelog.js.map +1 -0
  618. package/dist/src/setup/scan.js +725 -0
  619. package/dist/src/setup/scan.js.map +1 -0
  620. package/dist/src/setup/scanbuild.js +133 -0
  621. package/dist/src/setup/scanbuild.js.map +1 -0
  622. package/dist/src/setup/scanfacts.js +96 -0
  623. package/dist/src/setup/scanfacts.js.map +1 -0
  624. package/dist/src/setup/scanlease.js +251 -0
  625. package/dist/src/setup/scanlease.js.map +1 -0
  626. package/dist/src/setup/scanreport.js +289 -0
  627. package/dist/src/setup/scanreport.js.map +1 -0
  628. package/dist/src/setup/scanrun.js +1733 -0
  629. package/dist/src/setup/scanrun.js.map +1 -0
  630. package/dist/src/setup/scantree.js +257 -0
  631. package/dist/src/setup/scantree.js.map +1 -0
  632. package/dist/src/setup/stage2.js +617 -0
  633. package/dist/src/setup/stage2.js.map +1 -0
  634. package/dist/src/setup/stage2request.js +259 -0
  635. package/dist/src/setup/stage2request.js.map +1 -0
  636. package/dist/src/setup/survey.js +307 -0
  637. package/dist/src/setup/survey.js.map +1 -0
  638. package/dist/src/setup/surveyrun.js +549 -0
  639. package/dist/src/setup/surveyrun.js.map +1 -0
  640. package/dist/src/setup/textsniff.js +89 -0
  641. package/dist/src/setup/textsniff.js.map +1 -0
  642. package/dist/src/setup/trackersink.js +395 -0
  643. package/dist/src/setup/trackersink.js.map +1 -0
  644. package/dist/src/setup/triage.js +636 -0
  645. package/dist/src/setup/triage.js.map +1 -0
  646. package/dist/src/setup/tuning.js +585 -0
  647. package/dist/src/setup/tuning.js.map +1 -0
  648. package/dist/src/setup/unitcut.js +437 -0
  649. package/dist/src/setup/unitcut.js.map +1 -0
  650. package/dist/src/singleflight.js +72 -0
  651. package/dist/src/singleflight.js.map +1 -0
  652. package/dist/src/slack/announce.js +725 -0
  653. package/dist/src/slack/announce.js.map +1 -0
  654. package/dist/src/slack/api.js +227 -0
  655. package/dist/src/slack/api.js.map +1 -0
  656. package/dist/src/slack/messages.js +158 -0
  657. package/dist/src/slack/messages.js.map +1 -0
  658. package/dist/src/slack/origin.js +550 -0
  659. package/dist/src/slack/origin.js.map +1 -0
  660. package/dist/src/slack/policy.js +225 -0
  661. package/dist/src/slack/policy.js.map +1 -0
  662. package/dist/src/slack/reply.js +153 -0
  663. package/dist/src/slack/reply.js.map +1 -0
  664. package/dist/src/slack/router.js +189 -0
  665. package/dist/src/slack/router.js.map +1 -0
  666. package/dist/src/slack/socket.js +323 -0
  667. package/dist/src/slack/socket.js.map +1 -0
  668. package/dist/src/slack/types.js +11 -0
  669. package/dist/src/slack/types.js.map +1 -0
  670. package/dist/src/sqlitehint.js +30 -0
  671. package/dist/src/sqlitehint.js.map +1 -0
  672. package/dist/src/ssh-observation.js +25 -0
  673. package/dist/src/ssh-observation.js.map +1 -0
  674. package/dist/src/state.js +5869 -0
  675. package/dist/src/state.js.map +1 -0
  676. package/dist/src/statemachine.js +220 -0
  677. package/dist/src/statemachine.js.map +1 -0
  678. package/dist/src/stubs.js +52 -0
  679. package/dist/src/stubs.js.map +1 -0
  680. package/dist/src/takeover.js +506 -0
  681. package/dist/src/takeover.js.map +1 -0
  682. package/dist/src/takeoverpi.js +249 -0
  683. package/dist/src/takeoverpi.js.map +1 -0
  684. package/dist/src/terminal-failure.js +26 -0
  685. package/dist/src/terminal-failure.js.map +1 -0
  686. package/dist/src/thread-resolution-refusal.js +4 -0
  687. package/dist/src/thread-resolution-refusal.js.map +1 -0
  688. package/dist/src/tmux.js +126 -0
  689. package/dist/src/tmux.js.map +1 -0
  690. package/dist/src/trackerid.js +43 -0
  691. package/dist/src/trackerid.js.map +1 -0
  692. package/dist/src/transcriptindex.js +512 -0
  693. package/dist/src/transcriptindex.js.map +1 -0
  694. package/dist/src/tui/actions.js +404 -0
  695. package/dist/src/tui/actions.js.map +1 -0
  696. package/dist/src/tui/alerts.js +523 -0
  697. package/dist/src/tui/alerts.js.map +1 -0
  698. package/dist/src/tui/app.js +1835 -0
  699. package/dist/src/tui/app.js.map +1 -0
  700. package/dist/src/tui/archiveops.js +164 -0
  701. package/dist/src/tui/archiveops.js.map +1 -0
  702. package/dist/src/tui/autofile.js +191 -0
  703. package/dist/src/tui/autofile.js.map +1 -0
  704. package/dist/src/tui/board.js +1143 -0
  705. package/dist/src/tui/board.js.map +1 -0
  706. package/dist/src/tui/candidates.js +699 -0
  707. package/dist/src/tui/candidates.js.map +1 -0
  708. package/dist/src/tui/cellwidth.js +151 -0
  709. package/dist/src/tui/cellwidth.js.map +1 -0
  710. package/dist/src/tui/changelog-store.js +404 -0
  711. package/dist/src/tui/changelog-store.js.map +1 -0
  712. package/dist/src/tui/chord.js +26 -0
  713. package/dist/src/tui/chord.js.map +1 -0
  714. package/dist/src/tui/clipboard.js +81 -0
  715. package/dist/src/tui/clipboard.js.map +1 -0
  716. package/dist/src/tui/cmdbar.js +253 -0
  717. package/dist/src/tui/cmdbar.js.map +1 -0
  718. package/dist/src/tui/companion.js +1275 -0
  719. package/dist/src/tui/companion.js.map +1 -0
  720. package/dist/src/tui/companionplan.js +200 -0
  721. package/dist/src/tui/companionplan.js.map +1 -0
  722. package/dist/src/tui/companiontab.js +61 -0
  723. package/dist/src/tui/companiontab.js.map +1 -0
  724. package/dist/src/tui/confighome.js +105 -0
  725. package/dist/src/tui/confighome.js.map +1 -0
  726. package/dist/src/tui/connect.js +44 -0
  727. package/dist/src/tui/connect.js.map +1 -0
  728. package/dist/src/tui/deploy-ceremony.js +75 -0
  729. package/dist/src/tui/deploy-ceremony.js.map +1 -0
  730. package/dist/src/tui/deploy-drain.js +93 -0
  731. package/dist/src/tui/deploy-drain.js.map +1 -0
  732. package/dist/src/tui/deploy-process.js +234 -0
  733. package/dist/src/tui/deploy-process.js.map +1 -0
  734. package/dist/src/tui/deploytab.js +1263 -0
  735. package/dist/src/tui/deploytab.js.map +1 -0
  736. package/dist/src/tui/design.js +111 -0
  737. package/dist/src/tui/design.js.map +1 -0
  738. package/dist/src/tui/digesttab.js +148 -0
  739. package/dist/src/tui/digesttab.js.map +1 -0
  740. package/dist/src/tui/emptystate.js +32 -0
  741. package/dist/src/tui/emptystate.js.map +1 -0
  742. package/dist/src/tui/evidence.js +790 -0
  743. package/dist/src/tui/evidence.js.map +1 -0
  744. package/dist/src/tui/feed.js +415 -0
  745. package/dist/src/tui/feed.js.map +1 -0
  746. package/dist/src/tui/feedbacktab.js +907 -0
  747. package/dist/src/tui/feedbacktab.js.map +1 -0
  748. package/dist/src/tui/filters.js +72 -0
  749. package/dist/src/tui/filters.js.map +1 -0
  750. package/dist/src/tui/ghread.js +272 -0
  751. package/dist/src/tui/ghread.js.map +1 -0
  752. package/dist/src/tui/historypull.js +61 -0
  753. package/dist/src/tui/historypull.js.map +1 -0
  754. package/dist/src/tui/inboxpull.js +197 -0
  755. package/dist/src/tui/inboxpull.js.map +1 -0
  756. package/dist/src/tui/index.js +1425 -0
  757. package/dist/src/tui/index.js.map +1 -0
  758. package/dist/src/tui/issuesink.js +206 -0
  759. package/dist/src/tui/issuesink.js.map +1 -0
  760. package/dist/src/tui/jsonfile.js +32 -0
  761. package/dist/src/tui/jsonfile.js.map +1 -0
  762. package/dist/src/tui/keys.js +97 -0
  763. package/dist/src/tui/keys.js.map +1 -0
  764. package/dist/src/tui/layout.js +70 -0
  765. package/dist/src/tui/layout.js.map +1 -0
  766. package/dist/src/tui/learning.js +469 -0
  767. package/dist/src/tui/learning.js.map +1 -0
  768. package/dist/src/tui/lessonswitch.js +103 -0
  769. package/dist/src/tui/lessonswitch.js.map +1 -0
  770. package/dist/src/tui/livecontrol.js +167 -0
  771. package/dist/src/tui/livecontrol.js.map +1 -0
  772. package/dist/src/tui/memforward.js +310 -0
  773. package/dist/src/tui/memforward.js.map +1 -0
  774. package/dist/src/tui/memincident.js +287 -0
  775. package/dist/src/tui/memincident.js.map +1 -0
  776. package/dist/src/tui/memory.js +485 -0
  777. package/dist/src/tui/memory.js.map +1 -0
  778. package/dist/src/tui/memtab.js +513 -0
  779. package/dist/src/tui/memtab.js.map +1 -0
  780. package/dist/src/tui/metricstab.js +979 -0
  781. package/dist/src/tui/metricstab.js.map +1 -0
  782. package/dist/src/tui/model.js +104 -0
  783. package/dist/src/tui/model.js.map +1 -0
  784. package/dist/src/tui/mouse.js +83 -0
  785. package/dist/src/tui/mouse.js.map +1 -0
  786. package/dist/src/tui/msg.js +196 -0
  787. package/dist/src/tui/msg.js.map +1 -0
  788. package/dist/src/tui/nativecompanion.js +321 -0
  789. package/dist/src/tui/nativecompanion.js.map +1 -0
  790. package/dist/src/tui/openurl.js +17 -0
  791. package/dist/src/tui/openurl.js.map +1 -0
  792. package/dist/src/tui/paint.js +501 -0
  793. package/dist/src/tui/paint.js.map +1 -0
  794. package/dist/src/tui/panes.js +74 -0
  795. package/dist/src/tui/panes.js.map +1 -0
  796. package/dist/src/tui/pipane.js +166 -0
  797. package/dist/src/tui/pipane.js.map +1 -0
  798. package/dist/src/tui/poll-hooks.js +11 -0
  799. package/dist/src/tui/poll-hooks.js.map +1 -0
  800. package/dist/src/tui/poll.js +113 -0
  801. package/dist/src/tui/poll.js.map +1 -0
  802. package/dist/src/tui/proposals.js +715 -0
  803. package/dist/src/tui/proposals.js.map +1 -0
  804. package/dist/src/tui/prpause.js +132 -0
  805. package/dist/src/tui/prpause.js.map +1 -0
  806. package/dist/src/tui/reload.js +351 -0
  807. package/dist/src/tui/reload.js.map +1 -0
  808. package/dist/src/tui/remote.js +312 -0
  809. package/dist/src/tui/remote.js.map +1 -0
  810. package/dist/src/tui/rollover.js +767 -0
  811. package/dist/src/tui/rollover.js.map +1 -0
  812. package/dist/src/tui/scantab.js +1053 -0
  813. package/dist/src/tui/scantab.js.map +1 -0
  814. package/dist/src/tui/setupentry.js +81 -0
  815. package/dist/src/tui/setupentry.js.map +1 -0
  816. package/dist/src/tui/sidebar.js +602 -0
  817. package/dist/src/tui/sidebar.js.map +1 -0
  818. package/dist/src/tui/sshtriage.js +393 -0
  819. package/dist/src/tui/sshtriage.js.map +1 -0
  820. package/dist/src/tui/startup.js +172 -0
  821. package/dist/src/tui/startup.js.map +1 -0
  822. package/dist/src/tui/tabs.js +41 -0
  823. package/dist/src/tui/tabs.js.map +1 -0
  824. package/dist/src/tui/termmirror.js +217 -0
  825. package/dist/src/tui/termmirror.js.map +1 -0
  826. package/dist/src/tui/theme.js +95 -0
  827. package/dist/src/tui/theme.js.map +1 -0
  828. package/dist/src/tui/ticketstab.js +224 -0
  829. package/dist/src/tui/ticketstab.js.map +1 -0
  830. package/dist/src/tui/tmuxsocket.js +101 -0
  831. package/dist/src/tui/tmuxsocket.js.map +1 -0
  832. package/dist/src/tui/trackertickets.js +77 -0
  833. package/dist/src/tui/trackertickets.js.map +1 -0
  834. package/dist/src/tui/unwedge.js +245 -0
  835. package/dist/src/tui/unwedge.js.map +1 -0
  836. package/dist/src/tui/viewer.js +479 -0
  837. package/dist/src/tui/viewer.js.map +1 -0
  838. package/dist/src/tui/viewerinput.js +125 -0
  839. package/dist/src/tui/viewerinput.js.map +1 -0
  840. package/dist/src/updatenotice.js +143 -0
  841. package/dist/src/updatenotice.js.map +1 -0
  842. package/dist/src/usage.js +1007 -0
  843. package/dist/src/usage.js.map +1 -0
  844. package/dist/src/verdicts.js +3848 -0
  845. package/dist/src/verdicts.js.map +1 -0
  846. package/dist/src/version.js +58 -0
  847. package/dist/src/version.js.map +1 -0
  848. package/dist/src/wakes.js +411 -0
  849. package/dist/src/wakes.js.map +1 -0
  850. package/dist/src/webhook.js +725 -0
  851. package/dist/src/webhook.js.map +1 -0
  852. package/dist/src/webhookheal.js +238 -0
  853. package/dist/src/webhookheal.js.map +1 -0
  854. package/dist/src/wire.js +1801 -0
  855. package/dist/src/wire.js.map +1 -0
  856. package/dist/src/worker-session-host.js +531 -0
  857. package/dist/src/worker-session-host.js.map +1 -0
  858. package/dist/src/workerbreaker.js +112 -0
  859. package/dist/src/workerbreaker.js.map +1 -0
  860. package/dist/src/workercontrol.js +49 -0
  861. package/dist/src/workercontrol.js.map +1 -0
  862. package/dist/src/workerlease.js +351 -0
  863. package/dist/src/workerlease.js.map +1 -0
  864. package/dist/src/workerliveness.js +84 -0
  865. package/dist/src/workerliveness.js.map +1 -0
  866. package/dist/src/workerlog.js +65 -0
  867. package/dist/src/workerlog.js.map +1 -0
  868. package/dist/src/workerruntime.js +10 -0
  869. package/dist/src/workerruntime.js.map +1 -0
  870. package/dist/src/workersupervisor.js +1206 -0
  871. package/dist/src/workersupervisor.js.map +1 -0
  872. package/dist/src/workerusage.js +23 -0
  873. package/dist/src/workerusage.js.map +1 -0
  874. package/dist/src/workerworld.js +332 -0
  875. package/dist/src/workerworld.js.map +1 -0
  876. package/dist/src/worktrees.js +984 -0
  877. package/dist/src/worktrees.js.map +1 -0
  878. package/docker/Dockerfile +284 -0
  879. package/docker/Dockerfile.dockerignore +35 -0
  880. package/docker/README.md +221 -0
  881. package/docker/companion/Dockerfile +139 -0
  882. package/docker/companion/agents/evidence.md +34 -0
  883. package/docker/companion/agents/explore.md +26 -0
  884. package/docker/companion/agents/pass-survey.md +49 -0
  885. package/docker/companion/agents/study.md +26 -0
  886. package/docker/companion/entrypoint.sh +343 -0
  887. package/docker/companion/memory-health.mjs +269 -0
  888. package/docker/entrypoint.sh +782 -0
  889. package/docker/memory/Dockerfile +191 -0
  890. package/docker/memory/Dockerfile.dockerignore +20 -0
  891. package/docker/memory/README.md +60 -0
  892. package/docker/memory/entrypoint.sh +163 -0
  893. package/docker/setid/qcr-setid.c +109 -0
  894. package/docker/tunnel/Dockerfile.cloudflared +51 -0
  895. package/docker/tunnel/Dockerfile.ngrok +40 -0
  896. package/docker/tunnel/sidecar.mjs +411 -0
  897. package/docker/vm/tmux.conf +26 -0
  898. package/docker-compose.yml +348 -0
  899. package/extensions/cli/bash-guard-ambient.ts +71 -0
  900. package/extensions/cli/bash-guard.ts +12 -0
  901. package/extensions/cli/companion-guard.ts +8 -0
  902. package/extensions/cli/debug-round.ts +9 -0
  903. package/extensions/cli/inject-bridge.ts +8 -0
  904. package/extensions/cli/ledger-pin.ts +13 -0
  905. package/extensions/cli/lens.ts +22 -0
  906. package/extensions/cli/muted-theme.ts +9 -0
  907. package/extensions/cli/onboarding.ts +8 -0
  908. package/extensions/cli/setup.ts +8 -0
  909. package/extensions/cli/tui-view.ts +8 -0
  910. package/extensions/companion-guard.ts +411 -0
  911. package/extensions/debug-round.ts +281 -0
  912. package/extensions/inject-bridge.ts +630 -0
  913. package/extensions/inline-bash.ts +102 -0
  914. package/extensions/muted-theme.json +68 -0
  915. package/extensions/muted-theme.ts +23 -0
  916. package/extensions/onboarding.ts +233 -0
  917. package/extensions/setup-replay.ts +336 -0
  918. package/extensions/setup-scan.ts +1236 -0
  919. package/extensions/setup-triage.ts +190 -0
  920. package/extensions/setup.ts +1428 -0
  921. package/extensions/tui-view.ts +489 -0
  922. package/extensions/vendor/openviking-pi/LICENSE +201 -0
  923. package/extensions/vendor/openviking-pi/NOTICE +68 -0
  924. package/extensions/vendor/openviking-pi/README.md +550 -0
  925. package/extensions/vendor/openviking-pi/client.ts +588 -0
  926. package/extensions/vendor/openviking-pi/config.json +28 -0
  927. package/extensions/vendor/openviking-pi/config.ts +271 -0
  928. package/extensions/vendor/openviking-pi/index.ts +523 -0
  929. package/extensions/vendor/openviking-pi/lib/capture-adapter.d.mts +10 -0
  930. package/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +88 -0
  931. package/extensions/vendor/openviking-pi/lib/takeover-core.d.mts +80 -0
  932. package/extensions/vendor/openviking-pi/lib/takeover-core.mjs +406 -0
  933. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.d.mts +1 -0
  934. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +42 -0
  935. package/extensions/vendor/openviking-pi/patches/0000-vendoring-and-build-conformance.patch +726 -0
  936. package/extensions/vendor/openviking-pi/patches/0001-remove-session-before-compact-handler.patch +101 -0
  937. package/extensions/vendor/openviking-pi/patches/0002-no-ambient-work-in-subagent-leaves.patch +202 -0
  938. package/extensions/vendor/openviking-pi/patches/0003-never-auto-create-openviking-sessions.patch +120 -0
  939. package/extensions/vendor/openviking-pi/patches/0004-viking-write-durable-batch-write.patch +521 -0
  940. package/extensions/vendor/openviking-pi/patches/0005-second-memory-namespace.patch +786 -0
  941. package/extensions/vendor/openviking-pi/patches/0006-writes-that-stick-and-honest-errors.patch +996 -0
  942. package/extensions/vendor/openviking-pi/patches/0007-bounded-recall-no-commit.patch +794 -0
  943. package/extensions/vendor/openviking-pi/patches/0008-pr-derived-recall.patch +379 -0
  944. package/extensions/vendor/openviking-pi/patches/0009-pr-session-tools-in-round-areas.patch +375 -0
  945. package/extensions/vendor/openviking-pi/patches/0010-typed-lessons.patch +448 -0
  946. package/extensions/vendor/openviking-pi/patches/0011-review-session-memory-boundary.patch +382 -0
  947. package/extensions/vendor/openviking-pi/patches/0012-typecheck-against-the-real-pi.patch +129 -0
  948. package/extensions/vendor/openviking-pi/patches/0013-createopenviking-factory.patch +1168 -0
  949. package/extensions/vendor/openviking-pi/qcr-hint.ts +313 -0
  950. package/extensions/vendor/openviking-pi/qcr-honest.ts +183 -0
  951. package/extensions/vendor/openviking-pi/qcr-hooks.ts +87 -0
  952. package/extensions/vendor/openviking-pi/qcr-leaf.ts +78 -0
  953. package/extensions/vendor/openviking-pi/qcr-lesson.ts +231 -0
  954. package/extensions/vendor/openviking-pi/qcr-namespaces.ts +198 -0
  955. package/extensions/vendor/openviking-pi/qcr-recall.ts +288 -0
  956. package/extensions/vendor/openviking-pi/qcr-shim.ts +142 -0
  957. package/extensions/vendor/openviking-pi/qcr-write.ts +427 -0
  958. package/extensions/vendor/openviking-pi/recall.ts +149 -0
  959. package/extensions/vendor/openviking-pi/shared/capture-utils.d.mts +9 -0
  960. package/extensions/vendor/openviking-pi/shared/capture-utils.mjs +515 -0
  961. package/extensions/vendor/openviking-pi/shared/credentials.d.mts +14 -0
  962. package/extensions/vendor/openviking-pi/shared/credentials.mjs +228 -0
  963. package/extensions/vendor/openviking-pi/shared/pending-queue.d.mts +19 -0
  964. package/extensions/vendor/openviking-pi/shared/pending-queue.mjs +458 -0
  965. package/extensions/vendor/openviking-pi/shared/profile-inject.d.mts +17 -0
  966. package/extensions/vendor/openviking-pi/shared/profile-inject.mjs +294 -0
  967. package/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +195 -0
  968. package/extensions/vendor/openviking-pi/shared/recall-core.d.mts +13 -0
  969. package/extensions/vendor/openviking-pi/shared/recall-core.mjs +609 -0
  970. package/extensions/vendor/openviking-pi/shared/retryable.mjs +9 -0
  971. package/extensions/vendor/openviking-pi/shared/session-model.d.mts +3 -0
  972. package/extensions/vendor/openviking-pi/shared/session-model.mjs +57 -0
  973. package/extensions/vendor/openviking-pi/shared/uri-guard.mjs +56 -0
  974. package/extensions/vendor/openviking-pi/shared/workspace-peer.d.mts +5 -0
  975. package/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  976. package/extensions/vendor/openviking-pi/sync.ts +163 -0
  977. package/extensions/vendor/openviking-pi/takeover.ts +36 -0
  978. package/extensions/vendor/openviking-pi/tools.ts +479 -0
  979. package/extensions/vendor/openviking-pi/upstream.json +48 -0
  980. package/package.json +138 -4
  981. package/profiles/default/README.md +21 -0
  982. package/profiles/default/addenda/.gitkeep +0 -0
  983. package/profiles/default/profile.toml +17 -0
  984. package/profiles/example-django/README.md +21 -0
  985. package/profiles/example-django/addenda/10-migration-discipline.md +13 -0
  986. package/profiles/example-django/addenda/20-new-column-nullability.md +12 -0
  987. package/profiles/example-django/addenda/30-test-doctrine.md +12 -0
  988. package/profiles/example-django/addenda/40-orm-usage.md +19 -0
  989. package/profiles/example-django/addenda/50-declared-shape.md +10 -0
  990. package/profiles/example-django/addenda/60-config-placement.md +14 -0
  991. package/profiles/example-django/heuristics.toml +24 -0
  992. package/profiles/example-django/profile.toml +9 -0
  993. package/profiles/fast/README.md +24 -0
  994. package/profiles/fast/profile.toml +59 -0
  995. package/profiles/minimal/README.md +17 -0
  996. package/profiles/minimal/addenda/.gitkeep +0 -0
  997. package/profiles/minimal/profile.toml +8 -0
  998. package/profiles/snappy/README.md +24 -0
  999. package/profiles/snappy/addenda/10-race-as-question.md +6 -0
  1000. package/profiles/snappy/profile.toml +46 -0
  1001. package/prompts/companion-day-open.md +46 -0
  1002. package/prompts/companion-first-run.md +104 -0
  1003. package/prompts/companion.md +821 -0
  1004. package/prompts/conversation-system.md +117 -0
  1005. package/prompts/eod-sweep.md +120 -0
  1006. package/prompts/onboarding.md +74 -0
  1007. package/prompts/pass-common.md +52 -0
  1008. package/prompts/pass-quality-common.md +22 -0
  1009. package/prompts/round-first.md +874 -0
  1010. package/prompts/round-follow-up.md +991 -0
  1011. package/prompts/round-re-review.md +889 -0
  1012. package/prompts/round-recheck.md +196 -0
  1013. package/prompts/round-staleness.md +856 -0
  1014. package/schemas/review-result.v1.json +391 -0
  1015. package/schemas/scan-result.v1.json +421 -0
  1016. package/schemas/version.v1.json +57 -0
  1017. package/scripts/approve-pr.sh +16 -0
  1018. package/scripts/build-stamp.mjs +67 -0
  1019. package/scripts/commit-verdict.sh +155 -0
  1020. package/scripts/companion-e2e.sh +250 -0
  1021. package/scripts/companion-memory-forward.mjs +1966 -0
  1022. package/scripts/config-fingerprint.sh +28 -0
  1023. package/scripts/deploy-manifest.mjs +141 -0
  1024. package/scripts/deploy.sh +1435 -0
  1025. package/scripts/directory-lock.mjs +193 -0
  1026. package/scripts/heartbeat-fresh.mjs +54 -0
  1027. package/scripts/install-locator.sh +328 -0
  1028. package/scripts/install-wrapper.sh +76 -0
  1029. package/scripts/memory-search-check.mjs +98 -0
  1030. package/scripts/mint-token.sh +212 -0
  1031. package/scripts/openviking-embedder.py +392 -0
  1032. package/scripts/openviking-ov-conf.mjs +161 -0
  1033. package/scripts/openviking-provision.mjs +1122 -0
  1034. package/scripts/openviking-reembed.mjs +1154 -0
  1035. package/scripts/post-review.sh +16 -0
  1036. package/scripts/pr-checks.sh +256 -0
  1037. package/scripts/pr-context.py +174 -0
  1038. package/scripts/pr-context.sh +63 -0
  1039. package/scripts/pr-self.sh +144 -0
  1040. package/scripts/pr-threads.sh +145 -0
  1041. package/scripts/qcr +15 -0
  1042. package/scripts/qcr-host.sh +769 -0
  1043. package/scripts/render-review.sh +24 -0
  1044. package/scripts/reply-thread.sh +16 -0
  1045. package/scripts/required-passes.py +112 -0
  1046. package/scripts/smoke-companion.sh +211 -0
  1047. package/scripts/tui-deploy-runner.mjs +61 -0
  1048. package/scripts/verify-dist.mjs +201 -0
  1049. package/scripts/vm-ghcr-login.sh +188 -0
  1050. package/seeds/agents/pass-baseline.md +61 -0
  1051. package/seeds/agents/pass-contracts.md +30 -0
  1052. package/seeds/agents/pass-data-safety.md +54 -0
  1053. package/seeds/agents/pass-delivery.md +37 -0
  1054. package/seeds/agents/pass-prod-risk.md +24 -0
  1055. package/seeds/agents/pass-security.md +31 -0
  1056. package/seeds/agents/pass-statelessness.md +27 -0
  1057. package/seeds/agents/pass-ui.md +23 -0
  1058. package/seeds/agents/pass-validate.md +50 -0
  1059. package/seeds/prompts/conversation-system.md +117 -0
  1060. package/seeds/prompts/eod-sweep.md +120 -0
  1061. package/seeds/prompts/pass-common.md +52 -0
  1062. package/skills/companion/adjudicate/SKILL.md +247 -0
  1063. package/skills/companion/evidence/SKILL.md +150 -0
  1064. package/skills/companion/land/SKILL.md +200 -0
  1065. package/skills/companion/replay/SKILL.md +138 -0
  1066. package/skills/companion/setup/SKILL.md +167 -0
  1067. package/skills/companion/survey/SKILL.md +160 -0
  1068. package/skills/selfimprove/README.md +34 -0
  1069. package/skills/selfimprove/SKILL.md +127 -0
  1070. package/skills/selfimprove/agents/openai.yaml +2 -0
  1071. package/skills/selfimprove/commands/selfimprove.md +6 -0
  1072. package/skills/selfimprove/references/fix-loop.md +49 -0
  1073. package/skills/selfimprove/references/ledger.md +20 -0
  1074. package/skills/selfimprove/references/setup.md +40 -0
  1075. package/src/anomalies.ts +566 -0
  1076. package/src/answerworker.ts +251 -0
  1077. package/src/appstamp.ts +65 -0
  1078. package/src/archive/admission.ts +3 -0
  1079. package/src/archive/archivedb.ts +548 -0
  1080. package/src/archive/archiver.ts +1963 -0
  1081. package/src/archive/archivewrite.ts +279 -0
  1082. package/src/archive/bundle.ts +333 -0
  1083. package/src/archive/dbmove.ts +911 -0
  1084. package/src/archive/duplicatecounts.ts +98 -0
  1085. package/src/archive/eligibility.ts +181 -0
  1086. package/src/archive/extract.ts +342 -0
  1087. package/src/archive/fsutil.ts +415 -0
  1088. package/src/archive/gzfile.ts +370 -0
  1089. package/src/archive/kinds.ts +21 -0
  1090. package/src/archive/livecheckpoint.ts +217 -0
  1091. package/src/archive/liveretention.ts +180 -0
  1092. package/src/archive/manifest.ts +519 -0
  1093. package/src/archive/overseer.ts +336 -0
  1094. package/src/archive/piglobal.ts +174 -0
  1095. package/src/archive/plan.ts +612 -0
  1096. package/src/archive/prarchive.ts +984 -0
  1097. package/src/archive/prfiles.ts +406 -0
  1098. package/src/archive/report.ts +252 -0
  1099. package/src/archive/restore.ts +330 -0
  1100. package/src/archive/rows.ts +187 -0
  1101. package/src/archive/seal.ts +630 -0
  1102. package/src/archive/status.ts +719 -0
  1103. package/src/archive/storepass.ts +581 -0
  1104. package/src/backfill.ts +362 -0
  1105. package/src/bench/cost.ts +113 -0
  1106. package/src/bench/exec.ts +90 -0
  1107. package/src/bench/values.ts +13 -0
  1108. package/src/botcontrol.ts +176 -0
  1109. package/src/botworker.ts +953 -0
  1110. package/src/capture.ts +321 -0
  1111. package/src/cases.ts +1789 -0
  1112. package/src/channelfs.ts +26 -0
  1113. package/src/checklist.ts +506 -0
  1114. package/src/ciretry.ts +141 -0
  1115. package/src/cli.ts +2271 -0
  1116. package/src/cliops.ts +384 -0
  1117. package/src/clonedir.ts +15 -0
  1118. package/src/commandeffects.ts +57 -0
  1119. package/src/commands.ts +1678 -0
  1120. package/src/companioninbox.ts +239 -0
  1121. package/src/compare.ts +957 -0
  1122. package/src/config.ts +2050 -0
  1123. package/src/configcheck.ts +133 -0
  1124. package/src/coreext.ts +47 -0
  1125. package/src/daemon.ts +1302 -0
  1126. package/src/debuground.ts +927 -0
  1127. package/src/debugroundpi.ts +262 -0
  1128. package/src/diagnostics.ts +14 -0
  1129. package/src/digest.ts +183 -0
  1130. package/src/dispatch.ts +2250 -0
  1131. package/src/engine/answerguard.ts +27 -0
  1132. package/src/engine/botsdk.ts +336 -0
  1133. package/src/engine/caserunner-sdk.ts +423 -0
  1134. package/src/engine/debugpi.ts +235 -0
  1135. package/src/eod.ts +669 -0
  1136. package/src/eodpinwatch.ts +556 -0
  1137. package/src/escalation.ts +1253 -0
  1138. package/src/eventloop.ts +1045 -0
  1139. package/src/execboundary.ts +633 -0
  1140. package/src/feedback.ts +1162 -0
  1141. package/src/findingscheck.ts +298 -0
  1142. package/src/fsdenied.ts +24 -0
  1143. package/src/ghread.ts +242 -0
  1144. package/src/github.ts +1497 -0
  1145. package/src/homes.ts +175 -0
  1146. package/src/hostroute.ts +53 -0
  1147. package/src/improvements.ts +787 -0
  1148. package/src/install.ts +1103 -0
  1149. package/src/installkind.ts +50 -0
  1150. package/src/ipc/capability.ts +333 -0
  1151. package/src/ipc/client.ts +269 -0
  1152. package/src/ipc/control.ts +90 -0
  1153. package/src/ipc/ghreadshim.ts +94 -0
  1154. package/src/ipc/launcher.ts +65 -0
  1155. package/src/ipc/permits.ts +362 -0
  1156. package/src/ipc/postshim.ts +164 -0
  1157. package/src/ipc/protocol.ts +342 -0
  1158. package/src/ipc/server.ts +371 -0
  1159. package/src/ipc/workerspec.ts +218 -0
  1160. package/src/learner/learner.ts +1655 -0
  1161. package/src/learner/miner.ts +1290 -0
  1162. package/src/learner/packet.ts +340 -0
  1163. package/src/learner/receipt.ts +168 -0
  1164. package/src/learner/status.ts +107 -0
  1165. package/src/ledgercheck.ts +157 -0
  1166. package/src/lessonledger.ts +703 -0
  1167. package/src/lessonselect.ts +888 -0
  1168. package/src/lessonshadow.ts +810 -0
  1169. package/src/levers.ts +393 -0
  1170. package/src/live/projection.ts +491 -0
  1171. package/src/live/publish.ts +92 -0
  1172. package/src/live/read.ts +86 -0
  1173. package/src/livecli.ts +336 -0
  1174. package/src/loginhint.ts +56 -0
  1175. package/src/loginrefresh/atomic.ts +76 -0
  1176. package/src/loginrefresh/lock.ts +104 -0
  1177. package/src/loginrefresh/main.ts +59 -0
  1178. package/src/loginrefresh/pirefresh.ts +57 -0
  1179. package/src/loginrefresh/refresher.ts +326 -0
  1180. package/src/loginrefresh/supervisor.ts +273 -0
  1181. package/src/loginrefresh/types.ts +35 -0
  1182. package/src/memory/context.ts +385 -0
  1183. package/src/memory/datafence.ts +9 -0
  1184. package/src/memory/delivery.ts +171 -0
  1185. package/src/memory/eventtags.ts +80 -0
  1186. package/src/memory/health.ts +953 -0
  1187. package/src/memory/import.ts +664 -0
  1188. package/src/memory/layout.ts +261 -0
  1189. package/src/memory/legacy-file.ts +104 -0
  1190. package/src/memory/lessons.ts +447 -0
  1191. package/src/memory/ovsession.ts +601 -0
  1192. package/src/memory/relayout.ts +335 -0
  1193. package/src/memory/roundactivity.ts +209 -0
  1194. package/src/memory/selection.ts +989 -0
  1195. package/src/memory/shadowstatus.ts +125 -0
  1196. package/src/memory/store.ts +275 -0
  1197. package/src/memory/textidentity.ts +8 -0
  1198. package/src/metrics.ts +1056 -0
  1199. package/src/missingconfig.ts +7 -0
  1200. package/src/npmverbs.ts +264 -0
  1201. package/src/onboard/choices.ts +222 -0
  1202. package/src/onboard/engine.ts +518 -0
  1203. package/src/onboard/launch.ts +115 -0
  1204. package/src/onboard/steps/appslug.ts +265 -0
  1205. package/src/onboard/steps/bringup.ts +482 -0
  1206. package/src/onboard/steps/compose.ts +459 -0
  1207. package/src/onboard/steps/configdelivery.ts +58 -0
  1208. package/src/onboard/steps/configfill.ts +1352 -0
  1209. package/src/onboard/steps/deploysh.ts +105 -0
  1210. package/src/onboard/steps/embeddings.ts +550 -0
  1211. package/src/onboard/steps/escalation.ts +640 -0
  1212. package/src/onboard/steps/githubapp.ts +1414 -0
  1213. package/src/onboard/steps/golive.ts +577 -0
  1214. package/src/onboard/steps/index.ts +71 -0
  1215. package/src/onboard/steps/ingress.ts +907 -0
  1216. package/src/onboard/steps/inventory.ts +526 -0
  1217. package/src/onboard/steps/llmauth.ts +1095 -0
  1218. package/src/onboard/steps/memory.ts +1290 -0
  1219. package/src/onboard/steps/memorykeys.ts +85 -0
  1220. package/src/onboard/steps/preflight.ts +191 -0
  1221. package/src/onboard/steps/proof.ts +624 -0
  1222. package/src/onboard/steps/ssh.ts +377 -0
  1223. package/src/onboard/steps/topology.ts +337 -0
  1224. package/src/onboard/steps/transport.ts +665 -0
  1225. package/src/onboard/steps/verifyup.ts +448 -0
  1226. package/src/onboard/steps/vmdeploy.ts +442 -0
  1227. package/src/onboard/toml.ts +50 -0
  1228. package/src/opencli.ts +591 -0
  1229. package/src/openpr.ts +568 -0
  1230. package/src/openviking/client.ts +1131 -0
  1231. package/src/openviking/context.ts +263 -0
  1232. package/src/openviking/embedder.ts +516 -0
  1233. package/src/openviking/gapsink.ts +63 -0
  1234. package/src/openviking/health.ts +83 -0
  1235. package/src/openviking/index.ts +119 -0
  1236. package/src/openviking/lessonfind.ts +92 -0
  1237. package/src/openviking/probe.ts +129 -0
  1238. package/src/openviking/proc.ts +110 -0
  1239. package/src/openviking/provisionreport.ts +160 -0
  1240. package/src/openviking/reembed.ts +412 -0
  1241. package/src/openviking/relayout.ts +177 -0
  1242. package/src/openviking/sidecar-main.ts +38 -0
  1243. package/src/openviking/sidecar.ts +106 -0
  1244. package/src/openviking/store.ts +2025 -0
  1245. package/src/openviking/supervisor.ts +474 -0
  1246. package/src/openviking/types.ts +174 -0
  1247. package/src/operator-recovery.ts +237 -0
  1248. package/src/operatormessage.ts +52 -0
  1249. package/src/outcomes.ts +1670 -0
  1250. package/src/piauthcopy.ts +12 -0
  1251. package/src/picli.ts +49 -0
  1252. package/src/picwd.ts +25 -0
  1253. package/src/pilogin.ts +37 -0
  1254. package/src/pingpong.ts +1339 -0
  1255. package/src/posting-journal.ts +549 -0
  1256. package/src/posting-outbox.ts +802 -0
  1257. package/src/posting-receipt.ts +324 -0
  1258. package/src/posting.ts +603 -0
  1259. package/src/postops.ts +832 -0
  1260. package/src/pr-activity.ts +20 -0
  1261. package/src/pr-author.ts +6 -0
  1262. package/src/pr-conversation.ts +432 -0
  1263. package/src/pr-session-lifecycle.ts +631 -0
  1264. package/src/preflight.ts +391 -0
  1265. package/src/priorresolve.ts +343 -0
  1266. package/src/qcrbin.ts +186 -0
  1267. package/src/recheck.ts +1775 -0
  1268. package/src/reconcile.ts +1030 -0
  1269. package/src/recordedfindings.ts +27 -0
  1270. package/src/regression.ts +833 -0
  1271. package/src/replay.ts +816 -0
  1272. package/src/requiredpasses.ts +148 -0
  1273. package/src/resumecheck.ts +246 -0
  1274. package/src/reviewcli.ts +787 -0
  1275. package/src/reviewcontext.ts +35 -0
  1276. package/src/reviewdetach.ts +734 -0
  1277. package/src/reviewhistory.ts +427 -0
  1278. package/src/reviewhome.ts +36 -0
  1279. package/src/reviewmemory.ts +133 -0
  1280. package/src/reviewrendercli.ts +139 -0
  1281. package/src/round-work.ts +42 -0
  1282. package/src/runhost.ts +108 -0
  1283. package/src/scanauth.ts +36 -0
  1284. package/src/scanbox.ts +1081 -0
  1285. package/src/scancli.ts +1296 -0
  1286. package/src/scandriverlog.ts +32 -0
  1287. package/src/session-bridge.ts +139 -0
  1288. package/src/session-command-payload.ts +35 -0
  1289. package/src/session-command-supervisor.ts +1142 -0
  1290. package/src/sessionjsonl.ts +88 -0
  1291. package/src/sessions.ts +659 -0
  1292. package/src/setup/adapters.ts +335 -0
  1293. package/src/setup/baselines.ts +110 -0
  1294. package/src/setup/caserunner.ts +611 -0
  1295. package/src/setup/configcommit.ts +443 -0
  1296. package/src/setup/engine.ts +1001 -0
  1297. package/src/setup/facts.ts +627 -0
  1298. package/src/setup/findings.ts +1264 -0
  1299. package/src/setup/history.ts +443 -0
  1300. package/src/setup/interview.ts +243 -0
  1301. package/src/setup/ledger.ts +324 -0
  1302. package/src/setup/pins.ts +66 -0
  1303. package/src/setup/portrait.ts +635 -0
  1304. package/src/setup/presentation.ts +18 -0
  1305. package/src/setup/profile.ts +508 -0
  1306. package/src/setup/replay.ts +370 -0
  1307. package/src/setup/replaybuild.ts +392 -0
  1308. package/src/setup/replayrun.ts +1096 -0
  1309. package/src/setup/replaysource.ts +198 -0
  1310. package/src/setup/retune.ts +415 -0
  1311. package/src/setup/retunelog.ts +95 -0
  1312. package/src/setup/scan.ts +1033 -0
  1313. package/src/setup/scanbuild.ts +168 -0
  1314. package/src/setup/scanfacts.ts +107 -0
  1315. package/src/setup/scanlease.ts +297 -0
  1316. package/src/setup/scanreport.ts +373 -0
  1317. package/src/setup/scanrun.ts +2268 -0
  1318. package/src/setup/scantree.ts +259 -0
  1319. package/src/setup/stage2.ts +926 -0
  1320. package/src/setup/stage2request.ts +347 -0
  1321. package/src/setup/survey.ts +458 -0
  1322. package/src/setup/surveyrun.ts +758 -0
  1323. package/src/setup/textsniff.ts +95 -0
  1324. package/src/setup/trackersink.ts +433 -0
  1325. package/src/setup/triage.ts +768 -0
  1326. package/src/setup/tuning.ts +766 -0
  1327. package/src/setup/unitcut.ts +523 -0
  1328. package/src/singleflight.ts +86 -0
  1329. package/src/slack/announce.ts +911 -0
  1330. package/src/slack/api.ts +303 -0
  1331. package/src/slack/messages.ts +288 -0
  1332. package/src/slack/origin.ts +599 -0
  1333. package/src/slack/policy.ts +354 -0
  1334. package/src/slack/reply.ts +201 -0
  1335. package/src/slack/router.ts +285 -0
  1336. package/src/slack/socket.ts +384 -0
  1337. package/src/slack/types.ts +108 -0
  1338. package/src/sqlitehint.ts +32 -0
  1339. package/src/ssh-observation.ts +30 -0
  1340. package/src/state.ts +8243 -0
  1341. package/src/statemachine.ts +369 -0
  1342. package/src/stubs.ts +68 -0
  1343. package/src/takeover.ts +634 -0
  1344. package/src/takeoverpi.ts +293 -0
  1345. package/src/terminal-failure.ts +41 -0
  1346. package/src/thread-resolution-refusal.ts +2 -0
  1347. package/src/tmux.ts +153 -0
  1348. package/src/trackerid.ts +41 -0
  1349. package/src/transcriptindex.ts +665 -0
  1350. package/src/tui/actions.ts +484 -0
  1351. package/src/tui/alerts.ts +666 -0
  1352. package/src/tui/app.ts +1979 -0
  1353. package/src/tui/archiveops.ts +192 -0
  1354. package/src/tui/autofile.ts +233 -0
  1355. package/src/tui/board.ts +1432 -0
  1356. package/src/tui/candidates.ts +889 -0
  1357. package/src/tui/cellwidth.ts +148 -0
  1358. package/src/tui/changelog-store.ts +503 -0
  1359. package/src/tui/chord.ts +25 -0
  1360. package/src/tui/clipboard.ts +92 -0
  1361. package/src/tui/cmdbar.ts +296 -0
  1362. package/src/tui/companion.ts +1427 -0
  1363. package/src/tui/companionplan.ts +247 -0
  1364. package/src/tui/companiontab.ts +83 -0
  1365. package/src/tui/confighome.ts +155 -0
  1366. package/src/tui/connect.ts +68 -0
  1367. package/src/tui/deploy-ceremony.ts +104 -0
  1368. package/src/tui/deploy-drain.ts +129 -0
  1369. package/src/tui/deploy-process.ts +265 -0
  1370. package/src/tui/deploytab.ts +1523 -0
  1371. package/src/tui/design.ts +125 -0
  1372. package/src/tui/digesttab.ts +214 -0
  1373. package/src/tui/emptystate.ts +39 -0
  1374. package/src/tui/evidence.ts +999 -0
  1375. package/src/tui/feed.ts +604 -0
  1376. package/src/tui/feedbacktab.ts +1077 -0
  1377. package/src/tui/filters.ts +90 -0
  1378. package/src/tui/ghread.ts +321 -0
  1379. package/src/tui/historypull.ts +81 -0
  1380. package/src/tui/inboxpull.ts +236 -0
  1381. package/src/tui/index.ts +1565 -0
  1382. package/src/tui/issuesink.ts +238 -0
  1383. package/src/tui/jsonfile.ts +42 -0
  1384. package/src/tui/keys.ts +109 -0
  1385. package/src/tui/layout.ts +108 -0
  1386. package/src/tui/learning.ts +627 -0
  1387. package/src/tui/lessonswitch.ts +118 -0
  1388. package/src/tui/livecontrol.ts +228 -0
  1389. package/src/tui/memforward.ts +443 -0
  1390. package/src/tui/memincident.ts +363 -0
  1391. package/src/tui/memory.ts +620 -0
  1392. package/src/tui/memtab.ts +606 -0
  1393. package/src/tui/metricstab.ts +1177 -0
  1394. package/src/tui/model.ts +131 -0
  1395. package/src/tui/mouse.ts +98 -0
  1396. package/src/tui/msg.ts +268 -0
  1397. package/src/tui/nativecompanion.ts +417 -0
  1398. package/src/tui/openurl.ts +21 -0
  1399. package/src/tui/paint.ts +511 -0
  1400. package/src/tui/panes.ts +98 -0
  1401. package/src/tui/pipane.ts +219 -0
  1402. package/src/tui/poll-hooks.ts +12 -0
  1403. package/src/tui/poll.ts +147 -0
  1404. package/src/tui/proposals.ts +838 -0
  1405. package/src/tui/prpause.ts +150 -0
  1406. package/src/tui/reload.ts +436 -0
  1407. package/src/tui/remote.ts +413 -0
  1408. package/src/tui/rollover.ts +969 -0
  1409. package/src/tui/scantab.ts +1290 -0
  1410. package/src/tui/setupentry.ts +93 -0
  1411. package/src/tui/sidebar.ts +749 -0
  1412. package/src/tui/sshtriage.ts +510 -0
  1413. package/src/tui/startup.ts +231 -0
  1414. package/src/tui/tabs.ts +45 -0
  1415. package/src/tui/termmirror.ts +224 -0
  1416. package/src/tui/theme.ts +95 -0
  1417. package/src/tui/ticketstab.ts +310 -0
  1418. package/src/tui/tmuxsocket.ts +129 -0
  1419. package/src/tui/trackertickets.ts +84 -0
  1420. package/src/tui/unwedge.ts +286 -0
  1421. package/src/tui/viewer.ts +575 -0
  1422. package/src/tui/viewerinput.ts +173 -0
  1423. package/src/updatenotice.ts +178 -0
  1424. package/src/usage.ts +1154 -0
  1425. package/src/verdicts.ts +4689 -0
  1426. package/src/version.ts +80 -0
  1427. package/src/wakes.ts +476 -0
  1428. package/src/webhook.ts +942 -0
  1429. package/src/webhookheal.ts +276 -0
  1430. package/src/wire.ts +2153 -0
  1431. package/src/worker-session-host.ts +602 -0
  1432. package/src/workerbreaker.ts +156 -0
  1433. package/src/workercontrol.ts +104 -0
  1434. package/src/workerlease.ts +441 -0
  1435. package/src/workerliveness.ts +103 -0
  1436. package/src/workerlog.ts +79 -0
  1437. package/src/workerruntime.ts +30 -0
  1438. package/src/workersupervisor.ts +1538 -0
  1439. package/src/workerusage.ts +42 -0
  1440. package/src/workerworld.ts +427 -0
  1441. package/src/worktrees.ts +1138 -0
  1442. package/tests/fixtures/regression-cases.json +795 -0
  1443. package/tests/fixtures/seed-manifest.json +19 -0
@@ -0,0 +1,1028 @@
1
+ // The ping-pong path: an author replies in one of the bot's threads, the
2
+ // daemon wakes the PR session with thread context, the session posts exactly
3
+ // one reply through the gate.
4
+ //
5
+ // Reply discipline (conversation-system.md): one reply per author
6
+ // message; ≤3 exchanges per finding, then concede-or-hold; replies never change
7
+ // a posted verdict; no new findings in ping-pong. The mechanical halves — "one
8
+ // reply per message" and the exchange cap — are enforced here in SQLite; the
9
+ // judgment halves are prompt-side, restated in every wake message.
10
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, watch, writeFileSync, } from "node:fs";
11
+ import { join } from "node:path";
12
+ import { GitHubRequestError } from "./github.js";
13
+ /** Three exchanges per finding, then concede or hold. */
14
+ export const MAX_EXCHANGES_PER_FINDING = 3;
15
+ const SCHEMA = `
16
+ CREATE TABLE IF NOT EXISTS pingpong_threads (
17
+ thread_id INTEGER PRIMARY KEY,
18
+ pr INTEGER NOT NULL,
19
+ exchanges INTEGER NOT NULL DEFAULT 0,
20
+ updated_at TEXT NOT NULL
21
+ );
22
+ CREATE TABLE IF NOT EXISTS pingpong_handled (
23
+ comment_id INTEGER PRIMARY KEY,
24
+ thread_id INTEGER NOT NULL,
25
+ pr INTEGER NOT NULL,
26
+ handled_at TEXT NOT NULL
27
+ );
28
+ CREATE TABLE IF NOT EXISTS pingpong_decisions (
29
+ comment_id INTEGER PRIMARY KEY,
30
+ reply_posted INTEGER NOT NULL DEFAULT 0,
31
+ thread_resolved INTEGER NOT NULL DEFAULT 0,
32
+ updated_at TEXT NOT NULL
33
+ );
34
+ CREATE TABLE IF NOT EXISTS pingpong_decision_retries (
35
+ comment_id INTEGER PRIMARY KEY,
36
+ attempts INTEGER NOT NULL DEFAULT 0,
37
+ next_attempt_at TEXT,
38
+ last_error TEXT,
39
+ terminal INTEGER NOT NULL DEFAULT 0,
40
+ updated_at TEXT NOT NULL
41
+ );
42
+ CREATE TABLE IF NOT EXISTS pingpong_decision_breaker (
43
+ singleton INTEGER PRIMARY KEY CHECK (singleton = 1),
44
+ state TEXT NOT NULL CHECK (state IN ('closed', 'open', 'half_open')),
45
+ open_until TEXT,
46
+ rate_limit_streak INTEGER NOT NULL DEFAULT 0,
47
+ probe_started_at TEXT,
48
+ last_error TEXT,
49
+ updated_at TEXT NOT NULL
50
+ );
51
+ `;
52
+ export function threadIdOf(event) {
53
+ return event.in_reply_to_id || event.comment_id;
54
+ }
55
+ /**
56
+ * Exchange bookkeeping for ping-pong, in the same SQLite file as the rest of
57
+ * the state (own tables, created on construction).
58
+ */
59
+ export class PingPongLedger {
60
+ db;
61
+ now;
62
+ constructor(db, now = () => new Date()) {
63
+ this.db = db;
64
+ this.now = now;
65
+ this.db.exec(SCHEMA);
66
+ // Additive column: cap hits per thread (the ping-pong depth metric).
67
+ try {
68
+ this.db.exec("ALTER TABLE pingpong_threads ADD COLUMN cap_hits INTEGER NOT NULL DEFAULT 0");
69
+ }
70
+ catch {
71
+ /* column already present */
72
+ }
73
+ // Additive column: the human-request callback ran for this decision.
74
+ try {
75
+ this.db.exec("ALTER TABLE pingpong_decisions ADD COLUMN human_notified INTEGER NOT NULL DEFAULT 0");
76
+ }
77
+ catch {
78
+ /* column already present */
79
+ }
80
+ // Additive column: a reply POST was started for this decision.
81
+ try {
82
+ this.db.exec("ALTER TABLE pingpong_decisions ADD COLUMN reply_attempted INTEGER NOT NULL DEFAULT 0");
83
+ }
84
+ catch {
85
+ /* column already present */
86
+ }
87
+ }
88
+ ts() {
89
+ return this.now().toISOString();
90
+ }
91
+ exchanges(threadId) {
92
+ const row = this.db
93
+ .prepare("SELECT exchanges FROM pingpong_threads WHERE thread_id = ?")
94
+ .get(threadId);
95
+ return row?.exchanges ?? 0;
96
+ }
97
+ /**
98
+ * Claim an author message for exactly one reply. Returns false when this
99
+ * comment id was already handled (duplicate delivery or reconcile replay).
100
+ */
101
+ claimAuthorMessage(event) {
102
+ const info = this.db
103
+ .prepare("INSERT OR IGNORE INTO pingpong_handled (comment_id, thread_id, pr, handled_at) VALUES (?, ?, ?, ?)")
104
+ .run(event.comment_id, threadIdOf(event), event.pr, this.ts());
105
+ return info.changes === 1;
106
+ }
107
+ hasClaim(pr, threadId, commentId) {
108
+ return (this.db
109
+ .prepare("SELECT 1 FROM pingpong_handled WHERE comment_id = ? AND thread_id = ? AND pr = ?")
110
+ .get(commentId, threadId, pr) !== undefined);
111
+ }
112
+ /** A decision's progress. `reply_attempted`: a reply POST was started (it
113
+ * may have landed although no answer came back); `reply_posted`: the reply
114
+ * step is done; `thread_resolved`: the resolve step is done — GitHub may have
115
+ * answered a human-only skip, which the `pingpong_thread_resolved` event's
116
+ * `skipped` records. */
117
+ decisionProgress(commentId) {
118
+ const row = this.db
119
+ .prepare("SELECT reply_attempted, reply_posted, thread_resolved, human_notified FROM pingpong_decisions WHERE comment_id = ?")
120
+ .get(commentId);
121
+ return {
122
+ reply_attempted: row?.reply_attempted === 1,
123
+ reply_posted: row?.reply_posted === 1,
124
+ thread_resolved: row?.thread_resolved === 1,
125
+ human_notified: row?.human_notified === 1,
126
+ };
127
+ }
128
+ markDecisionStep(commentId, step) {
129
+ this.db
130
+ .prepare(`INSERT INTO pingpong_decisions (comment_id, ${step}, updated_at)
131
+ VALUES (?, 1, ?)
132
+ ON CONFLICT(comment_id) DO UPDATE SET ${step} = 1, updated_at = excluded.updated_at`)
133
+ .run(commentId, this.ts());
134
+ }
135
+ breaker() {
136
+ const row = this.db
137
+ .prepare("SELECT state, open_until, rate_limit_streak FROM pingpong_decision_breaker WHERE singleton = 1")
138
+ .get();
139
+ return row
140
+ ? {
141
+ state: row.state,
142
+ ...(row.open_until ? { open_until: row.open_until } : {}),
143
+ rate_limit_streak: row.rate_limit_streak,
144
+ }
145
+ : { state: "closed", rate_limit_streak: 0 };
146
+ }
147
+ openBreaker(now, error) {
148
+ const streak = this.breaker().rate_limit_streak + 1;
149
+ const delays = [60, 120, 240, 480, 900];
150
+ const openUntil = new Date(now.getTime() + delays[Math.min(streak - 1, delays.length - 1)] * 1000).toISOString();
151
+ this.db
152
+ .prepare(`INSERT INTO pingpong_decision_breaker (singleton, state, open_until, rate_limit_streak, last_error, updated_at)
153
+ VALUES (1, 'open', ?, ?, ?, ?)
154
+ ON CONFLICT(singleton) DO UPDATE SET state='open', open_until=excluded.open_until,
155
+ rate_limit_streak=excluded.rate_limit_streak, last_error=excluded.last_error, updated_at=excluded.updated_at`)
156
+ .run(openUntil, streak, error, now.toISOString());
157
+ return { open_until: openUntil, streak };
158
+ }
159
+ halfOpen(now) {
160
+ this.db
161
+ .prepare(`INSERT INTO pingpong_decision_breaker (singleton, state, open_until, rate_limit_streak, probe_started_at, updated_at)
162
+ VALUES (1, 'half_open', NULL, 0, ?, ?)
163
+ ON CONFLICT(singleton) DO UPDATE SET state='half_open', probe_started_at=excluded.probe_started_at, updated_at=excluded.updated_at`)
164
+ .run(now.toISOString(), now.toISOString());
165
+ }
166
+ recoverHalfOpen(now) {
167
+ this.db
168
+ .prepare("UPDATE pingpong_decision_breaker SET state='open', probe_started_at=NULL, updated_at=? WHERE singleton=1 AND state='half_open'")
169
+ .run(now.toISOString());
170
+ }
171
+ closeBreaker(now) {
172
+ this.db
173
+ .prepare(`INSERT INTO pingpong_decision_breaker (singleton, state, open_until, rate_limit_streak, updated_at)
174
+ VALUES (1, 'closed', NULL, 0, ?)
175
+ ON CONFLICT(singleton) DO UPDATE SET state='closed', open_until=NULL, rate_limit_streak=0,
176
+ last_error=NULL, updated_at=excluded.updated_at`)
177
+ .run(now.toISOString());
178
+ }
179
+ retry(commentId) {
180
+ const row = this.db
181
+ .prepare("SELECT attempts, next_attempt_at, last_error, terminal FROM pingpong_decision_retries WHERE comment_id = ?")
182
+ .get(commentId);
183
+ return row
184
+ ? {
185
+ attempts: row.attempts,
186
+ ...(row.next_attempt_at ? { next_attempt_at: row.next_attempt_at } : {}),
187
+ ...(row.last_error ? { last_error: row.last_error } : {}),
188
+ terminal: row.terminal === 1,
189
+ }
190
+ : { attempts: 0, terminal: false };
191
+ }
192
+ recordRetry(commentId, now, error) {
193
+ const attempts = this.retry(commentId).attempts + 1;
194
+ const terminal = attempts >= 3;
195
+ const delays = [30, 120];
196
+ const next = terminal
197
+ ? undefined
198
+ : new Date(now.getTime() + delays[attempts - 1] * 1000).toISOString();
199
+ this.db
200
+ .prepare(`INSERT INTO pingpong_decision_retries (comment_id, attempts, next_attempt_at, last_error, terminal, updated_at)
201
+ VALUES (?, ?, ?, ?, ?, ?)
202
+ ON CONFLICT(comment_id) DO UPDATE SET attempts=excluded.attempts, next_attempt_at=excluded.next_attempt_at,
203
+ last_error=excluded.last_error, terminal=excluded.terminal, updated_at=excluded.updated_at`)
204
+ .run(commentId, attempts, next ?? null, error, terminal ? 1 : 0, now.toISOString());
205
+ return { attempts, ...(next ? { next_attempt_at: next } : {}), terminal };
206
+ }
207
+ resetRetry(commentId) {
208
+ this.db.prepare("DELETE FROM pingpong_decision_retries WHERE comment_id = ?").run(commentId);
209
+ }
210
+ /** Whether a reply may be posted in this thread, and whether it is the last. */
211
+ discipline(threadId) {
212
+ const exchanges = this.exchanges(threadId);
213
+ if (exchanges >= MAX_EXCHANGES_PER_FINDING) {
214
+ return { allowed: false, exchanges, final: true, reason: "exchange-cap-reached" };
215
+ }
216
+ return { allowed: true, exchanges, final: exchanges === MAX_EXCHANGES_PER_FINDING - 1 };
217
+ }
218
+ /** Record that the exchange cap blocked a reply in this thread. The row is
219
+ * created if the cap was reached without any reply ever being counted here
220
+ * (defensive — the counter is the same row `recordExchange` maintains). */
221
+ recordCapHit(threadId, pr) {
222
+ this.db
223
+ .prepare(`INSERT INTO pingpong_threads (thread_id, pr, exchanges, cap_hits, updated_at) VALUES (?, ?, 0, 1, ?)
224
+ ON CONFLICT(thread_id) DO UPDATE SET cap_hits = cap_hits + 1, updated_at = excluded.updated_at`)
225
+ .run(threadId, pr, this.ts());
226
+ return this.capHits(threadId);
227
+ }
228
+ capHits(threadId) {
229
+ const row = this.db
230
+ .prepare("SELECT cap_hits FROM pingpong_threads WHERE thread_id = ?")
231
+ .get(threadId);
232
+ return row?.cap_hits ?? 0;
233
+ }
234
+ /** Count a posted reply. Returns the new exchange count. */
235
+ recordExchange(threadId, pr) {
236
+ this.db
237
+ .prepare(`INSERT INTO pingpong_threads (thread_id, pr, exchanges, updated_at) VALUES (?, ?, 1, ?)
238
+ ON CONFLICT(thread_id) DO UPDATE SET exchanges = exchanges + 1, updated_at = excluded.updated_at`)
239
+ .run(threadId, pr, this.ts());
240
+ return this.exchanges(threadId);
241
+ }
242
+ /** Count and receipt a decision's reply with its synchronous local writes.
243
+ * The daemon's registry and event log share this SQLite connection. */
244
+ recordReply(threadId, pr, decisionCommentId, localReceipt) {
245
+ return this.db
246
+ .transaction(() => {
247
+ if (decisionCommentId !== undefined &&
248
+ this.decisionProgress(decisionCommentId).reply_posted)
249
+ return this.exchanges(threadId);
250
+ const exchanges = this.recordExchange(threadId, pr);
251
+ localReceipt(exchanges);
252
+ if (decisionCommentId !== undefined)
253
+ this.markDecisionStep(decisionCommentId, "reply_posted");
254
+ return exchanges;
255
+ })
256
+ .immediate();
257
+ }
258
+ }
259
+ // ---- the wake message ----------------------------------------------------
260
+ /** The decision file's `outcome` field, as the wake states it. */
261
+ const OUTCOME_FIELD_NOTE = "`outcome` records what became of the finding: `fixed` (the code at the head now " +
262
+ "addresses it), `refuted` (you accept the author's argument — it was wrong or does " +
263
+ "not apply) or `held` (you keep it open). Leave it out when you cannot tell.";
264
+ /** How an author-reply wake begins: the heading plus the PR number. The
265
+ * held-wake coalescer recognises a recovered author reply by it. */
266
+ export const AUTHOR_REPLY_WAKE_HEADING = "# Author reply — PR #";
267
+ /**
268
+ * The inject payload that wakes the PR session for one author reply. The
269
+ * daemon writes it through the session hooks (`inject(pr, message)`); the
270
+ * discipline rules are restated every time because a compacted session may no
271
+ * longer hold them verbatim.
272
+ */
273
+ export function buildWakeMessage(event, ctx, discipline) {
274
+ const quoted = event.body
275
+ .trim()
276
+ .split("\n")
277
+ .map((l) => `> ${l}`)
278
+ .join("\n");
279
+ const lines = [
280
+ `${AUTHOR_REPLY_WAKE_HEADING}${event.pr}`,
281
+ "",
282
+ `**Thread**: \`${threadIdOf(event)}\`${ctx.finding_id ? ` (ledger ${ctx.finding_id})` : ""}` +
283
+ `${event.path ? ` · \`${event.path}\`` : ""}`,
284
+ `**From**: @${event.author} (comment \`${event.comment_id}\`)`,
285
+ ...(ctx.head_sha
286
+ ? [`**Head**: \`${ctx.head_sha}\`${ctx.worktree ? ` · worktree \`${ctx.worktree}\`` : ""}`]
287
+ : []),
288
+ `**Exchanges so far in this thread**: ${discipline.exchanges}/${MAX_EXCHANGES_PER_FINDING}`,
289
+ "",
290
+ ];
291
+ if (ctx.finding) {
292
+ lines.push("## Your finding in this thread", "", ctx.finding.trim(), "");
293
+ }
294
+ lines.push("## Their message", "", quoted, "", "## What to do");
295
+ if (!discipline.allowed) {
296
+ lines.push("", `The ${MAX_EXCHANGES_PER_FINDING}-exchange cap for this finding is reached. **Do not reply again.**`, "Inspect the current code and rationale anyway. Write the structured response file", `\`verdict/pr-${event.pr}-thread-${threadIdOf(event)}-comment-${event.comment_id}.json\` with`, `{"pr":${event.pr},"thread_id":${threadIdOf(event)},"comment_id":${event.comment_id},` +
297
+ '"resolution":"resolve|keep_open","reply":"","reason":"why","human_requested":false,' +
298
+ '"outcome":"fixed|refuted|held"}.', OUTCOME_FIELD_NOTE, "The daemon may resolve a satisfied thread, but it will not post a fourth reply.", "Mark the finding `conceded` or `held` in the ledger; only an explicit", "review re-request can start another round.");
299
+ }
300
+ else {
301
+ lines.push("", "- Post **one** reply to this message — brief, concrete, code-anchored.", "- Verify their claim mechanically at the current head; a claim is never a fact.", "- **Concede** (mark `conceded` in the ledger — settled next round) or **hold**", ' ("keeping this open for the next review round — re-add the `AI review requested`', ' label (or re-request the `review` team) when ready").', "- **Never change a posted verdict** — only a round can.", "- **No new findings**: record new observations in the ledger as `deferred`.", "- Decide whether the finding is now satisfied: inspect the current code and", " accept a sound author rationale. Never treat either as satisfied without checking.", `- Write exactly one response file at \`verdict/pr-${event.pr}-thread-${threadIdOf(event)}-comment-${event.comment_id}.json\``, " atomically, with this shape:", ` {"pr":${event.pr},"thread_id":${threadIdOf(event)},"comment_id":${event.comment_id},` +
302
+ '"resolution":"resolve|keep_open","reply":"brief reply","reason":"why",' +
303
+ '"human_requested":false,"outcome":"fixed|refuted|held"}.', " Use `resolve` only when the code addresses the finding or the rationale is satisfactory.", ` ${OUTCOME_FIELD_NOTE}`, " The daemon posts the reply and, for `resolve`, resolves this bot-owned thread.", "- If they ask for a human, set `human_requested: true` in that response file.", " The daemon records the request for the operator; it is NOT a handover, so", " do not promise one. Say that this review is not held for a person, and put", " the residual doubt where a human will see it: a `[check this]` item and the", " review body's `### For a human to double-check` section next round.");
304
+ if (discipline.final) {
305
+ lines.push("", `This is exchange ${discipline.exchanges + 1}/${MAX_EXCHANGES_PER_FINDING} — the **last** one on this`, "finding. Concede or hold in this reply; do not open another loop.");
306
+ }
307
+ }
308
+ return lines.join("\n");
309
+ }
310
+ /** Post one thread reply through the gate and register the posted comment id. */
311
+ export async function postReply(deps, input) {
312
+ if (input.decision_comment_id !== undefined &&
313
+ deps.ledger.decisionProgress(input.decision_comment_id).reply_posted)
314
+ return { posted: true, exchanges: deps.ledger.exchanges(input.thread_id) };
315
+ const discipline = deps.ledger.discipline(input.thread_id);
316
+ if (!discipline.allowed) {
317
+ const capHits = deps.ledger.recordCapHit(input.thread_id, input.pr);
318
+ deps.store.logEvent("pingpong_reply_suppressed", input.pr, {
319
+ thread_id: input.thread_id,
320
+ reason: discipline.reason,
321
+ cap_hits: capHits,
322
+ });
323
+ return {
324
+ posted: false,
325
+ exchanges: discipline.exchanges,
326
+ ...(discipline.reason ? { reason: discipline.reason } : {}),
327
+ };
328
+ }
329
+ const result = await deps.adapter.createReviewCommentReply(input.pr, input.thread_id, input.body);
330
+ if (result.blocked) {
331
+ // A posting guard refused (PR merged/closed, or its state unreadable).
332
+ // Nothing was posted, so nothing is counted against the exchange cap.
333
+ deps.store.logEvent("pingpong_reply_blocked", input.pr, {
334
+ thread_id: input.thread_id,
335
+ reason: result.blocked,
336
+ });
337
+ return { posted: false, result, exchanges: discipline.exchanges, blocked: result.blocked };
338
+ }
339
+ let registered;
340
+ const exchanges = deps.ledger.recordReply(input.thread_id, input.pr, input.decision_comment_id, (exchanges) => {
341
+ if (result.executed) {
342
+ const res = result.response;
343
+ if (typeof res?.id === "number") {
344
+ deps.store.registerBotComment(res.id, input.pr, "review_comment");
345
+ registered = res.id;
346
+ }
347
+ deps.store.logEvent("pingpong_reply_posted", input.pr, {
348
+ thread_id: input.thread_id,
349
+ exchanges,
350
+ });
351
+ }
352
+ else {
353
+ deps.store.logEvent("pingpong_reply_intent", input.pr, {
354
+ thread_id: input.thread_id,
355
+ exchanges,
356
+ dryrun_file: result.dryRunFile ?? null,
357
+ });
358
+ }
359
+ });
360
+ return { posted: true, result, exchanges, ...(registered !== undefined ? { registered } : {}) };
361
+ }
362
+ // ---- structured thread decisions -----------------------------------------
363
+ export const THREAD_DECISION_RE = /^pr-(\d+)-thread-(\d+)-comment-(\d+)\.json$/;
364
+ /** The hidden line a decision's reply carries: the author message it answers.
365
+ * A retry finds its own landed reply by it — never another decision's reply
366
+ * that happens to say the same words. */
367
+ export function replyMarker(commentId) {
368
+ return `<!-- qcr:reply=${commentId} -->`;
369
+ }
370
+ const REPLY_MARKER_RE = /<!-- qcr:reply=\d+ -->/;
371
+ const THREAD_OUTCOME_ALIASES = {
372
+ fixed: "fixed",
373
+ fix: "fixed",
374
+ addressed: "fixed",
375
+ refuted: "refuted",
376
+ refute: "refuted",
377
+ held: "held",
378
+ hold: "held",
379
+ upheld: "held",
380
+ kept: "held",
381
+ keep_open: "held",
382
+ };
383
+ /** The outcome a decision file names, folded onto the closed set. Anything
384
+ * else — absent, `unknown`, `conceded` (which the ledger uses for fixes and
385
+ * refutations alike), a typo — is no outcome: never a guess, and never a
386
+ * reason to refuse the decision, whose reply must still be posted. */
387
+ export function normalizeThreadOutcome(raw) {
388
+ if (typeof raw !== "string")
389
+ return undefined;
390
+ const word = raw
391
+ .trim()
392
+ .toLowerCase()
393
+ .replace(/[\s-]+/g, "_");
394
+ return Object.hasOwn(THREAD_OUTCOME_ALIASES, word) ? THREAD_OUTCOME_ALIASES[word] : undefined;
395
+ }
396
+ export function validateThreadDecision(raw) {
397
+ if (typeof raw !== "object" || raw === null)
398
+ return { ok: false, error: "not an object" };
399
+ const v = raw;
400
+ for (const key of ["pr", "thread_id", "comment_id"]) {
401
+ if (typeof v[key] === "string" && /^\d+$/.test(v[key]))
402
+ v[key] = Number(v[key]);
403
+ if (!Number.isInteger(v[key]))
404
+ return { ok: false, error: `${key} must be an integer` };
405
+ }
406
+ if (v.resolution !== "resolve" && v.resolution !== "keep_open")
407
+ return { ok: false, error: "bad resolution" };
408
+ if (typeof v.reply !== "string")
409
+ return { ok: false, error: "reply must be a string" };
410
+ if (v.reason !== undefined && typeof v.reason !== "string")
411
+ return { ok: false, error: "reason must be a string" };
412
+ if (v.human_requested !== undefined && typeof v.human_requested !== "boolean")
413
+ return { ok: false, error: "human_requested must be boolean" };
414
+ // Tolerant on purpose: an outcome the parser does not know is dropped, never
415
+ // a rejection — rejecting would drop the reply with it.
416
+ const outcome = normalizeThreadOutcome(v.outcome);
417
+ if (outcome)
418
+ v.outcome = outcome;
419
+ else
420
+ delete v.outcome;
421
+ return { ok: true, value: v };
422
+ }
423
+ export function classifyThreadDecisionError(error) {
424
+ // The adapter's own error carries the HTTP status structurally; its message
425
+ // puts the request path between the method and the status, so the text
426
+ // heuristics below can miss a REST 429 on a long route.
427
+ if (error instanceof GitHubRequestError && error.status === 429)
428
+ return "rate_limit";
429
+ const text = String(error);
430
+ if (/(?:graphql|github|http|status)[^\n]{0,24}\b429\b/i.test(text) ||
431
+ /graphql_rate_limit|\bRATE_LIMIT\b/.test(text))
432
+ return "rate_limit";
433
+ if (/\b403\b/.test(text) && /rate.?limit|secondary.?rate|abuse.?detect/i.test(text))
434
+ return "rate_limit";
435
+ return "non_rate";
436
+ }
437
+ /** Reliable session→daemon handoff for ping-pong judgments. Session output is
438
+ * treated as untrusted: ids must match a claimed author message, and the
439
+ * adapter independently verifies bot ownership before resolving a thread. */
440
+ export class ThreadDecisionWatcher {
441
+ deps;
442
+ watcher = null;
443
+ inFlight = new Set();
444
+ /** An unusable read of a decision file: its bytes and when they were first
445
+ * seen unchanged. */
446
+ invalidReads = new Map();
447
+ retryTimers = new Map();
448
+ processedDir;
449
+ failedDir;
450
+ pauseLogged = false;
451
+ sweeping = false;
452
+ schedulerTimer;
453
+ schedulerDeadline = 0;
454
+ lastGitHubStart = 0;
455
+ processing = false;
456
+ cursor = 0;
457
+ constructor(deps) {
458
+ this.deps = deps;
459
+ this.processedDir = join(deps.verdictDir, "processed");
460
+ this.failedDir = join(deps.verdictDir, "failed");
461
+ }
462
+ githubDelayMs(now) {
463
+ return this.lastGitHubStart > 0
464
+ ? Math.max(0, 5_000 - (now.getTime() - this.lastGitHubStart))
465
+ : 0;
466
+ }
467
+ deadlinePending(deadline, now) {
468
+ return !!deadline && Date.parse(deadline) > now.getTime();
469
+ }
470
+ breakerWaiting(breaker, now) {
471
+ return (breaker.state === "open" &&
472
+ (!breaker.open_until || this.deadlinePending(breaker.open_until, now)));
473
+ }
474
+ recoverInterruptedReplays() {
475
+ if (!existsSync(this.deps.verdictDir))
476
+ return;
477
+ for (const name of readdirSync(this.deps.verdictDir).filter((entry) => THREAD_DECISION_RE.test(entry))) {
478
+ const match = THREAD_DECISION_RE.exec(name);
479
+ const retry = this.deps.ledger.retry(Number(match[3]));
480
+ if (retry.terminal) {
481
+ this.quarantineTerminal(name, Number(match[1]), Number(match[2]), Number(match[3]), retry.attempts);
482
+ }
483
+ }
484
+ }
485
+ recoverOwnerAliasFailures(alias) {
486
+ if (!alias || !existsSync(this.failedDir))
487
+ return { restored: 0, refused: 0 };
488
+ let restored = 0;
489
+ let refused = 0;
490
+ for (const name of readdirSync(this.failedDir)
491
+ .filter((entry) => THREAD_DECISION_RE.test(entry))
492
+ .sort()) {
493
+ try {
494
+ const match = THREAD_DECISION_RE.exec(name);
495
+ const pr = Number(match[1]);
496
+ const threadId = Number(match[2]);
497
+ const commentId = Number(match[3]);
498
+ const retry = this.deps.ledger.retry(commentId);
499
+ const expected = `Error: refusing to resolve thread ${threadId} on #${pr}: root author is ${alias}`;
500
+ if (!retry.terminal || retry.last_error !== expected)
501
+ continue;
502
+ const parsed = validateThreadDecision(JSON.parse(readFileSync(join(this.failedDir, name), "utf8")));
503
+ if (!parsed.ok ||
504
+ parsed.value.pr !== pr ||
505
+ parsed.value.thread_id !== threadId ||
506
+ parsed.value.comment_id !== commentId ||
507
+ !this.deps.ledger.hasClaim(pr, threadId, commentId)) {
508
+ refused += 1;
509
+ continue;
510
+ }
511
+ if (!this.restoreFailed(name, commentId)) {
512
+ refused += 1;
513
+ continue;
514
+ }
515
+ this.deps.store.logEvent("pingpong_owner_alias_failure_restored", pr, {
516
+ file: name,
517
+ thread_id: threadId,
518
+ comment_id: commentId,
519
+ alias,
520
+ });
521
+ restored += 1;
522
+ }
523
+ catch (err) {
524
+ refused += 1;
525
+ this.deps.log?.(`pingpong: could not restore owner-alias failure ${name}`, err);
526
+ }
527
+ }
528
+ if (restored > 0) {
529
+ this.deps.store.logEvent("pingpong_owner_alias_backlog_restored", null, {
530
+ alias,
531
+ restored,
532
+ refused,
533
+ });
534
+ this.requestSweep();
535
+ }
536
+ return { restored, refused };
537
+ }
538
+ /** Move a failed decision back to pending and clear its retry state —
539
+ * false when a pending file of that name is already there. File first,
540
+ * metadata second: if the process dies between them, the startup sweep sees
541
+ * terminal metadata beside a pending file and moves it back to failed/, so
542
+ * the replay can safely be asked for again. */
543
+ restoreFailed(name, commentId) {
544
+ const destination = join(this.deps.verdictDir, name);
545
+ if (existsSync(destination))
546
+ return false;
547
+ renameSync(join(this.failedDir, name), destination);
548
+ this.deps.ledger.resetRetry(commentId);
549
+ return true;
550
+ }
551
+ retryFailed(commentId) {
552
+ try {
553
+ if (!existsSync(this.failedDir))
554
+ return { ok: false, reason: `no failed thread decision for comment ${commentId}` };
555
+ const matches = readdirSync(this.failedDir).filter((name) => {
556
+ const m = THREAD_DECISION_RE.exec(name);
557
+ return m && Number(m[3]) === commentId;
558
+ });
559
+ if (matches.length !== 1)
560
+ return {
561
+ ok: false,
562
+ reason: matches.length === 0
563
+ ? `no failed thread decision for comment ${commentId}`
564
+ : `ambiguous failed decisions for comment ${commentId}`,
565
+ };
566
+ const name = matches[0];
567
+ const parsed = validateThreadDecision(JSON.parse(readFileSync(join(this.failedDir, name), "utf8")));
568
+ if (!parsed.ok ||
569
+ parsed.value.comment_id !== commentId ||
570
+ !this.deps.ledger.retry(commentId).terminal) {
571
+ return { ok: false, reason: `failed decision ${name} does not match terminal retry state` };
572
+ }
573
+ if (!this.restoreFailed(name, commentId))
574
+ return { ok: false, reason: `pending destination already exists for ${name}` };
575
+ this.deps.store.logEvent("pingpong_decision_retry_requested", parsed.value.pr, {
576
+ file: name,
577
+ comment_id: commentId,
578
+ });
579
+ this.requestSweep();
580
+ return { ok: true, file: name };
581
+ }
582
+ catch (err) {
583
+ return {
584
+ ok: false,
585
+ reason: `could not restore failed thread decision ${commentId}: ${String(err)}`,
586
+ };
587
+ }
588
+ }
589
+ status() {
590
+ const breaker = this.deps.ledger.breaker();
591
+ const count = (dir) => existsSync(dir) ? readdirSync(dir).filter((name) => THREAD_DECISION_RE.test(name)).length : 0;
592
+ return {
593
+ breaker_state: breaker.state,
594
+ ...(breaker.open_until ? { open_until: breaker.open_until } : {}),
595
+ pending: count(this.deps.verdictDir),
596
+ failed: count(this.failedDir),
597
+ };
598
+ }
599
+ start() {
600
+ mkdirSync(this.deps.verdictDir, { recursive: true });
601
+ // Complete either side of an interrupted failed→pending recovery before
602
+ // applying the one-time alias migration. A terminal row beside a pending
603
+ // file means the prior process died after moving the file but before
604
+ // clearing metadata; put it back under failed/ so this same startup can
605
+ // reconsider it.
606
+ this.recoverInterruptedReplays();
607
+ if (this.deps.ownerActorAlias)
608
+ this.recoverOwnerAliasFailures(this.deps.ownerActorAlias);
609
+ this.requestSweep();
610
+ this.watcher = watch(this.deps.verdictDir, (_event, filename) => {
611
+ const name = filename ? String(filename) : "";
612
+ if (THREAD_DECISION_RE.test(name))
613
+ this.requestSweep();
614
+ });
615
+ }
616
+ /** Wake the one paced scheduler; filesystem and daemon callers never process directly. */
617
+ requestSweep(delayMs = 0) {
618
+ const deadline = Date.now() + Math.max(0, delayMs);
619
+ if (this.schedulerTimer && this.schedulerDeadline <= deadline)
620
+ return;
621
+ if (this.schedulerTimer)
622
+ clearTimeout(this.schedulerTimer);
623
+ this.schedulerDeadline = deadline;
624
+ this.schedulerTimer = setTimeout(() => {
625
+ this.schedulerTimer = undefined;
626
+ this.schedulerDeadline = 0;
627
+ void this.sweep().catch((err) => this.deps.log?.("pingpong scheduler failed", err));
628
+ }, delayMs);
629
+ this.schedulerTimer.unref?.();
630
+ }
631
+ stop() {
632
+ this.watcher?.close();
633
+ this.watcher = null;
634
+ if (this.schedulerTimer)
635
+ clearTimeout(this.schedulerTimer);
636
+ this.schedulerTimer = undefined;
637
+ this.schedulerDeadline = 0;
638
+ for (const timer of this.retryTimers.values())
639
+ clearTimeout(timer);
640
+ this.retryTimers.clear();
641
+ }
642
+ async sweep() {
643
+ if (this.sweeping || !existsSync(this.deps.verdictDir))
644
+ return [];
645
+ this.sweeping = true;
646
+ try {
647
+ if (this.deps.isDraining?.()) {
648
+ if (!this.pauseLogged) {
649
+ this.deps.store.logEvent("pingpong_decisions_paused_draining", null, {
650
+ pending: this.status().pending,
651
+ });
652
+ this.pauseLogged = true;
653
+ }
654
+ return [];
655
+ }
656
+ this.pauseLogged = false;
657
+ const now = (this.deps.now ?? (() => new Date()))();
658
+ const githubDelay = this.githubDelayMs(now);
659
+ if (githubDelay > 0) {
660
+ this.requestSweep(githubDelay);
661
+ return [];
662
+ }
663
+ const breaker = this.deps.ledger.breaker();
664
+ if (breaker.state === "open") {
665
+ if (this.breakerWaiting(breaker, now)) {
666
+ if (breaker.open_until)
667
+ this.requestSweep(Math.max(1, Date.parse(breaker.open_until) - now.getTime()));
668
+ return [];
669
+ }
670
+ // The cooldown is over; the probe starts at the first GitHub call.
671
+ }
672
+ else if (breaker.state === "half_open") {
673
+ // A live probe owns `sweeping`; observing persisted half-open here means
674
+ // the prior process died before recording its result. Recover without
675
+ // charging a synthetic rate-limit failure to the cooldown ladder.
676
+ this.deps.ledger.recoverHalfOpen(now);
677
+ this.requestSweep(1);
678
+ return [];
679
+ }
680
+ const files = readdirSync(this.deps.verdictDir)
681
+ .filter((name) => THREAD_DECISION_RE.test(name))
682
+ .sort();
683
+ if (files.length === 0)
684
+ return [];
685
+ const rotated = [
686
+ ...files.slice(this.cursor % files.length),
687
+ ...files.slice(0, this.cursor % files.length),
688
+ ];
689
+ let earliestRetry = Number.POSITIVE_INFINITY;
690
+ for (const name of rotated) {
691
+ const match = THREAD_DECISION_RE.exec(name);
692
+ const retry = this.deps.ledger.retry(Number(match[3]));
693
+ if (retry.terminal) {
694
+ this.quarantineTerminal(name, Number(match[1]), Number(match[2]), Number(match[3]), retry.attempts);
695
+ continue;
696
+ }
697
+ if (this.deadlinePending(retry.next_attempt_at, now)) {
698
+ earliestRetry = Math.min(earliestRetry, Date.parse(retry.next_attempt_at));
699
+ continue;
700
+ }
701
+ this.cursor = (files.indexOf(name) + 1) % files.length;
702
+ const done = await this.handleFile(name);
703
+ if (this.status().pending > 0)
704
+ this.requestSweep(5_000);
705
+ return done ? [name] : [];
706
+ }
707
+ if (Number.isFinite(earliestRetry))
708
+ this.requestSweep(Math.max(1, earliestRetry - now.getTime()));
709
+ return [];
710
+ }
711
+ finally {
712
+ this.sweeping = false;
713
+ }
714
+ }
715
+ /** A decision file that does not parse or does not validate. fs.watch
716
+ * commonly fires before a writer's last byte, so a read is provisional until
717
+ * the same bytes have sat unchanged for the settle window under our own
718
+ * observation; only then is the file malformed and archived. */
719
+ malformedRead(name, pr, body, error, now) {
720
+ const seen = this.invalidReads.get(name);
721
+ const settleMs = this.settleMs();
722
+ if (seen?.body !== body || now.getTime() - seen.since < settleMs) {
723
+ if (seen?.body !== body)
724
+ this.invalidReads.set(name, { body, since: now.getTime() });
725
+ this.retryAfterSettle(name);
726
+ return false;
727
+ }
728
+ this.deps.store.logEvent("pingpong_decision_malformed", pr, { file: name, error });
729
+ this.archive(name);
730
+ return true;
731
+ }
732
+ settleMs() {
733
+ return this.deps.malformedSettleMs ?? 250;
734
+ }
735
+ retryAfterSettle(name) {
736
+ if (this.retryTimers.has(name))
737
+ return;
738
+ const timer = setTimeout(() => {
739
+ this.retryTimers.delete(name);
740
+ this.requestSweep();
741
+ }, this.settleMs());
742
+ this.retryTimers.set(name, timer);
743
+ }
744
+ clearInvalid(name) {
745
+ this.invalidReads.delete(name);
746
+ const timer = this.retryTimers.get(name);
747
+ if (timer)
748
+ clearTimeout(timer);
749
+ this.retryTimers.delete(name);
750
+ }
751
+ archive(name) {
752
+ this.clearInvalid(name);
753
+ mkdirSync(this.processedDir, { recursive: true });
754
+ const ts = (this.deps.now ?? (() => new Date()))().toISOString().replace(/[:.]/g, "-");
755
+ try {
756
+ renameSync(join(this.deps.verdictDir, name), join(this.processedDir, `${ts}-${name}`));
757
+ }
758
+ catch (err) {
759
+ this.deps.log?.(`pingpong: could not archive ${name}`, err);
760
+ }
761
+ }
762
+ /** An expired open breaker becomes half-open when a decision is about to
763
+ * call GitHub, so a sweep that finds nothing to send leaves it as it was. */
764
+ startProbe(now) {
765
+ if (this.deps.ledger.breaker().state !== "open")
766
+ return;
767
+ this.deps.ledger.halfOpen(now);
768
+ this.deps.store.logEvent("pingpong_breaker_half_open", null, {});
769
+ }
770
+ async handleFile(name) {
771
+ const match = THREAD_DECISION_RE.exec(name);
772
+ if (!match || this.processing || this.inFlight.has(name) || this.deps.isDraining?.())
773
+ return false;
774
+ const now = (this.deps.now ?? (() => new Date()))();
775
+ if (this.githubDelayMs(now) > 0)
776
+ return false;
777
+ const breaker = this.deps.ledger.breaker();
778
+ if (this.breakerWaiting(breaker, now))
779
+ return false;
780
+ const retry = this.deps.ledger.retry(Number(match[3]));
781
+ if (retry.terminal || this.deadlinePending(retry.next_attempt_at, now))
782
+ return false;
783
+ this.processing = true;
784
+ this.inFlight.add(name);
785
+ try {
786
+ const path = join(this.deps.verdictDir, name);
787
+ if (!existsSync(path))
788
+ return false;
789
+ const body = readFileSync(path, "utf8");
790
+ let parsed;
791
+ try {
792
+ parsed = validateThreadDecision(JSON.parse(body));
793
+ }
794
+ catch (err) {
795
+ parsed = { ok: false, error: `unparseable: ${String(err)}` };
796
+ }
797
+ if (!parsed.ok)
798
+ return this.malformedRead(name, Number(match[1]), body, parsed.error, now);
799
+ this.clearInvalid(name);
800
+ const d = parsed.value;
801
+ if (d.pr !== Number(match[1]) ||
802
+ d.thread_id !== Number(match[2]) ||
803
+ d.comment_id !== Number(match[3]) ||
804
+ !this.deps.ledger.hasClaim(d.pr, d.thread_id, d.comment_id)) {
805
+ this.deps.store.logEvent("pingpong_decision_rejected", d.pr, {
806
+ file: name,
807
+ reason: "ids do not match a claimed author message",
808
+ });
809
+ this.archive(name);
810
+ return true;
811
+ }
812
+ const progress = this.deps.ledger.decisionProgress(d.comment_id);
813
+ if (!progress.reply_posted) {
814
+ if (this.deps.isDraining?.())
815
+ return false;
816
+ if (d.reply.trim())
817
+ this.startProbe(now);
818
+ // A POST started before — a caught failure, or a process that died
819
+ // before it could record the answer — may have landed: look first.
820
+ const landed = d.reply.trim() && (retry.attempts > 0 || progress.reply_attempted)
821
+ ? await this.findLandedReply(d.pr, d.thread_id, d.comment_id, d.reply.trim())
822
+ : undefined;
823
+ if (landed !== undefined) {
824
+ // The earlier attempt's POST reached GitHub but its answer never
825
+ // came back. Account for it exactly as a posted reply, and do NOT
826
+ // post it again: a second copy is a duplicate on the thread and one
827
+ // reply past the exchange cap.
828
+ this.deps.ledger.recordReply(d.thread_id, d.pr, d.comment_id, (exchanges) => {
829
+ this.deps.store.registerBotComment(landed, d.pr, "review_comment");
830
+ this.deps.store.logEvent("pingpong_reply_recovered", d.pr, {
831
+ thread_id: d.thread_id,
832
+ comment_id: d.comment_id,
833
+ reply_id: landed,
834
+ exchanges,
835
+ });
836
+ });
837
+ }
838
+ else if (d.reply.trim()) {
839
+ this.lastGitHubStart = now.getTime();
840
+ this.deps.ledger.markDecisionStep(d.comment_id, "reply_attempted");
841
+ const out = await postReply(this.deps, {
842
+ pr: d.pr,
843
+ thread_id: d.thread_id,
844
+ body: `${d.reply.trim()}\n\n${replyMarker(d.comment_id)}`,
845
+ decision_comment_id: d.comment_id,
846
+ });
847
+ // An unverifiable PR state is transient: fail this attempt so the
848
+ // bounded retry schedule below posts the reply later. A merged or
849
+ // closed PR is final — the reply is moot, so the decision proceeds.
850
+ if (out.blocked === "pr-unreadable") {
851
+ throw new Error(`reply refused by posting guard: ${out.blocked}`);
852
+ }
853
+ }
854
+ if (!this.deps.ledger.decisionProgress(d.comment_id).reply_posted)
855
+ this.deps.ledger.markDecisionStep(d.comment_id, "reply_posted");
856
+ this.deps.ledger.resetRetry(d.comment_id);
857
+ }
858
+ if (d.resolution === "resolve" && !progress.thread_resolved) {
859
+ if (this.deps.isDraining?.())
860
+ return false;
861
+ this.startProbe(now);
862
+ this.lastGitHubStart = now.getTime();
863
+ const resolution = await this.deps.adapter.resolveOwnReviewThread(d.pr, d.thread_id);
864
+ this.deps.ledger.markDecisionStep(d.comment_id, "thread_resolved");
865
+ this.deps.store.logEvent("pingpong_thread_resolved", d.pr, {
866
+ thread_id: d.thread_id,
867
+ comment_id: d.comment_id,
868
+ reason: d.reason ?? null,
869
+ skipped: resolution.skipped,
870
+ });
871
+ }
872
+ if (d.human_requested && !this.deps.ledger.decisionProgress(d.comment_id).human_notified) {
873
+ await this.deps.onHumanRequested?.(d);
874
+ this.deps.ledger.markDecisionStep(d.comment_id, "human_notified");
875
+ }
876
+ this.deps.ledger.resetRetry(d.comment_id);
877
+ if (this.deps.ledger.breaker().state === "half_open") {
878
+ this.deps.ledger.closeBreaker(now);
879
+ this.deps.store.logEvent("pingpong_breaker_closed", d.pr, { comment_id: d.comment_id });
880
+ }
881
+ this.deps.store.logEvent("pingpong_decision_applied", d.pr, {
882
+ thread_id: d.thread_id,
883
+ comment_id: d.comment_id,
884
+ resolution: d.resolution,
885
+ human_requested: d.human_requested ?? false,
886
+ // The session's own account of the finding's fate — the
887
+ // outcome capture's strongest evidence for this thread.
888
+ outcome: d.outcome ?? null,
889
+ });
890
+ this.archive(name);
891
+ return true;
892
+ }
893
+ catch (err) {
894
+ this.deps.log?.(`pingpong: ${name} failed`, err);
895
+ const classification = classifyThreadDecisionError(err);
896
+ const pr = Number(match[1]);
897
+ const commentId = Number(match[3]);
898
+ if (classification === "rate_limit") {
899
+ const opened = this.deps.ledger.openBreaker(now, String(err));
900
+ this.deps.store.logEvent("pingpong_breaker_opened", pr, {
901
+ file: name,
902
+ streak: opened.streak,
903
+ open_until: opened.open_until,
904
+ error: String(err),
905
+ });
906
+ this.deps.store.logEvent("pingpong_decision_failed", pr, {
907
+ file: name,
908
+ error: String(err),
909
+ classification,
910
+ attempt: this.deps.ledger.retry(commentId).attempts,
911
+ next_attempt_at: opened.open_until,
912
+ });
913
+ }
914
+ else {
915
+ // A half-open probe proved GitHub is answering. Its decision may still
916
+ // fail for a local/per-thread reason (ownership, auth shape, missing
917
+ // thread), but that must not leave the installation-wide breaker in
918
+ // half-open. Close globally and retry only this decision on its bounded
919
+ // schedule.
920
+ if (this.deps.ledger.breaker().state === "half_open") {
921
+ this.deps.ledger.closeBreaker(now);
922
+ this.deps.store.logEvent("pingpong_breaker_closed", pr, {
923
+ comment_id: commentId,
924
+ reason: "non-rate probe failure",
925
+ error: String(err),
926
+ });
927
+ }
928
+ const retryState = this.deps.ledger.recordRetry(commentId, now, String(err));
929
+ if (retryState.terminal) {
930
+ this.quarantineTerminal(name, pr, Number(match[2]), commentId, retryState.attempts);
931
+ }
932
+ else {
933
+ this.deps.store.logEvent("pingpong_decision_retry_scheduled", pr, {
934
+ file: name,
935
+ comment_id: commentId,
936
+ attempt: retryState.attempts,
937
+ next_attempt_at: retryState.next_attempt_at,
938
+ });
939
+ }
940
+ this.deps.store.logEvent("pingpong_decision_failed", pr, {
941
+ file: name,
942
+ error: String(err),
943
+ classification,
944
+ attempt: retryState.attempts,
945
+ next_attempt_at: retryState.next_attempt_at ?? null,
946
+ });
947
+ }
948
+ return false;
949
+ }
950
+ finally {
951
+ this.inFlight.delete(name);
952
+ this.processing = false;
953
+ }
954
+ }
955
+ /** After a POST that may have landed: the id of this decision's reply if it
956
+ * is on the thread (the bot's, newer than the author message it answers —
957
+ * GitHub ids are monotonic — and carrying this decision's `replyMarker`; a
958
+ * reply without any marker counts by its exact body), else undefined. A
959
+ * read that fails THROWS: the delivery is unknown, so the bounded retry
960
+ * schedule asks again rather than posting a second copy. Without the
961
+ * adapter's read or the bot's login nothing can be checked, and the retry
962
+ * posts. */
963
+ async findLandedReply(pr, threadId, commentId, body) {
964
+ const list = this.deps.adapter.listRecentReviewComments;
965
+ if (!list || !this.deps.botLogin)
966
+ return undefined;
967
+ let comments;
968
+ try {
969
+ comments = await list.call(this.deps.adapter, pr, commentId);
970
+ }
971
+ catch (err) {
972
+ // Rethrown as it came, so a rate limit still opens the breaker.
973
+ this.deps.log?.(`pingpong: could not check #${pr} thread ${threadId} for a landed reply — delivery unknown`, err);
974
+ throw err;
975
+ }
976
+ const marker = replyMarker(commentId);
977
+ return comments.find((c) => c.in_reply_to_id === threadId &&
978
+ c.user === this.deps.botLogin &&
979
+ c.id > commentId &&
980
+ (c.body.includes(marker) || (!REPLY_MARKER_RE.test(c.body) && c.body.trim() === body)))?.id;
981
+ }
982
+ quarantineTerminal(name, pr, threadId, commentId, attempts) {
983
+ try {
984
+ mkdirSync(this.failedDir, { recursive: true });
985
+ const source = join(this.deps.verdictDir, name);
986
+ if (!existsSync(source))
987
+ return true;
988
+ const failedPath = join(this.failedDir, name);
989
+ if (existsSync(failedPath))
990
+ return false;
991
+ renameSync(source, failedPath);
992
+ this.deps.store.logEvent("pingpong_decision_retry_exhausted", pr, {
993
+ file: name,
994
+ comment_id: commentId,
995
+ attempts,
996
+ failed_path: failedPath,
997
+ });
998
+ this.deps.store.logAnomaly?.("pingpong_decision_retry_exhausted", pr, null, `thread ${threadId} comment ${commentId} exhausted ${attempts} attempts; preserved at ${failedPath}`, `PING-PONG DECISION FAILED — PR #${pr}, thread ${threadId}, comment ${commentId}\nThe decision exhausted ${attempts} attempts and is preserved at ${failedPath}. Use retry-thread-decision after fixing the cause.`);
999
+ return true;
1000
+ }
1001
+ catch (err) {
1002
+ this.deps.store.logEvent("pingpong_decision_quarantine_failed", pr, {
1003
+ file: name,
1004
+ comment_id: commentId,
1005
+ error: String(err),
1006
+ });
1007
+ this.requestSweep(5_000);
1008
+ return false;
1009
+ }
1010
+ }
1011
+ }
1012
+ /**
1013
+ * Legacy wake-response filename, retained for input compatibility. No daemon
1014
+ * watcher consumes it; human requests use thread decisions.
1015
+ * @deprecated Use the thread-decision handoff.
1016
+ */
1017
+ export function wakeResponsePath(root, pr, ts = new Date().toISOString()) {
1018
+ return join(root, "verdict", `pr-${pr}-wake-${ts.replace(/[:.]/g, "-")}.json`);
1019
+ }
1020
+ /** @deprecated Writes a legacy artifact that no daemon watcher consumes. */
1021
+ export function writeWakeResponse(root, response) {
1022
+ const written_at = response.written_at ?? new Date().toISOString();
1023
+ const path = wakeResponsePath(root, response.pr, written_at);
1024
+ mkdirSync(join(root, "verdict"), { recursive: true });
1025
+ writeFileSync(path, JSON.stringify({ ...response, written_at }, null, 2));
1026
+ return path;
1027
+ }
1028
+ //# sourceMappingURL=pingpong.js.map