@quickchatai/quickreview 0.0.0-stage → 1.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1479) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +401 -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 +1099 -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/login-route.js +5 -0
  62. package/dist/extensions/cli/login-route.js.map +1 -0
  63. package/dist/extensions/cli/muted-theme.js +5 -0
  64. package/dist/extensions/cli/muted-theme.js.map +1 -0
  65. package/dist/extensions/cli/onboarding.js +5 -0
  66. package/dist/extensions/cli/onboarding.js.map +1 -0
  67. package/dist/extensions/cli/setup.js +5 -0
  68. package/dist/extensions/cli/setup.js.map +1 -0
  69. package/dist/extensions/cli/tui-view.js +5 -0
  70. package/dist/extensions/cli/tui-view.js.map +1 -0
  71. package/dist/extensions/companion-guard.js +361 -0
  72. package/dist/extensions/companion-guard.js.map +1 -0
  73. package/dist/extensions/debug-round.js +204 -0
  74. package/dist/extensions/debug-round.js.map +1 -0
  75. package/dist/extensions/inject-bridge.js +603 -0
  76. package/dist/extensions/inject-bridge.js.map +1 -0
  77. package/dist/extensions/login-route.js +180 -0
  78. package/dist/extensions/login-route.js.map +1 -0
  79. package/dist/extensions/muted-theme.js +12 -0
  80. package/dist/extensions/muted-theme.js.map +1 -0
  81. package/dist/extensions/onboarding.js +198 -0
  82. package/dist/extensions/onboarding.js.map +1 -0
  83. package/dist/extensions/setup-replay.js +269 -0
  84. package/dist/extensions/setup-replay.js.map +1 -0
  85. package/dist/extensions/setup-scan.js +998 -0
  86. package/dist/extensions/setup-scan.js.map +1 -0
  87. package/dist/extensions/setup-triage.js +175 -0
  88. package/dist/extensions/setup-triage.js.map +1 -0
  89. package/dist/extensions/setup.js +1160 -0
  90. package/dist/extensions/setup.js.map +1 -0
  91. package/dist/extensions/tui-view.js +389 -0
  92. package/dist/extensions/tui-view.js.map +1 -0
  93. package/dist/extensions/vendor/openviking-pi/client.js +376 -0
  94. package/dist/extensions/vendor/openviking-pi/client.js.map +1 -0
  95. package/dist/extensions/vendor/openviking-pi/config.js +189 -0
  96. package/dist/extensions/vendor/openviking-pi/config.js.map +1 -0
  97. package/dist/extensions/vendor/openviking-pi/index.js +421 -0
  98. package/dist/extensions/vendor/openviking-pi/index.js.map +1 -0
  99. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +86 -0
  100. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs.map +1 -0
  101. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs +408 -0
  102. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs.map +1 -0
  103. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +41 -0
  104. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs.map +1 -0
  105. package/dist/extensions/vendor/openviking-pi/qcr-hint.js +290 -0
  106. package/dist/extensions/vendor/openviking-pi/qcr-hint.js.map +1 -0
  107. package/dist/extensions/vendor/openviking-pi/qcr-honest.js +148 -0
  108. package/dist/extensions/vendor/openviking-pi/qcr-honest.js.map +1 -0
  109. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js +68 -0
  110. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js.map +1 -0
  111. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js +77 -0
  112. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js.map +1 -0
  113. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js +216 -0
  114. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js.map +1 -0
  115. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js +154 -0
  116. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js.map +1 -0
  117. package/dist/extensions/vendor/openviking-pi/qcr-recall.js +254 -0
  118. package/dist/extensions/vendor/openviking-pi/qcr-recall.js.map +1 -0
  119. package/dist/extensions/vendor/openviking-pi/qcr-shim.js +94 -0
  120. package/dist/extensions/vendor/openviking-pi/qcr-shim.js.map +1 -0
  121. package/dist/extensions/vendor/openviking-pi/qcr-write.js +333 -0
  122. package/dist/extensions/vendor/openviking-pi/qcr-write.js.map +1 -0
  123. package/dist/extensions/vendor/openviking-pi/recall.js +108 -0
  124. package/dist/extensions/vendor/openviking-pi/recall.js.map +1 -0
  125. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs +529 -0
  126. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs.map +1 -0
  127. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs +205 -0
  128. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs.map +1 -0
  129. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs +442 -0
  130. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs.map +1 -0
  131. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs +286 -0
  132. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs.map +1 -0
  133. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +189 -0
  134. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs.map +1 -0
  135. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs +580 -0
  136. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs.map +1 -0
  137. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs +11 -0
  138. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs.map +1 -0
  139. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs +63 -0
  140. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs.map +1 -0
  141. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs +58 -0
  142. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs.map +1 -0
  143. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  144. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs.map +1 -0
  145. package/dist/extensions/vendor/openviking-pi/sync.js +127 -0
  146. package/dist/extensions/vendor/openviking-pi/sync.js.map +1 -0
  147. package/dist/extensions/vendor/openviking-pi/takeover.js +25 -0
  148. package/dist/extensions/vendor/openviking-pi/takeover.js.map +1 -0
  149. package/dist/extensions/vendor/openviking-pi/tools.js +417 -0
  150. package/dist/extensions/vendor/openviking-pi/tools.js.map +1 -0
  151. package/dist/src/anomalies.js +483 -0
  152. package/dist/src/anomalies.js.map +1 -0
  153. package/dist/src/answerworker.js +180 -0
  154. package/dist/src/answerworker.js.map +1 -0
  155. package/dist/src/appstamp.js +68 -0
  156. package/dist/src/appstamp.js.map +1 -0
  157. package/dist/src/archive/admission.js +3 -0
  158. package/dist/src/archive/admission.js.map +1 -0
  159. package/dist/src/archive/archivedb.js +474 -0
  160. package/dist/src/archive/archivedb.js.map +1 -0
  161. package/dist/src/archive/archiver.js +1770 -0
  162. package/dist/src/archive/archiver.js.map +1 -0
  163. package/dist/src/archive/archivewrite.js +198 -0
  164. package/dist/src/archive/archivewrite.js.map +1 -0
  165. package/dist/src/archive/bundle.js +266 -0
  166. package/dist/src/archive/bundle.js.map +1 -0
  167. package/dist/src/archive/dbmove.js +638 -0
  168. package/dist/src/archive/dbmove.js.map +1 -0
  169. package/dist/src/archive/duplicatecounts.js +80 -0
  170. package/dist/src/archive/duplicatecounts.js.map +1 -0
  171. package/dist/src/archive/eligibility.js +113 -0
  172. package/dist/src/archive/eligibility.js.map +1 -0
  173. package/dist/src/archive/extract.js +288 -0
  174. package/dist/src/archive/extract.js.map +1 -0
  175. package/dist/src/archive/fsutil.js +330 -0
  176. package/dist/src/archive/fsutil.js.map +1 -0
  177. package/dist/src/archive/gzfile.js +277 -0
  178. package/dist/src/archive/gzfile.js.map +1 -0
  179. package/dist/src/archive/kinds.js +22 -0
  180. package/dist/src/archive/kinds.js.map +1 -0
  181. package/dist/src/archive/livecheckpoint.js +178 -0
  182. package/dist/src/archive/livecheckpoint.js.map +1 -0
  183. package/dist/src/archive/liveretention.js +145 -0
  184. package/dist/src/archive/liveretention.js.map +1 -0
  185. package/dist/src/archive/manifest.js +284 -0
  186. package/dist/src/archive/manifest.js.map +1 -0
  187. package/dist/src/archive/overseer.js +283 -0
  188. package/dist/src/archive/overseer.js.map +1 -0
  189. package/dist/src/archive/piglobal.js +129 -0
  190. package/dist/src/archive/piglobal.js.map +1 -0
  191. package/dist/src/archive/plan.js +398 -0
  192. package/dist/src/archive/plan.js.map +1 -0
  193. package/dist/src/archive/prarchive.js +831 -0
  194. package/dist/src/archive/prarchive.js.map +1 -0
  195. package/dist/src/archive/prfiles.js +303 -0
  196. package/dist/src/archive/prfiles.js.map +1 -0
  197. package/dist/src/archive/report.js +169 -0
  198. package/dist/src/archive/report.js.map +1 -0
  199. package/dist/src/archive/restore.js +276 -0
  200. package/dist/src/archive/restore.js.map +1 -0
  201. package/dist/src/archive/rows.js +106 -0
  202. package/dist/src/archive/rows.js.map +1 -0
  203. package/dist/src/archive/seal.js +480 -0
  204. package/dist/src/archive/seal.js.map +1 -0
  205. package/dist/src/archive/status.js +528 -0
  206. package/dist/src/archive/status.js.map +1 -0
  207. package/dist/src/archive/storepass.js +409 -0
  208. package/dist/src/archive/storepass.js.map +1 -0
  209. package/dist/src/backfill.js +217 -0
  210. package/dist/src/backfill.js.map +1 -0
  211. package/dist/src/bench/cost.js +87 -0
  212. package/dist/src/bench/exec.js +76 -0
  213. package/dist/src/bench/values.js +14 -0
  214. package/dist/src/botcontrol.js +127 -0
  215. package/dist/src/botcontrol.js.map +1 -0
  216. package/dist/src/botworker.js +805 -0
  217. package/dist/src/botworker.js.map +1 -0
  218. package/dist/src/capture.js +234 -0
  219. package/dist/src/capture.js.map +1 -0
  220. package/dist/src/cases.js +1491 -0
  221. package/dist/src/cases.js.map +1 -0
  222. package/dist/src/channelfs.js +27 -0
  223. package/dist/src/channelfs.js.map +1 -0
  224. package/dist/src/checklist.js +312 -0
  225. package/dist/src/checklist.js.map +1 -0
  226. package/dist/src/ciretry.js +92 -0
  227. package/dist/src/ciretry.js.map +1 -0
  228. package/dist/src/cli.js +1947 -0
  229. package/dist/src/cli.js.map +1 -0
  230. package/dist/src/cliops.js +334 -0
  231. package/dist/src/cliops.js.map +1 -0
  232. package/dist/src/clonedir.js +15 -0
  233. package/dist/src/clonedir.js.map +1 -0
  234. package/dist/src/commandeffects.js +43 -0
  235. package/dist/src/commandeffects.js.map +1 -0
  236. package/dist/src/commands.js +1335 -0
  237. package/dist/src/commands.js.map +1 -0
  238. package/dist/src/companioninbox.js +203 -0
  239. package/dist/src/companioninbox.js.map +1 -0
  240. package/dist/src/compare.js +673 -0
  241. package/dist/src/compare.js.map +1 -0
  242. package/dist/src/config.js +1041 -0
  243. package/dist/src/config.js.map +1 -0
  244. package/dist/src/configcheck.js +111 -0
  245. package/dist/src/configcheck.js.map +1 -0
  246. package/dist/src/coreext.js +43 -0
  247. package/dist/src/coreext.js.map +1 -0
  248. package/dist/src/daemon.js +945 -0
  249. package/dist/src/daemon.js.map +1 -0
  250. package/dist/src/debuground.js +731 -0
  251. package/dist/src/debuground.js.map +1 -0
  252. package/dist/src/debugroundpi.js +223 -0
  253. package/dist/src/debugroundpi.js.map +1 -0
  254. package/dist/src/diagnostics.js +14 -0
  255. package/dist/src/diagnostics.js.map +1 -0
  256. package/dist/src/digest.js +139 -0
  257. package/dist/src/digest.js.map +1 -0
  258. package/dist/src/dispatch.js +1727 -0
  259. package/dist/src/dispatch.js.map +1 -0
  260. package/dist/src/engine/answerguard.js +18 -0
  261. package/dist/src/engine/answerguard.js.map +1 -0
  262. package/dist/src/engine/botsdk.js +262 -0
  263. package/dist/src/engine/botsdk.js.map +1 -0
  264. package/dist/src/engine/caserunner-sdk.js +332 -0
  265. package/dist/src/engine/caserunner-sdk.js.map +1 -0
  266. package/dist/src/engine/debugpi.js +206 -0
  267. package/dist/src/engine/debugpi.js.map +1 -0
  268. package/dist/src/eod.js +473 -0
  269. package/dist/src/eod.js.map +1 -0
  270. package/dist/src/eodpinwatch.js +391 -0
  271. package/dist/src/eodpinwatch.js.map +1 -0
  272. package/dist/src/escalation.js +1009 -0
  273. package/dist/src/escalation.js.map +1 -0
  274. package/dist/src/eventloop.js +779 -0
  275. package/dist/src/eventloop.js.map +1 -0
  276. package/dist/src/execboundary.js +437 -0
  277. package/dist/src/execboundary.js.map +1 -0
  278. package/dist/src/feedback.js +915 -0
  279. package/dist/src/feedback.js.map +1 -0
  280. package/dist/src/findingscheck.js +200 -0
  281. package/dist/src/findingscheck.js.map +1 -0
  282. package/dist/src/fsdenied.js +26 -0
  283. package/dist/src/fsdenied.js.map +1 -0
  284. package/dist/src/ghread.js +181 -0
  285. package/dist/src/ghread.js.map +1 -0
  286. package/dist/src/github.js +1098 -0
  287. package/dist/src/github.js.map +1 -0
  288. package/dist/src/githubtoken.js +346 -0
  289. package/dist/src/githubtoken.js.map +1 -0
  290. package/dist/src/homes.js +103 -0
  291. package/dist/src/homes.js.map +1 -0
  292. package/dist/src/hostroute.js +24 -0
  293. package/dist/src/hostroute.js.map +1 -0
  294. package/dist/src/improvements.js +625 -0
  295. package/dist/src/improvements.js.map +1 -0
  296. package/dist/src/install.js +946 -0
  297. package/dist/src/install.js.map +1 -0
  298. package/dist/src/installkind.js +40 -0
  299. package/dist/src/installkind.js.map +1 -0
  300. package/dist/src/ipc/capability.js +286 -0
  301. package/dist/src/ipc/capability.js.map +1 -0
  302. package/dist/src/ipc/client.js +226 -0
  303. package/dist/src/ipc/client.js.map +1 -0
  304. package/dist/src/ipc/control.js +70 -0
  305. package/dist/src/ipc/control.js.map +1 -0
  306. package/dist/src/ipc/ghreadshim.js +77 -0
  307. package/dist/src/ipc/ghreadshim.js.map +1 -0
  308. package/dist/src/ipc/launcher.js +65 -0
  309. package/dist/src/ipc/launcher.js.map +1 -0
  310. package/dist/src/ipc/permits.js +293 -0
  311. package/dist/src/ipc/permits.js.map +1 -0
  312. package/dist/src/ipc/postshim.js +137 -0
  313. package/dist/src/ipc/postshim.js.map +1 -0
  314. package/dist/src/ipc/protocol.js +239 -0
  315. package/dist/src/ipc/protocol.js.map +1 -0
  316. package/dist/src/ipc/server.js +312 -0
  317. package/dist/src/ipc/server.js.map +1 -0
  318. package/dist/src/ipc/workerspec.js +148 -0
  319. package/dist/src/ipc/workerspec.js.map +1 -0
  320. package/dist/src/learner/learner.js +1272 -0
  321. package/dist/src/learner/learner.js.map +1 -0
  322. package/dist/src/learner/miner.js +948 -0
  323. package/dist/src/learner/miner.js.map +1 -0
  324. package/dist/src/learner/packet.js +216 -0
  325. package/dist/src/learner/packet.js.map +1 -0
  326. package/dist/src/learner/receipt.js +135 -0
  327. package/dist/src/learner/receipt.js.map +1 -0
  328. package/dist/src/learner/status.js +38 -0
  329. package/dist/src/learner/status.js.map +1 -0
  330. package/dist/src/ledgercheck.js +120 -0
  331. package/dist/src/ledgercheck.js.map +1 -0
  332. package/dist/src/lessonledger.js +451 -0
  333. package/dist/src/lessonledger.js.map +1 -0
  334. package/dist/src/lessonselect.js +639 -0
  335. package/dist/src/lessonselect.js.map +1 -0
  336. package/dist/src/lessonshadow.js +540 -0
  337. package/dist/src/lessonshadow.js.map +1 -0
  338. package/dist/src/levers.js +302 -0
  339. package/dist/src/levers.js.map +1 -0
  340. package/dist/src/live/projection.js +450 -0
  341. package/dist/src/live/projection.js.map +1 -0
  342. package/dist/src/live/publish.js +83 -0
  343. package/dist/src/live/publish.js.map +1 -0
  344. package/dist/src/live/read.js +60 -0
  345. package/dist/src/live/read.js.map +1 -0
  346. package/dist/src/livecli.js +288 -0
  347. package/dist/src/livecli.js.map +1 -0
  348. package/dist/src/loginhint.js +47 -0
  349. package/dist/src/loginhint.js.map +1 -0
  350. package/dist/src/loginrefresh/atomic.js +66 -0
  351. package/dist/src/loginrefresh/atomic.js.map +1 -0
  352. package/dist/src/loginrefresh/lock.js +93 -0
  353. package/dist/src/loginrefresh/lock.js.map +1 -0
  354. package/dist/src/loginrefresh/main.js +58 -0
  355. package/dist/src/loginrefresh/main.js.map +1 -0
  356. package/dist/src/loginrefresh/pirefresh.js +52 -0
  357. package/dist/src/loginrefresh/pirefresh.js.map +1 -0
  358. package/dist/src/loginrefresh/refresher.js +286 -0
  359. package/dist/src/loginrefresh/refresher.js.map +1 -0
  360. package/dist/src/loginrefresh/supervisor.js +253 -0
  361. package/dist/src/loginrefresh/supervisor.js.map +1 -0
  362. package/dist/src/loginrefresh/types.js +4 -0
  363. package/dist/src/loginrefresh/types.js.map +1 -0
  364. package/dist/src/memory/context.js +251 -0
  365. package/dist/src/memory/context.js.map +1 -0
  366. package/dist/src/memory/datafence.js +5 -0
  367. package/dist/src/memory/datafence.js.map +1 -0
  368. package/dist/src/memory/delivery.js +131 -0
  369. package/dist/src/memory/delivery.js.map +1 -0
  370. package/dist/src/memory/eventtags.js +81 -0
  371. package/dist/src/memory/eventtags.js.map +1 -0
  372. package/dist/src/memory/health.js +713 -0
  373. package/dist/src/memory/health.js.map +1 -0
  374. package/dist/src/memory/import.js +504 -0
  375. package/dist/src/memory/import.js.map +1 -0
  376. package/dist/src/memory/layout.js +252 -0
  377. package/dist/src/memory/layout.js.map +1 -0
  378. package/dist/src/memory/legacy-file.js +100 -0
  379. package/dist/src/memory/legacy-file.js.map +1 -0
  380. package/dist/src/memory/lessons.js +370 -0
  381. package/dist/src/memory/lessons.js.map +1 -0
  382. package/dist/src/memory/ovsession.js +449 -0
  383. package/dist/src/memory/ovsession.js.map +1 -0
  384. package/dist/src/memory/relayout.js +259 -0
  385. package/dist/src/memory/relayout.js.map +1 -0
  386. package/dist/src/memory/roundactivity.js +180 -0
  387. package/dist/src/memory/roundactivity.js.map +1 -0
  388. package/dist/src/memory/selection.js +690 -0
  389. package/dist/src/memory/selection.js.map +1 -0
  390. package/dist/src/memory/shadowstatus.js +69 -0
  391. package/dist/src/memory/shadowstatus.js.map +1 -0
  392. package/dist/src/memory/store.js +83 -0
  393. package/dist/src/memory/store.js.map +1 -0
  394. package/dist/src/memory/textidentity.js +8 -0
  395. package/dist/src/memory/textidentity.js.map +1 -0
  396. package/dist/src/metrics.js +773 -0
  397. package/dist/src/metrics.js.map +1 -0
  398. package/dist/src/missingconfig.js +8 -0
  399. package/dist/src/missingconfig.js.map +1 -0
  400. package/dist/src/npmverbs.js +228 -0
  401. package/dist/src/npmverbs.js.map +1 -0
  402. package/dist/src/onboard/choices.js +219 -0
  403. package/dist/src/onboard/choices.js.map +1 -0
  404. package/dist/src/onboard/engine.js +329 -0
  405. package/dist/src/onboard/engine.js.map +1 -0
  406. package/dist/src/onboard/launch.js +75 -0
  407. package/dist/src/onboard/launch.js.map +1 -0
  408. package/dist/src/onboard/pipin.js +22 -0
  409. package/dist/src/onboard/pipin.js.map +1 -0
  410. package/dist/src/onboard/stepforward.js +41 -0
  411. package/dist/src/onboard/stepforward.js.map +1 -0
  412. package/dist/src/onboard/steps/appslug.js +214 -0
  413. package/dist/src/onboard/steps/appslug.js.map +1 -0
  414. package/dist/src/onboard/steps/bringup.js +408 -0
  415. package/dist/src/onboard/steps/bringup.js.map +1 -0
  416. package/dist/src/onboard/steps/compose.js +372 -0
  417. package/dist/src/onboard/steps/compose.js.map +1 -0
  418. package/dist/src/onboard/steps/configdelivery.js +50 -0
  419. package/dist/src/onboard/steps/configdelivery.js.map +1 -0
  420. package/dist/src/onboard/steps/configfill.js +1218 -0
  421. package/dist/src/onboard/steps/configfill.js.map +1 -0
  422. package/dist/src/onboard/steps/deploysh.js +80 -0
  423. package/dist/src/onboard/steps/deploysh.js.map +1 -0
  424. package/dist/src/onboard/steps/embeddings.js +472 -0
  425. package/dist/src/onboard/steps/embeddings.js.map +1 -0
  426. package/dist/src/onboard/steps/escalation.js +571 -0
  427. package/dist/src/onboard/steps/escalation.js.map +1 -0
  428. package/dist/src/onboard/steps/githubaccount.js +595 -0
  429. package/dist/src/onboard/steps/githubaccount.js.map +1 -0
  430. package/dist/src/onboard/steps/githubapp.js +1150 -0
  431. package/dist/src/onboard/steps/githubapp.js.map +1 -0
  432. package/dist/src/onboard/steps/golive.js +508 -0
  433. package/dist/src/onboard/steps/golive.js.map +1 -0
  434. package/dist/src/onboard/steps/index.js +78 -0
  435. package/dist/src/onboard/steps/index.js.map +1 -0
  436. package/dist/src/onboard/steps/ingress.js +817 -0
  437. package/dist/src/onboard/steps/ingress.js.map +1 -0
  438. package/dist/src/onboard/steps/inventory.js +420 -0
  439. package/dist/src/onboard/steps/inventory.js.map +1 -0
  440. package/dist/src/onboard/steps/llmauth.js +966 -0
  441. package/dist/src/onboard/steps/llmauth.js.map +1 -0
  442. package/dist/src/onboard/steps/memory.js +1112 -0
  443. package/dist/src/onboard/steps/memory.js.map +1 -0
  444. package/dist/src/onboard/steps/memorykeys.js +43 -0
  445. package/dist/src/onboard/steps/memorykeys.js.map +1 -0
  446. package/dist/src/onboard/steps/preflight.js +172 -0
  447. package/dist/src/onboard/steps/preflight.js.map +1 -0
  448. package/dist/src/onboard/steps/proof.js +812 -0
  449. package/dist/src/onboard/steps/proof.js.map +1 -0
  450. package/dist/src/onboard/steps/ssh.js +300 -0
  451. package/dist/src/onboard/steps/ssh.js.map +1 -0
  452. package/dist/src/onboard/steps/topology.js +291 -0
  453. package/dist/src/onboard/steps/topology.js.map +1 -0
  454. package/dist/src/onboard/steps/transport.js +519 -0
  455. package/dist/src/onboard/steps/transport.js.map +1 -0
  456. package/dist/src/onboard/steps/tuiroute.js +102 -0
  457. package/dist/src/onboard/steps/tuiroute.js.map +1 -0
  458. package/dist/src/onboard/steps/verifyup.js +378 -0
  459. package/dist/src/onboard/steps/verifyup.js.map +1 -0
  460. package/dist/src/onboard/steps/vmdeploy.js +368 -0
  461. package/dist/src/onboard/steps/vmdeploy.js.map +1 -0
  462. package/dist/src/onboard/toml.js +53 -0
  463. package/dist/src/onboard/toml.js.map +1 -0
  464. package/dist/src/onboard/toolnames.js +30 -0
  465. package/dist/src/onboard/toolnames.js.map +1 -0
  466. package/dist/src/opencli.js +508 -0
  467. package/dist/src/opencli.js.map +1 -0
  468. package/dist/src/openpr.js +457 -0
  469. package/dist/src/openpr.js.map +1 -0
  470. package/dist/src/openviking/client.js +821 -0
  471. package/dist/src/openviking/client.js.map +1 -0
  472. package/dist/src/openviking/context.js +218 -0
  473. package/dist/src/openviking/context.js.map +1 -0
  474. package/dist/src/openviking/embedder.js +457 -0
  475. package/dist/src/openviking/embedder.js.map +1 -0
  476. package/dist/src/openviking/gapsink.js +38 -0
  477. package/dist/src/openviking/gapsink.js.map +1 -0
  478. package/dist/src/openviking/health.js +69 -0
  479. package/dist/src/openviking/health.js.map +1 -0
  480. package/dist/src/openviking/index.js +24 -0
  481. package/dist/src/openviking/index.js.map +1 -0
  482. package/dist/src/openviking/lessonfind.js +54 -0
  483. package/dist/src/openviking/lessonfind.js.map +1 -0
  484. package/dist/src/openviking/probe.js +89 -0
  485. package/dist/src/openviking/probe.js.map +1 -0
  486. package/dist/src/openviking/proc.js +95 -0
  487. package/dist/src/openviking/proc.js.map +1 -0
  488. package/dist/src/openviking/provisionreport.js +144 -0
  489. package/dist/src/openviking/provisionreport.js.map +1 -0
  490. package/dist/src/openviking/reembed.js +317 -0
  491. package/dist/src/openviking/reembed.js.map +1 -0
  492. package/dist/src/openviking/relayout.js +153 -0
  493. package/dist/src/openviking/relayout.js.map +1 -0
  494. package/dist/src/openviking/sidecar-main.js +39 -0
  495. package/dist/src/openviking/sidecar-main.js.map +1 -0
  496. package/dist/src/openviking/sidecar.js +79 -0
  497. package/dist/src/openviking/sidecar.js.map +1 -0
  498. package/dist/src/openviking/store.js +1758 -0
  499. package/dist/src/openviking/store.js.map +1 -0
  500. package/dist/src/openviking/supervisor.js +422 -0
  501. package/dist/src/openviking/supervisor.js.map +1 -0
  502. package/dist/src/openviking/types.js +5 -0
  503. package/dist/src/openviking/types.js.map +1 -0
  504. package/dist/src/operator-recovery.js +172 -0
  505. package/dist/src/operator-recovery.js.map +1 -0
  506. package/dist/src/operatormessage.js +44 -0
  507. package/dist/src/operatormessage.js.map +1 -0
  508. package/dist/src/operatorwrite.js +23 -0
  509. package/dist/src/operatorwrite.js.map +1 -0
  510. package/dist/src/outcomes.js +1364 -0
  511. package/dist/src/outcomes.js.map +1 -0
  512. package/dist/src/piauthcopy.js +5 -0
  513. package/dist/src/piauthcopy.js.map +1 -0
  514. package/dist/src/picli.js +45 -0
  515. package/dist/src/picli.js.map +1 -0
  516. package/dist/src/picwd.js +25 -0
  517. package/dist/src/picwd.js.map +1 -0
  518. package/dist/src/pilogin.js +35 -0
  519. package/dist/src/pilogin.js.map +1 -0
  520. package/dist/src/pingpong.js +1028 -0
  521. package/dist/src/pingpong.js.map +1 -0
  522. package/dist/src/posting-journal.js +442 -0
  523. package/dist/src/posting-journal.js.map +1 -0
  524. package/dist/src/posting-outbox.js +666 -0
  525. package/dist/src/posting-outbox.js.map +1 -0
  526. package/dist/src/posting-receipt.js +216 -0
  527. package/dist/src/posting-receipt.js.map +1 -0
  528. package/dist/src/posting.js +348 -0
  529. package/dist/src/posting.js.map +1 -0
  530. package/dist/src/postops.js +637 -0
  531. package/dist/src/postops.js.map +1 -0
  532. package/dist/src/pr-activity.js +11 -0
  533. package/dist/src/pr-activity.js.map +1 -0
  534. package/dist/src/pr-author.js +5 -0
  535. package/dist/src/pr-author.js.map +1 -0
  536. package/dist/src/pr-conversation.js +355 -0
  537. package/dist/src/pr-conversation.js.map +1 -0
  538. package/dist/src/pr-session-lifecycle.js +542 -0
  539. package/dist/src/pr-session-lifecycle.js.map +1 -0
  540. package/dist/src/preflight.js +341 -0
  541. package/dist/src/preflight.js.map +1 -0
  542. package/dist/src/priorresolve.js +275 -0
  543. package/dist/src/priorresolve.js.map +1 -0
  544. package/dist/src/qcrbin.js +180 -0
  545. package/dist/src/qcrbin.js.map +1 -0
  546. package/dist/src/recheck.js +1399 -0
  547. package/dist/src/recheck.js.map +1 -0
  548. package/dist/src/reconcile.js +840 -0
  549. package/dist/src/reconcile.js.map +1 -0
  550. package/dist/src/recordedfindings.js +15 -0
  551. package/dist/src/recordedfindings.js.map +1 -0
  552. package/dist/src/regression.js +546 -0
  553. package/dist/src/regression.js.map +1 -0
  554. package/dist/src/replay.js +598 -0
  555. package/dist/src/replay.js.map +1 -0
  556. package/dist/src/requiredpasses.js +113 -0
  557. package/dist/src/requiredpasses.js.map +1 -0
  558. package/dist/src/resumecheck.js +168 -0
  559. package/dist/src/resumecheck.js.map +1 -0
  560. package/dist/src/reviewcli.js +671 -0
  561. package/dist/src/reviewcli.js.map +1 -0
  562. package/dist/src/reviewcontext.js +22 -0
  563. package/dist/src/reviewcontext.js.map +1 -0
  564. package/dist/src/reviewdetach.js +574 -0
  565. package/dist/src/reviewdetach.js.map +1 -0
  566. package/dist/src/reviewhistory.js +310 -0
  567. package/dist/src/reviewhistory.js.map +1 -0
  568. package/dist/src/reviewhome.js +26 -0
  569. package/dist/src/reviewhome.js.map +1 -0
  570. package/dist/src/reviewmemory.js +110 -0
  571. package/dist/src/reviewmemory.js.map +1 -0
  572. package/dist/src/reviewnow.js +45 -0
  573. package/dist/src/reviewnow.js.map +1 -0
  574. package/dist/src/reviewrendercli.js +104 -0
  575. package/dist/src/reviewrendercli.js.map +1 -0
  576. package/dist/src/round-work.js +20 -0
  577. package/dist/src/round-work.js.map +1 -0
  578. package/dist/src/runhost.js +72 -0
  579. package/dist/src/runhost.js.map +1 -0
  580. package/dist/src/scanauth.js +25 -0
  581. package/dist/src/scanauth.js.map +1 -0
  582. package/dist/src/scanbox.js +846 -0
  583. package/dist/src/scanbox.js.map +1 -0
  584. package/dist/src/scancli.js +1074 -0
  585. package/dist/src/scancli.js.map +1 -0
  586. package/dist/src/scandriverlog.js +30 -0
  587. package/dist/src/scandriverlog.js.map +1 -0
  588. package/dist/src/session-bridge.js +75 -0
  589. package/dist/src/session-bridge.js.map +1 -0
  590. package/dist/src/session-command-payload.js +29 -0
  591. package/dist/src/session-command-payload.js.map +1 -0
  592. package/dist/src/session-command-supervisor.js +939 -0
  593. package/dist/src/session-command-supervisor.js.map +1 -0
  594. package/dist/src/sessionjsonl.js +85 -0
  595. package/dist/src/sessionjsonl.js.map +1 -0
  596. package/dist/src/sessions.js +541 -0
  597. package/dist/src/sessions.js.map +1 -0
  598. package/dist/src/setup/adapters.js +330 -0
  599. package/dist/src/setup/adapters.js.map +1 -0
  600. package/dist/src/setup/baselines.js +64 -0
  601. package/dist/src/setup/baselines.js.map +1 -0
  602. package/dist/src/setup/caserunner.js +554 -0
  603. package/dist/src/setup/caserunner.js.map +1 -0
  604. package/dist/src/setup/configcommit.js +358 -0
  605. package/dist/src/setup/configcommit.js.map +1 -0
  606. package/dist/src/setup/engine.js +672 -0
  607. package/dist/src/setup/engine.js.map +1 -0
  608. package/dist/src/setup/facts.js +593 -0
  609. package/dist/src/setup/facts.js.map +1 -0
  610. package/dist/src/setup/findings.js +948 -0
  611. package/dist/src/setup/findings.js.map +1 -0
  612. package/dist/src/setup/history.js +338 -0
  613. package/dist/src/setup/history.js.map +1 -0
  614. package/dist/src/setup/interview.js +185 -0
  615. package/dist/src/setup/interview.js.map +1 -0
  616. package/dist/src/setup/ledger.js +207 -0
  617. package/dist/src/setup/ledger.js.map +1 -0
  618. package/dist/src/setup/pins.js +43 -0
  619. package/dist/src/setup/pins.js.map +1 -0
  620. package/dist/src/setup/portrait.js +432 -0
  621. package/dist/src/setup/portrait.js.map +1 -0
  622. package/dist/src/setup/presentation.js +9 -0
  623. package/dist/src/setup/presentation.js.map +1 -0
  624. package/dist/src/setup/profile.js +417 -0
  625. package/dist/src/setup/profile.js.map +1 -0
  626. package/dist/src/setup/replay.js +240 -0
  627. package/dist/src/setup/replay.js.map +1 -0
  628. package/dist/src/setup/replaybuild.js +311 -0
  629. package/dist/src/setup/replaybuild.js.map +1 -0
  630. package/dist/src/setup/replayrun.js +806 -0
  631. package/dist/src/setup/replayrun.js.map +1 -0
  632. package/dist/src/setup/replaysource.js +169 -0
  633. package/dist/src/setup/replaysource.js.map +1 -0
  634. package/dist/src/setup/retune.js +333 -0
  635. package/dist/src/setup/retune.js.map +1 -0
  636. package/dist/src/setup/retunelog.js +51 -0
  637. package/dist/src/setup/retunelog.js.map +1 -0
  638. package/dist/src/setup/scan.js +725 -0
  639. package/dist/src/setup/scan.js.map +1 -0
  640. package/dist/src/setup/scanbuild.js +133 -0
  641. package/dist/src/setup/scanbuild.js.map +1 -0
  642. package/dist/src/setup/scanfacts.js +96 -0
  643. package/dist/src/setup/scanfacts.js.map +1 -0
  644. package/dist/src/setup/scanlease.js +251 -0
  645. package/dist/src/setup/scanlease.js.map +1 -0
  646. package/dist/src/setup/scanreport.js +289 -0
  647. package/dist/src/setup/scanreport.js.map +1 -0
  648. package/dist/src/setup/scanrun.js +1733 -0
  649. package/dist/src/setup/scanrun.js.map +1 -0
  650. package/dist/src/setup/scantree.js +257 -0
  651. package/dist/src/setup/scantree.js.map +1 -0
  652. package/dist/src/setup/stage2.js +617 -0
  653. package/dist/src/setup/stage2.js.map +1 -0
  654. package/dist/src/setup/stage2request.js +259 -0
  655. package/dist/src/setup/stage2request.js.map +1 -0
  656. package/dist/src/setup/survey.js +307 -0
  657. package/dist/src/setup/survey.js.map +1 -0
  658. package/dist/src/setup/surveyrun.js +549 -0
  659. package/dist/src/setup/surveyrun.js.map +1 -0
  660. package/dist/src/setup/textsniff.js +89 -0
  661. package/dist/src/setup/textsniff.js.map +1 -0
  662. package/dist/src/setup/trackersink.js +395 -0
  663. package/dist/src/setup/trackersink.js.map +1 -0
  664. package/dist/src/setup/triage.js +636 -0
  665. package/dist/src/setup/triage.js.map +1 -0
  666. package/dist/src/setup/tuning.js +585 -0
  667. package/dist/src/setup/tuning.js.map +1 -0
  668. package/dist/src/setup/unitcut.js +437 -0
  669. package/dist/src/setup/unitcut.js.map +1 -0
  670. package/dist/src/singleflight.js +72 -0
  671. package/dist/src/singleflight.js.map +1 -0
  672. package/dist/src/slack/announce.js +725 -0
  673. package/dist/src/slack/announce.js.map +1 -0
  674. package/dist/src/slack/api.js +227 -0
  675. package/dist/src/slack/api.js.map +1 -0
  676. package/dist/src/slack/messages.js +158 -0
  677. package/dist/src/slack/messages.js.map +1 -0
  678. package/dist/src/slack/origin.js +550 -0
  679. package/dist/src/slack/origin.js.map +1 -0
  680. package/dist/src/slack/policy.js +225 -0
  681. package/dist/src/slack/policy.js.map +1 -0
  682. package/dist/src/slack/reply.js +153 -0
  683. package/dist/src/slack/reply.js.map +1 -0
  684. package/dist/src/slack/router.js +189 -0
  685. package/dist/src/slack/router.js.map +1 -0
  686. package/dist/src/slack/socket.js +323 -0
  687. package/dist/src/slack/socket.js.map +1 -0
  688. package/dist/src/slack/types.js +11 -0
  689. package/dist/src/slack/types.js.map +1 -0
  690. package/dist/src/sqlitehint.js +30 -0
  691. package/dist/src/sqlitehint.js.map +1 -0
  692. package/dist/src/ssh-observation.js +25 -0
  693. package/dist/src/ssh-observation.js.map +1 -0
  694. package/dist/src/state.js +5869 -0
  695. package/dist/src/state.js.map +1 -0
  696. package/dist/src/statemachine.js +223 -0
  697. package/dist/src/statemachine.js.map +1 -0
  698. package/dist/src/stubs.js +52 -0
  699. package/dist/src/stubs.js.map +1 -0
  700. package/dist/src/takeover.js +506 -0
  701. package/dist/src/takeover.js.map +1 -0
  702. package/dist/src/takeoverpi.js +262 -0
  703. package/dist/src/takeoverpi.js.map +1 -0
  704. package/dist/src/terminal-failure.js +26 -0
  705. package/dist/src/terminal-failure.js.map +1 -0
  706. package/dist/src/thread-resolution-refusal.js +4 -0
  707. package/dist/src/thread-resolution-refusal.js.map +1 -0
  708. package/dist/src/tmux.js +126 -0
  709. package/dist/src/tmux.js.map +1 -0
  710. package/dist/src/trackerid.js +43 -0
  711. package/dist/src/trackerid.js.map +1 -0
  712. package/dist/src/transcriptindex.js +512 -0
  713. package/dist/src/transcriptindex.js.map +1 -0
  714. package/dist/src/tui/actions.js +404 -0
  715. package/dist/src/tui/actions.js.map +1 -0
  716. package/dist/src/tui/alerts.js +523 -0
  717. package/dist/src/tui/alerts.js.map +1 -0
  718. package/dist/src/tui/app.js +1884 -0
  719. package/dist/src/tui/app.js.map +1 -0
  720. package/dist/src/tui/archiveops.js +164 -0
  721. package/dist/src/tui/archiveops.js.map +1 -0
  722. package/dist/src/tui/autofile.js +191 -0
  723. package/dist/src/tui/autofile.js.map +1 -0
  724. package/dist/src/tui/board.js +1219 -0
  725. package/dist/src/tui/board.js.map +1 -0
  726. package/dist/src/tui/candidates.js +699 -0
  727. package/dist/src/tui/candidates.js.map +1 -0
  728. package/dist/src/tui/cellwidth.js +151 -0
  729. package/dist/src/tui/cellwidth.js.map +1 -0
  730. package/dist/src/tui/changelog-store.js +404 -0
  731. package/dist/src/tui/changelog-store.js.map +1 -0
  732. package/dist/src/tui/chord.js +26 -0
  733. package/dist/src/tui/chord.js.map +1 -0
  734. package/dist/src/tui/clipboard.js +81 -0
  735. package/dist/src/tui/clipboard.js.map +1 -0
  736. package/dist/src/tui/cmdbar.js +256 -0
  737. package/dist/src/tui/cmdbar.js.map +1 -0
  738. package/dist/src/tui/companion.js +1339 -0
  739. package/dist/src/tui/companion.js.map +1 -0
  740. package/dist/src/tui/companionplan.js +200 -0
  741. package/dist/src/tui/companionplan.js.map +1 -0
  742. package/dist/src/tui/companiontab.js +61 -0
  743. package/dist/src/tui/companiontab.js.map +1 -0
  744. package/dist/src/tui/confighome.js +105 -0
  745. package/dist/src/tui/confighome.js.map +1 -0
  746. package/dist/src/tui/connect.js +50 -0
  747. package/dist/src/tui/connect.js.map +1 -0
  748. package/dist/src/tui/deploy-ceremony.js +75 -0
  749. package/dist/src/tui/deploy-ceremony.js.map +1 -0
  750. package/dist/src/tui/deploy-drain.js +93 -0
  751. package/dist/src/tui/deploy-drain.js.map +1 -0
  752. package/dist/src/tui/deploy-process.js +234 -0
  753. package/dist/src/tui/deploy-process.js.map +1 -0
  754. package/dist/src/tui/deploytab.js +1263 -0
  755. package/dist/src/tui/deploytab.js.map +1 -0
  756. package/dist/src/tui/design.js +111 -0
  757. package/dist/src/tui/design.js.map +1 -0
  758. package/dist/src/tui/digesttab.js +148 -0
  759. package/dist/src/tui/digesttab.js.map +1 -0
  760. package/dist/src/tui/emptystate.js +32 -0
  761. package/dist/src/tui/emptystate.js.map +1 -0
  762. package/dist/src/tui/evidence.js +790 -0
  763. package/dist/src/tui/evidence.js.map +1 -0
  764. package/dist/src/tui/feed.js +415 -0
  765. package/dist/src/tui/feed.js.map +1 -0
  766. package/dist/src/tui/feedbacktab.js +907 -0
  767. package/dist/src/tui/feedbacktab.js.map +1 -0
  768. package/dist/src/tui/filters.js +75 -0
  769. package/dist/src/tui/filters.js.map +1 -0
  770. package/dist/src/tui/ghread.js +328 -0
  771. package/dist/src/tui/ghread.js.map +1 -0
  772. package/dist/src/tui/historypull.js +61 -0
  773. package/dist/src/tui/historypull.js.map +1 -0
  774. package/dist/src/tui/inboxpull.js +197 -0
  775. package/dist/src/tui/inboxpull.js.map +1 -0
  776. package/dist/src/tui/index.js +1511 -0
  777. package/dist/src/tui/index.js.map +1 -0
  778. package/dist/src/tui/issuesink.js +206 -0
  779. package/dist/src/tui/issuesink.js.map +1 -0
  780. package/dist/src/tui/jsonfile.js +32 -0
  781. package/dist/src/tui/jsonfile.js.map +1 -0
  782. package/dist/src/tui/keys.js +97 -0
  783. package/dist/src/tui/keys.js.map +1 -0
  784. package/dist/src/tui/layout.js +70 -0
  785. package/dist/src/tui/layout.js.map +1 -0
  786. package/dist/src/tui/learning.js +469 -0
  787. package/dist/src/tui/learning.js.map +1 -0
  788. package/dist/src/tui/lessonswitch.js +103 -0
  789. package/dist/src/tui/lessonswitch.js.map +1 -0
  790. package/dist/src/tui/livecontrol.js +167 -0
  791. package/dist/src/tui/livecontrol.js.map +1 -0
  792. package/dist/src/tui/memforward.js +347 -0
  793. package/dist/src/tui/memforward.js.map +1 -0
  794. package/dist/src/tui/memincident.js +287 -0
  795. package/dist/src/tui/memincident.js.map +1 -0
  796. package/dist/src/tui/memory.js +485 -0
  797. package/dist/src/tui/memory.js.map +1 -0
  798. package/dist/src/tui/memtab.js +513 -0
  799. package/dist/src/tui/memtab.js.map +1 -0
  800. package/dist/src/tui/metricstab.js +979 -0
  801. package/dist/src/tui/metricstab.js.map +1 -0
  802. package/dist/src/tui/model.js +129 -0
  803. package/dist/src/tui/model.js.map +1 -0
  804. package/dist/src/tui/mouse.js +83 -0
  805. package/dist/src/tui/mouse.js.map +1 -0
  806. package/dist/src/tui/msg.js +196 -0
  807. package/dist/src/tui/msg.js.map +1 -0
  808. package/dist/src/tui/nativecompanion.js +321 -0
  809. package/dist/src/tui/nativecompanion.js.map +1 -0
  810. package/dist/src/tui/openurl.js +17 -0
  811. package/dist/src/tui/openurl.js.map +1 -0
  812. package/dist/src/tui/paint.js +501 -0
  813. package/dist/src/tui/paint.js.map +1 -0
  814. package/dist/src/tui/panes.js +74 -0
  815. package/dist/src/tui/panes.js.map +1 -0
  816. package/dist/src/tui/pipane.js +166 -0
  817. package/dist/src/tui/pipane.js.map +1 -0
  818. package/dist/src/tui/poll-hooks.js +11 -0
  819. package/dist/src/tui/poll-hooks.js.map +1 -0
  820. package/dist/src/tui/poll.js +113 -0
  821. package/dist/src/tui/poll.js.map +1 -0
  822. package/dist/src/tui/proposals.js +715 -0
  823. package/dist/src/tui/proposals.js.map +1 -0
  824. package/dist/src/tui/prpause.js +139 -0
  825. package/dist/src/tui/prpause.js.map +1 -0
  826. package/dist/src/tui/reload.js +351 -0
  827. package/dist/src/tui/reload.js.map +1 -0
  828. package/dist/src/tui/remote.js +318 -0
  829. package/dist/src/tui/remote.js.map +1 -0
  830. package/dist/src/tui/rollover.js +767 -0
  831. package/dist/src/tui/rollover.js.map +1 -0
  832. package/dist/src/tui/route.js +143 -0
  833. package/dist/src/tui/route.js.map +1 -0
  834. package/dist/src/tui/scantab.js +1053 -0
  835. package/dist/src/tui/scantab.js.map +1 -0
  836. package/dist/src/tui/setupentry.js +81 -0
  837. package/dist/src/tui/setupentry.js.map +1 -0
  838. package/dist/src/tui/setupstate.js +29 -0
  839. package/dist/src/tui/setupstate.js.map +1 -0
  840. package/dist/src/tui/sidebar.js +602 -0
  841. package/dist/src/tui/sidebar.js.map +1 -0
  842. package/dist/src/tui/sshtriage.js +490 -0
  843. package/dist/src/tui/sshtriage.js.map +1 -0
  844. package/dist/src/tui/startup.js +172 -0
  845. package/dist/src/tui/startup.js.map +1 -0
  846. package/dist/src/tui/tabs.js +41 -0
  847. package/dist/src/tui/tabs.js.map +1 -0
  848. package/dist/src/tui/termmirror.js +217 -0
  849. package/dist/src/tui/termmirror.js.map +1 -0
  850. package/dist/src/tui/theme.js +96 -0
  851. package/dist/src/tui/theme.js.map +1 -0
  852. package/dist/src/tui/ticketstab.js +224 -0
  853. package/dist/src/tui/ticketstab.js.map +1 -0
  854. package/dist/src/tui/tmuxsocket.js +101 -0
  855. package/dist/src/tui/tmuxsocket.js.map +1 -0
  856. package/dist/src/tui/trackertickets.js +77 -0
  857. package/dist/src/tui/trackertickets.js.map +1 -0
  858. package/dist/src/tui/unwedge.js +235 -0
  859. package/dist/src/tui/unwedge.js.map +1 -0
  860. package/dist/src/tui/viewer.js +479 -0
  861. package/dist/src/tui/viewer.js.map +1 -0
  862. package/dist/src/tui/viewerinput.js +125 -0
  863. package/dist/src/tui/viewerinput.js.map +1 -0
  864. package/dist/src/updatenotice.js +143 -0
  865. package/dist/src/updatenotice.js.map +1 -0
  866. package/dist/src/usage.js +1007 -0
  867. package/dist/src/usage.js.map +1 -0
  868. package/dist/src/verdicts.js +3860 -0
  869. package/dist/src/verdicts.js.map +1 -0
  870. package/dist/src/version.js +58 -0
  871. package/dist/src/version.js.map +1 -0
  872. package/dist/src/wakes.js +411 -0
  873. package/dist/src/wakes.js.map +1 -0
  874. package/dist/src/webhook.js +736 -0
  875. package/dist/src/webhook.js.map +1 -0
  876. package/dist/src/webhookheal.js +238 -0
  877. package/dist/src/webhookheal.js.map +1 -0
  878. package/dist/src/wire.js +1823 -0
  879. package/dist/src/wire.js.map +1 -0
  880. package/dist/src/worker-session-host.js +531 -0
  881. package/dist/src/worker-session-host.js.map +1 -0
  882. package/dist/src/workerbreaker.js +112 -0
  883. package/dist/src/workerbreaker.js.map +1 -0
  884. package/dist/src/workercontrol.js +49 -0
  885. package/dist/src/workercontrol.js.map +1 -0
  886. package/dist/src/workerlease.js +351 -0
  887. package/dist/src/workerlease.js.map +1 -0
  888. package/dist/src/workerliveness.js +84 -0
  889. package/dist/src/workerliveness.js.map +1 -0
  890. package/dist/src/workerlog.js +65 -0
  891. package/dist/src/workerlog.js.map +1 -0
  892. package/dist/src/workerruntime.js +10 -0
  893. package/dist/src/workerruntime.js.map +1 -0
  894. package/dist/src/workersupervisor.js +1206 -0
  895. package/dist/src/workersupervisor.js.map +1 -0
  896. package/dist/src/workerusage.js +23 -0
  897. package/dist/src/workerusage.js.map +1 -0
  898. package/dist/src/workerworld.js +338 -0
  899. package/dist/src/workerworld.js.map +1 -0
  900. package/dist/src/worktrees.js +984 -0
  901. package/dist/src/worktrees.js.map +1 -0
  902. package/docker/Dockerfile +284 -0
  903. package/docker/Dockerfile.dockerignore +35 -0
  904. package/docker/README.md +221 -0
  905. package/docker/companion/Dockerfile +139 -0
  906. package/docker/companion/agents/evidence.md +34 -0
  907. package/docker/companion/agents/explore.md +26 -0
  908. package/docker/companion/agents/pass-survey.md +49 -0
  909. package/docker/companion/agents/study.md +26 -0
  910. package/docker/companion/entrypoint.sh +362 -0
  911. package/docker/companion/memory-health.mjs +269 -0
  912. package/docker/entrypoint.sh +799 -0
  913. package/docker/memory/Dockerfile +191 -0
  914. package/docker/memory/Dockerfile.dockerignore +20 -0
  915. package/docker/memory/README.md +60 -0
  916. package/docker/memory/entrypoint.sh +163 -0
  917. package/docker/setid/qcr-setid.c +109 -0
  918. package/docker/tunnel/Dockerfile.cloudflared +51 -0
  919. package/docker/tunnel/Dockerfile.ngrok +40 -0
  920. package/docker/tunnel/sidecar.mjs +411 -0
  921. package/docker/vm/tmux.conf +26 -0
  922. package/docker-compose.yml +348 -0
  923. package/extensions/cli/bash-guard-ambient.ts +71 -0
  924. package/extensions/cli/bash-guard.ts +12 -0
  925. package/extensions/cli/companion-guard.ts +8 -0
  926. package/extensions/cli/debug-round.ts +9 -0
  927. package/extensions/cli/inject-bridge.ts +8 -0
  928. package/extensions/cli/ledger-pin.ts +13 -0
  929. package/extensions/cli/lens.ts +22 -0
  930. package/extensions/cli/login-route.ts +10 -0
  931. package/extensions/cli/muted-theme.ts +9 -0
  932. package/extensions/cli/onboarding.ts +8 -0
  933. package/extensions/cli/setup.ts +8 -0
  934. package/extensions/cli/tui-view.ts +8 -0
  935. package/extensions/companion-guard.ts +411 -0
  936. package/extensions/debug-round.ts +281 -0
  937. package/extensions/inject-bridge.ts +630 -0
  938. package/extensions/inline-bash.ts +102 -0
  939. package/extensions/login-route.ts +220 -0
  940. package/extensions/muted-theme.json +68 -0
  941. package/extensions/muted-theme.ts +23 -0
  942. package/extensions/onboarding.ts +262 -0
  943. package/extensions/setup-replay.ts +336 -0
  944. package/extensions/setup-scan.ts +1236 -0
  945. package/extensions/setup-triage.ts +190 -0
  946. package/extensions/setup.ts +1428 -0
  947. package/extensions/tui-view.ts +489 -0
  948. package/extensions/vendor/openviking-pi/LICENSE +201 -0
  949. package/extensions/vendor/openviking-pi/NOTICE +68 -0
  950. package/extensions/vendor/openviking-pi/README.md +550 -0
  951. package/extensions/vendor/openviking-pi/client.ts +588 -0
  952. package/extensions/vendor/openviking-pi/config.json +28 -0
  953. package/extensions/vendor/openviking-pi/config.ts +271 -0
  954. package/extensions/vendor/openviking-pi/index.ts +523 -0
  955. package/extensions/vendor/openviking-pi/lib/capture-adapter.d.mts +10 -0
  956. package/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +88 -0
  957. package/extensions/vendor/openviking-pi/lib/takeover-core.d.mts +80 -0
  958. package/extensions/vendor/openviking-pi/lib/takeover-core.mjs +406 -0
  959. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.d.mts +1 -0
  960. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +42 -0
  961. package/extensions/vendor/openviking-pi/patches/0000-vendoring-and-build-conformance.patch +726 -0
  962. package/extensions/vendor/openviking-pi/patches/0001-remove-session-before-compact-handler.patch +101 -0
  963. package/extensions/vendor/openviking-pi/patches/0002-no-ambient-work-in-subagent-leaves.patch +202 -0
  964. package/extensions/vendor/openviking-pi/patches/0003-never-auto-create-openviking-sessions.patch +120 -0
  965. package/extensions/vendor/openviking-pi/patches/0004-viking-write-durable-batch-write.patch +521 -0
  966. package/extensions/vendor/openviking-pi/patches/0005-second-memory-namespace.patch +786 -0
  967. package/extensions/vendor/openviking-pi/patches/0006-writes-that-stick-and-honest-errors.patch +996 -0
  968. package/extensions/vendor/openviking-pi/patches/0007-bounded-recall-no-commit.patch +794 -0
  969. package/extensions/vendor/openviking-pi/patches/0008-pr-derived-recall.patch +379 -0
  970. package/extensions/vendor/openviking-pi/patches/0009-pr-session-tools-in-round-areas.patch +375 -0
  971. package/extensions/vendor/openviking-pi/patches/0010-typed-lessons.patch +448 -0
  972. package/extensions/vendor/openviking-pi/patches/0011-review-session-memory-boundary.patch +382 -0
  973. package/extensions/vendor/openviking-pi/patches/0012-typecheck-against-the-real-pi.patch +129 -0
  974. package/extensions/vendor/openviking-pi/patches/0013-createopenviking-factory.patch +1168 -0
  975. package/extensions/vendor/openviking-pi/qcr-hint.ts +313 -0
  976. package/extensions/vendor/openviking-pi/qcr-honest.ts +183 -0
  977. package/extensions/vendor/openviking-pi/qcr-hooks.ts +87 -0
  978. package/extensions/vendor/openviking-pi/qcr-leaf.ts +78 -0
  979. package/extensions/vendor/openviking-pi/qcr-lesson.ts +231 -0
  980. package/extensions/vendor/openviking-pi/qcr-namespaces.ts +198 -0
  981. package/extensions/vendor/openviking-pi/qcr-recall.ts +288 -0
  982. package/extensions/vendor/openviking-pi/qcr-shim.ts +142 -0
  983. package/extensions/vendor/openviking-pi/qcr-write.ts +427 -0
  984. package/extensions/vendor/openviking-pi/recall.ts +149 -0
  985. package/extensions/vendor/openviking-pi/shared/capture-utils.d.mts +9 -0
  986. package/extensions/vendor/openviking-pi/shared/capture-utils.mjs +515 -0
  987. package/extensions/vendor/openviking-pi/shared/credentials.d.mts +14 -0
  988. package/extensions/vendor/openviking-pi/shared/credentials.mjs +228 -0
  989. package/extensions/vendor/openviking-pi/shared/pending-queue.d.mts +19 -0
  990. package/extensions/vendor/openviking-pi/shared/pending-queue.mjs +458 -0
  991. package/extensions/vendor/openviking-pi/shared/profile-inject.d.mts +17 -0
  992. package/extensions/vendor/openviking-pi/shared/profile-inject.mjs +294 -0
  993. package/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +195 -0
  994. package/extensions/vendor/openviking-pi/shared/recall-core.d.mts +13 -0
  995. package/extensions/vendor/openviking-pi/shared/recall-core.mjs +609 -0
  996. package/extensions/vendor/openviking-pi/shared/retryable.mjs +9 -0
  997. package/extensions/vendor/openviking-pi/shared/session-model.d.mts +3 -0
  998. package/extensions/vendor/openviking-pi/shared/session-model.mjs +57 -0
  999. package/extensions/vendor/openviking-pi/shared/uri-guard.mjs +56 -0
  1000. package/extensions/vendor/openviking-pi/shared/workspace-peer.d.mts +5 -0
  1001. package/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  1002. package/extensions/vendor/openviking-pi/sync.ts +163 -0
  1003. package/extensions/vendor/openviking-pi/takeover.ts +36 -0
  1004. package/extensions/vendor/openviking-pi/tools.ts +479 -0
  1005. package/extensions/vendor/openviking-pi/upstream.json +48 -0
  1006. package/package.json +138 -4
  1007. package/profiles/default/README.md +21 -0
  1008. package/profiles/default/addenda/.gitkeep +0 -0
  1009. package/profiles/default/profile.toml +17 -0
  1010. package/profiles/example-django/README.md +21 -0
  1011. package/profiles/example-django/addenda/10-migration-discipline.md +13 -0
  1012. package/profiles/example-django/addenda/20-new-column-nullability.md +12 -0
  1013. package/profiles/example-django/addenda/30-test-doctrine.md +12 -0
  1014. package/profiles/example-django/addenda/40-orm-usage.md +19 -0
  1015. package/profiles/example-django/addenda/50-declared-shape.md +10 -0
  1016. package/profiles/example-django/addenda/60-config-placement.md +14 -0
  1017. package/profiles/example-django/heuristics.toml +24 -0
  1018. package/profiles/example-django/profile.toml +9 -0
  1019. package/profiles/fast/README.md +24 -0
  1020. package/profiles/fast/profile.toml +59 -0
  1021. package/profiles/minimal/README.md +17 -0
  1022. package/profiles/minimal/addenda/.gitkeep +0 -0
  1023. package/profiles/minimal/profile.toml +8 -0
  1024. package/profiles/snappy/README.md +24 -0
  1025. package/profiles/snappy/addenda/10-race-as-question.md +6 -0
  1026. package/profiles/snappy/profile.toml +46 -0
  1027. package/prompts/companion-day-open.md +46 -0
  1028. package/prompts/companion-first-run.md +104 -0
  1029. package/prompts/companion.md +821 -0
  1030. package/prompts/conversation-system.md +117 -0
  1031. package/prompts/eod-sweep.md +120 -0
  1032. package/prompts/onboarding.md +113 -0
  1033. package/prompts/pass-common.md +52 -0
  1034. package/prompts/pass-quality-common.md +22 -0
  1035. package/prompts/round-first.md +874 -0
  1036. package/prompts/round-follow-up.md +991 -0
  1037. package/prompts/round-re-review.md +889 -0
  1038. package/prompts/round-recheck.md +196 -0
  1039. package/prompts/round-staleness.md +856 -0
  1040. package/schemas/review-result.v1.json +391 -0
  1041. package/schemas/scan-result.v1.json +421 -0
  1042. package/schemas/version.v1.json +57 -0
  1043. package/scripts/approve-pr.sh +16 -0
  1044. package/scripts/build-stamp.mjs +67 -0
  1045. package/scripts/commit-verdict.sh +155 -0
  1046. package/scripts/companion-e2e.sh +250 -0
  1047. package/scripts/companion-memory-forward.mjs +1966 -0
  1048. package/scripts/config-fingerprint.sh +28 -0
  1049. package/scripts/deploy-manifest.mjs +141 -0
  1050. package/scripts/deploy.sh +1435 -0
  1051. package/scripts/directory-lock.mjs +193 -0
  1052. package/scripts/heartbeat-fresh.mjs +54 -0
  1053. package/scripts/install-locator.sh +328 -0
  1054. package/scripts/install-wrapper.sh +76 -0
  1055. package/scripts/memory-search-check.mjs +98 -0
  1056. package/scripts/mint-token.sh +233 -0
  1057. package/scripts/openviking-embedder.py +392 -0
  1058. package/scripts/openviking-ov-conf.mjs +161 -0
  1059. package/scripts/openviking-provision.mjs +1122 -0
  1060. package/scripts/openviking-reembed.mjs +1154 -0
  1061. package/scripts/post-review.sh +16 -0
  1062. package/scripts/pr-checks.sh +256 -0
  1063. package/scripts/pr-context.py +174 -0
  1064. package/scripts/pr-context.sh +63 -0
  1065. package/scripts/pr-self.sh +144 -0
  1066. package/scripts/pr-threads.sh +145 -0
  1067. package/scripts/qcr +15 -0
  1068. package/scripts/qcr-host.sh +769 -0
  1069. package/scripts/render-review.sh +24 -0
  1070. package/scripts/reply-thread.sh +16 -0
  1071. package/scripts/required-passes.py +112 -0
  1072. package/scripts/smoke-companion.sh +211 -0
  1073. package/scripts/tui-deploy-runner.mjs +61 -0
  1074. package/scripts/verify-dist.mjs +201 -0
  1075. package/scripts/vm-ghcr-login.sh +188 -0
  1076. package/seeds/agents/pass-baseline.md +61 -0
  1077. package/seeds/agents/pass-contracts.md +30 -0
  1078. package/seeds/agents/pass-data-safety.md +54 -0
  1079. package/seeds/agents/pass-delivery.md +37 -0
  1080. package/seeds/agents/pass-prod-risk.md +24 -0
  1081. package/seeds/agents/pass-security.md +31 -0
  1082. package/seeds/agents/pass-statelessness.md +27 -0
  1083. package/seeds/agents/pass-ui.md +23 -0
  1084. package/seeds/agents/pass-validate.md +50 -0
  1085. package/seeds/prompts/conversation-system.md +117 -0
  1086. package/seeds/prompts/eod-sweep.md +120 -0
  1087. package/seeds/prompts/pass-common.md +52 -0
  1088. package/skills/companion/adjudicate/SKILL.md +247 -0
  1089. package/skills/companion/evidence/SKILL.md +150 -0
  1090. package/skills/companion/land/SKILL.md +200 -0
  1091. package/skills/companion/replay/SKILL.md +138 -0
  1092. package/skills/companion/setup/SKILL.md +167 -0
  1093. package/skills/companion/survey/SKILL.md +160 -0
  1094. package/skills/selfimprove/README.md +34 -0
  1095. package/skills/selfimprove/SKILL.md +127 -0
  1096. package/skills/selfimprove/agents/openai.yaml +2 -0
  1097. package/skills/selfimprove/commands/selfimprove.md +6 -0
  1098. package/skills/selfimprove/references/fix-loop.md +49 -0
  1099. package/skills/selfimprove/references/ledger.md +20 -0
  1100. package/skills/selfimprove/references/setup.md +40 -0
  1101. package/src/anomalies.ts +566 -0
  1102. package/src/answerworker.ts +251 -0
  1103. package/src/appstamp.ts +65 -0
  1104. package/src/archive/admission.ts +3 -0
  1105. package/src/archive/archivedb.ts +548 -0
  1106. package/src/archive/archiver.ts +1963 -0
  1107. package/src/archive/archivewrite.ts +279 -0
  1108. package/src/archive/bundle.ts +333 -0
  1109. package/src/archive/dbmove.ts +911 -0
  1110. package/src/archive/duplicatecounts.ts +98 -0
  1111. package/src/archive/eligibility.ts +181 -0
  1112. package/src/archive/extract.ts +342 -0
  1113. package/src/archive/fsutil.ts +415 -0
  1114. package/src/archive/gzfile.ts +370 -0
  1115. package/src/archive/kinds.ts +21 -0
  1116. package/src/archive/livecheckpoint.ts +217 -0
  1117. package/src/archive/liveretention.ts +180 -0
  1118. package/src/archive/manifest.ts +519 -0
  1119. package/src/archive/overseer.ts +336 -0
  1120. package/src/archive/piglobal.ts +174 -0
  1121. package/src/archive/plan.ts +612 -0
  1122. package/src/archive/prarchive.ts +984 -0
  1123. package/src/archive/prfiles.ts +406 -0
  1124. package/src/archive/report.ts +252 -0
  1125. package/src/archive/restore.ts +330 -0
  1126. package/src/archive/rows.ts +187 -0
  1127. package/src/archive/seal.ts +630 -0
  1128. package/src/archive/status.ts +719 -0
  1129. package/src/archive/storepass.ts +581 -0
  1130. package/src/backfill.ts +362 -0
  1131. package/src/bench/cost.ts +113 -0
  1132. package/src/bench/exec.ts +90 -0
  1133. package/src/bench/values.ts +13 -0
  1134. package/src/botcontrol.ts +176 -0
  1135. package/src/botworker.ts +953 -0
  1136. package/src/capture.ts +321 -0
  1137. package/src/cases.ts +1789 -0
  1138. package/src/channelfs.ts +26 -0
  1139. package/src/checklist.ts +506 -0
  1140. package/src/ciretry.ts +142 -0
  1141. package/src/cli.ts +2306 -0
  1142. package/src/cliops.ts +385 -0
  1143. package/src/clonedir.ts +15 -0
  1144. package/src/commandeffects.ts +57 -0
  1145. package/src/commands.ts +1704 -0
  1146. package/src/companioninbox.ts +239 -0
  1147. package/src/compare.ts +957 -0
  1148. package/src/config.ts +2070 -0
  1149. package/src/configcheck.ts +133 -0
  1150. package/src/coreext.ts +47 -0
  1151. package/src/daemon.ts +1327 -0
  1152. package/src/debuground.ts +927 -0
  1153. package/src/debugroundpi.ts +272 -0
  1154. package/src/diagnostics.ts +14 -0
  1155. package/src/digest.ts +183 -0
  1156. package/src/dispatch.ts +2251 -0
  1157. package/src/engine/answerguard.ts +27 -0
  1158. package/src/engine/botsdk.ts +336 -0
  1159. package/src/engine/caserunner-sdk.ts +423 -0
  1160. package/src/engine/debugpi.ts +247 -0
  1161. package/src/eod.ts +669 -0
  1162. package/src/eodpinwatch.ts +556 -0
  1163. package/src/escalation.ts +1253 -0
  1164. package/src/eventloop.ts +1045 -0
  1165. package/src/execboundary.ts +645 -0
  1166. package/src/feedback.ts +1162 -0
  1167. package/src/findingscheck.ts +298 -0
  1168. package/src/fsdenied.ts +24 -0
  1169. package/src/ghread.ts +242 -0
  1170. package/src/github.ts +1539 -0
  1171. package/src/githubtoken.ts +435 -0
  1172. package/src/homes.ts +175 -0
  1173. package/src/hostroute.ts +53 -0
  1174. package/src/improvements.ts +787 -0
  1175. package/src/install.ts +1103 -0
  1176. package/src/installkind.ts +50 -0
  1177. package/src/ipc/capability.ts +333 -0
  1178. package/src/ipc/client.ts +269 -0
  1179. package/src/ipc/control.ts +90 -0
  1180. package/src/ipc/ghreadshim.ts +94 -0
  1181. package/src/ipc/launcher.ts +65 -0
  1182. package/src/ipc/permits.ts +362 -0
  1183. package/src/ipc/postshim.ts +164 -0
  1184. package/src/ipc/protocol.ts +342 -0
  1185. package/src/ipc/server.ts +371 -0
  1186. package/src/ipc/workerspec.ts +218 -0
  1187. package/src/learner/learner.ts +1655 -0
  1188. package/src/learner/miner.ts +1290 -0
  1189. package/src/learner/packet.ts +340 -0
  1190. package/src/learner/receipt.ts +168 -0
  1191. package/src/learner/status.ts +107 -0
  1192. package/src/ledgercheck.ts +157 -0
  1193. package/src/lessonledger.ts +703 -0
  1194. package/src/lessonselect.ts +888 -0
  1195. package/src/lessonshadow.ts +810 -0
  1196. package/src/levers.ts +393 -0
  1197. package/src/live/projection.ts +491 -0
  1198. package/src/live/publish.ts +92 -0
  1199. package/src/live/read.ts +86 -0
  1200. package/src/livecli.ts +336 -0
  1201. package/src/loginhint.ts +61 -0
  1202. package/src/loginrefresh/atomic.ts +76 -0
  1203. package/src/loginrefresh/lock.ts +104 -0
  1204. package/src/loginrefresh/main.ts +59 -0
  1205. package/src/loginrefresh/pirefresh.ts +60 -0
  1206. package/src/loginrefresh/refresher.ts +326 -0
  1207. package/src/loginrefresh/supervisor.ts +273 -0
  1208. package/src/loginrefresh/types.ts +35 -0
  1209. package/src/memory/context.ts +385 -0
  1210. package/src/memory/datafence.ts +9 -0
  1211. package/src/memory/delivery.ts +171 -0
  1212. package/src/memory/eventtags.ts +80 -0
  1213. package/src/memory/health.ts +953 -0
  1214. package/src/memory/import.ts +664 -0
  1215. package/src/memory/layout.ts +261 -0
  1216. package/src/memory/legacy-file.ts +104 -0
  1217. package/src/memory/lessons.ts +447 -0
  1218. package/src/memory/ovsession.ts +601 -0
  1219. package/src/memory/relayout.ts +335 -0
  1220. package/src/memory/roundactivity.ts +209 -0
  1221. package/src/memory/selection.ts +989 -0
  1222. package/src/memory/shadowstatus.ts +125 -0
  1223. package/src/memory/store.ts +275 -0
  1224. package/src/memory/textidentity.ts +8 -0
  1225. package/src/metrics.ts +1056 -0
  1226. package/src/missingconfig.ts +7 -0
  1227. package/src/npmverbs.ts +266 -0
  1228. package/src/onboard/choices.ts +255 -0
  1229. package/src/onboard/engine.ts +537 -0
  1230. package/src/onboard/launch.ts +103 -0
  1231. package/src/onboard/pipin.ts +31 -0
  1232. package/src/onboard/stepforward.ts +61 -0
  1233. package/src/onboard/steps/appslug.ts +268 -0
  1234. package/src/onboard/steps/bringup.ts +482 -0
  1235. package/src/onboard/steps/compose.ts +490 -0
  1236. package/src/onboard/steps/configdelivery.ts +58 -0
  1237. package/src/onboard/steps/configfill.ts +1440 -0
  1238. package/src/onboard/steps/deploysh.ts +105 -0
  1239. package/src/onboard/steps/embeddings.ts +550 -0
  1240. package/src/onboard/steps/escalation.ts +640 -0
  1241. package/src/onboard/steps/githubaccount.ts +716 -0
  1242. package/src/onboard/steps/githubapp.ts +1498 -0
  1243. package/src/onboard/steps/golive.ts +579 -0
  1244. package/src/onboard/steps/index.ts +82 -0
  1245. package/src/onboard/steps/ingress.ts +974 -0
  1246. package/src/onboard/steps/inventory.ts +526 -0
  1247. package/src/onboard/steps/llmauth.ts +1180 -0
  1248. package/src/onboard/steps/memory.ts +1347 -0
  1249. package/src/onboard/steps/memorykeys.ts +85 -0
  1250. package/src/onboard/steps/preflight.ts +191 -0
  1251. package/src/onboard/steps/proof.ts +1042 -0
  1252. package/src/onboard/steps/ssh.ts +377 -0
  1253. package/src/onboard/steps/topology.ts +338 -0
  1254. package/src/onboard/steps/transport.ts +680 -0
  1255. package/src/onboard/steps/tuiroute.ts +119 -0
  1256. package/src/onboard/steps/verifyup.ts +467 -0
  1257. package/src/onboard/steps/vmdeploy.ts +442 -0
  1258. package/src/onboard/toml.ts +50 -0
  1259. package/src/onboard/toolnames.ts +34 -0
  1260. package/src/opencli.ts +591 -0
  1261. package/src/openpr.ts +568 -0
  1262. package/src/openviking/client.ts +1131 -0
  1263. package/src/openviking/context.ts +263 -0
  1264. package/src/openviking/embedder.ts +516 -0
  1265. package/src/openviking/gapsink.ts +63 -0
  1266. package/src/openviking/health.ts +83 -0
  1267. package/src/openviking/index.ts +119 -0
  1268. package/src/openviking/lessonfind.ts +92 -0
  1269. package/src/openviking/probe.ts +129 -0
  1270. package/src/openviking/proc.ts +110 -0
  1271. package/src/openviking/provisionreport.ts +160 -0
  1272. package/src/openviking/reembed.ts +412 -0
  1273. package/src/openviking/relayout.ts +177 -0
  1274. package/src/openviking/sidecar-main.ts +38 -0
  1275. package/src/openviking/sidecar.ts +106 -0
  1276. package/src/openviking/store.ts +2025 -0
  1277. package/src/openviking/supervisor.ts +474 -0
  1278. package/src/openviking/types.ts +174 -0
  1279. package/src/operator-recovery.ts +237 -0
  1280. package/src/operatormessage.ts +52 -0
  1281. package/src/operatorwrite.ts +25 -0
  1282. package/src/outcomes.ts +1677 -0
  1283. package/src/piauthcopy.ts +12 -0
  1284. package/src/picli.ts +49 -0
  1285. package/src/picwd.ts +25 -0
  1286. package/src/pilogin.ts +37 -0
  1287. package/src/pingpong.ts +1339 -0
  1288. package/src/posting-journal.ts +554 -0
  1289. package/src/posting-outbox.ts +810 -0
  1290. package/src/posting-receipt.ts +341 -0
  1291. package/src/posting.ts +603 -0
  1292. package/src/postops.ts +832 -0
  1293. package/src/pr-activity.ts +20 -0
  1294. package/src/pr-author.ts +6 -0
  1295. package/src/pr-conversation.ts +432 -0
  1296. package/src/pr-session-lifecycle.ts +631 -0
  1297. package/src/preflight.ts +391 -0
  1298. package/src/priorresolve.ts +343 -0
  1299. package/src/qcrbin.ts +186 -0
  1300. package/src/recheck.ts +1776 -0
  1301. package/src/reconcile.ts +1056 -0
  1302. package/src/recordedfindings.ts +27 -0
  1303. package/src/regression.ts +833 -0
  1304. package/src/replay.ts +816 -0
  1305. package/src/requiredpasses.ts +148 -0
  1306. package/src/resumecheck.ts +246 -0
  1307. package/src/reviewcli.ts +787 -0
  1308. package/src/reviewcontext.ts +35 -0
  1309. package/src/reviewdetach.ts +734 -0
  1310. package/src/reviewhistory.ts +441 -0
  1311. package/src/reviewhome.ts +36 -0
  1312. package/src/reviewmemory.ts +133 -0
  1313. package/src/reviewnow.ts +76 -0
  1314. package/src/reviewrendercli.ts +139 -0
  1315. package/src/round-work.ts +42 -0
  1316. package/src/runhost.ts +108 -0
  1317. package/src/scanauth.ts +36 -0
  1318. package/src/scanbox.ts +1081 -0
  1319. package/src/scancli.ts +1296 -0
  1320. package/src/scandriverlog.ts +32 -0
  1321. package/src/session-bridge.ts +139 -0
  1322. package/src/session-command-payload.ts +35 -0
  1323. package/src/session-command-supervisor.ts +1142 -0
  1324. package/src/sessionjsonl.ts +88 -0
  1325. package/src/sessions.ts +659 -0
  1326. package/src/setup/adapters.ts +335 -0
  1327. package/src/setup/baselines.ts +110 -0
  1328. package/src/setup/caserunner.ts +611 -0
  1329. package/src/setup/configcommit.ts +443 -0
  1330. package/src/setup/engine.ts +1001 -0
  1331. package/src/setup/facts.ts +627 -0
  1332. package/src/setup/findings.ts +1264 -0
  1333. package/src/setup/history.ts +443 -0
  1334. package/src/setup/interview.ts +243 -0
  1335. package/src/setup/ledger.ts +324 -0
  1336. package/src/setup/pins.ts +66 -0
  1337. package/src/setup/portrait.ts +635 -0
  1338. package/src/setup/presentation.ts +18 -0
  1339. package/src/setup/profile.ts +508 -0
  1340. package/src/setup/replay.ts +370 -0
  1341. package/src/setup/replaybuild.ts +392 -0
  1342. package/src/setup/replayrun.ts +1096 -0
  1343. package/src/setup/replaysource.ts +198 -0
  1344. package/src/setup/retune.ts +415 -0
  1345. package/src/setup/retunelog.ts +95 -0
  1346. package/src/setup/scan.ts +1033 -0
  1347. package/src/setup/scanbuild.ts +168 -0
  1348. package/src/setup/scanfacts.ts +107 -0
  1349. package/src/setup/scanlease.ts +297 -0
  1350. package/src/setup/scanreport.ts +373 -0
  1351. package/src/setup/scanrun.ts +2268 -0
  1352. package/src/setup/scantree.ts +259 -0
  1353. package/src/setup/stage2.ts +926 -0
  1354. package/src/setup/stage2request.ts +347 -0
  1355. package/src/setup/survey.ts +458 -0
  1356. package/src/setup/surveyrun.ts +758 -0
  1357. package/src/setup/textsniff.ts +95 -0
  1358. package/src/setup/trackersink.ts +433 -0
  1359. package/src/setup/triage.ts +768 -0
  1360. package/src/setup/tuning.ts +766 -0
  1361. package/src/setup/unitcut.ts +523 -0
  1362. package/src/singleflight.ts +86 -0
  1363. package/src/slack/announce.ts +911 -0
  1364. package/src/slack/api.ts +303 -0
  1365. package/src/slack/messages.ts +288 -0
  1366. package/src/slack/origin.ts +599 -0
  1367. package/src/slack/policy.ts +354 -0
  1368. package/src/slack/reply.ts +201 -0
  1369. package/src/slack/router.ts +285 -0
  1370. package/src/slack/socket.ts +384 -0
  1371. package/src/slack/types.ts +108 -0
  1372. package/src/sqlitehint.ts +32 -0
  1373. package/src/ssh-observation.ts +30 -0
  1374. package/src/state.ts +8261 -0
  1375. package/src/statemachine.ts +372 -0
  1376. package/src/stubs.ts +68 -0
  1377. package/src/takeover.ts +634 -0
  1378. package/src/takeoverpi.ts +306 -0
  1379. package/src/terminal-failure.ts +41 -0
  1380. package/src/thread-resolution-refusal.ts +2 -0
  1381. package/src/tmux.ts +153 -0
  1382. package/src/trackerid.ts +41 -0
  1383. package/src/transcriptindex.ts +665 -0
  1384. package/src/tui/actions.ts +484 -0
  1385. package/src/tui/alerts.ts +666 -0
  1386. package/src/tui/app.ts +2026 -0
  1387. package/src/tui/archiveops.ts +192 -0
  1388. package/src/tui/autofile.ts +233 -0
  1389. package/src/tui/board.ts +1529 -0
  1390. package/src/tui/candidates.ts +889 -0
  1391. package/src/tui/cellwidth.ts +148 -0
  1392. package/src/tui/changelog-store.ts +503 -0
  1393. package/src/tui/chord.ts +25 -0
  1394. package/src/tui/clipboard.ts +92 -0
  1395. package/src/tui/cmdbar.ts +299 -0
  1396. package/src/tui/companion.ts +1495 -0
  1397. package/src/tui/companionplan.ts +247 -0
  1398. package/src/tui/companiontab.ts +83 -0
  1399. package/src/tui/confighome.ts +155 -0
  1400. package/src/tui/connect.ts +74 -0
  1401. package/src/tui/deploy-ceremony.ts +104 -0
  1402. package/src/tui/deploy-drain.ts +129 -0
  1403. package/src/tui/deploy-process.ts +265 -0
  1404. package/src/tui/deploytab.ts +1523 -0
  1405. package/src/tui/design.ts +125 -0
  1406. package/src/tui/digesttab.ts +214 -0
  1407. package/src/tui/emptystate.ts +39 -0
  1408. package/src/tui/evidence.ts +999 -0
  1409. package/src/tui/feed.ts +604 -0
  1410. package/src/tui/feedbacktab.ts +1077 -0
  1411. package/src/tui/filters.ts +94 -0
  1412. package/src/tui/ghread.ts +388 -0
  1413. package/src/tui/historypull.ts +81 -0
  1414. package/src/tui/inboxpull.ts +236 -0
  1415. package/src/tui/index.ts +1656 -0
  1416. package/src/tui/issuesink.ts +238 -0
  1417. package/src/tui/jsonfile.ts +42 -0
  1418. package/src/tui/keys.ts +109 -0
  1419. package/src/tui/layout.ts +108 -0
  1420. package/src/tui/learning.ts +627 -0
  1421. package/src/tui/lessonswitch.ts +118 -0
  1422. package/src/tui/livecontrol.ts +228 -0
  1423. package/src/tui/memforward.ts +492 -0
  1424. package/src/tui/memincident.ts +363 -0
  1425. package/src/tui/memory.ts +620 -0
  1426. package/src/tui/memtab.ts +606 -0
  1427. package/src/tui/metricstab.ts +1177 -0
  1428. package/src/tui/model.ts +165 -0
  1429. package/src/tui/mouse.ts +98 -0
  1430. package/src/tui/msg.ts +268 -0
  1431. package/src/tui/nativecompanion.ts +417 -0
  1432. package/src/tui/openurl.ts +21 -0
  1433. package/src/tui/paint.ts +511 -0
  1434. package/src/tui/panes.ts +98 -0
  1435. package/src/tui/pipane.ts +219 -0
  1436. package/src/tui/poll-hooks.ts +12 -0
  1437. package/src/tui/poll.ts +147 -0
  1438. package/src/tui/proposals.ts +838 -0
  1439. package/src/tui/prpause.ts +159 -0
  1440. package/src/tui/reload.ts +436 -0
  1441. package/src/tui/remote.ts +421 -0
  1442. package/src/tui/rollover.ts +969 -0
  1443. package/src/tui/route.ts +173 -0
  1444. package/src/tui/scantab.ts +1290 -0
  1445. package/src/tui/setupentry.ts +93 -0
  1446. package/src/tui/setupstate.ts +52 -0
  1447. package/src/tui/sidebar.ts +749 -0
  1448. package/src/tui/sshtriage.ts +631 -0
  1449. package/src/tui/startup.ts +231 -0
  1450. package/src/tui/tabs.ts +45 -0
  1451. package/src/tui/termmirror.ts +224 -0
  1452. package/src/tui/theme.ts +96 -0
  1453. package/src/tui/ticketstab.ts +310 -0
  1454. package/src/tui/tmuxsocket.ts +129 -0
  1455. package/src/tui/trackertickets.ts +84 -0
  1456. package/src/tui/unwedge.ts +274 -0
  1457. package/src/tui/viewer.ts +575 -0
  1458. package/src/tui/viewerinput.ts +173 -0
  1459. package/src/updatenotice.ts +178 -0
  1460. package/src/usage.ts +1154 -0
  1461. package/src/verdicts.ts +4707 -0
  1462. package/src/version.ts +80 -0
  1463. package/src/wakes.ts +476 -0
  1464. package/src/webhook.ts +951 -0
  1465. package/src/webhookheal.ts +276 -0
  1466. package/src/wire.ts +2182 -0
  1467. package/src/worker-session-host.ts +602 -0
  1468. package/src/workerbreaker.ts +156 -0
  1469. package/src/workercontrol.ts +104 -0
  1470. package/src/workerlease.ts +441 -0
  1471. package/src/workerliveness.ts +103 -0
  1472. package/src/workerlog.ts +79 -0
  1473. package/src/workerruntime.ts +30 -0
  1474. package/src/workersupervisor.ts +1538 -0
  1475. package/src/workerusage.ts +42 -0
  1476. package/src/workerworld.ts +433 -0
  1477. package/src/worktrees.ts +1138 -0
  1478. package/tests/fixtures/regression-cases.json +795 -0
  1479. package/tests/fixtures/seed-manifest.json +19 -0
