@resolveio/server-lib 22.3.195 → 22.3.197

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 (745) hide show
  1. package/.nodemon.json +5 -0
  2. package/.vscode/settings.json +21 -0
  3. package/AGENTS.md +195 -0
  4. package/README.md +22 -0
  5. package/build_package.sh +5 -0
  6. package/compileDTS.pl +64 -0
  7. package/docs/ai-assistant-nightly-eval.md +65 -0
  8. package/docs/ai-assistant-preflight-checklist.md +23 -0
  9. package/docs/ai-assistant-report-builder-bridge-playbook.md +115 -0
  10. package/eslint-plugin-custom/index.js +7 -0
  11. package/eslint-plugin-custom/rules/no-filter-zero-index.js +44 -0
  12. package/eslint.config.js +103 -0
  13. package/gulpfile.js +216 -0
  14. package/methodAndPublicationListGenerator.py +375 -0
  15. package/mongodbensurers.js +2 -0
  16. package/mongostop.js +3 -0
  17. package/package.json +1 -1
  18. package/scripts/cleanup-bypassed-callmethod-logs.js +616 -0
  19. package/settings.development.json +25 -0
  20. package/settings.development.redacted.json +25 -0
  21. package/src/.env +12 -0
  22. package/src/ai/assistant-core-heuristics.ts +379 -0
  23. package/src/ai/resolveio-platform-intelligence-memory-corpus.ts +185 -0
  24. package/src/ai/resolveio-platform-intelligence-memory.ts +325 -0
  25. package/{ai/resolveio-platform-intelligence-types.d.ts → src/ai/resolveio-platform-intelligence-types.ts} +20 -15
  26. package/src/ai/resolveio-platform-intelligence.ts +462 -0
  27. package/src/client-server-app.ts +12 -0
  28. package/src/collections/ai-run.collection.ts +117 -0
  29. package/src/collections/ai-terminal-conversation.collection.ts +91 -0
  30. package/src/collections/ai-terminal-issue-report.collection.ts +99 -0
  31. package/src/collections/ai-terminal-message.collection.ts +77 -0
  32. package/src/collections/app-setting.collection.ts +104 -0
  33. package/src/collections/app-status.collection.ts +58 -0
  34. package/src/collections/communication-metric.collection.ts +84 -0
  35. package/src/collections/counter.collection.ts +56 -0
  36. package/src/collections/cron-job-history.collection.ts +94 -0
  37. package/src/collections/cron-job.collection.ts +92 -0
  38. package/src/collections/customer-notification.collection.ts +131 -0
  39. package/src/collections/customer-portal-password.collection.ts +76 -0
  40. package/src/collections/email-history.collection.ts +134 -0
  41. package/src/collections/email-verified.collection.ts +62 -0
  42. package/src/collections/file.collection.ts +74 -0
  43. package/src/collections/flag-update.collection.ts +57 -0
  44. package/src/collections/flag.collection.ts +57 -0
  45. package/src/collections/log-method-latency.collection.ts +77 -0
  46. package/src/collections/log-subscription.collection.ts +80 -0
  47. package/src/collections/log.collection.ts +93 -0
  48. package/src/collections/logged-in-users.collection.ts +67 -0
  49. package/src/collections/monitor-cpu.collection.ts +65 -0
  50. package/src/collections/monitor-function.collection.ts +74 -0
  51. package/src/collections/monitor-memory.collection.ts +77 -0
  52. package/src/collections/monitor-mongo.collection.ts +71 -0
  53. package/src/collections/notification.collection.ts +57 -0
  54. package/src/collections/openai-usage-ledger.collection.ts +131 -0
  55. package/src/collections/report-builder-dashboard-builder.collection.ts +109 -0
  56. package/src/collections/report-builder-library.collection.ts +89 -0
  57. package/src/collections/report-builder-report.collection.ts +184 -0
  58. package/src/collections/user-group.collection.ts +89 -0
  59. package/src/collections/user-guide.collection.ts +57 -0
  60. package/src/collections/user.collection.ts +181 -0
  61. package/src/cron/cron.ts +117 -0
  62. package/src/fixtures/cron-jobs.ts +95 -0
  63. package/src/fixtures/init.ts +35 -0
  64. package/src/http/auth.ts +818 -0
  65. package/src/http/health.ts +7 -0
  66. package/src/http/home.ts +90 -0
  67. package/src/http/slow-query-publication.ts +49 -0
  68. package/src/index.ts +1 -0
  69. package/src/managers/ai-assistant-codex-manager.manager.ts +1131 -0
  70. package/src/managers/ai-run-evidence.manager.ts +264 -0
  71. package/src/managers/communication-metric.manager.ts +82 -0
  72. package/src/managers/cron.manager.ts +333 -0
  73. package/src/managers/customer-notification-content.manager.ts +236 -0
  74. package/src/managers/diagnostic-manager-bootstrap.ts +165 -0
  75. package/src/managers/error-auto-fix.manager.ts +2767 -0
  76. package/src/managers/local-log.manager.ts +113 -0
  77. package/src/managers/method.manager.ts +1857 -0
  78. package/src/managers/mongo.manager.ts +4575 -0
  79. package/src/managers/monitor.manager.ts +507 -0
  80. package/src/managers/openai-usage-ledger.manager.ts +112 -0
  81. package/src/managers/slow-query-verifier.manager.ts +3590 -0
  82. package/src/managers/slow-query.manager.ts +519 -0
  83. package/src/managers/subscription.manager.ts +3128 -0
  84. package/src/managers/websocket.manager.ts +746 -0
  85. package/src/managers/worker-dispatcher.manager.ts +1360 -0
  86. package/src/managers/worker-server.manager.ts +536 -0
  87. package/src/methods/accounts.ts +532 -0
  88. package/src/methods/ai-terminal.ts +23825 -0
  89. package/src/methods/app-settings.ts +114 -0
  90. package/src/methods/aws.ts +649 -0
  91. package/src/methods/collections.ts +641 -0
  92. package/src/methods/counters.ts +69 -0
  93. package/src/methods/cron-jobs.ts +2614 -0
  94. package/src/methods/customer-notifications.ts +458 -0
  95. package/src/methods/diagnostics.ts +616 -0
  96. package/src/methods/flag-updates.ts +7 -0
  97. package/src/methods/flags.ts +7 -0
  98. package/src/methods/logs.ts +657 -0
  99. package/src/methods/mongo-explorer.ts +1880 -0
  100. package/src/methods/monitor.ts +540 -0
  101. package/src/methods/pdf.ts +1236 -0
  102. package/src/methods/publications.ts +129 -0
  103. package/src/methods/report-builder.ts +3300 -0
  104. package/src/methods/support.ts +335 -0
  105. package/src/models/ai-run.model.ts +27 -0
  106. package/src/models/ai-terminal-conversation.model.ts +19 -0
  107. package/src/models/ai-terminal-issue-report.model.ts +21 -0
  108. package/src/models/ai-terminal-message.model.ts +24 -0
  109. package/src/models/app-setting.model.ts +17 -0
  110. package/{models/app-status.model.d.ts → src/models/app-status.model.ts} +3 -2
  111. package/{models/billing-logged-in-users.model.d.ts → src/models/billing-logged-in-users.model.ts} +5 -4
  112. package/src/models/collection-document.model.ts +24 -0
  113. package/src/models/communication-metric.model.ts +23 -0
  114. package/{models/counter.model.d.ts → src/models/counter.model.ts} +4 -3
  115. package/src/models/cron-job-history.model.ts +16 -0
  116. package/src/models/cron-job.model.ts +15 -0
  117. package/src/models/customer-notification.model.ts +28 -0
  118. package/src/models/customer-portal-password.model.ts +12 -0
  119. package/src/models/dialog.model.ts +25 -0
  120. package/{models/email-history.model.js → src/models/email-history.model.ts} +36 -4
  121. package/{models/email-verified.model.d.ts → src/models/email-verified.model.ts} +6 -5
  122. package/{models/file.model.d.ts → src/models/file.model.ts} +8 -7
  123. package/{models/flag-update.model.d.ts → src/models/flag-update.model.ts} +4 -3
  124. package/{models/flag.model.d.ts → src/models/flag.model.ts} +4 -3
  125. package/src/models/log-method-latency.model.ts +11 -0
  126. package/{models/log-subscription.model.d.ts → src/models/log-subscription.model.ts} +11 -9
  127. package/src/models/log.model.ts +19 -0
  128. package/{models/logged-in-users.model.d.ts → src/models/logged-in-users.model.ts} +6 -5
  129. package/{models/method-response.model.d.ts → src/models/method-response.model.ts} +7 -6
  130. package/src/models/method.model.ts +25 -0
  131. package/{models/monitor-cpu.model.d.ts → src/models/monitor-cpu.model.ts} +9 -7
  132. package/src/models/monitor-function.model.ts +16 -0
  133. package/src/models/monitor-memory.model.ts +17 -0
  134. package/src/models/monitor-mongo.model.ts +15 -0
  135. package/{models/notification.model.d.ts → src/models/notification.model.ts} +6 -4
  136. package/src/models/openai-usage-ledger.model.ts +56 -0
  137. package/src/models/pagination.model.ts +35 -0
  138. package/src/models/permission.model.ts +14 -0
  139. package/src/models/report-builder-dashboard-builder.model.ts +29 -0
  140. package/src/models/report-builder-library.model.ts +20 -0
  141. package/src/models/report-builder-report.model.ts +136 -0
  142. package/src/models/report-builder.model.ts +68 -0
  143. package/src/models/select-data-label.model.ts +9 -0
  144. package/src/models/server-message.model.ts +31 -0
  145. package/src/models/slow-query-report.model.ts +23 -0
  146. package/src/models/subscription.model.ts +73 -0
  147. package/src/models/support-ticket.model.ts +104 -0
  148. package/src/models/user-group.model.ts +24 -0
  149. package/{models/user-guide.model.d.ts → src/models/user-guide.model.ts} +5 -4
  150. package/src/models/user.model.ts +96 -0
  151. package/src/private/images/ResolveIO.png +0 -0
  152. package/src/publications/ai-terminal.ts +73 -0
  153. package/src/publications/app-settings.ts +25 -0
  154. package/src/publications/app-status.ts +13 -0
  155. package/src/publications/cron-jobs.ts +40 -0
  156. package/src/publications/customer-notifications.ts +101 -0
  157. package/src/publications/files.ts +33 -0
  158. package/src/publications/flags-update.ts +19 -0
  159. package/src/publications/flags.ts +19 -0
  160. package/src/publications/logs.ts +163 -0
  161. package/src/publications/notifications.ts +13 -0
  162. package/src/publications/report-builder-dashboard-builders.ts +39 -0
  163. package/src/publications/report-builder-libraries.ts +41 -0
  164. package/src/publications/report-builder-reports.ts +47 -0
  165. package/src/publications/super-admin.ts +13 -0
  166. package/src/publications/user-groups.ts +12 -0
  167. package/src/publications/user-guides.ts +12 -0
  168. package/src/resolveio-server-app.ts +617 -0
  169. package/src/server-app.ts +3354 -0
  170. package/src/services/codex-client.ts +1231 -0
  171. package/src/services/openai-client.ts +265 -0
  172. package/src/types/error-report.ts +26 -0
  173. package/src/types/js-tiktoken.d.ts +11 -0
  174. package/src/types/slow-query-report.ts +28 -0
  175. package/src/util/ai-qa-policy.ts +925 -0
  176. package/src/util/ai-run-evidence-adapters.ts +4642 -0
  177. package/src/util/ai-run-evidence-dashboard.ts +323 -0
  178. package/src/util/ai-run-evidence-eval.ts +1057 -0
  179. package/src/util/ai-run-evidence.ts +1185 -0
  180. package/src/util/ai-runner-artifacts.ts +586 -0
  181. package/src/util/ai-runner-manager-autopilot.ts +961 -0
  182. package/src/util/ai-runner-manager-policy.ts +4806 -0
  183. package/src/util/ai-runner-qa-auth.ts +821 -0
  184. package/src/util/ai-runner-qa-tools.ts +3045 -0
  185. package/src/util/aicoder-runner-v6.ts +2979 -0
  186. package/src/util/common.ts +649 -0
  187. package/src/util/customer-portal-password.ts +183 -0
  188. package/src/util/error-reporter.ts +332 -0
  189. package/src/util/error-tracking.ts +79 -0
  190. package/src/util/openai-usage-cost.ts +114 -0
  191. package/src/util/report-builder-unwinds.ts +180 -0
  192. package/src/util/runner-process-janitor.ts +219 -0
  193. package/src/util/schema-report-builder.ts +448 -0
  194. package/src/util/slow-query-reporter.ts +216 -0
  195. package/src/util/subscription-dependency-context.ts +1096 -0
  196. package/src/util/support-runner-v5.ts +6573 -0
  197. package/src/util/tokenizer.ts +38 -0
  198. package/src/workers/codex-runner.worker.ts +142 -0
  199. package/start_server.sh +5 -0
  200. package/tests/ai-assistant-corpus-build.ts +484 -0
  201. package/tests/ai-assistant-corpus-replay-e2e.ts +774 -0
  202. package/tests/ai-assistant-data-parity-e2e.ts +1989 -0
  203. package/tests/ai-assistant-eval-triage.ts +831 -0
  204. package/tests/ai-assistant-openai-e2e.ts +1061 -0
  205. package/tests/ai-assistant-openai-git-e2e.ts +155 -0
  206. package/tests/ai-assistant-preflight-matrix.ts +215 -0
  207. package/tests/ai-assistant-routing-eval.test.ts +560 -0
  208. package/tests/ai-assistant-snf-live-eval.ts +975 -0
  209. package/tests/ai-assistant-utils.test.ts +3057 -0
  210. package/tests/ai-manager-autopilot-snapshot.test.ts +193 -0
  211. package/tests/ai-manager-recovery-checkpoint.test.ts +1287 -0
  212. package/tests/ai-run-eval.test.ts +132 -0
  213. package/tests/ai-run-evidence.test.ts +2129 -0
  214. package/tests/ai-runner-contract.test.ts +488 -0
  215. package/tests/aicoder-runner-v6.test.ts +751 -0
  216. package/tests/error-reporter.test.ts +145 -0
  217. package/tests/method-publication-generator.test.ts +46 -0
  218. package/tests/report-builder-linking.test.ts +79 -0
  219. package/tests/resolveio-platform-intelligence.test.ts +352 -0
  220. package/tests/server-app-cron-owner.test.ts +127 -0
  221. package/tests/subscription-connect-race.test.ts +158 -0
  222. package/tests/subscription-dependency-context.test.ts +324 -0
  223. package/tests/subscription-manager-collection-tracking.test.ts +86 -0
  224. package/tests/subscription-manager-invalidation.test.ts +86 -0
  225. package/tests/support-runner-v5.test.ts +1473 -0
  226. package/tsconfig.json +34 -0
  227. package/ai/assistant-core-heuristics.d.ts +0 -11
  228. package/ai/assistant-core-heuristics.js +0 -356
  229. package/ai/assistant-core-heuristics.js.map +0 -1
  230. package/ai/resolveio-platform-intelligence-memory-corpus.d.ts +0 -3
  231. package/ai/resolveio-platform-intelligence-memory-corpus.js +0 -214
  232. package/ai/resolveio-platform-intelligence-memory-corpus.js.map +0 -1
  233. package/ai/resolveio-platform-intelligence-memory.d.ts +0 -20
  234. package/ai/resolveio-platform-intelligence-memory.js +0 -341
  235. package/ai/resolveio-platform-intelligence-memory.js.map +0 -1
  236. package/ai/resolveio-platform-intelligence-types.js +0 -4
  237. package/ai/resolveio-platform-intelligence-types.js.map +0 -1
  238. package/ai/resolveio-platform-intelligence.d.ts +0 -6
  239. package/ai/resolveio-platform-intelligence.js +0 -463
  240. package/ai/resolveio-platform-intelligence.js.map +0 -1
  241. package/client-server-app.d.ts +0 -1
  242. package/client-server-app.js +0 -68
  243. package/client-server-app.js.map +0 -1
  244. package/collections/ai-run.collection.d.ts +0 -3
  245. package/collections/ai-run.collection.js +0 -170
  246. package/collections/ai-run.collection.js.map +0 -1
  247. package/collections/ai-terminal-conversation.collection.d.ts +0 -2
  248. package/collections/ai-terminal-conversation.collection.js +0 -140
  249. package/collections/ai-terminal-conversation.collection.js.map +0 -1
  250. package/collections/ai-terminal-issue-report.collection.d.ts +0 -2
  251. package/collections/ai-terminal-issue-report.collection.js +0 -148
  252. package/collections/ai-terminal-issue-report.collection.js.map +0 -1
  253. package/collections/ai-terminal-message.collection.d.ts +0 -2
  254. package/collections/ai-terminal-message.collection.js +0 -121
  255. package/collections/ai-terminal-message.collection.js.map +0 -1
  256. package/collections/app-setting.collection.d.ts +0 -3
  257. package/collections/app-setting.collection.js +0 -103
  258. package/collections/app-setting.collection.js.map +0 -1
  259. package/collections/app-status.collection.d.ts +0 -3
  260. package/collections/app-status.collection.js +0 -57
  261. package/collections/app-status.collection.js.map +0 -1
  262. package/collections/communication-metric.collection.d.ts +0 -2
  263. package/collections/communication-metric.collection.js +0 -133
  264. package/collections/communication-metric.collection.js.map +0 -1
  265. package/collections/counter.collection.d.ts +0 -3
  266. package/collections/counter.collection.js +0 -56
  267. package/collections/counter.collection.js.map +0 -1
  268. package/collections/cron-job-history.collection.d.ts +0 -3
  269. package/collections/cron-job-history.collection.js +0 -137
  270. package/collections/cron-job-history.collection.js.map +0 -1
  271. package/collections/cron-job.collection.d.ts +0 -3
  272. package/collections/cron-job.collection.js +0 -92
  273. package/collections/cron-job.collection.js.map +0 -1
  274. package/collections/customer-notification.collection.d.ts +0 -3
  275. package/collections/customer-notification.collection.js +0 -130
  276. package/collections/customer-notification.collection.js.map +0 -1
  277. package/collections/customer-portal-password.collection.d.ts +0 -3
  278. package/collections/customer-portal-password.collection.js +0 -75
  279. package/collections/customer-portal-password.collection.js.map +0 -1
  280. package/collections/email-history.collection.d.ts +0 -3
  281. package/collections/email-history.collection.js +0 -134
  282. package/collections/email-history.collection.js.map +0 -1
  283. package/collections/email-verified.collection.d.ts +0 -3
  284. package/collections/email-verified.collection.js +0 -62
  285. package/collections/email-verified.collection.js.map +0 -1
  286. package/collections/file.collection.d.ts +0 -3
  287. package/collections/file.collection.js +0 -74
  288. package/collections/file.collection.js.map +0 -1
  289. package/collections/flag-update.collection.d.ts +0 -3
  290. package/collections/flag-update.collection.js +0 -57
  291. package/collections/flag-update.collection.js.map +0 -1
  292. package/collections/flag.collection.d.ts +0 -3
  293. package/collections/flag.collection.js +0 -57
  294. package/collections/flag.collection.js.map +0 -1
  295. package/collections/log-method-latency.collection.d.ts +0 -3
  296. package/collections/log-method-latency.collection.js +0 -77
  297. package/collections/log-method-latency.collection.js.map +0 -1
  298. package/collections/log-subscription.collection.d.ts +0 -3
  299. package/collections/log-subscription.collection.js +0 -80
  300. package/collections/log-subscription.collection.js.map +0 -1
  301. package/collections/log.collection.d.ts +0 -3
  302. package/collections/log.collection.js +0 -93
  303. package/collections/log.collection.js.map +0 -1
  304. package/collections/logged-in-users.collection.d.ts +0 -3
  305. package/collections/logged-in-users.collection.js +0 -67
  306. package/collections/logged-in-users.collection.js.map +0 -1
  307. package/collections/monitor-cpu.collection.d.ts +0 -3
  308. package/collections/monitor-cpu.collection.js +0 -65
  309. package/collections/monitor-cpu.collection.js.map +0 -1
  310. package/collections/monitor-function.collection.d.ts +0 -3
  311. package/collections/monitor-function.collection.js +0 -74
  312. package/collections/monitor-function.collection.js.map +0 -1
  313. package/collections/monitor-memory.collection.d.ts +0 -3
  314. package/collections/monitor-memory.collection.js +0 -77
  315. package/collections/monitor-memory.collection.js.map +0 -1
  316. package/collections/monitor-mongo.collection.d.ts +0 -3
  317. package/collections/monitor-mongo.collection.js +0 -71
  318. package/collections/monitor-mongo.collection.js.map +0 -1
  319. package/collections/notification.collection.d.ts +0 -3
  320. package/collections/notification.collection.js +0 -57
  321. package/collections/notification.collection.js.map +0 -1
  322. package/collections/openai-usage-ledger.collection.d.ts +0 -2
  323. package/collections/openai-usage-ledger.collection.js +0 -188
  324. package/collections/openai-usage-ledger.collection.js.map +0 -1
  325. package/collections/report-builder-dashboard-builder.collection.d.ts +0 -3
  326. package/collections/report-builder-dashboard-builder.collection.js +0 -109
  327. package/collections/report-builder-dashboard-builder.collection.js.map +0 -1
  328. package/collections/report-builder-library.collection.d.ts +0 -3
  329. package/collections/report-builder-library.collection.js +0 -87
  330. package/collections/report-builder-library.collection.js.map +0 -1
  331. package/collections/report-builder-report.collection.d.ts +0 -4
  332. package/collections/report-builder-report.collection.js +0 -184
  333. package/collections/report-builder-report.collection.js.map +0 -1
  334. package/collections/user-group.collection.d.ts +0 -4
  335. package/collections/user-group.collection.js +0 -89
  336. package/collections/user-group.collection.js.map +0 -1
  337. package/collections/user-guide.collection.d.ts +0 -3
  338. package/collections/user-guide.collection.js +0 -57
  339. package/collections/user-guide.collection.js.map +0 -1
  340. package/collections/user.collection.d.ts +0 -4
  341. package/collections/user.collection.js +0 -180
  342. package/collections/user.collection.js.map +0 -1
  343. package/cron/cron.d.ts +0 -14
  344. package/cron/cron.js +0 -216
  345. package/cron/cron.js.map +0 -1
  346. package/fixtures/cron-jobs.d.ts +0 -1
  347. package/fixtures/cron-jobs.js +0 -150
  348. package/fixtures/cron-jobs.js.map +0 -1
  349. package/fixtures/init.d.ts +0 -1
  350. package/fixtures/init.js +0 -91
  351. package/fixtures/init.js.map +0 -1
  352. package/http/auth.d.ts +0 -2
  353. package/http/auth.js +0 -951
  354. package/http/auth.js.map +0 -1
  355. package/http/health.d.ts +0 -1
  356. package/http/health.js +0 -11
  357. package/http/health.js.map +0 -1
  358. package/http/home.d.ts +0 -1
  359. package/http/home.js +0 -134
  360. package/http/home.js.map +0 -1
  361. package/http/slow-query-publication.d.ts +0 -2
  362. package/http/slow-query-publication.js +0 -99
  363. package/http/slow-query-publication.js.map +0 -1
  364. package/index.d.ts +0 -1
  365. package/index.js +0 -19
  366. package/index.js.map +0 -1
  367. package/managers/ai-assistant-codex-manager.manager.d.ts +0 -67
  368. package/managers/ai-assistant-codex-manager.manager.js +0 -1113
  369. package/managers/ai-assistant-codex-manager.manager.js.map +0 -1
  370. package/managers/ai-run-evidence.manager.d.ts +0 -36
  371. package/managers/ai-run-evidence.manager.js +0 -377
  372. package/managers/ai-run-evidence.manager.js.map +0 -1
  373. package/managers/communication-metric.manager.d.ts +0 -16
  374. package/managers/communication-metric.manager.js +0 -134
  375. package/managers/communication-metric.manager.js.map +0 -1
  376. package/managers/cron.manager.d.ts +0 -20
  377. package/managers/cron.manager.js +0 -534
  378. package/managers/cron.manager.js.map +0 -1
  379. package/managers/customer-notification-content.manager.d.ts +0 -55
  380. package/managers/customer-notification-content.manager.js +0 -158
  381. package/managers/customer-notification-content.manager.js.map +0 -1
  382. package/managers/diagnostic-manager-bootstrap.d.ts +0 -9
  383. package/managers/diagnostic-manager-bootstrap.js +0 -260
  384. package/managers/diagnostic-manager-bootstrap.js.map +0 -1
  385. package/managers/error-auto-fix.manager.d.ts +0 -149
  386. package/managers/error-auto-fix.manager.js +0 -3064
  387. package/managers/error-auto-fix.manager.js.map +0 -1
  388. package/managers/local-log.manager.d.ts +0 -18
  389. package/managers/local-log.manager.js +0 -88
  390. package/managers/local-log.manager.js.map +0 -1
  391. package/managers/method.manager.d.ts +0 -84
  392. package/managers/method.manager.js +0 -1964
  393. package/managers/method.manager.js.map +0 -1
  394. package/managers/mongo.manager.d.ts +0 -224
  395. package/managers/mongo.manager.js +0 -5000
  396. package/managers/mongo.manager.js.map +0 -1
  397. package/managers/monitor.manager.d.ts +0 -70
  398. package/managers/monitor.manager.js +0 -550
  399. package/managers/monitor.manager.js.map +0 -1
  400. package/managers/openai-usage-ledger.manager.d.ts +0 -30
  401. package/managers/openai-usage-ledger.manager.js +0 -142
  402. package/managers/openai-usage-ledger.manager.js.map +0 -1
  403. package/managers/slow-query-verifier.manager.d.ts +0 -144
  404. package/managers/slow-query-verifier.manager.js +0 -3857
  405. package/managers/slow-query-verifier.manager.js.map +0 -1
  406. package/managers/slow-query.manager.d.ts +0 -28
  407. package/managers/slow-query.manager.js +0 -468
  408. package/managers/slow-query.manager.js.map +0 -1
  409. package/managers/subscription.manager.d.ts +0 -169
  410. package/managers/subscription.manager.js +0 -3434
  411. package/managers/subscription.manager.js.map +0 -1
  412. package/managers/websocket.manager.d.ts +0 -73
  413. package/managers/websocket.manager.js +0 -673
  414. package/managers/websocket.manager.js.map +0 -1
  415. package/managers/worker-dispatcher.manager.d.ts +0 -120
  416. package/managers/worker-dispatcher.manager.js +0 -1266
  417. package/managers/worker-dispatcher.manager.js.map +0 -1
  418. package/managers/worker-server.manager.d.ts +0 -35
  419. package/managers/worker-server.manager.js +0 -582
  420. package/managers/worker-server.manager.js.map +0 -1
  421. package/methods/accounts.d.ts +0 -2
  422. package/methods/accounts.js +0 -624
  423. package/methods/accounts.js.map +0 -1
  424. package/methods/ai-terminal.d.ts +0 -338
  425. package/methods/ai-terminal.js +0 -23454
  426. package/methods/ai-terminal.js.map +0 -1
  427. package/methods/app-settings.d.ts +0 -2
  428. package/methods/app-settings.js +0 -169
  429. package/methods/app-settings.js.map +0 -1
  430. package/methods/aws.d.ts +0 -2
  431. package/methods/aws.js +0 -877
  432. package/methods/aws.js.map +0 -1
  433. package/methods/collections.d.ts +0 -2
  434. package/methods/collections.js +0 -719
  435. package/methods/collections.js.map +0 -1
  436. package/methods/counters.d.ts +0 -2
  437. package/methods/counters.js +0 -113
  438. package/methods/counters.js.map +0 -1
  439. package/methods/cron-jobs.d.ts +0 -2
  440. package/methods/cron-jobs.js +0 -2475
  441. package/methods/cron-jobs.js.map +0 -1
  442. package/methods/customer-notifications.d.ts +0 -2
  443. package/methods/customer-notifications.js +0 -528
  444. package/methods/customer-notifications.js.map +0 -1
  445. package/methods/diagnostics.d.ts +0 -2
  446. package/methods/diagnostics.js +0 -703
  447. package/methods/diagnostics.js.map +0 -1
  448. package/methods/flag-updates.d.ts +0 -2
  449. package/methods/flag-updates.js +0 -8
  450. package/methods/flag-updates.js.map +0 -1
  451. package/methods/flags.d.ts +0 -2
  452. package/methods/flags.js +0 -8
  453. package/methods/flags.js.map +0 -1
  454. package/methods/logs.d.ts +0 -2
  455. package/methods/logs.js +0 -751
  456. package/methods/logs.js.map +0 -1
  457. package/methods/mongo-explorer.d.ts +0 -2
  458. package/methods/mongo-explorer.js +0 -1808
  459. package/methods/mongo-explorer.js.map +0 -1
  460. package/methods/monitor.d.ts +0 -2
  461. package/methods/monitor.js +0 -543
  462. package/methods/monitor.js.map +0 -1
  463. package/methods/pdf.d.ts +0 -2
  464. package/methods/pdf.js +0 -1216
  465. package/methods/pdf.js.map +0 -1
  466. package/methods/publications.d.ts +0 -1
  467. package/methods/publications.js +0 -183
  468. package/methods/publications.js.map +0 -1
  469. package/methods/report-builder.d.ts +0 -2
  470. package/methods/report-builder.js +0 -3094
  471. package/methods/report-builder.js.map +0 -1
  472. package/methods/support.d.ts +0 -2
  473. package/methods/support.js +0 -430
  474. package/methods/support.js.map +0 -1
  475. package/models/ai-run.model.d.ts +0 -19
  476. package/models/ai-run.model.js +0 -4
  477. package/models/ai-run.model.js.map +0 -1
  478. package/models/ai-terminal-conversation.model.d.ts +0 -17
  479. package/models/ai-terminal-conversation.model.js +0 -4
  480. package/models/ai-terminal-conversation.model.js.map +0 -1
  481. package/models/ai-terminal-issue-report.model.d.ts +0 -19
  482. package/models/ai-terminal-issue-report.model.js +0 -4
  483. package/models/ai-terminal-issue-report.model.js.map +0 -1
  484. package/models/ai-terminal-message.model.d.ts +0 -22
  485. package/models/ai-terminal-message.model.js +0 -4
  486. package/models/ai-terminal-message.model.js.map +0 -1
  487. package/models/app-setting.model.d.ts +0 -16
  488. package/models/app-setting.model.js +0 -4
  489. package/models/app-setting.model.js.map +0 -1
  490. package/models/app-status.model.js +0 -4
  491. package/models/app-status.model.js.map +0 -1
  492. package/models/billing-logged-in-users.model.js +0 -4
  493. package/models/billing-logged-in-users.model.js.map +0 -1
  494. package/models/collection-document.model.d.ts +0 -21
  495. package/models/collection-document.model.js +0 -4
  496. package/models/collection-document.model.js.map +0 -1
  497. package/models/communication-metric.model.d.ts +0 -20
  498. package/models/communication-metric.model.js +0 -4
  499. package/models/communication-metric.model.js.map +0 -1
  500. package/models/counter.model.js +0 -4
  501. package/models/counter.model.js.map +0 -1
  502. package/models/cron-job-history.model.d.ts +0 -15
  503. package/models/cron-job-history.model.js +0 -4
  504. package/models/cron-job-history.model.js.map +0 -1
  505. package/models/cron-job.model.d.ts +0 -14
  506. package/models/cron-job.model.js +0 -4
  507. package/models/cron-job.model.js.map +0 -1
  508. package/models/customer-notification.model.d.ts +0 -26
  509. package/models/customer-notification.model.js +0 -4
  510. package/models/customer-notification.model.js.map +0 -1
  511. package/models/customer-portal-password.model.d.ts +0 -11
  512. package/models/customer-portal-password.model.js +0 -4
  513. package/models/customer-portal-password.model.js.map +0 -1
  514. package/models/dialog.model.d.ts +0 -23
  515. package/models/dialog.model.js +0 -4
  516. package/models/dialog.model.js.map +0 -1
  517. package/models/email-history.model.d.ts +0 -32
  518. package/models/email-history.model.js.map +0 -1
  519. package/models/email-verified.model.js +0 -4
  520. package/models/email-verified.model.js.map +0 -1
  521. package/models/file.model.js +0 -4
  522. package/models/file.model.js.map +0 -1
  523. package/models/flag-update.model.js +0 -4
  524. package/models/flag-update.model.js.map +0 -1
  525. package/models/flag.model.js +0 -4
  526. package/models/flag.model.js.map +0 -1
  527. package/models/log-method-latency.model.d.ts +0 -10
  528. package/models/log-method-latency.model.js +0 -4
  529. package/models/log-method-latency.model.js.map +0 -1
  530. package/models/log-subscription.model.js +0 -4
  531. package/models/log-subscription.model.js.map +0 -1
  532. package/models/log.model.d.ts +0 -17
  533. package/models/log.model.js +0 -4
  534. package/models/log.model.js.map +0 -1
  535. package/models/logged-in-users.model.js +0 -4
  536. package/models/logged-in-users.model.js.map +0 -1
  537. package/models/method-response.model.js +0 -4
  538. package/models/method-response.model.js.map +0 -1
  539. package/models/method.model.d.ts +0 -26
  540. package/models/method.model.js +0 -4
  541. package/models/method.model.js.map +0 -1
  542. package/models/monitor-cpu.model.js +0 -4
  543. package/models/monitor-cpu.model.js.map +0 -1
  544. package/models/monitor-function.model.d.ts +0 -14
  545. package/models/monitor-function.model.js +0 -4
  546. package/models/monitor-function.model.js.map +0 -1
  547. package/models/monitor-memory.model.d.ts +0 -15
  548. package/models/monitor-memory.model.js +0 -4
  549. package/models/monitor-memory.model.js.map +0 -1
  550. package/models/monitor-mongo.model.d.ts +0 -13
  551. package/models/monitor-mongo.model.js +0 -4
  552. package/models/monitor-mongo.model.js.map +0 -1
  553. package/models/notification.model.js +0 -4
  554. package/models/notification.model.js.map +0 -1
  555. package/models/openai-usage-ledger.model.d.ts +0 -30
  556. package/models/openai-usage-ledger.model.js +0 -4
  557. package/models/openai-usage-ledger.model.js.map +0 -1
  558. package/models/pagination.model.d.ts +0 -11
  559. package/models/pagination.model.js +0 -28
  560. package/models/pagination.model.js.map +0 -1
  561. package/models/permission.model.d.ts +0 -12
  562. package/models/permission.model.js +0 -4
  563. package/models/permission.model.js.map +0 -1
  564. package/models/report-builder-dashboard-builder.model.d.ts +0 -25
  565. package/models/report-builder-dashboard-builder.model.js +0 -4
  566. package/models/report-builder-dashboard-builder.model.js.map +0 -1
  567. package/models/report-builder-library.model.d.ts +0 -17
  568. package/models/report-builder-library.model.js +0 -4
  569. package/models/report-builder-library.model.js.map +0 -1
  570. package/models/report-builder-report.model.d.ts +0 -121
  571. package/models/report-builder-report.model.js +0 -4
  572. package/models/report-builder-report.model.js.map +0 -1
  573. package/models/report-builder.model.d.ts +0 -61
  574. package/models/report-builder.model.js +0 -4
  575. package/models/report-builder.model.js.map +0 -1
  576. package/models/select-data-label.model.d.ts +0 -9
  577. package/models/select-data-label.model.js +0 -4
  578. package/models/select-data-label.model.js.map +0 -1
  579. package/models/server-message.model.d.ts +0 -32
  580. package/models/server-message.model.js +0 -4
  581. package/models/server-message.model.js.map +0 -1
  582. package/models/slow-query-report.model.d.ts +0 -23
  583. package/models/slow-query-report.model.js +0 -4
  584. package/models/slow-query-report.model.js.map +0 -1
  585. package/models/subscription.model.d.ts +0 -31
  586. package/models/subscription.model.js +0 -4
  587. package/models/subscription.model.js.map +0 -1
  588. package/models/support-ticket.model.d.ts +0 -87
  589. package/models/support-ticket.model.js +0 -4
  590. package/models/support-ticket.model.js.map +0 -1
  591. package/models/user-group.model.d.ts +0 -20
  592. package/models/user-group.model.js +0 -4
  593. package/models/user-group.model.js.map +0 -1
  594. package/models/user-guide.model.js +0 -4
  595. package/models/user-guide.model.js.map +0 -1
  596. package/models/user.model.d.ts +0 -84
  597. package/models/user.model.js +0 -4
  598. package/models/user.model.js.map +0 -1
  599. package/private/images/ResolveIO.png +0 -0
  600. package/public_api.js +0 -127
  601. package/public_api.js.map +0 -1
  602. package/publications/ai-terminal.d.ts +0 -1
  603. package/publications/ai-terminal.js +0 -122
  604. package/publications/ai-terminal.js.map +0 -1
  605. package/publications/app-settings.d.ts +0 -2
  606. package/publications/app-settings.js +0 -28
  607. package/publications/app-settings.js.map +0 -1
  608. package/publications/app-status.d.ts +0 -2
  609. package/publications/app-status.js +0 -16
  610. package/publications/app-status.js.map +0 -1
  611. package/publications/cron-jobs.d.ts +0 -2
  612. package/publications/cron-jobs.js +0 -88
  613. package/publications/cron-jobs.js.map +0 -1
  614. package/publications/customer-notifications.d.ts +0 -2
  615. package/publications/customer-notifications.js +0 -161
  616. package/publications/customer-notifications.js.map +0 -1
  617. package/publications/files.d.ts +0 -2
  618. package/publications/files.js +0 -36
  619. package/publications/files.js.map +0 -1
  620. package/publications/flags-update.d.ts +0 -2
  621. package/publications/flags-update.js +0 -22
  622. package/publications/flags-update.js.map +0 -1
  623. package/publications/flags.d.ts +0 -2
  624. package/publications/flags.js +0 -22
  625. package/publications/flags.js.map +0 -1
  626. package/publications/logs.d.ts +0 -2
  627. package/publications/logs.js +0 -164
  628. package/publications/logs.js.map +0 -1
  629. package/publications/notifications.d.ts +0 -2
  630. package/publications/notifications.js +0 -16
  631. package/publications/notifications.js.map +0 -1
  632. package/publications/report-builder-dashboard-builders.d.ts +0 -2
  633. package/publications/report-builder-dashboard-builders.js +0 -42
  634. package/publications/report-builder-dashboard-builders.js.map +0 -1
  635. package/publications/report-builder-libraries.d.ts +0 -2
  636. package/publications/report-builder-libraries.js +0 -90
  637. package/publications/report-builder-libraries.js.map +0 -1
  638. package/publications/report-builder-reports.d.ts +0 -2
  639. package/publications/report-builder-reports.js +0 -50
  640. package/publications/report-builder-reports.js.map +0 -1
  641. package/publications/super-admin.d.ts +0 -2
  642. package/publications/super-admin.js +0 -16
  643. package/publications/super-admin.js.map +0 -1
  644. package/publications/user-groups.d.ts +0 -1
  645. package/publications/user-groups.js +0 -16
  646. package/publications/user-groups.js.map +0 -1
  647. package/publications/user-guides.d.ts +0 -1
  648. package/publications/user-guides.js +0 -16
  649. package/publications/user-guides.js.map +0 -1
  650. package/resolveio-server-app.d.ts +0 -70
  651. package/resolveio-server-app.js +0 -801
  652. package/resolveio-server-app.js.map +0 -1
  653. package/server-app.d.ts +0 -228
  654. package/server-app.js +0 -3566
  655. package/server-app.js.map +0 -1
  656. package/services/codex-client.d.ts +0 -128
  657. package/services/codex-client.js +0 -1629
  658. package/services/codex-client.js.map +0 -1
  659. package/services/openai-client.d.ts +0 -46
  660. package/services/openai-client.js +0 -318
  661. package/services/openai-client.js.map +0 -1
  662. package/types/error-report.d.ts +0 -25
  663. package/types/error-report.js +0 -4
  664. package/types/error-report.js.map +0 -1
  665. package/types/slow-query-report.d.ts +0 -27
  666. package/types/slow-query-report.js +0 -6
  667. package/types/slow-query-report.js.map +0 -1
  668. package/util/ai-qa-policy.d.ts +0 -124
  669. package/util/ai-qa-policy.js +0 -736
  670. package/util/ai-qa-policy.js.map +0 -1
  671. package/util/ai-run-evidence-adapters.d.ts +0 -109
  672. package/util/ai-run-evidence-adapters.js +0 -4124
  673. package/util/ai-run-evidence-adapters.js.map +0 -1
  674. package/util/ai-run-evidence-dashboard.d.ts +0 -84
  675. package/util/ai-run-evidence-dashboard.js +0 -336
  676. package/util/ai-run-evidence-dashboard.js.map +0 -1
  677. package/util/ai-run-evidence-eval.d.ts +0 -86
  678. package/util/ai-run-evidence-eval.js +0 -1018
  679. package/util/ai-run-evidence-eval.js.map +0 -1
  680. package/util/ai-run-evidence.d.ts +0 -244
  681. package/util/ai-run-evidence.js +0 -852
  682. package/util/ai-run-evidence.js.map +0 -1
  683. package/util/ai-runner-artifacts.d.ts +0 -82
  684. package/util/ai-runner-artifacts.js +0 -713
  685. package/util/ai-runner-artifacts.js.map +0 -1
  686. package/util/ai-runner-manager-autopilot.d.ts +0 -210
  687. package/util/ai-runner-manager-autopilot.js +0 -642
  688. package/util/ai-runner-manager-autopilot.js.map +0 -1
  689. package/util/ai-runner-manager-policy.d.ts +0 -767
  690. package/util/ai-runner-manager-policy.js +0 -3304
  691. package/util/ai-runner-manager-policy.js.map +0 -1
  692. package/util/ai-runner-qa-auth.d.ts +0 -5
  693. package/util/ai-runner-qa-auth.js +0 -822
  694. package/util/ai-runner-qa-auth.js.map +0 -1
  695. package/util/ai-runner-qa-tools.d.ts +0 -26
  696. package/util/ai-runner-qa-tools.js +0 -3029
  697. package/util/ai-runner-qa-tools.js.map +0 -1
  698. package/util/aicoder-runner-v6.d.ts +0 -423
  699. package/util/aicoder-runner-v6.js +0 -2177
  700. package/util/aicoder-runner-v6.js.map +0 -1
  701. package/util/common.d.ts +0 -31
  702. package/util/common.js +0 -683
  703. package/util/common.js.map +0 -1
  704. package/util/customer-portal-password.d.ts +0 -13
  705. package/util/customer-portal-password.js +0 -209
  706. package/util/customer-portal-password.js.map +0 -1
  707. package/util/error-reporter.d.ts +0 -52
  708. package/util/error-reporter.js +0 -326
  709. package/util/error-reporter.js.map +0 -1
  710. package/util/error-tracking.d.ts +0 -13
  711. package/util/error-tracking.js +0 -120
  712. package/util/error-tracking.js.map +0 -1
  713. package/util/openai-usage-cost.d.ts +0 -6
  714. package/util/openai-usage-cost.js +0 -103
  715. package/util/openai-usage-cost.js.map +0 -1
  716. package/util/report-builder-unwinds.d.ts +0 -15
  717. package/util/report-builder-unwinds.js +0 -156
  718. package/util/report-builder-unwinds.js.map +0 -1
  719. package/util/runner-process-janitor.d.ts +0 -27
  720. package/util/runner-process-janitor.js +0 -208
  721. package/util/runner-process-janitor.js.map +0 -1
  722. package/util/schema-report-builder.d.ts +0 -6
  723. package/util/schema-report-builder.js +0 -481
  724. package/util/schema-report-builder.js.map +0 -1
  725. package/util/slow-query-reporter.d.ts +0 -28
  726. package/util/slow-query-reporter.js +0 -226
  727. package/util/slow-query-reporter.js.map +0 -1
  728. package/util/subscription-dependency-context.d.ts +0 -34
  729. package/util/subscription-dependency-context.js +0 -1283
  730. package/util/subscription-dependency-context.js.map +0 -1
  731. package/util/support-runner-v5.d.ts +0 -1018
  732. package/util/support-runner-v5.js +0 -4615
  733. package/util/support-runner-v5.js.map +0 -1
  734. package/util/tokenizer.d.ts +0 -5
  735. package/util/tokenizer.js +0 -41
  736. package/util/tokenizer.js.map +0 -1
  737. package/workers/codex-runner.worker.d.ts +0 -1
  738. package/workers/codex-runner.worker.js +0 -192
  739. package/workers/codex-runner.worker.js.map +0 -1
  740. /package/{private → src/private}/email-templates/enrollment.html +0 -0
  741. /package/{private → src/private}/email-templates/forgot-password.html +0 -0
  742. /package/{private → src/private}/email-templates/support-ticket-deleted.html +0 -0
  743. /package/{private → src/private}/email-templates/support-ticket-modified.html +0 -0
  744. /package/{private → src/private}/email-templates/support-ticket.html +0 -0
  745. /package/{public_api.d.ts → src/public_api.ts} +0 -0
