@quickchatai/quickreview 0.0.0-stage → 1.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1443) hide show
  1. package/LICENSE +23 -0
  2. package/README.md +385 -2
  3. package/THIRD-PARTY-NOTICES.md +134 -0
  4. package/agents/pass-abstraction.md +64 -0
  5. package/agents/pass-ask-human.md +134 -0
  6. package/agents/pass-backcompat.md +67 -0
  7. package/agents/pass-baseline.md +61 -0
  8. package/agents/pass-behaviour-delta.md +64 -0
  9. package/agents/pass-bounds.md +36 -0
  10. package/agents/pass-claims.md +31 -0
  11. package/agents/pass-concurrency.md +168 -0
  12. package/agents/pass-consistency.md +57 -0
  13. package/agents/pass-contracts.md +30 -0
  14. package/agents/pass-data-safety.md +54 -0
  15. package/agents/pass-deferred.md +35 -0
  16. package/agents/pass-delivery.md +37 -0
  17. package/agents/pass-duplication.md +60 -0
  18. package/agents/pass-intent.md +63 -0
  19. package/agents/pass-lint-conformance.md +46 -0
  20. package/agents/pass-maintainability.md +67 -0
  21. package/agents/pass-placement.md +68 -0
  22. package/agents/pass-prod-risk.md +24 -0
  23. package/agents/pass-rollout.md +32 -0
  24. package/agents/pass-roundtrip.md +46 -0
  25. package/agents/pass-security.md +31 -0
  26. package/agents/pass-simplicity.md +68 -0
  27. package/agents/pass-statelessness.md +27 -0
  28. package/agents/pass-style.md +37 -0
  29. package/agents/pass-sweep.md +57 -0
  30. package/agents/pass-tests.md +58 -0
  31. package/agents/pass-ui.md +23 -0
  32. package/agents/pass-validate.md +50 -0
  33. package/agents/pass-widened.md +46 -0
  34. package/agents/scan/pass-scan.md +86 -0
  35. package/bin/qcr.js +11 -0
  36. package/config.example.toml +1067 -0
  37. package/deploy/ansible/README.md +356 -0
  38. package/deploy/ansible/group_vars/all.yml +212 -0
  39. package/deploy/ansible/inventory.example.ini +25 -0
  40. package/deploy/ansible/playbook.yml +360 -0
  41. package/deploy/collect-secrets.sh +289 -0
  42. package/deploy/collect-slack-secrets.mjs +1190 -0
  43. package/deploy/github-app-manifest.json +31 -0
  44. package/deploy/manifest.schema.json +75 -0
  45. package/deploy/qcr-update.sh +803 -0
  46. package/deploy/reviewer/AGENTS.override.md +12 -0
  47. package/dist/extensions/cli/bash-guard-ambient.js +42 -0
  48. package/dist/extensions/cli/bash-guard-ambient.js.map +1 -0
  49. package/dist/extensions/cli/bash-guard.js +5 -0
  50. package/dist/extensions/cli/bash-guard.js.map +1 -0
  51. package/dist/extensions/cli/companion-guard.js +5 -0
  52. package/dist/extensions/cli/companion-guard.js.map +1 -0
  53. package/dist/extensions/cli/debug-round.js +8 -0
  54. package/dist/extensions/cli/debug-round.js.map +1 -0
  55. package/dist/extensions/cli/inject-bridge.js +5 -0
  56. package/dist/extensions/cli/inject-bridge.js.map +1 -0
  57. package/dist/extensions/cli/ledger-pin.js +5 -0
  58. package/dist/extensions/cli/ledger-pin.js.map +1 -0
  59. package/dist/extensions/cli/lens.js +13 -0
  60. package/dist/extensions/cli/lens.js.map +1 -0
  61. package/dist/extensions/cli/muted-theme.js +5 -0
  62. package/dist/extensions/cli/muted-theme.js.map +1 -0
  63. package/dist/extensions/cli/onboarding.js +5 -0
  64. package/dist/extensions/cli/onboarding.js.map +1 -0
  65. package/dist/extensions/cli/setup.js +5 -0
  66. package/dist/extensions/cli/setup.js.map +1 -0
  67. package/dist/extensions/cli/tui-view.js +5 -0
  68. package/dist/extensions/cli/tui-view.js.map +1 -0
  69. package/dist/extensions/companion-guard.js +361 -0
  70. package/dist/extensions/companion-guard.js.map +1 -0
  71. package/dist/extensions/debug-round.js +204 -0
  72. package/dist/extensions/debug-round.js.map +1 -0
  73. package/dist/extensions/inject-bridge.js +603 -0
  74. package/dist/extensions/inject-bridge.js.map +1 -0
  75. package/dist/extensions/muted-theme.js +12 -0
  76. package/dist/extensions/muted-theme.js.map +1 -0
  77. package/dist/extensions/onboarding.js +175 -0
  78. package/dist/extensions/onboarding.js.map +1 -0
  79. package/dist/extensions/setup-replay.js +269 -0
  80. package/dist/extensions/setup-replay.js.map +1 -0
  81. package/dist/extensions/setup-scan.js +998 -0
  82. package/dist/extensions/setup-scan.js.map +1 -0
  83. package/dist/extensions/setup-triage.js +175 -0
  84. package/dist/extensions/setup-triage.js.map +1 -0
  85. package/dist/extensions/setup.js +1160 -0
  86. package/dist/extensions/setup.js.map +1 -0
  87. package/dist/extensions/tui-view.js +389 -0
  88. package/dist/extensions/tui-view.js.map +1 -0
  89. package/dist/extensions/vendor/openviking-pi/client.js +376 -0
  90. package/dist/extensions/vendor/openviking-pi/client.js.map +1 -0
  91. package/dist/extensions/vendor/openviking-pi/config.js +189 -0
  92. package/dist/extensions/vendor/openviking-pi/config.js.map +1 -0
  93. package/dist/extensions/vendor/openviking-pi/index.js +421 -0
  94. package/dist/extensions/vendor/openviking-pi/index.js.map +1 -0
  95. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +86 -0
  96. package/dist/extensions/vendor/openviking-pi/lib/capture-adapter.mjs.map +1 -0
  97. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs +408 -0
  98. package/dist/extensions/vendor/openviking-pi/lib/takeover-core.mjs.map +1 -0
  99. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +41 -0
  100. package/dist/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs.map +1 -0
  101. package/dist/extensions/vendor/openviking-pi/qcr-hint.js +290 -0
  102. package/dist/extensions/vendor/openviking-pi/qcr-hint.js.map +1 -0
  103. package/dist/extensions/vendor/openviking-pi/qcr-honest.js +148 -0
  104. package/dist/extensions/vendor/openviking-pi/qcr-honest.js.map +1 -0
  105. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js +68 -0
  106. package/dist/extensions/vendor/openviking-pi/qcr-hooks.js.map +1 -0
  107. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js +77 -0
  108. package/dist/extensions/vendor/openviking-pi/qcr-leaf.js.map +1 -0
  109. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js +216 -0
  110. package/dist/extensions/vendor/openviking-pi/qcr-lesson.js.map +1 -0
  111. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js +154 -0
  112. package/dist/extensions/vendor/openviking-pi/qcr-namespaces.js.map +1 -0
  113. package/dist/extensions/vendor/openviking-pi/qcr-recall.js +254 -0
  114. package/dist/extensions/vendor/openviking-pi/qcr-recall.js.map +1 -0
  115. package/dist/extensions/vendor/openviking-pi/qcr-shim.js +94 -0
  116. package/dist/extensions/vendor/openviking-pi/qcr-shim.js.map +1 -0
  117. package/dist/extensions/vendor/openviking-pi/qcr-write.js +333 -0
  118. package/dist/extensions/vendor/openviking-pi/qcr-write.js.map +1 -0
  119. package/dist/extensions/vendor/openviking-pi/recall.js +108 -0
  120. package/dist/extensions/vendor/openviking-pi/recall.js.map +1 -0
  121. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs +529 -0
  122. package/dist/extensions/vendor/openviking-pi/shared/capture-utils.mjs.map +1 -0
  123. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs +205 -0
  124. package/dist/extensions/vendor/openviking-pi/shared/credentials.mjs.map +1 -0
  125. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs +442 -0
  126. package/dist/extensions/vendor/openviking-pi/shared/pending-queue.mjs.map +1 -0
  127. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs +286 -0
  128. package/dist/extensions/vendor/openviking-pi/shared/profile-inject.mjs.map +1 -0
  129. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +189 -0
  130. package/dist/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs.map +1 -0
  131. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs +580 -0
  132. package/dist/extensions/vendor/openviking-pi/shared/recall-core.mjs.map +1 -0
  133. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs +11 -0
  134. package/dist/extensions/vendor/openviking-pi/shared/retryable.mjs.map +1 -0
  135. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs +63 -0
  136. package/dist/extensions/vendor/openviking-pi/shared/session-model.mjs.map +1 -0
  137. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs +58 -0
  138. package/dist/extensions/vendor/openviking-pi/shared/uri-guard.mjs.map +1 -0
  139. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  140. package/dist/extensions/vendor/openviking-pi/shared/workspace-peer.mjs.map +1 -0
  141. package/dist/extensions/vendor/openviking-pi/sync.js +127 -0
  142. package/dist/extensions/vendor/openviking-pi/sync.js.map +1 -0
  143. package/dist/extensions/vendor/openviking-pi/takeover.js +25 -0
  144. package/dist/extensions/vendor/openviking-pi/takeover.js.map +1 -0
  145. package/dist/extensions/vendor/openviking-pi/tools.js +417 -0
  146. package/dist/extensions/vendor/openviking-pi/tools.js.map +1 -0
  147. package/dist/src/anomalies.js +483 -0
  148. package/dist/src/anomalies.js.map +1 -0
  149. package/dist/src/answerworker.js +180 -0
  150. package/dist/src/answerworker.js.map +1 -0
  151. package/dist/src/appstamp.js +68 -0
  152. package/dist/src/appstamp.js.map +1 -0
  153. package/dist/src/archive/admission.js +3 -0
  154. package/dist/src/archive/admission.js.map +1 -0
  155. package/dist/src/archive/archivedb.js +474 -0
  156. package/dist/src/archive/archivedb.js.map +1 -0
  157. package/dist/src/archive/archiver.js +1770 -0
  158. package/dist/src/archive/archiver.js.map +1 -0
  159. package/dist/src/archive/archivewrite.js +198 -0
  160. package/dist/src/archive/archivewrite.js.map +1 -0
  161. package/dist/src/archive/bundle.js +266 -0
  162. package/dist/src/archive/bundle.js.map +1 -0
  163. package/dist/src/archive/dbmove.js +638 -0
  164. package/dist/src/archive/dbmove.js.map +1 -0
  165. package/dist/src/archive/duplicatecounts.js +80 -0
  166. package/dist/src/archive/duplicatecounts.js.map +1 -0
  167. package/dist/src/archive/eligibility.js +113 -0
  168. package/dist/src/archive/eligibility.js.map +1 -0
  169. package/dist/src/archive/extract.js +288 -0
  170. package/dist/src/archive/extract.js.map +1 -0
  171. package/dist/src/archive/fsutil.js +330 -0
  172. package/dist/src/archive/fsutil.js.map +1 -0
  173. package/dist/src/archive/gzfile.js +277 -0
  174. package/dist/src/archive/gzfile.js.map +1 -0
  175. package/dist/src/archive/kinds.js +22 -0
  176. package/dist/src/archive/kinds.js.map +1 -0
  177. package/dist/src/archive/livecheckpoint.js +178 -0
  178. package/dist/src/archive/livecheckpoint.js.map +1 -0
  179. package/dist/src/archive/liveretention.js +145 -0
  180. package/dist/src/archive/liveretention.js.map +1 -0
  181. package/dist/src/archive/manifest.js +284 -0
  182. package/dist/src/archive/manifest.js.map +1 -0
  183. package/dist/src/archive/overseer.js +283 -0
  184. package/dist/src/archive/overseer.js.map +1 -0
  185. package/dist/src/archive/piglobal.js +129 -0
  186. package/dist/src/archive/piglobal.js.map +1 -0
  187. package/dist/src/archive/plan.js +398 -0
  188. package/dist/src/archive/plan.js.map +1 -0
  189. package/dist/src/archive/prarchive.js +831 -0
  190. package/dist/src/archive/prarchive.js.map +1 -0
  191. package/dist/src/archive/prfiles.js +303 -0
  192. package/dist/src/archive/prfiles.js.map +1 -0
  193. package/dist/src/archive/report.js +169 -0
  194. package/dist/src/archive/report.js.map +1 -0
  195. package/dist/src/archive/restore.js +276 -0
  196. package/dist/src/archive/restore.js.map +1 -0
  197. package/dist/src/archive/rows.js +106 -0
  198. package/dist/src/archive/rows.js.map +1 -0
  199. package/dist/src/archive/seal.js +480 -0
  200. package/dist/src/archive/seal.js.map +1 -0
  201. package/dist/src/archive/status.js +528 -0
  202. package/dist/src/archive/status.js.map +1 -0
  203. package/dist/src/archive/storepass.js +409 -0
  204. package/dist/src/archive/storepass.js.map +1 -0
  205. package/dist/src/backfill.js +217 -0
  206. package/dist/src/backfill.js.map +1 -0
  207. package/dist/src/bench/cost.js +87 -0
  208. package/dist/src/bench/exec.js +76 -0
  209. package/dist/src/bench/values.js +14 -0
  210. package/dist/src/botcontrol.js +127 -0
  211. package/dist/src/botcontrol.js.map +1 -0
  212. package/dist/src/botworker.js +805 -0
  213. package/dist/src/botworker.js.map +1 -0
  214. package/dist/src/capture.js +234 -0
  215. package/dist/src/capture.js.map +1 -0
  216. package/dist/src/cases.js +1491 -0
  217. package/dist/src/cases.js.map +1 -0
  218. package/dist/src/channelfs.js +27 -0
  219. package/dist/src/channelfs.js.map +1 -0
  220. package/dist/src/checklist.js +312 -0
  221. package/dist/src/checklist.js.map +1 -0
  222. package/dist/src/ciretry.js +91 -0
  223. package/dist/src/ciretry.js.map +1 -0
  224. package/dist/src/cli.js +1916 -0
  225. package/dist/src/cli.js.map +1 -0
  226. package/dist/src/cliops.js +333 -0
  227. package/dist/src/cliops.js.map +1 -0
  228. package/dist/src/clonedir.js +15 -0
  229. package/dist/src/clonedir.js.map +1 -0
  230. package/dist/src/commandeffects.js +43 -0
  231. package/dist/src/commandeffects.js.map +1 -0
  232. package/dist/src/commands.js +1312 -0
  233. package/dist/src/commands.js.map +1 -0
  234. package/dist/src/companioninbox.js +203 -0
  235. package/dist/src/companioninbox.js.map +1 -0
  236. package/dist/src/compare.js +673 -0
  237. package/dist/src/compare.js.map +1 -0
  238. package/dist/src/config.js +1027 -0
  239. package/dist/src/config.js.map +1 -0
  240. package/dist/src/configcheck.js +111 -0
  241. package/dist/src/configcheck.js.map +1 -0
  242. package/dist/src/coreext.js +43 -0
  243. package/dist/src/coreext.js.map +1 -0
  244. package/dist/src/daemon.js +929 -0
  245. package/dist/src/daemon.js.map +1 -0
  246. package/dist/src/debuground.js +731 -0
  247. package/dist/src/debuground.js.map +1 -0
  248. package/dist/src/debugroundpi.js +219 -0
  249. package/dist/src/debugroundpi.js.map +1 -0
  250. package/dist/src/diagnostics.js +14 -0
  251. package/dist/src/diagnostics.js.map +1 -0
  252. package/dist/src/digest.js +139 -0
  253. package/dist/src/digest.js.map +1 -0
  254. package/dist/src/dispatch.js +1726 -0
  255. package/dist/src/dispatch.js.map +1 -0
  256. package/dist/src/engine/answerguard.js +18 -0
  257. package/dist/src/engine/answerguard.js.map +1 -0
  258. package/dist/src/engine/botsdk.js +262 -0
  259. package/dist/src/engine/botsdk.js.map +1 -0
  260. package/dist/src/engine/caserunner-sdk.js +332 -0
  261. package/dist/src/engine/caserunner-sdk.js.map +1 -0
  262. package/dist/src/engine/debugpi.js +194 -0
  263. package/dist/src/engine/debugpi.js.map +1 -0
  264. package/dist/src/eod.js +473 -0
  265. package/dist/src/eod.js.map +1 -0
  266. package/dist/src/eodpinwatch.js +391 -0
  267. package/dist/src/eodpinwatch.js.map +1 -0
  268. package/dist/src/escalation.js +1009 -0
  269. package/dist/src/escalation.js.map +1 -0
  270. package/dist/src/eventloop.js +779 -0
  271. package/dist/src/eventloop.js.map +1 -0
  272. package/dist/src/execboundary.js +430 -0
  273. package/dist/src/execboundary.js.map +1 -0
  274. package/dist/src/feedback.js +915 -0
  275. package/dist/src/feedback.js.map +1 -0
  276. package/dist/src/findingscheck.js +200 -0
  277. package/dist/src/findingscheck.js.map +1 -0
  278. package/dist/src/fsdenied.js +26 -0
  279. package/dist/src/fsdenied.js.map +1 -0
  280. package/dist/src/ghread.js +181 -0
  281. package/dist/src/ghread.js.map +1 -0
  282. package/dist/src/github.js +1063 -0
  283. package/dist/src/github.js.map +1 -0
  284. package/dist/src/homes.js +103 -0
  285. package/dist/src/homes.js.map +1 -0
  286. package/dist/src/hostroute.js +24 -0
  287. package/dist/src/hostroute.js.map +1 -0
  288. package/dist/src/improvements.js +625 -0
  289. package/dist/src/improvements.js.map +1 -0
  290. package/dist/src/install.js +946 -0
  291. package/dist/src/install.js.map +1 -0
  292. package/dist/src/installkind.js +40 -0
  293. package/dist/src/installkind.js.map +1 -0
  294. package/dist/src/ipc/capability.js +286 -0
  295. package/dist/src/ipc/capability.js.map +1 -0
  296. package/dist/src/ipc/client.js +226 -0
  297. package/dist/src/ipc/client.js.map +1 -0
  298. package/dist/src/ipc/control.js +70 -0
  299. package/dist/src/ipc/control.js.map +1 -0
  300. package/dist/src/ipc/ghreadshim.js +77 -0
  301. package/dist/src/ipc/ghreadshim.js.map +1 -0
  302. package/dist/src/ipc/launcher.js +65 -0
  303. package/dist/src/ipc/launcher.js.map +1 -0
  304. package/dist/src/ipc/permits.js +293 -0
  305. package/dist/src/ipc/permits.js.map +1 -0
  306. package/dist/src/ipc/postshim.js +137 -0
  307. package/dist/src/ipc/postshim.js.map +1 -0
  308. package/dist/src/ipc/protocol.js +239 -0
  309. package/dist/src/ipc/protocol.js.map +1 -0
  310. package/dist/src/ipc/server.js +312 -0
  311. package/dist/src/ipc/server.js.map +1 -0
  312. package/dist/src/ipc/workerspec.js +148 -0
  313. package/dist/src/ipc/workerspec.js.map +1 -0
  314. package/dist/src/learner/learner.js +1272 -0
  315. package/dist/src/learner/learner.js.map +1 -0
  316. package/dist/src/learner/miner.js +948 -0
  317. package/dist/src/learner/miner.js.map +1 -0
  318. package/dist/src/learner/packet.js +216 -0
  319. package/dist/src/learner/packet.js.map +1 -0
  320. package/dist/src/learner/receipt.js +135 -0
  321. package/dist/src/learner/receipt.js.map +1 -0
  322. package/dist/src/learner/status.js +38 -0
  323. package/dist/src/learner/status.js.map +1 -0
  324. package/dist/src/ledgercheck.js +120 -0
  325. package/dist/src/ledgercheck.js.map +1 -0
  326. package/dist/src/lessonledger.js +451 -0
  327. package/dist/src/lessonledger.js.map +1 -0
  328. package/dist/src/lessonselect.js +639 -0
  329. package/dist/src/lessonselect.js.map +1 -0
  330. package/dist/src/lessonshadow.js +540 -0
  331. package/dist/src/lessonshadow.js.map +1 -0
  332. package/dist/src/levers.js +302 -0
  333. package/dist/src/levers.js.map +1 -0
  334. package/dist/src/live/projection.js +450 -0
  335. package/dist/src/live/projection.js.map +1 -0
  336. package/dist/src/live/publish.js +83 -0
  337. package/dist/src/live/publish.js.map +1 -0
  338. package/dist/src/live/read.js +60 -0
  339. package/dist/src/live/read.js.map +1 -0
  340. package/dist/src/livecli.js +288 -0
  341. package/dist/src/livecli.js.map +1 -0
  342. package/dist/src/loginhint.js +42 -0
  343. package/dist/src/loginhint.js.map +1 -0
  344. package/dist/src/loginrefresh/atomic.js +66 -0
  345. package/dist/src/loginrefresh/atomic.js.map +1 -0
  346. package/dist/src/loginrefresh/lock.js +93 -0
  347. package/dist/src/loginrefresh/lock.js.map +1 -0
  348. package/dist/src/loginrefresh/main.js +58 -0
  349. package/dist/src/loginrefresh/main.js.map +1 -0
  350. package/dist/src/loginrefresh/pirefresh.js +49 -0
  351. package/dist/src/loginrefresh/pirefresh.js.map +1 -0
  352. package/dist/src/loginrefresh/refresher.js +286 -0
  353. package/dist/src/loginrefresh/refresher.js.map +1 -0
  354. package/dist/src/loginrefresh/supervisor.js +253 -0
  355. package/dist/src/loginrefresh/supervisor.js.map +1 -0
  356. package/dist/src/loginrefresh/types.js +4 -0
  357. package/dist/src/loginrefresh/types.js.map +1 -0
  358. package/dist/src/memory/context.js +251 -0
  359. package/dist/src/memory/context.js.map +1 -0
  360. package/dist/src/memory/datafence.js +5 -0
  361. package/dist/src/memory/datafence.js.map +1 -0
  362. package/dist/src/memory/delivery.js +131 -0
  363. package/dist/src/memory/delivery.js.map +1 -0
  364. package/dist/src/memory/eventtags.js +81 -0
  365. package/dist/src/memory/eventtags.js.map +1 -0
  366. package/dist/src/memory/health.js +713 -0
  367. package/dist/src/memory/health.js.map +1 -0
  368. package/dist/src/memory/import.js +504 -0
  369. package/dist/src/memory/import.js.map +1 -0
  370. package/dist/src/memory/layout.js +252 -0
  371. package/dist/src/memory/layout.js.map +1 -0
  372. package/dist/src/memory/legacy-file.js +100 -0
  373. package/dist/src/memory/legacy-file.js.map +1 -0
  374. package/dist/src/memory/lessons.js +370 -0
  375. package/dist/src/memory/lessons.js.map +1 -0
  376. package/dist/src/memory/ovsession.js +449 -0
  377. package/dist/src/memory/ovsession.js.map +1 -0
  378. package/dist/src/memory/relayout.js +259 -0
  379. package/dist/src/memory/relayout.js.map +1 -0
  380. package/dist/src/memory/roundactivity.js +180 -0
  381. package/dist/src/memory/roundactivity.js.map +1 -0
  382. package/dist/src/memory/selection.js +690 -0
  383. package/dist/src/memory/selection.js.map +1 -0
  384. package/dist/src/memory/shadowstatus.js +69 -0
  385. package/dist/src/memory/shadowstatus.js.map +1 -0
  386. package/dist/src/memory/store.js +83 -0
  387. package/dist/src/memory/store.js.map +1 -0
  388. package/dist/src/memory/textidentity.js +8 -0
  389. package/dist/src/memory/textidentity.js.map +1 -0
  390. package/dist/src/metrics.js +773 -0
  391. package/dist/src/metrics.js.map +1 -0
  392. package/dist/src/missingconfig.js +8 -0
  393. package/dist/src/missingconfig.js.map +1 -0
  394. package/dist/src/npmverbs.js +226 -0
  395. package/dist/src/npmverbs.js.map +1 -0
  396. package/dist/src/onboard/choices.js +191 -0
  397. package/dist/src/onboard/choices.js.map +1 -0
  398. package/dist/src/onboard/engine.js +344 -0
  399. package/dist/src/onboard/engine.js.map +1 -0
  400. package/dist/src/onboard/launch.js +83 -0
  401. package/dist/src/onboard/launch.js.map +1 -0
  402. package/dist/src/onboard/steps/appslug.js +211 -0
  403. package/dist/src/onboard/steps/appslug.js.map +1 -0
  404. package/dist/src/onboard/steps/bringup.js +408 -0
  405. package/dist/src/onboard/steps/bringup.js.map +1 -0
  406. package/dist/src/onboard/steps/compose.js +343 -0
  407. package/dist/src/onboard/steps/compose.js.map +1 -0
  408. package/dist/src/onboard/steps/configdelivery.js +50 -0
  409. package/dist/src/onboard/steps/configdelivery.js.map +1 -0
  410. package/dist/src/onboard/steps/configfill.js +1148 -0
  411. package/dist/src/onboard/steps/configfill.js.map +1 -0
  412. package/dist/src/onboard/steps/deploysh.js +80 -0
  413. package/dist/src/onboard/steps/deploysh.js.map +1 -0
  414. package/dist/src/onboard/steps/embeddings.js +472 -0
  415. package/dist/src/onboard/steps/embeddings.js.map +1 -0
  416. package/dist/src/onboard/steps/escalation.js +571 -0
  417. package/dist/src/onboard/steps/escalation.js.map +1 -0
  418. package/dist/src/onboard/steps/githubapp.js +1092 -0
  419. package/dist/src/onboard/steps/githubapp.js.map +1 -0
  420. package/dist/src/onboard/steps/golive.js +506 -0
  421. package/dist/src/onboard/steps/golive.js.map +1 -0
  422. package/dist/src/onboard/steps/index.js +67 -0
  423. package/dist/src/onboard/steps/index.js.map +1 -0
  424. package/dist/src/onboard/steps/ingress.js +762 -0
  425. package/dist/src/onboard/steps/ingress.js.map +1 -0
  426. package/dist/src/onboard/steps/inventory.js +420 -0
  427. package/dist/src/onboard/steps/inventory.js.map +1 -0
  428. package/dist/src/onboard/steps/llmauth.js +893 -0
  429. package/dist/src/onboard/steps/llmauth.js.map +1 -0
  430. package/dist/src/onboard/steps/memory.js +1060 -0
  431. package/dist/src/onboard/steps/memory.js.map +1 -0
  432. package/dist/src/onboard/steps/memorykeys.js +43 -0
  433. package/dist/src/onboard/steps/memorykeys.js.map +1 -0
  434. package/dist/src/onboard/steps/preflight.js +172 -0
  435. package/dist/src/onboard/steps/preflight.js.map +1 -0
  436. package/dist/src/onboard/steps/proof.js +502 -0
  437. package/dist/src/onboard/steps/proof.js.map +1 -0
  438. package/dist/src/onboard/steps/ssh.js +300 -0
  439. package/dist/src/onboard/steps/ssh.js.map +1 -0
  440. package/dist/src/onboard/steps/topology.js +291 -0
  441. package/dist/src/onboard/steps/topology.js.map +1 -0
  442. package/dist/src/onboard/steps/transport.js +511 -0
  443. package/dist/src/onboard/steps/transport.js.map +1 -0
  444. package/dist/src/onboard/steps/verifyup.js +362 -0
  445. package/dist/src/onboard/steps/verifyup.js.map +1 -0
  446. package/dist/src/onboard/steps/vmdeploy.js +368 -0
  447. package/dist/src/onboard/steps/vmdeploy.js.map +1 -0
  448. package/dist/src/onboard/toml.js +53 -0
  449. package/dist/src/onboard/toml.js.map +1 -0
  450. package/dist/src/opencli.js +508 -0
  451. package/dist/src/opencli.js.map +1 -0
  452. package/dist/src/openpr.js +457 -0
  453. package/dist/src/openpr.js.map +1 -0
  454. package/dist/src/openviking/client.js +821 -0
  455. package/dist/src/openviking/client.js.map +1 -0
  456. package/dist/src/openviking/context.js +218 -0
  457. package/dist/src/openviking/context.js.map +1 -0
  458. package/dist/src/openviking/embedder.js +457 -0
  459. package/dist/src/openviking/embedder.js.map +1 -0
  460. package/dist/src/openviking/gapsink.js +38 -0
  461. package/dist/src/openviking/gapsink.js.map +1 -0
  462. package/dist/src/openviking/health.js +69 -0
  463. package/dist/src/openviking/health.js.map +1 -0
  464. package/dist/src/openviking/index.js +24 -0
  465. package/dist/src/openviking/index.js.map +1 -0
  466. package/dist/src/openviking/lessonfind.js +54 -0
  467. package/dist/src/openviking/lessonfind.js.map +1 -0
  468. package/dist/src/openviking/probe.js +89 -0
  469. package/dist/src/openviking/probe.js.map +1 -0
  470. package/dist/src/openviking/proc.js +95 -0
  471. package/dist/src/openviking/proc.js.map +1 -0
  472. package/dist/src/openviking/provisionreport.js +144 -0
  473. package/dist/src/openviking/provisionreport.js.map +1 -0
  474. package/dist/src/openviking/reembed.js +317 -0
  475. package/dist/src/openviking/reembed.js.map +1 -0
  476. package/dist/src/openviking/relayout.js +153 -0
  477. package/dist/src/openviking/relayout.js.map +1 -0
  478. package/dist/src/openviking/sidecar-main.js +39 -0
  479. package/dist/src/openviking/sidecar-main.js.map +1 -0
  480. package/dist/src/openviking/sidecar.js +79 -0
  481. package/dist/src/openviking/sidecar.js.map +1 -0
  482. package/dist/src/openviking/store.js +1758 -0
  483. package/dist/src/openviking/store.js.map +1 -0
  484. package/dist/src/openviking/supervisor.js +422 -0
  485. package/dist/src/openviking/supervisor.js.map +1 -0
  486. package/dist/src/openviking/types.js +5 -0
  487. package/dist/src/openviking/types.js.map +1 -0
  488. package/dist/src/operator-recovery.js +172 -0
  489. package/dist/src/operator-recovery.js.map +1 -0
  490. package/dist/src/operatormessage.js +44 -0
  491. package/dist/src/operatormessage.js.map +1 -0
  492. package/dist/src/outcomes.js +1361 -0
  493. package/dist/src/outcomes.js.map +1 -0
  494. package/dist/src/piauthcopy.js +5 -0
  495. package/dist/src/piauthcopy.js.map +1 -0
  496. package/dist/src/picli.js +45 -0
  497. package/dist/src/picli.js.map +1 -0
  498. package/dist/src/picwd.js +25 -0
  499. package/dist/src/picwd.js.map +1 -0
  500. package/dist/src/pilogin.js +35 -0
  501. package/dist/src/pilogin.js.map +1 -0
  502. package/dist/src/pingpong.js +1028 -0
  503. package/dist/src/pingpong.js.map +1 -0
  504. package/dist/src/posting-journal.js +441 -0
  505. package/dist/src/posting-journal.js.map +1 -0
  506. package/dist/src/posting-outbox.js +662 -0
  507. package/dist/src/posting-outbox.js.map +1 -0
  508. package/dist/src/posting-receipt.js +203 -0
  509. package/dist/src/posting-receipt.js.map +1 -0
  510. package/dist/src/posting.js +348 -0
  511. package/dist/src/posting.js.map +1 -0
  512. package/dist/src/postops.js +637 -0
  513. package/dist/src/postops.js.map +1 -0
  514. package/dist/src/pr-activity.js +11 -0
  515. package/dist/src/pr-activity.js.map +1 -0
  516. package/dist/src/pr-author.js +5 -0
  517. package/dist/src/pr-author.js.map +1 -0
  518. package/dist/src/pr-conversation.js +355 -0
  519. package/dist/src/pr-conversation.js.map +1 -0
  520. package/dist/src/pr-session-lifecycle.js +542 -0
  521. package/dist/src/pr-session-lifecycle.js.map +1 -0
  522. package/dist/src/preflight.js +341 -0
  523. package/dist/src/preflight.js.map +1 -0
  524. package/dist/src/priorresolve.js +275 -0
  525. package/dist/src/priorresolve.js.map +1 -0
  526. package/dist/src/qcrbin.js +180 -0
  527. package/dist/src/qcrbin.js.map +1 -0
  528. package/dist/src/recheck.js +1398 -0
  529. package/dist/src/recheck.js.map +1 -0
  530. package/dist/src/reconcile.js +820 -0
  531. package/dist/src/reconcile.js.map +1 -0
  532. package/dist/src/recordedfindings.js +15 -0
  533. package/dist/src/recordedfindings.js.map +1 -0
  534. package/dist/src/regression.js +546 -0
  535. package/dist/src/regression.js.map +1 -0
  536. package/dist/src/replay.js +598 -0
  537. package/dist/src/replay.js.map +1 -0
  538. package/dist/src/requiredpasses.js +113 -0
  539. package/dist/src/requiredpasses.js.map +1 -0
  540. package/dist/src/resumecheck.js +168 -0
  541. package/dist/src/resumecheck.js.map +1 -0
  542. package/dist/src/reviewcli.js +671 -0
  543. package/dist/src/reviewcli.js.map +1 -0
  544. package/dist/src/reviewcontext.js +22 -0
  545. package/dist/src/reviewcontext.js.map +1 -0
  546. package/dist/src/reviewdetach.js +574 -0
  547. package/dist/src/reviewdetach.js.map +1 -0
  548. package/dist/src/reviewhistory.js +284 -0
  549. package/dist/src/reviewhistory.js.map +1 -0
  550. package/dist/src/reviewhome.js +26 -0
  551. package/dist/src/reviewhome.js.map +1 -0
  552. package/dist/src/reviewmemory.js +110 -0
  553. package/dist/src/reviewmemory.js.map +1 -0
  554. package/dist/src/reviewrendercli.js +104 -0
  555. package/dist/src/reviewrendercli.js.map +1 -0
  556. package/dist/src/round-work.js +20 -0
  557. package/dist/src/round-work.js.map +1 -0
  558. package/dist/src/runhost.js +72 -0
  559. package/dist/src/runhost.js.map +1 -0
  560. package/dist/src/scanauth.js +25 -0
  561. package/dist/src/scanauth.js.map +1 -0
  562. package/dist/src/scanbox.js +846 -0
  563. package/dist/src/scanbox.js.map +1 -0
  564. package/dist/src/scancli.js +1074 -0
  565. package/dist/src/scancli.js.map +1 -0
  566. package/dist/src/scandriverlog.js +30 -0
  567. package/dist/src/scandriverlog.js.map +1 -0
  568. package/dist/src/session-bridge.js +75 -0
  569. package/dist/src/session-bridge.js.map +1 -0
  570. package/dist/src/session-command-payload.js +29 -0
  571. package/dist/src/session-command-payload.js.map +1 -0
  572. package/dist/src/session-command-supervisor.js +939 -0
  573. package/dist/src/session-command-supervisor.js.map +1 -0
  574. package/dist/src/sessionjsonl.js +85 -0
  575. package/dist/src/sessionjsonl.js.map +1 -0
  576. package/dist/src/sessions.js +541 -0
  577. package/dist/src/sessions.js.map +1 -0
  578. package/dist/src/setup/adapters.js +330 -0
  579. package/dist/src/setup/adapters.js.map +1 -0
  580. package/dist/src/setup/baselines.js +64 -0
  581. package/dist/src/setup/baselines.js.map +1 -0
  582. package/dist/src/setup/caserunner.js +554 -0
  583. package/dist/src/setup/caserunner.js.map +1 -0
  584. package/dist/src/setup/configcommit.js +358 -0
  585. package/dist/src/setup/configcommit.js.map +1 -0
  586. package/dist/src/setup/engine.js +672 -0
  587. package/dist/src/setup/engine.js.map +1 -0
  588. package/dist/src/setup/facts.js +593 -0
  589. package/dist/src/setup/facts.js.map +1 -0
  590. package/dist/src/setup/findings.js +948 -0
  591. package/dist/src/setup/findings.js.map +1 -0
  592. package/dist/src/setup/history.js +338 -0
  593. package/dist/src/setup/history.js.map +1 -0
  594. package/dist/src/setup/interview.js +185 -0
  595. package/dist/src/setup/interview.js.map +1 -0
  596. package/dist/src/setup/ledger.js +207 -0
  597. package/dist/src/setup/ledger.js.map +1 -0
  598. package/dist/src/setup/pins.js +43 -0
  599. package/dist/src/setup/pins.js.map +1 -0
  600. package/dist/src/setup/portrait.js +432 -0
  601. package/dist/src/setup/portrait.js.map +1 -0
  602. package/dist/src/setup/presentation.js +9 -0
  603. package/dist/src/setup/presentation.js.map +1 -0
  604. package/dist/src/setup/profile.js +417 -0
  605. package/dist/src/setup/profile.js.map +1 -0
  606. package/dist/src/setup/replay.js +240 -0
  607. package/dist/src/setup/replay.js.map +1 -0
  608. package/dist/src/setup/replaybuild.js +311 -0
  609. package/dist/src/setup/replaybuild.js.map +1 -0
  610. package/dist/src/setup/replayrun.js +806 -0
  611. package/dist/src/setup/replayrun.js.map +1 -0
  612. package/dist/src/setup/replaysource.js +169 -0
  613. package/dist/src/setup/replaysource.js.map +1 -0
  614. package/dist/src/setup/retune.js +333 -0
  615. package/dist/src/setup/retune.js.map +1 -0
  616. package/dist/src/setup/retunelog.js +51 -0
  617. package/dist/src/setup/retunelog.js.map +1 -0
  618. package/dist/src/setup/scan.js +725 -0
  619. package/dist/src/setup/scan.js.map +1 -0
  620. package/dist/src/setup/scanbuild.js +133 -0
  621. package/dist/src/setup/scanbuild.js.map +1 -0
  622. package/dist/src/setup/scanfacts.js +96 -0
  623. package/dist/src/setup/scanfacts.js.map +1 -0
  624. package/dist/src/setup/scanlease.js +251 -0
  625. package/dist/src/setup/scanlease.js.map +1 -0
  626. package/dist/src/setup/scanreport.js +289 -0
  627. package/dist/src/setup/scanreport.js.map +1 -0
  628. package/dist/src/setup/scanrun.js +1733 -0
  629. package/dist/src/setup/scanrun.js.map +1 -0
  630. package/dist/src/setup/scantree.js +257 -0
  631. package/dist/src/setup/scantree.js.map +1 -0
  632. package/dist/src/setup/stage2.js +617 -0
  633. package/dist/src/setup/stage2.js.map +1 -0
  634. package/dist/src/setup/stage2request.js +259 -0
  635. package/dist/src/setup/stage2request.js.map +1 -0
  636. package/dist/src/setup/survey.js +307 -0
  637. package/dist/src/setup/survey.js.map +1 -0
  638. package/dist/src/setup/surveyrun.js +549 -0
  639. package/dist/src/setup/surveyrun.js.map +1 -0
  640. package/dist/src/setup/textsniff.js +89 -0
  641. package/dist/src/setup/textsniff.js.map +1 -0
  642. package/dist/src/setup/trackersink.js +395 -0
  643. package/dist/src/setup/trackersink.js.map +1 -0
  644. package/dist/src/setup/triage.js +636 -0
  645. package/dist/src/setup/triage.js.map +1 -0
  646. package/dist/src/setup/tuning.js +585 -0
  647. package/dist/src/setup/tuning.js.map +1 -0
  648. package/dist/src/setup/unitcut.js +437 -0
  649. package/dist/src/setup/unitcut.js.map +1 -0
  650. package/dist/src/singleflight.js +72 -0
  651. package/dist/src/singleflight.js.map +1 -0
  652. package/dist/src/slack/announce.js +725 -0
  653. package/dist/src/slack/announce.js.map +1 -0
  654. package/dist/src/slack/api.js +227 -0
  655. package/dist/src/slack/api.js.map +1 -0
  656. package/dist/src/slack/messages.js +158 -0
  657. package/dist/src/slack/messages.js.map +1 -0
  658. package/dist/src/slack/origin.js +550 -0
  659. package/dist/src/slack/origin.js.map +1 -0
  660. package/dist/src/slack/policy.js +225 -0
  661. package/dist/src/slack/policy.js.map +1 -0
  662. package/dist/src/slack/reply.js +153 -0
  663. package/dist/src/slack/reply.js.map +1 -0
  664. package/dist/src/slack/router.js +189 -0
  665. package/dist/src/slack/router.js.map +1 -0
  666. package/dist/src/slack/socket.js +323 -0
  667. package/dist/src/slack/socket.js.map +1 -0
  668. package/dist/src/slack/types.js +11 -0
  669. package/dist/src/slack/types.js.map +1 -0
  670. package/dist/src/sqlitehint.js +30 -0
  671. package/dist/src/sqlitehint.js.map +1 -0
  672. package/dist/src/ssh-observation.js +25 -0
  673. package/dist/src/ssh-observation.js.map +1 -0
  674. package/dist/src/state.js +5869 -0
  675. package/dist/src/state.js.map +1 -0
  676. package/dist/src/statemachine.js +220 -0
  677. package/dist/src/statemachine.js.map +1 -0
  678. package/dist/src/stubs.js +52 -0
  679. package/dist/src/stubs.js.map +1 -0
  680. package/dist/src/takeover.js +506 -0
  681. package/dist/src/takeover.js.map +1 -0
  682. package/dist/src/takeoverpi.js +249 -0
  683. package/dist/src/takeoverpi.js.map +1 -0
  684. package/dist/src/terminal-failure.js +26 -0
  685. package/dist/src/terminal-failure.js.map +1 -0
  686. package/dist/src/thread-resolution-refusal.js +4 -0
  687. package/dist/src/thread-resolution-refusal.js.map +1 -0
  688. package/dist/src/tmux.js +126 -0
  689. package/dist/src/tmux.js.map +1 -0
  690. package/dist/src/trackerid.js +43 -0
  691. package/dist/src/trackerid.js.map +1 -0
  692. package/dist/src/transcriptindex.js +512 -0
  693. package/dist/src/transcriptindex.js.map +1 -0
  694. package/dist/src/tui/actions.js +404 -0
  695. package/dist/src/tui/actions.js.map +1 -0
  696. package/dist/src/tui/alerts.js +523 -0
  697. package/dist/src/tui/alerts.js.map +1 -0
  698. package/dist/src/tui/app.js +1835 -0
  699. package/dist/src/tui/app.js.map +1 -0
  700. package/dist/src/tui/archiveops.js +164 -0
  701. package/dist/src/tui/archiveops.js.map +1 -0
  702. package/dist/src/tui/autofile.js +191 -0
  703. package/dist/src/tui/autofile.js.map +1 -0
  704. package/dist/src/tui/board.js +1143 -0
  705. package/dist/src/tui/board.js.map +1 -0
  706. package/dist/src/tui/candidates.js +699 -0
  707. package/dist/src/tui/candidates.js.map +1 -0
  708. package/dist/src/tui/cellwidth.js +151 -0
  709. package/dist/src/tui/cellwidth.js.map +1 -0
  710. package/dist/src/tui/changelog-store.js +404 -0
  711. package/dist/src/tui/changelog-store.js.map +1 -0
  712. package/dist/src/tui/chord.js +26 -0
  713. package/dist/src/tui/chord.js.map +1 -0
  714. package/dist/src/tui/clipboard.js +81 -0
  715. package/dist/src/tui/clipboard.js.map +1 -0
  716. package/dist/src/tui/cmdbar.js +253 -0
  717. package/dist/src/tui/cmdbar.js.map +1 -0
  718. package/dist/src/tui/companion.js +1275 -0
  719. package/dist/src/tui/companion.js.map +1 -0
  720. package/dist/src/tui/companionplan.js +200 -0
  721. package/dist/src/tui/companionplan.js.map +1 -0
  722. package/dist/src/tui/companiontab.js +61 -0
  723. package/dist/src/tui/companiontab.js.map +1 -0
  724. package/dist/src/tui/confighome.js +105 -0
  725. package/dist/src/tui/confighome.js.map +1 -0
  726. package/dist/src/tui/connect.js +44 -0
  727. package/dist/src/tui/connect.js.map +1 -0
  728. package/dist/src/tui/deploy-ceremony.js +75 -0
  729. package/dist/src/tui/deploy-ceremony.js.map +1 -0
  730. package/dist/src/tui/deploy-drain.js +93 -0
  731. package/dist/src/tui/deploy-drain.js.map +1 -0
  732. package/dist/src/tui/deploy-process.js +234 -0
  733. package/dist/src/tui/deploy-process.js.map +1 -0
  734. package/dist/src/tui/deploytab.js +1263 -0
  735. package/dist/src/tui/deploytab.js.map +1 -0
  736. package/dist/src/tui/design.js +111 -0
  737. package/dist/src/tui/design.js.map +1 -0
  738. package/dist/src/tui/digesttab.js +148 -0
  739. package/dist/src/tui/digesttab.js.map +1 -0
  740. package/dist/src/tui/emptystate.js +32 -0
  741. package/dist/src/tui/emptystate.js.map +1 -0
  742. package/dist/src/tui/evidence.js +790 -0
  743. package/dist/src/tui/evidence.js.map +1 -0
  744. package/dist/src/tui/feed.js +415 -0
  745. package/dist/src/tui/feed.js.map +1 -0
  746. package/dist/src/tui/feedbacktab.js +907 -0
  747. package/dist/src/tui/feedbacktab.js.map +1 -0
  748. package/dist/src/tui/filters.js +72 -0
  749. package/dist/src/tui/filters.js.map +1 -0
  750. package/dist/src/tui/ghread.js +272 -0
  751. package/dist/src/tui/ghread.js.map +1 -0
  752. package/dist/src/tui/historypull.js +61 -0
  753. package/dist/src/tui/historypull.js.map +1 -0
  754. package/dist/src/tui/inboxpull.js +197 -0
  755. package/dist/src/tui/inboxpull.js.map +1 -0
  756. package/dist/src/tui/index.js +1425 -0
  757. package/dist/src/tui/index.js.map +1 -0
  758. package/dist/src/tui/issuesink.js +206 -0
  759. package/dist/src/tui/issuesink.js.map +1 -0
  760. package/dist/src/tui/jsonfile.js +32 -0
  761. package/dist/src/tui/jsonfile.js.map +1 -0
  762. package/dist/src/tui/keys.js +97 -0
  763. package/dist/src/tui/keys.js.map +1 -0
  764. package/dist/src/tui/layout.js +70 -0
  765. package/dist/src/tui/layout.js.map +1 -0
  766. package/dist/src/tui/learning.js +469 -0
  767. package/dist/src/tui/learning.js.map +1 -0
  768. package/dist/src/tui/lessonswitch.js +103 -0
  769. package/dist/src/tui/lessonswitch.js.map +1 -0
  770. package/dist/src/tui/livecontrol.js +167 -0
  771. package/dist/src/tui/livecontrol.js.map +1 -0
  772. package/dist/src/tui/memforward.js +310 -0
  773. package/dist/src/tui/memforward.js.map +1 -0
  774. package/dist/src/tui/memincident.js +287 -0
  775. package/dist/src/tui/memincident.js.map +1 -0
  776. package/dist/src/tui/memory.js +485 -0
  777. package/dist/src/tui/memory.js.map +1 -0
  778. package/dist/src/tui/memtab.js +513 -0
  779. package/dist/src/tui/memtab.js.map +1 -0
  780. package/dist/src/tui/metricstab.js +979 -0
  781. package/dist/src/tui/metricstab.js.map +1 -0
  782. package/dist/src/tui/model.js +104 -0
  783. package/dist/src/tui/model.js.map +1 -0
  784. package/dist/src/tui/mouse.js +83 -0
  785. package/dist/src/tui/mouse.js.map +1 -0
  786. package/dist/src/tui/msg.js +196 -0
  787. package/dist/src/tui/msg.js.map +1 -0
  788. package/dist/src/tui/nativecompanion.js +321 -0
  789. package/dist/src/tui/nativecompanion.js.map +1 -0
  790. package/dist/src/tui/openurl.js +17 -0
  791. package/dist/src/tui/openurl.js.map +1 -0
  792. package/dist/src/tui/paint.js +501 -0
  793. package/dist/src/tui/paint.js.map +1 -0
  794. package/dist/src/tui/panes.js +74 -0
  795. package/dist/src/tui/panes.js.map +1 -0
  796. package/dist/src/tui/pipane.js +166 -0
  797. package/dist/src/tui/pipane.js.map +1 -0
  798. package/dist/src/tui/poll-hooks.js +11 -0
  799. package/dist/src/tui/poll-hooks.js.map +1 -0
  800. package/dist/src/tui/poll.js +113 -0
  801. package/dist/src/tui/poll.js.map +1 -0
  802. package/dist/src/tui/proposals.js +715 -0
  803. package/dist/src/tui/proposals.js.map +1 -0
  804. package/dist/src/tui/prpause.js +132 -0
  805. package/dist/src/tui/prpause.js.map +1 -0
  806. package/dist/src/tui/reload.js +351 -0
  807. package/dist/src/tui/reload.js.map +1 -0
  808. package/dist/src/tui/remote.js +312 -0
  809. package/dist/src/tui/remote.js.map +1 -0
  810. package/dist/src/tui/rollover.js +767 -0
  811. package/dist/src/tui/rollover.js.map +1 -0
  812. package/dist/src/tui/scantab.js +1053 -0
  813. package/dist/src/tui/scantab.js.map +1 -0
  814. package/dist/src/tui/setupentry.js +81 -0
  815. package/dist/src/tui/setupentry.js.map +1 -0
  816. package/dist/src/tui/sidebar.js +602 -0
  817. package/dist/src/tui/sidebar.js.map +1 -0
  818. package/dist/src/tui/sshtriage.js +393 -0
  819. package/dist/src/tui/sshtriage.js.map +1 -0
  820. package/dist/src/tui/startup.js +172 -0
  821. package/dist/src/tui/startup.js.map +1 -0
  822. package/dist/src/tui/tabs.js +41 -0
  823. package/dist/src/tui/tabs.js.map +1 -0
  824. package/dist/src/tui/termmirror.js +217 -0
  825. package/dist/src/tui/termmirror.js.map +1 -0
  826. package/dist/src/tui/theme.js +95 -0
  827. package/dist/src/tui/theme.js.map +1 -0
  828. package/dist/src/tui/ticketstab.js +224 -0
  829. package/dist/src/tui/ticketstab.js.map +1 -0
  830. package/dist/src/tui/tmuxsocket.js +101 -0
  831. package/dist/src/tui/tmuxsocket.js.map +1 -0
  832. package/dist/src/tui/trackertickets.js +77 -0
  833. package/dist/src/tui/trackertickets.js.map +1 -0
  834. package/dist/src/tui/unwedge.js +245 -0
  835. package/dist/src/tui/unwedge.js.map +1 -0
  836. package/dist/src/tui/viewer.js +479 -0
  837. package/dist/src/tui/viewer.js.map +1 -0
  838. package/dist/src/tui/viewerinput.js +125 -0
  839. package/dist/src/tui/viewerinput.js.map +1 -0
  840. package/dist/src/updatenotice.js +143 -0
  841. package/dist/src/updatenotice.js.map +1 -0
  842. package/dist/src/usage.js +1007 -0
  843. package/dist/src/usage.js.map +1 -0
  844. package/dist/src/verdicts.js +3848 -0
  845. package/dist/src/verdicts.js.map +1 -0
  846. package/dist/src/version.js +58 -0
  847. package/dist/src/version.js.map +1 -0
  848. package/dist/src/wakes.js +411 -0
  849. package/dist/src/wakes.js.map +1 -0
  850. package/dist/src/webhook.js +725 -0
  851. package/dist/src/webhook.js.map +1 -0
  852. package/dist/src/webhookheal.js +238 -0
  853. package/dist/src/webhookheal.js.map +1 -0
  854. package/dist/src/wire.js +1801 -0
  855. package/dist/src/wire.js.map +1 -0
  856. package/dist/src/worker-session-host.js +531 -0
  857. package/dist/src/worker-session-host.js.map +1 -0
  858. package/dist/src/workerbreaker.js +112 -0
  859. package/dist/src/workerbreaker.js.map +1 -0
  860. package/dist/src/workercontrol.js +49 -0
  861. package/dist/src/workercontrol.js.map +1 -0
  862. package/dist/src/workerlease.js +351 -0
  863. package/dist/src/workerlease.js.map +1 -0
  864. package/dist/src/workerliveness.js +84 -0
  865. package/dist/src/workerliveness.js.map +1 -0
  866. package/dist/src/workerlog.js +65 -0
  867. package/dist/src/workerlog.js.map +1 -0
  868. package/dist/src/workerruntime.js +10 -0
  869. package/dist/src/workerruntime.js.map +1 -0
  870. package/dist/src/workersupervisor.js +1206 -0
  871. package/dist/src/workersupervisor.js.map +1 -0
  872. package/dist/src/workerusage.js +23 -0
  873. package/dist/src/workerusage.js.map +1 -0
  874. package/dist/src/workerworld.js +332 -0
  875. package/dist/src/workerworld.js.map +1 -0
  876. package/dist/src/worktrees.js +984 -0
  877. package/dist/src/worktrees.js.map +1 -0
  878. package/docker/Dockerfile +284 -0
  879. package/docker/Dockerfile.dockerignore +35 -0
  880. package/docker/README.md +221 -0
  881. package/docker/companion/Dockerfile +139 -0
  882. package/docker/companion/agents/evidence.md +34 -0
  883. package/docker/companion/agents/explore.md +26 -0
  884. package/docker/companion/agents/pass-survey.md +49 -0
  885. package/docker/companion/agents/study.md +26 -0
  886. package/docker/companion/entrypoint.sh +343 -0
  887. package/docker/companion/memory-health.mjs +269 -0
  888. package/docker/entrypoint.sh +782 -0
  889. package/docker/memory/Dockerfile +191 -0
  890. package/docker/memory/Dockerfile.dockerignore +20 -0
  891. package/docker/memory/README.md +60 -0
  892. package/docker/memory/entrypoint.sh +163 -0
  893. package/docker/setid/qcr-setid.c +109 -0
  894. package/docker/tunnel/Dockerfile.cloudflared +51 -0
  895. package/docker/tunnel/Dockerfile.ngrok +40 -0
  896. package/docker/tunnel/sidecar.mjs +411 -0
  897. package/docker/vm/tmux.conf +26 -0
  898. package/docker-compose.yml +348 -0
  899. package/extensions/cli/bash-guard-ambient.ts +71 -0
  900. package/extensions/cli/bash-guard.ts +12 -0
  901. package/extensions/cli/companion-guard.ts +8 -0
  902. package/extensions/cli/debug-round.ts +9 -0
  903. package/extensions/cli/inject-bridge.ts +8 -0
  904. package/extensions/cli/ledger-pin.ts +13 -0
  905. package/extensions/cli/lens.ts +22 -0
  906. package/extensions/cli/muted-theme.ts +9 -0
  907. package/extensions/cli/onboarding.ts +8 -0
  908. package/extensions/cli/setup.ts +8 -0
  909. package/extensions/cli/tui-view.ts +8 -0
  910. package/extensions/companion-guard.ts +411 -0
  911. package/extensions/debug-round.ts +281 -0
  912. package/extensions/inject-bridge.ts +630 -0
  913. package/extensions/inline-bash.ts +102 -0
  914. package/extensions/muted-theme.json +68 -0
  915. package/extensions/muted-theme.ts +23 -0
  916. package/extensions/onboarding.ts +233 -0
  917. package/extensions/setup-replay.ts +336 -0
  918. package/extensions/setup-scan.ts +1236 -0
  919. package/extensions/setup-triage.ts +190 -0
  920. package/extensions/setup.ts +1428 -0
  921. package/extensions/tui-view.ts +489 -0
  922. package/extensions/vendor/openviking-pi/LICENSE +201 -0
  923. package/extensions/vendor/openviking-pi/NOTICE +68 -0
  924. package/extensions/vendor/openviking-pi/README.md +550 -0
  925. package/extensions/vendor/openviking-pi/client.ts +588 -0
  926. package/extensions/vendor/openviking-pi/config.json +28 -0
  927. package/extensions/vendor/openviking-pi/config.ts +271 -0
  928. package/extensions/vendor/openviking-pi/index.ts +523 -0
  929. package/extensions/vendor/openviking-pi/lib/capture-adapter.d.mts +10 -0
  930. package/extensions/vendor/openviking-pi/lib/capture-adapter.mjs +88 -0
  931. package/extensions/vendor/openviking-pi/lib/takeover-core.d.mts +80 -0
  932. package/extensions/vendor/openviking-pi/lib/takeover-core.mjs +406 -0
  933. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.d.mts +1 -0
  934. package/extensions/vendor/openviking-pi/lib/uri-guard-adapter.mjs +42 -0
  935. package/extensions/vendor/openviking-pi/patches/0000-vendoring-and-build-conformance.patch +726 -0
  936. package/extensions/vendor/openviking-pi/patches/0001-remove-session-before-compact-handler.patch +101 -0
  937. package/extensions/vendor/openviking-pi/patches/0002-no-ambient-work-in-subagent-leaves.patch +202 -0
  938. package/extensions/vendor/openviking-pi/patches/0003-never-auto-create-openviking-sessions.patch +120 -0
  939. package/extensions/vendor/openviking-pi/patches/0004-viking-write-durable-batch-write.patch +521 -0
  940. package/extensions/vendor/openviking-pi/patches/0005-second-memory-namespace.patch +786 -0
  941. package/extensions/vendor/openviking-pi/patches/0006-writes-that-stick-and-honest-errors.patch +996 -0
  942. package/extensions/vendor/openviking-pi/patches/0007-bounded-recall-no-commit.patch +794 -0
  943. package/extensions/vendor/openviking-pi/patches/0008-pr-derived-recall.patch +379 -0
  944. package/extensions/vendor/openviking-pi/patches/0009-pr-session-tools-in-round-areas.patch +375 -0
  945. package/extensions/vendor/openviking-pi/patches/0010-typed-lessons.patch +448 -0
  946. package/extensions/vendor/openviking-pi/patches/0011-review-session-memory-boundary.patch +382 -0
  947. package/extensions/vendor/openviking-pi/patches/0012-typecheck-against-the-real-pi.patch +129 -0
  948. package/extensions/vendor/openviking-pi/patches/0013-createopenviking-factory.patch +1168 -0
  949. package/extensions/vendor/openviking-pi/qcr-hint.ts +313 -0
  950. package/extensions/vendor/openviking-pi/qcr-honest.ts +183 -0
  951. package/extensions/vendor/openviking-pi/qcr-hooks.ts +87 -0
  952. package/extensions/vendor/openviking-pi/qcr-leaf.ts +78 -0
  953. package/extensions/vendor/openviking-pi/qcr-lesson.ts +231 -0
  954. package/extensions/vendor/openviking-pi/qcr-namespaces.ts +198 -0
  955. package/extensions/vendor/openviking-pi/qcr-recall.ts +288 -0
  956. package/extensions/vendor/openviking-pi/qcr-shim.ts +142 -0
  957. package/extensions/vendor/openviking-pi/qcr-write.ts +427 -0
  958. package/extensions/vendor/openviking-pi/recall.ts +149 -0
  959. package/extensions/vendor/openviking-pi/shared/capture-utils.d.mts +9 -0
  960. package/extensions/vendor/openviking-pi/shared/capture-utils.mjs +515 -0
  961. package/extensions/vendor/openviking-pi/shared/credentials.d.mts +14 -0
  962. package/extensions/vendor/openviking-pi/shared/credentials.mjs +228 -0
  963. package/extensions/vendor/openviking-pi/shared/pending-queue.d.mts +19 -0
  964. package/extensions/vendor/openviking-pi/shared/pending-queue.mjs +458 -0
  965. package/extensions/vendor/openviking-pi/shared/profile-inject.d.mts +17 -0
  966. package/extensions/vendor/openviking-pi/shared/profile-inject.mjs +294 -0
  967. package/extensions/vendor/openviking-pi/shared/recall-compress-core.mjs +195 -0
  968. package/extensions/vendor/openviking-pi/shared/recall-core.d.mts +13 -0
  969. package/extensions/vendor/openviking-pi/shared/recall-core.mjs +609 -0
  970. package/extensions/vendor/openviking-pi/shared/retryable.mjs +9 -0
  971. package/extensions/vendor/openviking-pi/shared/session-model.d.mts +3 -0
  972. package/extensions/vendor/openviking-pi/shared/session-model.mjs +57 -0
  973. package/extensions/vendor/openviking-pi/shared/uri-guard.mjs +56 -0
  974. package/extensions/vendor/openviking-pi/shared/workspace-peer.d.mts +5 -0
  975. package/extensions/vendor/openviking-pi/shared/workspace-peer.mjs +16 -0
  976. package/extensions/vendor/openviking-pi/sync.ts +163 -0
  977. package/extensions/vendor/openviking-pi/takeover.ts +36 -0
  978. package/extensions/vendor/openviking-pi/tools.ts +479 -0
  979. package/extensions/vendor/openviking-pi/upstream.json +48 -0
  980. package/package.json +138 -4
  981. package/profiles/default/README.md +21 -0
  982. package/profiles/default/addenda/.gitkeep +0 -0
  983. package/profiles/default/profile.toml +17 -0
  984. package/profiles/example-django/README.md +21 -0
  985. package/profiles/example-django/addenda/10-migration-discipline.md +13 -0
  986. package/profiles/example-django/addenda/20-new-column-nullability.md +12 -0
  987. package/profiles/example-django/addenda/30-test-doctrine.md +12 -0
  988. package/profiles/example-django/addenda/40-orm-usage.md +19 -0
  989. package/profiles/example-django/addenda/50-declared-shape.md +10 -0
  990. package/profiles/example-django/addenda/60-config-placement.md +14 -0
  991. package/profiles/example-django/heuristics.toml +24 -0
  992. package/profiles/example-django/profile.toml +9 -0
  993. package/profiles/fast/README.md +24 -0
  994. package/profiles/fast/profile.toml +59 -0
  995. package/profiles/minimal/README.md +17 -0
  996. package/profiles/minimal/addenda/.gitkeep +0 -0
  997. package/profiles/minimal/profile.toml +8 -0
  998. package/profiles/snappy/README.md +24 -0
  999. package/profiles/snappy/addenda/10-race-as-question.md +6 -0
  1000. package/profiles/snappy/profile.toml +46 -0
  1001. package/prompts/companion-day-open.md +46 -0
  1002. package/prompts/companion-first-run.md +104 -0
  1003. package/prompts/companion.md +821 -0
  1004. package/prompts/conversation-system.md +117 -0
  1005. package/prompts/eod-sweep.md +120 -0
  1006. package/prompts/onboarding.md +74 -0
  1007. package/prompts/pass-common.md +52 -0
  1008. package/prompts/pass-quality-common.md +22 -0
  1009. package/prompts/round-first.md +874 -0
  1010. package/prompts/round-follow-up.md +991 -0
  1011. package/prompts/round-re-review.md +889 -0
  1012. package/prompts/round-recheck.md +196 -0
  1013. package/prompts/round-staleness.md +856 -0
  1014. package/schemas/review-result.v1.json +391 -0
  1015. package/schemas/scan-result.v1.json +421 -0
  1016. package/schemas/version.v1.json +57 -0
  1017. package/scripts/approve-pr.sh +16 -0
  1018. package/scripts/build-stamp.mjs +67 -0
  1019. package/scripts/commit-verdict.sh +155 -0
  1020. package/scripts/companion-e2e.sh +250 -0
  1021. package/scripts/companion-memory-forward.mjs +1966 -0
  1022. package/scripts/config-fingerprint.sh +28 -0
  1023. package/scripts/deploy-manifest.mjs +141 -0
  1024. package/scripts/deploy.sh +1435 -0
  1025. package/scripts/directory-lock.mjs +193 -0
  1026. package/scripts/heartbeat-fresh.mjs +54 -0
  1027. package/scripts/install-locator.sh +328 -0
  1028. package/scripts/install-wrapper.sh +76 -0
  1029. package/scripts/memory-search-check.mjs +98 -0
  1030. package/scripts/mint-token.sh +212 -0
  1031. package/scripts/openviking-embedder.py +392 -0
  1032. package/scripts/openviking-ov-conf.mjs +161 -0
  1033. package/scripts/openviking-provision.mjs +1122 -0
  1034. package/scripts/openviking-reembed.mjs +1154 -0
  1035. package/scripts/post-review.sh +16 -0
  1036. package/scripts/pr-checks.sh +256 -0
  1037. package/scripts/pr-context.py +174 -0
  1038. package/scripts/pr-context.sh +63 -0
  1039. package/scripts/pr-self.sh +144 -0
  1040. package/scripts/pr-threads.sh +145 -0
  1041. package/scripts/qcr +15 -0
  1042. package/scripts/qcr-host.sh +769 -0
  1043. package/scripts/render-review.sh +24 -0
  1044. package/scripts/reply-thread.sh +16 -0
  1045. package/scripts/required-passes.py +112 -0
  1046. package/scripts/smoke-companion.sh +211 -0
  1047. package/scripts/tui-deploy-runner.mjs +61 -0
  1048. package/scripts/verify-dist.mjs +201 -0
  1049. package/scripts/vm-ghcr-login.sh +188 -0
  1050. package/seeds/agents/pass-baseline.md +61 -0
  1051. package/seeds/agents/pass-contracts.md +30 -0
  1052. package/seeds/agents/pass-data-safety.md +54 -0
  1053. package/seeds/agents/pass-delivery.md +37 -0
  1054. package/seeds/agents/pass-prod-risk.md +24 -0
  1055. package/seeds/agents/pass-security.md +31 -0
  1056. package/seeds/agents/pass-statelessness.md +27 -0
  1057. package/seeds/agents/pass-ui.md +23 -0
  1058. package/seeds/agents/pass-validate.md +50 -0
  1059. package/seeds/prompts/conversation-system.md +117 -0
  1060. package/seeds/prompts/eod-sweep.md +120 -0
  1061. package/seeds/prompts/pass-common.md +52 -0
  1062. package/skills/companion/adjudicate/SKILL.md +247 -0
  1063. package/skills/companion/evidence/SKILL.md +150 -0
  1064. package/skills/companion/land/SKILL.md +200 -0
  1065. package/skills/companion/replay/SKILL.md +138 -0
  1066. package/skills/companion/setup/SKILL.md +167 -0
  1067. package/skills/companion/survey/SKILL.md +160 -0
  1068. package/skills/selfimprove/README.md +34 -0
  1069. package/skills/selfimprove/SKILL.md +127 -0
  1070. package/skills/selfimprove/agents/openai.yaml +2 -0
  1071. package/skills/selfimprove/commands/selfimprove.md +6 -0
  1072. package/skills/selfimprove/references/fix-loop.md +49 -0
  1073. package/skills/selfimprove/references/ledger.md +20 -0
  1074. package/skills/selfimprove/references/setup.md +40 -0
  1075. package/src/anomalies.ts +566 -0
  1076. package/src/answerworker.ts +251 -0
  1077. package/src/appstamp.ts +65 -0
  1078. package/src/archive/admission.ts +3 -0
  1079. package/src/archive/archivedb.ts +548 -0
  1080. package/src/archive/archiver.ts +1963 -0
  1081. package/src/archive/archivewrite.ts +279 -0
  1082. package/src/archive/bundle.ts +333 -0
  1083. package/src/archive/dbmove.ts +911 -0
  1084. package/src/archive/duplicatecounts.ts +98 -0
  1085. package/src/archive/eligibility.ts +181 -0
  1086. package/src/archive/extract.ts +342 -0
  1087. package/src/archive/fsutil.ts +415 -0
  1088. package/src/archive/gzfile.ts +370 -0
  1089. package/src/archive/kinds.ts +21 -0
  1090. package/src/archive/livecheckpoint.ts +217 -0
  1091. package/src/archive/liveretention.ts +180 -0
  1092. package/src/archive/manifest.ts +519 -0
  1093. package/src/archive/overseer.ts +336 -0
  1094. package/src/archive/piglobal.ts +174 -0
  1095. package/src/archive/plan.ts +612 -0
  1096. package/src/archive/prarchive.ts +984 -0
  1097. package/src/archive/prfiles.ts +406 -0
  1098. package/src/archive/report.ts +252 -0
  1099. package/src/archive/restore.ts +330 -0
  1100. package/src/archive/rows.ts +187 -0
  1101. package/src/archive/seal.ts +630 -0
  1102. package/src/archive/status.ts +719 -0
  1103. package/src/archive/storepass.ts +581 -0
  1104. package/src/backfill.ts +362 -0
  1105. package/src/bench/cost.ts +113 -0
  1106. package/src/bench/exec.ts +90 -0
  1107. package/src/bench/values.ts +13 -0
  1108. package/src/botcontrol.ts +176 -0
  1109. package/src/botworker.ts +953 -0
  1110. package/src/capture.ts +321 -0
  1111. package/src/cases.ts +1789 -0
  1112. package/src/channelfs.ts +26 -0
  1113. package/src/checklist.ts +506 -0
  1114. package/src/ciretry.ts +141 -0
  1115. package/src/cli.ts +2271 -0
  1116. package/src/cliops.ts +384 -0
  1117. package/src/clonedir.ts +15 -0
  1118. package/src/commandeffects.ts +57 -0
  1119. package/src/commands.ts +1678 -0
  1120. package/src/companioninbox.ts +239 -0
  1121. package/src/compare.ts +957 -0
  1122. package/src/config.ts +2050 -0
  1123. package/src/configcheck.ts +133 -0
  1124. package/src/coreext.ts +47 -0
  1125. package/src/daemon.ts +1302 -0
  1126. package/src/debuground.ts +927 -0
  1127. package/src/debugroundpi.ts +262 -0
  1128. package/src/diagnostics.ts +14 -0
  1129. package/src/digest.ts +183 -0
  1130. package/src/dispatch.ts +2250 -0
  1131. package/src/engine/answerguard.ts +27 -0
  1132. package/src/engine/botsdk.ts +336 -0
  1133. package/src/engine/caserunner-sdk.ts +423 -0
  1134. package/src/engine/debugpi.ts +235 -0
  1135. package/src/eod.ts +669 -0
  1136. package/src/eodpinwatch.ts +556 -0
  1137. package/src/escalation.ts +1253 -0
  1138. package/src/eventloop.ts +1045 -0
  1139. package/src/execboundary.ts +633 -0
  1140. package/src/feedback.ts +1162 -0
  1141. package/src/findingscheck.ts +298 -0
  1142. package/src/fsdenied.ts +24 -0
  1143. package/src/ghread.ts +242 -0
  1144. package/src/github.ts +1497 -0
  1145. package/src/homes.ts +175 -0
  1146. package/src/hostroute.ts +53 -0
  1147. package/src/improvements.ts +787 -0
  1148. package/src/install.ts +1103 -0
  1149. package/src/installkind.ts +50 -0
  1150. package/src/ipc/capability.ts +333 -0
  1151. package/src/ipc/client.ts +269 -0
  1152. package/src/ipc/control.ts +90 -0
  1153. package/src/ipc/ghreadshim.ts +94 -0
  1154. package/src/ipc/launcher.ts +65 -0
  1155. package/src/ipc/permits.ts +362 -0
  1156. package/src/ipc/postshim.ts +164 -0
  1157. package/src/ipc/protocol.ts +342 -0
  1158. package/src/ipc/server.ts +371 -0
  1159. package/src/ipc/workerspec.ts +218 -0
  1160. package/src/learner/learner.ts +1655 -0
  1161. package/src/learner/miner.ts +1290 -0
  1162. package/src/learner/packet.ts +340 -0
  1163. package/src/learner/receipt.ts +168 -0
  1164. package/src/learner/status.ts +107 -0
  1165. package/src/ledgercheck.ts +157 -0
  1166. package/src/lessonledger.ts +703 -0
  1167. package/src/lessonselect.ts +888 -0
  1168. package/src/lessonshadow.ts +810 -0
  1169. package/src/levers.ts +393 -0
  1170. package/src/live/projection.ts +491 -0
  1171. package/src/live/publish.ts +92 -0
  1172. package/src/live/read.ts +86 -0
  1173. package/src/livecli.ts +336 -0
  1174. package/src/loginhint.ts +56 -0
  1175. package/src/loginrefresh/atomic.ts +76 -0
  1176. package/src/loginrefresh/lock.ts +104 -0
  1177. package/src/loginrefresh/main.ts +59 -0
  1178. package/src/loginrefresh/pirefresh.ts +57 -0
  1179. package/src/loginrefresh/refresher.ts +326 -0
  1180. package/src/loginrefresh/supervisor.ts +273 -0
  1181. package/src/loginrefresh/types.ts +35 -0
  1182. package/src/memory/context.ts +385 -0
  1183. package/src/memory/datafence.ts +9 -0
  1184. package/src/memory/delivery.ts +171 -0
  1185. package/src/memory/eventtags.ts +80 -0
  1186. package/src/memory/health.ts +953 -0
  1187. package/src/memory/import.ts +664 -0
  1188. package/src/memory/layout.ts +261 -0
  1189. package/src/memory/legacy-file.ts +104 -0
  1190. package/src/memory/lessons.ts +447 -0
  1191. package/src/memory/ovsession.ts +601 -0
  1192. package/src/memory/relayout.ts +335 -0
  1193. package/src/memory/roundactivity.ts +209 -0
  1194. package/src/memory/selection.ts +989 -0
  1195. package/src/memory/shadowstatus.ts +125 -0
  1196. package/src/memory/store.ts +275 -0
  1197. package/src/memory/textidentity.ts +8 -0
  1198. package/src/metrics.ts +1056 -0
  1199. package/src/missingconfig.ts +7 -0
  1200. package/src/npmverbs.ts +264 -0
  1201. package/src/onboard/choices.ts +222 -0
  1202. package/src/onboard/engine.ts +518 -0
  1203. package/src/onboard/launch.ts +115 -0
  1204. package/src/onboard/steps/appslug.ts +265 -0
  1205. package/src/onboard/steps/bringup.ts +482 -0
  1206. package/src/onboard/steps/compose.ts +459 -0
  1207. package/src/onboard/steps/configdelivery.ts +58 -0
  1208. package/src/onboard/steps/configfill.ts +1352 -0
  1209. package/src/onboard/steps/deploysh.ts +105 -0
  1210. package/src/onboard/steps/embeddings.ts +550 -0
  1211. package/src/onboard/steps/escalation.ts +640 -0
  1212. package/src/onboard/steps/githubapp.ts +1414 -0
  1213. package/src/onboard/steps/golive.ts +577 -0
  1214. package/src/onboard/steps/index.ts +71 -0
  1215. package/src/onboard/steps/ingress.ts +907 -0
  1216. package/src/onboard/steps/inventory.ts +526 -0
  1217. package/src/onboard/steps/llmauth.ts +1095 -0
  1218. package/src/onboard/steps/memory.ts +1290 -0
  1219. package/src/onboard/steps/memorykeys.ts +85 -0
  1220. package/src/onboard/steps/preflight.ts +191 -0
  1221. package/src/onboard/steps/proof.ts +624 -0
  1222. package/src/onboard/steps/ssh.ts +377 -0
  1223. package/src/onboard/steps/topology.ts +337 -0
  1224. package/src/onboard/steps/transport.ts +665 -0
  1225. package/src/onboard/steps/verifyup.ts +448 -0
  1226. package/src/onboard/steps/vmdeploy.ts +442 -0
  1227. package/src/onboard/toml.ts +50 -0
  1228. package/src/opencli.ts +591 -0
  1229. package/src/openpr.ts +568 -0
  1230. package/src/openviking/client.ts +1131 -0
  1231. package/src/openviking/context.ts +263 -0
  1232. package/src/openviking/embedder.ts +516 -0
  1233. package/src/openviking/gapsink.ts +63 -0
  1234. package/src/openviking/health.ts +83 -0
  1235. package/src/openviking/index.ts +119 -0
  1236. package/src/openviking/lessonfind.ts +92 -0
  1237. package/src/openviking/probe.ts +129 -0
  1238. package/src/openviking/proc.ts +110 -0
  1239. package/src/openviking/provisionreport.ts +160 -0
  1240. package/src/openviking/reembed.ts +412 -0
  1241. package/src/openviking/relayout.ts +177 -0
  1242. package/src/openviking/sidecar-main.ts +38 -0
  1243. package/src/openviking/sidecar.ts +106 -0
  1244. package/src/openviking/store.ts +2025 -0
  1245. package/src/openviking/supervisor.ts +474 -0
  1246. package/src/openviking/types.ts +174 -0
  1247. package/src/operator-recovery.ts +237 -0
  1248. package/src/operatormessage.ts +52 -0
  1249. package/src/outcomes.ts +1670 -0
  1250. package/src/piauthcopy.ts +12 -0
  1251. package/src/picli.ts +49 -0
  1252. package/src/picwd.ts +25 -0
  1253. package/src/pilogin.ts +37 -0
  1254. package/src/pingpong.ts +1339 -0
  1255. package/src/posting-journal.ts +549 -0
  1256. package/src/posting-outbox.ts +802 -0
  1257. package/src/posting-receipt.ts +324 -0
  1258. package/src/posting.ts +603 -0
  1259. package/src/postops.ts +832 -0
  1260. package/src/pr-activity.ts +20 -0
  1261. package/src/pr-author.ts +6 -0
  1262. package/src/pr-conversation.ts +432 -0
  1263. package/src/pr-session-lifecycle.ts +631 -0
  1264. package/src/preflight.ts +391 -0
  1265. package/src/priorresolve.ts +343 -0
  1266. package/src/qcrbin.ts +186 -0
  1267. package/src/recheck.ts +1775 -0
  1268. package/src/reconcile.ts +1030 -0
  1269. package/src/recordedfindings.ts +27 -0
  1270. package/src/regression.ts +833 -0
  1271. package/src/replay.ts +816 -0
  1272. package/src/requiredpasses.ts +148 -0
  1273. package/src/resumecheck.ts +246 -0
  1274. package/src/reviewcli.ts +787 -0
  1275. package/src/reviewcontext.ts +35 -0
  1276. package/src/reviewdetach.ts +734 -0
  1277. package/src/reviewhistory.ts +427 -0
  1278. package/src/reviewhome.ts +36 -0
  1279. package/src/reviewmemory.ts +133 -0
  1280. package/src/reviewrendercli.ts +139 -0
  1281. package/src/round-work.ts +42 -0
  1282. package/src/runhost.ts +108 -0
  1283. package/src/scanauth.ts +36 -0
  1284. package/src/scanbox.ts +1081 -0
  1285. package/src/scancli.ts +1296 -0
  1286. package/src/scandriverlog.ts +32 -0
  1287. package/src/session-bridge.ts +139 -0
  1288. package/src/session-command-payload.ts +35 -0
  1289. package/src/session-command-supervisor.ts +1142 -0
  1290. package/src/sessionjsonl.ts +88 -0
  1291. package/src/sessions.ts +659 -0
  1292. package/src/setup/adapters.ts +335 -0
  1293. package/src/setup/baselines.ts +110 -0
  1294. package/src/setup/caserunner.ts +611 -0
  1295. package/src/setup/configcommit.ts +443 -0
  1296. package/src/setup/engine.ts +1001 -0
  1297. package/src/setup/facts.ts +627 -0
  1298. package/src/setup/findings.ts +1264 -0
  1299. package/src/setup/history.ts +443 -0
  1300. package/src/setup/interview.ts +243 -0
  1301. package/src/setup/ledger.ts +324 -0
  1302. package/src/setup/pins.ts +66 -0
  1303. package/src/setup/portrait.ts +635 -0
  1304. package/src/setup/presentation.ts +18 -0
  1305. package/src/setup/profile.ts +508 -0
  1306. package/src/setup/replay.ts +370 -0
  1307. package/src/setup/replaybuild.ts +392 -0
  1308. package/src/setup/replayrun.ts +1096 -0
  1309. package/src/setup/replaysource.ts +198 -0
  1310. package/src/setup/retune.ts +415 -0
  1311. package/src/setup/retunelog.ts +95 -0
  1312. package/src/setup/scan.ts +1033 -0
  1313. package/src/setup/scanbuild.ts +168 -0
  1314. package/src/setup/scanfacts.ts +107 -0
  1315. package/src/setup/scanlease.ts +297 -0
  1316. package/src/setup/scanreport.ts +373 -0
  1317. package/src/setup/scanrun.ts +2268 -0
  1318. package/src/setup/scantree.ts +259 -0
  1319. package/src/setup/stage2.ts +926 -0
  1320. package/src/setup/stage2request.ts +347 -0
  1321. package/src/setup/survey.ts +458 -0
  1322. package/src/setup/surveyrun.ts +758 -0
  1323. package/src/setup/textsniff.ts +95 -0
  1324. package/src/setup/trackersink.ts +433 -0
  1325. package/src/setup/triage.ts +768 -0
  1326. package/src/setup/tuning.ts +766 -0
  1327. package/src/setup/unitcut.ts +523 -0
  1328. package/src/singleflight.ts +86 -0
  1329. package/src/slack/announce.ts +911 -0
  1330. package/src/slack/api.ts +303 -0
  1331. package/src/slack/messages.ts +288 -0
  1332. package/src/slack/origin.ts +599 -0
  1333. package/src/slack/policy.ts +354 -0
  1334. package/src/slack/reply.ts +201 -0
  1335. package/src/slack/router.ts +285 -0
  1336. package/src/slack/socket.ts +384 -0
  1337. package/src/slack/types.ts +108 -0
  1338. package/src/sqlitehint.ts +32 -0
  1339. package/src/ssh-observation.ts +30 -0
  1340. package/src/state.ts +8243 -0
  1341. package/src/statemachine.ts +369 -0
  1342. package/src/stubs.ts +68 -0
  1343. package/src/takeover.ts +634 -0
  1344. package/src/takeoverpi.ts +293 -0
  1345. package/src/terminal-failure.ts +41 -0
  1346. package/src/thread-resolution-refusal.ts +2 -0
  1347. package/src/tmux.ts +153 -0
  1348. package/src/trackerid.ts +41 -0
  1349. package/src/transcriptindex.ts +665 -0
  1350. package/src/tui/actions.ts +484 -0
  1351. package/src/tui/alerts.ts +666 -0
  1352. package/src/tui/app.ts +1979 -0
  1353. package/src/tui/archiveops.ts +192 -0
  1354. package/src/tui/autofile.ts +233 -0
  1355. package/src/tui/board.ts +1432 -0
  1356. package/src/tui/candidates.ts +889 -0
  1357. package/src/tui/cellwidth.ts +148 -0
  1358. package/src/tui/changelog-store.ts +503 -0
  1359. package/src/tui/chord.ts +25 -0
  1360. package/src/tui/clipboard.ts +92 -0
  1361. package/src/tui/cmdbar.ts +296 -0
  1362. package/src/tui/companion.ts +1427 -0
  1363. package/src/tui/companionplan.ts +247 -0
  1364. package/src/tui/companiontab.ts +83 -0
  1365. package/src/tui/confighome.ts +155 -0
  1366. package/src/tui/connect.ts +68 -0
  1367. package/src/tui/deploy-ceremony.ts +104 -0
  1368. package/src/tui/deploy-drain.ts +129 -0
  1369. package/src/tui/deploy-process.ts +265 -0
  1370. package/src/tui/deploytab.ts +1523 -0
  1371. package/src/tui/design.ts +125 -0
  1372. package/src/tui/digesttab.ts +214 -0
  1373. package/src/tui/emptystate.ts +39 -0
  1374. package/src/tui/evidence.ts +999 -0
  1375. package/src/tui/feed.ts +604 -0
  1376. package/src/tui/feedbacktab.ts +1077 -0
  1377. package/src/tui/filters.ts +90 -0
  1378. package/src/tui/ghread.ts +321 -0
  1379. package/src/tui/historypull.ts +81 -0
  1380. package/src/tui/inboxpull.ts +236 -0
  1381. package/src/tui/index.ts +1565 -0
  1382. package/src/tui/issuesink.ts +238 -0
  1383. package/src/tui/jsonfile.ts +42 -0
  1384. package/src/tui/keys.ts +109 -0
  1385. package/src/tui/layout.ts +108 -0
  1386. package/src/tui/learning.ts +627 -0
  1387. package/src/tui/lessonswitch.ts +118 -0
  1388. package/src/tui/livecontrol.ts +228 -0
  1389. package/src/tui/memforward.ts +443 -0
  1390. package/src/tui/memincident.ts +363 -0
  1391. package/src/tui/memory.ts +620 -0
  1392. package/src/tui/memtab.ts +606 -0
  1393. package/src/tui/metricstab.ts +1177 -0
  1394. package/src/tui/model.ts +131 -0
  1395. package/src/tui/mouse.ts +98 -0
  1396. package/src/tui/msg.ts +268 -0
  1397. package/src/tui/nativecompanion.ts +417 -0
  1398. package/src/tui/openurl.ts +21 -0
  1399. package/src/tui/paint.ts +511 -0
  1400. package/src/tui/panes.ts +98 -0
  1401. package/src/tui/pipane.ts +219 -0
  1402. package/src/tui/poll-hooks.ts +12 -0
  1403. package/src/tui/poll.ts +147 -0
  1404. package/src/tui/proposals.ts +838 -0
  1405. package/src/tui/prpause.ts +150 -0
  1406. package/src/tui/reload.ts +436 -0
  1407. package/src/tui/remote.ts +413 -0
  1408. package/src/tui/rollover.ts +969 -0
  1409. package/src/tui/scantab.ts +1290 -0
  1410. package/src/tui/setupentry.ts +93 -0
  1411. package/src/tui/sidebar.ts +749 -0
  1412. package/src/tui/sshtriage.ts +510 -0
  1413. package/src/tui/startup.ts +231 -0
  1414. package/src/tui/tabs.ts +45 -0
  1415. package/src/tui/termmirror.ts +224 -0
  1416. package/src/tui/theme.ts +95 -0
  1417. package/src/tui/ticketstab.ts +310 -0
  1418. package/src/tui/tmuxsocket.ts +129 -0
  1419. package/src/tui/trackertickets.ts +84 -0
  1420. package/src/tui/unwedge.ts +286 -0
  1421. package/src/tui/viewer.ts +575 -0
  1422. package/src/tui/viewerinput.ts +173 -0
  1423. package/src/updatenotice.ts +178 -0
  1424. package/src/usage.ts +1154 -0
  1425. package/src/verdicts.ts +4689 -0
  1426. package/src/version.ts +80 -0
  1427. package/src/wakes.ts +476 -0
  1428. package/src/webhook.ts +942 -0
  1429. package/src/webhookheal.ts +276 -0
  1430. package/src/wire.ts +2153 -0
  1431. package/src/worker-session-host.ts +602 -0
  1432. package/src/workerbreaker.ts +156 -0
  1433. package/src/workercontrol.ts +104 -0
  1434. package/src/workerlease.ts +441 -0
  1435. package/src/workerliveness.ts +103 -0
  1436. package/src/workerlog.ts +79 -0
  1437. package/src/workerruntime.ts +30 -0
  1438. package/src/workersupervisor.ts +1538 -0
  1439. package/src/workerusage.ts +42 -0
  1440. package/src/workerworld.ts +427 -0
  1441. package/src/worktrees.ts +1138 -0
  1442. package/tests/fixtures/regression-cases.json +795 -0
  1443. package/tests/fixtures/seed-manifest.json +19 -0
