@resolveio/server-lib 22.3.141 → 22.3.142

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 +77 -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 +57 -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 +23497 -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 +16 -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 +677 -0
  177. package/src/util/ai-run-evidence-dashboard.ts +271 -0
  178. package/src/util/ai-run-evidence-eval.ts +885 -0
  179. package/src/util/ai-run-evidence.ts +964 -0
  180. package/src/util/ai-runner-artifacts.ts +586 -0
  181. package/src/util/ai-runner-manager-autopilot.ts +380 -0
  182. package/src/util/ai-runner-manager-policy.ts +1740 -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 +875 -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 +2065 -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 +2968 -0
  210. package/tests/ai-manager-autopilot-snapshot.test.ts +172 -0
  211. package/tests/ai-manager-recovery-checkpoint.test.ts +323 -0
  212. package/tests/ai-run-eval.test.ts +88 -0
  213. package/tests/ai-run-evidence.test.ts +305 -0
  214. package/tests/ai-runner-contract.test.ts +488 -0
  215. package/tests/aicoder-runner-v6.test.ts +268 -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 +417 -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 -124
  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 -16
  401. package/managers/openai-usage-ledger.manager.js +0 -93
  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 -337
  425. package/methods/ai-terminal.js +0 -23166
  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 -15
  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 -33
  672. package/util/ai-run-evidence-adapters.js +0 -831
  673. package/util/ai-run-evidence-adapters.js.map +0 -1
  674. package/util/ai-run-evidence-dashboard.d.ts +0 -67
  675. package/util/ai-run-evidence-dashboard.js +0 -309
  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 -854
  679. package/util/ai-run-evidence-eval.js.map +0 -1
  680. package/util/ai-run-evidence.d.ts +0 -212
  681. package/util/ai-run-evidence.js +0 -649
  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 -92
  687. package/util/ai-runner-manager-autopilot.js +0 -281
  688. package/util/ai-runner-manager-autopilot.js.map +0 -1
  689. package/util/ai-runner-manager-policy.d.ts +0 -282
  690. package/util/ai-runner-manager-policy.js +0 -997
  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 -212
  699. package/util/aicoder-runner-v6.js +0 -502
  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 -413
  732. package/util/support-runner-v5.js +0 -1424
  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,1740 @@
