@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,1206 @@
1
+ // The WorkerSupervisor: the daemon's end of the per-round worker.
2
+ //
3
+ // One Node process serves one round of one PR (src/botworker.ts). This module
4
+ // starts it, watches it and ends it:
5
+ //
6
+ // - SPAWN. `node dist/src/botworker.js --command <id> --mode round|answer`, in
7
+ // a process group of its own, with the command's capability on an inherited
8
+ // fd (stdio[3]) and a small env built from an ALLOWLIST. No GitHub credential
9
+ // of any name is in it (GITHUB_TOKEN_ENVS, from packages/pi-plugin/src/envstrip.ts, so this
10
+ // module never imports src/engine/), and the capability is on the fd only.
11
+ // - LISTEN. It serves `worker.spec` and the worker's events over the IPC socket
12
+ // (src/ipc/server.ts). A request or event is accepted only for the command's
13
+ // live generation (the claim's attempt count); a worker from an earlier
14
+ // generation is refused, and its capability is dead anyway.
15
+ // - WATCH. The worker's heartbeats (`progress` events) are its liveness; the
16
+ // deadlines tolerate the 0.7-2.5 s a wave's session creation blocks its event
17
+ // loop (tests/cpu-gate: staggered grants will shorten it, not remove it). A
18
+ // worker is ended when it stops talking, when a stage runs over, or at its
19
+ // wall clock: SIGTERM to the group, SIGKILL after the grace.
20
+ // - LEASE. A file per session (src/workerlease.ts) names the leader's pid, pgid,
21
+ // start time and the boot/container id, fenced by an owner token. Pids and
22
+ // pgids repeat in a recreated container, so the daemon's boot signals a
23
+ // leased group only when the leader still has the recorded start time in the
24
+ // recorded boot and container.
25
+ // - WRITE. This module is the single writer of session_commands rows for a
26
+ // worker-hosted PR: it creates them, claims them, marks them started on the
27
+ // worker's `accepted`, finishes them from the exit, and requeues a round whose
28
+ // worker died. The one-active index (`session_commands_one_active`) gives one
29
+ // worker per session; a second spawn is refused before the row is claimed.
30
+ // - BREAKER (src/workerbreaker.ts). Every exit is counted: a worker that
31
+ // served its round resets its PR's count; a non-zero exit, a `failed` event or
32
+ // a deadline kill adds one. Two in a row park the PR (no further spawn, a
33
+ // `worker_crash_loop` anomaly, the last error in status.json); failures on three
34
+ // PRs within 15 minutes drain the bot. A drained bot or a parked PR starts no
35
+ // worker, of any mode: `launch` refuses and `launchPending` skips. An end by the
36
+ // daemon's own stop or by the operator is not a failure.
37
+ // - CONTROL. `control` forwards the operator's steer and follow-up to the
38
+ // round's worker over its own connection and answers with the worker's ack
39
+ // (queued, handled or refused); `abortRound` and the recovery `fence` ask the
40
+ // worker to abort and, when it has not gone within the grace period, SIGKILL its
41
+ // group (a lease the process table no longer confirms is never signalled).
42
+ // - TAKEOVER LEASE (src/takeover.ts). While the operator holds a PR's
43
+ // session no worker starts for it, of any mode (`hostGate`): the command waits
44
+ // as it does behind a drain, and the lease is freed only once the takeover pi
45
+ // is confirmed gone. The lease is granted only when no worker command is active.
46
+ // - HOSTED COMMANDS. A round the debug round runs in interactive pi
47
+ // (src/debuground.ts) has no worker process, but its row is still this module's to
48
+ // write: the debug manager asks for the claim, the start mark and the settlement
49
+ // (`claimHosted`, `markHostedStarted`, `settleHosted`).
50
+ // - RESTART. On a daemon restart every leased group is killed and its round is
51
+ // requeued under the same command id (`recover`), so the fresh worker resumes
52
+ // the JSONL and continues instead of sending the order again.
53
+ //
54
+ // The session host over it is src/worker-session-host.ts: the SessionHooks
55
+ // the daemon's state machine speaks, served by this supervisor.
56
+ import { spawn as nodeSpawn } from "node:child_process";
57
+ import { createHash, randomUUID } from "node:crypto";
58
+ import { closeSync, mkdirSync, openSync, renameSync, writeFileSync } from "node:fs";
59
+ import { dirname, join } from "node:path";
60
+ import { GITHUB_TOKEN_ENVS } from "@quickchatai/pi-quickreview/src/envstrip.js";
61
+ import { createCapabilityFd, ipcEnv, stdioWithCapability, } from "./ipc/capability.js";
62
+ import { IpcError, } from "./ipc/protocol.js";
63
+ import { CONTROL_ACK_OP, controlText, parseControlAck, } from "./ipc/control.js";
64
+ import { ghReadOps } from "./ghread.js";
65
+ import { permitOps } from "./ipc/permits.js";
66
+ import { WAKES_ACK_OP, WAKES_TAKE_OP, WORKER_SPEC_OP, parseWorkerSpec, } from "./ipc/workerspec.js";
67
+ import { DEFAULT_ANSWER_CAP_USD, DEFAULT_ANSWER_TIMEOUT_S } from "./config.js";
68
+ import { operatorMayPost } from "./operatormessage.js";
69
+ import { postOps } from "./postops.js";
70
+ import { messagePayload, verifiedPayload } from "./session-command-payload.js";
71
+ import { DEFAULT_WORKER_LOG_LIMITS, rotateWorkerLogs, workerLogPath, } from "./workerlog.js";
72
+ import { WorkerBreaker } from "./workerbreaker.js";
73
+ import { WorkerLeases, judgeLease, killLease, realProc, sendSignal, } from "./workerlease.js";
74
+ /** The env names a worker process may inherit from the daemon. Everything else is
75
+ * dropped, whatever the daemon's own env holds: a worker carries the daemon's
76
+ * locale, path and proxies, the tool-uid split the image arranged (the worker
77
+ * reads them to run the model's tools under it), and nothing that is a secret. */
78
+ export const WORKER_ENV_ALLOW = [
79
+ "PATH",
80
+ "HOME",
81
+ "LANG",
82
+ "LC_ALL",
83
+ "LC_CTYPE",
84
+ "TZ",
85
+ "TMPDIR",
86
+ "TERM",
87
+ "NODE_EXTRA_CA_CERTS",
88
+ "SSL_CERT_FILE",
89
+ "SSL_CERT_DIR",
90
+ "HTTP_PROXY",
91
+ "HTTPS_PROXY",
92
+ "NO_PROXY",
93
+ "http_proxy",
94
+ "https_proxy",
95
+ "no_proxy",
96
+ "PI_CODING_AGENT_DIR",
97
+ // The separate tool uid (packages/pi-plugin/src/engine/tooluid.ts TOOL_UID_ENVS; named here
98
+ // because the daemon never imports src/engine/).
99
+ "QCR_TOOL_UID",
100
+ "QCR_TOOL_GID",
101
+ "QCR_TOOL_UID_REQUIRED",
102
+ "QCR_ALLOW_SHARED_TOOL_UID",
103
+ // The bot's setid helper, which the worker reaches the tool uid through
104
+ // (tooluid.ts setidHelperOf): a path, no secret.
105
+ "QCR_SETPRIV_BIN",
106
+ ];
107
+ export const DEFAULT_WORKER_LIMITS = {
108
+ readyMs: 120_000,
109
+ acceptMs: 120_000,
110
+ heartbeatMs: 15_000,
111
+ missedBeats: 4,
112
+ stallAllowanceMs: 5_000,
113
+ wallGraceMs: 30_000,
114
+ killGraceMs: 10_000,
115
+ abortGraceMs: 5_000,
116
+ controlAckMs: 5_000,
117
+ maxRequeues: 3,
118
+ tickMs: 1_000,
119
+ fenceWaitMs: 15_000,
120
+ };
121
+ /** How long, once silent, a worker has before it is ended. */
122
+ export const staleAfterMs = (heartbeatMs, l) => l.missedBeats * heartbeatMs + l.stallAllowanceMs;
123
+ /**
124
+ * The exit decides the row. Exit 0 is a served round (a verdict may or may not
125
+ * have been written: that is the round's own business). A worker that failed in
126
+ * a way a fresh one would repeat (a refused login, a turn that ran out of time or
127
+ * money, a bad payload) fails the command; one that was lost (killed, crashed,
128
+ * its daemon went away) hands the round to a fresh worker, which resumes the
129
+ * JSONL. Ended for its wall clock, or by the operator: failed, not retried. Ended
130
+ * by a recovery fence: left as it is, for the caller that fenced it.
131
+ */
132
+ export function decideOutcome(x) {
133
+ if (x.spawnError !== undefined)
134
+ return { kind: "failed", reason: `could not start the worker: ${x.spawnError}` };
135
+ if (x.killedFor === "wall_clock")
136
+ return { kind: "failed", reason: "the worker ran past its wall clock and was ended" };
137
+ if (x.killedFor === "fence")
138
+ return { kind: "leave" };
139
+ if (x.killedFor === "operator")
140
+ return { kind: "failed", reason: "the worker was ended by the operator" };
141
+ if (x.killedFor !== undefined)
142
+ return { kind: "requeue", reason: `the worker was ended: ${x.killedFor}` };
143
+ if (x.code === 0)
144
+ return { kind: "acked" };
145
+ if (x.code !== null && x.code >= 1 && x.code <= 6)
146
+ return { kind: "failed", reason: x.failedReason ?? `the worker exited ${x.code}` };
147
+ return {
148
+ kind: "requeue",
149
+ reason: x.signal ? `the worker died of ${x.signal}` : `the worker exited ${x.code}`,
150
+ };
151
+ }
152
+ /** The env of one worker process: the allowlisted part of the daemon's env, the
153
+ * daemon's explicit additions, and the IPC names (the fd NUMBER, never the
154
+ * capability). A GitHub credential is dropped last, by name, so no addition can
155
+ * carry one in. */
156
+ export function workerProcessEnv(parent, extra, ipc) {
157
+ const env = {};
158
+ for (const name of WORKER_ENV_ALLOW) {
159
+ const value = parent[name];
160
+ if (value !== undefined && value !== "")
161
+ env[name] = value;
162
+ }
163
+ for (const [name, value] of Object.entries(extra))
164
+ if (!name.startsWith("QCR_IPC_"))
165
+ env[name] = value;
166
+ Object.assign(env, ipc);
167
+ for (const name of GITHUB_TOKEN_ENVS)
168
+ delete env[name];
169
+ return env;
170
+ }
171
+ const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
172
+ export class WorkerLaunchError extends Error {
173
+ constructor(message) {
174
+ super(message);
175
+ this.name = "WorkerLaunchError";
176
+ }
177
+ }
178
+ export class WorkerSupervisor {
179
+ deps;
180
+ limits;
181
+ leases;
182
+ /** The crash-loop breaker: also the question every host asks before a spawn. */
183
+ breaker;
184
+ byCommand = new Map();
185
+ bySession = new Map();
186
+ /** Sessions with a launch under way: the second spawn is refused before any await. */
187
+ launching = new Set();
188
+ spawnFn;
189
+ proc;
190
+ signal;
191
+ now;
192
+ log;
193
+ timer = null;
194
+ stopping = false;
195
+ constructor(deps) {
196
+ this.deps = deps;
197
+ this.limits = { ...DEFAULT_WORKER_LIMITS, ...deps.limits };
198
+ this.leases = new WorkerLeases(join(deps.runDir, "workers"));
199
+ this.spawnFn = deps.spawn ?? nodeSpawn;
200
+ this.proc = deps.proc ?? realProc;
201
+ this.signal = deps.signal ?? sendSignal;
202
+ this.now = deps.now ?? Date.now;
203
+ this.log = deps.log ?? (() => { });
204
+ this.breaker = new WorkerBreaker(deps.store, {
205
+ ...(deps.breaker ? { limits: deps.breaker } : {}),
206
+ now: this.now,
207
+ log: this.log,
208
+ });
209
+ deps.permits?.attach(deps.capabilities);
210
+ }
211
+ // ---- what the IPC server asks the daemon ---------------------------------
212
+ /** The server's view of a command, read fresh for every request. `active` is
213
+ * true only while THIS supervisor holds a live worker for the row, so a worker
214
+ * that outlived its row (or its supervisor) is refused as inactive; the
215
+ * generation is the live worker's, so an earlier one is refused as stale. */
216
+ lookup = (commandId) => {
217
+ const row = this.deps.store.getSessionCommand(commandId);
218
+ if (!row)
219
+ return null;
220
+ const rec = this.byCommand.get(commandId);
221
+ const live = rec !== undefined &&
222
+ !rec.settled &&
223
+ row.status === "running" &&
224
+ row.owner_token === rec.token;
225
+ const facts = this.deps.facts?.(row) ?? {};
226
+ const answer = row.kind === "answer";
227
+ const state = {
228
+ pr: row.pr,
229
+ generation: rec?.generation ?? row.attempt,
230
+ active: live,
231
+ // An answer worker posts only when the operator marked its message, and
232
+ // the daemon's word for that is the payload it dispatched.
233
+ may_post: answer ? rec?.mayPost === true : facts.may_post === true,
234
+ lease: facts.lease ?? "none",
235
+ };
236
+ if (answer)
237
+ state.answer = true;
238
+ return state;
239
+ };
240
+ /** The ops the daemon serves a worker: its spec, its post ops, and
241
+ * its held wakes. */
242
+ ops() {
243
+ const ops = {
244
+ [WORKER_SPEC_OP]: {
245
+ roles: ["worker"],
246
+ handle: (ctx) => {
247
+ const rec = this.byCommand.get(ctx.commandId);
248
+ if (!rec || rec.settled || rec.generation !== ctx.generation)
249
+ throw new IpcError("command_inactive", "no live worker for this command");
250
+ return rec.spec;
251
+ },
252
+ },
253
+ };
254
+ ops[CONTROL_ACK_OP] = {
255
+ roles: ["worker"],
256
+ handle: (ctx, body) => {
257
+ const ack = parseControlAck(body);
258
+ const rec = this.byCommand.get(ctx.commandId);
259
+ // An ack for a control nobody waits for any more is not an error.
260
+ rec?.controls.get(ack.id)?.(ack);
261
+ return {};
262
+ },
263
+ };
264
+ if (this.deps.post)
265
+ Object.assign(ops, postOps(this.deps.post));
266
+ if (this.deps.ghRead)
267
+ Object.assign(ops, ghReadOps({ reader: this.deps.ghRead, log: this.log }));
268
+ if (this.deps.permits)
269
+ Object.assign(ops, permitOps(this.deps.permits));
270
+ const wakes = this.deps.wakes;
271
+ if (wakes) {
272
+ ops[WAKES_TAKE_OP] = {
273
+ roles: ["worker"],
274
+ handle: (ctx) => ({ batches: wakes.take(ctx) }),
275
+ };
276
+ ops[WAKES_ACK_OP] = {
277
+ roles: ["worker"],
278
+ handle: (ctx, body) => {
279
+ const id = body?.id;
280
+ if (typeof id !== "string" || id === "")
281
+ throw new IpcError("bad_request", "wakes.ack: `id` must be a string");
282
+ wakes.ack(ctx, id);
283
+ return {};
284
+ },
285
+ };
286
+ }
287
+ return ops;
288
+ }
289
+ /** The worker's events. Any event is a sign of life; `accepted` is the row's
290
+ * start; the rest is kept for the exit and handed to the observer. */
291
+ onEvent = (ctx, kind, body) => {
292
+ const rec = this.byCommand.get(ctx.commandId);
293
+ if (!rec || rec.settled || rec.generation !== ctx.generation)
294
+ return;
295
+ const t = this.now();
296
+ rec.lastSeen = t;
297
+ const b = (typeof body === "object" && body !== null ? body : {});
298
+ switch (kind) {
299
+ case "ready":
300
+ rec.readyAt = t;
301
+ if (typeof b["session_id"] === "string")
302
+ rec.sessionId = b["session_id"];
303
+ break;
304
+ case "accepted":
305
+ if (rec.acceptedAt === undefined) {
306
+ rec.acceptedAt = t;
307
+ this.deps.store.markSessionCommandStarted(rec.row.id, rec.token, this.iso(this.hardDeadline(rec)));
308
+ }
309
+ break;
310
+ case "verdict_written":
311
+ rec.verdictWritten = true;
312
+ break;
313
+ case "posted":
314
+ rec.posted++;
315
+ break;
316
+ case "failed":
317
+ if (typeof b["reason"] === "string")
318
+ rec.failedReason = b["reason"].slice(0, 500);
319
+ break;
320
+ case "done":
321
+ rec.report = b;
322
+ break;
323
+ default:
324
+ break;
325
+ }
326
+ try {
327
+ this.deps.observe?.({
328
+ kind,
329
+ command_id: rec.row.id,
330
+ pr: rec.row.pr,
331
+ session: rec.row.session,
332
+ mode: rec.mode,
333
+ generation: rec.generation,
334
+ body,
335
+ });
336
+ }
337
+ catch (e) {
338
+ this.log(`worker observer failed: ${String(e)}`);
339
+ }
340
+ };
341
+ // ---- the single writer of session_commands -------------------------------
342
+ /** Create a worker-hosted command: the saved payload and its row. The inject
343
+ * path is a name only (`worker:<id>`): no bridge reads it. Refused while the
344
+ * session has work owed, and for a round that is no longer running. */
345
+ submit(input) {
346
+ const { store } = this.deps;
347
+ const session = `pr-${input.pr}`;
348
+ const blocking = store.blockingSessionCommand(session);
349
+ if (blocking)
350
+ throw new Error(`session command ${blocking.id} is ${blocking.status}`);
351
+ if (input.kind === "round" && input.round_no !== null) {
352
+ const status = store.roundStatus(input.pr, input.round_no);
353
+ if (status !== undefined && status !== "running")
354
+ throw new Error(`round ${input.round_no} of #${input.pr} is ${status}; not submitting its order`);
355
+ }
356
+ const id = randomUUID();
357
+ const payload = messagePayload(input.payload);
358
+ const payloadPath = join(this.deps.payloadDir, `${id}.md`);
359
+ mkdirSync(dirname(payloadPath), { recursive: true });
360
+ const tmp = `${payloadPath}.tmp-${process.pid}`;
361
+ writeFileSync(tmp, payload);
362
+ renameSync(tmp, payloadPath);
363
+ return store.createSessionCommand({
364
+ id,
365
+ pr: input.pr,
366
+ session,
367
+ kind: input.kind,
368
+ round_no: input.round_no,
369
+ payload_sha256: createHash("sha256").update(payload).digest("hex"),
370
+ payload_path: payloadPath,
371
+ inject_path: `worker:${id}`,
372
+ next_check_at: this.iso(this.now() + this.limits.readyMs),
373
+ });
374
+ }
375
+ /** Start a worker for a pending command. Refused (a `WorkerLaunchError`) when
376
+ * the session already has a worker, a lease held by a live process, or a login
377
+ * rewrite that does not end; the row is left as it was. */
378
+ async launch(commandId) {
379
+ if (this.stopping)
380
+ throw new WorkerLaunchError("the supervisor is stopping");
381
+ const first = this.deps.store.getSessionCommand(commandId);
382
+ if (!first)
383
+ throw new WorkerLaunchError(`no such command: ${commandId}`);
384
+ const session = first.session;
385
+ this.mayStart(first);
386
+ if (this.bySession.has(session) || this.launching.has(session))
387
+ throw new WorkerLaunchError(`${session} already has a worker`);
388
+ this.launching.add(session);
389
+ try {
390
+ return await this.launchHeld(commandId, session);
391
+ }
392
+ finally {
393
+ this.launching.delete(session);
394
+ }
395
+ }
396
+ /** Launch every pending command whose session has no worker, oldest first. */
397
+ async launchPending() {
398
+ const out = [];
399
+ for (const row of this.deps.store.activeSessionCommands()) {
400
+ if (row.status !== "pending" || row.kind === "legacy")
401
+ continue;
402
+ if (this.bySession.has(row.session) || this.launching.has(row.session))
403
+ continue;
404
+ // An answer is started the moment it is submitted or not at all: one still
405
+ // pending here was left by a daemon that went away. The operator asks again.
406
+ if (row.kind === "answer") {
407
+ this.deps.store.cancelAnswerCommand(row.id, "not started before the daemon stopped; ask again");
408
+ continue;
409
+ }
410
+ // A drained bot or a parked PR starts nothing; the command waits, and the
411
+ // refusal is not logged every pass.
412
+ if (!this.breaker.gate(row.pr).ok)
413
+ continue;
414
+ if (this.deps.hostGate?.(row.pr))
415
+ continue; // a takeover holds the session: the command waits
416
+ try {
417
+ out.push(await this.launch(row.id));
418
+ }
419
+ catch (e) {
420
+ this.log(`worker launch for ${row.id} failed: ${String(e)}`);
421
+ this.deps.store.logEvent("worker_launch_refused", row.pr, {
422
+ command_id: row.id,
423
+ error: String(e).slice(0, 300),
424
+ });
425
+ }
426
+ }
427
+ return out;
428
+ }
429
+ /** The no of the breaker (a drained bot, a parked PR: no worker of any mode; the
430
+ * debug round asks `breaker.gate` itself) and of the host lease (a PR under a
431
+ * takeover). The row is left as it was. */
432
+ mayStart(row) {
433
+ const verdict = this.breaker.gate(row.pr);
434
+ if (!verdict.ok)
435
+ throw new WorkerLaunchError(verdict.reason);
436
+ // A takeover holds the PR's session: two writers must never append to its JSONL.
437
+ const held = this.deps.hostGate?.(row.pr);
438
+ if (held)
439
+ throw new WorkerLaunchError(held);
440
+ }
441
+ async launchHeld(commandId, session) {
442
+ const { store, capabilities } = this.deps;
443
+ const gate = this.deps.loginGate;
444
+ if (gate?.paused() && !(await gate.whenResumed(this.deps.loginWaitMs ?? 30_000)))
445
+ throw new WorkerLaunchError("a login holds the refresher paused: not starting a worker");
446
+ if (this.stopping)
447
+ throw new WorkerLaunchError("the supervisor is stopping");
448
+ const row = store.getSessionCommand(commandId);
449
+ if (!row || row.status !== "pending" || row.kind === "legacy")
450
+ throw new WorkerLaunchError(`command ${commandId} is not a pending worker command`);
451
+ this.mayStart(row); // a login wait or a failing neighbour may have drained the bot meanwhile
452
+ // A lease still held by a live worker of ours (another daemon, a worker the
453
+ // boot could not kill) refuses the spawn; one that names nothing is cleared.
454
+ const held = this.leases.read(session);
455
+ if (held !== undefined) {
456
+ const verdict = held === null ? { kind: "dead" } : judgeLease(held, this.proc);
457
+ if (verdict.kind === "group" || verdict.kind === "members")
458
+ throw new WorkerLaunchError(`${session} has a live worker (lease of ${held?.command_id})`);
459
+ this.leases.forget(session);
460
+ }
461
+ // A wake outside a round is the PR's main session carrying on, so it runs as a
462
+ // round worker does; only an operator's message to an idle PR is an answer.
463
+ const mode = row.kind === "answer" ? "answer" : "round";
464
+ const payload = verifiedPayload(row, "the command's payload");
465
+ if (!payload.ok) {
466
+ if (row.kind === "answer")
467
+ store.cancelAnswerCommand(row.id, payload.why);
468
+ else
469
+ store.failPendingSessionCommand(row.id, payload.why);
470
+ throw new WorkerLaunchError(payload.why);
471
+ }
472
+ const mayPost = mode === "answer" && operatorMayPost(payload.payload.toString("utf8"));
473
+ const spec = this.checkedSpec(row, mode, mayPost);
474
+ const token = WorkerLeases.newToken();
475
+ const t0 = this.now();
476
+ const hardDeadline = t0 + spec.wall_clock_ms + this.limits.wallGraceMs + this.limits.killGraceMs;
477
+ const claimed = store.claimSessionCommand(row.id, token, this.iso(hardDeadline));
478
+ if (!claimed)
479
+ throw new WorkerLaunchError(`command ${commandId} was claimed by another`);
480
+ const generation = claimed.attempt;
481
+ const lease = {
482
+ v: 1,
483
+ owner_token: token,
484
+ command_id: row.id,
485
+ session,
486
+ pr: row.pr,
487
+ generation,
488
+ pid: null,
489
+ pgid: null,
490
+ start_time: null,
491
+ boot_id: this.proc.bootId(),
492
+ command: `botworker --command ${row.id} --mode ${mode}`,
493
+ created_at: new Date(t0).toISOString(),
494
+ };
495
+ let capFd = -1;
496
+ let logFd = -1;
497
+ let leased = false;
498
+ let child;
499
+ try {
500
+ this.leases.create(lease);
501
+ leased = true;
502
+ const capability = capabilities.mint(row.id);
503
+ // In run/caps, never run/ itself: run/ is the socket's dir, which the tool
504
+ // uid must still traverse (0710) when the model's tools run as another uid.
505
+ capFd = createCapabilityFd(join(this.deps.runDir, "caps"), capability);
506
+ mkdirSync(this.deps.logDir, { recursive: true });
507
+ rotateWorkerLogs(this.deps.logDir, row.id, t0, {
508
+ ...DEFAULT_WORKER_LOG_LIMITS,
509
+ ...this.deps.logLimits,
510
+ });
511
+ logFd = openSync(workerLogPath(this.deps.logDir, row.id), "a", 0o600);
512
+ const env = workerProcessEnv(this.deps.parentEnv ?? process.env, this.deps.extraEnv ?? {}, ipcEnv({ socketPath: this.deps.socketPath, commandId: row.id, generation }));
513
+ child = this.spawnFn(this.deps.nodeBin ?? process.execPath, [this.deps.workerMain, "--command", row.id, "--mode", mode], {
514
+ cwd: spec.root,
515
+ env,
516
+ detached: true,
517
+ stdio: stdioWithCapability(["ignore", logFd, logFd], capFd),
518
+ });
519
+ }
520
+ catch (e) {
521
+ this.abandon(row.id, token, session, leased, `could not start the worker: ${String(e)}`);
522
+ throw new WorkerLaunchError(`could not start the worker: ${String(e)}`);
523
+ }
524
+ finally {
525
+ if (capFd >= 0)
526
+ closeSync(capFd); // the child holds its own copy
527
+ if (logFd >= 0)
528
+ closeSync(logFd);
529
+ }
530
+ const pid = child.pid;
531
+ const identity = pid === undefined ? undefined : this.proc.identity(pid);
532
+ if (pid !== undefined)
533
+ this.leases.update(session, token, {
534
+ pid,
535
+ pgid: identity?.pgid ?? pid,
536
+ start_time: identity?.start ?? null,
537
+ });
538
+ let finish = () => { };
539
+ const done = new Promise((resolve) => (finish = resolve));
540
+ const rec = {
541
+ row: claimed,
542
+ spec,
543
+ mode,
544
+ token,
545
+ generation,
546
+ child,
547
+ lease: { ...lease, pid: pid ?? null, pgid: pid ?? null, start_time: identity?.start ?? null },
548
+ spawnedAt: t0,
549
+ wallDeadline: t0 + spec.wall_clock_ms + this.limits.wallGraceMs,
550
+ staleMs: staleAfterMs(spec.heartbeat_ms ?? this.limits.heartbeatMs, this.limits),
551
+ lastSeen: t0,
552
+ readyAt: undefined,
553
+ acceptedAt: undefined,
554
+ sessionId: undefined,
555
+ verdictWritten: false,
556
+ posted: 0,
557
+ failedReason: undefined,
558
+ spawnError: undefined,
559
+ report: undefined,
560
+ mayPost,
561
+ killedFor: undefined,
562
+ killTimer: undefined,
563
+ controls: new Map(),
564
+ forceKilled: false,
565
+ settled: false,
566
+ done,
567
+ finish,
568
+ };
569
+ this.byCommand.set(row.id, rec);
570
+ this.bySession.set(session, rec);
571
+ child.once("exit", (code, signal) => void this.settle(rec, code, signal));
572
+ child.once("error", (e) => {
573
+ if (pid === undefined) {
574
+ rec.spawnError = e.message;
575
+ void this.settle(rec, null, null);
576
+ }
577
+ else
578
+ this.log(`worker ${row.id}: ${e.message}`);
579
+ });
580
+ store.logEvent("worker_spawned", row.pr, {
581
+ command_id: row.id,
582
+ mode,
583
+ generation,
584
+ pid: pid ?? null,
585
+ });
586
+ return { command_id: row.id, session, pid: pid ?? -1, generation };
587
+ }
588
+ /** The spec as the worker will read it: from the builder, checked against the
589
+ * row (a spec for another command, PR or payload is a bug, not a request), with
590
+ * no GitHub credential, no IPC name, and the beat interval filled in. */
591
+ checkedSpec(row, mode, mayPost) {
592
+ const built = this.deps.buildSpec(row, mode);
593
+ const env = {};
594
+ for (const [name, value] of Object.entries(built.env)) {
595
+ if (name.startsWith("QCR_IPC_"))
596
+ throw new WorkerLaunchError(`the spec's env names ${name}: the IPC names are the supervisor's`);
597
+ if (!GITHUB_TOKEN_ENVS.includes(name))
598
+ env[name] = value;
599
+ }
600
+ // An answer is a short worker with caps of its own: the builder's round budget,
601
+ // its planned wave and its lens dir do not apply, and the may-post mark is the
602
+ // daemon's own reading of the payload, whatever the builder put.
603
+ const answer = mode === "answer"
604
+ ? {
605
+ wall_clock_ms: this.deps.answer?.timeoutMs ?? Math.round(DEFAULT_ANSWER_TIMEOUT_S * 1000),
606
+ cap_usd: this.deps.answer?.capUsd ?? DEFAULT_ANSWER_CAP_USD,
607
+ planned_wave: false,
608
+ may_post: mayPost,
609
+ // The newest round's live log is where a viewer following the PR looks.
610
+ ...(this.newestRound(row.pr) !== undefined
611
+ ? { live_round: this.newestRound(row.pr) }
612
+ : {}),
613
+ }
614
+ : {};
615
+ const spec = parseWorkerSpec(JSON.parse(JSON.stringify({
616
+ ...built,
617
+ ...answer,
618
+ env,
619
+ heartbeat_ms: built.heartbeat_ms ?? this.limits.heartbeatMs,
620
+ })));
621
+ if (spec.command_id !== row.id ||
622
+ spec.pr !== row.pr ||
623
+ spec.session !== row.session ||
624
+ spec.mode !== mode ||
625
+ spec.payload_path !== row.payload_path ||
626
+ spec.payload_sha256 !== row.payload_sha256)
627
+ throw new WorkerLaunchError("the spec is not for this command");
628
+ return spec;
629
+ }
630
+ newestRound(pr) {
631
+ return this.deps.store.roundsFor(pr).at(-1)?.round_no;
632
+ }
633
+ /** Undo a launch that never produced a process. */
634
+ abandon(id, token, session, leased, why) {
635
+ this.deps.capabilities.revoke(id);
636
+ if (leased)
637
+ this.leases.remove(session, token);
638
+ this.finishFailed(id, token, why);
639
+ }
640
+ // ---- commands another host runs ---------------------------------
641
+ /** A round order claimed for a host that is no worker process of ours: the debug
642
+ * round's interactive pi (src/debuground.ts). The supervisor stays the single writer
643
+ * of the rows, so the host asks for the claim, the start mark and the settlement
644
+ * here. `ownerToken` is the host's lease token; the row follows it as a worker's
645
+ * follows its spawn's. Undefined when another claimed the row first. */
646
+ claimHosted(commandId, ownerToken, nextCheckAt) {
647
+ return this.deps.store.claimSessionCommand(commandId, ownerToken, nextCheckAt);
648
+ }
649
+ /** The hosted round's order reached its session: the row is started. */
650
+ markHostedStarted(commandId, ownerToken, nextCheckAt) {
651
+ return this.deps.store.markSessionCommandStarted(commandId, ownerToken, nextCheckAt);
652
+ }
653
+ /**
654
+ * The hosted command's host is gone (confirmed by the caller). Served: the round's
655
+ * verdict was committed, so the row is acked. Otherwise the row goes back to
656
+ * `pending` for a worker, which resumes the session and continues, or
657
+ * fails once the requeues are spent or its round has ended. Nothing counts against
658
+ * the PR's crash-loop breaker: a person ended it.
659
+ */
660
+ settleHosted(commandId, ownerToken, outcome) {
661
+ const { store } = this.deps;
662
+ const row = store.getSessionCommand(commandId);
663
+ if (!row || row.status !== "running" || row.owner_token !== ownerToken)
664
+ return "gone";
665
+ if (outcome.served) {
666
+ store.markSessionCommandStarted(commandId, ownerToken, this.iso(this.now()));
667
+ if (store.finishSessionCommand(commandId, ownerToken, "acked"))
668
+ return "acked";
669
+ }
670
+ const reason = outcome.served ? "the round could not be marked served" : outcome.reason;
671
+ return this.requeueOrFail(commandId, ownerToken, reason) ? "requeued" : "failed";
672
+ }
673
+ // ---- watching ------------------------------------------------------------
674
+ /** Begin the periodic `tick`. */
675
+ start() {
676
+ if (this.timer)
677
+ return;
678
+ this.timer = setInterval(() => this.tick(), this.limits.tickMs);
679
+ this.timer.unref();
680
+ this.deps.permits?.start(this.lookup);
681
+ }
682
+ /** One pass of the deadlines. Pure of I/O but for the signals it sends. */
683
+ tick() {
684
+ const t = this.now();
685
+ for (const rec of [...this.byCommand.values()]) {
686
+ if (rec.settled || rec.killedFor !== undefined)
687
+ continue;
688
+ if (t >= rec.wallDeadline)
689
+ this.end(rec, "wall_clock");
690
+ else if (rec.readyAt === undefined) {
691
+ if (t - rec.spawnedAt > this.limits.readyMs)
692
+ this.end(rec, "stage_ready");
693
+ }
694
+ else if (rec.acceptedAt === undefined && t - rec.readyAt > this.limits.acceptMs)
695
+ this.end(rec, "stage_accept");
696
+ else if (t - rec.lastSeen > rec.staleMs)
697
+ this.end(rec, "heartbeat_lost");
698
+ }
699
+ }
700
+ /** End one worker's group (TERM, then KILL after the grace). The row follows
701
+ * the exit: an operator's end fails it, a lost worker requeues it. */
702
+ kill(commandId, why = "operator") {
703
+ const rec = this.byCommand.get(commandId);
704
+ if (!rec || rec.settled)
705
+ return false;
706
+ this.end(rec, why);
707
+ return true;
708
+ }
709
+ end(rec, why) {
710
+ if (rec.settled || rec.killedFor !== undefined)
711
+ return;
712
+ rec.killedFor = why;
713
+ this.log(`ending worker ${rec.row.id} (${why})`);
714
+ this.deps.store.logEvent("worker_ending", rec.row.pr, { command_id: rec.row.id, why });
715
+ this.signalGroup(rec, "SIGTERM");
716
+ rec.killTimer = setTimeout(() => {
717
+ if (!rec.settled)
718
+ this.signalGroup(rec, "SIGKILL");
719
+ }, this.limits.killGraceMs);
720
+ rec.killTimer.unref();
721
+ }
722
+ /** Signal the live child's group. Safe by construction: the child has not been
723
+ * reaped, so its pid cannot belong to anyone else. */
724
+ signalGroup(rec, sig) {
725
+ const pid = rec.child.pid;
726
+ if (pid === undefined)
727
+ return;
728
+ if (this.signal(-pid, sig) === "denied")
729
+ this.log(`worker ${rec.row.id}: ${sig} to the group was refused`);
730
+ }
731
+ async settle(rec, code, signal) {
732
+ if (rec.settled)
733
+ return;
734
+ rec.settled = true;
735
+ if (rec.killTimer)
736
+ clearTimeout(rec.killTimer);
737
+ for (const [id, resolve] of [...rec.controls])
738
+ resolve({ id, ack: "refused", reason: "the worker ended" });
739
+ const { store } = this.deps;
740
+ let survivors = false;
741
+ try {
742
+ // The leader is gone; whatever it left in its group goes with it.
743
+ const leftovers = await killLease(rec.lease, {
744
+ proc: this.proc,
745
+ signal: this.signal,
746
+ graceMs: 0,
747
+ pollMs: 10,
748
+ });
749
+ if (leftovers.verdict === "members")
750
+ this.log(`worker ${rec.row.id}: left members in its group; ended`);
751
+ if (leftovers.survivors) {
752
+ survivors = true;
753
+ this.log(`worker ${rec.row.id}: group members survived the kill`);
754
+ }
755
+ this.deps.capabilities.revoke(rec.row.id);
756
+ const outcome = decideOutcome({
757
+ code,
758
+ signal,
759
+ killedFor: rec.killedFor,
760
+ failedReason: rec.failedReason,
761
+ spawnError: rec.spawnError,
762
+ });
763
+ this.apply(rec, outcome);
764
+ store.logEvent("worker_exited", rec.row.pr, {
765
+ command_id: rec.row.id,
766
+ generation: rec.generation,
767
+ code,
768
+ signal,
769
+ outcome: outcome.kind,
770
+ ...(outcome.kind === "acked" || outcome.kind === "leave" ? {} : { reason: outcome.reason }),
771
+ verdict_written: rec.verdictWritten,
772
+ posted: rec.posted,
773
+ });
774
+ this.count(rec, outcome, code);
775
+ this.tell(rec, outcome, code, signal);
776
+ }
777
+ catch (e) {
778
+ this.log(`settling worker ${rec.row.id} failed: ${String(e)}`);
779
+ }
780
+ finally {
781
+ // A lease whose group members survived stays: it is what keeps a successor
782
+ // from launching beside them (launchHeld) until the process table shows them gone.
783
+ if (!survivors)
784
+ this.leases.remove(rec.row.session, rec.token);
785
+ this.byCommand.delete(rec.row.id);
786
+ if (this.bySession.get(rec.row.session) === rec)
787
+ this.bySession.delete(rec.row.session);
788
+ rec.finish();
789
+ }
790
+ }
791
+ /** Tell the breaker how the worker ended. A served round is a success; a
792
+ * non-zero exit, a `failed` event or a deadline kill is a failure; the daemon's
793
+ * own stop, the operator's end and a recovery fence are neither. A PR parked by this failure has
794
+ * no round to retry, so a requeue it just got is failed instead. */
795
+ count(rec, outcome, code) {
796
+ const { pr } = rec.row;
797
+ // An answer is the operator's chat, not the PR's round: its failures do not park
798
+ // the PR or feed the drain, and its success must not hide a round's crash loop.
799
+ if (rec.mode === "answer")
800
+ return;
801
+ // A fenced worker was ended by the caller, who owns the row's fate: not a worker failure.
802
+ if (rec.killedFor === "shutdown" || rec.killedFor === "operator" || outcome.kind === "leave")
803
+ return;
804
+ if (outcome.kind === "acked" && rec.failedReason === undefined) {
805
+ this.breaker.success(pr);
806
+ return;
807
+ }
808
+ const error = rec.failedReason ??
809
+ (outcome.kind === "acked"
810
+ ? `the worker reported a failure and exited ${code}`
811
+ : outcome.reason);
812
+ const res = this.breaker.failure(pr, rec.row.id, error);
813
+ if (res.parked && outcome.kind === "requeue")
814
+ this.deps.store.failPendingSessionCommand(rec.row.id, `PR #${pr} is parked after ${res.failures} consecutive worker failures: ${error}`.slice(0, 500));
815
+ }
816
+ /** Hand the host that submitted the command what the worker came to. */
817
+ tell(rec, outcome, code, signal) {
818
+ if (!this.deps.settled)
819
+ return;
820
+ try {
821
+ this.deps.settled({
822
+ command_id: rec.row.id,
823
+ pr: rec.row.pr,
824
+ session: rec.row.session,
825
+ mode: rec.mode,
826
+ kind: rec.row.kind,
827
+ outcome: outcome.kind,
828
+ reason: outcome.kind === "failed" || outcome.kind === "requeue"
829
+ ? (rec.failedReason ?? outcome.reason)
830
+ : undefined,
831
+ code,
832
+ signal,
833
+ report: rec.report,
834
+ posted: rec.posted,
835
+ verdict_written: rec.verdictWritten,
836
+ may_post: rec.mayPost,
837
+ });
838
+ }
839
+ catch (e) {
840
+ this.log(`worker settled hook failed: ${String(e)}`);
841
+ }
842
+ }
843
+ apply(rec, outcome) {
844
+ const { store } = this.deps;
845
+ const id = rec.row.id;
846
+ if (outcome.kind === "leave")
847
+ return;
848
+ if (outcome.kind === "acked") {
849
+ // An exit 0 is the round served, whether or not `accepted` got through.
850
+ store.markSessionCommandStarted(id, rec.token, this.iso(this.now()));
851
+ store.finishSessionCommand(id, rec.token, "acked");
852
+ }
853
+ else if (outcome.kind === "failed") {
854
+ this.finishFailed(id, rec.token, outcome.reason);
855
+ }
856
+ else {
857
+ this.requeueOrFail(id, rec.token, outcome.reason);
858
+ }
859
+ }
860
+ /** Hand the command to a fresh worker, or fail it once the requeues are spent
861
+ * (or its round has ended meanwhile). */
862
+ requeueOrFail(id, token, reason) {
863
+ const { store } = this.deps;
864
+ const row = store.getSessionCommand(id);
865
+ if (!row || row.status !== "running")
866
+ return false;
867
+ // A lost answer worker is not replayed: the operator is told (the reply file
868
+ // says the worker was lost) and asks again if they still want the answer.
869
+ if (row.kind === "answer") {
870
+ store.cancelAnswerCommand(id, reason);
871
+ return false;
872
+ }
873
+ if (row.recovery_attempts >= this.limits.maxRequeues) {
874
+ this.failRow(row, token, `${reason}; requeued ${row.recovery_attempts} times already`);
875
+ return false;
876
+ }
877
+ if (store.requeueWorkerCommand(id, token, this.iso(this.now())))
878
+ return true;
879
+ this.failRow(row, token, `${reason}; its round is no longer running`);
880
+ return false;
881
+ }
882
+ failRow(row, token, why) {
883
+ const { store } = this.deps;
884
+ if (token !== null)
885
+ this.finishFailed(row.id, token, why);
886
+ else {
887
+ store.failActiveSessionCommand(row.id, why);
888
+ this.endAnswer(row.id, why);
889
+ }
890
+ }
891
+ /** The row's `failed`, except that an answer command never ends failed: a failed
892
+ * non-round command is owed work that blocks the PR's next round, and an
893
+ * operator's message owes nothing (`cancelAnswerCommand`). */
894
+ finishFailed(id, token, why) {
895
+ const done = this.deps.store.finishSessionCommand(id, token, "failed", why);
896
+ if (done)
897
+ this.endAnswer(id, why);
898
+ return done;
899
+ }
900
+ endAnswer(id, why) {
901
+ if (this.deps.store.getSessionCommand(id)?.kind === "answer")
902
+ this.deps.store.cancelAnswerCommand(id, why);
903
+ }
904
+ // ---- restart -------------------------------------------------------------
905
+ /**
906
+ * The daemon's boot: no worker of a previous daemon is wanted. Every
907
+ * leased group is killed (only when the leader still has the lease's start time
908
+ * in the lease's boot/container), the leases are removed, and every command a
909
+ * dead worker held is handed back to `pending` under its own id, so the fresh
910
+ * worker resumes the JSONL and continues. A command whose group could not be
911
+ * ended is failed, not requeued: two workers must never serve one session.
912
+ * Run before any `launch`.
913
+ */
914
+ async recover() {
915
+ const result = { killed: [], stale: [], requeued: [], failed: [] };
916
+ const unkillable = new Set();
917
+ const entries = this.leases.list();
918
+ await Promise.all(entries.map(async ({ session, lease }) => {
919
+ if (lease === null) {
920
+ this.leases.forget(session);
921
+ result.stale.push(session);
922
+ return;
923
+ }
924
+ const out = await killLease(lease, {
925
+ proc: this.proc,
926
+ signal: this.signal,
927
+ graceMs: this.limits.killGraceMs,
928
+ });
929
+ if (out.verdict === "group" || out.verdict === "members")
930
+ result.killed.push(session);
931
+ else
932
+ result.stale.push(session);
933
+ if (out.survivors)
934
+ unkillable.add(lease.command_id);
935
+ else
936
+ this.leases.forget(session);
937
+ this.deps.store.logEvent("worker_lease_recovered", lease.pr, {
938
+ command_id: lease.command_id,
939
+ verdict: out.verdict,
940
+ killed: out.killed,
941
+ denied: out.denied,
942
+ survivors: out.survivors,
943
+ });
944
+ }));
945
+ for (const row of this.deps.store.activeSessionCommands()) {
946
+ if (row.status !== "running" || this.byCommand.has(row.id))
947
+ continue;
948
+ if (unkillable.has(row.id)) {
949
+ const why = "the previous worker's group could not be ended";
950
+ this.failRow(row, null, why);
951
+ this.tellLostAnswer(row, why);
952
+ result.failed.push(row.id);
953
+ }
954
+ else if (this.requeueOrFail(row.id, null, "the daemon restarted"))
955
+ result.requeued.push(row.id);
956
+ else {
957
+ this.tellLostAnswer(row, "the daemon restarted");
958
+ result.failed.push(row.id);
959
+ }
960
+ }
961
+ return result;
962
+ }
963
+ /** An answer command a restart cancelled has no worker to settle it: tell the
964
+ * `settled` hook, which owes the operator the result file it advertised. */
965
+ tellLostAnswer(row, reason) {
966
+ if (row.kind !== "answer" || !this.deps.settled)
967
+ return;
968
+ const payload = verifiedPayload(row, "the command's payload");
969
+ try {
970
+ this.deps.settled({
971
+ command_id: row.id,
972
+ pr: row.pr,
973
+ session: row.session,
974
+ mode: "answer",
975
+ kind: row.kind,
976
+ outcome: "failed",
977
+ reason: `the worker was lost: ${reason}`,
978
+ code: null,
979
+ signal: null,
980
+ report: undefined,
981
+ posted: 0,
982
+ verdict_written: false,
983
+ may_post: payload.ok && operatorMayPost(payload.payload.toString("utf8")),
984
+ });
985
+ }
986
+ catch (e) {
987
+ this.log(`worker settled hook failed: ${String(e)}`);
988
+ }
989
+ }
990
+ /** The daemon is going down: end every worker; their commands requeue. */
991
+ async stop() {
992
+ this.stopping = true;
993
+ if (this.timer)
994
+ clearInterval(this.timer);
995
+ this.timer = null;
996
+ this.deps.permits?.stop();
997
+ const live = [...this.byCommand.values()];
998
+ for (const rec of live)
999
+ this.end(rec, "shutdown");
1000
+ await Promise.all(live.map((rec) => rec.done));
1001
+ }
1002
+ // ---- the session host's questions -----------------------------------
1003
+ /**
1004
+ * Does a worker of this session run? Ours (a live child, or a launch under way),
1005
+ * or one a lease file still names that the process table confirms. The host's
1006
+ * liveness answer: a lease alone never says "alive", since pids repeat.
1007
+ */
1008
+ runs(session) {
1009
+ if (this.bySession.has(session) || this.launching.has(session))
1010
+ return true;
1011
+ const held = this.leases.read(session);
1012
+ if (!held)
1013
+ return false;
1014
+ const verdict = judgeLease(held, this.proc);
1015
+ return verdict.kind === "group" || verdict.kind === "members";
1016
+ }
1017
+ /**
1018
+ * End the session's worker and answer only once it is proven gone: true when no
1019
+ * worker of the session runs (it had none, or its exit has been reaped), false
1020
+ * when it outlived `fenceWaitMs`. The command's row is left as it is (`fence`):
1021
+ * the caller fenced the session to decide the row itself. A launch that is
1022
+ * still under way is waited out first, so a worker cannot start behind the fence.
1023
+ */
1024
+ async fence(session) {
1025
+ // Real time, not the injected clock: this waits on processes.
1026
+ const end = Date.now() + this.limits.fenceWaitMs;
1027
+ while (this.launching.has(session) && Date.now() < end)
1028
+ await sleep(5);
1029
+ const rec = this.bySession.get(session);
1030
+ if (rec) {
1031
+ // Abort first (the worker stops its session and the passes it started, and
1032
+ // exits); the group is sent SIGKILL when that has not happened in the grace.
1033
+ this.startAbort(rec, "fence");
1034
+ await this.exited(rec, Math.max(0, end - Date.now()));
1035
+ }
1036
+ else {
1037
+ // No child of ours, but a lease may still name a group (a worker the boot
1038
+ // could not end, another daemon's). It is killed only while its leader still
1039
+ // has the lease's start time in the lease's boot and container (judgeLease):
1040
+ // a recycled pid or pgid is a stranger's and is left alone.
1041
+ const held = this.leases.read(session);
1042
+ if (held) {
1043
+ const out = await killLease(held, {
1044
+ proc: this.proc,
1045
+ signal: this.signal,
1046
+ graceMs: 0,
1047
+ pollMs: 10,
1048
+ });
1049
+ if (!out.survivors)
1050
+ this.leases.forget(session);
1051
+ }
1052
+ }
1053
+ return !this.runs(session);
1054
+ }
1055
+ /**
1056
+ * Hand a command whose worker has been fenced and is gone back to `pending`
1057
+ * under the same id, for a fresh worker (`launch`) to resume. The CAS is on the
1058
+ * attempt the caller read, so a row that moved since is not replayed.
1059
+ */
1060
+ replay(commandId, expectedAttempt) {
1061
+ return this.deps.store.retrySessionCommandAfterFence(commandId, expectedAttempt, this.iso(this.now() + this.limits.readyMs));
1062
+ }
1063
+ // ---- the operator's controls ---------------------------------------
1064
+ /** The PR's worker, if it can be controlled: running, past `ready`, and not
1065
+ * already on its way out. A refusal says why. */
1066
+ controllable(pr) {
1067
+ const rec = this.bySession.get(`pr-${pr}`);
1068
+ if (!rec || rec.settled)
1069
+ return `no worker is running for #${pr}`;
1070
+ if (rec.killedFor !== undefined)
1071
+ return `the worker of #${pr} is ending`;
1072
+ if (rec.readyAt === undefined)
1073
+ return `the worker of #${pr} has not opened its session yet`;
1074
+ return rec;
1075
+ }
1076
+ /** Push `kind` to the worker and say when its ack comes: null when the worker
1077
+ * is not reachable, the ack otherwise (a settled worker acks `refused`). */
1078
+ forward(rec, kind, text, waitMs) {
1079
+ const id = randomUUID();
1080
+ let timer;
1081
+ const ack = new Promise((resolve) => {
1082
+ rec.controls.set(id, (a) => resolve(a));
1083
+ timer = setTimeout(() => resolve(null), waitMs);
1084
+ timer.unref();
1085
+ }).finally(() => {
1086
+ clearTimeout(timer);
1087
+ rec.controls.delete(id);
1088
+ });
1089
+ const sent = this.deps.push?.(rec.row.id, kind, {
1090
+ id,
1091
+ ...(text !== undefined ? { text } : {}),
1092
+ });
1093
+ if (!sent)
1094
+ rec.controls.get(id)?.({ id, ack: "refused", reason: "the worker is not connected" });
1095
+ return { sent: sent ?? 0, ack, id };
1096
+ }
1097
+ /**
1098
+ * Forward the operator's steer or follow-up to the PR's running worker and answer
1099
+ * with the worker's word: `queued` (the session has it and acts when its turn
1100
+ * allows), `handled` (it acted now), or a refusal with the reason. The text is
1101
+ * validated here as well as by the command's schema. A worker that does not answer
1102
+ * in `controlAckMs` is reported unacknowledged, never as delivered.
1103
+ */
1104
+ async control(pr, kind, text) {
1105
+ let checked;
1106
+ try {
1107
+ checked = controlText(text);
1108
+ }
1109
+ catch (e) {
1110
+ return { ok: false, reason: e instanceof Error ? e.message : String(e) };
1111
+ }
1112
+ if (!this.deps.push)
1113
+ return { ok: false, reason: "this daemon cannot reach its workers" };
1114
+ const rec = this.controllable(pr);
1115
+ if (typeof rec === "string")
1116
+ return { ok: false, reason: rec };
1117
+ const { ack } = this.forward(rec, kind, checked, this.limits.controlAckMs);
1118
+ const got = await ack;
1119
+ if (got === null)
1120
+ return { ok: false, reason: `the worker of #${pr} did not answer; check the session` };
1121
+ if (got.ack === "refused")
1122
+ return { ok: false, reason: got.reason ?? `the worker of #${pr} refused it` };
1123
+ return { ok: true, ack: got.ack, command_id: rec.row.id };
1124
+ }
1125
+ /**
1126
+ * The operator's abort-round: ask the worker to stop its session (and the lens
1127
+ * passes it started) and end. The command's row fails as ended by the operator
1128
+ * (`decideOutcome`). A worker that has not exited within `abortGraceMs`, or that
1129
+ * cannot be reached, has its group sent SIGKILL.
1130
+ */
1131
+ async abortRound(pr) {
1132
+ const rec = this.bySession.get(`pr-${pr}`);
1133
+ if (!rec || rec.settled)
1134
+ return { ok: false, reason: `no worker is running for #${pr}` };
1135
+ if (rec.killedFor !== undefined)
1136
+ return { ok: true, ack: "handled", command_id: rec.row.id, killed: rec.forceKilled };
1137
+ const { ack, sent } = this.startAbort(rec, "operator");
1138
+ // An ack ends the wait. So does the exit. No ack in the grace period (or a worker
1139
+ // that could not be asked) means the SIGKILL is due: wait for it to land.
1140
+ const got = sent > 0 ? await Promise.race([ack, rec.done]) : null;
1141
+ if (got === null || got === undefined)
1142
+ await this.exited(rec, this.limits.fenceWaitMs);
1143
+ return { ok: true, ack: "handled", command_id: rec.row.id, killed: rec.forceKilled };
1144
+ }
1145
+ /** Resolve when `rec` has been reaped or after `ms`, whichever is first. */
1146
+ async exited(rec, ms) {
1147
+ let timer;
1148
+ await Promise.race([
1149
+ rec.done,
1150
+ new Promise((resolve) => {
1151
+ timer = setTimeout(resolve, ms);
1152
+ timer.unref();
1153
+ }),
1154
+ ]);
1155
+ clearTimeout(timer);
1156
+ }
1157
+ /** Ask `rec`'s worker to abort and arm the SIGKILL of its group for when it has
1158
+ * not exited in the grace period (at once, when it cannot be asked). The row
1159
+ * follows the exit as `why` says. */
1160
+ startAbort(rec, why) {
1161
+ const fresh = rec.killedFor === undefined;
1162
+ if (fresh) {
1163
+ rec.killedFor = why;
1164
+ this.log(`aborting worker ${rec.row.id} (${why})`);
1165
+ this.deps.store.logEvent("worker_ending", rec.row.pr, { command_id: rec.row.id, why });
1166
+ }
1167
+ const { sent, ack } = this.forward(rec, "abort", undefined, this.limits.abortGraceMs);
1168
+ if (fresh) {
1169
+ rec.killTimer = setTimeout(() => {
1170
+ if (rec.settled)
1171
+ return;
1172
+ rec.forceKilled = true;
1173
+ this.log(`worker ${rec.row.id} did not stop on abort: SIGKILL to its group`);
1174
+ this.signalGroup(rec, "SIGKILL");
1175
+ }, sent > 0 ? this.limits.abortGraceMs : 0);
1176
+ rec.killTimer.unref();
1177
+ }
1178
+ return { ack, sent };
1179
+ }
1180
+ // ---- views ---------------------------------------------------------------
1181
+ isLive(session) {
1182
+ return this.bySession.has(session);
1183
+ }
1184
+ workers() {
1185
+ const t = this.now();
1186
+ return [...this.byCommand.values()].map((rec) => ({
1187
+ command_id: rec.row.id,
1188
+ pr: rec.row.pr,
1189
+ session: rec.row.session,
1190
+ mode: rec.mode,
1191
+ pid: rec.child.pid ?? -1,
1192
+ generation: rec.generation,
1193
+ stage: rec.readyAt === undefined ? "starting" : rec.acceptedAt === undefined ? "ready" : "running",
1194
+ age_ms: t - rec.spawnedAt,
1195
+ silent_ms: t - rec.lastSeen,
1196
+ ending: rec.killedFor ?? null,
1197
+ }));
1198
+ }
1199
+ hardDeadline(rec) {
1200
+ return rec.wallDeadline + this.limits.killGraceMs;
1201
+ }
1202
+ iso(ms) {
1203
+ return new Date(ms).toISOString();
1204
+ }
1205
+ }
1206
+ //# sourceMappingURL=workersupervisor.js.map