@@ -0,0 +1,1190 @@
1
+ #!/usr/bin/env node
2
+ // Interactive wizard: set up the Slack concierge end to end — create
3
+ // the app, collect the two tokens into the secrets dir, pick the ONE channel,
4
+ // build the [slack.users] identity map, and patch config.toml.
5
+ //
6
+ // Tokens are read with hidden input and NEVER printed back. Re-run any time —
7
+ // existing files are kept unless you choose to replace them.
8
+ //
9
+ // node deploy/collect-slack-secrets.mjs # fill in what is missing
10
+ // node deploy/collect-slack-secrets.mjs --force # offer to replace existing tokens too
11
+ // node deploy/collect-slack-secrets.mjs --no-verify # skip every network call (offline)
12
+ // node deploy/collect-slack-secrets.mjs --config PATH # patch a different config.toml
13
+ // (default: the install locator's answer)
14
+ // node deploy/collect-slack-secrets.mjs --secrets-dir PATH # override the secrets dir
15
+ // QC_SECRETS_DIR=/tmp/sec node deploy/collect-slack-secrets.mjs # same, via env
16
+ //
17
+ // WHY NODE, NOT BASH (deploy/collect-secrets.sh is bash):
18
+ // that wizard only writes flat files. This one also makes read-only Slack Web
19
+ // API calls (JSON) and surgically patches config.toml (comment-preserving text
20
+ // editing). Both are miserable in bash. It is still a *standalone* script:
21
+ // ESM, Node 26+ (supported), global fetch, zero imports outside node: — no npm deps, so
22
+ // it runs before/without an install. The visual language deliberately mirrors
23
+ // collect-secrets.sh (bold/ok/bad/info, same colours, hidden input).
24
+ //
25
+ // WHAT IT NEVER DOES: deploy, start a container, start the daemon, touch
26
+ // `dry_run`, or flip `enabled` behind your back. Slack calls are read-only
27
+ // (auth.test, apps.connections.open, conversations.info, users.list) — it never
28
+ // posts, never joins, never mutates anything in Slack.
29
+
30
+ import { execFileSync } from "node:child_process";
31
+ import { createInterface } from "node:readline/promises";
32
+ import {
33
+ chmodSync,
34
+ copyFileSync,
35
+ existsSync,
36
+ mkdirSync,
37
+ readFileSync,
38
+ renameSync,
39
+ statSync,
40
+ writeFileSync,
41
+ } from "node:fs";
42
+ import { homedir } from "node:os";
43
+ import { dirname, isAbsolute, join, resolve } from "node:path";
44
+ import { fileURLToPath } from "node:url";
45
+
46
+ const REPO = resolve(dirname(fileURLToPath(import.meta.url)), "..");
47
+
48
+ // ---------------------------------------------------------------- pure helpers
49
+ // Everything below the `export` keyword is covered by tests/slack-setup-wizard.test.ts.
50
+
51
+ /** ANSI helpers — same palette as deploy/collect-secrets.sh. */
52
+ export const bold = (s) => `${s}`;
53
+ export const okMark = "✔";
54
+ export const badMark = "✘";
55
+
56
+ /**
57
+ * Never reveal a token. Shows the prefix up to the first `-` plus a 3-char tail
58
+ * hint and the length — enough to tell two pastes apart, useless to an attacker.
59
+ */
60
+ export function maskToken(value) {
61
+ const v = String(value ?? "");
62
+ if (v === "") return "(empty)";
63
+ const dash = v.indexOf("-");
64
+ const head = dash > 0 ? v.slice(0, dash + 1) : v.slice(0, 2);
65
+ if (v.length <= head.length + 6) return `${"*".repeat(v.length)} (${v.length} chars)`;
66
+ return `${head}…${v.slice(-3)} (${v.length} chars)`;
67
+ }
68
+
69
+ /**
70
+ * Accept a raw channel id, a Slack permalink, or an archives URL (query string
71
+ * and all). Reject `#name` loudly — config.toml needs the id, not the name.
72
+ * Returns { ok: true, id } or { ok: false, reason }.
73
+ */
74
+ export function parseChannelId(input) {
75
+ const raw = String(input ?? "").trim();
76
+ if (raw === "") return { ok: false, reason: "empty — paste a channel id (C…) or a Slack link" };
77
+ const idRe = /^[CG][A-Z0-9]{5,}$/;
78
+
79
+ if (raw.startsWith("#")) {
80
+ return {
81
+ ok: false,
82
+ reason:
83
+ `"${raw}" is a channel NAME. config.toml needs the channel ID (starts with C). ` +
84
+ "In Slack: open the channel → click its name → About → scroll to the bottom → " +
85
+ "“Channel ID”, or use Copy link and paste that here.",
86
+ };
87
+ }
88
+
89
+ const bare = raw.toUpperCase();
90
+ if (idRe.test(bare)) return { ok: true, id: bare };
91
+
92
+ if (/^https?:\/\//i.test(raw)) {
93
+ let url;
94
+ try {
95
+ url = new URL(raw);
96
+ } catch {
97
+ return { ok: false, reason: `not a usable Slack link: ${raw}` };
98
+ }
99
+ const seg = url.pathname.split("/").filter(Boolean);
100
+ const i = seg.indexOf("archives");
101
+ const candidates = [];
102
+ if (i !== -1 && seg[i + 1]) candidates.push(seg[i + 1]);
103
+ for (const key of ["cid", "channel", "channel_id"]) {
104
+ const q = url.searchParams.get(key);
105
+ if (q) candidates.push(q);
106
+ }
107
+ for (const c of candidates) {
108
+ const up = String(c).toUpperCase();
109
+ if (idRe.test(up)) return { ok: true, id: up };
110
+ }
111
+ return {
112
+ ok: false,
113
+ reason:
114
+ "that link has no channel id in it — use the channel's “Copy link” " +
115
+ "(it looks like https://…/archives/C0ABCDEFG/p1712345678000100)",
116
+ };
117
+ }
118
+
119
+ return {
120
+ ok: false,
121
+ reason:
122
+ `"${raw}" is not a channel id. Ids look like C0ABCDEFG (8–11 chars, C then ` +
123
+ "capitals/digits). Channel → About → bottom, or Copy link and paste the URL.",
124
+ };
125
+ }
126
+
127
+ /** Slack member id, as accepted for legacy_owner_slack_id / [slack.users] keys. */
128
+ export function parseUserId(input) {
129
+ const raw = String(input ?? "")
130
+ .trim()
131
+ .toUpperCase();
132
+ if (/^[UW][A-Z0-9]{5,}$/.test(raw)) return { ok: true, id: raw };
133
+ return {
134
+ ok: false,
135
+ reason:
136
+ `"${String(input ?? "").trim()}" is not a Slack member id. Ids look like U01AB2CD3EF ` +
137
+ "(profile → ⋮ → Copy member ID).",
138
+ };
139
+ }
140
+
141
+ /**
142
+ * Shape check for the two tokens. `kind` is "bot" (xoxb-) or "app" (xapp-).
143
+ * The wrong-slot case gets its own message — pasting the app token at step 2 is
144
+ * the single most common mistake.
145
+ */
146
+ export function tokenLooksValid(kind, value) {
147
+ const v = String(value ?? "").trim();
148
+ const want = kind === "bot" ? "xoxb-" : "xapp-";
149
+ const other = kind === "bot" ? "xapp-" : "xoxb-";
150
+ const otherName =
151
+ kind === "bot"
152
+ ? "the APP-LEVEL token (step 3, Basic Information → App-Level Tokens)"
153
+ : "the BOT token (step 2, OAuth & Permissions → Bot User OAuth Token)";
154
+ if (v === "") return { ok: false, reason: "nothing pasted" };
155
+ if (/\s/.test(v)) return { ok: false, reason: "contains whitespace — paste one unbroken string" };
156
+ if (v.startsWith(other)) {
157
+ return {
158
+ ok: false,
159
+ reason: `that is ${otherName} — it starts ${other}, this step needs one starting ${want}`,
160
+ };
161
+ }
162
+ if (!v.startsWith(want)) return { ok: false, reason: `must start with ${want}` };
163
+ if (v.length < 24) return { ok: false, reason: `suspiciously short (${v.length} chars)` };
164
+ return { ok: true };
165
+ }
166
+
167
+ /** GitHub logins: 1–39 chars, alphanumeric or single hyphens, no leading/trailing hyphen. */
168
+ export function looksLikeGithubLogin(value) {
169
+ const v = String(value ?? "").trim();
170
+ return /^[A-Za-z\d](?:[A-Za-z\d]|-(?=[A-Za-z\d])){0,38}$/.test(v);
171
+ }
172
+
173
+ /** The [slack.users] table body: `U… = "login"` lines, one per entry, in order. */
174
+ export function renderUsersTable(users) {
175
+ const entries = users instanceof Map ? [...users.entries()] : Object.entries(users ?? {});
176
+ return entries.map(([id, login]) => `${id} = ${JSON.stringify(String(login))}`).join("\n");
177
+ }
178
+
179
+ /** Human-readable summary of what step 6 is about to write. */
180
+ export function renderSlackValues(values) {
181
+ const users =
182
+ values.users instanceof Map ? Object.fromEntries(values.users) : (values.users ?? {});
183
+ const n = Object.keys(users).length;
184
+ const lines = [
185
+ ` channel ${values.channel || "(empty)"}${values.channelName ? ` (#${values.channelName})` : ""}`,
186
+ ` channel_kind ${values.channel_kind}`,
187
+ ` legacy_owner_slack_id ${values.legacy_owner_slack_id || "(empty)"}`,
188
+ ` [slack.users] ${n} ${n === 1 ? "entry" : "entries"}`,
189
+ ];
190
+ for (const [id, login] of Object.entries(users)) {
191
+ lines.push(` ${id} → ${login}${id === values.legacy_owner_slack_id ? " (tier-M)" : ""}`);
192
+ }
193
+ return lines.join("\n");
194
+ }
195
+
196
+ /**
197
+ * Read back the [slack] scalars + users map from config.toml text (no TOML dep).
198
+ * `legacy_owner_slack_id` is the owner's Slack id resolved as the daemon resolves it:
199
+ * `[owner] slack_id` when set, else the legacy `[slack] legacy_owner_slack_id`.
200
+ * `owner_id_conflict` is true when both are set and differ — a config the
201
+ * daemon refuses to load.
202
+ */
203
+ export function readSlackValues(text) {
204
+ const section = sliceSection(String(text ?? ""), "[slack]");
205
+ const ownerSection = sliceSection(String(text ?? ""), "[owner]");
206
+ const scalarIn = (body, key) => {
207
+ const m = body.match(new RegExp(`^\\s*${key}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`, "m"));
208
+ return m ? (m[1] ?? m[2]) : "";
209
+ };
210
+ const scalar = (key) => scalarIn(section.body, key);
211
+ const ownerId = scalarIn(ownerSection.body, "slack_id").trim();
212
+ const legacyId = scalar("legacy_owner_slack_id").trim();
213
+ const enabledM = section.body.match(/^\s*enabled\s*=\s*(true|false)/m);
214
+ const usersSection = sliceSection(String(text ?? ""), "[slack.users]");
215
+ /** @type {Record<string, string>} */
216
+ const users = {};
217
+ for (const line of usersSection.body.split("\n")) {
218
+ const m = line.match(
219
+ /^\s*(?:"([^"]+)"|'([^']+)'|([A-Za-z\d_-]+))\s*=\s*(?:"([^"]*)"|'([^']*)')/,
220
+ );
221
+ if (m) users[m[1] ?? m[2] ?? m[3]] = m[4] ?? m[5];
222
+ }
223
+ return {
224
+ enabled: enabledM ? enabledM[1] === "true" : false,
225
+ channel: scalar("channel"),
226
+ channel_kind: scalar("channel_kind") || "public",
227
+ legacy_owner_slack_id: ownerId || legacyId,
228
+ owner_id_conflict: ownerId !== "" && legacyId !== "" && ownerId !== legacyId,
229
+ users,
230
+ };
231
+ }
232
+
233
+ /** Locate a TOML table: everything between its header line and the next `[`. */
234
+ function sectionHeaderMatches(line, header) {
235
+ return line.replace(/#.*$/, "").trim() === header;
236
+ }
237
+
238
+ function sliceSection(text, header) {
239
+ const lines = text.split("\n");
240
+ const start = lines.findIndex((l) => sectionHeaderMatches(l, header));
241
+ if (start === -1) return { start: -1, end: -1, body: "" };
242
+ let end = lines.length;
243
+ for (let i = start + 1; i < lines.length; i++) {
244
+ if (/^\s*\[/.test(lines[i])) {
245
+ end = i;
246
+ break;
247
+ }
248
+ }
249
+ return { start, end, body: lines.slice(start + 1, end).join("\n") };
250
+ }
251
+
252
+ const isKvLine = (l) => !/^\s*#/.test(l) && /^\s*(?:"[^"]*"|'[^']*'|[A-Za-z\d_-]+)\s*=/.test(l);
253
+
254
+ function replaceScalar(line, key, value) {
255
+ const re = new RegExp(`^(\\s*${key}\\s*=\\s*)("(?:[^"\\\\]|\\\\.)*"|'[^']*')(.*)$`);
256
+ const m = line.match(re);
257
+ if (!m) return line;
258
+ const head = `${m[1]}${JSON.stringify(String(value))}`;
259
+ // Keep a trailing comment in its original column when the new value still
260
+ // fits; the comment text itself is never altered.
261
+ const trailing = m[3].match(/^(\s+)(#.*)$/);
262
+ if (trailing) {
263
+ const column = line.length - trailing[2].length;
264
+ const pad = " ".repeat(Math.max(1, column - head.length));
265
+ return `${head}${pad}${trailing[2]}`;
266
+ }
267
+ return `${head}${m[3]}`;
268
+ }
269
+
270
+ /**
271
+ * Set `enabled = true` in [slack]: an existing assignment is rewritten, an
272
+ * absent one is inserted right after the section header.
273
+ */
274
+ export function enableSlack(text) {
275
+ const src = String(text ?? "");
276
+ const sec = sliceSection(src, "[slack]");
277
+ if (sec.start === -1) throw new Error("config.toml has no [slack] section — nothing to enable");
278
+ const lines = src.split("\n");
279
+ let found = false;
280
+ for (let i = sec.start + 1; i < sec.end; i++) {
281
+ if (/^\s*enabled\s*=/.test(lines[i])) {
282
+ found = true;
283
+ lines[i] = lines[i].replace(/^(\s*enabled\s*=\s*)(true|false)/, "$1true");
284
+ }
285
+ }
286
+ if (!found) lines.splice(sec.start + 1, 0, "enabled = true");
287
+ return lines.join("\n");
288
+ }
289
+
290
+ /**
291
+ * Surgically patch config.toml: only `channel`, `channel_kind`,
292
+ * `legacy_owner_slack_id`, the [slack.users] table body and a nonempty
293
+ * `[owner] slack_id` (kept equal to `legacy_owner_slack_id`) change. Every comment,
294
+ * every other key, and the whole [slack.policy] / [slack.policy.causes] block
295
+ * survive byte-identical. `enabled` is deliberately NOT touched here.
296
+ * Idempotent: patch(patch(t)) === patch(t).
297
+ */
298
+ export function patchConfigToml(text, values) {
299
+ const src = String(text ?? "");
300
+ const lines = src.split("\n");
301
+ const slack = sliceSection(src, "[slack]");
302
+ if (slack.start === -1) throw new Error("config.toml has no [slack] section — nothing to patch");
303
+
304
+ const out = lines.slice();
305
+ for (let i = slack.start + 1; i < slack.end; i++) {
306
+ if (values.channel !== undefined) out[i] = replaceScalar(out[i], "channel", values.channel);
307
+ if (values.channel_kind !== undefined)
308
+ out[i] = replaceScalar(out[i], "channel_kind", values.channel_kind);
309
+ if (values.legacy_owner_slack_id !== undefined) {
310
+ out[i] = replaceScalar(out[i], "legacy_owner_slack_id", values.legacy_owner_slack_id);
311
+ }
312
+ }
313
+
314
+ const missing = ["channel", "channel_kind", "legacy_owner_slack_id"]
315
+ .filter(
316
+ (key) =>
317
+ values[key] !== undefined &&
318
+ !lines
319
+ .slice(slack.start + 1, slack.end)
320
+ .some((line) => new RegExp(`^\\s*${key}\\s*=`).test(line)),
321
+ )
322
+ .map((key) => `${key} = ${JSON.stringify(String(values[key]))}`);
323
+ out.splice(slack.end, 0, ...missing);
324
+
325
+ // A set `[owner] slack_id` wins over the legacy key at load, and the two
326
+ // differing is a load error — so a set canonical id follows the same value.
327
+ const owner = sliceSection(out.join("\n"), "[owner]");
328
+ if (String(values.legacy_owner_slack_id ?? "").trim() !== "" && owner.start !== -1) {
329
+ for (let i = owner.start + 1; i < owner.end; i++) {
330
+ const m = out[i].match(/^\s*slack_id\s*=\s*(?:"([^"]*)"|'([^']*)')/);
331
+ if (m && (m[1] ?? m[2]).trim() !== "") {
332
+ out[i] = replaceScalar(out[i], "slack_id", values.legacy_owner_slack_id);
333
+ }
334
+ }
335
+ }
336
+
337
+ if (values.users !== undefined) {
338
+ const entries = renderUsersTable(values.users)
339
+ .split("\n")
340
+ .filter((l) => l !== "");
341
+ const uStart = out.findIndex((l) => sectionHeaderMatches(l, "[slack.users]"));
342
+ if (uStart === -1) {
343
+ out.splice(sliceSection(out.join("\n"), "[slack]").end, 0, "[slack.users]", ...entries, "");
344
+ } else {
345
+ let uEnd = out.length;
346
+ for (let i = uStart + 1; i < out.length; i++) {
347
+ if (/^\s*\[/.test(out[i])) {
348
+ uEnd = i;
349
+ break;
350
+ }
351
+ }
352
+ const section = out.slice(uStart + 1, uEnd);
353
+ const keep = section.filter((l) => !isKvLine(l));
354
+ let trailingBlanks = 0;
355
+ while (keep.length > 0 && keep[keep.length - 1].trim() === "") {
356
+ keep.pop();
357
+ trailingBlanks++;
358
+ }
359
+ const rebuilt = [...keep, ...entries, ...Array(trailingBlanks).fill("")];
360
+ out.splice(uStart + 1, uEnd - (uStart + 1), ...rebuilt);
361
+ }
362
+ }
363
+
364
+ return out.join("\n");
365
+ }
366
+
367
+ /** Minimal unified-ish diff (LCS), enough to review a surgical patch. */
368
+ export function diffLines(beforeText, afterText, context = 2) {
369
+ const a = String(beforeText ?? "").split("\n");
370
+ const b = String(afterText ?? "").split("\n");
371
+ const n = a.length;
372
+ const m = b.length;
373
+ const dp = Array.from({ length: n + 1 }, () => new Uint32Array(m + 1));
374
+ for (let i = n - 1; i >= 0; i--) {
375
+ for (let j = m - 1; j >= 0; j--) {
376
+ dp[i][j] = a[i] === b[j] ? dp[i + 1][j + 1] + 1 : Math.max(dp[i + 1][j], dp[i][j + 1]);
377
+ }
378
+ }
379
+ const ops = [];
380
+ let i = 0;
381
+ let j = 0;
382
+ while (i < n && j < m) {
383
+ if (a[i] === b[j]) ops.push([" ", a[i++], j++]);
384
+ else if (dp[i + 1][j] >= dp[i][j + 1]) ops.push(["-", a[i++]]);
385
+ else ops.push(["+", b[j++]]);
386
+ }
387
+ while (i < n) ops.push(["-", a[i++]]);
388
+ while (j < m) ops.push(["+", b[j++]]);
389
+
390
+ const keep = new Array(ops.length).fill(false);
391
+ ops.forEach((op, k) => {
392
+ if (op[0] === " ") return;
393
+ for (let x = Math.max(0, k - context); x <= Math.min(ops.length - 1, k + context); x++)
394
+ keep[x] = true;
395
+ });
396
+ const lines = [];
397
+ let gap = false;
398
+ ops.forEach((op, k) => {
399
+ if (!keep[k]) {
400
+ gap = true;
401
+ return;
402
+ }
403
+ if (gap && lines.length > 0) lines.push(" …");
404
+ gap = false;
405
+ lines.push(`${op[0]} ${op[1]}`);
406
+ });
407
+ return lines.join("\n");
408
+ }
409
+
410
+ /** The Slack app manifest, public or private variant. */
411
+ export function manifestYaml(kind = "public") {
412
+ const priv = kind === "private";
413
+ return `_metadata:
414
+ major_version: 2
415
+ minor_version: 1
416
+ display_information:
417
+ name: quickreview-concierge
418
+ description: Review-system overseer in Slack (one channel, thread-per-PR)
419
+ features:
420
+ bot_user:
421
+ display_name: quickreview
422
+ always_online: true
423
+ oauth_config:
424
+ scopes:
425
+ bot:
426
+ - chat:write
427
+ - channels:history
428
+ - channels:read
429
+ - users:read
430
+ ${priv ? "- groups:history" : "# - groups:history # only if the channel is private"}
431
+ ${priv ? "- groups:read" : "# - groups:read # only if the channel is private"}
432
+ settings:
433
+ socket_mode_enabled: true
434
+ event_subscriptions:
435
+ bot_events:
436
+ - message.channels
437
+ ${priv ? "- message.groups" : "# - message.groups # only if the channel is private"}
438
+ org_deploy_enabled: false
439
+ token_rotation_enabled: false
440
+ `;
441
+ }
442
+
443
+ /**
444
+ * The same conditions the daemon checks at boot (src/config.ts checkSlackShape +
445
+ * the token-file check). Returns [{ ok, label, hint }].
446
+ */
447
+ export function finalChecks(state) {
448
+ const users = state.users instanceof Map ? Object.fromEntries(state.users) : (state.users ?? {});
449
+ const id = String(state.legacy_owner_slack_id ?? "").trim();
450
+ return [
451
+ {
452
+ ok: String(state.channel ?? "").trim() !== "",
453
+ label: "channel is set",
454
+ hint: "re-run the wizard and complete step 4",
455
+ },
456
+ {
457
+ ok: state.channel_kind === "public" || state.channel_kind === "private",
458
+ label: 'channel_kind is "public" or "private"',
459
+ hint: "re-run the wizard and complete step 4",
460
+ },
461
+ {
462
+ ok: id !== "",
463
+ label: "legacy_owner_slack_id is set",
464
+ hint: "re-run the wizard and complete step 5",
465
+ },
466
+ {
467
+ ok: id !== "" && Object.prototype.hasOwnProperty.call(users, id),
468
+ label: "legacy_owner_slack_id is a key in [slack.users]",
469
+ hint: "boot fails otherwise — the owner's id must be in the identity map",
470
+ },
471
+ {
472
+ ok: state.owner_id_conflict !== true,
473
+ label: "[owner] slack_id and legacy [slack] legacy_owner_slack_id agree",
474
+ hint: "boot fails otherwise — set `[owner] slack_id` only and empty the legacy key",
475
+ },
476
+ {
477
+ ok: state.botTokenOk === true,
478
+ label: "slack_bot_token file present and non-empty",
479
+ hint: "re-run the wizard and complete step 2",
480
+ },
481
+ {
482
+ ok: state.appTokenOk === true,
483
+ label: "slack_app_token file present and non-empty",
484
+ hint: "re-run the wizard and complete step 3",
485
+ },
486
+ ];
487
+ }
488
+
489
+ /** ~-expansion, the same rule src/config.ts uses. */
490
+ export function expandHome(p, home = homedir()) {
491
+ const s = String(p ?? "");
492
+ if (s === "~") return home;
493
+ if (s.startsWith("~/")) return join(home, s.slice(2));
494
+ return s;
495
+ }
496
+
497
+ /** [github].secrets_dir out of config.toml text (no TOML dependency here), as
498
+ * written — "" when unset, which leaves the choice to the install locator. */
499
+ export function readSecretsDir(text) {
500
+ const gh = sliceSection(String(text ?? ""), "[github]");
501
+ const m = gh.body.match(/^\s*secrets_dir\s*=\s*(?:"([^"]*)"|'([^']*)')/m);
502
+ return m ? (m[1] ?? m[2]) : "";
503
+ }
504
+
505
+ /**
506
+ * Absolute paths of the two Slack token files, resolved as the daemon resolves
507
+ * them: `[slack] bot_token_file` / `app_token_file` (default `slack_bot_token`
508
+ * / `slack_app_token`), a bare name under `secretsDir`, an absolute or
509
+ * ~-rooted name taken as given.
510
+ */
511
+ export function slackTokenPaths(text, secretsDir, home = homedir()) {
512
+ const section = sliceSection(String(text ?? ""), "[slack]");
513
+ const pathOf = (key, fallback) => {
514
+ const m = section.body.match(new RegExp(`^\\s*${key}\\s*=\\s*(?:"([^"]*)"|'([^']*)')`, "m"));
515
+ const name = expandHome(m ? (m[1] ?? m[2]) : fallback, home);
516
+ return isAbsolute(name) ? name : join(secretsDir, name);
517
+ };
518
+ return {
519
+ bot: pathOf("bot_token_file", "slack_bot_token"),
520
+ app: pathOf("app_token_file", "slack_app_token"),
521
+ };
522
+ }
523
+
524
+ // -------------------------------------------------------------------- runtime
525
+ // Below this line: I/O, prompts and network. Not covered by unit tests. It all
526
+ // lives inside main(), which runs only when this file is executed directly —
527
+ // importing the module (as the tests do) must never open a prompt.
528
+
529
+ // RUNTIME-BEGIN
530
+ async function main() {
531
+ const args = process.argv.slice(2);
532
+ const flag = (name) => args.includes(name);
533
+ const valueOf = (name, fallback) => {
534
+ const i = args.indexOf(name);
535
+ return i !== -1 && args[i + 1] ? args[i + 1] : fallback;
536
+ };
537
+
538
+ if (flag("--help") || flag("-h")) {
539
+ process.stdout.write(
540
+ readFileSync(fileURLToPath(import.meta.url), "utf8")
541
+ .split("\n")
542
+ .filter((l) => l.startsWith("//"))
543
+ .map((l) => l.replace(/^\/\/ ?/, ""))
544
+ .join("\n") + "\n",
545
+ );
546
+ process.exit(0);
547
+ }
548
+
549
+ const FORCE = flag("--force");
550
+ const VERIFY = !flag("--no-verify");
551
+ // The default is the install locator's answer ($QCR_CONFIG, else the
552
+ // install's config home) — asked of its shell mirror, so this script builds
553
+ // no config path of its own.
554
+ const CONFIG_PATH = resolve(
555
+ valueOf("--config", "") ||
556
+ execFileSync(
557
+ "bash",
558
+ ["-c", '. "$1/scripts/install-locator.sh" && qcr_locate_config "$1"', "locate", REPO],
559
+ { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] },
560
+ ).trim(),
561
+ );
562
+
563
+ const out = (s = "") => process.stdout.write(`${s}\n`);
564
+ const title = (s) => out(`\n${bold(s)}`);
565
+ const ok = (s) => out(` ${okMark} ${s}`);
566
+ const bad = (s) => out(` ${badMark} ${s}`);
567
+ const info = (s) => out(` · ${s}`);
568
+ const para = (s) => out(` ${s}`);
569
+
570
+ let muted = false;
571
+ const rl = createInterface({
572
+ input: process.stdin,
573
+ output: process.stdout,
574
+ terminal: Boolean(process.stdin.isTTY),
575
+ });
576
+ rl._writeToOutput = function (str) {
577
+ if (!muted) this.output.write(str);
578
+ };
579
+ // Own line queue rather than rl.question(): with piped (non-TTY) stdin
580
+ // readline emits every buffered line at once, and question() would keep only
581
+ // the first. Queueing makes the wizard scriptable (`printf … | node …`).
582
+ let stdinClosed = false;
583
+ const queued = [];
584
+ let waiting = null;
585
+ rl.on("line", (line) => {
586
+ if (waiting) {
587
+ const resolve_ = waiting;
588
+ waiting = null;
589
+ resolve_(line);
590
+ } else {
591
+ queued.push(line);
592
+ }
593
+ });
594
+ rl.on("close", () => {
595
+ stdinClosed = true;
596
+ if (waiting) {
597
+ const resolve_ = waiting;
598
+ waiting = null;
599
+ resolve_(null);
600
+ }
601
+ });
602
+
603
+ process.on("SIGINT", () => {
604
+ out("\n · interrupted — nothing half-written; re-run any time");
605
+ process.exit(130);
606
+ });
607
+
608
+ const exhausted = () => stdinClosed && queued.length === 0;
609
+
610
+ function readLine() {
611
+ if (queued.length > 0) return Promise.resolve(queued.shift());
612
+ if (stdinClosed) return Promise.resolve(null);
613
+ return new Promise((res) => {
614
+ waiting = res;
615
+ });
616
+ }
617
+
618
+ async function ask(label, fallback = "") {
619
+ if (exhausted()) return fallback;
620
+ process.stdout.write(label);
621
+ const answer = await readLine();
622
+ if (answer === null) return fallback;
623
+ return String(answer).trim();
624
+ }
625
+
626
+ async function askHidden(label) {
627
+ if (exhausted()) return "";
628
+ process.stdout.write(label);
629
+ muted = true;
630
+ try {
631
+ const answer = await readLine();
632
+ return answer === null ? "" : String(answer).trim();
633
+ } finally {
634
+ muted = false;
635
+ process.stdout.write("\n");
636
+ }
637
+ }
638
+
639
+ async function confirm(label, def = false) {
640
+ const suffix = def ? "[Y/n]" : "[y/N]";
641
+ const a = (await ask(` ${label} ${suffix} `)).toLowerCase();
642
+ if (a === "") return def;
643
+ return a === "y" || a === "yes";
644
+ }
645
+
646
+ // ---- secrets dir -----------------------------------------------------------
647
+
648
+ const configText = existsSync(CONFIG_PATH) ? readFileSync(CONFIG_PATH, "utf8") : "";
649
+ if (!configText) {
650
+ bad(`no config.toml at ${CONFIG_PATH} — pass --config <path>`);
651
+ process.exit(1);
652
+ }
653
+ // --secrets-dir, then $QC_SECRETS_DIR, else the install locator's answer
654
+ // (its shell mirror, as for the config above): the configured
655
+ // [github] secrets_dir, else <config home>/secrets.
656
+ const SECRETS_DIR = resolve(
657
+ expandHome(
658
+ valueOf("--secrets-dir", "") ||
659
+ process.env.QC_SECRETS_DIR ||
660
+ execFileSync(
661
+ "bash",
662
+ [
663
+ "-c",
664
+ '. "$1/scripts/install-locator.sh" && qcr_locate_secrets "$2"',
665
+ "locate",
666
+ REPO,
667
+ readSecretsDir(configText),
668
+ ],
669
+ { encoding: "utf8", stdio: ["ignore", "pipe", "inherit"] },
670
+ ).trim(),
671
+ ),
672
+ );
673
+ const { bot: BOT_FILE, app: APP_FILE } = slackTokenPaths(configText, SECRETS_DIR);
674
+
675
+ mkdirSync(SECRETS_DIR, { recursive: true, mode: 0o700 });
676
+ try {
677
+ chmodSync(SECRETS_DIR, 0o700);
678
+ } catch {
679
+ /* not ours to chmod — fine */
680
+ }
681
+
682
+ function statusOf(path) {
683
+ try {
684
+ const st = statSync(path);
685
+ if (st.size === 0) return "MISSING (empty file)";
686
+ const when = new Date(st.mtimeMs).toISOString().slice(0, 16).replace("T", " ");
687
+ return `present (${st.size} bytes, ${when})`;
688
+ } catch {
689
+ return "MISSING";
690
+ }
691
+ }
692
+
693
+ const filePresent = (p) => {
694
+ try {
695
+ return readFileSync(p, "utf8").trim() !== "";
696
+ } catch {
697
+ return false;
698
+ }
699
+ };
700
+
701
+ /**
702
+ * Back up config.toml ONCE per run. Steps 6 and 7 both write, and a per-write
703
+ * backup would leave `.bak` holding step 6's output — i.e. "before the last
704
+ * write", not "before the wizard". This keeps the undo target honest.
705
+ */
706
+ let configBackedUp = false;
707
+ function backupConfigOnce() {
708
+ if (configBackedUp) return;
709
+ copyFileSync(CONFIG_PATH, `${CONFIG_PATH}.bak`);
710
+ configBackedUp = true;
711
+ }
712
+
713
+ /** Save a secret: umask 077, tmp file + rename, chmod 600, never echoed. */
714
+ function saveSecret(path, value) {
715
+ const prev = process.umask(0o077);
716
+ try {
717
+ mkdirSync(dirname(path), { recursive: true, mode: 0o700 });
718
+ const tmp = `${path}.tmp-${process.pid}`;
719
+ writeFileSync(tmp, value, { mode: 0o600 });
720
+ chmodSync(tmp, 0o600);
721
+ renameSync(tmp, path);
722
+ } finally {
723
+ process.umask(prev);
724
+ }
725
+ }
726
+
727
+ /** Mirror of the bash wizard's `want`: skip existing files unless --force. */
728
+ async function want(path, label) {
729
+ if (!filePresent(path)) return true;
730
+ if (!FORCE) {
731
+ info(`${label} already present — keeping it (re-run with --force to replace)`);
732
+ return false;
733
+ }
734
+ return await confirm(`${label} exists — replace it?`, false);
735
+ }
736
+
737
+ // ---- read-only Slack calls -------------------------------------------------
738
+
739
+ async function slackCall(method, token, params = {}, httpMethod = "GET") {
740
+ const url = new URL(`https://slack.com/api/${method}`);
741
+ if (httpMethod === "GET")
742
+ for (const [k, v] of Object.entries(params)) url.searchParams.set(k, String(v));
743
+ try {
744
+ const res = await fetch(url, {
745
+ method: httpMethod,
746
+ headers: {
747
+ Authorization: `Bearer ${token}`,
748
+ ...(httpMethod === "POST" ? { "Content-Type": "application/x-www-form-urlencoded" } : {}),
749
+ },
750
+ body: httpMethod === "POST" ? new URLSearchParams(params).toString() : undefined,
751
+ signal: AbortSignal.timeout(15000),
752
+ });
753
+ const data = await res.json();
754
+ return data;
755
+ } catch (err) {
756
+ return {
757
+ ok: false,
758
+ error: `network_error: ${err instanceof Error ? err.message : String(err)}`,
759
+ };
760
+ }
761
+ }
762
+
763
+ const SLACK_ERROR_HELP = {
764
+ invalid_auth:
765
+ "Slack rejected the token outright — it is wrong, revoked, or from another workspace. Copy it again from the app page.",
766
+ not_authed: "no token reached Slack — the paste was probably truncated.",
767
+ account_inactive: "the token belongs to a deactivated app/user.",
768
+ token_revoked: "this token was revoked (re-installing the app revokes the previous bot token).",
769
+ missing_scope:
770
+ "the token is valid but the app lacks a scope — re-check the manifest, then re-install.",
771
+ channel_not_found:
772
+ "no channel with that id is visible to this bot. Wrong id, wrong workspace, or a private channel the bot was never invited to.",
773
+ not_in_channel: "the bot is not a member of that channel — /invite @quickreview there.",
774
+ };
775
+ const explain = (code) => SLACK_ERROR_HELP[code] ?? `Slack said: ${code}`;
776
+
777
+ // ---- step 0 — overview -----------------------------------------------------
778
+
779
+ title("Slack concierge setup");
780
+ info(`config ${CONFIG_PATH}`);
781
+ info(`secrets ${SECRETS_DIR}`);
782
+ if (!VERIFY) info("--no-verify: every Slack API call is skipped (offline run)");
783
+ out();
784
+ out(` ${"slack_bot_token".padEnd(18)}${statusOf(BOT_FILE)}`);
785
+ out(` ${"slack_app_token".padEnd(18)}${statusOf(APP_FILE)}`);
786
+ const current = readSlackValues(configText);
787
+ out();
788
+ info(`[slack] enabled ${current.enabled}`);
789
+ info(`[slack] channel ${current.channel || "(empty)"}`);
790
+ info(`[slack] channel_kind ${current.channel_kind}`);
791
+ info(`[slack] legacy_owner_slack_id ${current.legacy_owner_slack_id || "(empty)"}`);
792
+ info(`[slack.users] ${Object.keys(current.users).length} entries`);
793
+ out();
794
+ para("This wizard collects the two Slack tokens, picks the one channel, builds the");
795
+ para("identity map and patches config.toml. It never deploys, never starts anything,");
796
+ para("and never touches dry_run. Ctrl-C is safe at any point.");
797
+
798
+ // ---- step 1 — create the Slack app ----------------------------------------
799
+
800
+ title("Step 1 — create the Slack app");
801
+ para("Go to https://api.slack.com/apps → “Create New App” → “From an app manifest”");
802
+ para("→ pick the workspace → choose YAML → paste the manifest below → Next → Create.");
803
+ out();
804
+ para("If the app already exists you can skip this; the manifest can be re-applied later");
805
+ para("under the app's “App Manifest” page (a scope change means re-installing, which");
806
+ para("mints a NEW bot token — then re-run this wizard with --force).");
807
+ out();
808
+ out(
809
+ manifestYaml("public")
810
+ .split("\n")
811
+ .map((l) => ` ${l}`)
812
+ .join("\n"),
813
+ );
814
+ para("PRIVATE channel variant: add `groups:history` to the bot scopes and");
815
+ para("`message.groups` to the bot events — otherwise Socket Mode delivers nothing");
816
+ para("from a private channel. Step 4 tells you which one you need.");
817
+ out();
818
+ if (
819
+ await confirm(
820
+ "write the manifest to a file you can open instead of copying from the terminal?",
821
+ true,
822
+ )
823
+ ) {
824
+ const manifestPath = join(REPO, "state", "slack-app-manifest.yaml");
825
+ mkdirSync(dirname(manifestPath), { recursive: true });
826
+ writeFileSync(manifestPath, manifestYaml("public"));
827
+ writeFileSync(join(REPO, "state", "slack-app-manifest-private.yaml"), manifestYaml("private"));
828
+ ok(`wrote ${manifestPath} (and …-private.yaml) — state/ is gitignored`);
829
+ }
830
+ await ask(" press Enter when the app exists … ");
831
+
832
+ // ---- step 2 — bot token ----------------------------------------------------
833
+
834
+ title("Step 2 — the bot token (xoxb-…)");
835
+ para("In the app: OAuth & Permissions → “Install to Workspace” → Allow → copy the");
836
+ para("“Bot User OAuth Token” at the top of that page. It starts with xoxb-.");
837
+ para("This is the token the daemon uses for every Web API call.");
838
+
839
+ let botToken = filePresent(BOT_FILE) ? readFileSync(BOT_FILE, "utf8").trim() : "";
840
+ if (await want(BOT_FILE, "slack_bot_token")) {
841
+ for (;;) {
842
+ const v = await askHidden(
843
+ " paste the bot token (input hidden, Enter to submit; empty to skip): ",
844
+ );
845
+ if (v === "") {
846
+ info("skipped slack_bot_token");
847
+ break;
848
+ }
849
+ const shape = tokenLooksValid("bot", v);
850
+ if (!shape.ok) {
851
+ bad(shape.reason);
852
+ if (exhausted()) break;
853
+ continue;
854
+ }
855
+ if (VERIFY) {
856
+ const res = await slackCall("auth.test", v, {}, "POST");
857
+ if (!res.ok) {
858
+ bad(`auth.test failed — ${explain(res.error)}`);
859
+ if (exhausted()) break;
860
+ continue;
861
+ }
862
+ ok(`auth.test: workspace “${res.team}”, bot user ${res.user} (${res.user_id})`);
863
+ }
864
+ saveSecret(BOT_FILE, v);
865
+ botToken = v;
866
+ ok(`slack_bot_token saved — ${maskToken(v)}`);
867
+ break;
868
+ }
869
+ }
870
+
871
+ // ---- step 3 — app-level token ---------------------------------------------
872
+
873
+ title("Step 3 — the app-level token (xapp-…)");
874
+ para("DIFFERENT token, different page: Basic Information → App-Level Tokens →");
875
+ para("“Generate Token and Scopes” → name it anything → add the scope connections:write");
876
+ para("→ Generate → copy it. It starts with xapp- and is used ONLY to open the socket.");
877
+
878
+ if (await want(APP_FILE, "slack_app_token")) {
879
+ for (;;) {
880
+ const v = await askHidden(
881
+ " paste the app-level token (input hidden, Enter to submit; empty to skip): ",
882
+ );
883
+ if (v === "") {
884
+ info("skipped slack_app_token");
885
+ break;
886
+ }
887
+ const shape = tokenLooksValid("app", v);
888
+ if (!shape.ok) {
889
+ bad(shape.reason);
890
+ if (exhausted()) break;
891
+ continue;
892
+ }
893
+ if (VERIFY) {
894
+ const res = await slackCall("apps.connections.open", v, {}, "POST");
895
+ if (!res.ok) {
896
+ bad(`apps.connections.open failed — ${explain(res.error)}`);
897
+ if (res.error === "missing_scope")
898
+ para("the app-level token needs the connections:write scope");
899
+ if (exhausted()) break;
900
+ continue;
901
+ }
902
+ ok("apps.connections.open: ok — Socket Mode will connect (URL not dialled)");
903
+ }
904
+ saveSecret(APP_FILE, v);
905
+ ok(`slack_app_token saved — ${maskToken(v)}`);
906
+ break;
907
+ }
908
+ }
909
+
910
+ // ---- step 4 — the channel --------------------------------------------------
911
+
912
+ title("Step 4 — the ONE channel (the step people get wrong)");
913
+ para("The concierge lives in exactly one channel. The bot MUST BE INVITED to it:");
914
+ para("without membership Socket Mode delivers nothing, the daemon looks perfectly");
915
+ para("healthy, and it is simply deaf. /invite @quickreview in that channel.");
916
+ out();
917
+ para("Paste the channel ID (C…) or the channel's “Copy link” URL.");
918
+ para("Find the id: channel name → About → scroll to the bottom.");
919
+
920
+ let channel = current.channel;
921
+ let channelName = "";
922
+ let channelKind = current.channel_kind || "public";
923
+
924
+ for (;;) {
925
+ const raw = await ask(` channel id or link${channel ? ` [${channel}]` : ""}: `);
926
+ if (raw === "" && channel) {
927
+ info(`keeping ${channel}`);
928
+ break;
929
+ }
930
+ const parsed = parseChannelId(raw);
931
+ if (!parsed.ok) {
932
+ bad(parsed.reason);
933
+ if (exhausted()) break;
934
+ continue;
935
+ }
936
+ channel = parsed.id;
937
+ if (!VERIFY) {
938
+ channelKind = (await confirm("is that a PRIVATE channel?", channelKind === "private"))
939
+ ? "private"
940
+ : "public";
941
+ ok(`channel ${channel} (${channelKind}) — not verified (--no-verify)`);
942
+ break;
943
+ }
944
+ if (!botToken) {
945
+ bad("no bot token available to verify the channel — skipping the check");
946
+ break;
947
+ }
948
+ let verified = false;
949
+ for (;;) {
950
+ const res = await slackCall("conversations.info", botToken, { channel });
951
+ if (!res.ok) {
952
+ bad(`conversations.info failed — ${explain(res.error)}`);
953
+ break;
954
+ }
955
+ channelName = res.channel?.name ?? "";
956
+ channelKind = res.channel?.is_private ? "private" : "public";
957
+ ok(`#${channelName} — ${channelKind}`);
958
+ if (res.channel?.is_member) {
959
+ ok("the bot IS a member of this channel");
960
+ verified = true;
961
+ break;
962
+ }
963
+ bad("the bot is NOT a member — Socket Mode will deliver NOTHING from here");
964
+ para(`remedy: open #${channelName} in Slack and type: /invite @quickreview`);
965
+ // Spent input ends the re-check: an empty answer would otherwise take
966
+ // the [Y/n] default and poll Slack forever.
967
+ if (exhausted() || !(await confirm("re-check now?", true))) break;
968
+ }
969
+ if (verified || exhausted()) break;
970
+ if (!(await confirm("use a different channel?", false))) break;
971
+ }
972
+
973
+ if (channelKind === "private") {
974
+ out();
975
+ bad("PRIVATE channel — three consequences:");
976
+ para(
977
+ "1. the manifest needs `groups:history` and `groups:read` (bot scope) and `message.groups` (bot event);",
978
+ );
979
+ para("2. applying that manifest means re-installing, which mints a NEW bot token and");
980
+ para(" revokes the current one;");
981
+ para("3. after re-installing, re-run this wizard with --force and redo step 2.");
982
+ }
983
+
984
+ // ---- step 5 — identity map -------------------------------------------------
985
+
986
+ title("Step 5 — the identity map ([slack.users])");
987
+ para("[slack.users] maps Slack member id → GitHub login. It is the ONLY source of");
988
+ para("identity: someone listed here is known by their GitHub login; the owner's id");
989
+ para("must be a key. Slack is outbound-only today — inbound messages are not answered.");
990
+ para("legacy_owner_slack_id is the single tier-M identity and MUST also be a key in the");
991
+ para("map — the daemon refuses to boot otherwise.");
992
+
993
+ const users = new Map(Object.entries(current.users));
994
+ let directory = null;
995
+
996
+ async function loadDirectory() {
997
+ if (directory || !VERIFY || !botToken) return directory;
998
+ const members = [];
999
+ let cursor = "";
1000
+ for (let page = 0; page < 10; page++) {
1001
+ const res = await slackCall("users.list", botToken, {
1002
+ limit: 200,
1003
+ ...(cursor ? { cursor } : {}),
1004
+ });
1005
+ if (!res.ok) {
1006
+ bad(`users.list failed — ${explain(res.error)}`);
1007
+ return null;
1008
+ }
1009
+ for (const m of res.members ?? []) {
1010
+ if (m.deleted || m.is_bot || m.id === "USLACKBOT") continue;
1011
+ members.push({
1012
+ id: m.id,
1013
+ name: m.profile?.real_name || m.real_name || m.name || m.id,
1014
+ handle: m.name ?? "",
1015
+ });
1016
+ }
1017
+ cursor = res.response_metadata?.next_cursor ?? "";
1018
+ if (!cursor) break;
1019
+ }
1020
+ directory = members;
1021
+ return directory;
1022
+ }
1023
+
1024
+ /** Ask for one Slack member id: by directory search or a pasted U…. */
1025
+ async function askSlackId(label) {
1026
+ for (;;) {
1027
+ const dir = await loadDirectory();
1028
+ const hint = dir ? "type part of a name to search, or paste a U… id" : "paste the U… id";
1029
+ const raw = await ask(` ${label} (${hint}, empty to stop): `);
1030
+ if (raw === "") return null;
1031
+ const parsed = parseUserId(raw);
1032
+ if (parsed.ok) return parsed.id;
1033
+ if (!dir) {
1034
+ bad(parsed.reason);
1035
+ if (exhausted()) return null;
1036
+ continue;
1037
+ }
1038
+ const needle = raw.toLowerCase();
1039
+ const hits = dir
1040
+ .filter(
1041
+ (m) => m.name.toLowerCase().includes(needle) || m.handle.toLowerCase().includes(needle),
1042
+ )
1043
+ .slice(0, 15);
1044
+ if (hits.length === 0) {
1045
+ bad(`no member matches “${raw}”`);
1046
+ if (exhausted()) return null;
1047
+ continue;
1048
+ }
1049
+ hits.forEach((m, i) =>
1050
+ out(` ${String(i + 1).padStart(2)}. ${m.id} — ${m.name} (@${m.handle})`),
1051
+ );
1052
+ const pick = await ask(" number (Enter to search again): ");
1053
+ const idx = Number.parseInt(pick, 10);
1054
+ if (Number.isInteger(idx) && idx >= 1 && idx <= hits.length) return hits[idx - 1].id;
1055
+ if (exhausted()) return null;
1056
+ }
1057
+ }
1058
+
1059
+ async function askLogin(forId) {
1060
+ for (;;) {
1061
+ const login = await ask(` GitHub login for ${forId}: `);
1062
+ if (login === "") return null;
1063
+ if (looksLikeGithubLogin(login)) return login;
1064
+ bad("that does not look like a GitHub login (letters/digits and single hyphens, ≤ 39 chars)");
1065
+ if (exhausted()) return null;
1066
+ }
1067
+ }
1068
+
1069
+ out();
1070
+ para("First: your own identity (tier-M).");
1071
+ let legacyOwnerSlackId = current.legacy_owner_slack_id;
1072
+ {
1073
+ const id = await askSlackId(
1074
+ `your Slack member id${legacyOwnerSlackId ? ` [${legacyOwnerSlackId}]` : ""}`,
1075
+ );
1076
+ if (id) legacyOwnerSlackId = id;
1077
+ if (legacyOwnerSlackId) {
1078
+ const existing = users.get(legacyOwnerSlackId);
1079
+ const login =
1080
+ existing && !FORCE ? existing : ((await askLogin(legacyOwnerSlackId)) ?? existing);
1081
+ if (login) {
1082
+ users.delete(legacyOwnerSlackId);
1083
+ const rest = [...users.entries()];
1084
+ users.clear();
1085
+ users.set(legacyOwnerSlackId, login);
1086
+ for (const [k, v] of rest) users.set(k, v);
1087
+ ok(`${legacyOwnerSlackId} → ${login} (tier-M)`);
1088
+ } else {
1089
+ bad("no GitHub login — legacy_owner_slack_id must be a key in [slack.users] or boot fails");
1090
+ }
1091
+ }
1092
+ }
1093
+
1094
+ while (!exhausted() && (await confirm("add a teammate?", false))) {
1095
+ const id = await askSlackId("their Slack member id");
1096
+ if (!id) break;
1097
+ const login = await askLogin(id);
1098
+ if (!login) break;
1099
+ users.set(id, login);
1100
+ ok(`${id} → ${login}`);
1101
+ }
1102
+
1103
+ // ---- step 6 — patch config.toml -------------------------------------------
1104
+
1105
+ title("Step 6 — write config.toml");
1106
+ const values = {
1107
+ channel,
1108
+ channel_kind: channelKind,
1109
+ legacy_owner_slack_id: legacyOwnerSlackId,
1110
+ users,
1111
+ channelName,
1112
+ };
1113
+ out(renderSlackValues(values));
1114
+ const patched = patchConfigToml(configText, values);
1115
+ out();
1116
+ if (patched === configText) {
1117
+ info("config.toml already says exactly this — nothing to write");
1118
+ } else {
1119
+ out(diffLines(configText, patched, 2));
1120
+ out();
1121
+ para("Only these lines change. Comments, [slack.policy], [slack.policy.causes] and");
1122
+ para("`enabled` are untouched.");
1123
+ if (await confirm("apply this patch?", true)) {
1124
+ backupConfigOnce();
1125
+ const tmp = `${CONFIG_PATH}.tmp-${process.pid}`;
1126
+ writeFileSync(tmp, patched);
1127
+ renameSync(tmp, CONFIG_PATH);
1128
+ ok(`config.toml written (backup: ${CONFIG_PATH}.bak)`);
1129
+ } else {
1130
+ info("config.toml left alone");
1131
+ }
1132
+ }
1133
+
1134
+ // ---- step 7 — enabling -----------------------------------------------------
1135
+
1136
+ title("Step 7 — enabling the concierge");
1137
+ para("`enabled = true` is a deliberate act: with it on, a missing token file is a HARD");
1138
+ para("startup error, never a silent read-only mode. And flipping it here changes only");
1139
+ para("your laptop's config — the VM still runs the old one until you deploy.");
1140
+ const nowText = readFileSync(CONFIG_PATH, "utf8");
1141
+ if (readSlackValues(nowText).enabled) {
1142
+ info("[slack] enabled is already true");
1143
+ } else if (await confirm("set enabled = true now?", false)) {
1144
+ const flipped = enableSlack(nowText);
1145
+ backupConfigOnce();
1146
+ const tmp = `${CONFIG_PATH}.tmp-${process.pid}`;
1147
+ writeFileSync(tmp, flipped);
1148
+ renameSync(tmp, CONFIG_PATH);
1149
+ ok("enabled = true");
1150
+ } else {
1151
+ info("left disabled — re-run this wizard (or edit the one line) when you are ready");
1152
+ }
1153
+
1154
+ // ---- step 8 — final check --------------------------------------------------
1155
+
1156
+ title("Step 8 — boot readiness (the same conditions the daemon checks)");
1157
+ const finalText = readFileSync(CONFIG_PATH, "utf8");
1158
+ const finalValues = readSlackValues(finalText);
1159
+ const checks = finalChecks({
1160
+ ...finalValues,
1161
+ botTokenOk: filePresent(BOT_FILE),
1162
+ appTokenOk: filePresent(APP_FILE),
1163
+ });
1164
+ for (const c of checks) {
1165
+ if (c.ok) ok(c.label);
1166
+ else {
1167
+ bad(c.label);
1168
+ para(c.hint);
1169
+ }
1170
+ }
1171
+ out();
1172
+ if (checks.every((c) => c.ok)) {
1173
+ ok("Slack setup is complete.");
1174
+ } else {
1175
+ bad("not ready yet — re-run this wizard to fill the gaps.");
1176
+ }
1177
+ out();
1178
+ para("This wizard does NOT deploy and does NOT start anything. The VM daemon is");
1179
+ para("intentionally stopped. When you are ready, ship the config home with a release:");
1180
+ out();
1181
+ out(` ${bold("./scripts/deploy.sh release <version>")}`);
1182
+ out();
1183
+
1184
+ rl.close();
1185
+ }
1186
+ // RUNTIME-END
1187
+
1188
+ const invokedDirectly =
1189
+ process.argv[1] !== undefined && resolve(process.argv[1]) === fileURLToPath(import.meta.url);
1190
+ if (invokedDirectly) await main();