1
+ export type ResolveIOAIManagerAction =
2
+ | 'continue'
3
+ | 'retry_infra'
4
+ | 'reset_loop_budget'
5
+ | 'park_repeated_failure'
6
+ | 'park_ping_pong'
7
+ | 'manual_handoff';
8
+
9
+ export interface ResolveIOAIManagerFailureRecord {
10
+ outcome?: string;
11
+ lane?: string;
12
+ stepType?: string;
13
+ failureClass?: string;
14
+ blocker?: string;
15
+ blockerFingerprint?: string;
16
+ evidenceHash?: string;
17
+ changedFiles?: string[];
18
+ artifactPaths?: string[];
19
+ summary?: string;
20
+ recordedAt?: Date | string;
21
+ }
22
+
23
+ export type ResolveIOAIManagerRecoveryClass =
24
+ | 'advance_after_proof'
25
+ | 'diagnosis_only'
26
+ | 'diagnosis_revision'
27
+ | 'infra_repair'
28
+ | 'compile_repair'
29
+ | 'journey_contract_repair'
30
+ | 'business_proof_repair'
31
+ | 'release_repair'
32
+ | 'product_code_repair'
33
+ | 'blocked_until_new_evidence'
34
+ | 'manual_handoff'
35
+ | 'continue';
36
+
37
+ export interface ResolveIOAIManagerRecoveryPlan {
38
+ recoveryClass: ResolveIOAIManagerRecoveryClass;
39
+ lane: string;
40
+ stepType: string;
41
+ nextActionLabel: string;
42
+ objective: string;
43
+ allowedAction: string;
44
+ productRepairAllowed: boolean;
45
+ expensiveModelAllowed: boolean;
46
+ maxAttemptsBeforePark: number;
47
+ finiteSteps: string[];
48
+ requiredEvidence: string[];
49
+ loopResetEvidence: string[];
50
+ forbiddenActions: string[];
51
+ notes: string[];
52
+ }
53
+
54
+ export type ResolveIOAIManagerRecoveryCheckpointStatus =
55
+ | 'active'
56
+ | 'parked'
57
+ | 'manual_handoff'
58
+ | 'complete';
59
+
60
+ export interface ResolveIOAIManagerRecoveryCheckpoint {
61
+ checkpointId: string;
62
+ recoveryClass: ResolveIOAIManagerRecoveryClass;
63
+ status: ResolveIOAIManagerRecoveryCheckpointStatus;
64
+ lane: string;
65
+ stepType: string;
66
+ allowedAction: string;
67
+ productRepairAllowed: boolean;
68
+ expensiveModelAllowed: boolean;
69
+ attempts: number;
70
+ maxAttemptsBeforePark: number;
71
+ blockerFingerprint: string;
72
+ evidenceHash: string;
73
+ changedFiles: string[];
74
+ artifactPaths: string[];
75
+ requiredEvidence: string[];
76
+ loopResetEvidence: string[];
77
+ forbiddenActions: string[];
78
+ objective: string;
79
+ nextActionLabel: string;
80
+ createdAt: string;
81
+ updatedAt: string;
82
+ }
83
+
84
+ export type ResolveIOAIManagerRecoveryEvidenceProbeStepKind =
85
+ | 'read_only_diagnosis'
86
+ | 'rerun_same_gate'
87
+ | 'infra_preflight'
88
+ | 'compile_check'
89
+ | 'route_probe'
90
+ | 'business_assertion'
91
+ | 'journey_validation'
92
+ | 'release_status'
93
+ | 'diff_scope_check'
94
+ | 'operator_review';
95
+
96
+ export interface ResolveIOAIManagerRecoveryEvidenceProbeStep {
97
+ id: string;
98
+ kind: ResolveIOAIManagerRecoveryEvidenceProbeStepKind;
99
+ label: string;
100
+ objective: string;
101
+ required: boolean;
102
+ commandHint?: string;
103
+ artifactExpectation: string;
104
+ successSignal: string;
105
+ }
106
+
107
+ export interface ResolveIOAIManagerRecoveryEvidenceProbe {
108
+ probeId: string;
109
+ checkpointId: string;
110
+ recoveryClass: ResolveIOAIManagerRecoveryClass;
111
+ lane: string;
112
+ stepType: string;
113
+ objective: string;
114
+ evidenceOnly: boolean;
115
+ productRepairAllowed: boolean;
116
+ expensiveModelAllowed: boolean;
117
+ evidenceHashBefore: string;
118
+ blockerFingerprint: string;
119
+ steps: ResolveIOAIManagerRecoveryEvidenceProbeStep[];
120
+ requiredArtifacts: string[];
121
+ acceptanceEvidence: string[];
122
+ stopConditions: string[];
123
+ loopResetEvidence: string[];
124
+ createdAt: string;
125
+ }
126
+
127
+ export type ResolveIOAIManagerRecoveryAutomationMode =
128
+ | 'advance'
129
+ | 'collect_evidence'
130
+ | 'read_only_diagnosis'
131
+ | 'repair_infra'
132
+ | 'repair_compile'
133
+ | 'repair_journey_contract'
134
+ | 'repair_business_assertion'
135
+ | 'repair_release'
136
+ | 'targeted_product_repair'
137
+ | 'manual_review'
138
+ | 'continue_gate';
139
+
140
+ export interface ResolveIOAIManagerRecoveryActionRetryPolicy {
141
+ allowImmediateRetry: boolean;
142
+ requireNewEvidence: boolean;
143
+ resetLoopWhen: string[];
144
+ stopWhen: string[];
145
+ }
146
+
147
+ export interface ResolveIOAIManagerRecoveryActionPacket {
148
+ actionId: string;
149
+ checkpointId: string;
150
+ probeId: string;
151
+ recoveryClass: ResolveIOAIManagerRecoveryClass;
152
+ mode: ResolveIOAIManagerRecoveryAutomationMode;
153
+ label: string;
154
+ lane: string;
155
+ stepType: string;
156
+ primaryStepKind: ResolveIOAIManagerRecoveryEvidenceProbeStepKind | 'none';
157
+ objective: string;
158
+ evidenceOnly: boolean;
159
+ autoRunnable: boolean;
160
+ productRepairAllowed: boolean;
161
+ expensiveModelAllowed: boolean;
162
+ canResetLoopAfterEvidence: boolean;
163
+ maxAttemptsBeforePark: number;
164
+ requiredArtifacts: string[];
165
+ nextCommands: string[];
166
+ successCriteria: string[];
167
+ retryPolicy: ResolveIOAIManagerRecoveryActionRetryPolicy;
168
+ blockedReason?: string;
169
+ createdAt: string;
170
+ }
171
+
172
+ export type ResolveIOAIManagerRecoveryActionDispatchAction =
173
+ | 'run_evidence_probe'
174
+ | 'run_read_only_diagnosis'
175
+ | 'run_infra_repair'
176
+ | 'run_compile_repair'
177
+ | 'run_journey_contract_repair'
178
+ | 'run_business_assertion_repair'
179
+ | 'run_release_repair'
180
+ | 'run_targeted_product_repair'
181
+ | 'advance'
182
+ | 'continue_gate'
183
+ | 'park_manual';
184
+
185
+ export type ResolveIOAIManagerRecoveryActionDispatchStatus =
186
+ | 'queued'
187
+ | 'started'
188
+ | 'completed'
189
+ | 'failed'
190
+ | 'parked';
191
+
192
+ export interface ResolveIOAIManagerRecoveryActionDispatchRecord {
193
+ dispatchId: string;
194
+ actionId: string;
195
+ checkpointId: string;
196
+ probeId: string;
197
+ mode: ResolveIOAIManagerRecoveryAutomationMode;
198
+ dispatchAction: ResolveIOAIManagerRecoveryActionDispatchAction;
199
+ status: ResolveIOAIManagerRecoveryActionDispatchStatus;
200
+ evidenceHash: string;
201
+ blockerFingerprint: string;
202
+ productRepairAllowed: boolean;
203
+ expensiveModelAllowed: boolean;
204
+ reason: string;
205
+ artifactPaths: string[];
206
+ startedAt?: string;
207
+ completedAt?: string;
208
+ createdAt: string;
209
+ }
210
+
211
+ export interface ResolveIOAIManagerRecoveryActionDispatchInput {
212
+ action?: ResolveIOAIManagerRecoveryActionPacket;
213
+ history?: ResolveIOAIManagerRecoveryActionDispatchRecord[];
214
+ current?: ResolveIOAIManagerFailureRecord;
215
+ operatorApproved?: boolean;
216
+ now?: Date | string;
217
+ }
218
+
219
+ export interface ResolveIOAIManagerRecoveryActionDispatchDecision {
220
+ dispatchAction: ResolveIOAIManagerRecoveryActionDispatchAction;
221
+ allowed: boolean;
222
+ reason: string;
223
+ status: ResolveIOAIManagerRecoveryActionDispatchStatus;
224
+ canRunProductRepair: boolean;
225
+ canRunExpensiveModel: boolean;
226
+ shouldRecordDispatch: boolean;
227
+ requiresNewEvidence: boolean;
228
+ newEvidence: boolean;
229
+ dispatchRecord?: ResolveIOAIManagerRecoveryActionDispatchRecord;
230
+ }
231
+
232
+ export type ResolveIOAIManagerRecoveryExecutionPhase =
233
+ | 'evidence'
234
+ | 'diagnosis'
235
+ | 'infra'
236
+ | 'compile'
237
+ | 'journey'
238
+ | 'business_proof'
239
+ | 'release'
240
+ | 'product_repair'
241
+ | 'advance'
242
+ | 'manual';
243
+
244
+ export interface ResolveIOAIManagerRecoveryExecutionDirectiveInput {
245
+ action?: ResolveIOAIManagerRecoveryActionPacket;
246
+ dispatchDecision?: ResolveIOAIManagerRecoveryActionDispatchDecision;
247
+ current?: ResolveIOAIManagerFailureRecord;
248
+ surface?: string;
249
+ now?: Date | string;
250
+ }
251
+
252
+ export interface ResolveIOAIManagerRecoveryExecutionDirective {
253
+ directiveId: string;
254
+ surface: string;
255
+ dispatchAction: ResolveIOAIManagerRecoveryActionDispatchAction;
256
+ phase: ResolveIOAIManagerRecoveryExecutionPhase;
257
+ allowed: boolean;
258
+ status: ResolveIOAIManagerRecoveryActionDispatchStatus;
259
+ reason: string;
260
+ lane: string;
261
+ stepType: string;
262
+ nextActionLabel: string;
263
+ rerunReason: string;
264
+ evidenceOnly: boolean;
265
+ autoRunnable: boolean;
266
+ productRepairAllowed: boolean;
267
+ expensiveModelAllowed: boolean;
268
+ canRunProductRepair: boolean;
269
+ canRunExpensiveModel: boolean;
270
+ canResetLoopAfterEvidence: boolean;
271
+ requiresNewEvidence: boolean;
272
+ newEvidence: boolean;
273
+ maxAttemptsBeforePark: number;
274
+ requiredArtifacts: string[];
275
+ nextCommands: string[];
276
+ successCriteria: string[];
277
+ forbiddenActions: string[];
278
+ dispatchRecord?: ResolveIOAIManagerRecoveryActionDispatchRecord;
279
+ createdAt: string;
280
+ }
281
+
282
+ export interface ResolveIOAIManagerRecoveryCheckpointInput {
283
+ plan: ResolveIOAIManagerRecoveryPlan;
284
+ current?: ResolveIOAIManagerFailureRecord;
285
+ previousCheckpoint?: ResolveIOAIManagerRecoveryCheckpoint;
286
+ now?: Date | string;
287
+ }
288
+
289
+ export type ResolveIOAIManagerRecoveryGateAction =
290
+ | 'allow'
291
+ | 'collect_new_evidence'
292
+ | 'reject_action'
293
+ | 'manual_handoff'
294
+ | 'complete';
295
+
296
+ export interface ResolveIOAIManagerRecoveryGateInput {
297
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint;
298
+ current?: ResolveIOAIManagerFailureRecord;
299
+ proposedAction?: string;
300
+ operatorApproved?: boolean;
301
+ now?: Date | string;
302
+ }
303
+
304
+ export interface ResolveIOAIManagerRecoveryGateDecision {
305
+ action: ResolveIOAIManagerRecoveryGateAction;
306
+ reason: string;
307
+ canRunProductRepair: boolean;
308
+ canRunExpensiveModel: boolean;
309
+ shouldResetLoopBudget: boolean;
310
+ shouldIncrementAttempt: boolean;
311
+ newEvidence: boolean;
312
+ blockerFingerprint: string;
313
+ evidenceHash: string;
314
+ missingEvidence: string[];
315
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint;
316
+ }
317
+
318
+ export interface ResolveIOAIManagerRecoveryEvidenceProbeInput {
319
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint;
320
+ current?: ResolveIOAIManagerFailureRecord;
321
+ now?: Date | string;
322
+ }
323
+
324
+ export interface ResolveIOAIManagerRecoveryActionPacketInput {
325
+ plan?: ResolveIOAIManagerRecoveryPlan;
326
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint;
327
+ probe?: ResolveIOAIManagerRecoveryEvidenceProbe;
328
+ current?: ResolveIOAIManagerFailureRecord;
329
+ now?: Date | string;
330
+ }
331
+
332
+ export interface ResolveIOAIManagerRecoveryPlanInput {
333
+ action?: ResolveIOAIManagerAction | string;
334
+ reason?: string;
335
+ failureClass?: string;
336
+ lane?: string;
337
+ stepType?: string;
338
+ blocker?: string;
339
+ sameFailureCount?: number;
340
+ pingPongCount?: number;
341
+ newEvidence?: boolean;
342
+ productRepairFailure?: boolean;
343
+ changedFiles?: string[];
344
+ artifactPaths?: string[];
345
+ maxSameFailureRepeats?: number;
346
+ }
347
+
348
+ export interface ResolveIOAIManagerPolicyInput {
349
+ history?: ResolveIOAIManagerFailureRecord[];
350
+ current?: ResolveIOAIManagerFailureRecord;
351
+ maxSameFailureRepeats?: number;
352
+ maxPingPongTransitions?: number;
353
+ infraFailureClasses?: string[];
354
+ ignoredFailureClasses?: string[];
355
+ }
356
+
357
+ export interface ResolveIOAIManagerPolicyDecision {
358
+ action: ResolveIOAIManagerAction;
359
+ reason: string;
360
+ failureClass: string;
361
+ blockerFingerprint: string;
362
+ evidenceHash: string;
363
+ sameFailureCount: number;
364
+ pingPongCount: number;
365
+ newEvidence: boolean;
366
+ loopBudgetShouldReset: boolean;
367
+ productRepairFailure: boolean;
368
+ recoveryPlan: ResolveIOAIManagerRecoveryPlan;
369
+ recoveryCheckpoint: ResolveIOAIManagerRecoveryCheckpoint;
370
+ recoveryEvidenceProbe: ResolveIOAIManagerRecoveryEvidenceProbe;
371
+ recoveryAction: ResolveIOAIManagerRecoveryActionPacket;
372
+ }
373
+
374
+ function cleanText(value: any, max = 2000): string {
375
+ return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max);
376
+ }
377
+
378
+ function cleanList(values: any, limit = 40, max = 500): string[] {
379
+ if (!Array.isArray(values)) {
380
+ return [];
381
+ }
382
+ const result: string[] = [];
383
+ for (const value of values) {
384
+ const normalized = cleanText(value, max);
385
+ if (normalized && !result.includes(normalized)) {
386
+ result.push(normalized);
387
+ }
388
+ if (result.length >= limit) {
389
+ break;
390
+ }
391
+ }
392
+ return result;
393
+ }
394
+
395
+ function isoNow(value?: Date | string): string {
396
+ if (value instanceof Date) {
397
+ return value.toISOString();
398
+ }
399
+ const parsed = value ? new Date(value) : new Date();
400
+ if (Number.isFinite(parsed.getTime())) {
401
+ return parsed.toISOString();
402
+ }
403
+ return new Date().toISOString();
404
+ }
405
+
406
+ function stableHash(prefix: string, value: any): string {
407
+ const normalized = typeof value === 'string'
408
+ ? cleanText(value, 12000)
409
+ : JSON.stringify(value || {});
410
+ let hash = 0;
411
+ for (let index = 0; index < normalized.length; index += 1) {
412
+ hash = ((hash << 5) - hash + normalized.charCodeAt(index)) | 0;
413
+ }
414
+ return `${prefix}-${Math.abs(hash).toString(36) || '0'}`;
415
+ }
416
+
417
+ export function normalizeResolveIOAIManagerFailureClass(value: any): string {
418
+ const normalized = cleanText(value, 80)
419
+ .toLowerCase()
420
+ .replace(/[\s-]+/g, '_');
421
+ if (!normalized) {
422
+ return 'unknown';
423
+ }
424
+ if (/^(qa_infra|infrastructure|harness|puppeteer|chrome|mongo|port|startup)$/.test(normalized)) {
425
+ return 'infra';
426
+ }
427
+ if (/^(build|compile|typescript|tsc|angular_build|ng_build)$/.test(normalized)) {
428
+ return 'compile';
429
+ }
430
+ if (/^(false_pass|route_only|missing_business_proof)$/.test(normalized)) {
431
+ return 'business';
432
+ }
433
+ return normalized.slice(0, 80);
434
+ }
435
+
436
+ export function fingerprintResolveIOAIManagerBlocker(value: any): string {
437
+ const normalized = cleanText(value, 4000)
438
+ .toLowerCase()
439
+ .replace(/[a-f0-9]{16,}/g, '<id>')
440
+ .replace(/\b\d{2,}\b/g, '<n>')
441
+ .replace(/\bline\s+<n>\b/g, 'line <n>')
442
+ .replace(/https?:\/\/\S+/g, '<url>')
443
+ .replace(/\s+/g, ' ')
444
+ .trim();
445
+ return stableHash('mgr-blocker', normalized);
446
+ }
447
+
448
+ function resolveResolveIOAIManagerBlockerFingerprint(
449
+ record: ResolveIOAIManagerFailureRecord | undefined,
450
+ fallback?: any
451
+ ): string {
452
+ const blockerText = cleanText(record?.blocker || record?.summary, 4000);
453
+ if (blockerText) {
454
+ return fingerprintResolveIOAIManagerBlocker(blockerText);
455
+ }
456
+ const explicit = cleanText(record?.blockerFingerprint, 120);
457
+ if (explicit) {
458
+ return explicit;
459
+ }
460
+ return fingerprintResolveIOAIManagerBlocker(fallback || '');
461
+ }
462
+
463
+ export function hashResolveIOAIManagerEvidence(record: ResolveIOAIManagerFailureRecord | undefined): string {
464
+ if (!record) {
465
+ return stableHash('mgr-evidence', '');
466
+ }
467
+ const explicit = cleanText(record.evidenceHash, 120);
468
+ if (explicit) {
469
+ return explicit;
470
+ }
471
+ return stableHash('mgr-evidence', {
472
+ failureClass: normalizeResolveIOAIManagerFailureClass(record.failureClass),
473
+ blocker: cleanText(record.blocker || record.summary, 2000),
474
+ changedFiles: cleanList(record.changedFiles, 80, 500).sort(),
475
+ artifactPaths: cleanList(record.artifactPaths, 80, 500).sort()
476
+ });
477
+ }
478
+
479
+ export function buildResolveIOAIManagerRecoveryCheckpoint(
480
+ input: ResolveIOAIManagerRecoveryCheckpointInput
481
+ ): ResolveIOAIManagerRecoveryCheckpoint {
482
+ const plan = input.plan;
483
+ const current = input.current || {};
484
+ const blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current, plan.objective);
485
+ const evidenceHash = hashResolveIOAIManagerEvidence(current);
486
+ const changedFiles = cleanList(current.changedFiles, 80, 500);
487
+ const artifactPaths = cleanList(current.artifactPaths, 80, 500);
488
+ const previous = input.previousCheckpoint;
489
+ const sameCheckpointBase = previous
490
+ && previous.recoveryClass === plan.recoveryClass
491
+ && previous.lane === plan.lane
492
+ && previous.stepType === plan.stepType
493
+ && previous.blockerFingerprint === blockerFingerprint
494
+ && previous.evidenceHash === evidenceHash;
495
+ const attempts = sameCheckpointBase ? Math.max(0, Number(previous.attempts || 0)) + 1 : 1;
496
+ const status: ResolveIOAIManagerRecoveryCheckpointStatus = plan.recoveryClass === 'manual_handoff'
497
+ ? 'manual_handoff'
498
+ : plan.recoveryClass === 'blocked_until_new_evidence'
499
+ ? 'parked'
500
+ : plan.recoveryClass === 'advance_after_proof'
501
+ ? 'complete'
502
+ : 'active';
503
+ const now = isoNow(input.now);
504
+ const checkpointId = stableHash('mgr-recovery', {
505
+ recoveryClass: plan.recoveryClass,
506
+ lane: plan.lane,
507
+ stepType: plan.stepType,
508
+ allowedAction: plan.allowedAction,
509
+ blockerFingerprint,
510
+ evidenceHash
511
+ });
512
+ return {
513
+ checkpointId,
514
+ recoveryClass: plan.recoveryClass,
515
+ status,
516
+ lane: plan.lane,
517
+ stepType: plan.stepType,
518
+ allowedAction: plan.allowedAction,
519
+ productRepairAllowed: plan.productRepairAllowed,
520
+ expensiveModelAllowed: plan.expensiveModelAllowed,
521
+ attempts,
522
+ maxAttemptsBeforePark: plan.maxAttemptsBeforePark,
523
+ blockerFingerprint,
524
+ evidenceHash,
525
+ changedFiles,
526
+ artifactPaths,
527
+ requiredEvidence: cleanList(plan.requiredEvidence, 40, 500),
528
+ loopResetEvidence: cleanList(plan.loopResetEvidence, 40, 500),
529
+ forbiddenActions: cleanList(plan.forbiddenActions, 40, 500),
530
+ objective: cleanText(plan.objective, 1000),
531
+ nextActionLabel: cleanText(plan.nextActionLabel, 160),
532
+ createdAt: sameCheckpointBase && previous?.createdAt ? previous.createdAt : now,
533
+ updatedAt: now
534
+ };
535
+ }
536
+
537
+ function makeRecoveryEvidenceProbeStep(
538
+ id: string,
539
+ kind: ResolveIOAIManagerRecoveryEvidenceProbeStepKind,
540
+ label: string,
541
+ objective: string,
542
+ artifactExpectation: string,
543
+ successSignal: string,
544
+ options: Partial<Pick<ResolveIOAIManagerRecoveryEvidenceProbeStep, 'required' | 'commandHint'>> = {}
545
+ ): ResolveIOAIManagerRecoveryEvidenceProbeStep {
546
+ return {
547
+ id,
548
+ kind,
549
+ label,
550
+ objective: cleanText(objective, 1000),
551
+ required: options.required !== false,
552
+ ...(options.commandHint ? { commandHint: cleanText(options.commandHint, 500) } : {}),
553
+ artifactExpectation: cleanText(artifactExpectation, 500),
554
+ successSignal: cleanText(successSignal, 500)
555
+ };
556
+ }
557
+
558
+ function recoveryEvidenceProbeStepsFor(
559
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint
560
+ ): ResolveIOAIManagerRecoveryEvidenceProbeStep[] {
561
+ const base = [
562
+ makeRecoveryEvidenceProbeStep(
563
+ 'snapshot_current_blocker',
564
+ 'rerun_same_gate',
565
+ 'Snapshot Current Blocker',
566
+ 'Capture the current blocker, failure class, evidence hash, changed files, and artifact paths before any new repair.',
567
+ 'runner-evidence/current-blocker.json',
568
+ 'Snapshot includes the same checkpointId, blockerFingerprint, and evidenceHashBefore.'
569
+ )
570
+ ];
571
+ if (checkpoint.recoveryClass === 'diagnosis_only' || checkpoint.recoveryClass === 'diagnosis_revision') {
572
+ return [
573
+ ...base,
574
+ makeRecoveryEvidenceProbeStep(
575
+ 'collect_read_only_root_cause_evidence',
576
+ 'read_only_diagnosis',
577
+ 'Collect Read-Only Root-Cause Evidence',
578
+ checkpoint.recoveryClass === 'diagnosis_revision'
579
+ ? 'Collect new evidence that proves the current owner_files or failing_path is wrong before broadening scope.'
580
+ : 'Reproduce or classify the issue and record the exact customer complaint, expected result, observed result, route/module, and account context.',
581
+ 'runner-evidence/diagnosis-readonly.md',
582
+ 'Evidence supports one falsifiable accepted hypothesis and at least one rejected alternative.'
583
+ ),
584
+ makeRecoveryEvidenceProbeStep(
585
+ 'validate_diagnosis_gate',
586
+ 'read_only_diagnosis',
587
+ 'Validate Diagnosis Gate',
588
+ 'Validate issue_case, accepted_hypothesis, rejected_alternatives, failing_path, owner_files, and before/action/after proof_plan.',
589
+ 'runner-evidence/diagnosis-gate.json',
590
+ 'Diagnosis gate validates before product-code repair is allowed.'
591
+ )
592
+ ];
593
+ }
594
+ if (checkpoint.recoveryClass === 'infra_repair') {
595
+ return [
596
+ ...base,
597
+ makeRecoveryEvidenceProbeStep(
598
+ 'run_infra_preflight',
599
+ 'infra_preflight',
600
+ 'Run Infra Preflight',
601
+ 'Check Puppeteer/Chrome, ports, Mongo/settings, cache state, startup commands, and server/client process health.',
602
+ 'runner-evidence/infra-preflight.log',
603
+ 'The same infra gate either passes or returns a new infra blocker hash.',
604
+ { commandHint: 'runner preflight: puppeteer/chrome/mongo/ports/startup' }
605
+ )
606
+ ];
607
+ }
608
+ if (checkpoint.recoveryClass === 'compile_repair') {
609
+ return [
610
+ ...base,
611
+ makeRecoveryEvidenceProbeStep(
612
+ 'rerun_compile_gate',
613
+ 'compile_check',
614
+ 'Rerun Compile Gate',
615
+ 'Rerun the same deterministic compile/build command and capture the first actionable error.',
616
+ 'runner-evidence/compile.log',
617
+ 'Compile passes or the first failing error changes.',
618
+ { commandHint: 'same finite build/compile command from the failed gate' }
619
+ )
620
+ ];
621
+ }
622
+ if (checkpoint.recoveryClass === 'journey_contract_repair') {
623
+ return [
624
+ ...base,
625
+ makeRecoveryEvidenceProbeStep(
626
+ 'validate_journey_contract',
627
+ 'journey_validation',
628
+ 'Validate Journey Contract',
629
+ 'Validate docs/APP_JOURNEY_CONTRACT.md has first/next/last workflow, route/action/method mapping, seeded data story, completion states, and QA assertions.',
630
+ 'runner-evidence/journey-contract-validation.json',
631
+ 'Journey contract validates before build tasks continue.'
632
+ ),
633
+ makeRecoveryEvidenceProbeStep(
634
+ 'verify_hub_workflow_mapping',
635
+ 'journey_validation',
636
+ 'Verify Hub Workflow Mapping',
637
+ 'Confirm the hub CTA and screen sequence implement the journey contract instead of link-only navigation.',
638
+ 'runner-evidence/hub-workflow-map.json',
639
+ 'Primary hub action maps to a real route/action/method/calculation and next state.'
640
+ )
641
+ ];
642
+ }
643
+ if (checkpoint.recoveryClass === 'business_proof_repair' || checkpoint.recoveryClass === 'product_code_repair') {
644
+ return [
645
+ ...base,
646
+ makeRecoveryEvidenceProbeStep(
647
+ 'rerun_business_assertion',
648
+ 'business_assertion',
649
+ 'Rerun Business Assertion',
650
+ 'Run the exact issue/app promise proof and capture before/action/after DOM/data evidence.',
651
+ 'runner-evidence/business-assertion.json',
652
+ 'Business assertion passes, or the observed failure changes with a new artifact path.'
653
+ ),
654
+ makeRecoveryEvidenceProbeStep(
655
+ 'check_diff_scope',
656
+ 'diff_scope_check',
657
+ 'Check Diff Scope',
658
+ 'Compare changed files against the current diagnosis/journey owner scope before another code repair.',
659
+ 'runner-evidence/diff-scope.json',
660
+ 'Changed files are in scope, or diagnosis/journey scope is revised with evidence.'
661
+ )
662
+ ];
663
+ }
664
+ if (checkpoint.recoveryClass === 'release_repair') {
665
+ return [
666
+ ...base,
667
+ makeRecoveryEvidenceProbeStep(
668
+ 'collect_release_status',
669
+ 'release_status',
670
+ 'Collect Release Status',
671
+ 'Collect publish/deploy/build-instance/domain/CloudFront status and the last actionable deploy error.',
672
+ 'runner-evidence/release-status.json',
673
+ 'Release gate passes or returns a new release blocker hash without product-code repair.'
674
+ )
675
+ ];
676
+ }
677
+ if (checkpoint.recoveryClass === 'manual_handoff') {
678
+ return [
679
+ ...base,
680
+ makeRecoveryEvidenceProbeStep(
681
+ 'operator_review_checkpoint',
682
+ 'operator_review',
683
+ 'Operator Review Checkpoint',
684
+ 'Expose budget, blocker, evidence hash, and the minimum policy/scope change needed before another expensive loop.',
685
+ 'runner-evidence/operator-review.json',
686
+ 'Operator approves a new scope/policy or provides new external evidence.'
687
+ )
688
+ ];
689
+ }
690
+ return [
691
+ ...base,
692
+ makeRecoveryEvidenceProbeStep(
693
+ 'rerun_same_deterministic_gate',
694
+ 'rerun_same_gate',
695
+ 'Rerun Same Deterministic Gate',
696
+ 'Rerun the exact failed check and capture new logs/artifacts without changing product code first.',
697
+ 'runner-evidence/retry-gate.log',
698
+ 'Gate passes, or evidenceHash/blockerFingerprint/artifactPaths change.'
699
+ )
700
+ ];
701
+ }
702
+
703
+ export function buildResolveIOAIManagerRecoveryEvidenceProbe(
704
+ input: ResolveIOAIManagerRecoveryEvidenceProbeInput
705
+ ): ResolveIOAIManagerRecoveryEvidenceProbe {
706
+ const checkpoint = input.checkpoint;
707
+ const now = isoNow(input.now);
708
+ const steps = recoveryEvidenceProbeStepsFor(checkpoint);
709
+ const requiredArtifacts = Array.from(new Set(steps
710
+ .filter((step) => step.required)
711
+ .map((step) => step.artifactExpectation)
712
+ .filter(Boolean)));
713
+ return {
714
+ probeId: stableHash('mgr-probe', {
715
+ checkpointId: checkpoint.checkpointId,
716
+ recoveryClass: checkpoint.recoveryClass,
717
+ evidenceHash: checkpoint.evidenceHash,
718
+ blockerFingerprint: checkpoint.blockerFingerprint
719
+ }),
720
+ checkpointId: checkpoint.checkpointId,
721
+ recoveryClass: checkpoint.recoveryClass,
722
+ lane: checkpoint.lane,
723
+ stepType: checkpoint.stepType,
724
+ objective: checkpoint.status === 'parked'
725
+ ? 'Collect new evidence before any additional expensive model/code repair.'
726
+ : cleanText(checkpoint.objective, 1000),
727
+ evidenceOnly: checkpoint.status === 'parked'
728
+ || checkpoint.recoveryClass === 'diagnosis_only'
729
+ || checkpoint.recoveryClass === 'diagnosis_revision'
730
+ || checkpoint.recoveryClass === 'infra_repair'
731
+ || checkpoint.recoveryClass === 'compile_repair'
732
+ || checkpoint.recoveryClass === 'release_repair',
733
+ productRepairAllowed: checkpoint.productRepairAllowed && checkpoint.status !== 'parked',
734
+ expensiveModelAllowed: checkpoint.expensiveModelAllowed && checkpoint.status !== 'parked',
735
+ evidenceHashBefore: checkpoint.evidenceHash,
736
+ blockerFingerprint: checkpoint.blockerFingerprint,
737
+ steps,
738
+ requiredArtifacts,
739
+ acceptanceEvidence: Array.from(new Set([
740
+ ...checkpoint.requiredEvidence,
741
+ ...checkpoint.loopResetEvidence,
742
+ ...steps.map((step) => step.successSignal)
743
+ ].map((entry) => cleanText(entry, 500)).filter(Boolean))).slice(0, 30),
744
+ stopConditions: Array.from(new Set([
745
+ ...checkpoint.forbiddenActions,
746
+ 'no new evidence hash',
747
+ 'no new artifact path',
748
+ 'product-code repair requested while evidenceOnly is true'
749
+ ].map((entry) => cleanText(entry, 500)).filter(Boolean))).slice(0, 30),
750
+ loopResetEvidence: checkpoint.loopResetEvidence,
751
+ createdAt: now
752
+ };
753
+ }
754
+
755
+ function recoveryAutomationModeFor(
756
+ checkpoint: ResolveIOAIManagerRecoveryCheckpoint
757
+ ): ResolveIOAIManagerRecoveryAutomationMode {
758
+ if (checkpoint.status === 'manual_handoff' || checkpoint.recoveryClass === 'manual_handoff') {
759
+ return 'manual_review';
760
+ }
761
+ if (checkpoint.status === 'complete' || checkpoint.recoveryClass === 'advance_after_proof') {
762
+ return 'advance';
763
+ }
764
+ if (checkpoint.status === 'parked' || checkpoint.recoveryClass === 'blocked_until_new_evidence') {
765
+ return 'collect_evidence';
766
+ }
767
+ if (checkpoint.recoveryClass === 'diagnosis_only' || checkpoint.recoveryClass === 'diagnosis_revision') {
768
+ return 'read_only_diagnosis';
769
+ }
770
+ if (checkpoint.recoveryClass === 'infra_repair') {
771
+ return 'repair_infra';
772
+ }
773
+ if (checkpoint.recoveryClass === 'compile_repair') {
774
+ return 'repair_compile';
775
+ }
776
+ if (checkpoint.recoveryClass === 'journey_contract_repair') {
777
+ return 'repair_journey_contract';
778
+ }
779
+ if (checkpoint.recoveryClass === 'business_proof_repair') {
780
+ return 'repair_business_assertion';
781
+ }
782
+ if (checkpoint.recoveryClass === 'release_repair') {
783
+ return 'repair_release';
784
+ }
785
+ if (checkpoint.recoveryClass === 'product_code_repair') {
786
+ return 'targeted_product_repair';
787
+ }
788
+ return 'continue_gate';
789
+ }
790
+
791
+ function recoveryActionLabelFor(mode: ResolveIOAIManagerRecoveryAutomationMode, checkpoint: ResolveIOAIManagerRecoveryCheckpoint): string {
792
+ const explicit = cleanText(checkpoint.nextActionLabel, 120);
793
+ if (explicit && mode !== 'collect_evidence') {
794
+ return explicit;
795
+ }
796
+ const labels: Record<ResolveIOAIManagerRecoveryAutomationMode, string> = {
797
+ advance: 'Advance To Next Gate',
798
+ collect_evidence: 'Collect New Evidence',
799
+ read_only_diagnosis: 'Run Diagnosis Evidence Pass',
800
+ repair_infra: 'Repair Infra Gate',
801
+ repair_compile: 'Repair Compile Gate',
802
+ repair_journey_contract: 'Repair Journey Contract',
803
+ repair_business_assertion: 'Repair Business Proof',
804
+ repair_release: 'Repair Release Gate',
805
+ targeted_product_repair: 'Run Targeted Repair',
806
+ manual_review: 'Manual Review',
807
+ continue_gate: 'Continue Current Gate'
808
+ };
809
+ return labels[mode];
810
+ }
811
+
812
+ function recoveryActionAutoRunnable(
813
+ mode: ResolveIOAIManagerRecoveryAutomationMode,
814
+ probe: ResolveIOAIManagerRecoveryEvidenceProbe
815
+ ): boolean {
816
+ if (mode === 'manual_review') {
817
+ return false;
818
+ }
819
+ if (mode === 'advance' || mode === 'continue_gate') {
820
+ return true;
821
+ }
822
+ if (mode === 'targeted_product_repair' || mode === 'read_only_diagnosis' || mode === 'repair_journey_contract' || mode === 'repair_business_assertion') {
823
+ return true;
824
+ }
825
+ return probe.steps.some((step) => step.commandHint || step.kind === 'rerun_same_gate' || step.kind === 'release_status' || step.kind === 'diff_scope_check');
826
+ }
827
+
828
+ export function buildResolveIOAIManagerRecoveryActionPacket(
829
+ input: ResolveIOAIManagerRecoveryActionPacketInput
830
+ ): ResolveIOAIManagerRecoveryActionPacket {
831
+ const checkpoint = input.checkpoint;
832
+ const probe = input.probe || buildResolveIOAIManagerRecoveryEvidenceProbe({
833
+ checkpoint,
834
+ current: input.current,
835
+ now: input.now
836
+ });
837
+ const mode = recoveryAutomationModeFor(checkpoint);
838
+ const primaryStep = probe.steps.find((step) => step.required && step.id !== 'snapshot_current_blocker')
839
+ || probe.steps.find((step) => step.required)
840
+ || probe.steps[0];
841
+ const evidenceOnly = probe.evidenceOnly || mode === 'collect_evidence' || mode === 'repair_infra' || mode === 'repair_compile' || mode === 'repair_release';
842
+ const requireNewEvidence = mode === 'collect_evidence'
843
+ || checkpoint.status === 'parked'
844
+ || checkpoint.attempts >= checkpoint.maxAttemptsBeforePark;
845
+ const stopWhen = Array.from(new Set([
846
+ ...probe.stopConditions,
847
+ ...(requireNewEvidence ? ['same blocker fingerprint and same evidence hash after probe'] : [])
848
+ ].map((entry) => cleanText(entry, 500)).filter(Boolean))).slice(0, 30);
849
+ const resetLoopWhen = Array.from(new Set([
850
+ ...checkpoint.loopResetEvidence,
851
+ ...probe.loopResetEvidence,
852
+ ...(requireNewEvidence ? ['changed evidence hash', 'new artifact path'] : [])
853
+ ].map((entry) => cleanText(entry, 500)).filter(Boolean))).slice(0, 30);
854
+ const nextCommands = probe.steps
855
+ .map((step) => cleanText(step.commandHint || `${step.kind}:${step.id}`, 500))
856
+ .filter(Boolean)
857
+ .slice(0, 12);
858
+ const now = isoNow(input.now);
859
+ return {
860
+ actionId: stableHash('mgr-action', {
861
+ checkpointId: checkpoint.checkpointId,
862
+ probeId: probe.probeId,
863
+ mode,
864
+ evidenceHash: checkpoint.evidenceHash,
865
+ blockerFingerprint: checkpoint.blockerFingerprint
866
+ }),
867
+ checkpointId: checkpoint.checkpointId,
868
+ probeId: probe.probeId,
869
+ recoveryClass: checkpoint.recoveryClass,
870
+ mode,
871
+ label: recoveryActionLabelFor(mode, checkpoint),
872
+ lane: checkpoint.lane,
873
+ stepType: checkpoint.stepType,
874
+ primaryStepKind: primaryStep?.kind || 'none',
875
+ objective: mode === 'collect_evidence'
876
+ ? probe.objective
877
+ : cleanText(checkpoint.objective || probe.objective, 1000),
878
+ evidenceOnly,
879
+ autoRunnable: recoveryActionAutoRunnable(mode, probe),
880
+ productRepairAllowed: checkpoint.productRepairAllowed && !evidenceOnly && checkpoint.status !== 'parked',
881
+ expensiveModelAllowed: checkpoint.expensiveModelAllowed && checkpoint.status !== 'parked',
882
+ canResetLoopAfterEvidence: resetLoopWhen.length > 0,
883
+ maxAttemptsBeforePark: checkpoint.maxAttemptsBeforePark,
884
+ requiredArtifacts: probe.requiredArtifacts.slice(0, 20),
885
+ nextCommands,
886
+ successCriteria: probe.acceptanceEvidence.slice(0, 20),
887
+ retryPolicy: {
888
+ allowImmediateRetry: checkpoint.status !== 'parked' && mode !== 'manual_review',
889
+ requireNewEvidence,
890
+ resetLoopWhen,
891
+ stopWhen
892
+ },
893
+ ...(mode === 'collect_evidence' ? { blockedReason: 'Manager parked this loop until the recovery action records new evidence.' } : {}),
894
+ createdAt: now
895
+ };
896
+ }
897
+
898
+ function dispatchActionForMode(mode: ResolveIOAIManagerRecoveryAutomationMode): ResolveIOAIManagerRecoveryActionDispatchAction {
899
+ const map: Record<ResolveIOAIManagerRecoveryAutomationMode, ResolveIOAIManagerRecoveryActionDispatchAction> = {
900
+ advance: 'advance',
901
+ collect_evidence: 'run_evidence_probe',
902
+ read_only_diagnosis: 'run_read_only_diagnosis',
903
+ repair_infra: 'run_infra_repair',
904
+ repair_compile: 'run_compile_repair',
905
+ repair_journey_contract: 'run_journey_contract_repair',
906
+ repair_business_assertion: 'run_business_assertion_repair',
907
+ repair_release: 'run_release_repair',
908
+ targeted_product_repair: 'run_targeted_product_repair',
909
+ manual_review: 'park_manual',
910
+ continue_gate: 'continue_gate'
911
+ };
912
+ return map[mode] || 'park_manual';
913
+ }
914
+
915
+ function buildRecoveryDispatchRecord(
916
+ action: ResolveIOAIManagerRecoveryActionPacket,
917
+ dispatchAction: ResolveIOAIManagerRecoveryActionDispatchAction,
918
+ status: ResolveIOAIManagerRecoveryActionDispatchStatus,
919
+ reason: string,
920
+ current?: ResolveIOAIManagerFailureRecord,
921
+ now?: Date | string
922
+ ): ResolveIOAIManagerRecoveryActionDispatchRecord {
923
+ const evidenceHash = current?.evidenceHash || action.checkpointId || action.actionId;
924
+ const blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current, action.objective);
925
+ const artifactPaths = cleanList(current?.artifactPaths, 20, 500);
926
+ const createdAt = isoNow(now);
927
+ return {
928
+ dispatchId: stableHash('mgr-dispatch', {
929
+ actionId: action.actionId,
930
+ dispatchAction,
931
+ evidenceHash,
932
+ blockerFingerprint,
933
+ status
934
+ }),
935
+ actionId: action.actionId,
936
+ checkpointId: action.checkpointId,
937
+ probeId: action.probeId,
938
+ mode: action.mode,
939
+ dispatchAction,
940
+ status,
941
+ evidenceHash,
942
+ blockerFingerprint,
943
+ productRepairAllowed: action.productRepairAllowed && dispatchAction === 'run_targeted_product_repair',
944
+ expensiveModelAllowed: action.expensiveModelAllowed && dispatchAction !== 'run_evidence_probe',
945
+ reason,
946
+ artifactPaths,
947
+ ...(status === 'started' ? { startedAt: createdAt } : {}),
948
+ ...(status === 'completed' ? { completedAt: createdAt } : {}),
949
+ createdAt
950
+ };
951
+ }
952
+
953
+ export function decideResolveIOAIManagerRecoveryActionDispatch(
954
+ input: ResolveIOAIManagerRecoveryActionDispatchInput
955
+ ): ResolveIOAIManagerRecoveryActionDispatchDecision {
956
+ const action = input.action;
957
+ const history = Array.isArray(input.history) ? input.history.filter(Boolean).slice(-50) : [];
958
+ const current = input.current || {};
959
+ if (!action) {
960
+ return {
961
+ dispatchAction: 'park_manual',
962
+ allowed: false,
963
+ reason: 'recovery_dispatch_missing_action',
964
+ status: 'parked',
965
+ canRunProductRepair: false,
966
+ canRunExpensiveModel: false,
967
+ shouldRecordDispatch: false,
968
+ requiresNewEvidence: true,
969
+ newEvidence: false
970
+ };
971
+ }
972
+ const dispatchAction = dispatchActionForMode(action.mode);
973
+ const evidenceHash = current.evidenceHash || action.checkpointId || action.actionId;
974
+ const blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current, action.objective);
975
+ const sameActionHistory = history.filter((entry) => entry.actionId === action.actionId);
976
+ const sameEvidenceHistory = sameActionHistory.filter((entry) => entry.evidenceHash === evidenceHash
977
+ && entry.blockerFingerprint === blockerFingerprint);
978
+ const activeDispatch = sameEvidenceHistory.find((entry) => entry.status === 'queued' || entry.status === 'started');
979
+ const completedDispatch = sameEvidenceHistory.find((entry) => entry.status === 'completed' || entry.status === 'failed');
980
+ const newEvidence = sameActionHistory.length > 0 && sameEvidenceHistory.length === 0;
981
+ const requiresNewEvidence = action.retryPolicy.requireNewEvidence === true;
982
+ const manualOnly = action.mode === 'manual_review' || !action.autoRunnable;
983
+ const productDispatch = dispatchAction === 'run_targeted_product_repair';
984
+ const expensiveDispatch = !['run_evidence_probe', 'advance', 'continue_gate', 'park_manual'].includes(dispatchAction);
985
+ if (manualOnly && input.operatorApproved !== true) {
986
+ const record = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_requires_manual_review', current, input.now);
987
+ return {
988
+ dispatchAction: 'park_manual',
989
+ allowed: false,
990
+ reason: record.reason,
991
+ status: 'parked',
992
+ canRunProductRepair: false,
993
+ canRunExpensiveModel: false,
994
+ shouldRecordDispatch: true,
995
+ requiresNewEvidence,
996
+ newEvidence,
997
+ dispatchRecord: record
998
+ };
999
+ }
1000
+ if (productDispatch && action.productRepairAllowed !== true) {
1001
+ const record = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_product_repair_not_allowed', current, input.now);
1002
+ return {
1003
+ dispatchAction: 'park_manual',
1004
+ allowed: false,
1005
+ reason: record.reason,
1006
+ status: 'parked',
1007
+ canRunProductRepair: false,
1008
+ canRunExpensiveModel: false,
1009
+ shouldRecordDispatch: true,
1010
+ requiresNewEvidence: true,
1011
+ newEvidence,
1012
+ dispatchRecord: record
1013
+ };
1014
+ }
1015
+ if (activeDispatch) {
1016
+ return {
1017
+ dispatchAction: 'park_manual',
1018
+ allowed: false,
1019
+ reason: 'recovery_dispatch_already_running_for_same_evidence',
1020
+ status: 'parked',
1021
+ canRunProductRepair: false,
1022
+ canRunExpensiveModel: false,
1023
+ shouldRecordDispatch: false,
1024
+ requiresNewEvidence: true,
1025
+ newEvidence: false
1026
+ };
1027
+ }
1028
+ if (completedDispatch && requiresNewEvidence && !newEvidence) {
1029
+ const record = buildRecoveryDispatchRecord(action, 'park_manual', 'parked', 'recovery_dispatch_same_evidence_already_attempted', current, input.now);
1030
+ return {
1031
+ dispatchAction: 'park_manual',
1032
+ allowed: false,
1033
+ reason: record.reason,
1034
+ status: 'parked',
1035
+ canRunProductRepair: false,
1036
+ canRunExpensiveModel: false,
1037
+ shouldRecordDispatch: true,
1038
+ requiresNewEvidence: true,
1039
+ newEvidence: false,
1040
+ dispatchRecord: record
1041
+ };
1042
+ }
1043
+ const status: ResolveIOAIManagerRecoveryActionDispatchStatus = dispatchAction === 'advance' || dispatchAction === 'continue_gate'
1044
+ ? 'completed'
1045
+ : 'started';
1046
+ const record = buildRecoveryDispatchRecord(action, dispatchAction, status, 'recovery_dispatch_allowed', current, input.now);
1047
+ return {
1048
+ dispatchAction,
1049
+ allowed: true,
1050
+ reason: 'recovery_dispatch_allowed',
1051
+ status,
1052
+ canRunProductRepair: productDispatch && action.productRepairAllowed === true,
1053
+ canRunExpensiveModel: expensiveDispatch && action.expensiveModelAllowed === true,
1054
+ shouldRecordDispatch: true,
1055
+ requiresNewEvidence,
1056
+ newEvidence,
1057
+ dispatchRecord: record
1058
+ };
1059
+ }
1060
+
1061
+ export function appendResolveIOAIManagerRecoveryActionDispatch(
1062
+ history: ResolveIOAIManagerRecoveryActionDispatchRecord[] | undefined,
1063
+ record: ResolveIOAIManagerRecoveryActionDispatchRecord | undefined,
1064
+ limit = 50
1065
+ ): ResolveIOAIManagerRecoveryActionDispatchRecord[] {
1066
+ const existing = Array.isArray(history) ? history.filter(Boolean) : [];
1067
+ if (!record) {
1068
+ return existing.slice(-limit);
1069
+ }
1070
+ const deduped = existing.filter((entry) => entry.dispatchId !== record.dispatchId);
1071
+ return [...deduped, record].slice(-limit);
1072
+ }
1073
+
1074
+ function recoveryExecutionPhaseForDispatch(
1075
+ dispatchAction: ResolveIOAIManagerRecoveryActionDispatchAction
1076
+ ): ResolveIOAIManagerRecoveryExecutionPhase {
1077
+ const map: Record<ResolveIOAIManagerRecoveryActionDispatchAction, ResolveIOAIManagerRecoveryExecutionPhase> = {
1078
+ run_evidence_probe: 'evidence',
1079
+ run_read_only_diagnosis: 'diagnosis',
1080
+ run_infra_repair: 'infra',
1081
+ run_compile_repair: 'compile',
1082
+ run_journey_contract_repair: 'journey',
1083
+ run_business_assertion_repair: 'business_proof',
1084
+ run_release_repair: 'release',
1085
+ run_targeted_product_repair: 'product_repair',
1086
+ advance: 'advance',
1087
+ continue_gate: 'advance',
1088
+ park_manual: 'manual'
1089
+ };
1090
+ return map[dispatchAction] || 'manual';
1091
+ }
1092
+
1093
+ function recoveryDirectiveReason(
1094
+ action: ResolveIOAIManagerRecoveryActionPacket | undefined,
1095
+ decision: ResolveIOAIManagerRecoveryActionDispatchDecision,
1096
+ current?: ResolveIOAIManagerFailureRecord
1097
+ ): string {
1098
+ const blocker = cleanText(current?.blocker || current?.summary || '', 260);
1099
+ const label = cleanText(action?.label, 120) || decision.dispatchAction;
1100
+ const objective = cleanText(action?.objective, 260);
1101
+ return [
1102
+ `MANAGER_RECOVERY:${decision.dispatchAction}`,
1103
+ `label=${label}`,
1104
+ decision.reason ? `reason=${decision.reason}` : '',
1105
+ blocker ? `blocker=${blocker}` : '',
1106
+ objective ? `objective=${objective}` : ''
1107
+ ].filter(Boolean).join(' | ');
1108
+ }
1109
+
1110
+ export function buildResolveIOAIManagerRecoveryExecutionDirective(
1111
+ input: ResolveIOAIManagerRecoveryExecutionDirectiveInput
1112
+ ): ResolveIOAIManagerRecoveryExecutionDirective {
1113
+ const action = input.action;
1114
+ const dispatchDecision = input.dispatchDecision || decideResolveIOAIManagerRecoveryActionDispatch({
1115
+ action,
1116
+ current: input.current,
1117
+ now: input.now
1118
+ });
1119
+ const dispatchAction = dispatchDecision.dispatchAction;
1120
+ const now = isoNow(input.now);
1121
+ const phase = recoveryExecutionPhaseForDispatch(dispatchAction);
1122
+ const lane = cleanText(action?.lane || input.current?.lane || '', 120);
1123
+ const stepType = cleanText(action?.stepType || input.current?.stepType || '', 120);
1124
+ const rerunReason = recoveryDirectiveReason(action, dispatchDecision, input.current);
1125
+ const surface = cleanText(input.surface || 'runner', 120);
1126
+ return {
1127
+ directiveId: stableHash('mgr-directive', {
1128
+ surface,
1129
+ actionId: action?.actionId || '',
1130
+ dispatchAction,
1131
+ reason: dispatchDecision.reason,
1132
+ evidenceHash: dispatchDecision.dispatchRecord?.evidenceHash || input.current?.evidenceHash || ''
1133
+ }),
1134
+ surface,
1135
+ dispatchAction,
1136
+ phase,
1137
+ allowed: dispatchDecision.allowed,
1138
+ status: dispatchDecision.status,
1139
+ reason: dispatchDecision.reason,
1140
+ lane,
1141
+ stepType,
1142
+ nextActionLabel: cleanText(action?.label, 160) || dispatchAction,
1143
+ rerunReason,
1144
+ evidenceOnly: action?.evidenceOnly !== false || dispatchAction === 'run_evidence_probe',
1145
+ autoRunnable: action?.autoRunnable === true,
1146
+ productRepairAllowed: action?.productRepairAllowed === true,
1147
+ expensiveModelAllowed: action?.expensiveModelAllowed === true,
1148
+ canRunProductRepair: dispatchDecision.canRunProductRepair,
1149
+ canRunExpensiveModel: dispatchDecision.canRunExpensiveModel,
1150
+ canResetLoopAfterEvidence: action?.canResetLoopAfterEvidence === true,
1151
+ requiresNewEvidence: dispatchDecision.requiresNewEvidence,
1152
+ newEvidence: dispatchDecision.newEvidence,
1153
+ maxAttemptsBeforePark: Math.max(1, Number(action?.maxAttemptsBeforePark || 1) || 1),
1154
+ requiredArtifacts: cleanList(action?.requiredArtifacts, 20, 500),
1155
+ nextCommands: cleanList(action?.nextCommands, 20, 500),
1156
+ successCriteria: cleanList(action?.successCriteria, 20, 500),
1157
+ forbiddenActions: action?.productRepairAllowed === true
1158
+ ? []
1159
+ : ['Do not run product-code repair from this directive unless canRunProductRepair is true.'],
1160
+ ...(dispatchDecision.dispatchRecord ? { dispatchRecord: dispatchDecision.dispatchRecord } : {}),
1161
+ createdAt: now
1162
+ };
1163
+ }
1164
+
1165
+ function listHasNewEntry(current: string[], previous: string[]): boolean {
1166
+ const existing = new Set(previous.map((entry) => cleanText(entry, 500)).filter(Boolean));
1167
+ return current.some((entry) => {
1168
+ const normalized = cleanText(entry, 500);
1169
+ return !!normalized && !existing.has(normalized);
1170
+ });
1171
+ }
1172
+
1173
+ function proposedActionIsProductRepair(value: any): boolean {
1174
+ const normalized = cleanText(value, 120);
1175
+ return /product|code|repair|build|business|journey|workflow/i.test(normalized)
1176
+ && !/infra|compile|diagnosis|manual|evidence|release|publish/i.test(normalized);
1177
+ }
1178
+
1179
+ export function decideResolveIOAIManagerRecoveryGate(
1180
+ input: ResolveIOAIManagerRecoveryGateInput
1181
+ ): ResolveIOAIManagerRecoveryGateDecision {
1182
+ const checkpoint = input.checkpoint;
1183
+ const hasCurrent = !!input.current;
1184
+ const current = input.current || {};
1185
+ const blockerFingerprint = hasCurrent
1186
+ ? resolveResolveIOAIManagerBlockerFingerprint(current, checkpoint.objective)
1187
+ : checkpoint.blockerFingerprint;
1188
+ const evidenceHash = hasCurrent ? hashResolveIOAIManagerEvidence(current) : checkpoint.evidenceHash;
1189
+ const changedFiles = hasCurrent ? cleanList(current.changedFiles, 80, 500) : checkpoint.changedFiles;
1190
+ const artifactPaths = hasCurrent ? cleanList(current.artifactPaths, 80, 500) : checkpoint.artifactPaths;
1191
+ const evidenceChanged = evidenceHash !== checkpoint.evidenceHash
1192
+ || blockerFingerprint !== checkpoint.blockerFingerprint
1193
+ || listHasNewEntry(changedFiles, checkpoint.changedFiles)
1194
+ || listHasNewEntry(artifactPaths, checkpoint.artifactPaths);
1195
+ const proposedAction = cleanText(input.proposedAction || checkpoint.allowedAction, 120);
1196
+ const productRepairRequested = proposedActionIsProductRepair(proposedAction);
1197
+ const missingEvidence = checkpoint.requiredEvidence.filter((required) => {
1198
+ const normalized = cleanText(required, 120).toLowerCase();
1199
+ if (!normalized) {
1200
+ return false;
1201
+ }
1202
+ if (/artifact|log|proof|gate|evidence/.test(normalized)) {
1203
+ return !artifactPaths.length && !current.evidenceHash;
1204
+ }
1205
+ if (/diff|changed files|owner|scope|file/.test(normalized)) {
1206
+ return !changedFiles.length;
1207
+ }
1208
+ return false;
1209
+ });
1210
+ const makeDecision = (
1211
+ action: ResolveIOAIManagerRecoveryGateAction,
1212
+ reason: string,
1213
+ overrides: Partial<ResolveIOAIManagerRecoveryGateDecision> = {}
1214
+ ): ResolveIOAIManagerRecoveryGateDecision => ({
1215
+ action,
1216
+ reason,
1217
+ canRunProductRepair: checkpoint.productRepairAllowed,
1218
+ canRunExpensiveModel: checkpoint.expensiveModelAllowed,
1219
+ shouldResetLoopBudget: false,
1220
+ shouldIncrementAttempt: action === 'allow',
1221
+ newEvidence: evidenceChanged,
1222
+ blockerFingerprint,
1223
+ evidenceHash,
1224
+ missingEvidence,
1225
+ checkpoint: {
1226
+ ...checkpoint,
1227
+ updatedAt: isoNow(input.now)
1228
+ },
1229
+ ...overrides
1230
+ });
1231
+
1232
+ if (checkpoint.status === 'complete') {
1233
+ return makeDecision('complete', 'recovery_gate_checkpoint_already_complete', {
1234
+ canRunProductRepair: false,
1235
+ canRunExpensiveModel: false,
1236
+ shouldIncrementAttempt: false
1237
+ });
1238
+ }
1239
+ if (checkpoint.status === 'manual_handoff' && input.operatorApproved !== true) {
1240
+ return makeDecision('manual_handoff', 'recovery_gate_manual_handoff_requires_operator_approval', {
1241
+ canRunProductRepair: false,
1242
+ canRunExpensiveModel: false,
1243
+ shouldIncrementAttempt: false
1244
+ });
1245
+ }
1246
+ if (productRepairRequested && !checkpoint.productRepairAllowed) {
1247
+ return makeDecision('reject_action', 'recovery_gate_product_repair_not_allowed_for_checkpoint', {
1248
+ canRunProductRepair: false,
1249
+ canRunExpensiveModel: false,
1250
+ shouldIncrementAttempt: false
1251
+ });
1252
+ }
1253
+ if (checkpoint.status === 'parked' && !evidenceChanged) {
1254
+ return makeDecision('collect_new_evidence', 'recovery_gate_parked_until_new_evidence', {
1255
+ canRunProductRepair: false,
1256
+ canRunExpensiveModel: false,
1257
+ shouldIncrementAttempt: false
1258
+ });
1259
+ }
1260
+ if (checkpoint.attempts >= checkpoint.maxAttemptsBeforePark && !evidenceChanged) {
1261
+ return makeDecision('collect_new_evidence', 'recovery_gate_attempt_limit_requires_new_evidence', {
1262
+ canRunProductRepair: false,
1263
+ canRunExpensiveModel: false,
1264
+ shouldIncrementAttempt: false
1265
+ });
1266
+ }
1267
+ if (evidenceChanged) {
1268
+ const currentFailureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);
1269
+ const currentCanRunProductRepair = checkpoint.productRepairAllowed
1270
+ || !/^(infra|compile|diagnosis|release)$/i.test(currentFailureClass);
1271
+ return makeDecision('allow', 'recovery_gate_new_evidence_unblocks_retry', {
1272
+ canRunProductRepair: currentCanRunProductRepair,
1273
+ canRunExpensiveModel: checkpoint.expensiveModelAllowed || currentCanRunProductRepair,
1274
+ shouldResetLoopBudget: true
1275
+ });
1276
+ }
1277
+ return makeDecision('allow', 'recovery_gate_action_allowed');
1278
+ }
1279
+
1280
+ function failureKey(record: ResolveIOAIManagerFailureRecord | undefined): string {
1281
+ if (!record) {
1282
+ return '';
1283
+ }
1284
+ const failureClass = normalizeResolveIOAIManagerFailureClass(record.failureClass);
1285
+ const blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(record);
1286
+ return `${cleanText(record.lane, 80)}:${cleanText(record.stepType, 80)}:${failureClass}:${blockerFingerprint}`;
1287
+ }
1288
+
1289
+ function failureEvidenceKey(record: ResolveIOAIManagerFailureRecord | undefined): string {
1290
+ return `${failureKey(record)}:${hashResolveIOAIManagerEvidence(record)}`;
1291
+ }
1292
+
1293
+ function isPassingOutcome(record: ResolveIOAIManagerFailureRecord | undefined): boolean {
1294
+ return /^(pass|accepted|ready_to_publish|published|ready_for_merge|complete|completed)$/i.test(cleanText(record?.outcome, 80));
1295
+ }
1296
+
1297
+ function isManualOutcome(record: ResolveIOAIManagerFailureRecord | undefined): boolean {
1298
+ return /^(manual_handoff|park_manual|stopped)$/i.test(cleanText(record?.outcome, 80));
1299
+ }
1300
+
1301
+ export function buildResolveIOAIManagerRecoveryPlan(input: ResolveIOAIManagerRecoveryPlanInput = {}): ResolveIOAIManagerRecoveryPlan {
1302
+ const action = cleanText(input.action, 80) || 'continue';
1303
+ const reason = cleanText(input.reason, 240);
1304
+ const failureClass = normalizeResolveIOAIManagerFailureClass(input.failureClass);
1305
+ const lane = cleanText(input.lane, 80) || 'supervisor';
1306
+ const stepType = cleanText(input.stepType, 80) || 'unknown';
1307
+ const blocker = cleanText(input.blocker, 700);
1308
+ const changedFiles = cleanList(input.changedFiles, 12, 240);
1309
+ const artifactPaths = cleanList(input.artifactPaths, 12, 240);
1310
+ const maxAttemptsBeforePark = Math.max(1, Number(input.maxSameFailureRepeats || 3) || 3);
1311
+ const commonNotes = [
1312
+ reason ? `policy_reason=${reason}` : '',
1313
+ blocker ? `blocker=${blocker}` : '',
1314
+ changedFiles.length ? `changed_files=${changedFiles.join(', ')}` : '',
1315
+ artifactPaths.length ? `artifacts=${artifactPaths.join(', ')}` : ''
1316
+ ].filter(Boolean);
1317
+ const base: Omit<ResolveIOAIManagerRecoveryPlan, 'recoveryClass' | 'nextActionLabel' | 'objective' | 'allowedAction' | 'productRepairAllowed' | 'expensiveModelAllowed' | 'finiteSteps' | 'requiredEvidence' | 'loopResetEvidence' | 'forbiddenActions'> = {
1318
+ lane,
1319
+ stepType,
1320
+ maxAttemptsBeforePark,
1321
+ notes: commonNotes
1322
+ };
1323
+ const makePlan = (
1324
+ recoveryClass: ResolveIOAIManagerRecoveryClass,
1325
+ nextActionLabel: string,
1326
+ objective: string,
1327
+ allowedAction: string,
1328
+ productRepairAllowed: boolean,
1329
+ expensiveModelAllowed: boolean,
1330
+ finiteSteps: string[],
1331
+ requiredEvidence: string[],
1332
+ loopResetEvidence: string[],
1333
+ forbiddenActions: string[]
1334
+ ): ResolveIOAIManagerRecoveryPlan => ({
1335
+ ...base,
1336
+ recoveryClass,
1337
+ nextActionLabel,
1338
+ objective,
1339
+ allowedAction,
1340
+ productRepairAllowed,
1341
+ expensiveModelAllowed,
1342
+ finiteSteps,
1343
+ requiredEvidence,
1344
+ loopResetEvidence,
1345
+ forbiddenActions
1346
+ });
1347
+ if (action === 'reset_loop_budget') {
1348
+ return makePlan(
1349
+ 'advance_after_proof',
1350
+ 'Advance After Proof',
1351
+ 'Checkpoint the passing evidence and move to the next required gate.',
1352
+ 'advance_to_next_gate',
1353
+ false,
1354
+ false,
1355
+ [
1356
+ 'Record the passing artifact, changed files, and gate result.',
1357
+ 'Reset the loop counter because a real gate passed.',
1358
+ 'Select the next unmet deterministic gate instead of repeating the previous repair.'
1359
+ ],
1360
+ ['passing gate record', 'artifact or log proving the passed check'],
1361
+ ['new passing gate result', 'new business proof artifact'],
1362
+ ['rerun the same repair after a pass', 'mark accepted without the required downstream gate']
1363
+ );
1364
+ }
1365
+ if (action === 'manual_handoff') {
1366
+ return makePlan(
1367
+ 'manual_handoff',
1368
+ 'Manual Review',
1369
+ 'Stop autonomous repair and expose the blocker, evidence, and last safe state.',
1370
+ 'manual_review_only',
1371
+ false,
1372
+ false,
1373
+ [
1374
+ 'Freeze further product-code edits.',
1375
+ 'Show the blocker fingerprint, evidence hash, and prior attempts.',
1376
+ 'Require a human edit to classification, scope, or retry policy before another model/code loop.'
1377
+ ],
1378
+ ['blocker fingerprint', 'evidence hash', 'attempt history'],
1379
+ ['manual policy change', 'new external evidence'],
1380
+ ['start another automatic model repair', 'hide the failed evidence']
1381
+ );
1382
+ }
1383
+ if (action === 'budget_stop') {
1384
+ return makePlan(
1385
+ 'manual_handoff',
1386
+ 'Budget Stop Review',
1387
+ 'Stop autonomous model/code loops until a cheaper scoped next action is selected.',
1388
+ 'budget_review_only',
1389
+ false,
1390
+ false,
1391
+ [
1392
+ 'Freeze further model repair loops.',
1393
+ 'Show the prompt/token/runtime budget that tripped the guard.',
1394
+ 'Select a cheaper deterministic gate, infra repair, diagnosis revision, or manual scope edit before resuming.'
1395
+ ],
1396
+ ['budget guard reason', 'latest prompt estimate', 'last blocker/evidence hash'],
1397
+ ['manual scope reduction', 'new deterministic evidence', 'approved budget policy change'],
1398
+ ['start another broad model prompt', 'reset budget without new evidence', 'hide cost context']
1399
+ );
1400
+ }
1401
+ if (failureClass === 'diagnosis' || stepType === 'diagnosis_gate') {
1402
+ return makePlan(
1403
+ 'diagnosis_only',
1404
+ 'Run Diagnosis Gate',
1405
+ 'Produce a falsifiable root-cause diagnosis before any repair.',
1406
+ 'read_only_diagnosis',
1407
+ false,
1408
+ true,
1409
+ [
1410
+ 'Reproduce or explicitly classify the customer issue.',
1411
+ 'Accept one falsifiable hypothesis and record rejected alternatives.',
1412
+ 'Identify the frontend/backend/shared failing path.',
1413
+ 'Select a small owner_files set.',
1414
+ 'Define exact before/action/after business proof.'
1415
+ ],
1416
+ ['issue_case', 'accepted_hypothesis', 'rejected_alternatives', 'failing_path', 'owner_files', 'proof_plan'],
1417
+ ['new reproduction artifact', 'new query/log/code evidence', 'validated diagnosis gate'],
1418
+ ['edit product code', 'run broad repo repair', 'accept route-load evidence as success']
1419
+ );
1420
+ }
1421
+ if (failureClass === 'owner_scope' || failureClass === 'out_of_scope' || /out.?of.?scope|owner_files/i.test(reason)) {
1422
+ return makePlan(
1423
+ 'diagnosis_revision',
1424
+ 'Revise Diagnosis Scope',
1425
+ 'Revise owner_files only when new evidence proves the current scope is wrong.',
1426
+ 'diagnosis_revision_only',
1427
+ false,
1428
+ true,
1429
+ [
1430
+ 'Compare changed files against the diagnosis owner_files.',
1431
+ 'Collect evidence proving why the new file is in the failing path.',
1432
+ 'Update accepted_hypothesis, failing_path, owner_files, and proof_plan together.',
1433
+ 'Resume repair only after the revised gate validates.'
1434
+ ],
1435
+ ['out-of-scope file list', 'new failing-path evidence', 'revalidated diagnosis gate'],
1436
+ ['revised owner_files with evidence', 'new business proof requirement'],
1437
+ ['keep broad edits without diagnosis', 'add convenience refactors', 'continue repair outside owner_files']
1438
+ );
1439
+ }
1440
+ if (action === 'retry_infra') {
1441
+ const isCompile = failureClass === 'compile';
1442
+ return makePlan(
1443
+ isCompile ? 'compile_repair' : 'infra_repair',
1444
+ isCompile ? 'Repair Compile Gate' : 'Repair Infra Gate',
1445
+ isCompile
1446
+ ? 'Fix the deterministic compile/build blocker before spending another product repair loop.'
1447
+ : 'Fix the deterministic harness/browser/server/Mongo blocker before product repair.',
1448
+ isCompile ? 'compile_repair_only' : 'infra_repair_only',
1449
+ false,
1450
+ false,
1451
+ isCompile
1452
+ ? [
1453
+ 'Read the exact compile/build log and identify the first actionable error.',
1454
+ 'Fix missing dependency, stale artifact, command, cache, or type wiring required by the compile gate.',
1455
+ 'Rerun the same finite compile command.',
1456
+ 'Return the compile log artifact and status.'
1457
+ ]
1458
+ : [
1459
+ 'Run preflight for Puppeteer, Chrome executable, ports, Mongo/settings, and startup command.',
1460
+ 'Repair only the failing harness/environment item.',
1461
+ 'Rerun the same infra check.',
1462
+ 'Return the infra log and pass/fail status.'
1463
+ ],
1464
+ isCompile
1465
+ ? ['compile command', 'compile log artifact', 'first failing error fixed or still failing']
1466
+ : ['preflight command', 'infra log artifact', 'specific repaired environment item'],
1467
+ ['same check now passes', 'new infra/compile blocker hash'],
1468
+ ['run product-code model repair', 'count this as product failure', 'accept route/business success without the compile/infra gate']
1469
+ );
1470
+ }
1471
+ if (action === 'park_repeated_failure' || action === 'park_ping_pong') {
1472
+ return makePlan(
1473
+ 'blocked_until_new_evidence',
1474
+ action === 'park_ping_pong' ? 'Park Ping-Pong Loop' : 'Park Repeated Failure',
1475
+ 'Stop the current loop until new evidence changes the diagnosis, route, or repair target.',
1476
+ 'collect_new_evidence_only',
1477
+ false,
1478
+ false,
1479
+ [
1480
+ 'Do not rerun the same prompt or same repair.',
1481
+ 'Show the repeated blocker and evidence hash.',
1482
+ 'Collect a new artifact: failing DOM state, stack trace, network response, Mongo delta, compile log, or revised diagnosis.',
1483
+ 'Reset the loop only after the new evidence hash changes.'
1484
+ ],
1485
+ ['same failure count', 'blocker fingerprint', 'evidence hash'],
1486
+ ['changed evidence hash', 'new artifact path', 'revised diagnosis or journey contract'],
1487
+ ['alternate between two failed patches', 'increase loop budget without evidence', 'hide the park reason']
1488
+ );
1489
+ }
1490
+ if (failureClass === 'journey') {
1491
+ return makePlan(
1492
+ 'journey_contract_repair',
1493
+ 'Repair Journey Contract',
1494
+ 'Fix the first/next/last workflow contract before app code work continues.',
1495
+ 'journey_contract_repair',
1496
+ false,
1497
+ true,
1498
+ [
1499
+ 'Open docs/APP_JOURNEY_CONTRACT.md.',
1500
+ 'Define first_screen, north_star_workflow, screen_sequence, data_story, completion_states, and qa_assertions.',
1501
+ 'Ensure each CTA maps to an action, route, method, calculation, or state transition.',
1502
+ 'Validate that sample data can drive the promised workflow.'
1503
+ ],
1504
+ ['validated journey_contract JSON', 'CTA-to-action mapping', 'workflow QA assertions'],
1505
+ ['journey validation passes', 'new workflow QA rows generated'],
1506
+ ['build empty routes', 'add link-only dashboard actions', 'defer workflow design to wow pass']
1507
+ );
1508
+ }
1509
+ if (failureClass === 'release') {
1510
+ return makePlan(
1511
+ 'release_repair',
1512
+ 'Repair Release Gate',
1513
+ 'Repair deploy/publish/sample-data release evidence without rewriting working app flow.',
1514
+ 'release_repair_only',
1515
+ false,
1516
+ false,
1517
+ [
1518
+ 'Read the deploy/publish/sample-data log.',
1519
+ 'Identify whether the blocker is domain, asset, seed data, route, permission, or CDN.',
1520
+ 'Repair the release artifact/config/seed issue.',
1521
+ 'Rerun only the failed release gate.'
1522
+ ],
1523
+ ['deploy or publish log', 'sample-data status', 'failed release gate rerun'],
1524
+ ['release gate passes', 'new release blocker hash'],
1525
+ ['change core workflow after business QA passed', 'mark accepted from scorecard only', 'rerun full builder loop']
1526
+ );
1527
+ }
1528
+ if (failureClass === 'business' || failureClass === 'qa_evidence' || failureClass === 'route') {
1529
+ return makePlan(
1530
+ 'business_proof_repair',
1531
+ 'Repair Business Proof',
1532
+ 'Fix the exact failing workflow assertion and prove before/action/after behavior.',
1533
+ 'business_repair',
1534
+ true,
1535
+ true,
1536
+ [
1537
+ 'Open the failing QA row or proof_plan.',
1538
+ 'Trace the UI action to method/publication/query/calculation.',
1539
+ 'Patch the smallest owner or workflow files.',
1540
+ 'Rerun only the failed business assertion.',
1541
+ 'Record DOM/data/Mongo/artifact proof.'
1542
+ ],
1543
+ ['failing assertion', 'action trace', 'business proof artifact'],
1544
+ ['business assertion passes', 'new failed assertion with new evidence'],
1545
+ ['treat route load as success', 'rerun unrelated QA rows first', 'accept scorecard-only evidence']
1546
+ );
1547
+ }
1548
+ if (input.productRepairFailure !== false || failureClass === 'product_code') {
1549
+ return makePlan(
1550
+ 'product_code_repair',
1551
+ 'Run Targeted Product Repair',
1552
+ 'Repair the current product-code blocker with the smallest scoped edit and immediate proof.',
1553
+ 'targeted_product_repair',
1554
+ true,
1555
+ true,
1556
+ [
1557
+ 'Inspect the current blocker, artifacts, changed files, and owner/workflow scope.',
1558
+ 'Form one small repair hypothesis.',
1559
+ 'Patch only files justified by the active diagnosis or journey contract.',
1560
+ 'Rerun the smallest failed gate.',
1561
+ 'Record new evidence before any additional loop.'
1562
+ ],
1563
+ ['owner/workflow scope', 'repair diff', 'failed gate rerun artifact'],
1564
+ ['new evidence hash', 'same gate passes'],
1565
+ ['broad repo search-and-edit', 'rerun the same prompt without inspecting artifacts', 'change unrelated UI polish']
1566
+ );
1567
+ }
1568
+ return makePlan(
1569
+ 'continue',
1570
+ 'Continue Current Gate',
1571
+ 'Continue the current lane because no blocking loop or infra condition was detected.',
1572
+ 'continue',
1573
+ false,
1574
+ false,
1575
+ [
1576
+ 'Use the active lane memory.',
1577
+ 'Run the next finite gate.',
1578
+ 'Record artifacts and evidence hash.'
1579
+ ],
1580
+ ['active lane memory', 'finite gate artifact'],
1581
+ ['new gate result', 'new artifact path'],
1582
+ ['spawn duplicate runners', 'advance without evidence']
1583
+ );
1584
+ }
1585
+
1586
+ function collectOpenTail(records: ResolveIOAIManagerFailureRecord[]): ResolveIOAIManagerFailureRecord[] {
1587
+ const tail: ResolveIOAIManagerFailureRecord[] = [];
1588
+ for (let index = records.length - 1; index >= 0; index -= 1) {
1589
+ const record = records[index];
1590
+ if (isPassingOutcome(record)) {
1591
+ break;
1592
+ }
1593
+ tail.unshift(record);
1594
+ }
1595
+ return tail;
1596
+ }
1597
+
1598
+ function countSameFailure(records: ResolveIOAIManagerFailureRecord[], current: ResolveIOAIManagerFailureRecord): number {
1599
+ const currentKey = failureEvidenceKey(current);
1600
+ let count = 0;
1601
+ for (let index = records.length - 1; index >= 0; index -= 1) {
1602
+ const record = records[index];
1603
+ if (isPassingOutcome(record)) {
1604
+ break;
1605
+ }
1606
+ if (failureEvidenceKey(record) !== currentKey) {
1607
+ break;
1608
+ }
1609
+ count += 1;
1610
+ }
1611
+ return count;
1612
+ }
1613
+
1614
+ function countPingPong(records: ResolveIOAIManagerFailureRecord[], current: ResolveIOAIManagerFailureRecord): number {
1615
+ const tail = collectOpenTail(records).filter((record) => {
1616
+ return cleanText(record.lane, 80) === cleanText(current.lane, 80)
1617
+ && cleanText(record.stepType, 80) === cleanText(current.stepType, 80);
1618
+ });
1619
+ if (tail.length < 4) {
1620
+ return 0;
1621
+ }
1622
+ const keys = tail.map(failureKey).filter(Boolean);
1623
+ const last = keys.slice(-6);
1624
+ if (last.length < 4) {
1625
+ return 0;
1626
+ }
1627
+ const distinct = Array.from(new Set(last));
1628
+ if (distinct.length !== 2) {
1629
+ return 0;
1630
+ }
1631
+ for (let index = 2; index < last.length; index += 1) {
1632
+ if (last[index] !== last[index - 2]) {
1633
+ return 0;
1634
+ }
1635
+ }
1636
+ return last.length - 1;
1637
+ }
1638
+
1639
+ export function decideResolveIOAIManagerPolicy(input: ResolveIOAIManagerPolicyInput): ResolveIOAIManagerPolicyDecision {
1640
+ const history = Array.isArray(input.history) ? input.history : [];
1641
+ const current = input.current || history[history.length - 1] || {};
1642
+ const failureClass = normalizeResolveIOAIManagerFailureClass(current.failureClass);
1643
+ const blockerFingerprint = resolveResolveIOAIManagerBlockerFingerprint(current);
1644
+ const evidenceHash = hashResolveIOAIManagerEvidence(current);
1645
+ const previous = history.length > 1 ? history[history.length - 2] : undefined;
1646
+ const previousSameFailure = previous && failureKey(previous) === failureKey(current);
1647
+ const previousEvidenceHash = previousSameFailure ? hashResolveIOAIManagerEvidence(previous) : '';
1648
+ const newEvidence = !!previousSameFailure && !!previousEvidenceHash && previousEvidenceHash !== evidenceHash;
1649
+ const sameFailureCount = countSameFailure(history, current);
1650
+ const pingPongCount = countPingPong(history, current);
1651
+ const maxSameFailureRepeats = Math.max(1, Number(input.maxSameFailureRepeats || 3) || 3);
1652
+ const maxPingPongTransitions = Math.max(3, Number(input.maxPingPongTransitions || 3) || 3);
1653
+ const infraClasses = new Set((input.infraFailureClasses || ['infra', 'compile']).map(normalizeResolveIOAIManagerFailureClass));
1654
+ const ignoredClasses = new Set((input.ignoredFailureClasses || []).map(normalizeResolveIOAIManagerFailureClass));
1655
+ const base = {
1656
+ failureClass,
1657
+ blockerFingerprint,
1658
+ evidenceHash,
1659
+ sameFailureCount,
1660
+ pingPongCount,
1661
+ newEvidence,
1662
+ loopBudgetShouldReset: false,
1663
+ productRepairFailure: !infraClasses.has(failureClass) && !ignoredClasses.has(failureClass)
1664
+ };
1665
+ const withPlan = (
1666
+ action: ResolveIOAIManagerAction,
1667
+ reason: string,
1668
+ overrides: Partial<Omit<ResolveIOAIManagerPolicyDecision, 'action' | 'reason' | 'recoveryPlan' | 'recoveryCheckpoint'>> = {}
1669
+ ): ResolveIOAIManagerPolicyDecision => {
1670
+ const merged = {
1671
+ ...base,
1672
+ ...overrides
1673
+ };
1674
+ const recoveryPlan = buildResolveIOAIManagerRecoveryPlan({
1675
+ action,
1676
+ reason,
1677
+ failureClass: merged.failureClass,
1678
+ lane: current.lane,
1679
+ stepType: current.stepType,
1680
+ blocker: current.blocker || current.summary,
1681
+ sameFailureCount: merged.sameFailureCount,
1682
+ pingPongCount: merged.pingPongCount,
1683
+ newEvidence: merged.newEvidence,
1684
+ productRepairFailure: merged.productRepairFailure,
1685
+ changedFiles: current.changedFiles,
1686
+ artifactPaths: current.artifactPaths,
1687
+ maxSameFailureRepeats
1688
+ });
1689
+ const recoveryCheckpoint = buildResolveIOAIManagerRecoveryCheckpoint({
1690
+ plan: recoveryPlan,
1691
+ current
1692
+ });
1693
+ const recoveryEvidenceProbe = buildResolveIOAIManagerRecoveryEvidenceProbe({
1694
+ checkpoint: recoveryCheckpoint,
1695
+ current
1696
+ });
1697
+ return {
1698
+ ...merged,
1699
+ action,
1700
+ reason,
1701
+ recoveryPlan,
1702
+ recoveryCheckpoint,
1703
+ recoveryEvidenceProbe,
1704
+ recoveryAction: buildResolveIOAIManagerRecoveryActionPacket({
1705
+ plan: recoveryPlan,
1706
+ checkpoint: recoveryCheckpoint,
1707
+ probe: recoveryEvidenceProbe,
1708
+ current
1709
+ })
1710
+ };
1711
+ };
1712
+ if (isPassingOutcome(current)) {
1713
+ return withPlan('reset_loop_budget', 'manager_policy_progress_passed', {
1714
+ loopBudgetShouldReset: true,
1715
+ productRepairFailure: false
1716
+ });
1717
+ }
1718
+ if (isManualOutcome(current)) {
1719
+ return withPlan('manual_handoff', 'manager_policy_manual_or_stopped');
1720
+ }
1721
+ if (pingPongCount >= maxPingPongTransitions) {
1722
+ return withPlan('park_ping_pong', 'manager_policy_ping_pong_failure_loop');
1723
+ }
1724
+ if (sameFailureCount >= maxSameFailureRepeats && !newEvidence) {
1725
+ return withPlan('park_repeated_failure', 'manager_policy_same_failure_without_new_evidence');
1726
+ }
1727
+ if (infraClasses.has(failureClass)) {
1728
+ return withPlan('retry_infra', 'manager_policy_infra_failure_routes_to_infra_repair', {
1729
+ productRepairFailure: false
1730
+ });
1731
+ }
1732
+ if (newEvidence || !previousSameFailure) {
1733
+ return withPlan('continue', newEvidence
1734
+ ? 'manager_policy_new_evidence_resets_loop_budget'
1735
+ : 'manager_policy_new_failure_or_lane', {
1736
+ loopBudgetShouldReset: true
1737
+ });
1738
+ }
1739
+ return withPlan('continue', 'manager_policy_retry_below_repeat_limit');
1740
+ }