@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
package/src/usage.ts ADDED
@@ -0,0 +1,1154 @@
1
+ // Round usage measurement from pi session JSONLs. Verdict files
2
+ // self-report spend_usd but the models copy the template's example figure, so
3
+ // real accounting reads the session store instead: per-session dirs at
4
+ // <root>/<cfg.pi.session_dir>/<session>/*.jsonl. Lines are JSON records; the
5
+ // interesting ones are {type:"message", timestamp, message:{role, usage:{input,
6
+ // output, ...}}} (assistant messages carry usage) and model_change records
7
+ // {provider, modelId} which set the attribution for subsequent messages.
8
+ //
9
+ // pi's NATIVE subagent children run without a saved session (or in a temp
10
+ // session dir removed when they exit), so they leave no transcript anywhere
11
+ // the walk reads; counting the main session alone undercounts a round many
12
+ // times over. Their usage IS in the parent's transcript: the `subagent` / `launch_plan`
13
+ // (or `lens` / `lens_wave`, packages/pi-plugin/src/lensresult.ts) tool result carries
14
+ // `details.results[]`, each child's model and its summed `usage` (input,
15
+ // output, cacheRead, cost — native runSingleAgent). Each child counts there,
16
+ // once (`childUsage`), surfaced via `children_included`. A lens-ledger line
17
+ // (`lens-ledger.jsonl` in the session dir) is read the same way, and a lens
18
+ // run that carries an `id` counts once however many results and ledger lines
19
+ // repeat it; a warm-up session, which only the ledger records, counts too.
20
+ //
21
+ // This file owns WHAT a transcript line contributes — its usage and its
22
+ // exec-policy audit items (`parseTranscriptLine`) — and how contributions add
23
+ // up (`addLineUsage`). READING the transcripts is `transcriptindex.ts`: async,
24
+ // chunked, each line parsed once for both consumers, each byte read
25
+ // once per daemon lifetime. Everything here is pure: malformed lines are
26
+ // skipped, never thrown.
27
+ // The guard's TOKENISER — not its policy. The rules below stay an
28
+ // independent implementation on purpose (see execViolationKind).
29
+ import {
30
+ isLensTool,
31
+ ledgerLineFrom,
32
+ lensIdOf,
33
+ type LensLedgerLine,
34
+ } from "@quickchatai/pi-quickreview/src/lensresult.js";
35
+ import {
36
+ normalizeRedirections,
37
+ opensUnmodelledQuoting,
38
+ redirectTargets,
39
+ sedWords,
40
+ splitShellSegments,
41
+ } from "@quickchatai/pi-quickreview/extensions/bash-guard.js";
42
+
43
+ export interface ModelUsage {
44
+ in: number;
45
+ out: number;
46
+ }
47
+
48
+ export interface RoundUsage {
49
+ tokens_in: number;
50
+ /** Output tokens INCLUDING reasoning tokens (pi reports them separately). */
51
+ tokens_out: number;
52
+ tokens_cache_read: number;
53
+ /** Sum of pi's own per-record usage.cost.total (USD) — the primary cost
54
+ * source, verified live on the VM. Null when no record in the window
55
+ * carried a cost object. */
56
+ cost_usd: number | null;
57
+ models: Record<string, ModelUsage>;
58
+ /** True when at least one global-store (pass/subagent) file matched. */
59
+ passes_included: boolean;
60
+ /** True when at least one child's usage counted from a subagent or
61
+ * launch_plan tool result. */
62
+ children_included: boolean;
63
+ }
64
+
65
+ /** The zero a round's usage starts from. */
66
+ export function emptyRoundUsage(): RoundUsage {
67
+ return {
68
+ tokens_in: 0,
69
+ tokens_out: 0,
70
+ tokens_cache_read: 0,
71
+ cost_usd: null,
72
+ models: {},
73
+ passes_included: false,
74
+ children_included: false,
75
+ };
76
+ }
77
+
78
+ interface JsonlRecord {
79
+ type?: unknown;
80
+ timestamp?: unknown;
81
+ provider?: unknown;
82
+ modelId?: unknown;
83
+ message?: {
84
+ role?: unknown;
85
+ toolName?: unknown;
86
+ details?: { results?: unknown };
87
+ // Live-verified shape (VM): {input, output, cacheRead, cacheWrite,
88
+ // reasoning, totalTokens, cost: {input, output, cacheRead, cacheWrite, total}}.
89
+ usage?: {
90
+ input?: unknown;
91
+ output?: unknown;
92
+ cacheRead?: unknown;
93
+ reasoning?: unknown;
94
+ cost?: { total?: unknown };
95
+ };
96
+ };
97
+ [k: string]: unknown;
98
+ }
99
+
100
+ /** An ISO string or epoch ms; anything else is no timestamp. */
101
+ export function parseTs(v: unknown): number | null {
102
+ if (typeof v === "number" && Number.isFinite(v)) return v;
103
+ if (typeof v !== "string") return null;
104
+ const ms = Date.parse(v);
105
+ return Number.isNaN(ms) ? null : ms;
106
+ }
107
+
108
+ function num(v: unknown): number {
109
+ return typeof v === "number" && Number.isFinite(v) ? v : 0;
110
+ }
111
+
112
+ /** The model attribution a file starts with, before any model_change. */
113
+ export const UNKNOWN_MODEL = "unknown";
114
+
115
+ /** One assistant message's usage, attributed to the model in effect. */
116
+ export interface LineUsage {
117
+ model: string;
118
+ tin: number;
119
+ /** output + reasoning — reasoning is output we paid for. */
120
+ tout: number;
121
+ cache: number;
122
+ /** pi's own `usage.cost.total`, when the record carries a finite one. */
123
+ cost: number | null;
124
+ /** A lens child's run id (LensResult v1), when it carries one: the key the
125
+ * round counts it once by. */
126
+ lensId?: string;
127
+ }
128
+
129
+ /** What one transcript line contributes to the round's two measures. A line
130
+ * that contributes to neither is not represented at all. */
131
+ export interface LineContribution {
132
+ /** The record's top-level timestamp — the round-window filter for a
133
+ * session-dir line. Null when it has none (such a line never counts in a
134
+ * window, and counts in a whole-file read). */
135
+ ts: number | null;
136
+ usage?: LineUsage;
137
+ /** Each lens child's usage, from a subagent / launch_plan tool result. */
138
+ childUsage?: LineUsage[];
139
+ /** Its exec-policy audit items, in the order the audit meets them. */
140
+ audit?: ExecViolation[];
141
+ }
142
+
143
+ /**
144
+ * Parse one transcript line — ONCE, for both consumers. `model` is
145
+ * the attribution in effect before the line; the result carries the one in
146
+ * effect after it (a `modelId` record re-keys attribution for everything after
147
+ * it, including an assistant message on the same line).
148
+ *
149
+ * The rules: for usage, a non-object record contributes nothing, only an
150
+ * assistant message with a usage object counts, and a finite
151
+ * `usage.cost.total` is the primary cost; for the audit (as
152
+ * `auditExecViolationDetails`), any value JSON.parse returns is walked, and
153
+ * the window reads its top-level `timestamp`.
154
+ */
155
+ export function parseTranscriptLine(
156
+ line: string,
157
+ model: string,
158
+ ): { model: string; contribution: LineContribution | null } {
159
+ const trimmed = line.trim();
160
+ if (!trimmed) return { model, contribution: null };
161
+ let value: unknown;
162
+ try {
163
+ value = JSON.parse(trimmed);
164
+ } catch {
165
+ return { model, contribution: null }; // malformed line — skipped, never thrown
166
+ }
167
+ // A JSON `null` record, like any value without a `timestamp`, reads as no
168
+ // timestamp.
169
+ const ts = value === null ? null : parseTs((value as { timestamp?: unknown }).timestamp);
170
+ let usage: LineUsage | undefined;
171
+ let childUsage: LineUsage[] = [];
172
+ if (typeof value === "object" && value !== null) {
173
+ const rec = value as JsonlRecord;
174
+ // model_change records re-key attribution for everything after them.
175
+ if (typeof rec.modelId === "string" && rec.modelId.length > 0) {
176
+ model =
177
+ typeof rec.provider === "string" && rec.provider.length > 0
178
+ ? `${rec.provider}/${rec.modelId}`
179
+ : rec.modelId;
180
+ }
181
+ usage = assistantUsage(rec, model);
182
+ const ledger = ledgerLineFrom(rec);
183
+ childUsage = ledger !== null ? [ledgerUsageOf(ledger)] : childUsageOf(rec);
184
+ }
185
+ const audit = auditItemsOf(value);
186
+ if (usage === undefined && audit.length === 0 && childUsage.length === 0)
187
+ return { model, contribution: null };
188
+ return {
189
+ model,
190
+ contribution: {
191
+ ts,
192
+ ...(usage !== undefined ? { usage } : {}),
193
+ ...(childUsage.length > 0 ? { childUsage } : {}),
194
+ ...(audit.length > 0 ? { audit } : {}),
195
+ },
196
+ };
197
+ }
198
+
199
+ /** A child's model without its `:<thinking>` suffix (the pricing table's key). */
200
+ function childModel(model: unknown): string {
201
+ return typeof model === "string" && model ? model.replace(/:[a-z]+$/, "") : UNKNOWN_MODEL;
202
+ }
203
+
204
+ /** What one lens-ledger line contributes: its run's usage, keyed by its id. */
205
+ function ledgerUsageOf(line: LensLedgerLine): LineUsage {
206
+ return {
207
+ model: childModel(line.model),
208
+ tin: line.usage.input,
209
+ tout: line.usage.output,
210
+ cache: line.usage.cacheRead,
211
+ cost: line.usage.cost,
212
+ lensId: line.id,
213
+ };
214
+ }
215
+
216
+ /** Each child's usage in a lens tool result (`subagent`, `launch_plan`, `lens`,
217
+ * `lens_wave` — the tmux bot's spellings and the engine's), attributed to
218
+ * the child's model without its `:<thinking>` suffix (the pricing table's
219
+ * key). A result's `usage` is the child's sum over its turns — input, output,
220
+ * cacheRead, and `cost` as a NUMBER (the sum of each turn's cost.total); seen in
221
+ * production on `lens` and `lens_wave` results at pi 1.3.0. The older spellings
222
+ * survive only in archived transcripts. */
223
+ function childUsageOf(rec: JsonlRecord): LineUsage[] {
224
+ if (rec.type !== "message") return [];
225
+ const msg = rec.message;
226
+ if (typeof msg !== "object" || msg === null || msg.role !== "toolResult") return [];
227
+ if (!isLensTool(msg.toolName)) return [];
228
+ const results = msg.details?.results;
229
+ if (!Array.isArray(results)) return [];
230
+ const out: LineUsage[] = [];
231
+ for (const r of results) {
232
+ if (typeof r !== "object" || r === null) continue;
233
+ const { usage, model } = r as { usage?: Record<string, unknown>; model?: unknown };
234
+ if (typeof usage !== "object" || usage === null) continue;
235
+ const cost = usage.cost;
236
+ const lensId = lensIdOf(r);
237
+ out.push({
238
+ model: childModel(model),
239
+ tin: num(usage.input),
240
+ tout: num(usage.output),
241
+ cache: num(usage.cacheRead),
242
+ cost: typeof cost === "number" && Number.isFinite(cost) ? cost : null,
243
+ ...(lensId !== null ? { lensId } : {}),
244
+ });
245
+ }
246
+ return out;
247
+ }
248
+
249
+ function assistantUsage(rec: JsonlRecord, model: string): LineUsage | undefined {
250
+ if (rec.type !== "message") return undefined;
251
+ const msg = rec.message;
252
+ if (typeof msg !== "object" || msg === null) return undefined;
253
+ if (msg.role !== "assistant") return undefined;
254
+ const usage = msg.usage;
255
+ if (typeof usage !== "object" || usage === null) return undefined;
256
+ const costTotal = usage.cost && typeof usage.cost === "object" ? usage.cost.total : undefined;
257
+ return {
258
+ model,
259
+ tin: num(usage.input),
260
+ tout: num(usage.output) + num(usage.reasoning), // reasoning is output we paid for
261
+ cache: num(usage.cacheRead),
262
+ cost: typeof costTotal === "number" && Number.isFinite(costTotal) ? costTotal : null,
263
+ };
264
+ }
265
+
266
+ /** Add one in-window assistant message to the round's usage — in file order,
267
+ * so the floating-point sums (which are order-sensitive) come out the same
268
+ * bit for bit however the transcripts are read. */
269
+ export function addLineUsage(acc: RoundUsage, u: LineUsage): void {
270
+ if (u.cost !== null) acc.cost_usd = (acc.cost_usd ?? 0) + u.cost; // pi's own accounting — primary
271
+ if (u.tin === 0 && u.tout === 0 && u.cache === 0) return;
272
+ acc.tokens_in += u.tin;
273
+ acc.tokens_out += u.tout;
274
+ acc.tokens_cache_read += u.cache;
275
+ const m = (acc.models[u.model] ??= { in: 0, out: 0 });
276
+ m.in += u.tin;
277
+ m.out += u.tout;
278
+ }
279
+
280
+ // ---- pricing ---------------------------------------------------------------
281
+
282
+ export interface ModelPricing {
283
+ input_per_mtok: number;
284
+ output_per_mtok: number;
285
+ }
286
+
287
+ /** USD estimate over per-model token counts. Returns null when any model in
288
+ * play has no price entry — an honest "unknown" beats a silent undercount.
289
+ * Lookup tolerates the provider prefix: "openai-codex/gpt-x" matches either
290
+ * the full key or a bare "gpt-x" pricing entry. */
291
+ export function estimateUsd(
292
+ models: Record<string, ModelUsage>,
293
+ pricing: Record<string, ModelPricing>,
294
+ ): number | null {
295
+ let usd = 0;
296
+ for (const [model, usage] of Object.entries(models)) {
297
+ const bare = model.includes("/") ? model.slice(model.lastIndexOf("/") + 1) : model;
298
+ const price = pricing[model] ?? pricing[bare];
299
+ if (!price) return null;
300
+ usd +=
301
+ (usage.in / 1_000_000) * price.input_per_mtok +
302
+ (usage.out / 1_000_000) * price.output_per_mtok;
303
+ }
304
+ return usd;
305
+ }
306
+
307
+ // ---- exec-policy audit -----------------------------------------------------
308
+
309
+ /**
310
+ * The post-hoc audit's vocabulary. Interpreters alone are not enough: chains
311
+ * such as `gh pr review --approve`, `gh api … --input`,
312
+ * `gh api -fevent=APPROVE`, `git -c alias.x=!cmd x`,
313
+ * `git --git-dir=<dir> diff` and `HOME=<dir> git diff` execute or POST
314
+ * without one, so each class below has its own kind.
315
+ *
316
+ * What this is and is not. It is TELEMETRY: a durable event and an overseer
317
+ * line, not a control. It is deliberately an INDEPENDENT implementation rather
318
+ * than a call into `packages/pi-plugin/extensions/bash-guard.ts` — a shared implementation shares
319
+ * its blind spots, and the point of a second reader is that it fails
320
+ * differently. It is coarse and high-recall by design: a false line costs an
321
+ * operator ten seconds, a missing line costs the incident.
322
+ *
323
+ * It cannot see what leaves no recognisable spelling. That bound is real and
324
+ * is why this is the third layer and not the second: the config-scope pin
325
+ * (`sessionGitConfigPins`) and the write-boundary veto (`checkWritePath`) are
326
+ * what make the innocent-command form impossible rather than merely visible.
327
+ */
328
+ export type ExecViolationKind =
329
+ | "interpreter"
330
+ | "github_write"
331
+ | "git_write"
332
+ | "git_config_injection"
333
+ | "git_config_surface_write"
334
+ /** A read-only-allowlisted program (awk/sed/sort/find) used in a write or
335
+ * exec mode, and git's read verbs in theirs: `--output=<file>` (the diff
336
+ * options' file write) and `git grep -O<cmd>`. */
337
+ | "reader_write_or_exec"
338
+ /** A write landing on THIS system's own policy surface — config.toml,
339
+ * scripts/, dist/, extensions/, prompts/agents/seeds, .pi/. The
340
+ * one-level-out analogue of `git_config_surface_write`. */
341
+ | "policy_surface_write"
342
+ /** A write landing on a MEMORY-SCOPE file — the recall hint
343
+ * (`recall-hints/<session>.json`) or the retired list
344
+ * (`retired-uris.json`) a session's own memory recall reads.
345
+ * Writing either widens what that recall may reach. */
346
+ | "memory_scope_write"
347
+ /** A write landing on a WAKE-DELIVERY file — an inject dir, the inject
348
+ * bridge's `.done/`, or a wake file by its name. The daemon reads a wake's
349
+ * move into `.done/` as "this turn is running". */
350
+ | "delivery_surface_write"
351
+ /** A session env-prefix that relocates this system's policy inputs
352
+ * (`QCR_CONFIG=` and kin), at the top level or laundered inside a
353
+ * `bash -c '…'` payload. */
354
+ | "policy_relocation";
355
+
356
+ /** Interpreters. */
357
+ const EXEC_VIOLATION_RE =
358
+ /\b(?:python3?|pytest|uv|npm|npx|node|make|pip3?|poetry|cargo|go (?:run|test)|[gmn]?awk|perl|ruby|php)\b/;
359
+
360
+ /** A `gh api` call that will not be a GET: an explicit mutating method, or any
361
+ * body-carrying flag (gh promotes GET→POST when a body is present — the
362
+ * `--input` form is the one the predecessor used for every review it posted). */
363
+ const GH_API_WRITE_RE =
364
+ /\bgh\s+(?:-\S+\s+)*api\b[^\n]*?(?:-X\s*(?:POST|PATCH|PUT|DELETE)|--method[=\s]+(?:POST|PATCH|PUT|DELETE)|--input\b|--input=|--field\b|--field=|--raw-field\b|--raw-field=|(?:^|\s)-[A-Za-z]*[fF](?:\s|=|[A-Za-z_]+=))/i;
365
+
366
+ /** An explicit `-X`/`--method` on a `gh api` call. As in the guard's
367
+ * `ghApiEffectiveMethod`, the explicit method WINS — a body flag only promotes
368
+ * gh's default GET — so `gh api search/issues --method GET -f q=…` is a read,
369
+ * and the LAST explicit method is the one gh sends. A quoted method
370
+ * (`--method "GET"`) is the same token to the guard's tokenizer. */
371
+ const GH_API_EXPLICIT_METHOD_RE = /(?:^|\s)(?:-X\s*|--method[=\s]+)['"]?([A-Za-z]+)/gi;
372
+
373
+ /** Does this `gh api` segment send something other than GET/HEAD? */
374
+ function ghApiWrites(segment: string): boolean {
375
+ if (!GH_API_WRITE_RE.test(segment)) return false;
376
+ const api = /\bgh\s+(?:-\S+\s+)*api\b/.exec(segment);
377
+ const args = api ? segment.slice(api.index + api[0].length) : segment;
378
+ let explicit: string | null = null;
379
+ for (const m of args.matchAll(GH_API_EXPLICIT_METHOD_RE)) explicit = m[1]!.toUpperCase();
380
+ return explicit === null || (explicit !== "GET" && explicit !== "HEAD");
381
+ }
382
+
383
+ /** A `gh` subcommand that is not one of the read verbs. Expressed as the
384
+ * complement of the read set rather than as a list of write verbs, so a verb
385
+ * `gh` grows tomorrow is audited by default instead of being invisible until
386
+ * someone remembers it. */
387
+ const GH_SUBCOMMAND_RE = /\bgh\s+(?:-\S+\s+)*([a-z-]+)(?:\s+(?:-\S+\s+)*([a-z-]+))?/;
388
+ const GH_AUDIT_READ_NAMESPACES = new Set(["api", "search", "status", "version", "help", "auth"]);
389
+ const GH_AUDIT_READ_VERBS = new Set([
390
+ "view",
391
+ "list",
392
+ "diff",
393
+ "checks",
394
+ "status",
395
+ "get-url",
396
+ "download",
397
+ ]);
398
+
399
+ /** A write reaching GitHub by some route other than `gh` — the shape a fifth
400
+ * channel would take. `curl`/`wget` are not on the guard's allowlist, so this
401
+ * fires only for something that already got past it. A method or a request
402
+ * body is required: `gh api repos/o/n/pulls/5/reviews` is a legitimate GET and
403
+ * must not be audited as a write. */
404
+ const GITHUB_DIRECT_WRITE_RE =
405
+ /(?:api\.github\.com[^\n]*?(?:-X\s*(?:POST|PATCH|PUT|DELETE)|--request[=\s]+(?:POST|PATCH|PUT|DELETE)|(?:^|\s)(?:-d|--data|--data-raw|--data-binary|--json)\b)|(?:-X\s*(?:POST|PATCH|PUT|DELETE)|--request[=\s]+(?:POST|PATCH|PUT|DELETE))[^\n]*api\.github\.com)/i;
406
+
407
+ /** `git` verbs that write. Plain reads (`git diff`, `git log`, `git show`)
408
+ * must NOT match — the audit runs on every round and a read-shaped false line
409
+ * every time would train the operator to ignore the whole event. */
410
+ const GIT_WRITE_RE =
411
+ /\bgit\s+(?:-\S+\s+|-[cC]\s+\S+\s+)*(?:push|send-pack|commit|merge|rebase|reset|revert|cherry-pick|am|apply|checkout|switch|restore|clean|stash|init|clone|update-ref|update-index|symbolic-ref|filter-branch|fast-import|gc|prune|notes|mv|rm|add)\b/;
412
+
413
+ /** Anything that changes WHICH CONFIG GIT READS, or names a program for it to
414
+ * run. Both the option forms and their environment-prefix twins: either one
415
+ * alone is bypassed by the other. */
416
+ const GIT_CONFIG_INJECTION_RE =
417
+ /(?:\bgit\s+(?:-\S+\s+)*-c\s|--config-env[=\s]|--git-dir[=\s]|--work-tree[=\s]|--exec-path[=\s]|--upload-pack[=\s]|--receive-pack[=\s]|(?:^|[\s;&|(])(?:GIT_CONFIG[A-Z0-9_]*|GIT_DIR|GIT_COMMON_DIR|GIT_WORK_TREE|GIT_EXEC_PATH|GIT_EXTERNAL_DIFF|GIT_PAGER|PAGER|GIT_SSH|GIT_SSH_COMMAND|GIT_ASKPASS|GIT_EDITOR|GIT_SEQUENCE_EDITOR|GIT_PROXY_COMMAND|GIT_TEMPLATE_DIR|HOME|XDG_CONFIG_HOME|LD_PRELOAD|LD_AUDIT|BASH_ENV|ENV|PATH|SHELL|IFS|NODE_OPTIONS|PYTHONSTARTUP|PERL5OPT)=)/;
418
+
419
+ /**
420
+ * A write landing on git's configuration surface — the class no command guard
421
+ * can see from the command that EXPLOITS it, because that command is a plain
422
+ * `git diff`. The write itself, however, is right there in the transcript, and
423
+ * it is visible whether it came from bash or from the write TOOL (see
424
+ * `writeTargetsIn`). This is the audit's only genuinely enumeration-free rule:
425
+ * it keys on git's own documented config locations, not on an attack.
426
+ */
427
+ const GIT_CONFIG_SURFACE_PATH_RE = /(?:^|\/)(?:\.git\/|\.gitconfig$|git\/config$|\.gitattributes$)/;
428
+
429
+ /** The operators that WRITE the word after them: a redirection (`>`, `>>`,
430
+ * every other spelling folded onto those by `normalizeRedirections`) and the
431
+ * diff options' `--output=<file>` / `--output <file>`, which `git log`,
432
+ * `git show` and `git diff` write into (the guard refuses it; this is what
433
+ * makes a write that got past it visible). */
434
+ const WRITE_OPERATOR = String.raw`(?:>>?|--output[=\s])\s*`;
435
+
436
+ /** The same surface as a bash WRITE: a redirection target, or `sed -i`'s. A
437
+ * bare mention is not enough — `git show HEAD:.gitattributes` is a legitimate
438
+ * read of a file the PR touched, and auditing it as a config write would be
439
+ * the kind of routine false line that teaches an operator to skip the event. */
440
+ const GIT_CONFIG_SURFACE_WRITE_RE =
441
+ /(?:(?:>>?|--output[=\s])\s*\S*(?:\.git\/\S*|\.gitconfig|git\/config|\.gitattributes)|\bsed\s+(?:-\S+\s+)*-[a-zA-Z]*i\S*(?:\s+\S+)*?\s+\S*(?:\.git\/\S*|\.gitconfig|git\/config|\.gitattributes))/;
442
+
443
+ /**
444
+ * A write landing on THIS system's own policy surface — the same
445
+ * SHAPE as `GIT_CONFIG_SURFACE_WRITE_RE`, one level out: a redirection or a
446
+ * `sed -i` whose target is `config.toml`, an agent-context file
447
+ * (`AGENTS.md`/`AGENTS.override.md`/`CLAUDE.md` and their `.MD` spellings —
448
+ * the guard's `POLICY_SURFACE_FILES`), `scripts/`, `dist/`, `extensions/`
449
+ * or a frozen-seed dir. A bare mention is not enough — a review session greps
450
+ * and reads these paths all day, and auditing a read would be the routine false
451
+ * line that teaches an operator to skip the event. Mirrors `isPolicySurface` in
452
+ * the guard, kept an independent implementation on purpose. */
453
+ const POLICY_SURFACE_FILES = [
454
+ "config.toml",
455
+ "qcr-profile-write.json",
456
+ ".qcr-profile-write.json.tmp",
457
+ "AGENTS.override.md",
458
+ "AGENTS.MD",
459
+ "AGENTS.md",
460
+ "CLAUDE.MD",
461
+ "CLAUDE.md",
462
+ // a whole path, not a bare name: the review core's export map
463
+ "packages/pi-plugin/package.json",
464
+ ] as const;
465
+ const POLICY_SURFACE_DIRS = [
466
+ "scripts",
467
+ "dist",
468
+ "extensions",
469
+ "prompts",
470
+ "agents",
471
+ "seeds",
472
+ ".pi",
473
+ ] as const;
474
+ /** The names above as one regex alternation — the one vocabulary the shell
475
+ * rule, the write-tool path rule and the pattern expansion below all read. */
476
+ const reAlt = (names: readonly string[]): string =>
477
+ names.map((n) => n.replace(/[.*+?^${}()|[\]\\/]/g, "\\$&")).join("|");
478
+ const POLICY_FILES_ALT = reAlt(POLICY_SURFACE_FILES);
479
+ const POLICY_DIRS_ALT = reAlt(POLICY_SURFACE_DIRS);
480
+ const POLICY_SURFACE_TARGET = String.raw`(?:\S*\/)?(?:(?:${POLICY_FILES_ALT})|(?:${POLICY_DIRS_ALT})\/\S+)`;
481
+ const POLICY_SURFACE_WRITE_RE = new RegExp(
482
+ String.raw`(?:` +
483
+ WRITE_OPERATOR +
484
+ POLICY_SURFACE_TARGET +
485
+ String.raw`|\bsed\s+(?:-\S+\s+)*-[a-zA-Z]*i\S*(?:\s+\S+)*?\s+` +
486
+ POLICY_SURFACE_TARGET +
487
+ String.raw`)`,
488
+ );
489
+
490
+ /** The same policy surface as a WRITE-TOOL target path: `config.toml`
491
+ * or an agent-context file at any depth, or anything under scripts/dist/extensions/prompts/agents/seeds/.pi
492
+ * (the built `state/agents/…` included — `agents/` follows a slash). */
493
+ const POLICY_SURFACE_PATH_RE = new RegExp(
494
+ String.raw`(?:^|\/)(?:${POLICY_FILES_ALT})$|(?:^|\/)(?:${POLICY_DIRS_ALT})\/`,
495
+ );
496
+
497
+ /**
498
+ * A write landing on a MEMORY-SCOPE file — the same SHAPE again:
499
+ * a redirection or a `sed -i` whose target is the recall hint dir
500
+ * (`recall-hints/`) or the retired list (`retired-uris.json`), at any prefix.
501
+ * A review session never writes either; the daemon does, every round. Mirrors
502
+ * `isMemoryScopeSurface` in the guard, kept an independent implementation on
503
+ * purpose.
504
+ */
505
+ const MEMORY_SCOPE_TARGET = String.raw`(?:\S*\/)?(?:recall-hints(?:\/\S*)?|retired-uris\.json(?:\.tmp-\S*)?)(?=[\s;&|()<>]|$)`;
506
+ const MEMORY_SCOPE_WRITE_RE = new RegExp(
507
+ String.raw`(?:` +
508
+ WRITE_OPERATOR +
509
+ MEMORY_SCOPE_TARGET +
510
+ String.raw`|\bsed\s+(?:-\S+\s+)*-[a-zA-Z]*i\S*(?:\s+\S+)*?\s+` +
511
+ MEMORY_SCOPE_TARGET +
512
+ String.raw`)`,
513
+ );
514
+
515
+ /** The same memory-scope files as a WRITE-TOOL target path: the hint dir and
516
+ * anything in it, the retired list and its atomic-write temp — the guard's
517
+ * shapes, so the audit flags exactly what the guard refuses (a
518
+ * `docs/recall-hints.md` or a `retired-uris.json.bak` is neither). */
519
+ const MEMORY_SCOPE_PATH_RE = /(?:^|\/)(?:recall-hints(?:\/|$)|retired-uris\.json(?:\.tmp-[^/]*)?$)/;
520
+
521
+ /**
522
+ * A write landing on a WAKE-DELIVERY file — the same SHAPE once more: a
523
+ * redirection or a `sed -i` whose target is under an `inject` dir or a
524
+ * `.done` dir, or is named like a wake file (`<ISO stamp>-<seq>….md`), at any
525
+ * prefix. Mirrors `isDeliverySurface` in the guard, kept an independent
526
+ * implementation on purpose.
527
+ */
528
+ const WAKE_FILE_NAME = String.raw`\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}-\d{3}Z-\d{4,}(?:--cmd-[^/\s]*)?\.md(?:\.tmp-[^/\s]*)?`;
529
+ const DELIVERY_TARGET =
530
+ String.raw`(?:\S*\/)?(?:inject(?:\/\S*)?|\.done(?:\/\S*)?|` +
531
+ WAKE_FILE_NAME +
532
+ String.raw`)(?=[\s;&|()<>]|$)`;
533
+ const DELIVERY_WRITE_RE = new RegExp(
534
+ String.raw`(?:` +
535
+ WRITE_OPERATOR +
536
+ DELIVERY_TARGET +
537
+ String.raw`|\bsed\s+(?:-\S+\s+)*-[a-zA-Z]*i\S*(?:\s+\S+)*?\s+` +
538
+ DELIVERY_TARGET +
539
+ String.raw`)`,
540
+ );
541
+
542
+ /** The same wake-delivery files as a WRITE-TOOL target path — the guard's
543
+ * shapes. */
544
+ const DELIVERY_PATH_RE = new RegExp(
545
+ String.raw`(?:^|\/)(?:inject(?:\/|$)|\.done(?:\/|$)|` + WAKE_FILE_NAME + String.raw`$)`,
546
+ );
547
+
548
+ /**
549
+ * A write target spelled as a PATTERN: bash expands a
550
+ * redirection target before it opens the file, so `> retired-uri[s].json`,
551
+ * `> recall-hint?/pr-1.json`, `> config.tom?` and `> recall-hint{s..s}/…`
552
+ * write the protected file while no literal name above matches. Each pattern
553
+ * component (a brace group widened to `*`) is tried against the protected
554
+ * component names and the substituted paths are classified by the path
555
+ * rules — the guard's `protectedPatternHit` is the same idea, and this is an
556
+ * independent implementation of it on purpose.
557
+ */
558
+ const PATTERN_SYNTAX_RE = /[*?[]|\{[^{}]*(?:,|\.\.)[^{}]*\}/;
559
+ const SURFACE_COMPONENT_NAMES: readonly string[] = [
560
+ ".git",
561
+ ".gitconfig",
562
+ "git",
563
+ "config",
564
+ ".gitattributes",
565
+ ...POLICY_SURFACE_FILES,
566
+ ...POLICY_SURFACE_DIRS,
567
+ "recall-hints",
568
+ "retired-uris.json",
569
+ "retired-uris.json.tmp-1",
570
+ "inject",
571
+ ".done",
572
+ ];
573
+
574
+ /** A shell pattern component as an anchored regex: `*`, `?`, `[…]`/`[!…]`. */
575
+ function componentPatternRe(c: string): RegExp {
576
+ let re = "";
577
+ for (let i = 0; i < c.length; i++) {
578
+ const ch = c[i]!;
579
+ if (ch === "*") re += ".*";
580
+ else if (ch === "?") re += ".";
581
+ else if (ch === "[" && c.indexOf("]", i + 2) > 0) {
582
+ const close = c.indexOf("]", i + 2);
583
+ const body = c.slice(i + 1, close);
584
+ re += `[${body.startsWith("!") ? `^${body.slice(1)}` : body}]`.replace(/\\/g, "\\\\");
585
+ i = close;
586
+ } else re += ch.replace(/[.+^${}()|\\/[\]]/g, "\\$&");
587
+ }
588
+ try {
589
+ return new RegExp(`^${re}$`);
590
+ } catch {
591
+ return /^$/;
592
+ }
593
+ }
594
+
595
+ /** Which protected surface a write-tool target path is, if any. */
596
+ function surfacePathKind(path: string): ExecViolationKind | null {
597
+ if (GIT_CONFIG_SURFACE_PATH_RE.test(path)) return "git_config_surface_write";
598
+ if (MEMORY_SCOPE_PATH_RE.test(path)) return "memory_scope_write";
599
+ if (DELIVERY_PATH_RE.test(path)) return "delivery_surface_write";
600
+ if (POLICY_SURFACE_PATH_RE.test(path)) return "policy_surface_write";
601
+ return null;
602
+ }
603
+
604
+ /** Conservatively recognize every wake-like literal prefix before a glob,
605
+ * independently of the guard's implementation. No single date represents
606
+ * the timestamp, sequence and command-id families. */
607
+ function wakePatternPrefix(component: string): boolean {
608
+ const at = component.search(/[*?[]/);
609
+ if (at < 0) return false;
610
+ const literal = component.slice(0, at);
611
+ const shape = "dddd-dd-ddTdd-dd-dd-dddZ-dddd";
612
+ for (let i = 0; i < Math.min(shape.length, literal.length); i++) {
613
+ if (shape[i] === "d" ? !/^[0-9]$/.test(literal[i]!) : shape[i] !== literal[i]) return false;
614
+ }
615
+ if (literal.length <= shape.length) return true;
616
+ const suffix = literal.slice(shape.length).replace(/^[0-9]+/, "");
617
+ if ("--cmd-".startsWith(suffix) || suffix.startsWith("--cmd-")) return true;
618
+ if (".md".startsWith(suffix)) return true;
619
+ return (
620
+ suffix.startsWith(".md") &&
621
+ (".tmp-".startsWith(suffix.slice(3)) || suffix.slice(3).startsWith(".tmp-"))
622
+ );
623
+ }
624
+
625
+ /** The surface a PATTERN write target can expand onto, if any. */
626
+ function patternTargetKind(target: string): ExecViolationKind | null {
627
+ if (!PATTERN_SYNTAX_RE.test(target)) return null;
628
+ const parts = target.replace(/\{[^{}]*(?:,|\.\.)[^{}]*\}/g, "*").split("/");
629
+ if (wakePatternPrefix(parts[parts.length - 1]!)) return "delivery_surface_write";
630
+ let paths = [""];
631
+ for (const [k, part] of parts.entries()) {
632
+ const options = [part];
633
+ if (/[*?[]/.test(part)) {
634
+ const re = componentPatternRe(part);
635
+ for (const n of SURFACE_COMPONENT_NAMES) if (re.test(n)) options.push(n);
636
+ }
637
+ paths = paths.flatMap((p) => options.map((o) => (k === 0 ? o : `${p}/${o}`)));
638
+ // Too broad to enumerate: a pattern this wide over a write is itself the
639
+ // line — the policy surface is the widest set it could reach.
640
+ if (paths.length > 512) return "policy_surface_write";
641
+ }
642
+ for (const p of paths) {
643
+ const kind = surfacePathKind(p);
644
+ if (kind !== null) return kind;
645
+ }
646
+ return null;
647
+ }
648
+
649
+ /** Every `--output` target in one (dequoted) segment. The redirection
650
+ * targets come from the guard's quote-aware `redirectTargets` — its
651
+ * tokeniser, borrowed like `splitShellSegments`, so a `>` inside a quoted
652
+ * grep pattern is no write here either. */
653
+ const OUTPUT_TARGET_RE = /--output[=\s]\s*([^\s;&|()<>]+)/g;
654
+
655
+ /** A session env-prefix that relocates this system's own policy inputs — the
656
+ * `QCR_` inputs the guard refuses in `POLICY_RELOCATING_ENV` (`QCR_INSTALL`
657
+ * included: it names the config home the locator reads). Matched as
658
+ * an assignment prefix at a command position (or after a separator), so a
659
+ * laundered `bash -c 'sanctioned ; QCR_CONFIG=… script'` is seen: the string is
660
+ * right there in the segment whether it is quoted or not. Independent of the
661
+ * guard's own list by design. */
662
+ const POLICY_RELOCATION_RE =
663
+ /(?:^|[\s;&|(])QCR_(?:CONFIG|SANDBOX_ROOT|INSTALL|STATE_DB|DRYRUN_DIR|POSTING_RECEIPT_DIR)=/;
664
+
665
+ /**
666
+ * Programs whose ARGUMENTS are search patterns and paths, never commands.
667
+ *
668
+ * Without this the audit would read every grep pattern as if it were a
669
+ * command, and fire on the reads that ARE the job here: `rg -n PATH= Dockerfile`,
670
+ * `grep -n ENV= .env.example`, `rg -n 'gh pr create' .github/workflows/ci.yml`,
671
+ * `grep -n 'git push' scripts/deploy.sh`. Reviewing a PR that touches a
672
+ * Dockerfile, a workflow or a deploy script means grepping for exactly those
673
+ * tokens. A routine false line teaches the operator to skip the event, which is
674
+ * worse than silence — so the content rules do not run against a reader's
675
+ * arguments at all.
676
+ *
677
+ * This does NOT make a reader invisible: its own write/exec modes are checked
678
+ * first (below), and every OTHER segment of the pipeline is classified
679
+ * normally, so `python3 evil.py | grep x` is still caught on its first segment.
680
+ */
681
+ const AUDIT_READERS: ReadonlySet<string> = new Set([
682
+ "rg",
683
+ "grep",
684
+ "egrep",
685
+ "fgrep",
686
+ "ag",
687
+ "ack",
688
+ "cat",
689
+ "head",
690
+ "tail",
691
+ "nl",
692
+ "wc",
693
+ "jq",
694
+ "cut",
695
+ "tr",
696
+ "uniq",
697
+ "sort",
698
+ "ls",
699
+ "echo",
700
+ "printf",
701
+ "diff",
702
+ "comm",
703
+ "column",
704
+ "find",
705
+ "basename",
706
+ "dirname",
707
+ "stat",
708
+ "sed",
709
+ "xargs",
710
+ "test",
711
+ // Not `awk`: it is off the guard's ALLOWED set, so an awk invocation in a
712
+ // transcript is itself a policy violation, classified as the interpreter it
713
+ // is.
714
+ ]);
715
+
716
+ /**
717
+ * The write/exec MODES of the programs that are allowlisted for reading.
718
+ * Without them the audit would be blind to the very write primitives (e.g.
719
+ * onto `<clone>/.git/config`) that the guard's reader-mode check stops, so a
720
+ * gap in that check would go unseen — which undercuts the point of having
721
+ * both layers.
722
+ *
723
+ * This is the same SHAPE as `checkReaderModes` in the guard, as a separate
724
+ * coarse implementation over whole segments; independence buys less here than
725
+ * it does elsewhere in this file.
726
+ *
727
+ * The variable-target write — `T=.git/config; cat p >> $T` — is deliberately
728
+ * NOT here. Its target is a variable, so no reader of command strings can ever see
729
+ * it; that one is caught by the round-boundary integrity check in
730
+ * `execboundary.ts`, which is why that check exists.
731
+ *
732
+ * `awk` has no entry: the same indirection defeats any pattern for it
733
+ * (`print "cmd" | c`), so awk is off the guard's ALLOWED set entirely and any
734
+ * awk at all is an `interpreter` line.
735
+ */
736
+ const READER_MODE_AUDIT: Readonly<Record<string, RegExp>> = {
737
+ find: /(?:^|\s)-(?:exec|execdir|ok|okdir|delete|fprintf|fprint|fprint0|fls)(?:\s|$)/,
738
+ // `o` is unambiguous in sort's short options, so a cluster carrying it —
739
+ // its value attached (`-o/tmp/out`) or not — is an output redirect.
740
+ sort: /(?:^|\s)(?:--(?:output|compress-program)(?:=|\s)|-(?!-)[a-zA-Z]*o)/,
741
+ // sed has no pattern here: `sedAuditHit` reads its words as bash hands them over.
742
+ // The diff options' `--output=<file>` on any verb, and
743
+ // `git grep`'s `--open-files-in-pager[=<cmd>]` / `-O<cmd>` (any unique
744
+ // abbreviation of the long form; `-O` ending a short cluster).
745
+ git: /(?:^|\s)--output(?:=|\s|$)|\bgit\s+(?:-C\s+\S+\s+|-\S+\s+)*grep\b.*?\s(?:--op[a-z-]*(?:=|\s|$)|-[A-Za-z]*O)/,
746
+ };
747
+
748
+ /** The first real program token in a segment: `VAR=val` prefixes, `env` and its
749
+ * flags, and redirection remnants skipped — the same shape the bash guard's
750
+ * `checkSegment` uses to find what a segment actually runs. */
751
+ function segmentProgram(segment: string): string | null {
752
+ // `xargs` RUNS the program named after it, so it is resolved through rather
753
+ // than treated as the program — the guard's `checkProgram` recurses for the
754
+ // same reason. Without this, `… | xargs awk '{print}'` would classify as
755
+ // `xargs`, which is on AUDIT_READERS, and the whole segment would be
756
+ // skipped.
757
+ let sawXargs = false;
758
+ for (const raw of segment.trim().split(/\s+/)) {
759
+ const t = raw.replace(/^['"(]+|['")]+$/g, "");
760
+ if (t.length === 0) continue;
761
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) continue;
762
+ if (t === "env" || (t.startsWith("-") && t.length <= 3)) continue;
763
+ if (/^\d*[<>]/.test(t)) continue;
764
+ const base = t.slice(t.lastIndexOf("/") + 1);
765
+ if (sawXargs) {
766
+ if (t.startsWith("-") || t === "{}") continue; // xargs' own flags
767
+ return base;
768
+ }
769
+ if (base === "xargs") {
770
+ sawXargs = true;
771
+ continue;
772
+ }
773
+ return base;
774
+ }
775
+ return sawXargs ? "xargs" : null; // bare `xargs` runs echo
776
+ }
777
+
778
+ /** The `VAR=val` prefixes in front of a segment's program (and of `env`),
779
+ * space-joined — what `segmentProgram` skips to find the program. */
780
+ function assignmentPrefix(segment: string): string {
781
+ const out: string[] = [];
782
+ for (const raw of segment.trim().split(/\s+/)) {
783
+ const t = raw.replace(/^['"(]+|['")]+$/g, "");
784
+ if (t.length === 0) continue;
785
+ if (/^[A-Za-z_][A-Za-z0-9_]*=/.test(t)) {
786
+ out.push(t);
787
+ continue;
788
+ }
789
+ if (t === "env" || (t.startsWith("-") && t.length <= 3)) continue;
790
+ if (/^\d*[<>]/.test(t)) continue; // a redirection remnant, as segmentProgram skips
791
+ break;
792
+ }
793
+ return out.join(" ");
794
+ }
795
+
796
+ /** Git search text is data. Parse only the invocation shape here; the
797
+ * independent reader-mode and protected-target checks still run first. */
798
+ function gitSearchReader(segment: string): boolean {
799
+ const words = sedWords(segment);
800
+ if (words === null) return false;
801
+ let i = 0;
802
+ while (words[i] === "env" || /^[A-Za-z_][A-Za-z0-9_]*=/.test(words[i] ?? "")) i++;
803
+ if (!/(?:^|\/)git$/.test(words[i++] ?? "")) return false;
804
+ while (words[i]?.startsWith("-")) {
805
+ const option = words[i++]!;
806
+ if (option === "-C") {
807
+ if (words[i++] === undefined) return false;
808
+ } else if (
809
+ !["--no-pager", "--paginate", "--literal-pathspecs", "--no-optional-locks"].includes(option)
810
+ )
811
+ return false;
812
+ }
813
+ if (!["grep", "log"].includes(words[i++] ?? "")) return false;
814
+ // Program/config selectors are options wherever they occur, independently
815
+ // of the guard's parser. A pattern containing these whole option words
816
+ // stays conservatively visible, matching the existing reader-mode policy.
817
+ return !words
818
+ .slice(i)
819
+ .some((word) =>
820
+ /^--(?:config-env|git-dir|work-tree|exec-path|exec|upload-pack|receive-pack)(?:=|$)/.test(
821
+ word,
822
+ ),
823
+ );
824
+ }
825
+
826
+ /** sed's script words in a segment: every `-e X`/`-eX`/`--e…=X`/`--e… X`
827
+ * value, else its first operand — with an `-i`/`-f` (or `--in-place`/`--file`
828
+ * by any prefix) reported as `writes`. Read from the words bash hands sed, so
829
+ * adjacent quoted pieces are one word (`"1"'w out'` is `1w out`), and a word
830
+ * whose value the text does not fix (`$'…'`, `$X`, a backtick) is read with
831
+ * its quoting stripped — coarse on purpose, never "no script". */
832
+ function sedScripts(segment: string): { writes: boolean; scripts: string[] } {
833
+ let after: string | null = null;
834
+ for (const m of segment.matchAll(/\S+/g)) {
835
+ const t = m[0].replace(/^[\\'"(]+|['")]+$/g, "");
836
+ if (t.slice(t.lastIndexOf("/") + 1) === "sed") {
837
+ after = segment.slice(m.index + m[0].length);
838
+ break;
839
+ }
840
+ }
841
+ if (after === null) return { writes: false, scripts: [] };
842
+ const words =
843
+ sedWords(after) ??
844
+ after
845
+ .replace(/[$'"`\\]/g, "")
846
+ .split(/\s+/)
847
+ .filter((w) => w.length > 0);
848
+ const scripts: string[] = [];
849
+ let operand: string | null = null;
850
+ let writes = false;
851
+ for (let k = 0; k < words.length; k++) {
852
+ const w = words[k]!;
853
+ if (w === "--") {
854
+ if (operand === null && words[k + 1] !== undefined) operand = words[k + 1]!;
855
+ break;
856
+ }
857
+ if (/^--(?:i|f)[a-z-]*(?:=|$)/.test(w)) writes = true;
858
+ else if (/^--e[a-z-]*=/.test(w)) scripts.push(w.slice(w.indexOf("=") + 1));
859
+ else if (/^--e[a-z-]*$/.test(w)) scripts.push(words[++k] ?? "");
860
+ else if (/^-[^-]/.test(w)) {
861
+ const short = /^-([a-zA-Z0-9]*?)([eif])(.*)$/s.exec(w);
862
+ if (short?.[2] === "e") scripts.push(short[3] !== "" ? short[3]! : (words[++k] ?? ""));
863
+ else if (short !== null) writes = true;
864
+ } else if (operand === null) operand = w;
865
+ }
866
+ if (scripts.length === 0 && operand !== null) scripts.push(operand);
867
+ return { writes, scripts };
868
+ }
869
+
870
+ /** A sed address run: numbers, `first~step`, `$`, `/re/` and `\cREc` (with
871
+ * their I/M flags), `,`, `+N` and `!`. `group` numbers the `\cREc`
872
+ * delimiter's capture, so the run can appear twice in one pattern. */
873
+ const sedAddr = (group: number): string => {
874
+ const ref = `\\${group}`;
875
+ return (
876
+ String.raw`(?:\s*(?:[0-9]+|\$|~[0-9]*|\+[0-9]*|[,!]|\/(?:\\.|[^/\\\n])*\/[IM]*|\\([^\n\\])(?:\\.|(?!` +
877
+ ref +
878
+ String.raw`)[^\\\n])*` +
879
+ ref +
880
+ String.raw`[IM]*))*`
881
+ );
882
+ };
883
+ /** A w/W/r/R/e command where a command starts: the script's start, after `;`,
884
+ * `{`, `}` or a newline, or after a branch or label and the whitespace that
885
+ * ends it (`bx e cmd` is a branch, then `e`) — behind any address. A `w`
886
+ * glued to its file (`wout`) is one too. */
887
+ const SED_VERB_RE = new RegExp(
888
+ String.raw`(?:^|[;{}\n])(?:` +
889
+ sedAddr(1) +
890
+ String.raw`\s*[:btT][ \t]*[^\s;}]+[ \t]+)*` +
891
+ sedAddr(2) +
892
+ String.raw`\s*[wWrRe]`,
893
+ );
894
+ /** An s command whose flags carry `e` (runs the pattern space) or `w` (writes),
895
+ * with any delimiter and the flags in any order. */
896
+ const SED_SFLAG_RE =
897
+ /s([^\\\n])(?:\\.|(?!\1)[^\\\n])*\1(?:\\.|(?!\1)[^\\\n])*\1[gpiImMnN0-9 \t]*[ew]/;
898
+
899
+ /** Whether this segment's sed accesses another file or runs a command. */
900
+ function sedAuditHit(segment: string): boolean {
901
+ const { writes, scripts } = sedScripts(segment);
902
+ return writes || scripts.some((sc) => SED_VERB_RE.test(sc) || SED_SFLAG_RE.test(sc));
903
+ }
904
+
905
+ /** Which rule, if any, this ONE segment trips. */
906
+ function segmentViolationKind(segment: string): ExecViolationKind | null {
907
+ // The redirection/`sed -i` surface rules run on every segment, reader or not:
908
+ // their subject is the segment's own write target, not a quoted pattern. They
909
+ // read the target with its quoting removed, as bash would open it — `>
910
+ // con"fig".toml` and `> config\.toml` are `config.toml`.
911
+ const bare = segment.replace(/["'\\]/g, "");
912
+ if (GIT_CONFIG_SURFACE_WRITE_RE.test(bare)) return "git_config_surface_write";
913
+ if (MEMORY_SCOPE_WRITE_RE.test(bare)) return "memory_scope_write";
914
+ if (DELIVERY_WRITE_RE.test(bare)) return "delivery_surface_write";
915
+ if (POLICY_SURFACE_WRITE_RE.test(bare)) return "policy_surface_write";
916
+ // The same surfaces once more, over the writes bash would actually perform:
917
+ // every unquoted redirection's target with its
918
+ // quoting removed as bash removes it (`> $'retired-uris.json'`), and every
919
+ // `--output` target — each named literally, or as a PATTERN bash expands
920
+ // (`> retired-uri[s].json`).
921
+ for (const target of [
922
+ ...redirectTargets(segment),
923
+ ...[...bare.matchAll(OUTPUT_TARGET_RE)].map((m) => m[1]!),
924
+ ]) {
925
+ const kind = surfacePathKind(target) ?? patternTargetKind(target);
926
+ if (kind !== null) return kind;
927
+ }
928
+ const prog = segmentProgram(segment);
929
+ if (prog !== null) {
930
+ // Checked BEFORE the reader skip below: these programs are readers by
931
+ // default and writers on a flag, and the flag is the whole point. git's
932
+ // rule reads the DEQUOTED segment, as git receives its options
933
+ // (`--out"put"=…` is `--output=…`); sed's reads it with a quote nested in
934
+ // the other kind masked (`maskNestedQuotes`).
935
+ const hit = prog === "sed" ? sedAuditHit(segment) : READER_MODE_AUDIT[prog]?.test(bare);
936
+ if (hit === true) return "reader_write_or_exec";
937
+ if (/(?:^|\s)(?:\S*\/)?xargs(?:\s|$)/.test(bare)) {
938
+ if (["find", "uniq", "sh", "xargs"].includes(prog)) return "reader_write_or_exec";
939
+ if (
940
+ ["sort", "sed", "git", "gh"].includes(prog) &&
941
+ (!/\s--\s*$/.test(bare) || /(?:^|\s)(?:-[a-zA-Z]*[Ii]|--replace)/.test(bare))
942
+ )
943
+ return "reader_write_or_exec";
944
+ }
945
+ if (prog === "sh" && /\bsh\s+-n\s+(?:\+|-(?!--(?:\s|$)|(?:\s|$)))/.test(bare))
946
+ return "interpreter";
947
+ if (prog === "uniq") {
948
+ const words = sedWords(segment);
949
+ if (words !== null) {
950
+ const at = words.findIndex((w) => /(?:^|\/)uniq$/.test(w));
951
+ let operands = 0;
952
+ let options = true;
953
+ for (let i = at + 1; i < words.length; i++) {
954
+ const word = words[i]!;
955
+ if (options && word === "--") {
956
+ options = false;
957
+ continue;
958
+ }
959
+ if (options && word.startsWith("-") && word !== "-") {
960
+ if (/^-[fsw]$|^--(?:skip-fields|skip-chars|check-chars)$/.test(word)) i++;
961
+ } else operands++;
962
+ }
963
+ if (operands > 1) return "reader_write_or_exec";
964
+ }
965
+ }
966
+ // A reader's ARGUMENTS are patterns, but an assignment PREFIX in front
967
+ // of it is the environment it runs in — `LD_PRELOAD=… cat f` loads code
968
+ // whatever cat then reads.
969
+ if (AUDIT_READERS.has(prog) || (prog === "git" && gitSearchReader(segment))) {
970
+ const prefix = assignmentPrefix(segment);
971
+ if (POLICY_RELOCATION_RE.test(prefix)) return "policy_relocation";
972
+ return GIT_CONFIG_INJECTION_RE.test(prefix) ? "git_config_injection" : null;
973
+ }
974
+ }
975
+ // A policy-relocation env prefix (`QCR_CONFIG=` and kin) — checked AFTER the
976
+ // reader skip so `grep QCR_CONFIG=x file` (a read of a config) does not trip
977
+ // it, but a `bash -c '… ; QCR_CONFIG=… script'` (prog is `bash`, not a
978
+ // reader) still does.
979
+ if (POLICY_RELOCATION_RE.test(segment)) return "policy_relocation";
980
+ // gh is judged as it receives its words, like the guard: on the dequoted
981
+ // segment too, and a gh or git segment opening `$'…'`/`$"…"` quoting —
982
+ // which can spell any flag — is flagged until shown otherwise.
983
+ if (ghApiWrites(segment) || ghApiWrites(bare) || GITHUB_DIRECT_WRITE_RE.test(segment))
984
+ return "github_write";
985
+ if (prog === "gh" && opensUnmodelledQuoting(segment)) return "github_write";
986
+ if (prog === "git" && opensUnmodelledQuoting(segment)) return "git_config_injection";
987
+ const gh = GH_SUBCOMMAND_RE.exec(segment);
988
+ if (gh) {
989
+ const ns = gh[1]!;
990
+ const verb = gh[2];
991
+ if (!GH_AUDIT_READ_NAMESPACES.has(ns) && verb !== undefined && !GH_AUDIT_READ_VERBS.has(verb))
992
+ return "github_write";
993
+ }
994
+ if (GIT_WRITE_RE.test(segment)) return "git_write";
995
+ if (GIT_CONFIG_INJECTION_RE.test(segment)) return "git_config_injection";
996
+ if (EXEC_VIOLATION_RE.test(segment)) return "interpreter";
997
+ return null;
998
+ }
999
+
1000
+ /**
1001
+ * Which rule, if any, this command trips — decided PER SHELL SEGMENT.
1002
+ *
1003
+ * Not whole-command matching: a pattern in an argument to `rg` is not a
1004
+ * command, and treating it as one produces false positives on ordinary review
1005
+ * reads. Segmenting reuses the guard's splitter — the TOKENISER, not its
1006
+ * policy; the rules above stay an independent implementation on purpose, so
1007
+ * this reader and the guard do not fail in the same places.
1008
+ */
1009
+ export function execViolationKind(cmd: string): ExecViolationKind | null {
1010
+ // The guard's redirection normaliser, borrowed like its splitter: `&>f`,
1011
+ // `>&f`, `{v}>f`, `1<>f` and `>|f` all become `>f`, so a write the guard
1012
+ // refuses is spelled the same way when this audit reads it back.
1013
+ const normalized = normalizeRedirections(cmd);
1014
+ const segments = splitShellSegments(normalized);
1015
+ const root = process.env.QCR_SANDBOX_ROOT ?? process.cwd();
1016
+ const changedDirectory = segments.some((segment) => {
1017
+ if (segmentProgram(segment) !== "cd") return false;
1018
+ const words = sedWords(segment);
1019
+ return words === null || words.length !== 2 || words[1] !== root;
1020
+ });
1021
+ if (
1022
+ changedDirectory &&
1023
+ segments.some((segment) => {
1024
+ const prog = segmentProgram(segment);
1025
+ return (
1026
+ prog !== null &&
1027
+ !AUDIT_READERS.has(prog) &&
1028
+ /(?:^|[\s'"(])(?:\.\/)?scripts\/[a-z-]+\.sh(?:[\s'";)]|$)/.test(segment)
1029
+ );
1030
+ })
1031
+ )
1032
+ return "interpreter";
1033
+ for (const segment of segments) {
1034
+ if (segment.trim().length === 0) continue;
1035
+ const kind = segmentViolationKind(segment);
1036
+ if (kind !== null) return kind;
1037
+ }
1038
+ return null;
1039
+ }
1040
+
1041
+ /**
1042
+ * Every tool call in a record, wherever it nests (eight levels deep): its
1043
+ * tool name (`toolName`, `name` or `tool`) and the objects its arguments may
1044
+ * ride in — each argument envelope (`arguments`, `input`, `args`, `params`)
1045
+ * that is an object, then the call itself. The ONE reading of the transcript's
1046
+ * tool-call shape; what to pull out of the arguments is the caller's.
1047
+ */
1048
+ function forEachToolCall(
1049
+ value: unknown,
1050
+ visit: (toolName: unknown, argObjects: Array<Record<string, unknown>>) => void,
1051
+ depth = 8,
1052
+ ): void {
1053
+ if (depth < 0 || typeof value !== "object" || value === null) return;
1054
+ if (Array.isArray(value)) {
1055
+ for (const item of value) forEachToolCall(item, visit, depth - 1);
1056
+ return;
1057
+ }
1058
+ const obj = value as Record<string, unknown>;
1059
+ const envelopes: Array<Record<string, unknown>> = [];
1060
+ for (const argsKey of ["arguments", "input", "args", "params"]) {
1061
+ const args = obj[argsKey];
1062
+ if (typeof args === "object" && args !== null) envelopes.push(args as Record<string, unknown>);
1063
+ }
1064
+ visit(obj.toolName ?? obj.name ?? obj.tool, [...envelopes, obj]);
1065
+ for (const v of Object.values(obj)) forEachToolCall(v, visit, depth - 1);
1066
+ }
1067
+
1068
+ /** Pull every bash toolCall command out of a record, wherever it nests. */
1069
+ function bashCommandsIn(value: unknown, out: string[]): void {
1070
+ forEachToolCall(value, (toolName, argObjects) => {
1071
+ if (toolName !== "bash") return;
1072
+ for (const a of argObjects) if (typeof a.command === "string") out.push(a.command);
1073
+ });
1074
+ }
1075
+
1076
+ /** Tool names that write a file, as recorded in the transcript. Mirrors
1077
+ * WRITE_TOOLS in packages/pi-plugin/extensions/bash-guard.ts — deliberately broad. */
1078
+ const WRITE_TOOL_NAMES = new Set([
1079
+ "write",
1080
+ "edit",
1081
+ "multi_edit",
1082
+ "multiedit",
1083
+ "str_replace",
1084
+ "create",
1085
+ "write_file",
1086
+ "apply_patch",
1087
+ ]);
1088
+
1089
+ /**
1090
+ * Every write-TOOL target in a record. The bash-only collector above is why
1091
+ * the audit was blind to the decisive half of all four bypasses: the command
1092
+ * they ran was innocent, and the payload was a file written with the ordinary
1093
+ * write tool, which never appears in a bash command at all.
1094
+ */
1095
+ function writeTargetsIn(value: unknown, out: string[]): void {
1096
+ forEachToolCall(value, (toolName, argObjects) => {
1097
+ if (typeof toolName !== "string" || !WRITE_TOOL_NAMES.has(toolName)) return;
1098
+ for (const a of argObjects)
1099
+ for (const pathKey of ["path", "file_path", "filePath"]) {
1100
+ const p = a[pathKey];
1101
+ if (typeof p === "string") out.push(p);
1102
+ }
1103
+ });
1104
+ }
1105
+
1106
+ export interface ExecViolation {
1107
+ command: string;
1108
+ kind: ExecViolationKind;
1109
+ }
1110
+
1111
+ /** One parsed record's audit items — its bash commands, then its write-tool
1112
+ * targets, each that trips a rule — in the order the audit meets them. A
1113
+ * write target's key is `write <path>`. */
1114
+ export function auditItemsOf(rec: unknown): ExecViolation[] {
1115
+ const out: ExecViolation[] = [];
1116
+ const commands: string[] = [];
1117
+ bashCommandsIn(rec, commands);
1118
+ for (const command of commands) {
1119
+ const kind = execViolationKind(command);
1120
+ if (kind) out.push({ command, kind });
1121
+ }
1122
+ const targets: string[] = [];
1123
+ writeTargetsIn(rec, targets);
1124
+ for (const target of targets) {
1125
+ const kind = surfacePathKind(target);
1126
+ if (kind !== null) out.push({ command: `write ${target}`, kind });
1127
+ }
1128
+ return out;
1129
+ }
1130
+
1131
+ /** Every policy-forbidden action visible in the given JSONL lines, classified.
1132
+ * Deduplicated by command, order-preserving; malformed lines skipped. */
1133
+ export function auditExecViolationDetails(lines: string[]): ExecViolation[] {
1134
+ const seen = new Map<string, ExecViolationKind>();
1135
+ for (const line of lines) {
1136
+ let rec: unknown;
1137
+ try {
1138
+ rec = JSON.parse(line);
1139
+ } catch {
1140
+ continue;
1141
+ }
1142
+ for (const item of auditItemsOf(rec))
1143
+ if (!seen.has(item.command)) seen.set(item.command, item.kind);
1144
+ }
1145
+ return [...seen].map(([command, kind]) => ({ command, kind }));
1146
+ }
1147
+
1148
+ /** The audit items of the given JSONL lines, by their key alone: a bash
1149
+ * command that trips any rule (an executor, a GitHub or git write, a
1150
+ * protected-surface write, …) or `write <path>` for a write-tool target on a
1151
+ * protected surface. Deduplicated, order-preserving; malformed lines skipped. */
1152
+ export function auditExecViolations(lines: string[]): string[] {
1153
+ return auditExecViolationDetails(lines).map((v) => v.command);
1154
+ }