@@ -0,0 +1,803 @@
1
+ #!/usr/bin/env bash
2
+ # qcr-update — the thin updater that `provision` installs on the VM once
3
+ # (/usr/local/sbin/qcr-update, root 0755). Every deploy afterwards is
4
+ #
5
+ # tar -C <config home> -cf - config.toml profiles \
6
+ # | ssh vm sudo qcr-update <version>@<daemon index digest> \
7
+ # --memory-digest <memory index digest> [--cutover-ack <version>]
8
+ #
9
+ # and that is the ONLY thing a deploy runs on the VM (scripts/deploy.sh
10
+ # release). Nothing is rsynced, built or installed: the images were built once
11
+ # by CI and are pulled by digest.
12
+ #
13
+ # The config home arrives as a tar on stdin: config.toml and profiles/ only.
14
+ # The updater REFUSES a tar with a secrets/ entry (secrets stay with
15
+ # provision), with an absolute or `..` path, with a link, or with any other
16
+ # top-level name.
17
+ #
18
+ # Order of a run (a refusal before "stop" changes nothing on the VM):
19
+ # lock flock, one updater at a time
20
+ # drain refuse unless status.json says draining=true, running_rounds=0
21
+ # layout on the legacy layout, refuse without --cutover-ack <version>
22
+ # pull pull both images BY DIGEST, check the digests and the labels
23
+ # runspec refuse an image whose qcr.runspec label is newer than
24
+ # update.conf's: "re-run provision"
25
+ # stage-config unpack the tar into config-home.next
26
+ # config-check the NEW image's `qcr config check --json` on it
27
+ # --- from here a failure is RESCUED ---
28
+ # stop stop the daemon container
29
+ # snapshot state.db(+wal/shm) and a tar of state/pi-sessions into
30
+ # <backups>/<version>-<ts>/ (root, 0600; pihome never)
31
+ # preflight the new image's `daemon --preflight` on a scratch copy of
32
+ # the snapshot, --network none. Required: an image without
33
+ # the qcr.preflight label was refused at "pull"
34
+ # seed legacy layout only: seed the sidecar store once (copy plus
35
+ # checksum verify; the daemon's old store is left untouched)
36
+ # swap config-home -> .prev, .next -> config-home
37
+ # sidecar-start / sidecar-ready start the memory sidecar, wait for /ready
38
+ # (a long timeout: a re-embed is a boot)
39
+ # recreate recreate the daemon container on the new image. At the
40
+ # cutover this is the point of no return: the first boot
41
+ # migrates forward.
42
+ #
43
+ # RESCUE (any failure from "stop" up to the recreate): restore the previous
44
+ # config, remove the newly started sidecar (and put the old one back), start
45
+ # the OLD daemon container, wait for its first reconcile in status.json (a
46
+ # healthy legacy boot lifts the drain, and the first reconcile is the
47
+ # observable that it ran), re-send `drain on` through the operator channel,
48
+ # confirm draining=true, and exit non-zero naming the step. Between the
49
+ # auto-lift and the re-sent drain the dispatch pump may already have started
50
+ # held pending_wakes rounds: the bot is left drained but rounds may be
51
+ # running, and a retry waits for running_rounds 0. A failure AFTER the
52
+ # recreate keeps the drain on (a failed first reconcile never lifts it) and is
53
+ # fixed forward.
54
+ #
55
+ # qcr-update status [--json] the layout, the image digests and labels, the
56
+ # run-spec version and fingerprint, the drain
57
+ # state and the last run
58
+ #
59
+ # The run spec is /etc/qcr/update.conf (KEY=VALUE, root-owned, rendered by
60
+ # `deploy.sh provision` from group_vars). Its RUNSPEC_FINGERPRINT is the
61
+ # sha256 of every other KEY=VALUE line, in order; this script recomputes it.
62
+ #
63
+ # Test seam: run as a non-root user, QCR_UPDATE_CONF, QCR_UPDATE_DOCKER,
64
+ # QCR_UPDATE_POLL_S, QCR_UPDATE_NAP_S, QCR_RESCUE_WAIT_S, QCR_DRAIN_RECEIPT_WAIT_S, QCR_MEMORY_READY_TIMEOUT_S and
65
+ # QCR_UPDATE_FAIL_AT=<step> are honoured. As root none of
66
+ # them is: root reads /etc/qcr/update.conf and runs `docker`. (sudo also resets
67
+ # the environment.) tests/qcr-update.test.ts drives it with a fake docker.
68
+
69
+ set -Eeuo pipefail
70
+ umask 077
71
+
72
+ SELF="qcr-update"
73
+
74
+ # ---- the seam ----------------------------------------------------------------
75
+
76
+ TEST_MODE=0
77
+ if [[ "$(id -u)" -eq 0 ]]; then
78
+ CONF=/etc/qcr/update.conf
79
+ DOCKER=docker
80
+ POLL_S=5
81
+ FAIL_AT=""
82
+ RESCUE_WAIT_S=300
83
+ DRAIN_WAIT_S=120
84
+ READY_WAIT_S=""
85
+ NAP_S=5
86
+ elif [[ -n "${QCR_UPDATE_CONF:-}" ]]; then
87
+ TEST_MODE=1
88
+ CONF="$QCR_UPDATE_CONF"
89
+ DOCKER="${QCR_UPDATE_DOCKER:-docker}"
90
+ POLL_S="${QCR_UPDATE_POLL_S:-5}"
91
+ FAIL_AT="${QCR_UPDATE_FAIL_AT:-}"
92
+ RESCUE_WAIT_S="${QCR_RESCUE_WAIT_S:-300}"
93
+ DRAIN_WAIT_S="${QCR_DRAIN_RECEIPT_WAIT_S:-120}"
94
+ READY_WAIT_S="${QCR_MEMORY_READY_TIMEOUT_S:-}"
95
+ NAP_S="${QCR_UPDATE_NAP_S:-$POLL_S}"
96
+ else
97
+ echo "$SELF: must run as root (sudo qcr-update ...)" >&2
98
+ exit 2
99
+ fi
100
+
101
+ LOG_FILE=""
102
+ log() {
103
+ local line="$SELF: $*"
104
+ echo "$line" >&2
105
+ [[ -z "$LOG_FILE" ]] || echo "$(date -u +%Y-%m-%dT%H:%M:%SZ) $line" >>"$LOG_FILE" 2>/dev/null || true
106
+ }
107
+ die() {
108
+ log "$*"
109
+ exit 1
110
+ }
111
+
112
+ # ---- the run spec -------------------------------------------------------------
113
+
114
+ declare -A C=()
115
+ REQUIRED_KEYS=(
116
+ RUNSPEC_VERSION RUNSPEC_FINGERPRINT SANDBOX_ROOT APP_ROOT
117
+ DAEMON_CONTAINER MEMORY_CONTAINER DAEMON_IMAGE_REPO MEMORY_IMAGE_REPO
118
+ MEMORY_NETWORK WEBHOOK_PORT CONTAINER_UID TOOL_UID TOOL_GID TZ
119
+ DAEMON_CPUS DAEMON_MEMORY MEMORY_CPUS MEMORY_MEMORY
120
+ MEMORY_STATE_DIR OPENVIKING_HOME OPENVIKING_PORT BASE_CLONE_DIR LEGACY_SANDBOX_ROOT
121
+ BACKUP_DIR UPDATE_STATE_DIR
122
+ )
123
+
124
+ fingerprint_of() {
125
+ grep -E '^[A-Z][A-Z0-9_]*=' "$1" | grep -v '^RUNSPEC_FINGERPRINT=' | sha256sum | cut -d' ' -f1
126
+ }
127
+
128
+ load_conf() {
129
+ [[ -f "$CONF" ]] || die "no run spec at $CONF — run \`deploy.sh provision\` first"
130
+ if [[ $TEST_MODE -eq 0 ]]; then
131
+ local owner mode
132
+ owner="$(stat -c '%u' "$CONF")"
133
+ mode="$(stat -c '%a' "$CONF")"
134
+ [[ "$owner" == 0 ]] || die "$CONF is not owned by root"
135
+ [[ "${mode: -1}" != [2367] && "${mode: -2:1}" != [2367] ]] || die "$CONF is writable by group or others (mode $mode)"
136
+ fi
137
+ local line key val
138
+ while IFS= read -r line || [[ -n "$line" ]]; do
139
+ [[ -z "$line" || "$line" == \#* ]] && continue
140
+ [[ "$line" =~ ^([A-Z][A-Z0-9_]*)=([A-Za-z0-9_./:@+,-]*)$ ]] || die "$CONF has a line this updater will not read: ${line:0:60}"
141
+ key="${BASH_REMATCH[1]}"
142
+ val="${BASH_REMATCH[2]}"
143
+ C["$key"]="$val"
144
+ done <"$CONF"
145
+ for key in "${REQUIRED_KEYS[@]}"; do
146
+ [[ -n "${C[$key]:-}" ]] || die "$CONF lacks $key — re-run provision"
147
+ done
148
+ [[ "$(fingerprint_of "$CONF")" == "${C[RUNSPEC_FINGERPRINT]}" ]] ||
149
+ die "$CONF does not match its RUNSPEC_FINGERPRINT (edited by hand?) — re-run provision"
150
+ [[ "${C[RUNSPEC_VERSION]}" =~ ^[0-9]+$ ]] || die "$CONF RUNSPEC_VERSION is not a number"
151
+ }
152
+
153
+ # ---- docker helpers ------------------------------------------------------------
154
+
155
+ d() { "$DOCKER" "$@"; }
156
+
157
+ # Every lookup by name is `container inspect`: a bare `docker inspect` resolves any
158
+ # object, and the memory network shares the sidecar's name (the 1.0.2 cutover
159
+ # took the network for an old sidecar and failed renaming it).
160
+
161
+ # A container's label, or "" (a missing container or label is "").
162
+ container_label() {
163
+ d container inspect -f "{{index .Config.Labels \"$2\"}}" "$1" 2>/dev/null | sed 's/^<no value>$//' || true
164
+ }
165
+ image_label() {
166
+ d image inspect -f "{{index .Config.Labels \"$2\"}}" "$1" 2>/dev/null | sed 's/^<no value>$//' || true
167
+ }
168
+ container_exists() { d container inspect -f '{{.Id}}' "$1" >/dev/null 2>&1; }
169
+ container_running() { [[ "$(d container inspect -f '{{.State.Running}}' "$1" 2>/dev/null || true)" == true ]]; }
170
+
171
+ # release | legacy | none — of the daemon container.
172
+ detect_layout() {
173
+ if ! container_exists "${C[DAEMON_CONTAINER]}"; then echo none; return; fi
174
+ if [[ "$(container_label "${C[DAEMON_CONTAINER]}" qcr.layout)" == release ]]; then echo release; else echo legacy; fi
175
+ }
176
+
177
+ # ---- the drain ------------------------------------------------------------------
178
+
179
+ STATUS_JSON() { echo "${C[SANDBOX_ROOT]}/state/status.json"; }
180
+
181
+ # First `"key": value` of status.json, or "".
182
+ status_value() {
183
+ local f; f="$(STATUS_JSON)"
184
+ [[ -f "$f" ]] || return 0
185
+ grep -m1 -o "\"$1\"[[:space:]]*:[[:space:]]*\"\?[^,}\" ]*" "$f" 2>/dev/null | sed -E 's/^[^:]*:[[:space:]]*"?//' || true
186
+ }
187
+
188
+ # ---- status ---------------------------------------------------------------------
189
+
190
+ json_str() { printf '"%s"' "$(printf '%s' "$1" | tr -d '\000-\037"\\')"; }
191
+ json_bool_or_null() { case "$1" in true|false) printf '%s' "$1" ;; *) printf null ;; esac; }
192
+ json_num_or_null() { if [[ "$1" =~ ^[0-9]+$ ]]; then printf '%s' "$1"; else printf null; fi; }
193
+
194
+ image_block() {
195
+ local container="$1" img id
196
+ if ! container_exists "$container"; then printf null; return; fi
197
+ img="$(d container inspect -f '{{.Config.Image}}' "$container" 2>/dev/null || true)"
198
+ printf '{"container":%s,"running":%s,"image":%s,"layout":%s,"build_sha":%s,"runspec":%s,"preflight":%s,"pi":%s}' \
199
+ "$(json_str "$container")" "$(container_running "$container" && echo true || echo false)" \
200
+ "$(json_str "$img")" "$(json_str "$(container_label "$container" qcr.layout)")" \
201
+ "$(json_str "$(container_label "$container" qcr.build-sha)")" \
202
+ "$(json_str "$(container_label "$container" qcr.runspec)")" \
203
+ "$(json_str "$(container_label "$container" qcr.preflight)")" \
204
+ "$(json_str "$(container_label "$container" qcr.pi)")"
205
+ }
206
+
207
+ cmd_status() {
208
+ local json="$1"
209
+ load_conf
210
+ local layout draining rounds last="null" fpfile
211
+ layout="$(detect_layout)"
212
+ draining="$(status_value draining)"
213
+ rounds="$(status_value running_rounds)"
214
+ fpfile="${C[UPDATE_STATE_DIR]}/last-run.json"
215
+ [[ -s "$fpfile" ]] && last="$(cat "$fpfile")"
216
+ if [[ "$json" -eq 1 ]]; then
217
+ printf '{"layout":%s,"daemon":%s,"memory":%s,"runspec":{"version":%s,"fingerprint":%s},"drain":{"draining":%s,"running_rounds":%s},"last_run":%s}\n' \
218
+ "$(json_str "$layout")" "$(image_block "${C[DAEMON_CONTAINER]}")" "$(image_block "${C[MEMORY_CONTAINER]}")" \
219
+ "$(json_str "${C[RUNSPEC_VERSION]}")" "$(json_str "${C[RUNSPEC_FINGERPRINT]}")" \
220
+ "$(json_bool_or_null "$draining")" "$(json_num_or_null "$rounds")" "$last"
221
+ else
222
+ echo "layout $layout"
223
+ echo "runspec v${C[RUNSPEC_VERSION]} ${C[RUNSPEC_FINGERPRINT]}"
224
+ echo "drain draining=${draining:-unknown} running_rounds=${rounds:-unknown}"
225
+ echo "daemon $(image_block "${C[DAEMON_CONTAINER]}")"
226
+ echo "memory $(image_block "${C[MEMORY_CONTAINER]}")"
227
+ echo "last run $last"
228
+ fi
229
+ }
230
+
231
+ # ---- arguments --------------------------------------------------------------------
232
+
233
+ VERSION=""
234
+ DAEMON_DIGEST=""
235
+ MEMORY_DIGEST=""
236
+ ACK=""
237
+
238
+ usage() {
239
+ echo "usage: $SELF <version>@<sha256:daemon-index-digest> --memory-digest <sha256:...> [--cutover-ack <version>] < config.tar" >&2
240
+ echo " $SELF status [--json]" >&2
241
+ exit 2
242
+ }
243
+
244
+ VERSION_RE='^[0-9]+\.[0-9]+\.[0-9]+(-[0-9A-Za-z.]+)?$'
245
+ DIGEST_RE='^sha256:[0-9a-f]{64}$'
246
+
247
+ if [[ "${1:-}" == status ]]; then
248
+ shift
249
+ json=0
250
+ [[ "${1:-}" == --json ]] && { json=1; shift; }
251
+ [[ $# -eq 0 ]] || usage
252
+ cmd_status "$json"
253
+ exit 0
254
+ fi
255
+
256
+ [[ $# -ge 1 ]] || usage
257
+ if [[ "$1" =~ ^([^@]+)@(.+)$ ]]; then
258
+ VERSION="${BASH_REMATCH[1]}"
259
+ DAEMON_DIGEST="${BASH_REMATCH[2]}"
260
+ else
261
+ usage
262
+ fi
263
+ shift
264
+ while [[ $# -gt 0 ]]; do
265
+ case "$1" in
266
+ --memory-digest) [[ $# -ge 2 ]] || usage; MEMORY_DIGEST="$2"; shift ;;
267
+ --cutover-ack) [[ $# -ge 2 ]] || usage; ACK="$2"; shift ;;
268
+ *) usage ;;
269
+ esac
270
+ shift
271
+ done
272
+ [[ "$VERSION" =~ $VERSION_RE ]] || die "'$VERSION' is not a version (X.Y.Z); there is no latest tag"
273
+ [[ "$DAEMON_DIGEST" =~ $DIGEST_RE ]] || die "the daemon digest must be sha256:<64 hex> (got '$DAEMON_DIGEST')"
274
+ [[ "$MEMORY_DIGEST" =~ $DIGEST_RE ]] || die "--memory-digest sha256:<64 hex> is required (got '${MEMORY_DIGEST:-nothing}')"
275
+
276
+ load_conf
277
+
278
+ # ---- state of this run -----------------------------------------------------------
279
+
280
+ TS="$(date -u +%Y%m%dT%H%M%SZ)"
281
+ mkdir -p "${C[UPDATE_STATE_DIR]}"
282
+ LOG_FILE="${C[UPDATE_STATE_DIR]}/update.log"
283
+ STEP="start"
284
+ PHASE=init # init -> rescuable (the stop) -> committed (the recreate)
285
+ WORK="$(mktemp -d "${TMPDIR:-/tmp}/qcr-update.XXXXXX")"
286
+ ROOT="${C[SANDBOX_ROOT]}"
287
+ CFG="$ROOT/config-home"
288
+ UID_GID="${C[CONTAINER_UID]}:${C[CONTAINER_UID]}"
289
+ DAEMON="${C[DAEMON_CONTAINER]}"
290
+ MEM="${C[MEMORY_CONTAINER]}"
291
+ DAEMON_REF="${C[DAEMON_IMAGE_REPO]}@$DAEMON_DIGEST"
292
+ MEMORY_REF="${C[MEMORY_IMAGE_REPO]}@$MEMORY_DIGEST"
293
+ # 0: untouched; 1: config-home moved to .prev; 2: .next is config-home
294
+ SWAP_STATE=0
295
+ LOCKED=0
296
+ OLD_DAEMON_RENAMED=0
297
+ OLD_MEM_RENAMED=0
298
+ OLD_MEM_STOPPED=0
299
+ NEW_MEM_STARTED=0
300
+ SEEDED=0
301
+ RESCUE_OK=1
302
+ SWAP_MARKER="${C[UPDATE_STATE_DIR]}/swap-pending"
303
+ # the SQLite files the snapshot and the preflight scratch copy both carry
304
+ STATE_DB_FILES=(state.db state.db-wal state.db-shm)
305
+ NEW_DAEMON_STARTED=0
306
+ DAEMON_STOPPED=0
307
+ LAYOUT=none
308
+ CONFIG_PATH_IN_CONTAINER="/opt/quickreview/config-home/config.toml"
309
+
310
+ step() {
311
+ STEP="$1"
312
+ log "step: $1"
313
+ [[ -z "$FAIL_AT" || "$FAIL_AT" != "$1" ]] || die "injected failure at step '$1' (test seam)"
314
+ }
315
+
316
+ record_last_run() {
317
+ local result="$1" detail="$2"
318
+ printf '{"version":%s,"at":%s,"result":%s,"step":%s,"detail":%s}\n' \
319
+ "$(json_str "$VERSION")" "$(json_str "$TS")" "$(json_str "$result")" "$(json_str "$STEP")" "$(json_str "$detail")" \
320
+ >"${C[UPDATE_STATE_DIR]}/last-run.json" 2>/dev/null || true
321
+ }
322
+
323
+ # ---- the operator channel (drain) -----------------------------------------------------
324
+
325
+ OPERATOR_DIR="$ROOT/sandbox/commands/operator"
326
+ RESULTS_DIR="$ROOT/sandbox/commands/results"
327
+
328
+ # The operator channel's directory, made and sealed by root here, while no
329
+ # container runs: commands/operator, root-owned 0755. The bot holds no
330
+ # capability that lets root inside it create or take over a directory in the
331
+ # daemon's commands/, so the operator's `docker exec -u 0` writes only
332
+ # into this one, which root owns. A symlink in its place is refused, never
333
+ # followed.
334
+ ensure_operator_channel() {
335
+ local parent="$ROOT/sandbox/commands"
336
+ [[ -d "$parent" && ! -L "$parent" ]] || return 0
337
+ [[ ! -L "$OPERATOR_DIR" ]] || die "$OPERATOR_DIR is a symlink — refusing to seal the operator channel through it"
338
+ [[ -e "$OPERATOR_DIR" ]] || mkdir "$OPERATOR_DIR"
339
+ [[ -d "$OPERATOR_DIR" ]] || die "$OPERATOR_DIR is not a directory — cannot seal the operator channel"
340
+ if [[ $TEST_MODE -eq 0 ]]; then
341
+ chown -h 0:0 "$OPERATOR_DIR" && chmod 0755 "$OPERATOR_DIR"
342
+ fi
343
+ }
344
+
345
+ # Write one `drain on` command as root into the sealed operator directory and
346
+ # wait for the daemon's receipt. 0 only when the receipt says draining=true.
347
+ send_drain_on() {
348
+ local name base waited=0 wait_s="${1:-120}" result
349
+ [[ -d "$ROOT/sandbox/commands" ]] || { log "no commands dir at $ROOT/sandbox/commands — cannot send drain on"; return 1; }
350
+ mkdir -p "$OPERATOR_DIR"
351
+ if [[ $TEST_MODE -eq 0 ]]; then
352
+ chown 0:0 "$OPERATOR_DIR" && chmod 0755 "$OPERATOR_DIR"
353
+ fi
354
+ base="$(date -u +%Y-%m-%dT%H-%M-%S-%3NZ)-qcr-update-drain"
355
+ name="$base.json"
356
+ printf '{"command":"drain","on":true}\n' >"$OPERATOR_DIR/.$name.tmp"
357
+ chmod 0644 "$OPERATOR_DIR/.$name.tmp"
358
+ mv "$OPERATOR_DIR/.$name.tmp" "$OPERATOR_DIR/$name"
359
+ result="$RESULTS_DIR/$base.result.json"
360
+ while (( waited <= wait_s )); do
361
+ if [[ -f "$result" ]] && grep -Eq '"ok"[[:space:]]*:[[:space:]]*true' "$result" &&
362
+ grep -Eq '"draining"[[:space:]]*:[[:space:]]*true' "$result"; then
363
+ return 0
364
+ fi
365
+ if [[ -f "$result" ]] && grep -Eq '"ok"[[:space:]]*:[[:space:]]*false' "$result"; then
366
+ log "the daemon refused drain on: $(head -c 300 "$result" | tr -d '\n')"
367
+ return 1
368
+ fi
369
+ sleep "$NAP_S"
370
+ waited=$((waited + POLL_S))
371
+ done
372
+ log "no receipt for drain on within ${wait_s}s"
373
+ return 1
374
+ }
375
+
376
+ # The old container's first reconcile, as status.json shows it: a heartbeat
377
+ # written by this boot (after the container's StartedAt) with the drain lifted,
378
+ # which is what a healthy first reconcile does. The daemon writes `draining`
379
+ # only while draining and omits the key once lifted, so lifted = absent (or false). A boot whose first reconcile
380
+ # fails leaves the drain standing, so the wait also ends at the timeout.
381
+ wait_first_reconcile() {
382
+ local container="$1" wait_s="${2:-300}" waited=0 started written draining
383
+ started="$(d container inspect -f '{{.State.StartedAt}}' "$container" 2>/dev/null | cut -c1-19 || true)"
384
+ while (( waited <= wait_s )); do
385
+ written="$(status_value written_at | cut -c1-19)"
386
+ draining="$(status_value draining)"
387
+ if [[ -n "$started" && -n "$written" && ! "$written" < "$started" && "$draining" != true ]]; then
388
+ log "the old daemon's first reconcile has run (heartbeat $written, drain lifted)"
389
+ return 0
390
+ fi
391
+ sleep "$NAP_S"
392
+ waited=$((waited + POLL_S))
393
+ done
394
+ log "no first reconcile from the old daemon within ${wait_s}s (the drain may be standing already)"
395
+ return 0
396
+ }
397
+
398
+ # ---- rescue ---------------------------------------------------------------------------
399
+
400
+ rescue() {
401
+ set +e
402
+ trap - ERR
403
+ log "RESCUE after failure at step '$STEP': restoring the previous config and the old containers"
404
+ local ok=1
405
+ [[ $SWAP_STATE -ge 1 ]] || rm -f "$SWAP_MARKER"
406
+ if [[ $SWAP_STATE -ge 1 ]]; then
407
+ # the new config is set aside as .failed, the previous one is current again
408
+ rm -rf "$CFG.failed"
409
+ if [[ -e "$CFG" ]]; then mv "$CFG" "$CFG.failed" || ok=0; fi
410
+ if mv "$CFG.prev" "$CFG"; then rm -f "$SWAP_MARKER"; else log "RESCUE: could not restore $CFG.prev"; ok=0; fi
411
+ fi
412
+ if [[ $NEW_MEM_STARTED -eq 1 || $OLD_MEM_RENAMED -eq 1 ]]; then
413
+ d rm -f "$MEM" >/dev/null 2>&1
414
+ if [[ $OLD_MEM_RENAMED -eq 1 ]]; then
415
+ d rename "$MEM-prev" "$MEM" >/dev/null 2>&1 || { log "RESCUE: could not put the old sidecar back"; ok=0; }
416
+ fi
417
+ fi
418
+ if [[ $OLD_MEM_STOPPED -eq 1 ]]; then
419
+ d start "$MEM" >/dev/null 2>&1 || { log "RESCUE: the old sidecar did not start"; ok=0; }
420
+ fi
421
+ if [[ $SEEDED -eq 1 ]]; then
422
+ # The legacy daemon owns its store again, so the copy this run seeded goes stale from
423
+ # here on: it is set aside (never deleted) and the next run seeds afresh.
424
+ local aside="${C[MEMORY_STATE_DIR]}.rescued-$TS"
425
+ if mv "${C[MEMORY_STATE_DIR]}" "$aside"; then
426
+ log "RESCUE: the sidecar store this run seeded is set aside at $aside; the next run seeds afresh"
427
+ else
428
+ log "RESCUE: could not set aside ${C[MEMORY_STATE_DIR]}: move it away before the next run, or it boots a stale store"
429
+ ok=0
430
+ fi
431
+ fi
432
+ if [[ $NEW_DAEMON_STARTED -eq 1 || $OLD_DAEMON_RENAMED -eq 1 ]]; then
433
+ d rm -f "$DAEMON" >/dev/null 2>&1
434
+ if [[ $OLD_DAEMON_RENAMED -eq 1 ]]; then
435
+ d rename "$DAEMON-prev" "$DAEMON" >/dev/null 2>&1 || { log "RESCUE: could not put the old daemon container back"; ok=0; }
436
+ fi
437
+ fi
438
+ if [[ $DAEMON_STOPPED -eq 1 && "$LAYOUT" != none ]]; then
439
+ d start "$DAEMON" >/dev/null 2>&1 || { log "RESCUE: the old daemon container did not start"; ok=0; }
440
+ wait_first_reconcile "$DAEMON" "$RESCUE_WAIT_S"
441
+ if send_drain_on "$DRAIN_WAIT_S"; then
442
+ log "RESCUE: drain on confirmed. Rounds may be running (held wakes started after the auto-lift): retry once running_rounds is 0"
443
+ else
444
+ log "RESCUE: COULD NOT CONFIRM drain on — drain by hand (qcr drain on) before anything else"
445
+ ok=0
446
+ fi
447
+ fi
448
+ RESCUE_OK=$ok
449
+ [[ $ok -eq 1 ]] && log "RESCUE complete: the previous version is running again" || log "RESCUE INCOMPLETE — look at the VM"
450
+ return 0
451
+ }
452
+
453
+ # Only the run that holds the lock may touch the staging directory.
454
+ cleanup() {
455
+ rm -rf "$WORK"
456
+ [[ $LOCKED -ne 1 ]] || rm -rf "$CFG.next"
457
+ }
458
+
459
+ on_exit() {
460
+ local rc=$?
461
+ trap - EXIT
462
+ if [[ $rc -ne 0 ]]; then
463
+ if [[ "$PHASE" == rescuable ]]; then
464
+ rescue
465
+ if [[ $RESCUE_OK -eq 1 ]]; then
466
+ record_last_run "rescued" "failed at $STEP; previous version restored"
467
+ else
468
+ record_last_run "rescue-incomplete" "failed at $STEP; the rescue did not complete, look at the VM"
469
+ fi
470
+ elif [[ "$PHASE" == committed ]]; then
471
+ log "FAILED at step '$STEP' AFTER the recreate: the drain stays on (a failed first reconcile never lifts it); fix forward"
472
+ record_last_run "failed-forward" "failed at $STEP after the recreate"
473
+ else
474
+ log "FAILED at step '$STEP' — nothing was changed on the VM"
475
+ record_last_run "refused" "failed at $STEP before the stop"
476
+ fi
477
+ cleanup
478
+ log "exit $rc: step '$STEP'"
479
+ exit "$rc"
480
+ fi
481
+ cleanup
482
+ }
483
+ trap on_exit EXIT
484
+ trap 'exit 1' ERR
485
+
486
+ # ---- 1. the lock ------------------------------------------------------------------------
487
+
488
+ step lock
489
+ exec 9>"${C[UPDATE_STATE_DIR]}/update.lock"
490
+ flock -n 9 || die "another qcr-update is running (lock ${C[UPDATE_STATE_DIR]}/update.lock)"
491
+ LOCKED=1
492
+ [[ ! -e "$SWAP_MARKER" ]] ||
493
+ die "a previous qcr-update was interrupted between the config swap and the recreate ($SWAP_MARKER): $CFG.prev holds the config the running daemon was started on. Put it back by hand (mv $CFG $CFG.failed; mv $CFG.prev $CFG), remove the marker, then retry"
494
+
495
+ # The config tar, spooled first so a refusal below needs no stdin.
496
+ step read-config
497
+ cat >"$WORK/config.tar"
498
+ [[ -s "$WORK/config.tar" ]] || die "no config tar on stdin (config.toml and profiles/)"
499
+
500
+ # ---- 2. the drain --------------------------------------------------------------------------
501
+
502
+ step drain
503
+ # A first install has nothing to drain: no daemon container, no heartbeat, no
504
+ # state database. Anything less than all three is an existing install (a lost
505
+ # container over live state), and keeps the drain requirement.
506
+ FRESH=0
507
+ if [[ "$(detect_layout)" == none && ! -e "$(STATUS_JSON)" && ! -e "${C[SANDBOX_ROOT]}/state/state.db" ]]; then
508
+ FRESH=1
509
+ log "fresh install: no daemon container, heartbeat or state database; nothing to drain or snapshot"
510
+ fi
511
+ draining="$(status_value draining)"
512
+ rounds="$(status_value running_rounds)"
513
+ [[ $FRESH -eq 1 ]] || [[ "$draining" == true ]] || die "refusing: the bot is not drained (draining=${draining:-unreadable}). Run \`qcr drain on\`, wait for running_rounds 0, retry"
514
+ [[ $FRESH -eq 1 ]] || [[ "$rounds" =~ ^[0-9]+$ ]] || die "refusing: running_rounds is unreadable in status.json"
515
+ [[ $FRESH -eq 1 ]] || [[ "$rounds" -eq 0 ]] || die "refusing: $rounds round(s) still running. Wait for running_rounds 0, retry"
516
+
517
+ # ---- 3. the layout ------------------------------------------------------------------------------
518
+
519
+ step layout
520
+ LAYOUT="$(detect_layout)"
521
+ log "layout: $LAYOUT"
522
+ # No container of this name, yet a running container writes this state: the run
523
+ # spec names the wrong daemon, and a second daemon would share its state.db.
524
+ if [[ "$LAYOUT" == none && $FRESH -eq 0 ]]; then
525
+ for id in $(d ps -q); do
526
+ if d container inspect -f '{{range .Mounts}}{{.Source}} {{end}}' "$id" 2>/dev/null | tr ' ' '\n' | grep -qx "${C[SANDBOX_ROOT]}/state"; then
527
+ die "refusing: no container ${C[DAEMON_CONTAINER]}, but the running container $(d container inspect -f '{{.Name}}' "$id" | tr -d /) mounts ${C[SANDBOX_ROOT]}/state. The run spec names the wrong daemon: set image_name (and memory_container_name) to the containers this host runs, then provision again"
528
+ fi
529
+ done
530
+ fi
531
+ if [[ "$LAYOUT" == legacy && "$ACK" != "$VERSION" ]]; then
532
+ die "refusing: the VM still runs the legacy layout, so this deploy is the cutover (the first boot migrates forward). Re-run with --cutover-ack $VERSION"
533
+ fi
534
+
535
+ # ---- 4. pull both images by digest, check them ----------------------------------------------------------
536
+
537
+ step pull
538
+ d pull "$DAEMON_REF" >/dev/null || die "could not pull $DAEMON_REF (is the VM logged in to ghcr.io? scripts/vm-ghcr-login.sh)"
539
+ d pull "$MEMORY_REF" >/dev/null || die "could not pull $MEMORY_REF"
540
+
541
+ step check-images
542
+ check_digest() {
543
+ local ref="$1" digest="$2" digests
544
+ digests="$(d image inspect -f '{{range .RepoDigests}}{{.}} {{end}}' "$ref" 2>/dev/null || true)"
545
+ [[ "$digests" == *"@$digest"* ]] || die "the pulled image $ref does not carry the digest $digest (RepoDigests: ${digests:-none})"
546
+ }
547
+ check_digest "$DAEMON_REF" "$DAEMON_DIGEST"
548
+ check_digest "$MEMORY_REF" "$MEMORY_DIGEST"
549
+ [[ "$(image_label "$DAEMON_REF" qcr.layout)" == release ]] || die "$DAEMON_REF is not a release-layout image (no qcr.layout=release label)"
550
+ sha_label="$(image_label "$DAEMON_REF" qcr.build-sha)"
551
+ [[ -n "$sha_label" && "$sha_label" != unstamped ]] || die "$DAEMON_REF carries no CI build stamp (qcr.build-sha)"
552
+ [[ "$(image_label "$DAEMON_REF" qcr.preflight)" == true ]] ||
553
+ die "$DAEMON_REF has no qcr.preflight label: the required \`daemon --preflight\` step cannot run, so the image is refused"
554
+
555
+ step runspec
556
+ image_runspec="$(image_label "$DAEMON_REF" qcr.runspec)"
557
+ [[ "$image_runspec" =~ ^[0-9]+$ ]] || die "$DAEMON_REF has no numeric qcr.runspec label"
558
+ if [[ "$image_runspec" -gt "${C[RUNSPEC_VERSION]}" ]]; then
559
+ die "refusing: the image needs run spec v$image_runspec but $CONF is v${C[RUNSPEC_VERSION]} — re-run provision"
560
+ fi
561
+ # The gate group of the image's setid helper (docker/Dockerfile): the
562
+ # bot is given it, and the helper is what runs the model's tools as TOOL_UID. An
563
+ # image from before the helper (run spec v1) has no label and needs no group.
564
+ SETID_GID="$(image_label "$DAEMON_REF" qcr.setid-gid)"
565
+ if [[ "$image_runspec" -ge 2 || -n "$SETID_GID" ]]; then
566
+ [[ "$SETID_GID" =~ ^[1-9][0-9]*$ ]] || die "$DAEMON_REF needs run spec v$image_runspec but has no numeric qcr.setid-gid label"
567
+ [[ "$SETID_GID" != "${C[CONTAINER_UID]}" ]] || die "$DAEMON_REF's setid gate group $SETID_GID is the container uid's own group"
568
+ fi
569
+ [[ "${C[TOOL_UID]}" =~ ^[1-9][0-9]*$ && "${C[TOOL_UID]}" != "${C[CONTAINER_UID]}" ]] ||
570
+ die "$CONF TOOL_UID (${C[TOOL_UID]}) must be a non-zero uid other than CONTAINER_UID — re-run provision"
571
+ [[ "${C[TOOL_GID]}" =~ ^[1-9][0-9]*$ && "${C[TOOL_GID]}" != "${C[CONTAINER_UID]}" ]] ||
572
+ die "$CONF TOOL_GID (${C[TOOL_GID]}) must be a non-zero gid other than the container's — re-run provision"
573
+ # The helper switches to the identity compiled into the image and nothing else
574
+ # (docker/setid/qcr-setid.c): the run spec must name that same identity.
575
+ if [[ -n "$SETID_GID" ]]; then
576
+ for k in uid gid; do
577
+ want="$(image_label "$DAEMON_REF" "qcr.tool-$k")"
578
+ have="${C[TOOL_${k^^}]}"
579
+ [[ "$want" == "$have" ]] ||
580
+ die "$DAEMON_REF runs the model's tools as tool $k ${want:-?}, but $CONF says TOOL_${k^^}=$have — re-run provision"
581
+ done
582
+ fi
583
+
584
+ # ---- 5. stage the config and check it with the NEW image ---------------------------------------------------
585
+
586
+ step stage-config
587
+ # Names only: no secrets/, no absolute or `..` paths, no links, nothing but
588
+ # config.toml and profiles/.
589
+ bad=""
590
+ while IFS= read -r entry; do
591
+ e="${entry#./}"
592
+ e="${e%/}"
593
+ [[ -z "$e" || "$e" == . ]] && continue
594
+ top="${e%%/*}"
595
+ if [[ "$e" == /* || "$e" == *..* ]]; then bad="$entry (absolute or parent path)"; break; fi
596
+ if [[ "$top" == secrets ]]; then bad="$entry (secrets/ never rides the config tar — secrets stay with provision)"; break; fi
597
+ if [[ "$top" != config.toml && "$top" != profiles ]]; then bad="$entry (only config.toml and profiles/ are accepted)"; break; fi
598
+ if [[ "$top" == config.toml && "$e" != config.toml ]]; then bad="$entry"; break; fi
599
+ done < <(tar -tf "$WORK/config.tar")
600
+ [[ -z "$bad" ]] || die "refusing the config tar: $bad"
601
+ if tar -tvf "$WORK/config.tar" | grep -Eq '^[lh]'; then
602
+ die "refusing the config tar: it holds a link (the controller ships profiles dereferenced)"
603
+ fi
604
+ rm -rf "$CFG.next"
605
+ mkdir -p "$CFG.next"
606
+ tar -xf "$WORK/config.tar" --no-same-owner --no-same-permissions -C "$CFG.next"
607
+ [[ -f "$CFG.next/config.toml" ]] || die "the config tar holds no config.toml"
608
+ chmod -R u+rwX,go+rX,go-w "$CFG.next"
609
+ if [[ $TEST_MODE -eq 0 ]]; then chown -R "$UID_GID" "$CFG.next"; fi
610
+
611
+ step config-check
612
+ check_out="$WORK/config-check.json"
613
+ if ! d run --rm --network none --user "$UID_GID" -v "$CFG.next:/cfg:ro" "$DAEMON_REF" config check --json --config-home /cfg >"$check_out" 2>"$WORK/config-check.err"; then
614
+ log "$(head -c 2000 "$check_out" | tr '\n' ' ')"
615
+ log "$(head -c 500 "$WORK/config-check.err" | tr '\n' ' ')"
616
+ die "refusing: the new image's \`qcr config check\` fails on this config home. Nothing was changed"
617
+ fi
618
+
619
+ # The network is a precondition that changes nothing running.
620
+ if ! d network inspect "${C[MEMORY_NETWORK]}" >/dev/null 2>&1; then
621
+ d network create "${C[MEMORY_NETWORK]}" >/dev/null
622
+ fi
623
+
624
+ # ---- 6. from here a failure is rescued ----------------------------------------------------------------------------
625
+
626
+ BACKUP="${C[BACKUP_DIR]}/$VERSION-$TS"
627
+ STATE="$ROOT/state"
628
+
629
+ PHASE=rescuable
630
+ # Marked before the stop, so a stop that fails half way is rescued like any
631
+ # other step: the old container is started (a no-op if it runs) and re-drained.
632
+ [[ "$LAYOUT" == none ]] || DAEMON_STOPPED=1
633
+ step stop
634
+ if [[ "$LAYOUT" != none ]]; then
635
+ d stop -t 90 "$DAEMON" >/dev/null
636
+ fi
637
+
638
+ step snapshot
639
+ mkdir -p "$BACKUP"
640
+ chmod 0700 "${C[BACKUP_DIR]}" "$BACKUP"
641
+ [[ $FRESH -eq 1 || -f "$STATE/state.db" ]] || die "no $STATE/state.db to snapshot"
642
+ for f in "${STATE_DB_FILES[@]}"; do
643
+ [[ -f "$STATE/$f" ]] && cp -p "$STATE/$f" "$BACKUP/$f"
644
+ done
645
+ if [[ -d "$STATE/pi-sessions" ]]; then
646
+ tar -C "$STATE" -czf "$BACKUP/pi-sessions.tar.gz" pi-sessions
647
+ fi
648
+ chmod 0600 "$BACKUP"/* 2>/dev/null || true
649
+ log "snapshot in $BACKUP"
650
+
651
+ step preflight
652
+ # The scratch copy: the snapshot's db files and the sessions, owned by the
653
+ # container uid, mounted as the app's state dir. --network none: the preflight
654
+ # reads, it reaches nothing. `daemon --preflight` is the image's own check
655
+ #: migrate the scratch db forward, resume the live JSONLs offline.
656
+ SCRATCH="$WORK/preflight-state"
657
+ mkdir -p "$SCRATCH"
658
+ for f in "${STATE_DB_FILES[@]}"; do
659
+ [[ -f "$BACKUP/$f" ]] && cp -p "$BACKUP/$f" "$SCRATCH/$f"
660
+ done
661
+ [[ -f "$BACKUP/pi-sessions.tar.gz" ]] && tar -xzf "$BACKUP/pi-sessions.tar.gz" -C "$SCRATCH"
662
+ if [[ $TEST_MODE -eq 0 ]]; then chown -R "$UID_GID" "$SCRATCH"; fi
663
+ chmod -R go+rX "$SCRATCH"
664
+ d run --rm --network none --user "$UID_GID" \
665
+ -e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER" \
666
+ -v "$SCRATCH:${C[APP_ROOT]}/state" -v "$CFG.next:/opt/quickreview/config-home:ro" \
667
+ -v "$ROOT/pihome:/home/qcr/.pi:ro" \
668
+ "$DAEMON_REF" daemon --preflight >"$WORK/preflight.out" 2>&1 ||
669
+ { tail -n 20 "$WORK/preflight.out" >&2 || true; die "the new image's \`daemon --preflight\` failed on a scratch copy of the snapshot"; }
670
+ rm -rf "$SCRATCH"
671
+
672
+ step seed
673
+ if [[ "$LAYOUT" == legacy ]]; then
674
+ marker="${C[MEMORY_STATE_DIR]}/.seeded-from-daemon"
675
+ if [[ ! -e "$marker" ]]; then
676
+ mkdir -p "${C[MEMORY_STATE_DIR]}" "${C[OPENVIKING_HOME]}"
677
+ chmod 0700 "${C[MEMORY_STATE_DIR]}"
678
+ if [[ $TEST_MODE -eq 0 ]]; then chown "$UID_GID" "${C[MEMORY_STATE_DIR]}"; fi
679
+ # a copy that fails part way is already a stale partial store: marked before the
680
+ # copy, so the rescue sets it aside and the retry seeds from an empty directory
681
+ SEEDED=1
682
+ # additive: no --delete, nothing on either side is removed
683
+ rsync -a "${C[OPENVIKING_HOME]}/" "${C[MEMORY_STATE_DIR]}/"
684
+ diff_out="$(rsync -a --checksum --dry-run --itemize-changes "${C[OPENVIKING_HOME]}/" "${C[MEMORY_STATE_DIR]}/")"
685
+ [[ -z "$diff_out" ]] || die "the sidecar store copy does not verify by checksum: ${diff_out:0:200}"
686
+ printf 'seeded from %s on %s\n' "${C[OPENVIKING_HOME]}" "$TS" >"$marker"
687
+ chmod 0600 "$marker"
688
+ if [[ $TEST_MODE -eq 0 ]]; then chown "$UID_GID" "$marker"; fi
689
+ log "sidecar store seeded from ${C[OPENVIKING_HOME]} (copy verified; the old store is untouched)"
690
+ else
691
+ log "sidecar store already seeded"
692
+ fi
693
+ fi
694
+
695
+ step swap
696
+ rm -rf "$CFG.prev"
697
+ printf '%s\n' "$TS" >"$SWAP_MARKER"
698
+ if [[ -d "$CFG" ]]; then mv "$CFG" "$CFG.prev"; else mkdir -p "$CFG.prev"; fi
699
+ SWAP_STATE=1
700
+ mv "$CFG.next" "$CFG"
701
+ SWAP_STATE=2
702
+
703
+ step sidecar-start
704
+ mem_args=(
705
+ run -d --name "$MEM" --restart unless-stopped --init
706
+ --user "$UID_GID"
707
+ --cpus "${C[MEMORY_CPUS]}" --memory "${C[MEMORY_MEMORY]}" --memory-swap "${C[MEMORY_MEMORY]}"
708
+ --network "${C[MEMORY_NETWORK]}"
709
+ # no published port: OpenViking answers on the container network only
710
+ -v "${C[MEMORY_STATE_DIR]}:${C[OPENVIKING_HOME]}"
711
+ -v "$ROOT/secrets:/opt/quickreview/secrets:ro"
712
+ -v "$ROOT/config-home:/opt/quickreview/config-home:ro"
713
+ -e "TZ=${C[TZ]}" -e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER"
714
+ )
715
+ for key in "${!C[@]}"; do
716
+ [[ "$key" == SIDECAR_ENV_* ]] && mem_args+=(-e "${key#SIDECAR_ENV_}=${C[$key]}")
717
+ done
718
+ mem_args+=("$MEMORY_REF")
719
+ if container_exists "$MEM"; then
720
+ # one writer on the store: the old sidecar stops before the new one starts
721
+ if container_running "$MEM"; then OLD_MEM_STOPPED=1; d stop -t 90 "$MEM" >/dev/null; fi
722
+ d rm -f "$MEM-prev" >/dev/null 2>&1 || true
723
+ d rename "$MEM" "$MEM-prev"
724
+ OLD_MEM_RENAMED=1
725
+ fi
726
+ NEW_MEM_STARTED=1
727
+ d "${mem_args[@]}" >/dev/null
728
+
729
+ step sidecar-ready
730
+ ready_wait="${READY_WAIT_S:-${C[MEMORY_READY_TIMEOUT_S]:-1800}}"
731
+ waited=0
732
+ until d exec "$MEM" curl -fsS "http://127.0.0.1:${C[OPENVIKING_PORT]}/ready" >/dev/null 2>&1; do
733
+ (( waited < ready_wait )) || die "the memory sidecar was not ready within ${ready_wait}s (a re-embed is a boot; read: docker logs --tail 100 $MEM)"
734
+ sleep "$NAP_S"
735
+ waited=$((waited + POLL_S))
736
+ done
737
+ log "memory sidecar ready after ${waited}s"
738
+
739
+ step recreate
740
+ daemon_args=(
741
+ run -d --name "$DAEMON" --restart unless-stopped --init
742
+ --cpus "${C[DAEMON_CPUS]}" --memory "${C[DAEMON_MEMORY]}" --memory-swap "${C[DAEMON_MEMORY]}"
743
+ --user "$UID_GID"
744
+ # the model's tools run as TOOL_UID:TOOL_GID (QCR_TOOLS_AS), which cannot
745
+ # read secrets/ or pi's login; the bot reaches it through the image's setid
746
+ # helper, which switches to that one identity only, given by the --group-add
747
+ # below. The bot stays this uid, so a `docker exec` lands as it. No
748
+ # capability beyond SETUID/SETGID, the helper's file capabilities: the
749
+ # operator channel's `docker exec -u 0` writes into commands/operator, which
750
+ # is root's own (ensure_operator_channel), and needs none.
751
+ # no-new-privileges stays off: it would void the helper's file capabilities;
752
+ # the model's tools carry no_new_privs of their own.
753
+ --cap-drop ALL --cap-add SETUID --cap-add SETGID
754
+ -e "QCR_TOOLS_AS=${C[TOOL_UID]}"
755
+ -p "127.0.0.1:${C[WEBHOOK_PORT]}:${C[WEBHOOK_PORT]}"
756
+ --network "${C[MEMORY_NETWORK]}"
757
+ -v "$ROOT/state:${C[APP_ROOT]}/state"
758
+ -v "$ROOT/secrets:/opt/quickreview/secrets:ro"
759
+ -v "$ROOT/config-home:/opt/quickreview/config-home:ro"
760
+ -v "$ROOT/pihome:/home/qcr/.pi"
761
+ -v "$ROOT/sandbox/wt:${C[APP_ROOT]}/wt"
762
+ -v "$ROOT/sandbox/archive:${C[APP_ROOT]}/archive"
763
+ -v "$ROOT/sandbox/commands:${C[APP_ROOT]}/commands"
764
+ -v "$ROOT/sandbox/digest:${C[APP_ROOT]}/digest"
765
+ -v "$ROOT/sandbox/inject:${C[APP_ROOT]}/inject"
766
+ -v "$ROOT/sandbox/verdict:${C[APP_ROOT]}/verdict"
767
+ # the sessions' own HOME (<root>/pihome: their ovcli.conf, recall hints, retired
768
+ # list and pinned git config), the directory the legacy container kept beside them
769
+ -v "$ROOT/sandbox/pihome:${C[APP_ROOT]}/pihome"
770
+ -v "$ROOT/sandbox/${C[BASE_CLONE_DIR]}:${C[APP_ROOT]}/${C[BASE_CLONE_DIR]}"
771
+ # path continuity for what the legacy container recorded
772
+ -v "$ROOT/sandbox/wt:${C[LEGACY_SANDBOX_ROOT]}/wt"
773
+ -v "$ROOT/sandbox/${C[BASE_CLONE_DIR]}:${C[LEGACY_SANDBOX_ROOT]}/${C[BASE_CLONE_DIR]}"
774
+ -e "TZ=${C[TZ]}" -e "QC_REVIEW_PORT=${C[WEBHOOK_PORT]}" -e QC_BIND_HOST=0.0.0.0
775
+ -e "QCR_CONFIG=$CONFIG_PATH_IN_CONTAINER"
776
+ )
777
+ if [[ -n "$SETID_GID" ]]; then
778
+ # the helper's gate group, and the tool gid the shared directories belong to
779
+ daemon_args+=(--group-add "$SETID_GID" --group-add "${C[TOOL_GID]}")
780
+ fi
781
+ if [[ -n "${C[DAEMON_ENV_FILE]:-}" && -f "${C[DAEMON_ENV_FILE]}" ]]; then
782
+ daemon_args+=(--env-file "${C[DAEMON_ENV_FILE]}")
783
+ fi
784
+ daemon_args+=("$DAEMON_REF" daemon)
785
+ if container_exists "$DAEMON"; then
786
+ d rm -f "$DAEMON-prev" >/dev/null 2>&1 || true
787
+ d rename "$DAEMON" "$DAEMON-prev"
788
+ OLD_DAEMON_RENAMED=1
789
+ fi
790
+ ensure_operator_channel
791
+ NEW_DAEMON_STARTED=1
792
+ d "${daemon_args[@]}" >/dev/null
793
+
794
+ # ---- the point of no return ---------------------------------------------------------------------------------------------
795
+ PHASE=committed
796
+ rm -f "$SWAP_MARKER"
797
+ step post-recreate
798
+ d tag "$DAEMON_REF" "${C[DAEMON_IMAGE_REPO]}:$VERSION" >/dev/null 2>&1 || true
799
+ d tag "$MEMORY_REF" "${C[MEMORY_IMAGE_REPO]}:$VERSION" >/dev/null 2>&1 || true
800
+ container_running "$DAEMON" || die "the new daemon container is not running right after the recreate (docker logs --tail 100 $DAEMON)"
801
+ STEP="done"
802
+ record_last_run "ok" "updated to $VERSION ($sha_label); the drain stays on until the first healthy reconcile lifts it"
803
+ log "updated to $VERSION (build $sha_label). The drain stays on: the new boot's first healthy reconcile lifts it (cutover: the owner triggers and checks one worker round first)"