@@ -0,0 +1,1185 @@
1
+ export type AIRunSource =
2
+ | 'support_ticket'
3
+ | 'aicoder_app'
4
+ | 'ai_assistant'
5
+ | 'qa_runner'
6
+ | 'unknown';
7
+
8
+ export type AIRunOutcomeLabel =
9
+ | 'accepted'
10
+ | 'rejected'
11
+ | 'qa_incomplete'
12
+ | 'qa_infra_failed'
13
+ | 'build_failed'
14
+ | 'release_blocked'
15
+ | 'manual_handoff'
16
+ | 'false_pass'
17
+ | 'stopped'
18
+ | 'unknown';
19
+
20
+ export type AIRunEventType =
21
+ | 'model_call'
22
+ | 'log'
23
+ | 'qa_infra'
24
+ | 'qa_compile'
25
+ | 'qa_route_probe'
26
+ | 'qa_business_assertion'
27
+ | 'scorecard'
28
+ | 'deploy'
29
+ | 'publish'
30
+ | 'hotfix'
31
+ | 'assistant_message'
32
+ | 'assistant_query'
33
+ | 'git_commit'
34
+ | 'usage'
35
+ | 'human_intervention';
36
+
37
+ export type AIRunGateStatus = 'pass' | 'fail' | 'warn' | 'blocked' | 'skipped';
38
+
39
+ export type AIQaCheckStatus = 'pass' | 'fail' | 'blocked' | 'warn' | 'skipped' | 'unknown';
40
+
41
+ export type AIQaCompileStatus = 'pass' | 'fail' | 'blocked' | 'stale' | 'skipped' | 'unknown';
42
+
43
+ export type AIQaOutcome =
44
+ | 'infra_failed'
45
+ | 'compile_failed'
46
+ | 'route_failed'
47
+ | 'route_only_pass'
48
+ | 'business_assertion_passed'
49
+ | 'business_assertion_failed'
50
+ | 'incomplete';
51
+
52
+ export interface AIRunEvent {
53
+ id?: string;
54
+ type: AIRunEventType;
55
+ source?: AIRunSource | string;
56
+ message?: string;
57
+ category?: string;
58
+ artifactPaths?: string[];
59
+ metadata?: Record<string, any>;
60
+ recordedAt?: Date | string;
61
+ }
62
+
63
+ export interface AIRunGateResult {
64
+ key: string;
65
+ label: string;
66
+ status: AIRunGateStatus;
67
+ reason: string;
68
+ evidenceRefs: string[];
69
+ recordedAt: string;
70
+ metadata?: Record<string, any>;
71
+ }
72
+
73
+ export interface AIRunCost {
74
+ inputTokens: number;
75
+ cachedInputTokens: number;
76
+ outputTokens: number;
77
+ totalTokens: number;
78
+ estimatedUsd: number;
79
+ models: string[];
80
+ categories: Record<string, {
81
+ inputTokens: number;
82
+ cachedInputTokens: number;
83
+ outputTokens: number;
84
+ totalTokens: number;
85
+ estimatedUsd: number;
86
+ count: number;
87
+ }>;
88
+ sources?: Record<string, {
89
+ inputTokens: number;
90
+ cachedInputTokens: number;
91
+ outputTokens: number;
92
+ totalTokens: number;
93
+ estimatedUsd: number;
94
+ count: number;
95
+ manualCount: number;
96
+ untrackedCount: number;
97
+ }>;
98
+ surfaces?: Record<string, {
99
+ totalTokens: number;
100
+ estimatedUsd: number;
101
+ count: number;
102
+ }>;
103
+ manualEstimatedUsd?: number;
104
+ untrackedEstimatedUsd?: number;
105
+ untrackedWarnings?: string[];
106
+ wallTimeMs?: number;
107
+ retries?: number;
108
+ }
109
+
110
+ export interface OpenAIUsageCostEntry {
111
+ model?: string;
112
+ category?: string;
113
+ id_request?: string;
114
+ idRequest?: string;
115
+ id_conversation?: string;
116
+ idConversation?: string;
117
+ timestamp?: Date | string;
118
+ input_tokens?: number;
119
+ inputTokens?: number;
120
+ cached_input_tokens?: number;
121
+ cachedInputTokens?: number;
122
+ output_tokens?: number;
123
+ outputTokens?: number;
124
+ total_tokens?: number;
125
+ totalTokens?: number;
126
+ cost_estimate?: number;
127
+ estimatedUsd?: number;
128
+ usage_source?: string;
129
+ usageSource?: string;
130
+ usage_surface?: string;
131
+ usageSurface?: string;
132
+ usage_phase?: string;
133
+ usagePhase?: string;
134
+ cost_basis?: string;
135
+ costBasis?: string;
136
+ is_manual?: boolean;
137
+ isManual?: boolean;
138
+ is_untracked?: boolean;
139
+ isUntracked?: boolean;
140
+ untracked_reason?: string;
141
+ untrackedReason?: string;
142
+ [key: string]: any;
143
+ }
144
+
145
+ export interface AIQaInfraCheck {
146
+ name: string;
147
+ status: AIQaCheckStatus;
148
+ message?: string;
149
+ path?: string;
150
+ durationMs?: number;
151
+ metadata?: Record<string, any>;
152
+ checkedAt?: Date | string;
153
+ }
154
+
155
+ export interface AIQaCompileResult {
156
+ status: AIQaCompileStatus;
157
+ command?: string;
158
+ artifactPath?: string;
159
+ message?: string;
160
+ durationMs?: number;
161
+ staleEvidence?: boolean;
162
+ recordedAt?: Date | string;
163
+ metadata?: Record<string, any>;
164
+ }
165
+
166
+ export interface AIQaRouteProbe {
167
+ route: string;
168
+ status: AIQaCheckStatus;
169
+ screenshot?: string;
170
+ caption?: string;
171
+ shellOnly?: boolean;
172
+ authenticated?: boolean;
173
+ consoleErrors?: string[];
174
+ networkErrors?: string[];
175
+ message?: string;
176
+ recordedAt?: Date | string;
177
+ metadata?: Record<string, any>;
178
+ }
179
+
180
+ export interface AIQaBusinessAssertion {
181
+ assertion: string;
182
+ status: AIQaCheckStatus;
183
+ workflow?: string;
184
+ route?: string;
185
+ action?: string;
186
+ expected?: string;
187
+ observed?: string;
188
+ dataProof?: string;
189
+ mongoDelta?: Record<string, any>;
190
+ artifactPaths?: string[];
191
+ message?: string;
192
+ recordedAt?: Date | string;
193
+ metadata?: Record<string, any>;
194
+ }
195
+
196
+ export interface AIQaArtifact {
197
+ type: 'screenshot' | 'trace' | 'console_log' | 'network_log' | 'coverage_matrix' | 'seed_data' | 'script' | 'other';
198
+ path?: string;
199
+ url?: string;
200
+ title?: string;
201
+ caption?: string;
202
+ metadata?: Record<string, any>;
203
+ }
204
+
205
+ export interface AIQaRun {
206
+ outcome: AIQaOutcome;
207
+ infraChecks: AIQaInfraCheck[];
208
+ compile?: AIQaCompileResult;
209
+ routeProbes: AIQaRouteProbe[];
210
+ businessAssertions: AIQaBusinessAssertion[];
211
+ artifacts: AIQaArtifact[];
212
+ gateResults: AIRunGateResult[];
213
+ updatedAt: string;
214
+ }
215
+
216
+ export interface AIRun {
217
+ id?: string;
218
+ source: AIRunSource;
219
+ sourceIds: Record<string, string>;
220
+ title?: string;
221
+ status?: string;
222
+ phase?: string;
223
+ startedAt?: Date | string;
224
+ completedAt?: Date | string;
225
+ outcome: AIRunOutcomeLabel;
226
+ events: AIRunEvent[];
227
+ gates: AIRunGateResult[];
228
+ qa?: AIQaRun;
229
+ cost?: AIRunCost;
230
+ nextAction?: string;
231
+ warnings?: string[];
232
+ metadata?: Record<string, any>;
233
+ }
234
+
235
+ export interface AIRunTrainingExample {
236
+ runId: string;
237
+ source: AIRunSource;
238
+ inputSummary: string;
239
+ actionSummary: string;
240
+ outcome: AIRunOutcomeLabel;
241
+ evidence: string[];
242
+ cost?: AIRunCost;
243
+ metadata?: Record<string, any>;
244
+ }
245
+
246
+ export interface AIQaEvaluationInput {
247
+ infraChecks?: AIQaInfraCheck[];
248
+ compile?: AIQaCompileResult;
249
+ routeProbes?: AIQaRouteProbe[];
250
+ businessAssertions?: AIQaBusinessAssertion[];
251
+ artifacts?: AIQaArtifact[];
252
+ now?: Date | string;
253
+ }
254
+
255
+ export interface AIRunOutcomeInput {
256
+ source?: AIRunSource;
257
+ status?: string;
258
+ phase?: string;
259
+ qa?: AIQaRun | AIQaEvaluationInput;
260
+ gates?: AIRunGateResult[];
261
+ scorecardPassed?: boolean;
262
+ scorecardStatus?: string;
263
+ deployStatus?: string;
264
+ publishStatus?: string;
265
+ sampleDataStatus?: string;
266
+ manualHandoff?: boolean;
267
+ stopped?: boolean;
268
+ rejected?: boolean;
269
+ explicitAccepted?: boolean;
270
+ terminal?: boolean;
271
+ now?: Date | string;
272
+ }
273
+
274
+ export interface AIRunOutcomeDecision {
275
+ outcome: AIRunOutcomeLabel;
276
+ reason: string;
277
+ nextAction: string;
278
+ gates: AIRunGateResult[];
279
+ warnings: string[];
280
+ recordedAt: string;
281
+ }
282
+
283
+ function isoNow(value?: Date | string): string {
284
+ if (value instanceof Date) {
285
+ return value.toISOString();
286
+ }
287
+ const parsed = value ? new Date(value) : new Date();
288
+ if (Number.isFinite(parsed.getTime())) {
289
+ return parsed.toISOString();
290
+ }
291
+ return new Date().toISOString();
292
+ }
293
+
294
+ function cleanText(value: any, max = 1000): string {
295
+ return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max);
296
+ }
297
+
298
+ function cleanUsageNumber(value: any): number {
299
+ const parsed = Number(value);
300
+ return Number.isFinite(parsed) ? parsed : 0;
301
+ }
302
+
303
+ function cleanUsageDate(value: any): Date | undefined {
304
+ if (!value) {
305
+ return undefined;
306
+ }
307
+ const date = value instanceof Date ? value : new Date(value);
308
+ return Number.isFinite(date.getTime()) ? date : undefined;
309
+ }
310
+
311
+ export function isCumulativeCodexUsageEntry(entry: OpenAIUsageCostEntry): boolean {
312
+ return cleanText(entry?.category, 180).toLowerCase().startsWith('ai-dashboard-codex:');
313
+ }
314
+
315
+ export function resolveOpenAIUsageThreadKey(entry: OpenAIUsageCostEntry): string {
316
+ const conversationId = cleanText(entry?.id_conversation ?? entry?.idConversation, 240);
317
+ if (conversationId) {
318
+ return conversationId;
319
+ }
320
+ return cleanText(entry?.id_request ?? entry?.idRequest, 240);
321
+ }
322
+
323
+ export function normalizeOpenAIUsageRowsForCosting<T extends OpenAIUsageCostEntry>(rows: T[] = []): T[] {
324
+ if (!Array.isArray(rows) || !rows.length) {
325
+ return [];
326
+ }
327
+ const sortedRows = rows
328
+ .map((row, index) => ({
329
+ ...row,
330
+ _sortIndex: index
331
+ }))
332
+ .sort((a, b) => {
333
+ const timeA = cleanUsageDate(a.timestamp)?.getTime() || 0;
334
+ const timeB = cleanUsageDate(b.timestamp)?.getTime() || 0;
335
+ if (timeA !== timeB) {
336
+ return timeA - timeB;
337
+ }
338
+ const requestCompare = cleanText(a.id_request ?? a.idRequest, 240)
339
+ .localeCompare(cleanText(b.id_request ?? b.idRequest, 240));
340
+ if (requestCompare) {
341
+ return requestCompare;
342
+ }
343
+ const conversationCompare = cleanText(a.id_conversation ?? a.idConversation, 240)
344
+ .localeCompare(cleanText(b.id_conversation ?? b.idConversation, 240));
345
+ if (conversationCompare) {
346
+ return conversationCompare;
347
+ }
348
+ return cleanUsageNumber(a._sortIndex) - cleanUsageNumber(b._sortIndex);
349
+ });
350
+ const previousByThread = new Map<string, {
351
+ inputTokens: number;
352
+ cachedInputTokens: number;
353
+ outputTokens: number;
354
+ totalTokens: number;
355
+ estimatedUsd: number;
356
+ }>();
357
+ return sortedRows.map((row) => {
358
+ const inputTokens = cleanUsageNumber(row.input_tokens ?? row.inputTokens);
359
+ const cachedInputTokens = cleanUsageNumber(row.cached_input_tokens ?? row.cachedInputTokens);
360
+ const outputTokens = cleanUsageNumber(row.output_tokens ?? row.outputTokens);
361
+ const totalTokens = cleanUsageNumber(row.total_tokens ?? row.totalTokens ?? (inputTokens + outputTokens));
362
+ const estimatedUsd = cleanUsageNumber(row.cost_estimate ?? row.estimatedUsd);
363
+ const threadKey = isCumulativeCodexUsageEntry(row) ? resolveOpenAIUsageThreadKey(row) : '';
364
+ let normalizedInputTokens = inputTokens;
365
+ let normalizedCachedInputTokens = cachedInputTokens;
366
+ let normalizedOutputTokens = outputTokens;
367
+ let normalizedTotalTokens = totalTokens;
368
+ let normalizedEstimatedUsd = estimatedUsd;
369
+ if (threadKey) {
370
+ const previous = previousByThread.get(threadKey);
371
+ if (previous
372
+ && inputTokens >= previous.inputTokens
373
+ && cachedInputTokens >= previous.cachedInputTokens
374
+ && outputTokens >= previous.outputTokens
375
+ && totalTokens >= previous.totalTokens
376
+ && estimatedUsd >= previous.estimatedUsd
377
+ ) {
378
+ normalizedInputTokens = Math.max(0, inputTokens - previous.inputTokens);
379
+ normalizedCachedInputTokens = Math.max(0, cachedInputTokens - previous.cachedInputTokens);
380
+ normalizedOutputTokens = Math.max(0, outputTokens - previous.outputTokens);
381
+ normalizedTotalTokens = Math.max(0, totalTokens - previous.totalTokens);
382
+ normalizedEstimatedUsd = Math.max(0, estimatedUsd - previous.estimatedUsd);
383
+ }
384
+ previousByThread.set(threadKey, {
385
+ inputTokens,
386
+ cachedInputTokens,
387
+ outputTokens,
388
+ totalTokens,
389
+ estimatedUsd
390
+ });
391
+ }
392
+ const resolvedTotalTokens = normalizedTotalTokens || (normalizedInputTokens + normalizedOutputTokens);
393
+ const resolvedEstimatedUsd = Number(normalizedEstimatedUsd.toFixed(6));
394
+ return {
395
+ ...row,
396
+ input_tokens: normalizedInputTokens,
397
+ inputTokens: normalizedInputTokens,
398
+ cached_input_tokens: normalizedCachedInputTokens,
399
+ cachedInputTokens: normalizedCachedInputTokens,
400
+ output_tokens: normalizedOutputTokens,
401
+ outputTokens: normalizedOutputTokens,
402
+ total_tokens: resolvedTotalTokens,
403
+ totalTokens: resolvedTotalTokens,
404
+ cost_estimate: resolvedEstimatedUsd,
405
+ estimatedUsd: resolvedEstimatedUsd
406
+ } as T;
407
+ });
408
+ }
409
+
410
+ function cleanList(values: any, limit = 20, max = 500): string[] {
411
+ if (!Array.isArray(values)) {
412
+ return [];
413
+ }
414
+ const result: string[] = [];
415
+ for (const value of values) {
416
+ const normalized = cleanText(value, max);
417
+ if (normalized && !result.includes(normalized)) {
418
+ result.push(normalized);
419
+ }
420
+ if (result.length >= limit) {
421
+ break;
422
+ }
423
+ }
424
+ return result;
425
+ }
426
+
427
+ function normalizeCheckStatus(value: any): AIQaCheckStatus {
428
+ const normalized = cleanText(value, 40).toLowerCase().replace(/[_\s-]+/g, '_');
429
+ if (normalized === 'passed' || normalized === 'ok' || normalized === 'ready') {
430
+ return 'pass';
431
+ }
432
+ if (normalized === 'failed' || normalized === 'error' || normalized === 'fail') {
433
+ return 'fail';
434
+ }
435
+ if (normalized === 'blocked' || normalized === 'dependency_blocked') {
436
+ return 'blocked';
437
+ }
438
+ if (normalized === 'warning') {
439
+ return 'warn';
440
+ }
441
+ if (normalized === 'skipped' || normalized === 'not_applicable') {
442
+ return 'skipped';
443
+ }
444
+ return normalized === 'pass' || normalized === 'warn' ? normalized : 'unknown';
445
+ }
446
+
447
+ function normalizeCompileStatus(value: any): AIQaCompileStatus {
448
+ const normalized = cleanText(value, 40).toLowerCase().replace(/[_\s-]+/g, '_');
449
+ if (normalized === 'passed' || normalized === 'ok') {
450
+ return 'pass';
451
+ }
452
+ if (normalized === 'failed' || normalized === 'error') {
453
+ return 'fail';
454
+ }
455
+ if (normalized === 'blocked') {
456
+ return 'blocked';
457
+ }
458
+ if (normalized === 'stale' || normalized === 'stale_evidence') {
459
+ return 'stale';
460
+ }
461
+ if (normalized === 'skipped' || normalized === 'not_applicable') {
462
+ return 'skipped';
463
+ }
464
+ return normalized === 'pass' || normalized === 'fail' ? normalized : 'unknown';
465
+ }
466
+
467
+ function makeGate(
468
+ key: string,
469
+ label: string,
470
+ status: AIRunGateStatus,
471
+ reason: string,
472
+ evidenceRefs: string[] = [],
473
+ now?: Date | string,
474
+ metadata?: Record<string, any>
475
+ ): AIRunGateResult {
476
+ return {
477
+ key,
478
+ label,
479
+ status,
480
+ reason: cleanText(reason, 1400),
481
+ evidenceRefs: cleanList(evidenceRefs, 20, 500),
482
+ recordedAt: isoNow(now),
483
+ ...(metadata ? { metadata } : {})
484
+ };
485
+ }
486
+
487
+ function failedOrBlocked(status: AIQaCheckStatus | AIQaCompileStatus): boolean {
488
+ return status === 'fail' || status === 'blocked';
489
+ }
490
+
491
+ function passed(status: AIQaCheckStatus | AIQaCompileStatus): boolean {
492
+ return status === 'pass';
493
+ }
494
+
495
+ function normalizeInfraChecks(values: AIQaInfraCheck[] | undefined): AIQaInfraCheck[] {
496
+ return (Array.isArray(values) ? values : []).map((entry) => ({
497
+ ...entry,
498
+ name: cleanText(entry?.name, 120) || 'infra_check',
499
+ status: normalizeCheckStatus(entry?.status),
500
+ message: cleanText(entry?.message, 1000),
501
+ path: cleanText(entry?.path, 500)
502
+ }));
503
+ }
504
+
505
+ function normalizeRouteProbes(values: AIQaRouteProbe[] | undefined): AIQaRouteProbe[] {
506
+ return (Array.isArray(values) ? values : []).map((entry) => ({
507
+ ...entry,
508
+ route: cleanText(entry?.route, 500) || '/',
509
+ status: normalizeCheckStatus(entry?.status),
510
+ screenshot: cleanText(entry?.screenshot, 500),
511
+ caption: cleanText(entry?.caption, 1000),
512
+ message: cleanText(entry?.message, 1000),
513
+ consoleErrors: cleanList(entry?.consoleErrors, 30, 500),
514
+ networkErrors: cleanList(entry?.networkErrors, 30, 500)
515
+ }));
516
+ }
517
+
518
+ function normalizeBusinessAssertions(values: AIQaBusinessAssertion[] | undefined): AIQaBusinessAssertion[] {
519
+ return (Array.isArray(values) ? values : []).map((entry) => ({
520
+ ...entry,
521
+ assertion: cleanText(entry?.assertion, 1000) || 'business assertion',
522
+ status: normalizeCheckStatus(entry?.status),
523
+ workflow: cleanText(entry?.workflow, 400),
524
+ route: cleanText(entry?.route, 500),
525
+ action: cleanText(entry?.action, 500),
526
+ expected: cleanText(entry?.expected, 1000),
527
+ observed: cleanText(entry?.observed, 1000),
528
+ dataProof: cleanText(entry?.dataProof, 1400),
529
+ artifactPaths: cleanList(entry?.artifactPaths, 30, 500),
530
+ message: cleanText(entry?.message, 1000)
531
+ }));
532
+ }
533
+
534
+ function collectBusinessAssertionArtifactPaths(assertions: AIQaBusinessAssertion[]): string[] {
535
+ const paths: string[] = [];
536
+ for (const assertion of assertions) {
537
+ for (const artifactPath of assertion.artifactPaths || []) {
538
+ if (artifactPath && !paths.includes(artifactPath)) {
539
+ paths.push(artifactPath);
540
+ }
541
+ }
542
+ }
543
+ return paths;
544
+ }
545
+
546
+ export function buildAIQaRun(input: AIQaEvaluationInput = {}): AIQaRun {
547
+ const now = isoNow(input.now);
548
+ const infraChecks = normalizeInfraChecks(input.infraChecks);
549
+ const compile = input.compile
550
+ ? {
551
+ ...input.compile,
552
+ status: normalizeCompileStatus(input.compile.status),
553
+ command: cleanText(input.compile.command, 500),
554
+ artifactPath: cleanText(input.compile.artifactPath, 500),
555
+ message: cleanText(input.compile.message, 1000)
556
+ }
557
+ : undefined;
558
+ const routeProbes = normalizeRouteProbes(input.routeProbes);
559
+ const businessAssertions = normalizeBusinessAssertions(input.businessAssertions);
560
+ const artifacts = Array.isArray(input.artifacts) ? input.artifacts : [];
561
+ const gateResults: AIRunGateResult[] = [];
562
+
563
+ const failedInfra = infraChecks.filter((check) => failedOrBlocked(check.status));
564
+ if (failedInfra.length) {
565
+ gateResults.push(makeGate(
566
+ 'qa_infra',
567
+ 'QA infrastructure',
568
+ 'blocked',
569
+ `QA infrastructure failed before model/business validation: ${failedInfra.map((check) => `${check.name}: ${check.message || check.status}`).join('; ')}`,
570
+ failedInfra.map((check) => check.path || '').filter(Boolean),
571
+ now,
572
+ { failed_checks: failedInfra.map((check) => check.name) }
573
+ ));
574
+ return { outcome: 'infra_failed', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
575
+ }
576
+ if (infraChecks.length) {
577
+ gateResults.push(makeGate('qa_infra', 'QA infrastructure', 'pass', 'QA infrastructure preflight checks passed.', [], now));
578
+ }
579
+
580
+ if (compile && (failedOrBlocked(compile.status) || compile.status === 'stale' || compile.staleEvidence === true)) {
581
+ gateResults.push(makeGate(
582
+ 'qa_compile',
583
+ 'Compile/build',
584
+ 'fail',
585
+ compile.status === 'stale' || compile.staleEvidence === true
586
+ ? 'Compile/build evidence is stale and cannot be used for acceptance.'
587
+ : (compile.message || 'Compile/build failed before browser QA.'),
588
+ compile.artifactPath ? [compile.artifactPath] : [],
589
+ now,
590
+ { command: compile.command || '' }
591
+ ));
592
+ return { outcome: 'compile_failed', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
593
+ }
594
+ if (compile && passed(compile.status)) {
595
+ gateResults.push(makeGate('qa_compile', 'Compile/build', 'pass', 'Compile/build evidence passed.', compile.artifactPath ? [compile.artifactPath] : [], now));
596
+ }
597
+
598
+ const failedRouteProbes = routeProbes.filter((probe) => failedOrBlocked(probe.status) || probe.shellOnly === true);
599
+ if (failedRouteProbes.length) {
600
+ gateResults.push(makeGate(
601
+ 'qa_route_probe',
602
+ 'Browser route probe',
603
+ 'fail',
604
+ `Browser route probe failed or showed shell-only UI: ${failedRouteProbes.map((probe) => `${probe.route}: ${probe.message || probe.caption || probe.status}`).join('; ')}`,
605
+ failedRouteProbes.map((probe) => probe.screenshot || '').filter(Boolean),
606
+ now
607
+ ));
608
+ return { outcome: 'route_failed', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
609
+ }
610
+ if (routeProbes.some((probe) => passed(probe.status))) {
611
+ gateResults.push(makeGate(
612
+ 'qa_route_probe',
613
+ 'Browser route probe',
614
+ 'pass',
615
+ 'Browser route reached authenticated application content. This is not business acceptance by itself.',
616
+ routeProbes.map((probe) => probe.screenshot || '').filter(Boolean),
617
+ now
618
+ ));
619
+ }
620
+
621
+ const failedBusinessAssertions = businessAssertions.filter((assertion) => failedOrBlocked(assertion.status));
622
+ if (failedBusinessAssertions.length) {
623
+ gateResults.push(makeGate(
624
+ 'qa_business_assertion',
625
+ 'Business assertion',
626
+ 'fail',
627
+ `Issue-specific workflow assertion failed: ${failedBusinessAssertions.map((assertion) => assertion.message || assertion.observed || assertion.assertion).join('; ')}`,
628
+ collectBusinessAssertionArtifactPaths(failedBusinessAssertions),
629
+ now
630
+ ));
631
+ return { outcome: 'business_assertion_failed', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
632
+ }
633
+
634
+ const passedBusinessAssertions = businessAssertions.filter((assertion) => passed(assertion.status));
635
+ if (passedBusinessAssertions.length) {
636
+ gateResults.push(makeGate(
637
+ 'qa_business_assertion',
638
+ 'Business assertion',
639
+ 'pass',
640
+ 'At least one issue-specific workflow/data assertion passed.',
641
+ collectBusinessAssertionArtifactPaths(passedBusinessAssertions),
642
+ now,
643
+ { passed_assertions: passedBusinessAssertions.map((assertion) => assertion.assertion) }
644
+ ));
645
+ return { outcome: 'business_assertion_passed', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
646
+ }
647
+
648
+ if (routeProbes.some((probe) => passed(probe.status))) {
649
+ gateResults.push(makeGate(
650
+ 'qa_business_assertion',
651
+ 'Business assertion',
652
+ 'blocked',
653
+ 'Browser route loaded, but no issue-specific business assertion passed. Route-only proof cannot accept the run.',
654
+ [],
655
+ now
656
+ ));
657
+ return { outcome: 'route_only_pass', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
658
+ }
659
+
660
+ gateResults.push(makeGate(
661
+ 'qa_business_assertion',
662
+ 'Business assertion',
663
+ 'blocked',
664
+ 'No issue-specific QA assertion was recorded.',
665
+ [],
666
+ now
667
+ ));
668
+ return { outcome: 'incomplete', infraChecks, compile, routeProbes, businessAssertions, artifacts, gateResults, updatedAt: now };
669
+ }
670
+
671
+ function normalizeQaRun(input?: AIQaRun | AIQaEvaluationInput): AIQaRun | undefined {
672
+ if (!input) {
673
+ return undefined;
674
+ }
675
+ if ((input as AIQaRun).outcome && Array.isArray((input as AIQaRun).gateResults)) {
676
+ return input as AIQaRun;
677
+ }
678
+ return buildAIQaRun(input as AIQaEvaluationInput);
679
+ }
680
+
681
+ function statusLooksFailed(value: any): boolean {
682
+ const normalized = cleanText(value, 120).toLowerCase();
683
+ return !!normalized && /(fail|failed|error|blocked|missing|empty|stale|skipped|not ready|not_ready|could not|cannot)/i.test(normalized);
684
+ }
685
+
686
+ function statusLooksPassed(value: any): boolean {
687
+ const normalized = cleanText(value, 120).toLowerCase();
688
+ return !!normalized && /(pass|passed|success|complete|completed|ready|published|deployed|live|merged)/i.test(normalized);
689
+ }
690
+
691
+ function addGateOnce(gates: AIRunGateResult[], gate: AIRunGateResult): void {
692
+ if (gates.some((entry) => entry.key === gate.key && entry.status === gate.status && entry.reason === gate.reason)) {
693
+ return;
694
+ }
695
+ gates.push(gate);
696
+ }
697
+
698
+ export function classifyAIRunOutcome(input: AIRunOutcomeInput = {}): AIRunOutcomeDecision {
699
+ const now = isoNow(input.now);
700
+ const gates = Array.isArray(input.gates) ? [...input.gates] : [];
701
+ const warnings: string[] = [];
702
+ const qa = normalizeQaRun(input.qa);
703
+ if (qa) {
704
+ for (const gate of qa.gateResults) {
705
+ addGateOnce(gates, gate);
706
+ }
707
+ }
708
+
709
+ if (input.manualHandoff === true) {
710
+ return {
711
+ outcome: 'manual_handoff',
712
+ reason: 'Run requires manual handoff.',
713
+ nextAction: 'Ask a human operator to resolve the blocked run.',
714
+ gates,
715
+ warnings,
716
+ recordedAt: now
717
+ };
718
+ }
719
+ if (input.stopped === true || /stop|stopped|cancel|cancelled|paused/i.test(`${input.status || ''} ${input.phase || ''}`)) {
720
+ return {
721
+ outcome: 'stopped',
722
+ reason: 'Run was stopped before accepted evidence was recorded.',
723
+ nextAction: 'Resume or restart only if the request is still active.',
724
+ gates,
725
+ warnings,
726
+ recordedAt: now
727
+ };
728
+ }
729
+ if (input.rejected === true) {
730
+ return {
731
+ outcome: 'rejected',
732
+ reason: 'Run was explicitly rejected.',
733
+ nextAction: 'Start a repair run from the failing evidence.',
734
+ gates,
735
+ warnings,
736
+ recordedAt: now
737
+ };
738
+ }
739
+
740
+ const blockedHotfixCommitGate = gates.find((gate) => gate.key === 'hotfix_commit_proof' && (gate.status === 'blocked' || gate.status === 'fail'));
741
+ if (blockedHotfixCommitGate) {
742
+ return {
743
+ outcome: 'release_blocked',
744
+ reason: `Hotfix cannot be treated as durable until GitHub commit proof passes: ${blockedHotfixCommitGate.reason}`,
745
+ nextAction: 'Commit and push the hotfix to GitHub, record sourceCommitSha/githubCommitUrl/gitCommitStatus/gitPushStatus, then rerun the smallest release gate.',
746
+ gates,
747
+ warnings,
748
+ recordedAt: now
749
+ };
750
+ }
751
+ const blockedNoBlindLoopGate = gates.find((gate) => gate.key === 'manager_no_blind_loop_policy' && gate.status === 'blocked');
752
+ if (blockedNoBlindLoopGate) {
753
+ return {
754
+ outcome: 'manual_handoff',
755
+ reason: `Manager parked the run to avoid a blind loop: ${blockedNoBlindLoopGate.reason}`,
756
+ nextAction: 'Collect new material evidence or approve the specific recovery decision before any more model/code repair.',
757
+ gates,
758
+ warnings,
759
+ recordedAt: now
760
+ };
761
+ }
762
+ const blockedSupportDiagnosisBeforeRepairGate = gates.find((gate) => gate.key === 'support_diagnosis_before_repair' && gate.status === 'blocked');
763
+ if (blockedSupportDiagnosisBeforeRepairGate) {
764
+ return {
765
+ outcome: 'manual_handoff',
766
+ reason: `Support repair is parked until root-cause diagnosis validates: ${blockedSupportDiagnosisBeforeRepairGate.reason}`,
767
+ nextAction: 'Run read-only support diagnosis, record support_diagnosis_gate with owner_files and before/action/after proof, then retry only the owner-scoped repair.',
768
+ gates,
769
+ warnings,
770
+ recordedAt: now
771
+ };
772
+ }
773
+ const blockedSupportOwnerFileScopeGate = gates.find((gate) => gate.key === 'support_owner_file_scope' && gate.status === 'blocked');
774
+ if (blockedSupportOwnerFileScopeGate) {
775
+ return {
776
+ outcome: 'manual_handoff',
777
+ reason: `Support repair exceeded the diagnosed owner-file scope: ${blockedSupportOwnerFileScopeGate.reason}`,
778
+ nextAction: 'Revise the SupportDiagnosisGate with evidence for each new owner file, update failing_path/proof_plan, then run only the bounded owner-scoped repair.',
779
+ gates,
780
+ warnings,
781
+ recordedAt: now
782
+ };
783
+ }
784
+
785
+ if (qa?.outcome === 'infra_failed') {
786
+ return {
787
+ outcome: 'qa_infra_failed',
788
+ reason: 'QA infrastructure failed before product validation.',
789
+ nextAction: 'Repair QA harness dependencies, ports, browser, Mongo, or startup before another model repair loop.',
790
+ gates,
791
+ warnings,
792
+ recordedAt: now
793
+ };
794
+ }
795
+ if (qa?.outcome === 'compile_failed') {
796
+ return {
797
+ outcome: 'build_failed',
798
+ reason: 'Compile/build evidence failed or was stale.',
799
+ nextAction: 'Repair compile/build first, then rerun QA from the same failed step.',
800
+ gates,
801
+ warnings,
802
+ recordedAt: now
803
+ };
804
+ }
805
+ if (qa?.outcome === 'route_failed') {
806
+ return {
807
+ outcome: 'qa_incomplete',
808
+ reason: 'Browser route probe failed before business proof.',
809
+ nextAction: 'Repair route/auth/startup issue and rerun the same browser route probe.',
810
+ gates,
811
+ warnings,
812
+ recordedAt: now
813
+ };
814
+ }
815
+ const blockedAICoderJourneyContractGate = gates.find((gate) => gate.key === 'aicoder_journey_contract' && (gate.status === 'blocked' || gate.status === 'fail'));
816
+ if (blockedAICoderJourneyContractGate) {
817
+ const claimedSuccess = input.explicitAccepted === true || input.scorecardPassed === true || statusLooksPassed(input.scorecardStatus) || statusLooksPassed(`${input.status || ''} ${input.phase || ''}`);
818
+ return {
819
+ outcome: claimedSuccess ? 'false_pass' : 'qa_incomplete',
820
+ reason: claimedSuccess
821
+ ? `AICoder run claimed success without a valid Journey Contract: ${blockedAICoderJourneyContractGate.reason}`
822
+ : `AICoder workflow is blocked until the Journey Contract validates: ${blockedAICoderJourneyContractGate.reason}`,
823
+ nextAction: 'Generate or repair docs/APP_JOURNEY_CONTRACT.md, validate first/next/last workflow/data story/QA assertions, then rerun workflow build and workflow QA.',
824
+ gates,
825
+ warnings,
826
+ recordedAt: now
827
+ };
828
+ }
829
+ const blockedSupportNextActionContractGate = gates.find((gate) => gate.key === 'support_next_action_contract' && gate.status === 'blocked');
830
+ if (
831
+ blockedSupportNextActionContractGate
832
+ && qa?.outcome !== 'business_assertion_passed'
833
+ && input.scorecardPassed !== true
834
+ && !statusLooksPassed(input.scorecardStatus)
835
+ ) {
836
+ return {
837
+ outcome: 'manual_handoff',
838
+ reason: `Support manager cannot safely continue without a valid next-action contract: ${blockedSupportNextActionContractGate.reason}`,
839
+ nextAction: 'Record one validated next-action contract with safeToAutoRun, canRunWithoutCodexMonitor, codexFallbackRequired, preconditions, stop conditions, and success evidence before another autonomous recovery.',
840
+ gates,
841
+ warnings,
842
+ recordedAt: now
843
+ };
844
+ }
845
+ const blockedSupportIssueClassProbePlanGate = gates.find((gate) => gate.key === 'support_issue_class_probe_plan' && (gate.status === 'blocked' || gate.status === 'fail'));
846
+ if (input.source === 'support_ticket' && blockedSupportIssueClassProbePlanGate) {
847
+ const claimedSuccess = input.explicitAccepted === true
848
+ || input.scorecardPassed === true
849
+ || statusLooksPassed(input.scorecardStatus)
850
+ || statusLooksPassed(`${input.status || ''} ${input.phase || ''}`);
851
+ return {
852
+ outcome: claimedSuccess ? 'false_pass' : 'qa_incomplete',
853
+ reason: claimedSuccess
854
+ ? `Support run claimed success without a valid issue-class probe plan: ${blockedSupportIssueClassProbePlanGate.reason}`
855
+ : `Support business proof is blocked until the issue-class probe plan validates: ${blockedSupportIssueClassProbePlanGate.reason}`,
856
+ nextAction: 'Generate or repair the Support IssueClassProbePlan from the diagnosis proof_plan, then rerun issue-specific business proof QA.',
857
+ gates,
858
+ warnings,
859
+ recordedAt: now
860
+ };
861
+ }
862
+ const blockedAssistantAnswerActionabilityGate = gates.find((gate) => gate.key === 'assistant_answer_actionability' && (gate.status === 'blocked' || gate.status === 'fail'));
863
+ if (input.source === 'ai_assistant' && blockedAssistantAnswerActionabilityGate) {
864
+ const claimedSuccess = input.explicitAccepted === true
865
+ || statusLooksPassed(`${input.status || ''} ${input.phase || ''}`);
866
+ return {
867
+ outcome: claimedSuccess ? 'false_pass' : 'qa_incomplete',
868
+ reason: claimedSuccess
869
+ ? `Assistant answer was marked accepted without a valid actionability contract: ${blockedAssistantAnswerActionabilityGate.reason}`
870
+ : `Assistant answer is blocked until actionability evidence validates: ${blockedAssistantAnswerActionabilityGate.reason}`,
871
+ nextAction: 'Record verified query/date/permission/citation/confidence evidence and one assistant actionability contract before answering or drafting customer-facing text.',
872
+ gates,
873
+ warnings,
874
+ recordedAt: now
875
+ };
876
+ }
877
+ if (qa?.outcome === 'route_only_pass' || qa?.outcome === 'incomplete') {
878
+ return {
879
+ outcome: input.scorecardPassed === true ? 'false_pass' : 'qa_incomplete',
880
+ reason: input.scorecardPassed === true
881
+ ? 'Scorecard or workflow status passed without issue-specific business assertion proof.'
882
+ : 'QA has not recorded issue-specific business assertion proof.',
883
+ nextAction: 'Add before/action/after workflow proof with screenshot/data assertions before acceptance.',
884
+ gates,
885
+ warnings,
886
+ recordedAt: now
887
+ };
888
+ }
889
+ if (qa?.outcome === 'business_assertion_failed') {
890
+ return {
891
+ outcome: input.terminal === true ? 'rejected' : 'qa_incomplete',
892
+ reason: 'Issue-specific business assertion failed.',
893
+ nextAction: 'Repair the product/data defect and rerun the failing assertion.',
894
+ gates,
895
+ warnings,
896
+ recordedAt: now
897
+ };
898
+ }
899
+
900
+ const hasBusinessPass = qa?.outcome === 'business_assertion_passed';
901
+ const scorecardPassed = input.scorecardPassed === true || statusLooksPassed(input.scorecardStatus);
902
+ const releaseBlockers: string[] = [];
903
+ if (statusLooksFailed(input.deployStatus)) {
904
+ releaseBlockers.push(`deploy=${cleanText(input.deployStatus, 120)}`);
905
+ }
906
+ if (statusLooksFailed(input.publishStatus)) {
907
+ releaseBlockers.push(`publish=${cleanText(input.publishStatus, 120)}`);
908
+ }
909
+ if (statusLooksFailed(input.sampleDataStatus)) {
910
+ releaseBlockers.push(`sample_data=${cleanText(input.sampleDataStatus, 120)}`);
911
+ }
912
+ if (releaseBlockers.length && (scorecardPassed || hasBusinessPass)) {
913
+ addGateOnce(gates, makeGate(
914
+ 'release',
915
+ 'Release/deploy',
916
+ 'fail',
917
+ `Final acceptance is blocked after QA/scorecard because release gates failed: ${releaseBlockers.join(', ')}.`,
918
+ [],
919
+ now
920
+ ));
921
+ return {
922
+ outcome: 'release_blocked',
923
+ reason: `Release gates failed after QA/scorecard: ${releaseBlockers.join(', ')}.`,
924
+ nextAction: 'Repair deploy/publish/sample-data coverage before marking the run accepted.',
925
+ gates,
926
+ warnings,
927
+ recordedAt: now
928
+ };
929
+ }
930
+
931
+ const blockedAICoderNextActionContractGate = gates.find((gate) => gate.key === 'aicoder_next_action_contract' && (gate.status === 'blocked' || gate.status === 'fail'));
932
+ if (input.source === 'aicoder_app' && blockedAICoderNextActionContractGate) {
933
+ const claimedSuccess = input.explicitAccepted === true
934
+ || input.scorecardPassed === true
935
+ || statusLooksPassed(input.scorecardStatus)
936
+ || statusLooksPassed(`${input.status || ''} ${input.phase || ''}`);
937
+ return {
938
+ outcome: claimedSuccess ? 'false_pass' : 'manual_handoff',
939
+ reason: claimedSuccess
940
+ ? `AICoder run claimed success without a manager-safe next-action contract: ${blockedAICoderNextActionContractGate.reason}`
941
+ : `AICoder manager cannot safely continue without a manager-safe next-action contract: ${blockedAICoderNextActionContractGate.reason}`,
942
+ nextAction: 'Record one validated AICoder next-action contract with safeToAutoRun, canRunWithoutCodexMonitor, codexFallbackRequired, stop conditions, and success evidence before another autonomous loop.',
943
+ gates,
944
+ warnings,
945
+ recordedAt: now
946
+ };
947
+ }
948
+
949
+ if (scorecardPassed && !hasBusinessPass) {
950
+ warnings.push('scorecard_pass_without_business_assertion');
951
+ addGateOnce(gates, makeGate(
952
+ 'business_assertion_required',
953
+ 'Business assertion',
954
+ 'blocked',
955
+ 'Scorecard passed, but no issue-specific business assertion proof was recorded.',
956
+ [],
957
+ now
958
+ ));
959
+ return {
960
+ outcome: 'false_pass',
961
+ reason: 'Scorecard-only proof is not acceptance.',
962
+ nextAction: 'Record issue-specific workflow/data proof, then reclassify the run.',
963
+ gates,
964
+ warnings,
965
+ recordedAt: now
966
+ };
967
+ }
968
+
969
+ const statusPhase = `${input.status || ''} ${input.phase || ''}`;
970
+ if ((input.explicitAccepted === true || statusLooksPassed(statusPhase) || scorecardPassed) && hasBusinessPass) {
971
+ return {
972
+ outcome: 'accepted',
973
+ reason: 'Run has terminal success signal and issue-specific business assertion proof.',
974
+ nextAction: 'No repair action required.',
975
+ gates,
976
+ warnings,
977
+ recordedAt: now
978
+ };
979
+ }
980
+
981
+ if (statusLooksFailed(statusPhase)) {
982
+ return {
983
+ outcome: 'rejected',
984
+ reason: 'Run ended with a failure status and no accepted proof.',
985
+ nextAction: 'Classify the failing gate and rerun the smallest repair step.',
986
+ gates,
987
+ warnings,
988
+ recordedAt: now
989
+ };
990
+ }
991
+
992
+ return {
993
+ outcome: 'unknown',
994
+ reason: 'Run does not have enough normalized evidence for a terminal label.',
995
+ nextAction: 'Ingest QA, deploy, assistant, usage, and commit evidence before using this run for training.',
996
+ gates,
997
+ warnings,
998
+ recordedAt: now
999
+ };
1000
+ }
1001
+
1002
+ export function buildAIRun(input: Omit<AIRun, 'outcome' | 'gates'> & {
1003
+ outcome?: AIRunOutcomeLabel;
1004
+ gates?: AIRunGateResult[];
1005
+ scorecardPassed?: boolean;
1006
+ deployStatus?: string;
1007
+ publishStatus?: string;
1008
+ sampleDataStatus?: string;
1009
+ manualHandoff?: boolean;
1010
+ stopped?: boolean;
1011
+ rejected?: boolean;
1012
+ explicitAccepted?: boolean;
1013
+ terminal?: boolean;
1014
+ now?: Date | string;
1015
+ }): AIRun {
1016
+ const decision = input.outcome
1017
+ ? {
1018
+ outcome: input.outcome,
1019
+ gates: input.gates || [],
1020
+ warnings: input.warnings || [],
1021
+ nextAction: input.nextAction || '',
1022
+ reason: '',
1023
+ recordedAt: isoNow(input.now)
1024
+ }
1025
+ : classifyAIRunOutcome({
1026
+ source: input.source,
1027
+ status: input.status,
1028
+ phase: input.phase,
1029
+ qa: input.qa,
1030
+ gates: input.gates,
1031
+ scorecardPassed: input.scorecardPassed,
1032
+ deployStatus: input.deployStatus,
1033
+ publishStatus: input.publishStatus,
1034
+ sampleDataStatus: input.sampleDataStatus,
1035
+ manualHandoff: input.manualHandoff,
1036
+ stopped: input.stopped,
1037
+ rejected: input.rejected,
1038
+ explicitAccepted: input.explicitAccepted,
1039
+ terminal: input.terminal,
1040
+ now: input.now
1041
+ });
1042
+ return {
1043
+ id: input.id,
1044
+ source: input.source || 'unknown',
1045
+ sourceIds: input.sourceIds || {},
1046
+ title: input.title,
1047
+ status: input.status,
1048
+ phase: input.phase,
1049
+ startedAt: input.startedAt,
1050
+ completedAt: input.completedAt,
1051
+ outcome: decision.outcome,
1052
+ events: Array.isArray(input.events) ? input.events : [],
1053
+ gates: decision.gates,
1054
+ qa: normalizeQaRun(input.qa),
1055
+ cost: input.cost,
1056
+ nextAction: decision.nextAction,
1057
+ warnings: decision.warnings,
1058
+ metadata: input.metadata
1059
+ };
1060
+ }
1061
+
1062
+ export function buildAIRunCost(entries: OpenAIUsageCostEntry[] = []): AIRunCost {
1063
+ const cost: AIRunCost = {
1064
+ inputTokens: 0,
1065
+ cachedInputTokens: 0,
1066
+ outputTokens: 0,
1067
+ totalTokens: 0,
1068
+ estimatedUsd: 0,
1069
+ models: [],
1070
+ categories: {},
1071
+ sources: {},
1072
+ surfaces: {},
1073
+ manualEstimatedUsd: 0,
1074
+ untrackedEstimatedUsd: 0,
1075
+ untrackedWarnings: []
1076
+ };
1077
+ for (const entry of normalizeOpenAIUsageRowsForCosting(entries)) {
1078
+ const category = cleanText(entry.category, 120) || 'unknown';
1079
+ const source = cleanText(entry.usage_source ?? entry.usageSource, 80) || 'unknown';
1080
+ const surface = cleanText(entry.usage_surface ?? entry.usageSurface, 80) || 'unknown';
1081
+ const isManual = entry.is_manual === true || entry.isManual === true || source === 'manual_codex';
1082
+ const isUntracked = entry.is_untracked === true || entry.isUntracked === true;
1083
+ const untrackedReason = cleanText(entry.untracked_reason ?? entry.untrackedReason, 500);
1084
+ const model = cleanText(entry.model, 120);
1085
+ const inputTokens = Number(entry.input_tokens ?? entry.inputTokens ?? 0) || 0;
1086
+ const cachedInputTokens = Number(entry.cached_input_tokens ?? entry.cachedInputTokens ?? 0) || 0;
1087
+ const outputTokens = Number(entry.output_tokens ?? entry.outputTokens ?? 0) || 0;
1088
+ const totalTokens = Number(entry.total_tokens ?? entry.totalTokens ?? (inputTokens + outputTokens)) || 0;
1089
+ const estimatedUsd = Number(entry.cost_estimate ?? entry.estimatedUsd ?? 0) || 0;
1090
+ cost.inputTokens += inputTokens;
1091
+ cost.cachedInputTokens += cachedInputTokens;
1092
+ cost.outputTokens += outputTokens;
1093
+ cost.totalTokens += totalTokens;
1094
+ cost.estimatedUsd += estimatedUsd;
1095
+ if (isManual) {
1096
+ cost.manualEstimatedUsd = Number(cost.manualEstimatedUsd || 0) + estimatedUsd;
1097
+ }
1098
+ if (isUntracked) {
1099
+ cost.untrackedEstimatedUsd = Number(cost.untrackedEstimatedUsd || 0) + estimatedUsd;
1100
+ const warning = untrackedReason || `${source} usage is an estimate outside managed runner telemetry.`;
1101
+ if (warning && !cost.untrackedWarnings?.includes(warning)) {
1102
+ cost.untrackedWarnings?.push(warning);
1103
+ }
1104
+ }
1105
+ if (model && !cost.models.includes(model)) {
1106
+ cost.models.push(model);
1107
+ }
1108
+ if (!cost.categories[category]) {
1109
+ cost.categories[category] = {
1110
+ inputTokens: 0,
1111
+ cachedInputTokens: 0,
1112
+ outputTokens: 0,
1113
+ totalTokens: 0,
1114
+ estimatedUsd: 0,
1115
+ count: 0
1116
+ };
1117
+ }
1118
+ cost.categories[category].inputTokens += inputTokens;
1119
+ cost.categories[category].cachedInputTokens += cachedInputTokens;
1120
+ cost.categories[category].outputTokens += outputTokens;
1121
+ cost.categories[category].totalTokens += totalTokens;
1122
+ cost.categories[category].estimatedUsd += estimatedUsd;
1123
+ cost.categories[category].count += 1;
1124
+ if (!cost.sources?.[source]) {
1125
+ cost.sources![source] = {
1126
+ inputTokens: 0,
1127
+ cachedInputTokens: 0,
1128
+ outputTokens: 0,
1129
+ totalTokens: 0,
1130
+ estimatedUsd: 0,
1131
+ count: 0,
1132
+ manualCount: 0,
1133
+ untrackedCount: 0
1134
+ };
1135
+ }
1136
+ cost.sources[source].inputTokens += inputTokens;
1137
+ cost.sources[source].cachedInputTokens += cachedInputTokens;
1138
+ cost.sources[source].outputTokens += outputTokens;
1139
+ cost.sources[source].totalTokens += totalTokens;
1140
+ cost.sources[source].estimatedUsd += estimatedUsd;
1141
+ cost.sources[source].count += 1;
1142
+ if (isManual) {
1143
+ cost.sources[source].manualCount += 1;
1144
+ }
1145
+ if (isUntracked) {
1146
+ cost.sources[source].untrackedCount += 1;
1147
+ }
1148
+ if (!cost.surfaces?.[surface]) {
1149
+ cost.surfaces![surface] = {
1150
+ totalTokens: 0,
1151
+ estimatedUsd: 0,
1152
+ count: 0
1153
+ };
1154
+ }
1155
+ cost.surfaces[surface].totalTokens += totalTokens;
1156
+ cost.surfaces[surface].estimatedUsd += estimatedUsd;
1157
+ cost.surfaces[surface].count += 1;
1158
+ }
1159
+ cost.estimatedUsd = Number(cost.estimatedUsd.toFixed(6));
1160
+ cost.manualEstimatedUsd = Number(Number(cost.manualEstimatedUsd || 0).toFixed(6));
1161
+ cost.untrackedEstimatedUsd = Number(Number(cost.untrackedEstimatedUsd || 0).toFixed(6));
1162
+ for (const category of Object.keys(cost.categories)) {
1163
+ cost.categories[category].estimatedUsd = Number(cost.categories[category].estimatedUsd.toFixed(6));
1164
+ }
1165
+ for (const source of Object.keys(cost.sources || {})) {
1166
+ cost.sources![source].estimatedUsd = Number(cost.sources![source].estimatedUsd.toFixed(6));
1167
+ }
1168
+ for (const surface of Object.keys(cost.surfaces || {})) {
1169
+ cost.surfaces![surface].estimatedUsd = Number(cost.surfaces![surface].estimatedUsd.toFixed(6));
1170
+ }
1171
+ return cost;
1172
+ }
1173
+
1174
+ export function redactAIRunTrainingExample(example: AIRunTrainingExample): AIRunTrainingExample {
1175
+ const redact = (value: string): string => cleanText(value, 5000)
1176
+ .replace(/mongodb(?:\+srv)?:\/\/[^\s"'<>]+/ig, '[redacted-mongo-url]')
1177
+ .replace(/\b(?:sk|ghp|xoxb|AKIA)[A-Za-z0-9_\-]{12,}\b/g, '[redacted-secret]')
1178
+ .replace(/\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Z]{2,}\b/ig, '[redacted-email]');
1179
+ return {
1180
+ ...example,
1181
+ inputSummary: redact(example.inputSummary),
1182
+ actionSummary: redact(example.actionSummary),
1183
+ evidence: cleanList(example.evidence, 80, 5000).map(redact)
1184
+ };
1185
+ }