@resolveio/server-lib 22.3.221 → 22.3.222

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/ai/assistant-core-heuristics.d.ts +11 -0
  2. package/ai/assistant-core-heuristics.js +356 -0
  3. package/ai/assistant-core-heuristics.js.map +1 -0
  4. package/ai/resolveio-platform-intelligence-memory-corpus.d.ts +3 -0
  5. package/ai/resolveio-platform-intelligence-memory-corpus.js +214 -0
  6. package/ai/resolveio-platform-intelligence-memory-corpus.js.map +1 -0
  7. package/ai/resolveio-platform-intelligence-memory.d.ts +20 -0
  8. package/ai/resolveio-platform-intelligence-memory.js +341 -0
  9. package/ai/resolveio-platform-intelligence-memory.js.map +1 -0
  10. package/{src/ai/resolveio-platform-intelligence-types.ts → ai/resolveio-platform-intelligence-types.d.ts} +15 -20
  11. package/ai/resolveio-platform-intelligence-types.js +4 -0
  12. package/ai/resolveio-platform-intelligence-types.js.map +1 -0
  13. package/ai/resolveio-platform-intelligence.d.ts +6 -0
  14. package/ai/resolveio-platform-intelligence.js +463 -0
  15. package/ai/resolveio-platform-intelligence.js.map +1 -0
  16. package/client-server-app.d.ts +1 -0
  17. package/client-server-app.js +68 -0
  18. package/client-server-app.js.map +1 -0
  19. package/collections/ai-run.collection.d.ts +3 -0
  20. package/collections/ai-run.collection.js +170 -0
  21. package/collections/ai-run.collection.js.map +1 -0
  22. package/collections/ai-terminal-conversation.collection.d.ts +2 -0
  23. package/collections/ai-terminal-conversation.collection.js +140 -0
  24. package/collections/ai-terminal-conversation.collection.js.map +1 -0
  25. package/collections/ai-terminal-issue-report.collection.d.ts +2 -0
  26. package/collections/ai-terminal-issue-report.collection.js +148 -0
  27. package/collections/ai-terminal-issue-report.collection.js.map +1 -0
  28. package/collections/ai-terminal-message.collection.d.ts +2 -0
  29. package/collections/ai-terminal-message.collection.js +121 -0
  30. package/collections/ai-terminal-message.collection.js.map +1 -0
  31. package/collections/app-setting.collection.d.ts +3 -0
  32. package/collections/app-setting.collection.js +103 -0
  33. package/collections/app-setting.collection.js.map +1 -0
  34. package/collections/app-status.collection.d.ts +3 -0
  35. package/collections/app-status.collection.js +57 -0
  36. package/collections/app-status.collection.js.map +1 -0
  37. package/collections/communication-metric.collection.d.ts +2 -0
  38. package/collections/communication-metric.collection.js +133 -0
  39. package/collections/communication-metric.collection.js.map +1 -0
  40. package/collections/counter.collection.d.ts +3 -0
  41. package/collections/counter.collection.js +56 -0
  42. package/collections/counter.collection.js.map +1 -0
  43. package/collections/cron-job-history.collection.d.ts +3 -0
  44. package/collections/cron-job-history.collection.js +137 -0
  45. package/collections/cron-job-history.collection.js.map +1 -0
  46. package/collections/cron-job.collection.d.ts +3 -0
  47. package/collections/cron-job.collection.js +92 -0
  48. package/collections/cron-job.collection.js.map +1 -0
  49. package/collections/customer-notification.collection.d.ts +3 -0
  50. package/collections/customer-notification.collection.js +130 -0
  51. package/collections/customer-notification.collection.js.map +1 -0
  52. package/collections/customer-portal-password.collection.d.ts +3 -0
  53. package/collections/customer-portal-password.collection.js +75 -0
  54. package/collections/customer-portal-password.collection.js.map +1 -0
  55. package/collections/email-history.collection.d.ts +3 -0
  56. package/collections/email-history.collection.js +134 -0
  57. package/collections/email-history.collection.js.map +1 -0
  58. package/collections/email-verified.collection.d.ts +3 -0
  59. package/collections/email-verified.collection.js +62 -0
  60. package/collections/email-verified.collection.js.map +1 -0
  61. package/collections/file.collection.d.ts +3 -0
  62. package/collections/file.collection.js +74 -0
  63. package/collections/file.collection.js.map +1 -0
  64. package/collections/flag-update.collection.d.ts +3 -0
  65. package/collections/flag-update.collection.js +57 -0
  66. package/collections/flag-update.collection.js.map +1 -0
  67. package/collections/flag.collection.d.ts +3 -0
  68. package/collections/flag.collection.js +57 -0
  69. package/collections/flag.collection.js.map +1 -0
  70. package/collections/log-method-latency.collection.d.ts +3 -0
  71. package/collections/log-method-latency.collection.js +77 -0
  72. package/collections/log-method-latency.collection.js.map +1 -0
  73. package/collections/log-subscription.collection.d.ts +3 -0
  74. package/collections/log-subscription.collection.js +80 -0
  75. package/collections/log-subscription.collection.js.map +1 -0
  76. package/collections/log.collection.d.ts +3 -0
  77. package/collections/log.collection.js +93 -0
  78. package/collections/log.collection.js.map +1 -0
  79. package/collections/logged-in-users.collection.d.ts +3 -0
  80. package/collections/logged-in-users.collection.js +67 -0
  81. package/collections/logged-in-users.collection.js.map +1 -0
  82. package/collections/monitor-cpu.collection.d.ts +3 -0
  83. package/collections/monitor-cpu.collection.js +65 -0
  84. package/collections/monitor-cpu.collection.js.map +1 -0
  85. package/collections/monitor-function.collection.d.ts +3 -0
  86. package/collections/monitor-function.collection.js +74 -0
  87. package/collections/monitor-function.collection.js.map +1 -0
  88. package/collections/monitor-memory.collection.d.ts +3 -0
  89. package/collections/monitor-memory.collection.js +77 -0
  90. package/collections/monitor-memory.collection.js.map +1 -0
  91. package/collections/monitor-mongo.collection.d.ts +3 -0
  92. package/collections/monitor-mongo.collection.js +71 -0
  93. package/collections/monitor-mongo.collection.js.map +1 -0
  94. package/collections/notification.collection.d.ts +3 -0
  95. package/collections/notification.collection.js +57 -0
  96. package/collections/notification.collection.js.map +1 -0
  97. package/collections/openai-usage-ledger.collection.d.ts +2 -0
  98. package/collections/openai-usage-ledger.collection.js +188 -0
  99. package/collections/openai-usage-ledger.collection.js.map +1 -0
  100. package/collections/report-builder-dashboard-builder.collection.d.ts +3 -0
  101. package/collections/report-builder-dashboard-builder.collection.js +109 -0
  102. package/collections/report-builder-dashboard-builder.collection.js.map +1 -0
  103. package/collections/report-builder-library.collection.d.ts +3 -0
  104. package/collections/report-builder-library.collection.js +87 -0
  105. package/collections/report-builder-library.collection.js.map +1 -0
  106. package/collections/report-builder-report.collection.d.ts +4 -0
  107. package/collections/report-builder-report.collection.js +184 -0
  108. package/collections/report-builder-report.collection.js.map +1 -0
  109. package/collections/user-group.collection.d.ts +4 -0
  110. package/collections/user-group.collection.js +89 -0
  111. package/collections/user-group.collection.js.map +1 -0
  112. package/collections/user-guide.collection.d.ts +3 -0
  113. package/collections/user-guide.collection.js +57 -0
  114. package/collections/user-guide.collection.js.map +1 -0
  115. package/collections/user.collection.d.ts +4 -0
  116. package/collections/user.collection.js +180 -0
  117. package/collections/user.collection.js.map +1 -0
  118. package/cron/cron.d.ts +14 -0
  119. package/cron/cron.js +216 -0
  120. package/cron/cron.js.map +1 -0
  121. package/fixtures/cron-jobs.d.ts +1 -0
  122. package/fixtures/cron-jobs.js +150 -0
  123. package/fixtures/cron-jobs.js.map +1 -0
  124. package/fixtures/init.d.ts +1 -0
  125. package/fixtures/init.js +91 -0
  126. package/fixtures/init.js.map +1 -0
  127. package/http/auth.d.ts +2 -0
  128. package/http/auth.js +951 -0
  129. package/http/auth.js.map +1 -0
  130. package/http/health.d.ts +1 -0
  131. package/http/health.js +11 -0
  132. package/http/health.js.map +1 -0
  133. package/http/home.d.ts +1 -0
  134. package/http/home.js +134 -0
  135. package/http/home.js.map +1 -0
  136. package/http/slow-query-publication.d.ts +2 -0
  137. package/http/slow-query-publication.js +99 -0
  138. package/http/slow-query-publication.js.map +1 -0
  139. package/index.d.ts +1 -0
  140. package/index.js +19 -0
  141. package/index.js.map +1 -0
  142. package/managers/ai-assistant-codex-manager.manager.d.ts +67 -0
  143. package/managers/ai-assistant-codex-manager.manager.js +1113 -0
  144. package/managers/ai-assistant-codex-manager.manager.js.map +1 -0
  145. package/managers/ai-run-evidence.manager.d.ts +36 -0
  146. package/managers/ai-run-evidence.manager.js +377 -0
  147. package/managers/ai-run-evidence.manager.js.map +1 -0
  148. package/managers/communication-metric.manager.d.ts +16 -0
  149. package/managers/communication-metric.manager.js +134 -0
  150. package/managers/communication-metric.manager.js.map +1 -0
  151. package/managers/cron.manager.d.ts +20 -0
  152. package/managers/cron.manager.js +534 -0
  153. package/managers/cron.manager.js.map +1 -0
  154. package/managers/customer-notification-content.manager.d.ts +55 -0
  155. package/managers/customer-notification-content.manager.js +158 -0
  156. package/managers/customer-notification-content.manager.js.map +1 -0
  157. package/managers/diagnostic-manager-bootstrap.d.ts +9 -0
  158. package/managers/diagnostic-manager-bootstrap.js +260 -0
  159. package/managers/diagnostic-manager-bootstrap.js.map +1 -0
  160. package/managers/error-auto-fix.manager.d.ts +149 -0
  161. package/managers/error-auto-fix.manager.js +3064 -0
  162. package/managers/error-auto-fix.manager.js.map +1 -0
  163. package/managers/local-log.manager.d.ts +18 -0
  164. package/managers/local-log.manager.js +88 -0
  165. package/managers/local-log.manager.js.map +1 -0
  166. package/managers/method.manager.d.ts +84 -0
  167. package/managers/method.manager.js +1964 -0
  168. package/managers/method.manager.js.map +1 -0
  169. package/managers/mongo.manager.d.ts +224 -0
  170. package/managers/mongo.manager.js +5000 -0
  171. package/managers/mongo.manager.js.map +1 -0
  172. package/managers/monitor.manager.d.ts +70 -0
  173. package/managers/monitor.manager.js +550 -0
  174. package/managers/monitor.manager.js.map +1 -0
  175. package/managers/openai-usage-ledger.manager.d.ts +30 -0
  176. package/managers/openai-usage-ledger.manager.js +142 -0
  177. package/managers/openai-usage-ledger.manager.js.map +1 -0
  178. package/managers/slow-query-verifier.manager.d.ts +144 -0
  179. package/managers/slow-query-verifier.manager.js +3857 -0
  180. package/managers/slow-query-verifier.manager.js.map +1 -0
  181. package/managers/slow-query.manager.d.ts +28 -0
  182. package/managers/slow-query.manager.js +468 -0
  183. package/managers/slow-query.manager.js.map +1 -0
  184. package/managers/subscription.manager.d.ts +169 -0
  185. package/managers/subscription.manager.js +3434 -0
  186. package/managers/subscription.manager.js.map +1 -0
  187. package/managers/websocket.manager.d.ts +73 -0
  188. package/managers/websocket.manager.js +673 -0
  189. package/managers/websocket.manager.js.map +1 -0
  190. package/managers/worker-dispatcher.manager.d.ts +120 -0
  191. package/managers/worker-dispatcher.manager.js +1266 -0
  192. package/managers/worker-dispatcher.manager.js.map +1 -0
  193. package/managers/worker-server.manager.d.ts +35 -0
  194. package/managers/worker-server.manager.js +582 -0
  195. package/managers/worker-server.manager.js.map +1 -0
  196. package/methods/accounts.d.ts +2 -0
  197. package/methods/accounts.js +624 -0
  198. package/methods/accounts.js.map +1 -0
  199. package/methods/ai-terminal.d.ts +458 -0
  200. package/methods/ai-terminal.js +27991 -0
  201. package/methods/ai-terminal.js.map +1 -0
  202. package/methods/app-settings.d.ts +2 -0
  203. package/methods/app-settings.js +169 -0
  204. package/methods/app-settings.js.map +1 -0
  205. package/methods/aws.d.ts +2 -0
  206. package/methods/aws.js +877 -0
  207. package/methods/aws.js.map +1 -0
  208. package/methods/collections.d.ts +2 -0
  209. package/methods/collections.js +719 -0
  210. package/methods/collections.js.map +1 -0
  211. package/methods/counters.d.ts +2 -0
  212. package/methods/counters.js +113 -0
  213. package/methods/counters.js.map +1 -0
  214. package/methods/cron-jobs.d.ts +2 -0
  215. package/methods/cron-jobs.js +2475 -0
  216. package/methods/cron-jobs.js.map +1 -0
  217. package/methods/customer-notifications.d.ts +2 -0
  218. package/methods/customer-notifications.js +528 -0
  219. package/methods/customer-notifications.js.map +1 -0
  220. package/methods/diagnostics.d.ts +2 -0
  221. package/methods/diagnostics.js +703 -0
  222. package/methods/diagnostics.js.map +1 -0
  223. package/methods/flag-updates.d.ts +2 -0
  224. package/methods/flag-updates.js +8 -0
  225. package/methods/flag-updates.js.map +1 -0
  226. package/methods/flags.d.ts +2 -0
  227. package/methods/flags.js +8 -0
  228. package/methods/flags.js.map +1 -0
  229. package/methods/logs.d.ts +2 -0
  230. package/methods/logs.js +751 -0
  231. package/methods/logs.js.map +1 -0
  232. package/methods/mongo-explorer.d.ts +2 -0
  233. package/methods/mongo-explorer.js +1808 -0
  234. package/methods/mongo-explorer.js.map +1 -0
  235. package/methods/monitor.d.ts +2 -0
  236. package/methods/monitor.js +543 -0
  237. package/methods/monitor.js.map +1 -0
  238. package/methods/pdf.d.ts +2 -0
  239. package/methods/pdf.js +1216 -0
  240. package/methods/pdf.js.map +1 -0
  241. package/methods/publications.d.ts +1 -0
  242. package/methods/publications.js +183 -0
  243. package/methods/publications.js.map +1 -0
  244. package/methods/report-builder.d.ts +2 -0
  245. package/methods/report-builder.js +3094 -0
  246. package/methods/report-builder.js.map +1 -0
  247. package/methods/support.d.ts +2 -0
  248. package/methods/support.js +430 -0
  249. package/methods/support.js.map +1 -0
  250. package/models/ai-run.model.d.ts +19 -0
  251. package/models/ai-run.model.js +4 -0
  252. package/models/ai-run.model.js.map +1 -0
  253. package/models/ai-terminal-conversation.model.d.ts +17 -0
  254. package/models/ai-terminal-conversation.model.js +4 -0
  255. package/models/ai-terminal-conversation.model.js.map +1 -0
  256. package/models/ai-terminal-issue-report.model.d.ts +19 -0
  257. package/models/ai-terminal-issue-report.model.js +4 -0
  258. package/models/ai-terminal-issue-report.model.js.map +1 -0
  259. package/models/ai-terminal-message.model.d.ts +22 -0
  260. package/models/ai-terminal-message.model.js +4 -0
  261. package/models/ai-terminal-message.model.js.map +1 -0
  262. package/models/app-setting.model.d.ts +16 -0
  263. package/models/app-setting.model.js +4 -0
  264. package/models/app-setting.model.js.map +1 -0
  265. package/{src/models/app-status.model.ts → models/app-status.model.d.ts} +2 -3
  266. package/models/app-status.model.js +4 -0
  267. package/models/app-status.model.js.map +1 -0
  268. package/{src/models/billing-logged-in-users.model.ts → models/billing-logged-in-users.model.d.ts} +4 -5
  269. package/models/billing-logged-in-users.model.js +4 -0
  270. package/models/billing-logged-in-users.model.js.map +1 -0
  271. package/models/collection-document.model.d.ts +21 -0
  272. package/models/collection-document.model.js +4 -0
  273. package/models/collection-document.model.js.map +1 -0
  274. package/models/communication-metric.model.d.ts +20 -0
  275. package/models/communication-metric.model.js +4 -0
  276. package/models/communication-metric.model.js.map +1 -0
  277. package/{src/models/counter.model.ts → models/counter.model.d.ts} +3 -4
  278. package/models/counter.model.js +4 -0
  279. package/models/counter.model.js.map +1 -0
  280. package/models/cron-job-history.model.d.ts +15 -0
  281. package/models/cron-job-history.model.js +4 -0
  282. package/models/cron-job-history.model.js.map +1 -0
  283. package/models/cron-job.model.d.ts +14 -0
  284. package/models/cron-job.model.js +4 -0
  285. package/models/cron-job.model.js.map +1 -0
  286. package/models/customer-notification.model.d.ts +26 -0
  287. package/models/customer-notification.model.js +4 -0
  288. package/models/customer-notification.model.js.map +1 -0
  289. package/models/customer-portal-password.model.d.ts +11 -0
  290. package/models/customer-portal-password.model.js +4 -0
  291. package/models/customer-portal-password.model.js.map +1 -0
  292. package/models/dialog.model.d.ts +23 -0
  293. package/models/dialog.model.js +4 -0
  294. package/models/dialog.model.js.map +1 -0
  295. package/models/email-history.model.d.ts +32 -0
  296. package/{src/models/email-history.model.ts → models/email-history.model.js} +4 -36
  297. package/models/email-history.model.js.map +1 -0
  298. package/{src/models/email-verified.model.ts → models/email-verified.model.d.ts} +5 -6
  299. package/models/email-verified.model.js +4 -0
  300. package/models/email-verified.model.js.map +1 -0
  301. package/{src/models/file.model.ts → models/file.model.d.ts} +7 -8
  302. package/models/file.model.js +4 -0
  303. package/models/file.model.js.map +1 -0
  304. package/{src/models/flag-update.model.ts → models/flag-update.model.d.ts} +3 -4
  305. package/models/flag-update.model.js +4 -0
  306. package/models/flag-update.model.js.map +1 -0
  307. package/{src/models/flag.model.ts → models/flag.model.d.ts} +3 -4
  308. package/models/flag.model.js +4 -0
  309. package/models/flag.model.js.map +1 -0
  310. package/models/log-method-latency.model.d.ts +10 -0
  311. package/models/log-method-latency.model.js +4 -0
  312. package/models/log-method-latency.model.js.map +1 -0
  313. package/{src/models/log-subscription.model.ts → models/log-subscription.model.d.ts} +9 -11
  314. package/models/log-subscription.model.js +4 -0
  315. package/models/log-subscription.model.js.map +1 -0
  316. package/models/log.model.d.ts +17 -0
  317. package/models/log.model.js +4 -0
  318. package/models/log.model.js.map +1 -0
  319. package/{src/models/logged-in-users.model.ts → models/logged-in-users.model.d.ts} +5 -6
  320. package/models/logged-in-users.model.js +4 -0
  321. package/models/logged-in-users.model.js.map +1 -0
  322. package/{src/models/method-response.model.ts → models/method-response.model.d.ts} +6 -7
  323. package/models/method-response.model.js +4 -0
  324. package/models/method-response.model.js.map +1 -0
  325. package/models/method.model.d.ts +26 -0
  326. package/models/method.model.js +4 -0
  327. package/models/method.model.js.map +1 -0
  328. package/{src/models/monitor-cpu.model.ts → models/monitor-cpu.model.d.ts} +7 -9
  329. package/models/monitor-cpu.model.js +4 -0
  330. package/models/monitor-cpu.model.js.map +1 -0
  331. package/models/monitor-function.model.d.ts +14 -0
  332. package/models/monitor-function.model.js +4 -0
  333. package/models/monitor-function.model.js.map +1 -0
  334. package/models/monitor-memory.model.d.ts +15 -0
  335. package/models/monitor-memory.model.js +4 -0
  336. package/models/monitor-memory.model.js.map +1 -0
  337. package/models/monitor-mongo.model.d.ts +13 -0
  338. package/models/monitor-mongo.model.js +4 -0
  339. package/models/monitor-mongo.model.js.map +1 -0
  340. package/{src/models/notification.model.ts → models/notification.model.d.ts} +4 -6
  341. package/models/notification.model.js +4 -0
  342. package/models/notification.model.js.map +1 -0
  343. package/models/openai-usage-ledger.model.d.ts +30 -0
  344. package/models/openai-usage-ledger.model.js +4 -0
  345. package/models/openai-usage-ledger.model.js.map +1 -0
  346. package/models/pagination.model.d.ts +11 -0
  347. package/models/pagination.model.js +28 -0
  348. package/models/pagination.model.js.map +1 -0
  349. package/models/permission.model.d.ts +12 -0
  350. package/models/permission.model.js +4 -0
  351. package/models/permission.model.js.map +1 -0
  352. package/models/report-builder-dashboard-builder.model.d.ts +25 -0
  353. package/models/report-builder-dashboard-builder.model.js +4 -0
  354. package/models/report-builder-dashboard-builder.model.js.map +1 -0
  355. package/models/report-builder-library.model.d.ts +17 -0
  356. package/models/report-builder-library.model.js +4 -0
  357. package/models/report-builder-library.model.js.map +1 -0
  358. package/models/report-builder-report.model.d.ts +121 -0
  359. package/models/report-builder-report.model.js +4 -0
  360. package/models/report-builder-report.model.js.map +1 -0
  361. package/models/report-builder.model.d.ts +61 -0
  362. package/models/report-builder.model.js +4 -0
  363. package/models/report-builder.model.js.map +1 -0
  364. package/models/select-data-label.model.d.ts +9 -0
  365. package/models/select-data-label.model.js +4 -0
  366. package/models/select-data-label.model.js.map +1 -0
  367. package/models/server-message.model.d.ts +32 -0
  368. package/models/server-message.model.js +4 -0
  369. package/models/server-message.model.js.map +1 -0
  370. package/models/slow-query-report.model.d.ts +23 -0
  371. package/models/slow-query-report.model.js +4 -0
  372. package/models/slow-query-report.model.js.map +1 -0
  373. package/models/subscription.model.d.ts +31 -0
  374. package/models/subscription.model.js +4 -0
  375. package/models/subscription.model.js.map +1 -0
  376. package/models/support-ticket.model.d.ts +87 -0
  377. package/models/support-ticket.model.js +4 -0
  378. package/models/support-ticket.model.js.map +1 -0
  379. package/models/user-group.model.d.ts +20 -0
  380. package/models/user-group.model.js +4 -0
  381. package/models/user-group.model.js.map +1 -0
  382. package/{src/models/user-guide.model.ts → models/user-guide.model.d.ts} +4 -5
  383. package/models/user-guide.model.js +4 -0
  384. package/models/user-guide.model.js.map +1 -0
  385. package/models/user.model.d.ts +84 -0
  386. package/models/user.model.js +4 -0
  387. package/models/user.model.js.map +1 -0
  388. package/package.json +1 -1
  389. package/private/images/ResolveIO.png +0 -0
  390. package/public_api.js +127 -0
  391. package/public_api.js.map +1 -0
  392. package/publications/ai-terminal.d.ts +1 -0
  393. package/publications/ai-terminal.js +122 -0
  394. package/publications/ai-terminal.js.map +1 -0
  395. package/publications/app-settings.d.ts +2 -0
  396. package/publications/app-settings.js +28 -0
  397. package/publications/app-settings.js.map +1 -0
  398. package/publications/app-status.d.ts +2 -0
  399. package/publications/app-status.js +16 -0
  400. package/publications/app-status.js.map +1 -0
  401. package/publications/cron-jobs.d.ts +2 -0
  402. package/publications/cron-jobs.js +88 -0
  403. package/publications/cron-jobs.js.map +1 -0
  404. package/publications/customer-notifications.d.ts +2 -0
  405. package/publications/customer-notifications.js +161 -0
  406. package/publications/customer-notifications.js.map +1 -0
  407. package/publications/files.d.ts +2 -0
  408. package/publications/files.js +36 -0
  409. package/publications/files.js.map +1 -0
  410. package/publications/flags-update.d.ts +2 -0
  411. package/publications/flags-update.js +22 -0
  412. package/publications/flags-update.js.map +1 -0
  413. package/publications/flags.d.ts +2 -0
  414. package/publications/flags.js +22 -0
  415. package/publications/flags.js.map +1 -0
  416. package/publications/logs.d.ts +2 -0
  417. package/publications/logs.js +164 -0
  418. package/publications/logs.js.map +1 -0
  419. package/publications/notifications.d.ts +2 -0
  420. package/publications/notifications.js +16 -0
  421. package/publications/notifications.js.map +1 -0
  422. package/publications/report-builder-dashboard-builders.d.ts +2 -0
  423. package/publications/report-builder-dashboard-builders.js +42 -0
  424. package/publications/report-builder-dashboard-builders.js.map +1 -0
  425. package/publications/report-builder-libraries.d.ts +2 -0
  426. package/publications/report-builder-libraries.js +90 -0
  427. package/publications/report-builder-libraries.js.map +1 -0
  428. package/publications/report-builder-reports.d.ts +2 -0
  429. package/publications/report-builder-reports.js +50 -0
  430. package/publications/report-builder-reports.js.map +1 -0
  431. package/publications/super-admin.d.ts +2 -0
  432. package/publications/super-admin.js +16 -0
  433. package/publications/super-admin.js.map +1 -0
  434. package/publications/user-groups.d.ts +1 -0
  435. package/publications/user-groups.js +16 -0
  436. package/publications/user-groups.js.map +1 -0
  437. package/publications/user-guides.d.ts +1 -0
  438. package/publications/user-guides.js +16 -0
  439. package/publications/user-guides.js.map +1 -0
  440. package/resolveio-server-app.d.ts +70 -0
  441. package/resolveio-server-app.js +801 -0
  442. package/resolveio-server-app.js.map +1 -0
  443. package/server-app.d.ts +228 -0
  444. package/server-app.js +3566 -0
  445. package/server-app.js.map +1 -0
  446. package/services/codex-client.d.ts +128 -0
  447. package/services/codex-client.js +1629 -0
  448. package/services/codex-client.js.map +1 -0
  449. package/services/openai-client.d.ts +46 -0
  450. package/services/openai-client.js +318 -0
  451. package/services/openai-client.js.map +1 -0
  452. package/types/error-report.d.ts +25 -0
  453. package/types/error-report.js +4 -0
  454. package/types/error-report.js.map +1 -0
  455. package/types/slow-query-report.d.ts +27 -0
  456. package/types/slow-query-report.js +6 -0
  457. package/types/slow-query-report.js.map +1 -0
  458. package/util/ai-qa-policy.d.ts +124 -0
  459. package/util/ai-qa-policy.js +736 -0
  460. package/util/ai-qa-policy.js.map +1 -0
  461. package/util/ai-run-evidence-adapters.d.ts +109 -0
  462. package/util/ai-run-evidence-adapters.js +7234 -0
  463. package/util/ai-run-evidence-adapters.js.map +1 -0
  464. package/util/ai-run-evidence-dashboard.d.ts +88 -0
  465. package/util/ai-run-evidence-dashboard.js +343 -0
  466. package/util/ai-run-evidence-dashboard.js.map +1 -0
  467. package/util/ai-run-evidence-eval.d.ts +86 -0
  468. package/util/ai-run-evidence-eval.js +1018 -0
  469. package/util/ai-run-evidence-eval.js.map +1 -0
  470. package/util/ai-run-evidence.d.ts +244 -0
  471. package/util/ai-run-evidence.js +1096 -0
  472. package/util/ai-run-evidence.js.map +1 -0
  473. package/util/ai-runner-artifacts.d.ts +82 -0
  474. package/util/ai-runner-artifacts.js +713 -0
  475. package/util/ai-runner-artifacts.js.map +1 -0
  476. package/util/ai-runner-manager-autopilot.d.ts +210 -0
  477. package/util/ai-runner-manager-autopilot.js +642 -0
  478. package/util/ai-runner-manager-autopilot.js.map +1 -0
  479. package/util/ai-runner-manager-policy.d.ts +807 -0
  480. package/util/ai-runner-manager-policy.js +3501 -0
  481. package/util/ai-runner-manager-policy.js.map +1 -0
  482. package/util/ai-runner-qa-auth.d.ts +5 -0
  483. package/util/ai-runner-qa-auth.js +839 -0
  484. package/util/ai-runner-qa-auth.js.map +1 -0
  485. package/util/ai-runner-qa-tools.d.ts +26 -0
  486. package/util/ai-runner-qa-tools.js +3520 -0
  487. package/util/ai-runner-qa-tools.js.map +1 -0
  488. package/util/aicoder-runner-v6.d.ts +426 -0
  489. package/util/aicoder-runner-v6.js +2464 -0
  490. package/util/aicoder-runner-v6.js.map +1 -0
  491. package/util/common.d.ts +31 -0
  492. package/util/common.js +683 -0
  493. package/util/common.js.map +1 -0
  494. package/util/customer-portal-password.d.ts +13 -0
  495. package/util/customer-portal-password.js +209 -0
  496. package/util/customer-portal-password.js.map +1 -0
  497. package/util/error-reporter.d.ts +52 -0
  498. package/util/error-reporter.js +326 -0
  499. package/util/error-reporter.js.map +1 -0
  500. package/util/error-tracking.d.ts +13 -0
  501. package/util/error-tracking.js +120 -0
  502. package/util/error-tracking.js.map +1 -0
  503. package/util/openai-usage-cost.d.ts +6 -0
  504. package/util/openai-usage-cost.js +103 -0
  505. package/util/openai-usage-cost.js.map +1 -0
  506. package/util/report-builder-unwinds.d.ts +15 -0
  507. package/util/report-builder-unwinds.js +156 -0
  508. package/util/report-builder-unwinds.js.map +1 -0
  509. package/util/runner-process-janitor.d.ts +27 -0
  510. package/util/runner-process-janitor.js +208 -0
  511. package/util/runner-process-janitor.js.map +1 -0
  512. package/util/schema-report-builder.d.ts +6 -0
  513. package/util/schema-report-builder.js +481 -0
  514. package/util/schema-report-builder.js.map +1 -0
  515. package/util/slow-query-reporter.d.ts +28 -0
  516. package/util/slow-query-reporter.js +226 -0
  517. package/util/slow-query-reporter.js.map +1 -0
  518. package/util/subscription-dependency-context.d.ts +34 -0
  519. package/util/subscription-dependency-context.js +1283 -0
  520. package/util/subscription-dependency-context.js.map +1 -0
  521. package/util/support-runner-v5.d.ts +1426 -0
  522. package/util/support-runner-v5.js +7643 -0
  523. package/util/support-runner-v5.js.map +1 -0
  524. package/util/tokenizer.d.ts +5 -0
  525. package/util/tokenizer.js +41 -0
  526. package/util/tokenizer.js.map +1 -0
  527. package/workers/codex-runner.worker.d.ts +1 -0
  528. package/workers/codex-runner.worker.js +192 -0
  529. package/workers/codex-runner.worker.js.map +1 -0
  530. package/.nodemon.json +0 -5
  531. package/.vscode/settings.json +0 -21
  532. package/AGENTS.md +0 -195
  533. package/README.md +0 -22
  534. package/build_package.sh +0 -5
  535. package/compileDTS.pl +0 -64
  536. package/docs/ai-assistant-nightly-eval.md +0 -65
  537. package/docs/ai-assistant-preflight-checklist.md +0 -23
  538. package/docs/ai-assistant-report-builder-bridge-playbook.md +0 -115
  539. package/eslint-plugin-custom/index.js +0 -7
  540. package/eslint-plugin-custom/rules/no-filter-zero-index.js +0 -44
  541. package/eslint.config.js +0 -103
  542. package/gulpfile.js +0 -216
  543. package/methodAndPublicationListGenerator.py +0 -375
  544. package/mongodbensurers.js +0 -2
  545. package/mongostop.js +0 -3
  546. package/scripts/cleanup-bypassed-callmethod-logs.js +0 -616
  547. package/settings.development.json +0 -25
  548. package/settings.development.redacted.json +0 -25
  549. package/src/.env +0 -12
  550. package/src/ai/assistant-core-heuristics.ts +0 -379
  551. package/src/ai/resolveio-platform-intelligence-memory-corpus.ts +0 -185
  552. package/src/ai/resolveio-platform-intelligence-memory.ts +0 -325
  553. package/src/ai/resolveio-platform-intelligence.ts +0 -462
  554. package/src/client-server-app.ts +0 -12
  555. package/src/collections/ai-run.collection.ts +0 -117
  556. package/src/collections/ai-terminal-conversation.collection.ts +0 -91
  557. package/src/collections/ai-terminal-issue-report.collection.ts +0 -99
  558. package/src/collections/ai-terminal-message.collection.ts +0 -77
  559. package/src/collections/app-setting.collection.ts +0 -104
  560. package/src/collections/app-status.collection.ts +0 -58
  561. package/src/collections/communication-metric.collection.ts +0 -84
  562. package/src/collections/counter.collection.ts +0 -56
  563. package/src/collections/cron-job-history.collection.ts +0 -94
  564. package/src/collections/cron-job.collection.ts +0 -92
  565. package/src/collections/customer-notification.collection.ts +0 -131
  566. package/src/collections/customer-portal-password.collection.ts +0 -76
  567. package/src/collections/email-history.collection.ts +0 -134
  568. package/src/collections/email-verified.collection.ts +0 -62
  569. package/src/collections/file.collection.ts +0 -74
  570. package/src/collections/flag-update.collection.ts +0 -57
  571. package/src/collections/flag.collection.ts +0 -57
  572. package/src/collections/log-method-latency.collection.ts +0 -77
  573. package/src/collections/log-subscription.collection.ts +0 -80
  574. package/src/collections/log.collection.ts +0 -93
  575. package/src/collections/logged-in-users.collection.ts +0 -67
  576. package/src/collections/monitor-cpu.collection.ts +0 -65
  577. package/src/collections/monitor-function.collection.ts +0 -74
  578. package/src/collections/monitor-memory.collection.ts +0 -77
  579. package/src/collections/monitor-mongo.collection.ts +0 -71
  580. package/src/collections/notification.collection.ts +0 -57
  581. package/src/collections/openai-usage-ledger.collection.ts +0 -131
  582. package/src/collections/report-builder-dashboard-builder.collection.ts +0 -109
  583. package/src/collections/report-builder-library.collection.ts +0 -89
  584. package/src/collections/report-builder-report.collection.ts +0 -184
  585. package/src/collections/user-group.collection.ts +0 -89
  586. package/src/collections/user-guide.collection.ts +0 -57
  587. package/src/collections/user.collection.ts +0 -181
  588. package/src/cron/cron.ts +0 -117
  589. package/src/fixtures/cron-jobs.ts +0 -95
  590. package/src/fixtures/init.ts +0 -35
  591. package/src/http/auth.ts +0 -818
  592. package/src/http/health.ts +0 -7
  593. package/src/http/home.ts +0 -90
  594. package/src/http/slow-query-publication.ts +0 -49
  595. package/src/index.ts +0 -1
  596. package/src/managers/ai-assistant-codex-manager.manager.ts +0 -1131
  597. package/src/managers/ai-run-evidence.manager.ts +0 -264
  598. package/src/managers/communication-metric.manager.ts +0 -82
  599. package/src/managers/cron.manager.ts +0 -333
  600. package/src/managers/customer-notification-content.manager.ts +0 -236
  601. package/src/managers/diagnostic-manager-bootstrap.ts +0 -165
  602. package/src/managers/error-auto-fix.manager.ts +0 -2767
  603. package/src/managers/local-log.manager.ts +0 -113
  604. package/src/managers/method.manager.ts +0 -1857
  605. package/src/managers/mongo.manager.ts +0 -4575
  606. package/src/managers/monitor.manager.ts +0 -507
  607. package/src/managers/openai-usage-ledger.manager.ts +0 -112
  608. package/src/managers/slow-query-verifier.manager.ts +0 -3590
  609. package/src/managers/slow-query.manager.ts +0 -519
  610. package/src/managers/subscription.manager.ts +0 -3128
  611. package/src/managers/websocket.manager.ts +0 -746
  612. package/src/managers/worker-dispatcher.manager.ts +0 -1360
  613. package/src/managers/worker-server.manager.ts +0 -536
  614. package/src/methods/accounts.ts +0 -532
  615. package/src/methods/ai-terminal.ts +0 -29070
  616. package/src/methods/app-settings.ts +0 -114
  617. package/src/methods/aws.ts +0 -649
  618. package/src/methods/collections.ts +0 -641
  619. package/src/methods/counters.ts +0 -69
  620. package/src/methods/cron-jobs.ts +0 -2614
  621. package/src/methods/customer-notifications.ts +0 -458
  622. package/src/methods/diagnostics.ts +0 -616
  623. package/src/methods/flag-updates.ts +0 -7
  624. package/src/methods/flags.ts +0 -7
  625. package/src/methods/logs.ts +0 -657
  626. package/src/methods/mongo-explorer.ts +0 -1880
  627. package/src/methods/monitor.ts +0 -540
  628. package/src/methods/pdf.ts +0 -1236
  629. package/src/methods/publications.ts +0 -129
  630. package/src/methods/report-builder.ts +0 -3300
  631. package/src/methods/support.ts +0 -335
  632. package/src/models/ai-run.model.ts +0 -27
  633. package/src/models/ai-terminal-conversation.model.ts +0 -19
  634. package/src/models/ai-terminal-issue-report.model.ts +0 -21
  635. package/src/models/ai-terminal-message.model.ts +0 -24
  636. package/src/models/app-setting.model.ts +0 -17
  637. package/src/models/collection-document.model.ts +0 -24
  638. package/src/models/communication-metric.model.ts +0 -23
  639. package/src/models/cron-job-history.model.ts +0 -16
  640. package/src/models/cron-job.model.ts +0 -15
  641. package/src/models/customer-notification.model.ts +0 -28
  642. package/src/models/customer-portal-password.model.ts +0 -12
  643. package/src/models/dialog.model.ts +0 -25
  644. package/src/models/log-method-latency.model.ts +0 -11
  645. package/src/models/log.model.ts +0 -19
  646. package/src/models/method.model.ts +0 -25
  647. package/src/models/monitor-function.model.ts +0 -16
  648. package/src/models/monitor-memory.model.ts +0 -17
  649. package/src/models/monitor-mongo.model.ts +0 -15
  650. package/src/models/openai-usage-ledger.model.ts +0 -56
  651. package/src/models/pagination.model.ts +0 -35
  652. package/src/models/permission.model.ts +0 -14
  653. package/src/models/report-builder-dashboard-builder.model.ts +0 -29
  654. package/src/models/report-builder-library.model.ts +0 -20
  655. package/src/models/report-builder-report.model.ts +0 -136
  656. package/src/models/report-builder.model.ts +0 -68
  657. package/src/models/select-data-label.model.ts +0 -9
  658. package/src/models/server-message.model.ts +0 -31
  659. package/src/models/slow-query-report.model.ts +0 -23
  660. package/src/models/subscription.model.ts +0 -73
  661. package/src/models/support-ticket.model.ts +0 -104
  662. package/src/models/user-group.model.ts +0 -24
  663. package/src/models/user.model.ts +0 -96
  664. package/src/private/images/ResolveIO.png +0 -0
  665. package/src/publications/ai-terminal.ts +0 -73
  666. package/src/publications/app-settings.ts +0 -25
  667. package/src/publications/app-status.ts +0 -13
  668. package/src/publications/cron-jobs.ts +0 -40
  669. package/src/publications/customer-notifications.ts +0 -101
  670. package/src/publications/files.ts +0 -33
  671. package/src/publications/flags-update.ts +0 -19
  672. package/src/publications/flags.ts +0 -19
  673. package/src/publications/logs.ts +0 -163
  674. package/src/publications/notifications.ts +0 -13
  675. package/src/publications/report-builder-dashboard-builders.ts +0 -39
  676. package/src/publications/report-builder-libraries.ts +0 -41
  677. package/src/publications/report-builder-reports.ts +0 -47
  678. package/src/publications/super-admin.ts +0 -13
  679. package/src/publications/user-groups.ts +0 -12
  680. package/src/publications/user-guides.ts +0 -12
  681. package/src/resolveio-server-app.ts +0 -617
  682. package/src/server-app.ts +0 -3354
  683. package/src/services/codex-client.ts +0 -1231
  684. package/src/services/openai-client.ts +0 -265
  685. package/src/types/error-report.ts +0 -26
  686. package/src/types/js-tiktoken.d.ts +0 -11
  687. package/src/types/slow-query-report.ts +0 -28
  688. package/src/util/ai-qa-policy.ts +0 -925
  689. package/src/util/ai-run-evidence-adapters.ts +0 -8347
  690. package/src/util/ai-run-evidence-dashboard.ts +0 -323
  691. package/src/util/ai-run-evidence-eval.ts +0 -1057
  692. package/src/util/ai-run-evidence.ts +0 -1430
  693. package/src/util/ai-runner-artifacts.ts +0 -586
  694. package/src/util/ai-runner-manager-autopilot.ts +0 -961
  695. package/src/util/ai-runner-manager-policy.ts +0 -5011
  696. package/src/util/ai-runner-qa-auth.ts +0 -838
  697. package/src/util/ai-runner-qa-tools.ts +0 -3536
  698. package/src/util/aicoder-runner-v6.ts +0 -3121
  699. package/src/util/common.ts +0 -649
  700. package/src/util/customer-portal-password.ts +0 -183
  701. package/src/util/error-reporter.ts +0 -332
  702. package/src/util/error-tracking.ts +0 -79
  703. package/src/util/openai-usage-cost.ts +0 -114
  704. package/src/util/report-builder-unwinds.ts +0 -180
  705. package/src/util/runner-process-janitor.ts +0 -219
  706. package/src/util/schema-report-builder.ts +0 -448
  707. package/src/util/slow-query-reporter.ts +0 -216
  708. package/src/util/subscription-dependency-context.ts +0 -1096
  709. package/src/util/support-runner-v5.ts +0 -10040
  710. package/src/util/tokenizer.ts +0 -38
  711. package/src/workers/codex-runner.worker.ts +0 -142
  712. package/start_server.sh +0 -5
  713. package/tests/ai-assistant-corpus-build.ts +0 -484
  714. package/tests/ai-assistant-corpus-replay-e2e.ts +0 -774
  715. package/tests/ai-assistant-data-parity-e2e.ts +0 -1989
  716. package/tests/ai-assistant-eval-triage.ts +0 -831
  717. package/tests/ai-assistant-openai-e2e.ts +0 -1061
  718. package/tests/ai-assistant-openai-git-e2e.ts +0 -155
  719. package/tests/ai-assistant-preflight-matrix.ts +0 -215
  720. package/tests/ai-assistant-routing-eval.test.ts +0 -585
  721. package/tests/ai-assistant-snf-live-eval.ts +0 -975
  722. package/tests/ai-assistant-utils.test.ts +0 -4834
  723. package/tests/ai-manager-autopilot-snapshot.test.ts +0 -193
  724. package/tests/ai-manager-recovery-checkpoint.test.ts +0 -1383
  725. package/tests/ai-run-eval.test.ts +0 -132
  726. package/tests/ai-run-evidence.test.ts +0 -3773
  727. package/tests/ai-runner-contract.test.ts +0 -515
  728. package/tests/aicoder-runner-v6.test.ts +0 -822
  729. package/tests/error-reporter.test.ts +0 -145
  730. package/tests/method-publication-generator.test.ts +0 -46
  731. package/tests/report-builder-linking.test.ts +0 -79
  732. package/tests/resolveio-platform-intelligence.test.ts +0 -352
  733. package/tests/server-app-cron-owner.test.ts +0 -127
  734. package/tests/subscription-connect-race.test.ts +0 -158
  735. package/tests/subscription-dependency-context.test.ts +0 -324
  736. package/tests/subscription-manager-collection-tracking.test.ts +0 -86
  737. package/tests/subscription-manager-invalidation.test.ts +0 -86
  738. package/tests/support-runner-v5.test.ts +0 -3201
  739. package/tsconfig.json +0 -34
  740. /package/{src/private → private}/email-templates/enrollment.html +0 -0
  741. /package/{src/private → private}/email-templates/forgot-password.html +0 -0
  742. /package/{src/private → private}/email-templates/support-ticket-deleted.html +0 -0
  743. /package/{src/private → private}/email-templates/support-ticket-modified.html +0 -0
  744. /package/{src/private → private}/email-templates/support-ticket.html +0 -0
  745. /package/{src/public_api.ts → public_api.d.ts} +0 -0
@@ -1,3121 +0,0 @@
1
- import {
2
- buildResolveIOAIManagerRecoveryCheckpoint,
3
- buildResolveIOAIManagerRecoveryActionPacket,
4
- buildResolveIOAIManagerRecoveryEvidenceProbe,
5
- buildResolveIOAIManagerRecoveryPlan,
6
- decideResolveIOAIManagerPolicy,
7
- hashResolveIOAIManagerEvidence,
8
- ResolveIOAIManagerRecoveryCheckpoint,
9
- ResolveIOAIManagerRecoveryActionPacket,
10
- ResolveIOAIManagerRecoveryActionDispatchRecord,
11
- ResolveIOAIManagerRecoveryExecutionDirective,
12
- ResolveIOAIManagerRecoveryEvidenceProbe,
13
- ResolveIOAIManagerRecoveryPlan,
14
- ResolveIOAIManagerRecoveryPlanInput
15
- } from './ai-runner-manager-policy';
16
-
17
- export type ResolveIOAICoderV6Lane =
18
- | 'intake'
19
- | 'plan'
20
- | 'build'
21
- | 'qa'
22
- | 'repair'
23
- | 'review'
24
- | 'publish';
25
-
26
- export type ResolveIOAICoderV6StepType =
27
- | 'intake'
28
- | 'journey_contract'
29
- | 'journey_validation'
30
- | 'plan'
31
- | 'task'
32
- | 'workflow_build'
33
- | 'workflow_qa'
34
- | 'build'
35
- | 'qa'
36
- | 'repair'
37
- | 'review'
38
- | 'test_deploy'
39
- | 'live_deploy'
40
- | 'publish'
41
- | 'cleanup';
42
-
43
- export type ResolveIOAICoderV6Outcome =
44
- | 'pass'
45
- | 'needs_repair'
46
- | 'retry_same_step'
47
- | 'park_manual'
48
- | 'budget_stop'
49
- | 'infra_retry'
50
- | 'ready_to_publish'
51
- | 'published';
52
-
53
- export type ResolveIOAICoderV6RunKind = 'initial_builder' | 'terminal_helper';
54
-
55
- export interface ResolveIOAICoderV6Budget {
56
- maxPromptTokensPerNonInitialStep: number;
57
- maxTotalPromptTokens: number;
58
- maxLoopsPerRun: number;
59
- maxRepeatedNoProgress: number;
60
- maxRuntimeMinutesPerLane: number;
61
- softBudgetUsd: number;
62
- hardBudgetUsd: number;
63
- totalPromptTokenEstimate: number;
64
- totalInputTokens: number;
65
- totalCachedInputTokens: number;
66
- totalOutputTokens: number;
67
- totalRuntimeMs: number;
68
- loopCount: number;
69
- }
70
-
71
- export interface ResolveIOAICoderV6LaneMemory {
72
- lane: ResolveIOAICoderV6Lane;
73
- model: string;
74
- threadKey: string;
75
- scopeSummary: string;
76
- activeStep: ResolveIOAICoderV6StepType;
77
- activeBlocker: string;
78
- activeQaRow?: {
79
- index?: number;
80
- workflow?: string;
81
- route?: string;
82
- assertion?: string;
83
- status?: string;
84
- };
85
- changedFiles: string[];
86
- artifactPaths: string[];
87
- latestPromptVersion?: string;
88
- latestPromptTokenEstimate?: number;
89
- updatedAt: string;
90
- }
91
-
92
- export interface ResolveIOAICoderV6WorkflowQaRow {
93
- index?: number;
94
- workflowId?: string;
95
- workflowStepId?: string;
96
- workflowStepIds?: string[];
97
- stepId?: string;
98
- route?: string;
99
- action?: string;
100
- assertion?: string;
101
- expectedState?: string;
102
- expectedOutput?: string;
103
- proofKind?: string;
104
- coverageTags?: string[];
105
- acceptanceGate?: 'aiqa_business_assertion';
106
- requiredArtifacts?: string[];
107
- stateTransition?: {
108
- before?: string;
109
- action?: string;
110
- after?: string;
111
- assertion?: string;
112
- };
113
- status?: string;
114
- artifactPaths?: string[];
115
- }
116
-
117
- export interface ResolveIOAICoderV6WorkflowMemory {
118
- journeyContractPath: string;
119
- primaryWorkflowId: string;
120
- activeWorkflowStep: string;
121
- workflowQaRows: ResolveIOAICoderV6WorkflowQaRow[];
122
- completedWorkflowSteps: string[];
123
- blockedWorkflowStep: string;
124
- businessProofArtifacts: string[];
125
- updatedAt: string;
126
- }
127
-
128
- export interface ResolveIOAICoderJourneyContractValidationIssue {
129
- code: string;
130
- path: string;
131
- message: string;
132
- severity: 'error' | 'warning';
133
- }
134
-
135
- export interface ResolveIOAICoderJourneyContractValidationResult {
136
- valid: boolean;
137
- contract: Record<string, any> | null;
138
- issues: ResolveIOAICoderJourneyContractValidationIssue[];
139
- workflowQaRows: ResolveIOAICoderV6WorkflowQaRow[];
140
- primaryWorkflowId: string;
141
- }
142
-
143
- export type ResolveIOAICoderWorkflowProofReadinessStatus =
144
- | 'ready'
145
- | 'missing_journey_contract'
146
- | 'journey_invalid'
147
- | 'route_only'
148
- | 'workflow_qa_missing'
149
- | 'workflow_qa_incomplete'
150
- | 'business_proof_missing'
151
- | 'business_proof_weak'
152
- | 'sample_data_missing'
153
- | 'release_blocked'
154
- | 'stale_workflow_proof'
155
- | 'blocked';
156
-
157
- export interface ResolveIOAICoderWorkflowProofReadinessInput {
158
- journeyContract?: any;
159
- journeyContractMarkdown?: string;
160
- workflowQaRows?: ResolveIOAICoderV6WorkflowQaRow[];
161
- businessAssertions?: Array<Record<string, any>>;
162
- routeProbes?: Array<Record<string, any>>;
163
- artifactPaths?: string[];
164
- scorecardPassed?: boolean;
165
- deployStatus?: string;
166
- publishStatus?: string;
167
- sampleDataStatus?: string;
168
- previousWorkflowProofFingerprint?: string;
169
- previousArtifactFingerprint?: string;
170
- previousWorkflowProofFingerprints?: string[];
171
- previousArtifactFingerprints?: string[];
172
- now?: Date | string;
173
- }
174
-
175
- export type ResolveIOAICoderWorkflowProofFreshness =
176
- | 'fresh'
177
- | 'same_as_previous'
178
- | 'stale_artifact'
179
- | 'missing'
180
- | 'unknown';
181
-
182
- export interface ResolveIOAICoderWorkflowProofReadiness {
183
- ready: boolean;
184
- status: ResolveIOAICoderWorkflowProofReadinessStatus;
185
- reason: string;
186
- blockers: string[];
187
- journeyContractValid: boolean;
188
- primaryWorkflowId: string;
189
- passedWorkflowRows: string[];
190
- missingWorkflowRows: string[];
191
- failedWorkflowRows: string[];
192
- passedBusinessAssertions: string[];
193
- routeOnly: boolean;
194
- scorecardOnly: boolean;
195
- sampleDataReady: boolean;
196
- releaseBlockers: string[];
197
- artifactPaths: string[];
198
- workflowProofFingerprint: string;
199
- artifactFingerprint: string;
200
- proofFreshness: ResolveIOAICoderWorkflowProofFreshness;
201
- nextAction: string;
202
- evaluatedAt: string;
203
- }
204
-
205
- export type ResolveIOAICoderV6ContinuationAction =
206
- | 'continue'
207
- | 'retry_same_step'
208
- | 'switch_to_repair'
209
- | 'park'
210
- | 'budget_stop'
211
- | 'infra_retry'
212
- | 'ready_to_publish';
213
-
214
- export type ResolveIOAICoderNextActionCostRisk =
215
- | 'free_or_deterministic'
216
- | 'small_model_or_qa'
217
- | 'expensive_model'
218
- | 'release_or_customer_send'
219
- | 'manual_blocked';
220
-
221
- export type ResolveIOAICoderWorkflowReadinessStatus =
222
- | 'journey_contract_required'
223
- | 'journey_contract_repair_required'
224
- | 'workflow_build_ready'
225
- | 'workflow_qa_required'
226
- | 'workflow_business_proof_ready'
227
- | 'release_repair_required'
228
- | 'infra_repair_only'
229
- | 'compile_repair_only'
230
- | 'collect_new_evidence'
231
- | 'budget_stopped'
232
- | 'parked';
233
-
234
- export type ResolveIOAICoderWorkflowReadinessGate =
235
- | 'journey_contract'
236
- | 'build'
237
- | 'workflow_qa'
238
- | 'release'
239
- | 'infra'
240
- | 'compile'
241
- | 'evidence'
242
- | 'manual';
243
-
244
- export type ResolveIOAICoderWorkflowProofCheckpointStatus =
245
- | 'waiting_for_journey_contract'
246
- | 'waiting_for_workflow_proof'
247
- | 'waiting_for_new_evidence'
248
- | 'waiting_for_release_gate'
249
- | 'waiting_for_infra_or_compile'
250
- | 'ready_to_continue';
251
-
252
- export interface ResolveIOAICoderWorkflowProofCheckpoint {
253
- required: boolean;
254
- status: ResolveIOAICoderWorkflowProofCheckpointStatus;
255
- readinessStatus: ResolveIOAICoderWorkflowReadinessStatus;
256
- nextGate: ResolveIOAICoderWorkflowReadinessGate;
257
- startingFailureClass: string;
258
- startingBlockerFingerprint: string;
259
- startingEvidenceHash: string;
260
- workflowProofFingerprint: string;
261
- artifactFingerprint: string;
262
- requiredEvidence: string[];
263
- requiredResetEvidence: string[];
264
- successRequiresWorkflowBusinessProof: boolean;
265
- blocksProductRepairUntilJourneyContract: boolean;
266
- blocksPublishUntilWorkflowProof: boolean;
267
- blocksPublishUntilReleaseGate: boolean;
268
- blocksWowUiUntilWorkflowProof: boolean;
269
- nextAction: string;
270
- }
271
-
272
- export interface ResolveIOAICoderWorkflowReadiness {
273
- status: ResolveIOAICoderWorkflowReadinessStatus;
274
- nextGate: ResolveIOAICoderWorkflowReadinessGate;
275
- nextLane: ResolveIOAICoderV6Lane;
276
- nextStep: ResolveIOAICoderV6StepType;
277
- nextCommand: string;
278
- journeyContractReady: boolean;
279
- workflowQaRowsReady: boolean;
280
- businessProofReady: boolean;
281
- routeOnlyBlocked: boolean;
282
- releaseBlocked: boolean;
283
- infraOnly: boolean;
284
- compileOnly: boolean;
285
- sameFailureParked: boolean;
286
- canRunProductRepair: boolean;
287
- canRunWorkflowQa: boolean;
288
- canPublish: boolean;
289
- canPolishWowUi: boolean;
290
- requiresHumanDecision: boolean;
291
- reason: string;
292
- blockers: string[];
293
- primaryWorkflowId: string;
294
- activeWorkflowStep: string;
295
- businessProofArtifacts: string[];
296
- workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
297
- }
298
-
299
- export interface ResolveIOAICoderNextActionContract {
300
- contractId: string;
301
- action: ResolveIOAICoderV6ContinuationAction;
302
- label: string;
303
- primaryCommand: string;
304
- lane: ResolveIOAICoderV6Lane;
305
- stepType: ResolveIOAICoderV6StepType;
306
- safeToAutoRun: boolean;
307
- requiresHumanApproval: boolean;
308
- canRunWithoutCodexMonitor: boolean;
309
- codexFallbackRequired: boolean;
310
- codexFallbackReason: string;
311
- costRisk: ResolveIOAICoderNextActionCostRisk;
312
- workflowFirstSatisfied: boolean;
313
- decisionBasis: {
314
- journeyContractReady: boolean;
315
- workflowProofReady: boolean;
316
- sampleDataReady: boolean;
317
- releaseBlocked: boolean;
318
- routeOnlyBlocked: boolean;
319
- infraOnly: boolean;
320
- compileOnly: boolean;
321
- sameFailureParked: boolean;
322
- canPublish: boolean;
323
- canPolishWowUi: boolean;
324
- workflowReadinessStatus: string;
325
- workflowProofCheckpointStatus: string;
326
- failureClass: string;
327
- evidenceHash: string;
328
- hotfixCommitRequired: boolean;
329
- liveHotfixBlockedUntilCommit: boolean;
330
- };
331
- preconditions: string[];
332
- expectedStateTransition: string;
333
- successEvidence: string[];
334
- requiredHotfixCommitProof: string[];
335
- stopConditions: string[];
336
- forbiddenActions: string[];
337
- nextCommands: string[];
338
- blockers: string[];
339
- ownerFiles?: string[];
340
- createdAt: string;
341
- }
342
-
343
- export interface ResolveIOAICoderV6SupervisorState {
344
- version: 'v6';
345
- runKind: ResolveIOAICoderV6RunKind;
346
- status: 'active' | 'parked' | 'complete';
347
- currentGoal: string;
348
- approvedScope: string;
349
- branchName: string;
350
- activeLane: ResolveIOAICoderV6Lane;
351
- activeStep: ResolveIOAICoderV6StepType;
352
- activeBlocker: string;
353
- lastGoodCheckpoint: string;
354
- lastGoodCommit?: string;
355
- testDeployStatus?: string;
356
- liveDeployStatus?: string;
357
- processLease?: {
358
- runId?: string;
359
- token?: string;
360
- generation?: number;
361
- workspace?: string;
362
- lane?: string;
363
- };
364
- artifactLinks: string[];
365
- updatedAt: string;
366
- }
367
-
368
- export interface ResolveIOAICoderV6StepRecord {
369
- stepType: ResolveIOAICoderV6StepType;
370
- outcome: ResolveIOAICoderV6Outcome;
371
- lane: ResolveIOAICoderV6Lane;
372
- model?: string;
373
- threadKey?: string;
374
- promptVersion?: string;
375
- promptTokenEstimate?: number;
376
- inputTokens?: number;
377
- cachedInputTokens?: number;
378
- outputTokens?: number;
379
- runtimeMs?: number;
380
- summary: string;
381
- blocker?: string;
382
- blockerFingerprint?: string;
383
- failureClass?: string;
384
- evidenceHash?: string;
385
- changedFiles?: string[];
386
- artifactPaths?: string[];
387
- nextAction?: ResolveIOAICoderV6ContinuationAction;
388
- recordedAt: string;
389
- }
390
-
391
- export interface ResolveIOAICoderV6RunnerIncident {
392
- incidentClass: string;
393
- summary: string;
394
- stepType?: ResolveIOAICoderV6StepType;
395
- lane?: ResolveIOAICoderV6Lane;
396
- blockerFingerprint?: string;
397
- artifactPaths?: string[];
398
- recordedAt: string;
399
- }
400
-
401
- export interface ResolveIOAICoderV6StateBundle {
402
- aiCoderRunnerVersion: 'v6';
403
- aiCoderV6SupervisorState: ResolveIOAICoderV6SupervisorState;
404
- aiCoderV6LaneMemory: Record<ResolveIOAICoderV6Lane, ResolveIOAICoderV6LaneMemory>;
405
- aiCoderV6WorkflowMemory: ResolveIOAICoderV6WorkflowMemory;
406
- aiCoderV6StepHistory: ResolveIOAICoderV6StepRecord[];
407
- aiCoderV6Budget: ResolveIOAICoderV6Budget;
408
- aiCoderV6RunnerIncidents: ResolveIOAICoderV6RunnerIncident[];
409
- aiCoderV6RecoveryPlan?: ResolveIOAIManagerRecoveryPlan;
410
- aiCoderV6RecoveryCheckpoint?: ResolveIOAIManagerRecoveryCheckpoint;
411
- aiCoderV6RecoveryEvidenceProbe?: ResolveIOAIManagerRecoveryEvidenceProbe;
412
- aiCoderV6RecoveryAction?: ResolveIOAIManagerRecoveryActionPacket;
413
- aiCoderV6RecoveryDispatchHistory?: ResolveIOAIManagerRecoveryActionDispatchRecord[];
414
- aiCoderV6RecoveryDirective?: ResolveIOAIManagerRecoveryExecutionDirective;
415
- aiCoderV6WorkflowReadiness?: ResolveIOAICoderWorkflowReadiness;
416
- }
417
-
418
- export interface ResolveIOAICoderV6InitializeInput {
419
- runKind: ResolveIOAICoderV6RunKind;
420
- jobId: string;
421
- appId?: string;
422
- conversationId?: string;
423
- title?: string;
424
- description?: string;
425
- approvedScopeRequirements?: string[];
426
- branchName?: string;
427
- journeyContractPath?: string;
428
- defaultModel?: string;
429
- laneThreadKeys?: Partial<Record<ResolveIOAICoderV6Lane, string>>;
430
- processLease?: ResolveIOAICoderV6SupervisorState['processLease'];
431
- now?: Date | string;
432
- existing?: Partial<ResolveIOAICoderV6StateBundle>;
433
- }
434
-
435
- export interface ResolveIOAICoderV6StepInput {
436
- stepType: ResolveIOAICoderV6StepType;
437
- outcome: ResolveIOAICoderV6Outcome;
438
- lane: ResolveIOAICoderV6Lane;
439
- model?: string;
440
- threadKey?: string;
441
- promptVersion?: string;
442
- promptTokenEstimate?: number;
443
- inputTokens?: number;
444
- cachedInputTokens?: number;
445
- outputTokens?: number;
446
- runtimeMs?: number;
447
- summary?: string;
448
- blocker?: string;
449
- failureClass?: string;
450
- evidenceHash?: string;
451
- primaryWorkflowId?: string;
452
- activeWorkflowStep?: string;
453
- workflowQaRows?: ResolveIOAICoderV6WorkflowQaRow[];
454
- completedWorkflowSteps?: string[];
455
- blockedWorkflowStep?: string;
456
- businessProofArtifacts?: string[];
457
- changedFiles?: string[];
458
- artifactPaths?: string[];
459
- activeQaRow?: ResolveIOAICoderV6LaneMemory['activeQaRow'];
460
- nextAction?: ResolveIOAICoderV6ContinuationAction;
461
- now?: Date | string;
462
- }
463
-
464
- export interface ResolveIOAICoderV6ContinuationDecision {
465
- action: ResolveIOAICoderV6ContinuationAction;
466
- reason: string;
467
- nextLane: ResolveIOAICoderV6Lane;
468
- nextStep: ResolveIOAICoderV6StepType;
469
- repeatedNoProgressCount: number;
470
- budgetExceeded: boolean;
471
- workflowReadiness: ResolveIOAICoderWorkflowReadiness;
472
- workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
473
- nextActionContract: ResolveIOAICoderNextActionContract;
474
- recoveryPlan: ResolveIOAIManagerRecoveryPlan;
475
- recoveryCheckpoint: ResolveIOAIManagerRecoveryCheckpoint;
476
- recoveryEvidenceProbe: ResolveIOAIManagerRecoveryEvidenceProbe;
477
- recoveryAction: ResolveIOAIManagerRecoveryActionPacket;
478
- }
479
-
480
- const LANES: ResolveIOAICoderV6Lane[] = ['intake', 'plan', 'build', 'qa', 'repair', 'review', 'publish'];
481
-
482
- function isoNow(value?: Date | string): string {
483
- if (value instanceof Date) {
484
- return value.toISOString();
485
- }
486
- const parsed = value ? new Date(value) : new Date();
487
- if (Number.isFinite(parsed.getTime())) {
488
- return parsed.toISOString();
489
- }
490
- return new Date().toISOString();
491
- }
492
-
493
- function cleanText(value: any, max = 2000): string {
494
- return String(value || '').replace(/\s+/g, ' ').trim().slice(0, max);
495
- }
496
-
497
- function cleanList(values: any, limit = 20, max = 500): string[] {
498
- if (!Array.isArray(values)) {
499
- return [];
500
- }
501
- const result: string[] = [];
502
- for (const value of values) {
503
- const normalized = cleanText(value, max);
504
- if (normalized && !result.includes(normalized)) {
505
- result.push(normalized);
506
- }
507
- if (result.length >= limit) {
508
- break;
509
- }
510
- }
511
- return result;
512
- }
513
-
514
- function readField(source: any, keys: string[]): any {
515
- if (!source || typeof source !== 'object') {
516
- return undefined;
517
- }
518
- for (const key of keys) {
519
- if (source[key] !== undefined && source[key] !== null) {
520
- return source[key];
521
- }
522
- }
523
- return undefined;
524
- }
525
-
526
- function cleanField(source: any, keys: string[], max = 500): string {
527
- return cleanText(readField(source, keys), max);
528
- }
529
-
530
- function concatFields(source: any, keys: string[], maxEach = 500): string {
531
- if (!source || typeof source !== 'object') {
532
- return '';
533
- }
534
- return keys
535
- .map((key) => cleanText(source[key], maxEach))
536
- .filter(Boolean)
537
- .join(' ');
538
- }
539
-
540
- function asArray(value: any): any[] {
541
- if (!Array.isArray(value)) {
542
- return [];
543
- }
544
- return value;
545
- }
546
-
547
- function stripJsonComments(value: string): string {
548
- let output = '';
549
- let inString = false;
550
- let escaped = false;
551
- for (let index = 0; index < value.length; index += 1) {
552
- const char = value[index];
553
- const next = value[index + 1];
554
- if (inString) {
555
- output += char;
556
- if (escaped) {
557
- escaped = false;
558
- }
559
- else if (char === '\\') {
560
- escaped = true;
561
- }
562
- else if (char === '"') {
563
- inString = false;
564
- }
565
- continue;
566
- }
567
- if (char === '"') {
568
- inString = true;
569
- output += char;
570
- continue;
571
- }
572
- if (char === '/' && next === '/') {
573
- while (index < value.length && value[index] !== '\n') {
574
- index += 1;
575
- }
576
- output += '\n';
577
- continue;
578
- }
579
- if (char === '/' && next === '*') {
580
- index += 2;
581
- while (index < value.length && !(value[index] === '*' && value[index + 1] === '/')) {
582
- index += 1;
583
- }
584
- index += 1;
585
- continue;
586
- }
587
- output += char;
588
- }
589
- return output;
590
- }
591
-
592
- function parseJsonObject(value: string): Record<string, any> | null {
593
- try {
594
- const parsed = JSON.parse(stripJsonComments(value));
595
- return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : null;
596
- }
597
- catch {
598
- return null;
599
- }
600
- }
601
-
602
- export function extractResolveIOAICoderJourneyContractFromMarkdown(content: string | null | undefined): Record<string, any> | null {
603
- const normalized = String(content || '').replace(/\r\n/g, '\n');
604
- const sectionMatch = normalized.match(/##\s*journey_contract[\s\S]*?```json\s*([\s\S]*?)```/i)
605
- || normalized.match(/##\s*journey_contract[\s\S]*?```\s*([\s\S]*?)```/i);
606
- if (sectionMatch?.[1]) {
607
- return parseJsonObject(sectionMatch[1].trim());
608
- }
609
- const fencedMatch = normalized.match(/```json\s*([\s\S]*?)```/i);
610
- if (fencedMatch?.[1]) {
611
- return parseJsonObject(fencedMatch[1].trim());
612
- }
613
- const objectMatch = normalized.match(/\{\s*"app_archetype"[\s\S]*\}\s*$/m);
614
- if (objectMatch?.[0]) {
615
- return parseJsonObject(objectMatch[0].trim());
616
- }
617
- return null;
618
- }
619
-
620
- function looksLikeAbsoluteRoute(value: string): boolean {
621
- return value.startsWith('/') && !/\s/.test(value);
622
- }
623
-
624
- function looksPlaceholder(value: string): boolean {
625
- return /\b(tbd|todo|placeholder|generic crud|crud-only|lorem ipsum|add details|fill in|coming soon)\b/i.test(value || '');
626
- }
627
-
628
- function isNavigationOnlyAction(source: any): boolean {
629
- const effect = cleanField(source, ['effect', 'outcome', 'state_change', 'expected_state_transition', 'expected_next_state'], 500).toLowerCase();
630
- const implementation = cleanField(source, [
631
- 'method_or_calculation',
632
- 'server_method_or_publication',
633
- 'local_calculation_path',
634
- 'action_implementation',
635
- 'calculation_path',
636
- 'data_mutation',
637
- 'mutation',
638
- 'persisted_result'
639
- ], 500);
640
- if (implementation) {
641
- return false;
642
- }
643
- const actionType = cleanField(source, ['action_type', 'type', 'kind'], 120).toLowerCase();
644
- const actionText = [
645
- cleanField(source, ['action', 'visible_cta', 'cta', 'label'], 300),
646
- cleanField(source, ['next_step_destination', 'next_step', 'destination'], 300)
647
- ].join(' ').toLowerCase();
648
- const navigationSignals = /\b(navigate|go to|open|view|link|route|page)\b/.test(actionText)
649
- || /^(?:link|nav|navigation|route)$/i.test(actionType);
650
- const productiveEffect = /\b(save|saved|create|created|update|updated|calculate|calculated|optimize|optimized|import|export|report|persist|queued|submitted|validated|generated|compare|recommendation|complete|completed)\b/.test(effect);
651
- return navigationSignals && !productiveEffect;
652
- }
653
-
654
- function addJourneyIssue(
655
- issues: ResolveIOAICoderJourneyContractValidationIssue[],
656
- code: string,
657
- path: string,
658
- message: string,
659
- severity: 'error' | 'warning' = 'error'
660
- ): void {
661
- issues.push({ code, path, message, severity });
662
- }
663
-
664
- function normalizeWorkflowStepPosition(step: any, index: number, total: number): string {
665
- const explicit = cleanField(step, ['position', 'phase', 'order_role'], 60).toLowerCase();
666
- if (explicit) {
667
- return explicit;
668
- }
669
- if (index === 0) {
670
- return 'first';
671
- }
672
- if (index === total - 1) {
673
- return 'last';
674
- }
675
- return 'next';
676
- }
677
-
678
- function normalizeJourneyReferenceKey(value: any): string {
679
- return cleanText(value, 160).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '');
680
- }
681
-
682
- function normalizeJourneyRouteKey(value: any): string {
683
- const raw = cleanText(value, 240);
684
- if (!raw) {
685
- return '';
686
- }
687
- const route = raw.split(/[?#]/)[0].replace(/\/+$/g, '') || '/';
688
- return route.toLowerCase();
689
- }
690
-
691
- function normalizeJourneyActionText(value: any): string {
692
- return cleanText(value, 1000).toLowerCase().replace(/[^a-z0-9]+/g, ' ').trim();
693
- }
694
-
695
- function buildWorkflowStepId(step: any, index: number): string {
696
- return cleanField(step, ['id', 'step_id', 'key'], 120)
697
- || cleanField(step, ['label', 'title', 'visible_cta'], 120).toLowerCase().replace(/[^a-z0-9]+/g, '-').replace(/^-|-$/g, '')
698
- || `step-${index + 1}`;
699
- }
700
-
701
- function workflowStepVisibleAction(step: any): string {
702
- return cleanField(step, ['visible_cta', 'cta', 'label', 'action', 'embedded_hub_action', 'hub_action'], 500);
703
- }
704
-
705
- function journeySourceVisibleAction(source: any): string {
706
- return concatFields(source, [
707
- 'visible_cta',
708
- 'cta',
709
- 'label',
710
- 'action',
711
- 'browser_steps',
712
- 'expected_dom_or_data_proof',
713
- 'proof',
714
- 'assertion',
715
- 'expected_result'
716
- ], 700);
717
- }
718
-
719
- function actionTextReferencesLabel(actionText: string, label: string): boolean {
720
- const action = normalizeJourneyActionText(actionText);
721
- const expected = normalizeJourneyActionText(label);
722
- if (!action || !expected || expected.length < 4) {
723
- return false;
724
- }
725
- if (action === expected || action.includes(expected) || expected.includes(action)) {
726
- return true;
727
- }
728
- const actionTokens = new Set(action.split(/\s+/).filter((token) => token.length > 2));
729
- const expectedTokens = expected.split(/\s+/).filter((token) => token.length > 2);
730
- if (!expectedTokens.length) {
731
- return false;
732
- }
733
- const matched = expectedTokens.filter((token) => actionTokens.has(token)).length;
734
- return matched >= Math.min(expectedTokens.length, Math.max(2, Math.ceil(expectedTokens.length * 0.67)));
735
- }
736
-
737
- function collectJourneyReferenceKeys(source: any): string[] {
738
- if (!source || typeof source !== 'object') {
739
- return [];
740
- }
741
- const values: any[] = [];
742
- for (const key of [
743
- 'workflow_step_id',
744
- 'workflowStepId',
745
- 'workflow_step_ids',
746
- 'workflowStepIds',
747
- 'covers_workflow_step_id',
748
- 'coversWorkflowStepId',
749
- 'covers_workflow_step_ids',
750
- 'coversWorkflowStepIds',
751
- 'north_star_step_id',
752
- 'northStarStepId',
753
- 'step_ref',
754
- 'stepRef'
755
- ]) {
756
- const value = source[key];
757
- if (Array.isArray(value)) {
758
- values.push(...value);
759
- }
760
- else if (value !== undefined && value !== null) {
761
- values.push(value);
762
- }
763
- }
764
- return Array.from(new Set(values.map(normalizeJourneyReferenceKey).filter(Boolean))).slice(0, 20);
765
- }
766
-
767
- function journeySourceMapsToWorkflowStep(source: any, step: any, index: number): boolean {
768
- const stepId = normalizeJourneyReferenceKey(buildWorkflowStepId(step, index));
769
- const refs = collectJourneyReferenceKeys(source);
770
- if (stepId && refs.includes(stepId)) {
771
- return true;
772
- }
773
- const sourceRoute = normalizeJourneyRouteKey(cleanField(source, ['route', 'screen_route', 'path'], 240));
774
- const stepRoute = normalizeJourneyRouteKey(cleanField(step, ['route'], 240));
775
- if (!sourceRoute || !stepRoute || sourceRoute !== stepRoute) {
776
- return false;
777
- }
778
- return actionTextReferencesLabel(journeySourceVisibleAction(source), workflowStepVisibleAction(step));
779
- }
780
-
781
- function normalizeWorkflowProofKind(source: any, fallbackText = ''): string {
782
- const explicit = cleanField(source, ['proof_kind', 'proofKind', 'qa_proof_kind', 'qaProofKind', 'type', 'kind'], 120).toLowerCase().replace(/[\s-]+/g, '_');
783
- if (explicit) {
784
- return explicit;
785
- }
786
- const text = cleanText([
787
- fallbackText,
788
- concatFields(source, ['id', 'step_id', 'stepId', 'action', 'browser_steps', 'expected_dom_or_data_proof', 'proof', 'expected_result', 'viewport'], 700)
789
- ].filter(Boolean).join(' '), 1800).toLowerCase();
790
- if (/\b(mobile|390x844|viewport)\b/.test(text)) {
791
- return 'mobile';
792
- }
793
- if (/\b(export|report|pdf|download)\b/.test(text)) {
794
- return 'report_export';
795
- }
796
- if (/\b(complete|saved|save|result|recommendation|calculated|optimized|final)\b/.test(text)) {
797
- return 'workflow_completion';
798
- }
799
- if (/\b(sample|seeded|non[-\s]?empty|kpi|table|chart|record|row)\b/.test(text)) {
800
- return 'non_empty_data';
801
- }
802
- if (/\b(empty|error|recovery|invalid)\b/.test(text)) {
803
- return 'recovery';
804
- }
805
- if (/\b(hub|dashboard|command center|next up|queue)\b/.test(text)) {
806
- return 'hub_action';
807
- }
808
- return 'business_workflow';
809
- }
810
-
811
- function normalizeWorkflowQaCoverageTag(value: any): string {
812
- const normalized = cleanText(value, 120).toLowerCase().replace(/[^a-z0-9]+/g, '_').replace(/^_+|_+$/g, '');
813
- if (!normalized) {
814
- return '';
815
- }
816
- const aliases: Record<string, string> = {
817
- auth: 'login',
818
- authentication: 'login',
819
- authenticated_session: 'login',
820
- signed_in: 'login',
821
- dashboard: 'hub_action',
822
- dashboard_hub: 'hub_action',
823
- hub: 'hub_action',
824
- primary_hub_action: 'hub_action',
825
- command_center: 'hub_action',
826
- embedded_hub_action: 'hub_action',
827
- completion: 'workflow_completion',
828
- business_completion: 'workflow_completion',
829
- final_result: 'workflow_completion',
830
- result: 'workflow_completion',
831
- saved_result: 'workflow_completion',
832
- saved_output: 'workflow_completion',
833
- calculated_result: 'workflow_completion',
834
- export: 'report_export',
835
- report: 'report_export',
836
- pdf_export: 'report_export',
837
- report_download: 'report_export',
838
- sample_data: 'non_empty_data',
839
- seed_data: 'non_empty_data',
840
- seeded_data: 'non_empty_data',
841
- non_empty: 'non_empty_data',
842
- nonempty: 'non_empty_data',
843
- kpi_data: 'non_empty_data',
844
- responsive: 'mobile',
845
- responsive_mobile: 'mobile',
846
- mobile_viewport: 'mobile',
847
- phone: 'mobile',
848
- empty_state: 'recovery',
849
- error_state: 'recovery',
850
- error_recovery: 'recovery',
851
- empty_error_recovery: 'recovery',
852
- invalid_input_recovery: 'recovery'
853
- };
854
- return aliases[normalized] || normalized;
855
- }
856
-
857
- function appendWorkflowQaCoverageValues(target: string[], value: any): void {
858
- if (Array.isArray(value)) {
859
- value.forEach((entry) => appendWorkflowQaCoverageValues(target, entry));
860
- return;
861
- }
862
- if (value && typeof value === 'object') {
863
- for (const [key, entry] of Object.entries(value)) {
864
- if (entry === true) {
865
- target.push(normalizeWorkflowQaCoverageTag(key));
866
- }
867
- else if (typeof entry === 'string' || Array.isArray(entry) || (entry && typeof entry === 'object')) {
868
- appendWorkflowQaCoverageValues(target, entry);
869
- }
870
- }
871
- return;
872
- }
873
- const text = cleanText(value, 500);
874
- if (!text) {
875
- return;
876
- }
877
- for (const entry of text.split(/[|,;]/)) {
878
- target.push(normalizeWorkflowQaCoverageTag(entry));
879
- }
880
- }
881
-
882
- function normalizeWorkflowQaCoverageTags(source: any, options: { includeProofKind?: boolean } = {}): string[] {
883
- const tags: string[] = [];
884
- for (const key of [
885
- 'coverage',
886
- 'coverage_tags',
887
- 'coverageTags',
888
- 'qa_coverage',
889
- 'qaCoverage',
890
- 'required_coverage',
891
- 'requiredCoverage',
892
- 'business_coverage',
893
- 'businessCoverage'
894
- ]) {
895
- appendWorkflowQaCoverageValues(tags, readField(source, [key]));
896
- }
897
- if (options.includeProofKind !== false) {
898
- for (const key of ['proof_kind', 'proofKind', 'proof_kinds', 'proofKinds']) {
899
- appendWorkflowQaCoverageValues(tags, readField(source, [key]));
900
- }
901
- }
902
- return Array.from(new Set(tags.filter(Boolean))).slice(0, 20);
903
- }
904
-
905
- function buildWorkflowQaRequiredArtifacts(source: any, proofKind: string): string[] {
906
- const explicit = cleanList(readField(source, ['required_artifacts', 'requiredArtifacts', 'proof_artifacts', 'artifact_expectation', 'artifacts_required']), 12, 180);
907
- const defaultsByKind: Record<string, string[]> = {
908
- login: ['authenticated session proof', 'post-login hub route proof'],
909
- hub_action: ['hub screenshot or DOM snapshot', 'next action state proof'],
910
- workflow_completion: ['before/action/after trace', 'saved or calculated output proof', 'business assertion artifact'],
911
- report_export: ['generated report/export artifact', 'export control proof', 'saved output row proof'],
912
- non_empty_data: ['seeded data snapshot', 'non-empty KPI/table/chart proof'],
913
- mobile: ['mobile viewport screenshot or trace', 'responsive workflow action proof'],
914
- recovery: ['empty/error state screenshot or trace', 'recovery action proof'],
915
- business_workflow: ['browser trace or screenshot', 'DOM/data assertion artifact']
916
- };
917
- return Array.from(new Set([
918
- ...explicit,
919
- ...(defaultsByKind[proofKind] || defaultsByKind.business_workflow)
920
- ])).slice(0, 16);
921
- }
922
-
923
- function buildWorkflowQaStateTransition(source: any, fallback: Partial<ResolveIOAICoderV6WorkflowQaRow> = {}): ResolveIOAICoderV6WorkflowQaRow['stateTransition'] {
924
- return {
925
- before: cleanField(source, ['before', 'setup_state', 'initial_state'], 700) || fallback.expectedState,
926
- action: cleanField(source, ['action', 'browser_steps', 'visible_cta', 'cta'], 700) || fallback.action,
927
- after: cleanField(source, ['after', 'expected_state', 'expected_result', 'expected_dom_or_data_proof', 'proof'], 700) || fallback.assertion || fallback.expectedState,
928
- assertion: cleanField(source, ['assertion', 'expected_dom_or_data_proof', 'proof', 'expected_result'], 700) || fallback.assertion
929
- };
930
- }
931
-
932
- export function buildResolveIOAICoderWorkflowQaRowsFromJourneyContract(input: any): ResolveIOAICoderV6WorkflowQaRow[] {
933
- const contract = typeof input === 'string'
934
- ? extractResolveIOAICoderJourneyContractFromMarkdown(input)
935
- : (input && typeof input === 'object' && !Array.isArray(input) ? input : null);
936
- if (!contract) {
937
- return [];
938
- }
939
- const workflowId = cleanField(contract, ['primary_workflow_id', 'workflow_id', 'id'], 160) || 'north-star';
940
- const rows: ResolveIOAICoderV6WorkflowQaRow[] = [];
941
- const qaAssertions = asArray(contract.qa_assertions);
942
- qaAssertions.forEach((assertion, index) => {
943
- if (!assertion || typeof assertion !== 'object' || Array.isArray(assertion)) {
944
- return;
945
- }
946
- const route = cleanField(assertion, ['route', 'screen_route', 'path'], 240);
947
- const action = cleanField(assertion, ['action', 'browser_steps', 'cta', 'visible_cta'], 500);
948
- const expectedState = cleanField(assertion, ['expected_state', 'expected_result', 'expected_dom_or_data_proof', 'proof'], 500);
949
- const assertionText = cleanField(assertion, ['assertion', 'expected_dom_or_data_proof', 'proof', 'expected_result'], 700);
950
- if (!route && !action && !assertionText) {
951
- return;
952
- }
953
- const proofKind = normalizeWorkflowProofKind(assertion);
954
- const coverageTags = normalizeWorkflowQaCoverageTags(assertion);
955
- const rowBase = {
956
- route: route || undefined,
957
- action: action || undefined,
958
- assertion: assertionText || undefined,
959
- expectedState: expectedState || undefined
960
- };
961
- rows.push({
962
- index: cleanNumber(readField(assertion, ['index', 'order'])) || index + 1,
963
- workflowId: cleanField(assertion, ['workflow_id', 'workflowId'], 160) || workflowId,
964
- workflowStepId: cleanField(assertion, [
965
- 'workflow_step_id',
966
- 'workflowStepId',
967
- 'covers_workflow_step_id',
968
- 'coversWorkflowStepId',
969
- 'north_star_step_id',
970
- 'northStarStepId'
971
- ], 160) || undefined,
972
- workflowStepIds: collectJourneyReferenceKeys(assertion),
973
- stepId: cleanField(assertion, ['step_id', 'stepId', 'id'], 160) || `qa-${index + 1}`,
974
- ...rowBase,
975
- expectedOutput: cleanField(assertion, ['expected_output', 'expectedOutput', 'saved_output', 'calculated_output', 'report_output'], 700) || expectedState || assertionText || undefined,
976
- proofKind,
977
- coverageTags,
978
- acceptanceGate: 'aiqa_business_assertion',
979
- requiredArtifacts: buildWorkflowQaRequiredArtifacts(assertion, proofKind),
980
- stateTransition: buildWorkflowQaStateTransition(assertion, rowBase),
981
- status: cleanField(assertion, ['status'], 120) || undefined,
982
- artifactPaths: cleanList(readField(assertion, ['artifact_paths', 'artifactPaths']), 20, 500)
983
- });
984
- });
985
- if (rows.length) {
986
- return rows.slice(0, 80);
987
- }
988
- asArray(contract.north_star_workflow).forEach((step, index, workflow) => {
989
- if (!step || typeof step !== 'object' || Array.isArray(step)) {
990
- return;
991
- }
992
- const proofKind = normalizeWorkflowProofKind(step, normalizeWorkflowStepPosition(step, index, workflow.length));
993
- const rowBase = {
994
- route: cleanField(step, ['route'], 240) || undefined,
995
- action: cleanField(step, ['visible_cta', 'action', 'cta'], 500) || undefined,
996
- assertion: cleanField(step, ['success_confirmation', 'expected_state_transition', 'final_result'], 700) || undefined,
997
- expectedState: cleanField(step, ['expected_state_transition', 'success_confirmation', 'final_result'], 500) || undefined
998
- };
999
- rows.push({
1000
- index: index + 1,
1001
- workflowId,
1002
- workflowStepId: buildWorkflowStepId(step, index),
1003
- workflowStepIds: [buildWorkflowStepId(step, index)],
1004
- stepId: buildWorkflowStepId(step, index),
1005
- ...rowBase,
1006
- expectedOutput: cleanField(step, ['final_result', 'saved_exported_reported_result', 'completion_result', 'expected_state_transition'], 700) || rowBase.expectedState || rowBase.assertion,
1007
- proofKind,
1008
- coverageTags: Array.from(new Set([proofKind, normalizeWorkflowStepPosition(step, index, workflow.length)].map(normalizeWorkflowQaCoverageTag).filter(Boolean))),
1009
- acceptanceGate: 'aiqa_business_assertion',
1010
- requiredArtifacts: buildWorkflowQaRequiredArtifacts(step, proofKind),
1011
- stateTransition: buildWorkflowQaStateTransition(step, rowBase),
1012
- status: undefined,
1013
- artifactPaths: []
1014
- });
1015
- void workflow;
1016
- });
1017
- return rows.slice(0, 80);
1018
- }
1019
-
1020
- export function validateResolveIOAICoderJourneyContract(input: any, options: {
1021
- pathLabel?: string;
1022
- requireMarkdownEnvelope?: boolean;
1023
- } = {}): ResolveIOAICoderJourneyContractValidationResult {
1024
- const pathLabel = cleanText(options.pathLabel || 'docs/APP_JOURNEY_CONTRACT.md', 240) || 'docs/APP_JOURNEY_CONTRACT.md';
1025
- const issues: ResolveIOAICoderJourneyContractValidationIssue[] = [];
1026
- let contract: Record<string, any> | null = null;
1027
- if (typeof input === 'string') {
1028
- const normalized = input.replace(/\r\n/g, '\n');
1029
- if (!normalized.trim()) {
1030
- addJourneyIssue(issues, 'missing_contract', pathLabel, `${pathLabel}: missing app journey contract.`);
1031
- return { valid: false, contract: null, issues, workflowQaRows: [], primaryWorkflowId: '' };
1032
- }
1033
- if (options.requireMarkdownEnvelope !== false && !/^\s*#\s+App Journey Contract/im.test(normalized)) {
1034
- addJourneyIssue(issues, 'missing_heading', pathLabel, `${pathLabel}: missing "# App Journey Contract" heading.`);
1035
- }
1036
- if (options.requireMarkdownEnvelope !== false && !/##\s*journey_contract/i.test(normalized)) {
1037
- addJourneyIssue(issues, 'missing_json_section', pathLabel, `${pathLabel}: missing "## journey_contract" JSON section.`);
1038
- }
1039
- if (looksPlaceholder(normalized)) {
1040
- addJourneyIssue(issues, 'placeholder_text', pathLabel, `${pathLabel}: contains placeholder or generic journey text.`);
1041
- }
1042
- contract = extractResolveIOAICoderJourneyContractFromMarkdown(normalized);
1043
- }
1044
- else if (input && typeof input === 'object' && !Array.isArray(input)) {
1045
- contract = input;
1046
- }
1047
- if (!contract) {
1048
- addJourneyIssue(issues, 'invalid_json', pathLabel, `${pathLabel}: journey_contract JSON is missing or invalid.`);
1049
- return { valid: false, contract: null, issues, workflowQaRows: [], primaryWorkflowId: '' };
1050
- }
1051
- const requiredKeys = [
1052
- 'app_archetype',
1053
- 'primary_actor',
1054
- 'primary_goal',
1055
- 'first_screen',
1056
- 'north_star_workflow',
1057
- 'secondary_workflows',
1058
- 'screen_sequence',
1059
- 'data_story',
1060
- 'completion_states',
1061
- 'qa_assertions'
1062
- ];
1063
- for (const key of requiredKeys) {
1064
- if (!(key in contract)) {
1065
- addJourneyIssue(issues, 'missing_key', `${pathLabel}.journey_contract.${key}`, `${pathLabel}: journey_contract missing key "${key}".`);
1066
- }
1067
- }
1068
- for (const key of ['app_archetype', 'primary_actor', 'primary_goal']) {
1069
- const value = cleanText(contract[key], 500);
1070
- if (value.length < 4) {
1071
- addJourneyIssue(issues, 'empty_core_field', `${pathLabel}.journey_contract.${key}`, `${pathLabel}: journey_contract.${key} must be non-empty.`);
1072
- }
1073
- if (looksPlaceholder(value)) {
1074
- addJourneyIssue(issues, 'placeholder_core_field', `${pathLabel}.journey_contract.${key}`, `${pathLabel}: journey_contract.${key} is placeholder text.`);
1075
- }
1076
- }
1077
- const firstScreen = contract.first_screen;
1078
- if (!firstScreen || typeof firstScreen !== 'object' || Array.isArray(firstScreen)) {
1079
- addJourneyIssue(issues, 'invalid_first_screen', `${pathLabel}.journey_contract.first_screen`, `${pathLabel}: first_screen must be an object.`);
1080
- }
1081
- else {
1082
- const route = cleanField(firstScreen, ['route'], 240);
1083
- for (const [label, keys] of [
1084
- ['route', ['route']],
1085
- ['purpose', ['purpose', 'screen_purpose']],
1086
- ['visible_cta', ['visible_cta', 'cta', 'primary_cta']],
1087
- ['next_step', ['next_step', 'next_step_destination', 'expected_next_state']]
1088
- ] as Array<[string, string[]]>) {
1089
- if (cleanField(firstScreen, keys, 500).length < 4) {
1090
- addJourneyIssue(issues, 'incomplete_first_screen', `${pathLabel}.journey_contract.first_screen.${label}`, `${pathLabel}: first_screen.${label} must be non-empty.`);
1091
- }
1092
- }
1093
- if (route && !looksLikeAbsoluteRoute(route)) {
1094
- addJourneyIssue(issues, 'relative_first_screen_route', `${pathLabel}.journey_contract.first_screen.route`, `${pathLabel}: first_screen.route must be an absolute app route.`);
1095
- }
1096
- }
1097
- const workflow = asArray(contract.north_star_workflow);
1098
- if (workflow.length < 3) {
1099
- addJourneyIssue(issues, 'workflow_too_short', `${pathLabel}.journey_contract.north_star_workflow`, `${pathLabel}: north_star_workflow must include at least first, next, and last steps.`);
1100
- }
1101
- const positions = new Set(workflow.map((step: any, index: number) => normalizeWorkflowStepPosition(step, index, workflow.length)));
1102
- for (const requiredPosition of ['first', 'next', 'last']) {
1103
- if (!positions.has(requiredPosition)) {
1104
- addJourneyIssue(issues, 'missing_workflow_position', `${pathLabel}.journey_contract.north_star_workflow`, `${pathLabel}: north_star_workflow missing position "${requiredPosition}".`);
1105
- }
1106
- }
1107
- workflow.forEach((step: any, index: number) => {
1108
- const stepPath = `${pathLabel}.journey_contract.north_star_workflow[${index}]`;
1109
- if (!step || typeof step !== 'object' || Array.isArray(step)) {
1110
- addJourneyIssue(issues, 'invalid_workflow_step', stepPath, `${pathLabel}: north_star_workflow[${index}] must be an object.`);
1111
- return;
1112
- }
1113
- const position = normalizeWorkflowStepPosition(step, index, workflow.length);
1114
- const route = cleanField(step, ['route'], 240);
1115
- const embeddedAction = cleanField(step, ['embedded_hub_action', 'hub_action'], 240);
1116
- const implementation = cleanField(step, [
1117
- 'method_or_calculation',
1118
- 'server_method_or_publication',
1119
- 'local_calculation_path',
1120
- 'action_implementation',
1121
- 'calculation_path',
1122
- 'data_mutation',
1123
- 'mutation',
1124
- 'persisted_result'
1125
- ], 500);
1126
- const requiredStepFields: Array<[string, string[]]> = [
1127
- ['position', ['position']],
1128
- ['visible_cta', ['visible_cta', 'cta', 'label']],
1129
- ['data_input_or_selection', ['data_input_or_selection', 'data_input', 'selection', 'input']],
1130
- ['expected_state_transition', ['expected_state_transition', 'expected_next_state', 'state_change']],
1131
- ['success_confirmation', ['success_confirmation', 'confirmation', 'success_message']],
1132
- ['next_step_destination', ['next_step_destination', 'next_step', 'destination']]
1133
- ];
1134
- for (const [fieldName, keys] of requiredStepFields) {
1135
- if (fieldName === 'next_step_destination' && position === 'last') {
1136
- continue;
1137
- }
1138
- if (cleanField(step, keys, 500).length < 3) {
1139
- addJourneyIssue(issues, 'incomplete_workflow_step', `${stepPath}.${fieldName}`, `${pathLabel}: north_star_workflow[${index}].${fieldName} must be non-empty.`);
1140
- }
1141
- }
1142
- if (!route && !embeddedAction) {
1143
- addJourneyIssue(issues, 'workflow_step_missing_route_or_hub_action', stepPath, `${pathLabel}: north_star_workflow[${index}] must specify a route or embedded hub action.`);
1144
- }
1145
- if (route && !looksLikeAbsoluteRoute(route)) {
1146
- addJourneyIssue(issues, 'relative_workflow_route', `${stepPath}.route`, `${pathLabel}: north_star_workflow[${index}].route must be an absolute app route.`);
1147
- }
1148
- if (!implementation) {
1149
- addJourneyIssue(issues, 'workflow_step_missing_implementation', stepPath, `${pathLabel}: north_star_workflow[${index}] must map the CTA to a server method, publication, local calculation, persisted mutation, or export/report action.`);
1150
- }
1151
- if (isNavigationOnlyAction(step)) {
1152
- addJourneyIssue(issues, 'navigation_only_workflow_step', stepPath, `${pathLabel}: north_star_workflow[${index}] appears to be navigation-only instead of advancing state.`);
1153
- }
1154
- if (position === 'last' && cleanField(step, ['final_result', 'saved_exported_reported_result', 'completion_result'], 700).length < 8) {
1155
- addJourneyIssue(issues, 'last_step_missing_final_result', `${stepPath}.final_result`, `${pathLabel}: last workflow step must define the saved, exported, reported, or calculated final result.`);
1156
- }
1157
- });
1158
- const secondaryWorkflows = asArray(contract.secondary_workflows);
1159
- if (secondaryWorkflows.length < 3) {
1160
- addJourneyIssue(issues, 'missing_secondary_workflows', `${pathLabel}.journey_contract.secondary_workflows`, `${pathLabel}: secondary_workflows must include setup, manage, report/export, settings/secrets, or recovery coverage.`);
1161
- }
1162
- const screenSequence = asArray(contract.screen_sequence);
1163
- if (screenSequence.length < Math.min(3, Math.max(workflow.length, 3))) {
1164
- addJourneyIssue(issues, 'screen_sequence_too_short', `${pathLabel}.journey_contract.screen_sequence`, `${pathLabel}: screen_sequence must map workflow steps to routes, CTAs, data, and next state.`);
1165
- }
1166
- screenSequence.forEach((screen: any, index: number) => {
1167
- const screenPath = `${pathLabel}.journey_contract.screen_sequence[${index}]`;
1168
- if (!screen || typeof screen !== 'object' || Array.isArray(screen)) {
1169
- addJourneyIssue(issues, 'invalid_screen_sequence_row', screenPath, `${pathLabel}: screen_sequence[${index}] must be an object.`);
1170
- return;
1171
- }
1172
- for (const [fieldName, keys] of [
1173
- ['route', ['route']],
1174
- ['screen_purpose', ['screen_purpose', 'purpose']],
1175
- ['visible_cta', ['visible_cta', 'cta']],
1176
- ['expected_next_state', ['expected_next_state', 'expected_state_transition']],
1177
- ['data_shown', ['data_shown', 'data', 'records_shown']]
1178
- ] as Array<[string, string[]]>) {
1179
- if (cleanField(screen, keys, 500).length < 3) {
1180
- addJourneyIssue(issues, 'incomplete_screen_sequence_row', `${screenPath}.${fieldName}`, `${pathLabel}: screen_sequence[${index}].${fieldName} must be non-empty.`);
1181
- }
1182
- }
1183
- const route = cleanField(screen, ['route'], 240);
1184
- if (route && !looksLikeAbsoluteRoute(route)) {
1185
- addJourneyIssue(issues, 'relative_screen_route', `${screenPath}.route`, `${pathLabel}: screen_sequence[${index}].route must be an absolute app route.`);
1186
- }
1187
- if (isNavigationOnlyAction(screen)) {
1188
- addJourneyIssue(issues, 'navigation_only_screen_action', screenPath, `${pathLabel}: screen_sequence[${index}] CTA appears to navigate without changing workflow state.`);
1189
- }
1190
- if (workflow.length && !workflow.some((step: any, workflowIndex: number) => journeySourceMapsToWorkflowStep(screen, step, workflowIndex))) {
1191
- addJourneyIssue(issues, 'screen_sequence_unmapped_to_workflow', screenPath, `${pathLabel}: screen_sequence[${index}] must reference a north_star_workflow step by workflow_step_id or match that step's route and CTA.`);
1192
- }
1193
- });
1194
- workflow.forEach((step: any, index: number) => {
1195
- if (!step || typeof step !== 'object' || Array.isArray(step)) {
1196
- return;
1197
- }
1198
- const stepPath = `${pathLabel}.journey_contract.north_star_workflow[${index}]`;
1199
- const matchingScreens = screenSequence.filter((screen: any) => journeySourceMapsToWorkflowStep(screen, step, index));
1200
- if (!matchingScreens.length) {
1201
- addJourneyIssue(issues, 'workflow_step_missing_screen_mapping', stepPath, `${pathLabel}: north_star_workflow[${index}] must have a matching screen_sequence row with the same step id or route/CTA mapping.`);
1202
- }
1203
- });
1204
- const firstScreenRoute = cleanField(firstScreen, ['route'], 240);
1205
- const hubScreens = screenSequence.filter((screen: any) => {
1206
- const route = cleanField(screen, ['route'], 240);
1207
- return route === firstScreenRoute || /hub|dashboard/i.test(route);
1208
- });
1209
- const hubHasEmbeddedAction = hubScreens.some((screen: any) => {
1210
- const text = [
1211
- cleanField(screen, ['embedded_action', 'hub_action', 'action'], 500),
1212
- cleanField(screen, ['method_or_calculation', 'server_method_or_publication', 'local_calculation_path', 'action_implementation'], 500),
1213
- cleanField(screen, ['expected_next_state', 'expected_state_transition'], 500)
1214
- ].join(' ');
1215
- return text.trim().length >= 8 && !isNavigationOnlyAction(screen);
1216
- });
1217
- if (!hubHasEmbeddedAction) {
1218
- addJourneyIssue(issues, 'hub_missing_embedded_action', `${pathLabel}.journey_contract.screen_sequence`, `${pathLabel}: dashboard hub/first screen must embed at least one primary workflow action instead of acting as a link farm.`);
1219
- }
1220
- const dataStory = contract.data_story;
1221
- if (!dataStory || typeof dataStory !== 'object' || Array.isArray(dataStory)) {
1222
- addJourneyIssue(issues, 'invalid_data_story', `${pathLabel}.journey_contract.data_story`, `${pathLabel}: data_story must be an object.`);
1223
- }
1224
- else {
1225
- if (cleanField(dataStory, ['seeded_scenario', 'scenario'], 800).length < 12) {
1226
- addJourneyIssue(issues, 'missing_seeded_scenario', `${pathLabel}.journey_contract.data_story.seeded_scenario`, `${pathLabel}: data_story.seeded_scenario must describe the launch sample scenario.`);
1227
- }
1228
- if (!asArray(readField(dataStory, ['records', 'seed_records'])).length) {
1229
- addJourneyIssue(issues, 'missing_seed_records', `${pathLabel}.journey_contract.data_story.records`, `${pathLabel}: data_story.records must list seeded records.`);
1230
- }
1231
- if (!asArray(readField(dataStory, ['relationships', 'record_relationships'])).length) {
1232
- addJourneyIssue(issues, 'missing_seed_relationships', `${pathLabel}.journey_contract.data_story.relationships`, `${pathLabel}: data_story.relationships must list seeded data relationships.`);
1233
- }
1234
- if (asArray(readField(dataStory, ['non_empty_states', 'non_empty_dashboard_states'])).length < 2) {
1235
- addJourneyIssue(issues, 'missing_non_empty_states', `${pathLabel}.journey_contract.data_story.non_empty_states`, `${pathLabel}: data_story.non_empty_states must list non-empty dashboard, workflow, or report states.`);
1236
- }
1237
- }
1238
- if (asArray(contract.completion_states).length < 2) {
1239
- addJourneyIssue(issues, 'missing_completion_states', `${pathLabel}.journey_contract.completion_states`, `${pathLabel}: completion_states must define what done looks like to the user.`);
1240
- }
1241
- const qaAssertions = asArray(contract.qa_assertions);
1242
- if (qaAssertions.length < 5) {
1243
- addJourneyIssue(issues, 'qa_assertions_too_short', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions must include login, hub action, workflow completion, sample data, and mobile proof.`);
1244
- }
1245
- const workflowStepsWithQa = new Set<string>();
1246
- let hasMobileQa = false;
1247
- let hasRecoveryQa = false;
1248
- let hasCompletionQa = false;
1249
- let hasNonEmptyQa = false;
1250
- let hasLoginQa = false;
1251
- let hasHubActionQa = false;
1252
- qaAssertions.forEach((assertion: any, index: number) => {
1253
- const qaPath = `${pathLabel}.journey_contract.qa_assertions[${index}]`;
1254
- if (!assertion || typeof assertion !== 'object' || Array.isArray(assertion)) {
1255
- addJourneyIssue(issues, 'invalid_qa_assertion', qaPath, `${pathLabel}: qa_assertions[${index}] must be an object.`);
1256
- return;
1257
- }
1258
- for (const [fieldName, keys] of [
1259
- ['route', ['route', 'screen_route', 'path']],
1260
- ['action', ['action', 'browser_steps', 'visible_cta']],
1261
- ['expected_dom_or_data_proof', ['expected_dom_or_data_proof', 'proof', 'expected_result']]
1262
- ] as Array<[string, string[]]>) {
1263
- if (cleanField(assertion, keys, 700).length < 3) {
1264
- addJourneyIssue(issues, 'incomplete_qa_assertion', `${qaPath}.${fieldName}`, `${pathLabel}: qa_assertions[${index}].${fieldName} must be non-empty.`);
1265
- }
1266
- }
1267
- const route = cleanField(assertion, ['route', 'screen_route', 'path'], 240);
1268
- if (route && !looksLikeAbsoluteRoute(route)) {
1269
- addJourneyIssue(issues, 'relative_qa_route', `${qaPath}.route`, `${pathLabel}: qa_assertions[${index}].route must be an absolute app route.`);
1270
- }
1271
- const explicitCoverageTags = normalizeWorkflowQaCoverageTags(assertion, { includeProofKind: false });
1272
- const coverageTags = normalizeWorkflowQaCoverageTags(assertion);
1273
- if (!explicitCoverageTags.length) {
1274
- addJourneyIssue(issues, 'qa_assertion_missing_structured_coverage', `${qaPath}.coverage_tags`, `${pathLabel}: qa_assertions[${index}] must declare coverage_tags such as login, hub_action, workflow_completion, non_empty_data, mobile, or recovery; prose-only keyword detection is not accepted.`);
1275
- }
1276
- hasLoginQa = hasLoginQa || coverageTags.includes('login');
1277
- hasHubActionQa = hasHubActionQa || coverageTags.includes('hub_action');
1278
- hasMobileQa = hasMobileQa || coverageTags.includes('mobile');
1279
- hasRecoveryQa = hasRecoveryQa || coverageTags.includes('recovery');
1280
- hasCompletionQa = hasCompletionQa || coverageTags.includes('workflow_completion');
1281
- hasNonEmptyQa = hasNonEmptyQa || coverageTags.includes('non_empty_data');
1282
- const mappedWorkflowStepIds = workflow
1283
- .map((step: any, workflowIndex: number) => journeySourceMapsToWorkflowStep(assertion, step, workflowIndex) ? buildWorkflowStepId(step, workflowIndex) : '')
1284
- .filter(Boolean);
1285
- mappedWorkflowStepIds.forEach((stepId: string) => workflowStepsWithQa.add(stepId));
1286
- if (workflow.length && !mappedWorkflowStepIds.length) {
1287
- addJourneyIssue(issues, 'qa_assertion_unmapped_to_workflow', qaPath, `${pathLabel}: qa_assertions[${index}] must reference a north_star_workflow step by workflow_step_id/covers_workflow_step_ids or match that step's route and CTA/action.`);
1288
- }
1289
- });
1290
- if (!hasLoginQa) {
1291
- addJourneyIssue(issues, 'missing_login_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing structured login coverage.`);
1292
- }
1293
- if (!hasHubActionQa) {
1294
- addJourneyIssue(issues, 'missing_hub_action_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing structured dashboard hub action coverage.`);
1295
- }
1296
- if (!hasCompletionQa) {
1297
- addJourneyIssue(issues, 'missing_completion_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing business completion proof.`);
1298
- }
1299
- if (!hasNonEmptyQa) {
1300
- addJourneyIssue(issues, 'missing_non_empty_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing non-empty seeded data proof.`);
1301
- }
1302
- if (!hasMobileQa) {
1303
- addJourneyIssue(issues, 'missing_mobile_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing mobile viewport proof.`);
1304
- }
1305
- if (!hasRecoveryQa) {
1306
- addJourneyIssue(issues, 'missing_recovery_qa', `${pathLabel}.journey_contract.qa_assertions`, `${pathLabel}: qa_assertions missing empty/error recovery proof.`);
1307
- }
1308
- workflow.forEach((step: any, index: number) => {
1309
- if (!step || typeof step !== 'object' || Array.isArray(step)) {
1310
- return;
1311
- }
1312
- const stepId = buildWorkflowStepId(step, index);
1313
- if (!workflowStepsWithQa.has(stepId)) {
1314
- addJourneyIssue(issues, 'workflow_step_missing_qa_assertion', `${pathLabel}.journey_contract.north_star_workflow[${index}]`, `${pathLabel}: north_star_workflow[${index}] must be covered by at least one qa_assertions row using workflow_step_id/covers_workflow_step_ids or matching route/CTA.`);
1315
- }
1316
- });
1317
- const workflowQaRows = buildResolveIOAICoderWorkflowQaRowsFromJourneyContract(contract);
1318
- return {
1319
- valid: !issues.some((issue) => issue.severity === 'error'),
1320
- contract,
1321
- issues,
1322
- workflowQaRows,
1323
- primaryWorkflowId: cleanField(contract, ['primary_workflow_id', 'workflow_id', 'id'], 160) || 'north-star'
1324
- };
1325
- }
1326
-
1327
- export function collectResolveIOAICoderJourneyContractIssues(input: any, options: {
1328
- pathLabel?: string;
1329
- requireMarkdownEnvelope?: boolean;
1330
- } = {}): string[] {
1331
- return validateResolveIOAICoderJourneyContract(input, options).issues.map((issue) => issue.message);
1332
- }
1333
-
1334
- function cleanNumber(value: any): number {
1335
- const parsed = Number(value);
1336
- return Number.isFinite(parsed) && parsed > 0 ? Math.floor(parsed) : 0;
1337
- }
1338
-
1339
- function cleanWorkflowQaRows(values: any, limit = 40): ResolveIOAICoderV6WorkflowQaRow[] {
1340
- if (!Array.isArray(values)) {
1341
- return [];
1342
- }
1343
- const rows: ResolveIOAICoderV6WorkflowQaRow[] = [];
1344
- for (const value of values) {
1345
- if (!value || typeof value !== 'object') {
1346
- continue;
1347
- }
1348
- const row: ResolveIOAICoderV6WorkflowQaRow = {
1349
- index: cleanNumber((value as any).index) || undefined,
1350
- workflowId: cleanText((value as any).workflowId || (value as any).workflow_id, 160) || undefined,
1351
- workflowStepId: cleanText((value as any).workflowStepId || (value as any).workflow_step_id, 160) || undefined,
1352
- workflowStepIds: cleanList((value as any).workflowStepIds || (value as any).workflow_step_ids, 20, 160),
1353
- stepId: cleanText((value as any).stepId || (value as any).step_id, 160) || undefined,
1354
- route: cleanText((value as any).route, 240) || undefined,
1355
- action: cleanText((value as any).action, 500) || undefined,
1356
- assertion: cleanText((value as any).assertion, 700) || undefined,
1357
- expectedState: cleanText((value as any).expectedState || (value as any).expected_state, 500) || undefined,
1358
- expectedOutput: cleanText((value as any).expectedOutput || (value as any).expected_output, 700) || undefined,
1359
- proofKind: cleanText((value as any).proofKind || (value as any).proof_kind, 120) || undefined,
1360
- coverageTags: normalizeWorkflowQaCoverageTags(value),
1361
- acceptanceGate: ((value as any).acceptanceGate || (value as any).acceptance_gate) === 'aiqa_business_assertion'
1362
- ? 'aiqa_business_assertion'
1363
- : undefined,
1364
- requiredArtifacts: cleanList((value as any).requiredArtifacts || (value as any).required_artifacts, 20, 180),
1365
- stateTransition: (value as any).stateTransition || (value as any).state_transition
1366
- ? {
1367
- before: cleanText(((value as any).stateTransition || (value as any).state_transition).before, 700) || undefined,
1368
- action: cleanText(((value as any).stateTransition || (value as any).state_transition).action, 700) || undefined,
1369
- after: cleanText(((value as any).stateTransition || (value as any).state_transition).after, 700) || undefined,
1370
- assertion: cleanText(((value as any).stateTransition || (value as any).state_transition).assertion, 700) || undefined
1371
- }
1372
- : undefined,
1373
- status: cleanText((value as any).status, 120) || undefined,
1374
- artifactPaths: cleanList((value as any).artifactPaths || (value as any).artifact_paths, 20, 500)
1375
- };
1376
- if (row.workflowId || row.stepId || row.route || row.action || row.assertion) {
1377
- rows.push(row);
1378
- }
1379
- if (rows.length >= limit) {
1380
- break;
1381
- }
1382
- }
1383
- return rows;
1384
- }
1385
-
1386
- function statusLooksPassed(value: any): boolean {
1387
- const normalized = cleanText(value, 120).toLowerCase();
1388
- return !!normalized && /\b(pass|passed|success|succeeded|ok|done|complete|completed|ready|saved|published|deployed)\b/i.test(normalized);
1389
- }
1390
-
1391
- function statusLooksFailed(value: any): boolean {
1392
- const normalized = cleanText(value, 160).toLowerCase();
1393
- return !!normalized && /\b(fail|failed|error|blocked|missing|empty|stale|skipped|not ready|not_ready|cannot|could not|invalid)\b/i.test(normalized);
1394
- }
1395
-
1396
- function normalizeProofKey(value: any): string {
1397
- return cleanText(value, 500).toLowerCase().replace(/[^a-z0-9]+/g, ' ').replace(/\s+/g, ' ').trim();
1398
- }
1399
-
1400
- function cleanAssertionArtifactPaths(value: Record<string, any>): string[] {
1401
- return cleanList(
1402
- value.artifactPaths
1403
- || value.artifact_paths
1404
- || value.artifacts
1405
- || value.screenshots
1406
- || (value.screenshot ? [value.screenshot] : []),
1407
- 20,
1408
- 500
1409
- );
1410
- }
1411
-
1412
- function normalizeWorkflowProofAssertion(value: any): Record<string, any> {
1413
- const source = value && typeof value === 'object' && !Array.isArray(value) ? value : {};
1414
- return {
1415
- assertion: cleanText(source.assertion || source.name || source.label || source.expected, 1000),
1416
- status: cleanText(source.status || source.outcome || source.result || (source.passed === true ? 'pass' : source.passed === false ? 'fail' : ''), 120),
1417
- workflowId: cleanText(source.workflowId || source.workflow_id || source.workflow || source.workflowName || source.workflow_name, 200),
1418
- stepId: cleanText(source.stepId || source.step_id || source.id || source.key, 200),
1419
- route: cleanText(source.route || source.path || source.url, 500),
1420
- action: cleanText(source.action || source.browser_steps || source.action_under_test || source.actionUnderTest, 800),
1421
- expected: cleanText(source.expected || source.expected_state || source.expectedState || source.expected_business_state_change || source.expectedBusinessStateChange, 1000),
1422
- observed: cleanText(source.observed || source.actual || source.after || source.after_state || source.afterState, 1000),
1423
- dataProof: cleanText(source.dataProof || source.data_proof || source.domProof || source.dom_proof || source.proof || source.summary, 1400),
1424
- artifactPaths: cleanAssertionArtifactPaths(source),
1425
- metadata: source.metadata && typeof source.metadata === 'object' && !Array.isArray(source.metadata) ? source.metadata : {}
1426
- };
1427
- }
1428
-
1429
- function workflowRowKey(row: ResolveIOAICoderV6WorkflowQaRow, index: number): string {
1430
- return cleanText(row.stepId || row.assertion || row.action || row.route || `workflow-row-${index + 1}`, 200);
1431
- }
1432
-
1433
- function sameWorkflowRow(left: ResolveIOAICoderV6WorkflowQaRow, right: ResolveIOAICoderV6WorkflowQaRow): boolean {
1434
- const leftStep = normalizeProofKey(left.stepId);
1435
- const rightStep = normalizeProofKey(right.stepId);
1436
- if (leftStep && rightStep && leftStep === rightStep) {
1437
- return true;
1438
- }
1439
- const leftRoute = normalizeProofKey(left.route);
1440
- const rightRoute = normalizeProofKey(right.route);
1441
- const leftAction = normalizeProofKey(left.action || left.assertion);
1442
- const rightAction = normalizeProofKey(right.action || right.assertion);
1443
- return !!leftRoute && !!rightRoute && leftRoute === rightRoute && !!leftAction && !!rightAction && (leftAction.includes(rightAction) || rightAction.includes(leftAction));
1444
- }
1445
-
1446
- function mergeWorkflowQaRows(
1447
- contractRows: ResolveIOAICoderV6WorkflowQaRow[],
1448
- recordedRows: ResolveIOAICoderV6WorkflowQaRow[]
1449
- ): ResolveIOAICoderV6WorkflowQaRow[] {
1450
- if (!contractRows.length) {
1451
- return recordedRows;
1452
- }
1453
- return contractRows.map((contractRow) => {
1454
- const recorded = recordedRows.find((row) => sameWorkflowRow(contractRow, row));
1455
- if (!recorded) {
1456
- return contractRow;
1457
- }
1458
- return {
1459
- ...contractRow,
1460
- ...recorded,
1461
- workflowId: recorded.workflowId || contractRow.workflowId,
1462
- stepId: recorded.stepId || contractRow.stepId,
1463
- route: recorded.route || contractRow.route,
1464
- action: recorded.action || contractRow.action,
1465
- assertion: recorded.assertion || contractRow.assertion,
1466
- expectedState: recorded.expectedState || contractRow.expectedState,
1467
- expectedOutput: recorded.expectedOutput || contractRow.expectedOutput,
1468
- proofKind: recorded.proofKind || contractRow.proofKind,
1469
- coverageTags: Array.from(new Set([
1470
- ...cleanList(contractRow.coverageTags, 20, 120),
1471
- ...cleanList(recorded.coverageTags, 20, 120)
1472
- ])),
1473
- acceptanceGate: recorded.acceptanceGate || contractRow.acceptanceGate,
1474
- requiredArtifacts: Array.from(new Set([
1475
- ...cleanList(contractRow.requiredArtifacts, 20, 180),
1476
- ...cleanList(recorded.requiredArtifacts, 20, 180)
1477
- ])),
1478
- stateTransition: recorded.stateTransition || contractRow.stateTransition,
1479
- artifactPaths: Array.from(new Set([
1480
- ...cleanList(contractRow.artifactPaths, 20, 500),
1481
- ...cleanList(recorded.artifactPaths, 20, 500)
1482
- ]))
1483
- };
1484
- });
1485
- }
1486
-
1487
- function assertionMatchesWorkflowRow(assertion: Record<string, any>, row: ResolveIOAICoderV6WorkflowQaRow): boolean {
1488
- const metadata = assertion.metadata || {};
1489
- if (metadata.workflowQaRowMatched === true || metadata.journeyContractMatched === true || metadata.aicoderWorkflowProof === true) {
1490
- return true;
1491
- }
1492
- const rowStep = normalizeProofKey(row.stepId);
1493
- const assertionStep = normalizeProofKey(assertion.stepId || metadata.stepId || metadata.step_id);
1494
- if (rowStep && assertionStep && rowStep === assertionStep) {
1495
- return true;
1496
- }
1497
- const rowRoute = normalizeProofKey(row.route);
1498
- const assertionRoute = normalizeProofKey(assertion.route);
1499
- const rowAction = normalizeProofKey(row.action || row.assertion);
1500
- const assertionAction = normalizeProofKey([
1501
- assertion.action,
1502
- assertion.assertion,
1503
- assertion.expected,
1504
- assertion.observed,
1505
- assertion.dataProof
1506
- ].filter(Boolean).join(' '));
1507
- return !!rowRoute
1508
- && !!assertionRoute
1509
- && rowRoute === assertionRoute
1510
- && !!rowAction
1511
- && !!assertionAction
1512
- && (assertionAction.includes(rowAction) || rowAction.includes(assertionAction));
1513
- }
1514
-
1515
- function workflowRowPassingAssertion(row: ResolveIOAICoderV6WorkflowQaRow, assertions: Record<string, any>[]): Record<string, any> | undefined {
1516
- return assertions.find((assertion) => statusLooksPassed(assertion.status) && assertionMatchesWorkflowRow(assertion, row));
1517
- }
1518
-
1519
- function workflowAssertionHasObservedOutputProof(assertion: Record<string, any> | undefined): boolean {
1520
- if (!assertion) {
1521
- return false;
1522
- }
1523
- return cleanText(assertion.dataProof, 1000).length >= 8
1524
- || cleanText(assertion.observed, 1000).length >= 8;
1525
- }
1526
-
1527
- function workflowRowArtifactPaths(row: ResolveIOAICoderV6WorkflowQaRow, assertion?: Record<string, any>): string[] {
1528
- return Array.from(new Set([
1529
- ...cleanList(row.artifactPaths, 20, 500),
1530
- ...cleanList(assertion?.artifactPaths, 20, 500)
1531
- ]));
1532
- }
1533
-
1534
- function workflowRowRequiresOutputProof(row: ResolveIOAICoderV6WorkflowQaRow): boolean {
1535
- const proofKind = cleanText(row.proofKind, 120).toLowerCase();
1536
- if (/^(workflow_completion|report_export|non_empty_data|hub_action|business_workflow)$/.test(proofKind)) {
1537
- return true;
1538
- }
1539
- const text = cleanText([
1540
- row.expectedOutput,
1541
- row.expectedState,
1542
- row.assertion,
1543
- row.stateTransition?.after,
1544
- row.stateTransition?.assertion
1545
- ].filter(Boolean).join(' '), 1600).toLowerCase();
1546
- return /\b(save|saved|persist|calculated|optimized|recommendation|report|export|result|non[-\s]?empty|record|row|kpi|table|chart)\b/.test(text);
1547
- }
1548
-
1549
- function workflowRowRequiresMappedBusinessAssertion(row: ResolveIOAICoderV6WorkflowQaRow): boolean {
1550
- const proofKind = cleanText(row.proofKind, 120).toLowerCase();
1551
- if (/^(workflow_completion|report_export)$/.test(proofKind)) {
1552
- return true;
1553
- }
1554
- if (/^(mobile|recovery|hub_action|non_empty_data)$/.test(proofKind)) {
1555
- return false;
1556
- }
1557
- const text = cleanText([
1558
- row.stepId,
1559
- row.expectedOutput,
1560
- row.expectedState,
1561
- row.assertion,
1562
- row.stateTransition?.after
1563
- ].filter(Boolean).join(' '), 1600).toLowerCase();
1564
- return /\b(workflow[-_\s]?completion|save|saved|persist|calculated|optimized|recommendation|report|export|final result)\b/.test(text);
1565
- }
1566
-
1567
- function workflowRowWeakProofReason(row: ResolveIOAICoderV6WorkflowQaRow, assertions: Record<string, any>[]): string {
1568
- const assertion = workflowRowPassingAssertion(row, assertions);
1569
- const rowPassed = statusLooksPassed(row.status);
1570
- if (!rowPassed && !assertion) {
1571
- return '';
1572
- }
1573
- const artifactPaths = workflowRowArtifactPaths(row, assertion);
1574
- const requiredArtifacts = cleanList(row.requiredArtifacts, 20, 180);
1575
- if (requiredArtifacts.length && !artifactPaths.length) {
1576
- return `${workflowRowKey(row, 0)} missing required artifact proof: ${requiredArtifacts.slice(0, 3).join(', ')}`;
1577
- }
1578
- if (row.acceptanceGate === 'aiqa_business_assertion' && workflowRowRequiresMappedBusinessAssertion(row) && !assertion) {
1579
- return `${workflowRowKey(row, 0)} requires mapped AIQaBusinessAssertion proof.`;
1580
- }
1581
- if (workflowRowRequiresOutputProof(row) && !workflowAssertionHasObservedOutputProof(assertion)) {
1582
- return `${workflowRowKey(row, 0)} missing observed DOM/data proof for the saved/calculated/report output.`;
1583
- }
1584
- return '';
1585
- }
1586
-
1587
- function workflowRowHasProof(row: ResolveIOAICoderV6WorkflowQaRow, assertions: Record<string, any>[]): boolean {
1588
- if (workflowRowWeakProofReason(row, assertions)) {
1589
- return false;
1590
- }
1591
- if (statusLooksPassed(row.status) && cleanList(row.artifactPaths, 20, 500).length) {
1592
- return true;
1593
- }
1594
- return !!workflowRowPassingAssertion(row, assertions);
1595
- }
1596
-
1597
- function workflowRowFailed(row: ResolveIOAICoderV6WorkflowQaRow, assertions: Record<string, any>[]): boolean {
1598
- if (statusLooksFailed(row.status)) {
1599
- return true;
1600
- }
1601
- return assertions.some((assertion) => statusLooksFailed(assertion.status) && assertionMatchesWorkflowRow(assertion, row));
1602
- }
1603
-
1604
- function collectContractArtifactPaths(
1605
- rows: ResolveIOAICoderV6WorkflowQaRow[],
1606
- assertions: Record<string, any>[],
1607
- extraPaths: any
1608
- ): string[] {
1609
- return Array.from(new Set([
1610
- ...cleanList(extraPaths, 40, 500),
1611
- ...rows.flatMap((row) => cleanList(row.artifactPaths, 20, 500)),
1612
- ...assertions.flatMap((assertion) => cleanList(assertion.artifactPaths, 20, 500))
1613
- ])).slice(0, 80);
1614
- }
1615
-
1616
- function stableProofValue(value: any): any {
1617
- if (Array.isArray(value)) {
1618
- return value.map(stableProofValue);
1619
- }
1620
- if (value && typeof value === 'object') {
1621
- return Object.keys(value)
1622
- .sort()
1623
- .reduce((accumulator, key) => {
1624
- const cleanKey = cleanText(key, 120);
1625
- if (!cleanKey || /^(evaluatedAt|recordedAt|createdAt|updatedAt|timestamp|durationMs)$/i.test(cleanKey)) {
1626
- return accumulator;
1627
- }
1628
- const nextValue = stableProofValue(value[key]);
1629
- if (nextValue !== undefined && nextValue !== '' && !(Array.isArray(nextValue) && !nextValue.length)) {
1630
- accumulator[cleanKey] = nextValue;
1631
- }
1632
- return accumulator;
1633
- }, {} as Record<string, any>);
1634
- }
1635
- if (typeof value === 'number') {
1636
- return Number.isFinite(value) ? value : undefined;
1637
- }
1638
- if (typeof value === 'boolean') {
1639
- return value;
1640
- }
1641
- return cleanText(value, 2000);
1642
- }
1643
-
1644
- function fingerprintResolveIOAICoderWorkflowProofPayload(value: any, prefix: string): string {
1645
- const text = JSON.stringify(stableProofValue(value));
1646
- let hash = 0;
1647
- for (let index = 0; index < text.length; index += 1) {
1648
- hash = ((hash << 5) - hash + text.charCodeAt(index)) | 0;
1649
- }
1650
- return `${prefix}-${Math.abs(hash).toString(36)}`;
1651
- }
1652
-
1653
- function normalizeWorkflowProofFingerprintList(...values: any[]): string[] {
1654
- const fingerprints: string[] = [];
1655
- for (const value of values) {
1656
- const list = Array.isArray(value) ? value : value ? [value] : [];
1657
- for (const entry of list) {
1658
- const normalized = cleanText(entry, 200);
1659
- if (normalized && !fingerprints.includes(normalized)) {
1660
- fingerprints.push(normalized);
1661
- }
1662
- }
1663
- }
1664
- return fingerprints.slice(0, 40);
1665
- }
1666
-
1667
- export function evaluateResolveIOAICoderWorkflowProofReadiness(
1668
- input: ResolveIOAICoderWorkflowProofReadinessInput = {}
1669
- ): ResolveIOAICoderWorkflowProofReadiness {
1670
- const now = isoNow(input.now);
1671
- const journeyInput = input.journeyContract !== undefined ? input.journeyContract : input.journeyContractMarkdown;
1672
- const hasJourneyInput = journeyInput !== undefined && journeyInput !== null && cleanText(journeyInput, 100).length > 0;
1673
- const journeyValidation = hasJourneyInput
1674
- ? validateResolveIOAICoderJourneyContract(journeyInput, {
1675
- requireMarkdownEnvelope: typeof journeyInput === 'string'
1676
- })
1677
- : {
1678
- valid: false,
1679
- contract: null,
1680
- issues: [{
1681
- code: 'missing_contract',
1682
- path: 'docs/APP_JOURNEY_CONTRACT.md',
1683
- message: 'docs/APP_JOURNEY_CONTRACT.md is required before workflow proof can accept the app.',
1684
- severity: 'error' as const
1685
- }],
1686
- workflowQaRows: [],
1687
- primaryWorkflowId: ''
1688
- };
1689
- const recordedRows = cleanWorkflowQaRows(input.workflowQaRows, 120);
1690
- const rows = mergeWorkflowQaRows(journeyValidation.workflowQaRows, recordedRows);
1691
- const assertions = asArray(input.businessAssertions).map(normalizeWorkflowProofAssertion).filter((assertion) => {
1692
- return assertion.assertion || assertion.route || assertion.action || assertion.dataProof || assertion.status;
1693
- });
1694
- const routeOnly = asArray(input.routeProbes).some((probe) => statusLooksPassed((probe as any)?.status || ((probe as any)?.passed === true ? 'pass' : '')))
1695
- && !assertions.some((assertion) => statusLooksPassed(assertion.status));
1696
- const weakProofReasons = rows.map((row) => workflowRowWeakProofReason(row, assertions)).filter(Boolean);
1697
- const failedRows = rows.filter((row) => workflowRowFailed(row, assertions));
1698
- const passedRows = rows.filter((row) => workflowRowHasProof(row, assertions));
1699
- const missingRows = rows.filter((row) => !workflowRowHasProof(row, assertions) && !workflowRowFailed(row, assertions));
1700
- const passedAssertions = assertions.filter((assertion) => statusLooksPassed(assertion.status));
1701
- const releaseBlockers = [
1702
- statusLooksFailed(input.deployStatus) ? `deploy=${cleanText(input.deployStatus, 160)}` : '',
1703
- statusLooksFailed(input.publishStatus) ? `publish=${cleanText(input.publishStatus, 160)}` : '',
1704
- statusLooksFailed(input.sampleDataStatus) ? `sample_data=${cleanText(input.sampleDataStatus, 160)}` : ''
1705
- ].filter(Boolean);
1706
- const hasDataProof = passedAssertions.some((assertion) => cleanText(assertion.dataProof, 1000).length >= 8);
1707
- const sampleDataReady = statusLooksPassed(input.sampleDataStatus)
1708
- || (!statusLooksFailed(input.sampleDataStatus) && hasDataProof);
1709
- const artifactPaths = collectContractArtifactPaths(rows, assertions, input.artifactPaths);
1710
- const workflowProofFingerprint = fingerprintResolveIOAICoderWorkflowProofPayload({
1711
- primaryWorkflowId: journeyValidation.primaryWorkflowId || cleanText(recordedRows[0]?.workflowId, 160),
1712
- passedWorkflowRows: passedRows.map(workflowRowKey),
1713
- failedWorkflowRows: failedRows.map(workflowRowKey),
1714
- missingWorkflowRows: missingRows.map(workflowRowKey),
1715
- passedBusinessAssertions: passedAssertions.map((assertion) => ({
1716
- assertion: assertion.assertion,
1717
- workflowId: assertion.workflowId,
1718
- stepId: assertion.stepId,
1719
- route: assertion.route,
1720
- action: assertion.action,
1721
- expected: assertion.expected,
1722
- observed: assertion.observed,
1723
- dataProof: assertion.dataProof,
1724
- artifactPaths: assertion.artifactPaths
1725
- })),
1726
- sampleDataStatus: input.sampleDataStatus,
1727
- sampleDataReady,
1728
- artifactPaths
1729
- }, 'aicoder-workflow-proof');
1730
- const artifactFingerprint = fingerprintResolveIOAICoderWorkflowProofPayload({
1731
- artifactPaths,
1732
- businessDataProof: passedAssertions.map((assertion) => ({
1733
- stepId: assertion.stepId,
1734
- route: assertion.route,
1735
- dataProof: assertion.dataProof,
1736
- observed: assertion.observed,
1737
- artifactPaths: assertion.artifactPaths
1738
- }))
1739
- }, 'aicoder-workflow-artifacts');
1740
- const previousWorkflowFingerprints = normalizeWorkflowProofFingerprintList(
1741
- input.previousWorkflowProofFingerprint,
1742
- input.previousWorkflowProofFingerprints
1743
- );
1744
- const previousArtifactFingerprints = normalizeWorkflowProofFingerprintList(
1745
- input.previousArtifactFingerprint,
1746
- input.previousArtifactFingerprints
1747
- );
1748
- let proofFreshness: ResolveIOAICoderWorkflowProofFreshness = 'unknown';
1749
- if (!passedAssertions.length && !artifactPaths.length) {
1750
- proofFreshness = 'missing';
1751
- }
1752
- else if (previousWorkflowFingerprints.includes(workflowProofFingerprint)) {
1753
- proofFreshness = 'same_as_previous';
1754
- }
1755
- else if (previousArtifactFingerprints.includes(artifactFingerprint)) {
1756
- proofFreshness = 'stale_artifact';
1757
- }
1758
- else {
1759
- proofFreshness = 'fresh';
1760
- }
1761
- const blockers: string[] = [];
1762
- let status: ResolveIOAICoderWorkflowProofReadinessStatus = 'ready';
1763
- let reason = 'Journey contract and workflow business proof are ready.';
1764
- let nextAction = 'Proceed to the smallest remaining release gate.';
1765
- if (!hasJourneyInput) {
1766
- status = 'missing_journey_contract';
1767
- blockers.push('Generate and validate docs/APP_JOURNEY_CONTRACT.md before build/acceptance.');
1768
- reason = 'AICoder cannot accept an app without a journey contract.';
1769
- nextAction = 'Run journey_contract generation and validation first.';
1770
- }
1771
- else if (!journeyValidation.valid) {
1772
- status = 'journey_invalid';
1773
- blockers.push(...journeyValidation.issues.filter((issue) => issue.severity === 'error').map((issue) => issue.message).slice(0, 8));
1774
- reason = 'Journey contract validation failed.';
1775
- nextAction = 'Repair docs/APP_JOURNEY_CONTRACT.md before product-code repair.';
1776
- }
1777
- else if (routeOnly) {
1778
- status = 'route_only';
1779
- blockers.push('Route/browser proof passed, but no workflow business assertion passed.');
1780
- reason = 'Route-only proof cannot accept an AICoder app.';
1781
- nextAction = 'Run workflow QA generated from the journey contract.';
1782
- }
1783
- else if (!rows.length) {
1784
- status = 'workflow_qa_missing';
1785
- blockers.push('No workflow QA rows were generated or recorded from the journey contract.');
1786
- reason = 'Workflow QA evidence is missing.';
1787
- nextAction = 'Generate workflow QA rows from journey_contract.qa_assertions.';
1788
- }
1789
- else if (weakProofReasons.length) {
1790
- status = 'business_proof_weak';
1791
- blockers.push(...weakProofReasons.slice(0, 8));
1792
- reason = 'Workflow QA rows passed without the structured artifacts or mapped output proof required by the Journey Contract.';
1793
- nextAction = 'Rerun the weak workflow QA rows and record AIQaBusinessAssertion plus required artifacts.';
1794
- }
1795
- else if (failedRows.length || missingRows.length) {
1796
- status = 'workflow_qa_incomplete';
1797
- blockers.push(
1798
- ...failedRows.map((row, index) => `failed:${workflowRowKey(row, index)}`).slice(0, 8),
1799
- ...missingRows.map((row, index) => `missing:${workflowRowKey(row, index)}`).slice(0, 8)
1800
- );
1801
- reason = 'Not all journey contract workflow QA rows have passed business proof.';
1802
- nextAction = 'Rerun or repair the incomplete workflow QA rows before publish.';
1803
- }
1804
- else if (!passedAssertions.length) {
1805
- status = input.scorecardPassed === true ? 'business_proof_missing' : 'workflow_qa_incomplete';
1806
- blockers.push('Workflow rows have no mapped AIQaBusinessAssertion business proof.');
1807
- reason = input.scorecardPassed === true
1808
- ? 'Scorecard-only proof is not acceptance.'
1809
- : 'Workflow business proof is missing.';
1810
- nextAction = 'Record AIQaBusinessAssertion rows tied to the journey contract.';
1811
- }
1812
- else if (releaseBlockers.length) {
1813
- status = 'release_blocked';
1814
- blockers.push(...releaseBlockers);
1815
- reason = 'Workflow proof passed, but release/deploy/sample-data gates block acceptance.';
1816
- nextAction = 'Repair only the failed release gate or hotfix artifact before rerunning publish/deploy.';
1817
- }
1818
- else if (!sampleDataReady) {
1819
- status = 'sample_data_missing';
1820
- blockers.push('No non-empty seeded/sample data proof is available for the workflow.');
1821
- reason = 'AICoder app proof must include meaningful non-empty data.';
1822
- nextAction = 'Seed meaningful records and rerun workflow QA against that data.';
1823
- }
1824
- else if (proofFreshness === 'same_as_previous' || proofFreshness === 'stale_artifact') {
1825
- status = 'stale_workflow_proof';
1826
- blockers.push(proofFreshness === 'same_as_previous'
1827
- ? 'Workflow business proof fingerprint is unchanged from a prior run.'
1828
- : 'Workflow proof artifacts are unchanged from a prior run.');
1829
- reason = 'AICoder workflow proof is stale; repeated evidence cannot advance acceptance.';
1830
- nextAction = 'Rerun workflow QA from journey_contract.qa_assertions and record fresh AIQaBusinessAssertion artifacts.';
1831
- }
1832
- return {
1833
- ready: status === 'ready',
1834
- status,
1835
- reason,
1836
- blockers,
1837
- journeyContractValid: journeyValidation.valid,
1838
- primaryWorkflowId: journeyValidation.primaryWorkflowId || cleanText(recordedRows[0]?.workflowId, 160),
1839
- passedWorkflowRows: passedRows.map(workflowRowKey),
1840
- missingWorkflowRows: missingRows.map(workflowRowKey),
1841
- failedWorkflowRows: failedRows.map(workflowRowKey),
1842
- passedBusinessAssertions: passedAssertions.map((assertion) => cleanText(assertion.assertion || assertion.stepId || assertion.route, 300)).filter(Boolean).slice(0, 40),
1843
- routeOnly,
1844
- scorecardOnly: input.scorecardPassed === true && !passedAssertions.length,
1845
- sampleDataReady,
1846
- releaseBlockers,
1847
- artifactPaths,
1848
- workflowProofFingerprint,
1849
- artifactFingerprint,
1850
- proofFreshness,
1851
- nextAction,
1852
- evaluatedAt: now
1853
- };
1854
- }
1855
-
1856
- export function fingerprintResolveIOAICoderV6Blocker(value: any): string {
1857
- const text = cleanText(value, 4000)
1858
- .toLowerCase()
1859
- .replace(/[a-f0-9]{16,}/g, '<id>')
1860
- .replace(/\b\d{2,}\b/g, '<n>')
1861
- .replace(/\bline\s+<n>\b/g, 'line <n>')
1862
- .replace(/https?:\/\/\S+/g, '<url>');
1863
- let hash = 0;
1864
- for (let index = 0; index < text.length; index += 1) {
1865
- hash = ((hash << 5) - hash + text.charCodeAt(index)) | 0;
1866
- }
1867
- return `aicoder-v6-${Math.abs(hash).toString(36)}`;
1868
- }
1869
-
1870
- function classifyResolveIOAICoderV6FailureClass(step: {
1871
- outcome?: ResolveIOAICoderV6Outcome;
1872
- lane?: ResolveIOAICoderV6Lane;
1873
- stepType?: ResolveIOAICoderV6StepType;
1874
- blocker?: string;
1875
- summary?: string;
1876
- failureClass?: string;
1877
- }): string {
1878
- const explicit = cleanText(step.failureClass, 80).toLowerCase().replace(/[\s-]+/g, '_');
1879
- if (explicit) {
1880
- return explicit;
1881
- }
1882
- if (step.outcome === 'infra_retry') {
1883
- return 'infra';
1884
- }
1885
- const text = `${step.stepType || ''}\n${step.lane || ''}\n${step.blocker || ''}\n${step.summary || ''}`.toLowerCase();
1886
- if (/\b(puppeteer|chrome|browser executable|mongo|port|startup|settings\.json|node_modules|npm install|cache|lock)\b/.test(text)) {
1887
- return 'infra';
1888
- }
1889
- if (/\b(ts[0-9]{3,5}|typescript|compile|build failed|ng build|cannot find name|module not found|syntax error)\b/.test(text)
1890
- || step.stepType === 'build') {
1891
- return 'compile';
1892
- }
1893
- if (step.stepType === 'journey_contract' || step.stepType === 'journey_validation') {
1894
- return 'journey';
1895
- }
1896
- if (step.stepType === 'workflow_qa' || step.lane === 'qa') {
1897
- return 'business';
1898
- }
1899
- if (step.stepType === 'publish' || step.stepType === 'test_deploy' || step.stepType === 'live_deploy' || step.lane === 'publish') {
1900
- return 'release';
1901
- }
1902
- return 'product_code';
1903
- }
1904
-
1905
- function aicoderWorkflowReadinessNextCommand(status: ResolveIOAICoderWorkflowReadinessStatus): string {
1906
- switch (status) {
1907
- case 'journey_contract_required':
1908
- return 'Generate and validate docs/APP_JOURNEY_CONTRACT.md before product-code build work.';
1909
- case 'journey_contract_repair_required':
1910
- return 'Repair the journey contract until first/next/last workflow QA rows validate.';
1911
- case 'workflow_build_ready':
1912
- return 'Build the north-star workflow from the journey contract and seeded data story.';
1913
- case 'workflow_qa_required':
1914
- return 'Run workflow QA from journey_contract.qa_assertions and record AIQaBusinessAssertion proof.';
1915
- case 'workflow_business_proof_ready':
1916
- return 'Proceed only to release/publish gates; wow UI polish is allowed after business proof.';
1917
- case 'release_repair_required':
1918
- return 'Repair the failed publish/deploy/sample-data gate without rebuilding the app shell.';
1919
- case 'infra_repair_only':
1920
- return 'Repair Puppeteer, Chrome, Mongo, startup, port, cache, or environment evidence only.';
1921
- case 'compile_repair_only':
1922
- return 'Repair compile/build evidence only and rerun the same deterministic build gate.';
1923
- case 'collect_new_evidence':
1924
- return 'Collect new evidence for the stuck blocker before another model/code loop.';
1925
- case 'budget_stopped':
1926
- return 'Stop autonomous spend and request a bounded human decision.';
1927
- case 'parked':
1928
- return 'Park the run until a human chooses the next bounded action.';
1929
- default:
1930
- return 'Review workflow evidence before continuing.';
1931
- }
1932
- }
1933
-
1934
- function aicoderWorkflowReadinessGateFor(status: ResolveIOAICoderWorkflowReadinessStatus): ResolveIOAICoderWorkflowReadinessGate {
1935
- switch (status) {
1936
- case 'journey_contract_required':
1937
- case 'journey_contract_repair_required':
1938
- return 'journey_contract';
1939
- case 'workflow_build_ready':
1940
- return 'build';
1941
- case 'workflow_qa_required':
1942
- case 'workflow_business_proof_ready':
1943
- return 'workflow_qa';
1944
- case 'release_repair_required':
1945
- return 'release';
1946
- case 'infra_repair_only':
1947
- return 'infra';
1948
- case 'compile_repair_only':
1949
- return 'compile';
1950
- case 'collect_new_evidence':
1951
- return 'evidence';
1952
- case 'budget_stopped':
1953
- case 'parked':
1954
- return 'manual';
1955
- default:
1956
- return 'manual';
1957
- }
1958
- }
1959
-
1960
- export function buildResolveIOAICoderWorkflowProofCheckpoint(input: {
1961
- status: ResolveIOAICoderWorkflowReadinessStatus;
1962
- nextGate: ResolveIOAICoderWorkflowReadinessGate;
1963
- nextAction?: any;
1964
- last?: Partial<ResolveIOAICoderV6StepRecord>;
1965
- journeyContractReady?: boolean;
1966
- businessProofReady?: boolean;
1967
- routeOnlyBlocked?: boolean;
1968
- releaseBlocked?: boolean;
1969
- infraOnly?: boolean;
1970
- compileOnly?: boolean;
1971
- sameFailureParked?: boolean;
1972
- primaryWorkflowId?: any;
1973
- activeWorkflowStep?: any;
1974
- workflowQaRows?: any;
1975
- businessProofArtifacts?: any;
1976
- completedWorkflowSteps?: any;
1977
- }): ResolveIOAICoderWorkflowProofCheckpoint {
1978
- const status = input.status;
1979
- const nextGate = input.nextGate;
1980
- const proofArtifacts = cleanList(input.businessProofArtifacts, 80, 500);
1981
- const workflowRows = cleanWorkflowQaRows(input.workflowQaRows, 80);
1982
- const completedWorkflowSteps = cleanList(input.completedWorkflowSteps, 80, 240);
1983
- const workflowProofFingerprint = fingerprintResolveIOAICoderWorkflowProofPayload({
1984
- primaryWorkflowId: input.primaryWorkflowId,
1985
- activeWorkflowStep: input.activeWorkflowStep,
1986
- workflowRows: workflowRows.map((row) => ({
1987
- workflowId: row.workflowId,
1988
- stepId: row.stepId,
1989
- status: row.status,
1990
- acceptanceGate: row.acceptanceGate,
1991
- assertion: row.assertion
1992
- })),
1993
- completedWorkflowSteps,
1994
- proofArtifacts
1995
- }, 'aicoder-workflow-readiness');
1996
- const artifactFingerprint = fingerprintResolveIOAICoderWorkflowProofPayload({
1997
- proofArtifacts,
1998
- rowArtifacts: workflowRows.flatMap((row) => cleanList(row.artifactPaths, 10, 500))
1999
- }, 'aicoder-workflow-artifacts');
2000
- const requiredEvidenceByStatus: Record<ResolveIOAICoderWorkflowReadinessStatus, string[]> = {
2001
- journey_contract_required: [
2002
- 'docs/APP_JOURNEY_CONTRACT.md with validated journey_contract JSON',
2003
- 'first/next/last north_star_workflow steps',
2004
- 'workflow QA rows generated from journey_contract.qa_assertions'
2005
- ],
2006
- journey_contract_repair_required: [
2007
- 'repaired journey contract validation result',
2008
- 'command-center hub action mapped to workflow state transition'
2009
- ],
2010
- workflow_build_ready: [
2011
- 'implemented north-star workflow from the Journey Contract',
2012
- 'seeded data story available in the app'
2013
- ],
2014
- workflow_qa_required: [
2015
- 'AIQaBusinessAssertion for the north-star workflow',
2016
- 'non-empty data proof',
2017
- 'saved/calculated output proof',
2018
- 'report/export proof when promised'
2019
- ],
2020
- workflow_business_proof_ready: [
2021
- 'deterministic release gate before publish',
2022
- 'workflow proof artifact retained for acceptance'
2023
- ],
2024
- release_repair_required: [
2025
- 'publish/deploy/sample-data failure artifact',
2026
- 'hotfix or release-gate evidence before another full deploy'
2027
- ],
2028
- infra_repair_only: [
2029
- 'Puppeteer/Chrome/Mongo/startup/preflight evidence',
2030
- 'infra failure class changed or preflight passed'
2031
- ],
2032
- compile_repair_only: [
2033
- 'compile/build log evidence',
2034
- 'compile failure class changed or build passed'
2035
- ],
2036
- collect_new_evidence: [
2037
- 'changed blocker fingerprint or evidence hash',
2038
- 'fresh workflow QA artifact',
2039
- 'AIQaBusinessAssertion or precise workflow blocker artifact'
2040
- ],
2041
- budget_stopped: [
2042
- 'budget summary',
2043
- 'one human decision for next bounded action'
2044
- ],
2045
- parked: [
2046
- 'operator decision',
2047
- 'new evidence before retry'
2048
- ]
2049
- };
2050
- const waitingStatus: ResolveIOAICoderWorkflowProofCheckpointStatus = status === 'workflow_business_proof_ready'
2051
- ? 'ready_to_continue'
2052
- : status === 'release_repair_required'
2053
- ? 'waiting_for_release_gate'
2054
- : status === 'collect_new_evidence' || input.sameFailureParked === true
2055
- ? 'waiting_for_new_evidence'
2056
- : status === 'infra_repair_only' || status === 'compile_repair_only'
2057
- ? 'waiting_for_infra_or_compile'
2058
- : status === 'journey_contract_required' || status === 'journey_contract_repair_required'
2059
- ? 'waiting_for_journey_contract'
2060
- : 'waiting_for_workflow_proof';
2061
- const blocksProductRepairUntilJourneyContract = input.journeyContractReady !== true
2062
- || status === 'journey_contract_required'
2063
- || status === 'journey_contract_repair_required';
2064
- const blocksPublishUntilWorkflowProof = input.businessProofReady !== true
2065
- || input.routeOnlyBlocked === true
2066
- || input.sameFailureParked === true
2067
- || blocksProductRepairUntilJourneyContract
2068
- || status === 'workflow_qa_required'
2069
- || status === 'workflow_build_ready'
2070
- || status === 'collect_new_evidence';
2071
- return {
2072
- required: true,
2073
- status: waitingStatus,
2074
- readinessStatus: status,
2075
- nextGate,
2076
- startingFailureClass: cleanText(input.last?.failureClass, 120),
2077
- startingBlockerFingerprint: cleanText(input.last?.blockerFingerprint || fingerprintResolveIOAICoderV6Blocker(input.last?.blocker || input.last?.summary || ''), 160),
2078
- startingEvidenceHash: cleanText(input.last?.evidenceHash, 160),
2079
- workflowProofFingerprint,
2080
- artifactFingerprint,
2081
- requiredEvidence: (requiredEvidenceByStatus[status] || []).slice(0, 20),
2082
- requiredResetEvidence: Array.from(new Set([
2083
- ...(requiredEvidenceByStatus[status] || []),
2084
- ...(input.sameFailureParked === true ? ['new workflow proof fingerprint', 'new artifact fingerprint'] : []),
2085
- ...(input.releaseBlocked === true ? ['changed release gate fingerprint'] : [])
2086
- ])).slice(0, 20),
2087
- successRequiresWorkflowBusinessProof: status !== 'infra_repair_only' && status !== 'compile_repair_only' && status !== 'budget_stopped',
2088
- blocksProductRepairUntilJourneyContract,
2089
- blocksPublishUntilWorkflowProof,
2090
- blocksPublishUntilReleaseGate: input.releaseBlocked === true || status === 'release_repair_required',
2091
- blocksWowUiUntilWorkflowProof: blocksPublishUntilWorkflowProof,
2092
- nextAction: cleanText(input.nextAction, 500) || aicoderWorkflowReadinessNextCommand(status)
2093
- };
2094
- }
2095
-
2096
- export function buildResolveIOAICoderV6WorkflowReadiness(
2097
- bundle: ResolveIOAICoderV6StateBundle,
2098
- context: {
2099
- action?: ResolveIOAICoderV6ContinuationAction;
2100
- reason?: string;
2101
- nextLane?: ResolveIOAICoderV6Lane;
2102
- nextStep?: ResolveIOAICoderV6StepType;
2103
- budgetExceeded?: boolean;
2104
- repeatedNoProgressCount?: number;
2105
- } = {}
2106
- ): ResolveIOAICoderWorkflowReadiness {
2107
- const history = Array.isArray(bundle.aiCoderV6StepHistory) ? bundle.aiCoderV6StepHistory : [];
2108
- const last = history[history.length - 1];
2109
- const workflowMemory = bundle.aiCoderV6WorkflowMemory || {} as ResolveIOAICoderV6WorkflowMemory;
2110
- const rows = cleanWorkflowQaRows(workflowMemory.workflowQaRows, 80);
2111
- const proofArtifacts = cleanList(workflowMemory.businessProofArtifacts, 80, 500);
2112
- const completedSteps = cleanList(workflowMemory.completedWorkflowSteps, 80, 240);
2113
- const primaryWorkflowId = cleanText(workflowMemory.primaryWorkflowId || rows[0]?.workflowId, 200);
2114
- const activeWorkflowStep = cleanText(workflowMemory.activeWorkflowStep || workflowMemory.blockedWorkflowStep || rows.find((row) => !statusLooksPassed(row.status))?.stepId, 200);
2115
- const failureClass = cleanText(last?.failureClass, 120).toLowerCase();
2116
- const contextReason = cleanText(context.reason, 1000);
2117
- const observedBlocker = cleanText(last?.blocker || last?.summary, 1000);
2118
- const reason = contextReason || observedBlocker;
2119
- const combinedText = `${failureClass}\n${contextReason}\n${observedBlocker}\n${last?.stepType || ''}\n${last?.lane || ''}`.toLowerCase();
2120
- const compileOnly = failureClass === 'compile'
2121
- || /\b(compile|typescript|ts[0-9]{3,5}|ng build|cannot find name|module not found)\b/i.test(combinedText);
2122
- const infraOnly = !compileOnly && (failureClass === 'infra'
2123
- || /\b(puppeteer|chrome|browser executable|mongo|port|startup|settings\.json|node_modules|cache|lock)\b/i.test(combinedText));
2124
- const releaseBlocked = failureClass === 'release'
2125
- || context.nextLane === 'publish'
2126
- || /\b(release|publish|deploy|cloudfront|artifact|sample data|sample_data)\b/i.test(combinedText);
2127
- const routeOnlyBlocked = /\b(route only|route-only|route loaded|route_probe|browser route|shell only|shell-only)\b/i.test(combinedText);
2128
- const sameFailureParked = context.action === 'park'
2129
- || context.reason === 'aicoder_v6_repeated_no_progress'
2130
- || context.reason === 'aicoder_v6_ping_pong_no_progress';
2131
- const budgetStopped = context.action === 'budget_stop' || context.budgetExceeded === true;
2132
- const workflowQaRowsReady = rows.length > 0;
2133
- const journeyContractReady = !!cleanText(workflowMemory.journeyContractPath, 500)
2134
- && (!!primaryWorkflowId || workflowQaRowsReady || completedSteps.length > 0);
2135
- const businessProofReady = proofArtifacts.length > 0;
2136
- let status: ResolveIOAICoderWorkflowReadinessStatus = 'workflow_build_ready';
2137
- const blockers: string[] = [];
2138
- if (budgetStopped) {
2139
- status = 'budget_stopped';
2140
- blockers.push('Budget guard stopped autonomous spend.');
2141
- }
2142
- else if (sameFailureParked) {
2143
- status = 'collect_new_evidence';
2144
- blockers.push('Same failure class repeated without enough new evidence.');
2145
- }
2146
- else if (compileOnly && context.action === 'infra_retry') {
2147
- status = 'compile_repair_only';
2148
- blockers.push('Compile/build gate failed; do not count this as product workflow failure.');
2149
- }
2150
- else if (infraOnly && context.action === 'infra_retry') {
2151
- status = 'infra_repair_only';
2152
- blockers.push('Infra gate failed; repair only environment/browser/startup dependencies.');
2153
- }
2154
- else if (failureClass === 'journey' || context.reason === 'aicoder_v6_journey_contract_repair_required') {
2155
- status = 'journey_contract_repair_required';
2156
- blockers.push('Journey contract failed validation.');
2157
- }
2158
- else if (!journeyContractReady) {
2159
- status = 'journey_contract_required';
2160
- blockers.push('Journey contract workflow memory is not ready.');
2161
- }
2162
- else if (releaseBlocked || context.reason === 'aicoder_v6_release_repair_required') {
2163
- status = 'release_repair_required';
2164
- blockers.push('Release/publish/deploy gate blocks acceptance.');
2165
- }
2166
- else if (!workflowQaRowsReady || !businessProofReady || routeOnlyBlocked) {
2167
- status = 'workflow_qa_required';
2168
- if (!workflowQaRowsReady) {
2169
- blockers.push('Workflow QA rows are missing.');
2170
- }
2171
- if (!businessProofReady) {
2172
- blockers.push('AIQaBusinessAssertion proof is missing.');
2173
- }
2174
- if (routeOnlyBlocked) {
2175
- blockers.push('Route/browser proof is not workflow business proof.');
2176
- }
2177
- }
2178
- else if (businessProofReady) {
2179
- status = 'workflow_business_proof_ready';
2180
- }
2181
- const canRunWorkflowQa = journeyContractReady
2182
- && workflowQaRowsReady
2183
- && !infraOnly
2184
- && !compileOnly
2185
- && !sameFailureParked
2186
- && !budgetStopped;
2187
- const canPublish = status === 'workflow_business_proof_ready'
2188
- && !releaseBlocked
2189
- && !infraOnly
2190
- && !compileOnly
2191
- && !sameFailureParked
2192
- && !budgetStopped;
2193
- const canRunProductRepair = journeyContractReady
2194
- && !infraOnly
2195
- && !compileOnly
2196
- && !sameFailureParked
2197
- && !budgetStopped
2198
- && status !== 'journey_contract_repair_required'
2199
- && status !== 'release_repair_required'
2200
- && status !== 'workflow_business_proof_ready';
2201
- const nextGate = aicoderWorkflowReadinessGateFor(status);
2202
- const nextCommand = aicoderWorkflowReadinessNextCommand(status);
2203
- const workflowProofCheckpoint = buildResolveIOAICoderWorkflowProofCheckpoint({
2204
- status,
2205
- nextGate,
2206
- nextAction: nextCommand,
2207
- last,
2208
- journeyContractReady,
2209
- businessProofReady,
2210
- routeOnlyBlocked,
2211
- releaseBlocked,
2212
- infraOnly,
2213
- compileOnly,
2214
- sameFailureParked,
2215
- primaryWorkflowId,
2216
- activeWorkflowStep,
2217
- workflowQaRows: rows,
2218
- businessProofArtifacts: proofArtifacts,
2219
- completedWorkflowSteps: completedSteps
2220
- });
2221
- return {
2222
- status,
2223
- nextGate,
2224
- nextLane: context.nextLane || last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2225
- nextStep: context.nextStep || last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2226
- nextCommand,
2227
- journeyContractReady,
2228
- workflowQaRowsReady,
2229
- businessProofReady,
2230
- routeOnlyBlocked,
2231
- releaseBlocked,
2232
- infraOnly,
2233
- compileOnly,
2234
- sameFailureParked,
2235
- canRunProductRepair,
2236
- canRunWorkflowQa,
2237
- canPublish,
2238
- canPolishWowUi: canPublish,
2239
- requiresHumanDecision: budgetStopped || sameFailureParked,
2240
- reason: reason || aicoderWorkflowReadinessNextCommand(status),
2241
- blockers: blockers.slice(0, 8),
2242
- primaryWorkflowId,
2243
- activeWorkflowStep,
2244
- businessProofArtifacts: proofArtifacts,
2245
- workflowProofCheckpoint
2246
- };
2247
- }
2248
-
2249
- function aicoderNextActionLabel(command: string): string {
2250
- switch (command) {
2251
- case 'repair_aicoder_journey_contract':
2252
- return 'Repair Journey Contract';
2253
- case 'run_aicoder_workflow_build':
2254
- return 'Build North-Star Workflow';
2255
- case 'run_aicoder_workflow_qa':
2256
- return 'Run Workflow QA';
2257
- case 'repair_aicoder_release_gate':
2258
- return 'Repair Release Gate';
2259
- case 'repair_aicoder_compile_gate':
2260
- return 'Repair Compile Gate';
2261
- case 'repair_aicoder_infra_gate':
2262
- return 'Repair Infra Gate';
2263
- case 'run_aicoder_owner_scoped_repair':
2264
- return 'Run Scoped Repair';
2265
- case 'publish_aicoder_after_workflow_proof':
2266
- return 'Publish After Workflow Proof';
2267
- case 'park_aicoder_until_new_evidence':
2268
- return 'Park Until New Evidence';
2269
- case 'park_aicoder_budget_stop':
2270
- return 'Park Budget Stop';
2271
- default:
2272
- return 'Continue Workflow';
2273
- }
2274
- }
2275
-
2276
- function aicoderNextActionPrimaryCommand(
2277
- action: ResolveIOAICoderV6ContinuationAction,
2278
- readiness: ResolveIOAICoderWorkflowReadiness
2279
- ): string {
2280
- if (action === 'budget_stop') {
2281
- return 'park_aicoder_budget_stop';
2282
- }
2283
- if (action === 'park') {
2284
- return 'park_aicoder_until_new_evidence';
2285
- }
2286
- if (action === 'infra_retry') {
2287
- return readiness.compileOnly ? 'repair_aicoder_compile_gate' : 'repair_aicoder_infra_gate';
2288
- }
2289
- if (readiness.status === 'journey_contract_required' || readiness.status === 'journey_contract_repair_required') {
2290
- return 'repair_aicoder_journey_contract';
2291
- }
2292
- if (readiness.status === 'workflow_build_ready') {
2293
- return 'run_aicoder_workflow_build';
2294
- }
2295
- if (readiness.status === 'workflow_qa_required') {
2296
- return 'run_aicoder_workflow_qa';
2297
- }
2298
- if (readiness.status === 'release_repair_required') {
2299
- return 'repair_aicoder_release_gate';
2300
- }
2301
- if (action === 'ready_to_publish') {
2302
- return 'publish_aicoder_after_workflow_proof';
2303
- }
2304
- if (action === 'switch_to_repair' || action === 'retry_same_step') {
2305
- return 'run_aicoder_owner_scoped_repair';
2306
- }
2307
- return 'continue_aicoder_workflow';
2308
- }
2309
-
2310
- function aicoderNextActionCostRisk(
2311
- action: ResolveIOAICoderV6ContinuationAction,
2312
- command: string,
2313
- readiness: ResolveIOAICoderWorkflowReadiness
2314
- ): ResolveIOAICoderNextActionCostRisk {
2315
- if (action === 'park' || action === 'budget_stop' || readiness.requiresHumanDecision) {
2316
- return 'manual_blocked';
2317
- }
2318
- if (action === 'ready_to_publish' || command === 'repair_aicoder_release_gate' || readiness.nextGate === 'release') {
2319
- return 'release_or_customer_send';
2320
- }
2321
- if (command === 'run_aicoder_workflow_qa' || command === 'repair_aicoder_compile_gate' || command === 'repair_aicoder_infra_gate') {
2322
- return 'small_model_or_qa';
2323
- }
2324
- if (command === 'continue_aicoder_workflow') {
2325
- return 'free_or_deterministic';
2326
- }
2327
- return 'expensive_model';
2328
- }
2329
-
2330
- function aicoderNextActionExpectedTransition(command: string): string {
2331
- switch (command) {
2332
- case 'repair_aicoder_journey_contract':
2333
- return 'Missing or invalid journey contract becomes a validated first/next/last workflow graph with QA rows.';
2334
- case 'run_aicoder_workflow_build':
2335
- return 'Journey contract becomes implemented workflow screens, hub action, data story, and reachable completion state.';
2336
- case 'run_aicoder_workflow_qa':
2337
- return 'Route/browser evidence becomes AIQaBusinessAssertion proof for the north-star workflow.';
2338
- case 'repair_aicoder_release_gate':
2339
- return 'Publish/deploy/sample-data blocker becomes hotfix evidence, release-gate evidence, or one explicit force-deploy decision.';
2340
- case 'repair_aicoder_compile_gate':
2341
- return 'Compile failure becomes a passing build or a new compile blocker fingerprint.';
2342
- case 'repair_aicoder_infra_gate':
2343
- return 'Infra/preflight failure becomes a passing startup/browser/Mongo gate or a new infra blocker fingerprint.';
2344
- case 'run_aicoder_owner_scoped_repair':
2345
- return 'Current blocker changes to passed, a new evidence hash, or a parked manual decision.';
2346
- case 'publish_aicoder_after_workflow_proof':
2347
- return 'Workflow-proven artifact moves through the release gate exactly once with publish/deploy evidence recorded.';
2348
- case 'park_aicoder_budget_stop':
2349
- case 'park_aicoder_until_new_evidence':
2350
- return 'Runner stops spending until an operator records new evidence or an explicit next action.';
2351
- default:
2352
- return 'Runner advances to the next workflow-first gate with evidence recorded.';
2353
- }
2354
- }
2355
-
2356
- function buildResolveIOAICoderNextActionStopConditions(
2357
- readiness: ResolveIOAICoderWorkflowReadiness,
2358
- command: string
2359
- ): string[] {
2360
- const stopConditions = [
2361
- 'Do not accept scorecard, wow score, or route load as app success without AIQaBusinessAssertion workflow proof.'
2362
- ];
2363
- if (!readiness.journeyContractReady || command === 'repair_aicoder_journey_contract') {
2364
- stopConditions.push('Do not run build tasks until docs/APP_JOURNEY_CONTRACT.md validates with first/next/last workflow steps.');
2365
- }
2366
- if (!readiness.businessProofReady || readiness.routeOnlyBlocked || command === 'run_aicoder_workflow_qa') {
2367
- stopConditions.push('Do not publish or run wow UI polish until workflow business proof passes.');
2368
- stopConditions.push('Route-only proof must stay labeled as route evidence, not acceptance.');
2369
- }
2370
- if (readiness.releaseBlocked || command === 'repair_aicoder_release_gate') {
2371
- stopConditions.push('Do not repeat a full publish/deploy until release blocker evidence changes or hotfix/force evidence is recorded.');
2372
- }
2373
- if (readiness.infraOnly || readiness.compileOnly) {
2374
- stopConditions.push('Infra, startup, Puppeteer, Chrome, Mongo, and compile failures stay in infra/compile repair; do not charge them as product workflow failure.');
2375
- }
2376
- if (readiness.sameFailureParked) {
2377
- stopConditions.push('Do not retry the same model/code repair until the blocker fingerprint, evidence hash, or workflow proof artifact changes.');
2378
- }
2379
- if (readiness.requiresHumanDecision) {
2380
- stopConditions.push('Do not spend additional model or release budget until an operator records the next bounded action.');
2381
- }
2382
- return Array.from(new Set(stopConditions)).slice(0, 12);
2383
- }
2384
-
2385
- export function buildResolveIOAICoderNextActionContract(input: {
2386
- bundle: ResolveIOAICoderV6StateBundle;
2387
- action: ResolveIOAICoderV6ContinuationAction;
2388
- reason: string;
2389
- nextLane: ResolveIOAICoderV6Lane;
2390
- nextStep: ResolveIOAICoderV6StepType;
2391
- budgetExceeded?: boolean;
2392
- workflowReadiness: ResolveIOAICoderWorkflowReadiness;
2393
- workflowProofCheckpoint: ResolveIOAICoderWorkflowProofCheckpoint;
2394
- now?: Date | string;
2395
- }): ResolveIOAICoderNextActionContract {
2396
- const workflowReadiness = input.workflowReadiness;
2397
- const workflowProofCheckpoint = input.workflowProofCheckpoint;
2398
- const history = Array.isArray(input.bundle.aiCoderV6StepHistory) ? input.bundle.aiCoderV6StepHistory : [];
2399
- const last = history[history.length - 1];
2400
- const command = aicoderNextActionPrimaryCommand(input.action, workflowReadiness);
2401
- const costRisk = aicoderNextActionCostRisk(input.action, command, workflowReadiness);
2402
- const hotfixCommitRequired = command === 'repair_aicoder_release_gate'
2403
- || workflowReadiness.releaseBlocked
2404
- || workflowReadiness.nextGate === 'release';
2405
- const liveHotfixBlockedUntilCommit = hotfixCommitRequired;
2406
- const requiredHotfixCommitProof = hotfixCommitRequired
2407
- ? ['sourceCommitSha', 'githubCommitUrl', 'gitCommitStatus=passed', 'gitPushStatus=passed']
2408
- : [];
2409
- const requiresHumanApproval = input.action === 'park'
2410
- || input.action === 'budget_stop'
2411
- || input.action === 'ready_to_publish'
2412
- || input.budgetExceeded === true
2413
- || workflowReadiness.requiresHumanDecision === true;
2414
- const workflowFirstSatisfied = workflowReadiness.journeyContractReady
2415
- && workflowReadiness.businessProofReady
2416
- && !workflowReadiness.releaseBlocked
2417
- && !workflowReadiness.routeOnlyBlocked
2418
- && !workflowReadiness.infraOnly
2419
- && !workflowReadiness.compileOnly
2420
- && !workflowReadiness.sameFailureParked;
2421
- const safeToAutoRun = !requiresHumanApproval && (
2422
- command === 'repair_aicoder_journey_contract'
2423
- || command === 'run_aicoder_workflow_build'
2424
- || command === 'run_aicoder_workflow_qa'
2425
- || command === 'repair_aicoder_release_gate'
2426
- || command === 'repair_aicoder_compile_gate'
2427
- || command === 'repair_aicoder_infra_gate'
2428
- || (command === 'run_aicoder_owner_scoped_repair' && workflowReadiness.canRunProductRepair)
2429
- || (command === 'continue_aicoder_workflow' && !workflowReadiness.blockers.length)
2430
- );
2431
- const canRunWithoutCodexMonitor = safeToAutoRun
2432
- && workflowProofCheckpoint.requiredEvidence.length > 0
2433
- && workflowProofCheckpoint.nextAction.length > 0;
2434
- const blockers = Array.from(new Set([
2435
- ...workflowReadiness.blockers,
2436
- ...(workflowProofCheckpoint.status === 'waiting_for_new_evidence' ? workflowProofCheckpoint.requiredResetEvidence : [])
2437
- ])).slice(0, 12);
2438
- const preconditions = Array.from(new Set([
2439
- workflowProofCheckpoint.nextAction,
2440
- ...workflowProofCheckpoint.requiredEvidence,
2441
- ...(workflowReadiness.journeyContractReady ? [] : ['validated APP_JOURNEY_CONTRACT.md journey_contract JSON']),
2442
- ...(workflowReadiness.canRunWorkflowQa ? ['workflow QA rows generated from the journey contract'] : []),
2443
- ...(workflowReadiness.releaseBlocked ? ['release blocker artifact or hotfix-first release evidence'] : []),
2444
- ...(hotfixCommitRequired ? ['sourceCommitSha, githubCommitUrl, passed gitCommitStatus, and passed gitPushStatus before live hotfix apply'] : [])
2445
- ].map((entry) => cleanText(entry, 300)).filter(Boolean))).slice(0, 12);
2446
- const successEvidence = Array.from(new Set([
2447
- ...workflowProofCheckpoint.requiredEvidence,
2448
- ...(workflowReadiness.businessProofReady ? ['retained AIQaBusinessAssertion artifact'] : []),
2449
- ...(workflowReadiness.canPublish ? ['release gate accepts the workflow-proven artifact'] : []),
2450
- ...(command === 'repair_aicoder_release_gate' ? ['hotfix evidence or explicit one-time force release decision'] : []),
2451
- ...(hotfixCommitRequired ? ['GitHub commit and push proof for any manager-applied hotfix'] : [])
2452
- ].map((entry) => cleanText(entry, 300)).filter(Boolean))).slice(0, 12);
2453
- const stopConditions = buildResolveIOAICoderNextActionStopConditions(workflowReadiness, command);
2454
- if (hotfixCommitRequired) {
2455
- stopConditions.push('Do not apply a live AICoder backend/static hotfix until sourceCommitSha, githubCommitUrl, passed gitCommitStatus, and passed gitPushStatus are recorded.');
2456
- }
2457
- const forbiddenActions = Array.from(new Set([
2458
- 'accepting route-only proof as app success',
2459
- 'accepting scorecard-only or wow-score-only proof as app success',
2460
- ...(workflowReadiness.journeyContractReady ? [] : ['building product routes before the journey contract validates']),
2461
- ...(workflowReadiness.businessProofReady ? [] : ['publishing before north-star workflow business proof passes']),
2462
- ...(workflowReadiness.releaseBlocked ? ['rerunning full deploy/publish without changed release evidence'] : []),
2463
- ...(hotfixCommitRequired ? ['applying live hotfix before pushed GitHub commit proof'] : []),
2464
- ...(workflowReadiness.sameFailureParked ? ['retrying the same repair loop without new evidence'] : [])
2465
- ])).slice(0, 12);
2466
- const nextCommands = Array.from(new Set([
2467
- command,
2468
- ...(command === 'repair_aicoder_journey_contract' ? ['validate_aicoder_journey_contract', 'generate_workflow_qa_rows'] : []),
2469
- ...(command === 'run_aicoder_workflow_qa' ? ['execute_contract_qa_assertions', 'record_aiqa_business_assertion'] : []),
2470
- ...(command === 'repair_aicoder_release_gate' ? [
2471
- 'collect_release_blocker_evidence',
2472
- 'prefer_hotfix_before_full_deploy',
2473
- 'prepare_hotfix_patch_without_live_apply',
2474
- 'commit_and_push_hotfix_to_github',
2475
- 'record_github_commit_for_hotfix',
2476
- 'apply_live_hotfix_only_after_github_commit_proof'
2477
- ] : []),
2478
- ...(command === 'repair_aicoder_compile_gate' ? ['rerun_compile_gate_only', 'record_compile_evidence_hash'] : []),
2479
- ...(command === 'repair_aicoder_infra_gate' ? ['rerun_preflight_gate_only', 'record_infra_evidence_hash'] : []),
2480
- 'record_aicoder_next_action_result'
2481
- ])).slice(0, 12);
2482
- const contractBasis = {
2483
- action: input.action,
2484
- reason: cleanText(input.reason, 500),
2485
- command,
2486
- readinessStatus: workflowReadiness.status,
2487
- checkpointStatus: workflowProofCheckpoint.status,
2488
- failureClass: cleanText(last?.failureClass, 120),
2489
- evidenceHash: hashResolveIOAIManagerEvidence(last as any)
2490
- };
2491
- return {
2492
- contractId: `aicoder-next-${hashResolveIOAIManagerEvidence({
2493
- failureClass: contractBasis.failureClass,
2494
- summary: `${contractBasis.reason}:${contractBasis.command}:${contractBasis.readinessStatus}:${contractBasis.checkpointStatus}`,
2495
- evidenceHash: contractBasis.evidenceHash,
2496
- changedFiles: last?.changedFiles,
2497
- artifactPaths: last?.artifactPaths
2498
- } as any)}`,
2499
- action: input.action,
2500
- label: aicoderNextActionLabel(command),
2501
- primaryCommand: command,
2502
- lane: input.nextLane,
2503
- stepType: input.nextStep,
2504
- safeToAutoRun,
2505
- requiresHumanApproval,
2506
- canRunWithoutCodexMonitor,
2507
- codexFallbackRequired: !canRunWithoutCodexMonitor && !requiresHumanApproval,
2508
- codexFallbackReason: canRunWithoutCodexMonitor
2509
- ? ''
2510
- : requiresHumanApproval
2511
- ? 'Operator approval is required before the next action.'
2512
- : 'Next action needs stronger deterministic evidence before it can run unattended.',
2513
- costRisk,
2514
- workflowFirstSatisfied,
2515
- decisionBasis: {
2516
- journeyContractReady: workflowReadiness.journeyContractReady,
2517
- workflowProofReady: workflowReadiness.businessProofReady,
2518
- sampleDataReady: workflowReadiness.businessProofReady && !workflowReadiness.releaseBlocked,
2519
- releaseBlocked: workflowReadiness.releaseBlocked,
2520
- routeOnlyBlocked: workflowReadiness.routeOnlyBlocked,
2521
- infraOnly: workflowReadiness.infraOnly,
2522
- compileOnly: workflowReadiness.compileOnly,
2523
- sameFailureParked: workflowReadiness.sameFailureParked,
2524
- canPublish: workflowReadiness.canPublish,
2525
- canPolishWowUi: workflowReadiness.canPolishWowUi,
2526
- workflowReadinessStatus: workflowReadiness.status,
2527
- workflowProofCheckpointStatus: workflowProofCheckpoint.status,
2528
- failureClass: contractBasis.failureClass,
2529
- evidenceHash: cleanText(last?.evidenceHash || contractBasis.evidenceHash, 160),
2530
- hotfixCommitRequired,
2531
- liveHotfixBlockedUntilCommit
2532
- },
2533
- preconditions,
2534
- expectedStateTransition: aicoderNextActionExpectedTransition(command),
2535
- successEvidence,
2536
- requiredHotfixCommitProof,
2537
- stopConditions,
2538
- forbiddenActions,
2539
- nextCommands,
2540
- blockers,
2541
- ownerFiles: cleanList(last?.changedFiles, 20, 500),
2542
- createdAt: isoNow(input.now)
2543
- };
2544
- }
2545
-
2546
- export function buildResolveIOAICoderV6Budget(existing?: Partial<ResolveIOAICoderV6Budget>): ResolveIOAICoderV6Budget {
2547
- return {
2548
- maxPromptTokensPerNonInitialStep: Number(existing?.maxPromptTokensPerNonInitialStep || 4000),
2549
- maxTotalPromptTokens: Number(existing?.maxTotalPromptTokens || 120000),
2550
- maxLoopsPerRun: Number(existing?.maxLoopsPerRun || 24),
2551
- maxRepeatedNoProgress: Number(existing?.maxRepeatedNoProgress || 2),
2552
- maxRuntimeMinutesPerLane: Number(existing?.maxRuntimeMinutesPerLane || 30),
2553
- softBudgetUsd: Number(existing?.softBudgetUsd || 30),
2554
- hardBudgetUsd: Number(existing?.hardBudgetUsd || 60),
2555
- totalPromptTokenEstimate: cleanNumber(existing?.totalPromptTokenEstimate),
2556
- totalInputTokens: cleanNumber(existing?.totalInputTokens),
2557
- totalCachedInputTokens: cleanNumber(existing?.totalCachedInputTokens),
2558
- totalOutputTokens: cleanNumber(existing?.totalOutputTokens),
2559
- totalRuntimeMs: cleanNumber(existing?.totalRuntimeMs),
2560
- loopCount: cleanNumber(existing?.loopCount)
2561
- };
2562
- }
2563
-
2564
- export function initializeResolveIOAICoderV6State(input: ResolveIOAICoderV6InitializeInput): ResolveIOAICoderV6StateBundle {
2565
- const now = isoNow(input.now);
2566
- const existing = input.existing || {};
2567
- const existingSupervisor = existing.aiCoderV6SupervisorState;
2568
- const existingLaneMemory = existing.aiCoderV6LaneMemory || {} as ResolveIOAICoderV6StateBundle['aiCoderV6LaneMemory'];
2569
- const existingWorkflowMemory = existing.aiCoderV6WorkflowMemory || {} as Partial<ResolveIOAICoderV6WorkflowMemory>;
2570
- const scope = cleanList(input.approvedScopeRequirements, 24, 240).join(' | ')
2571
- || cleanText(input.description, 1000)
2572
- || cleanText(input.title, 300);
2573
- const runId = cleanText(input.conversationId || input.jobId || input.appId, 120);
2574
- const defaultModel = cleanText(input.defaultModel || 'gpt-5.3-codex', 80);
2575
- const buildLaneMemory = (lane: ResolveIOAICoderV6Lane): ResolveIOAICoderV6LaneMemory => {
2576
- const previous = existingLaneMemory[lane] || {} as Partial<ResolveIOAICoderV6LaneMemory>;
2577
- return {
2578
- lane,
2579
- model: cleanText(previous.model || defaultModel, 80),
2580
- threadKey: cleanText(input.laneThreadKeys?.[lane] || previous.threadKey || `aicoder:${input.runKind}:${runId}:${lane}`, 240),
2581
- scopeSummary: cleanText(previous.scopeSummary || scope, 1200),
2582
- activeStep: previous.activeStep || (lane === 'plan' ? 'plan' : lane === 'qa' ? 'qa' : lane === 'review' ? 'review' : lane === 'publish' ? 'publish' : 'task'),
2583
- activeBlocker: cleanText(previous.activeBlocker, 1200),
2584
- activeQaRow: previous.activeQaRow,
2585
- changedFiles: cleanList(previous.changedFiles, 80, 500),
2586
- artifactPaths: cleanList(previous.artifactPaths, 80, 500),
2587
- latestPromptVersion: cleanText(previous.latestPromptVersion, 120) || undefined,
2588
- latestPromptTokenEstimate: cleanNumber(previous.latestPromptTokenEstimate) || undefined,
2589
- updatedAt: previous.updatedAt || now
2590
- };
2591
- };
2592
- const laneMemory = LANES.reduce((accumulator, lane) => {
2593
- accumulator[lane] = buildLaneMemory(lane);
2594
- return accumulator;
2595
- }, {} as Record<ResolveIOAICoderV6Lane, ResolveIOAICoderV6LaneMemory>);
2596
- const activeLane = existingSupervisor?.activeLane || (input.runKind === 'initial_builder' ? 'plan' : 'build');
2597
- return {
2598
- aiCoderRunnerVersion: 'v6',
2599
- aiCoderV6SupervisorState: {
2600
- version: 'v6',
2601
- runKind: input.runKind,
2602
- status: existingSupervisor?.status || 'active',
2603
- currentGoal: cleanText(existingSupervisor?.currentGoal || `Run AICoder ${input.runKind} ${runId}`, 500),
2604
- approvedScope: cleanText(existingSupervisor?.approvedScope || scope, 1400),
2605
- branchName: cleanText(input.branchName || existingSupervisor?.branchName, 240),
2606
- activeLane,
2607
- activeStep: existingSupervisor?.activeStep || laneMemory[activeLane].activeStep,
2608
- activeBlocker: cleanText(existingSupervisor?.activeBlocker, 1200),
2609
- lastGoodCheckpoint: existingSupervisor?.lastGoodCheckpoint || 'v6_initialized',
2610
- lastGoodCommit: cleanText(existingSupervisor?.lastGoodCommit, 240) || undefined,
2611
- testDeployStatus: cleanText(existingSupervisor?.testDeployStatus, 120) || undefined,
2612
- liveDeployStatus: cleanText(existingSupervisor?.liveDeployStatus, 120) || undefined,
2613
- processLease: input.processLease || existingSupervisor?.processLease,
2614
- artifactLinks: cleanList(existingSupervisor?.artifactLinks, 80, 500),
2615
- updatedAt: now
2616
- },
2617
- aiCoderV6LaneMemory: laneMemory,
2618
- aiCoderV6WorkflowMemory: {
2619
- journeyContractPath: cleanText(input.journeyContractPath || existingWorkflowMemory.journeyContractPath || 'docs/APP_JOURNEY_CONTRACT.md', 500),
2620
- primaryWorkflowId: cleanText(existingWorkflowMemory.primaryWorkflowId, 200),
2621
- activeWorkflowStep: cleanText(existingWorkflowMemory.activeWorkflowStep, 200),
2622
- workflowQaRows: cleanWorkflowQaRows(existingWorkflowMemory.workflowQaRows, 80),
2623
- completedWorkflowSteps: cleanList(existingWorkflowMemory.completedWorkflowSteps, 80, 240),
2624
- blockedWorkflowStep: cleanText(existingWorkflowMemory.blockedWorkflowStep, 240),
2625
- businessProofArtifacts: cleanList(existingWorkflowMemory.businessProofArtifacts, 80, 500),
2626
- updatedAt: existingWorkflowMemory.updatedAt || now
2627
- },
2628
- aiCoderV6StepHistory: Array.isArray(existing.aiCoderV6StepHistory)
2629
- ? existing.aiCoderV6StepHistory.slice(-100)
2630
- : [],
2631
- aiCoderV6Budget: buildResolveIOAICoderV6Budget(existing.aiCoderV6Budget),
2632
- aiCoderV6RunnerIncidents: Array.isArray(existing.aiCoderV6RunnerIncidents)
2633
- ? existing.aiCoderV6RunnerIncidents.slice(-100)
2634
- : [],
2635
- aiCoderV6RecoveryPlan: (existing as any).aiCoderV6RecoveryPlan,
2636
- aiCoderV6RecoveryCheckpoint: (existing as any).aiCoderV6RecoveryCheckpoint,
2637
- aiCoderV6RecoveryEvidenceProbe: (existing as any).aiCoderV6RecoveryEvidenceProbe,
2638
- aiCoderV6RecoveryAction: (existing as any).aiCoderV6RecoveryAction,
2639
- aiCoderV6RecoveryDispatchHistory: Array.isArray((existing as any).aiCoderV6RecoveryDispatchHistory)
2640
- ? (existing as any).aiCoderV6RecoveryDispatchHistory.slice(-50)
2641
- : [],
2642
- aiCoderV6RecoveryDirective: (existing as any).aiCoderV6RecoveryDirective
2643
- };
2644
- }
2645
-
2646
- export function recordResolveIOAICoderV6Step(
2647
- bundle: ResolveIOAICoderV6StateBundle,
2648
- step: ResolveIOAICoderV6StepInput
2649
- ): ResolveIOAICoderV6StateBundle {
2650
- const now = isoNow(step.now);
2651
- const promptTokens = cleanNumber(step.promptTokenEstimate);
2652
- const inputTokens = cleanNumber(step.inputTokens);
2653
- const cachedInputTokens = cleanNumber(step.cachedInputTokens);
2654
- const outputTokens = cleanNumber(step.outputTokens);
2655
- const runtimeMs = cleanNumber(step.runtimeMs);
2656
- const blocker = cleanText(step.blocker, 1200);
2657
- const failureClass = classifyResolveIOAICoderV6FailureClass({
2658
- outcome: step.outcome,
2659
- lane: step.lane,
2660
- stepType: step.stepType,
2661
- blocker,
2662
- summary: step.summary,
2663
- failureClass: step.failureClass
2664
- });
2665
- const previousWorkflowMemory = bundle.aiCoderV6WorkflowMemory || {} as ResolveIOAICoderV6WorkflowMemory;
2666
- const activeWorkflowStep = cleanText(step.activeWorkflowStep || previousWorkflowMemory.activeWorkflowStep, 200);
2667
- const explicitCompletedSteps = cleanList(step.completedWorkflowSteps, 40, 240);
2668
- const completedWorkflowSteps = Array.from(new Set([
2669
- ...cleanList(previousWorkflowMemory.completedWorkflowSteps, 80, 240),
2670
- ...explicitCompletedSteps,
2671
- ...(step.outcome === 'pass' && activeWorkflowStep ? [activeWorkflowStep] : [])
2672
- ])).slice(-80);
2673
- const businessProofArtifacts = Array.from(new Set([
2674
- ...cleanList(previousWorkflowMemory.businessProofArtifacts, 80, 500),
2675
- ...cleanList(step.businessProofArtifacts, 40, 500)
2676
- ])).slice(-80);
2677
- const workflowQaRows = step.workflowQaRows !== undefined
2678
- ? cleanWorkflowQaRows(step.workflowQaRows, 80)
2679
- : cleanWorkflowQaRows(previousWorkflowMemory.workflowQaRows, 80);
2680
- const blockedWorkflowStep = cleanText(
2681
- step.blockedWorkflowStep
2682
- || ((step.outcome === 'needs_repair' || step.outcome === 'park_manual') ? activeWorkflowStep : '')
2683
- || previousWorkflowMemory.blockedWorkflowStep,
2684
- 240
2685
- );
2686
- const record: ResolveIOAICoderV6StepRecord = {
2687
- stepType: step.stepType,
2688
- outcome: step.outcome,
2689
- lane: step.lane,
2690
- model: cleanText(step.model, 80) || undefined,
2691
- threadKey: cleanText(step.threadKey, 240) || undefined,
2692
- promptVersion: cleanText(step.promptVersion, 120) || undefined,
2693
- promptTokenEstimate: promptTokens || undefined,
2694
- inputTokens: inputTokens || undefined,
2695
- cachedInputTokens: cachedInputTokens || undefined,
2696
- outputTokens: outputTokens || undefined,
2697
- runtimeMs: runtimeMs || undefined,
2698
- summary: cleanText(step.summary || blocker || step.outcome, 1200),
2699
- blocker: blocker || undefined,
2700
- blockerFingerprint: blocker ? fingerprintResolveIOAICoderV6Blocker(blocker) : undefined,
2701
- failureClass,
2702
- changedFiles: cleanList(step.changedFiles, 80, 500),
2703
- artifactPaths: cleanList(step.artifactPaths, 80, 500),
2704
- nextAction: step.nextAction,
2705
- recordedAt: now
2706
- };
2707
- record.evidenceHash = cleanText(step.evidenceHash, 120)
2708
- || hashResolveIOAIManagerEvidence(record);
2709
- const previousRecord = bundle.aiCoderV6StepHistory[bundle.aiCoderV6StepHistory.length - 1];
2710
- const managerDecision = decideResolveIOAIManagerPolicy({
2711
- history: [...bundle.aiCoderV6StepHistory, record],
2712
- current: record,
2713
- maxSameFailureRepeats: buildResolveIOAICoderV6Budget(bundle.aiCoderV6Budget).maxRepeatedNoProgress + 1
2714
- });
2715
- const nextLoopCount = managerDecision.loopBudgetShouldReset
2716
- || previousRecord?.failureClass !== record.failureClass
2717
- || previousRecord?.blockerFingerprint !== record.blockerFingerprint
2718
- || previousRecord?.evidenceHash !== record.evidenceHash
2719
- ? 1
2720
- : bundle.aiCoderV6Budget.loopCount + 1;
2721
- const budget = buildResolveIOAICoderV6Budget(bundle.aiCoderV6Budget);
2722
- const shouldParkForRepeatedNoProgress = !managerDecision.loopBudgetShouldReset
2723
- && nextLoopCount > budget.maxRepeatedNoProgress
2724
- && step.outcome !== 'pass'
2725
- && step.outcome !== 'ready_to_publish'
2726
- && step.outcome !== 'published';
2727
- const recordedRecoveryPlan = shouldParkForRepeatedNoProgress
2728
- ? buildResolveIOAIManagerRecoveryPlan({
2729
- action: 'park_repeated_failure',
2730
- reason: 'aicoder_v6_repeated_no_progress',
2731
- failureClass: record.failureClass,
2732
- lane: record.lane,
2733
- stepType: record.stepType,
2734
- blocker: record.blocker || record.summary,
2735
- changedFiles: record.changedFiles,
2736
- artifactPaths: record.artifactPaths,
2737
- maxSameFailureRepeats: budget.maxRepeatedNoProgress + 1
2738
- })
2739
- : managerDecision.recoveryPlan;
2740
- const recordedRecoveryCheckpoint = shouldParkForRepeatedNoProgress
2741
- ? buildResolveIOAIManagerRecoveryCheckpoint({
2742
- plan: recordedRecoveryPlan,
2743
- current: record
2744
- })
2745
- : managerDecision.recoveryCheckpoint;
2746
- const recordedRecoveryEvidenceProbe = shouldParkForRepeatedNoProgress
2747
- ? buildResolveIOAIManagerRecoveryEvidenceProbe({
2748
- checkpoint: recordedRecoveryCheckpoint,
2749
- current: record
2750
- })
2751
- : managerDecision.recoveryEvidenceProbe;
2752
- const recordedRecoveryAction = shouldParkForRepeatedNoProgress
2753
- ? buildResolveIOAIManagerRecoveryActionPacket({
2754
- plan: recordedRecoveryPlan,
2755
- checkpoint: recordedRecoveryCheckpoint,
2756
- probe: recordedRecoveryEvidenceProbe,
2757
- current: record
2758
- })
2759
- : managerDecision.recoveryAction;
2760
- const previousLane = bundle.aiCoderV6LaneMemory[step.lane];
2761
- const laneMemory = {
2762
- ...bundle.aiCoderV6LaneMemory,
2763
- [step.lane]: {
2764
- ...previousLane,
2765
- model: record.model || previousLane.model,
2766
- threadKey: record.threadKey || previousLane.threadKey,
2767
- activeStep: step.stepType,
2768
- activeBlocker: record.blocker || previousLane.activeBlocker || '',
2769
- activeQaRow: step.activeQaRow || previousLane.activeQaRow,
2770
- changedFiles: record.changedFiles?.length ? record.changedFiles : previousLane.changedFiles,
2771
- artifactPaths: record.artifactPaths?.length ? record.artifactPaths : previousLane.artifactPaths,
2772
- latestPromptVersion: record.promptVersion || previousLane.latestPromptVersion,
2773
- latestPromptTokenEstimate: promptTokens || previousLane.latestPromptTokenEstimate,
2774
- updatedAt: now
2775
- }
2776
- };
2777
- const complete = step.outcome === 'published' || step.outcome === 'ready_to_publish';
2778
- const parked = step.outcome === 'park_manual' || step.outcome === 'budget_stop';
2779
- return {
2780
- ...bundle,
2781
- aiCoderV6SupervisorState: {
2782
- ...bundle.aiCoderV6SupervisorState,
2783
- status: complete ? 'complete' : (parked ? 'parked' : 'active'),
2784
- activeLane: step.lane,
2785
- activeStep: step.stepType,
2786
- activeBlocker: record.blocker || '',
2787
- lastGoodCheckpoint: step.outcome === 'pass' || complete ? step.stepType : bundle.aiCoderV6SupervisorState.lastGoodCheckpoint,
2788
- artifactLinks: Array.from(new Set([
2789
- ...bundle.aiCoderV6SupervisorState.artifactLinks,
2790
- ...(record.artifactPaths || [])
2791
- ])).slice(-80),
2792
- updatedAt: now
2793
- },
2794
- aiCoderV6LaneMemory: laneMemory,
2795
- aiCoderV6WorkflowMemory: {
2796
- journeyContractPath: cleanText(previousWorkflowMemory.journeyContractPath || 'docs/APP_JOURNEY_CONTRACT.md', 500),
2797
- primaryWorkflowId: cleanText(step.primaryWorkflowId || previousWorkflowMemory.primaryWorkflowId, 200),
2798
- activeWorkflowStep,
2799
- workflowQaRows,
2800
- completedWorkflowSteps,
2801
- blockedWorkflowStep,
2802
- businessProofArtifacts,
2803
- updatedAt: now
2804
- },
2805
- aiCoderV6StepHistory: [...bundle.aiCoderV6StepHistory, record].slice(-120),
2806
- aiCoderV6Budget: {
2807
- ...bundle.aiCoderV6Budget,
2808
- totalPromptTokenEstimate: bundle.aiCoderV6Budget.totalPromptTokenEstimate + promptTokens,
2809
- totalInputTokens: bundle.aiCoderV6Budget.totalInputTokens + inputTokens,
2810
- totalCachedInputTokens: bundle.aiCoderV6Budget.totalCachedInputTokens + cachedInputTokens,
2811
- totalOutputTokens: bundle.aiCoderV6Budget.totalOutputTokens + outputTokens,
2812
- totalRuntimeMs: bundle.aiCoderV6Budget.totalRuntimeMs + runtimeMs,
2813
- loopCount: nextLoopCount
2814
- },
2815
- aiCoderV6RecoveryPlan: recordedRecoveryPlan,
2816
- aiCoderV6RecoveryCheckpoint: recordedRecoveryCheckpoint,
2817
- aiCoderV6RecoveryEvidenceProbe: recordedRecoveryEvidenceProbe,
2818
- aiCoderV6RecoveryAction: recordedRecoveryAction
2819
- };
2820
- }
2821
-
2822
- export function decideResolveIOAICoderV6Continuation(bundle: ResolveIOAICoderV6StateBundle): ResolveIOAICoderV6ContinuationDecision {
2823
- const history = bundle.aiCoderV6StepHistory || [];
2824
- const budget = buildResolveIOAICoderV6Budget(bundle.aiCoderV6Budget);
2825
- const last = history[history.length - 1];
2826
- const lastFingerprint = fingerprintResolveIOAICoderV6Blocker(last?.blocker || last?.summary || '');
2827
- let repeatedNoProgressCount = 0;
2828
- for (let index = history.length - 1; index >= 0; index -= 1) {
2829
- const item = history[index];
2830
- if (item.outcome === 'pass' || item.outcome === 'ready_to_publish' || item.outcome === 'published') {
2831
- break;
2832
- }
2833
- if (item.stepType !== last?.stepType || item.lane !== last?.lane) {
2834
- break;
2835
- }
2836
- if (fingerprintResolveIOAICoderV6Blocker(item.blocker || item.summary || '') === lastFingerprint) {
2837
- repeatedNoProgressCount += 1;
2838
- }
2839
- }
2840
- const managerDecision = decideResolveIOAIManagerPolicy({
2841
- history,
2842
- current: last,
2843
- maxSameFailureRepeats: budget.maxRepeatedNoProgress + 1,
2844
- maxPingPongTransitions: 3,
2845
- infraFailureClasses: ['infra', 'compile']
2846
- });
2847
- const recoveryPlanFor = (
2848
- action: ResolveIOAICoderV6ContinuationDecision['action'] | string,
2849
- reason: string,
2850
- extra: Partial<ResolveIOAIManagerRecoveryPlanInput> = {}
2851
- ): ResolveIOAIManagerRecoveryPlan => buildResolveIOAIManagerRecoveryPlan({
2852
- action,
2853
- reason,
2854
- failureClass: last?.failureClass,
2855
- lane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2856
- stepType: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2857
- blocker: last?.blocker || last?.summary,
2858
- changedFiles: last?.changedFiles,
2859
- artifactPaths: last?.artifactPaths,
2860
- maxSameFailureRepeats: budget.maxRepeatedNoProgress + 1,
2861
- ...extra
2862
- });
2863
- const recoveryCheckpointFor = (
2864
- recoveryPlan: ResolveIOAIManagerRecoveryPlan
2865
- ): ResolveIOAIManagerRecoveryCheckpoint => buildResolveIOAIManagerRecoveryCheckpoint({
2866
- plan: recoveryPlan,
2867
- current: last
2868
- });
2869
- const recoveryFieldsFor = (
2870
- recoveryPlan: ResolveIOAIManagerRecoveryPlan,
2871
- recoveryCheckpoint?: ResolveIOAIManagerRecoveryCheckpoint,
2872
- recoveryEvidenceProbe?: ResolveIOAIManagerRecoveryEvidenceProbe
2873
- ): Pick<ResolveIOAICoderV6ContinuationDecision, 'recoveryPlan' | 'recoveryCheckpoint' | 'recoveryEvidenceProbe' | 'recoveryAction'> => {
2874
- const checkpoint = recoveryCheckpoint || recoveryCheckpointFor(recoveryPlan);
2875
- const probe = recoveryEvidenceProbe || buildResolveIOAIManagerRecoveryEvidenceProbe({
2876
- checkpoint,
2877
- current: last
2878
- });
2879
- return {
2880
- recoveryPlan,
2881
- recoveryCheckpoint: checkpoint,
2882
- recoveryEvidenceProbe: probe,
2883
- recoveryAction: buildResolveIOAIManagerRecoveryActionPacket({
2884
- plan: recoveryPlan,
2885
- checkpoint,
2886
- probe,
2887
- current: last
2888
- })
2889
- };
2890
- };
2891
- const managerRecoveryFields = () => recoveryFieldsFor(
2892
- managerDecision.recoveryPlan,
2893
- managerDecision.recoveryCheckpoint,
2894
- managerDecision.recoveryEvidenceProbe
2895
- );
2896
- const withWorkflowReadiness = (
2897
- decision: Omit<ResolveIOAICoderV6ContinuationDecision, 'workflowReadiness' | 'workflowProofCheckpoint' | 'nextActionContract'>
2898
- ): ResolveIOAICoderV6ContinuationDecision => {
2899
- const workflowReadiness = buildResolveIOAICoderV6WorkflowReadiness(bundle, {
2900
- action: decision.action,
2901
- reason: decision.reason,
2902
- nextLane: decision.nextLane,
2903
- nextStep: decision.nextStep,
2904
- budgetExceeded: decision.budgetExceeded,
2905
- repeatedNoProgressCount: decision.repeatedNoProgressCount
2906
- });
2907
- const workflowProofCheckpoint = workflowReadiness.workflowProofCheckpoint;
2908
- return {
2909
- ...decision,
2910
- workflowReadiness,
2911
- workflowProofCheckpoint,
2912
- nextActionContract: buildResolveIOAICoderNextActionContract({
2913
- bundle,
2914
- action: decision.action,
2915
- reason: decision.reason,
2916
- nextLane: decision.nextLane,
2917
- nextStep: decision.nextStep,
2918
- budgetExceeded: decision.budgetExceeded,
2919
- workflowReadiness,
2920
- workflowProofCheckpoint
2921
- })
2922
- };
2923
- };
2924
- const budgetExceeded = (budget.loopCount >= budget.maxLoopsPerRun && !managerDecision.loopBudgetShouldReset)
2925
- || budget.totalPromptTokenEstimate >= budget.maxTotalPromptTokens
2926
- || (last?.promptTokenEstimate || 0) > budget.maxPromptTokensPerNonInitialStep * 2;
2927
- if (budgetExceeded) {
2928
- const recoveryPlan = recoveryPlanFor('budget_stop', 'aicoder_v6_budget_guard', {
2929
- productRepairFailure: false
2930
- });
2931
- return withWorkflowReadiness({
2932
- action: 'budget_stop',
2933
- reason: 'aicoder_v6_budget_guard',
2934
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2935
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2936
- repeatedNoProgressCount,
2937
- budgetExceeded,
2938
- ...recoveryFieldsFor(recoveryPlan)
2939
- });
2940
- }
2941
- if (managerDecision.action === 'park_ping_pong') {
2942
- return withWorkflowReadiness({
2943
- action: 'park',
2944
- reason: 'aicoder_v6_ping_pong_no_progress',
2945
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2946
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2947
- repeatedNoProgressCount: managerDecision.pingPongCount,
2948
- budgetExceeded: false,
2949
- ...managerRecoveryFields()
2950
- });
2951
- }
2952
- if (managerDecision.action === 'park_repeated_failure') {
2953
- return withWorkflowReadiness({
2954
- action: 'park',
2955
- reason: 'aicoder_v6_repeated_no_progress',
2956
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2957
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2958
- repeatedNoProgressCount: managerDecision.sameFailureCount,
2959
- budgetExceeded: false,
2960
- ...managerRecoveryFields()
2961
- });
2962
- }
2963
- if (repeatedNoProgressCount > budget.maxRepeatedNoProgress) {
2964
- const recoveryPlan = recoveryPlanFor('park', 'aicoder_v6_repeated_no_progress', {
2965
- action: 'park_repeated_failure',
2966
- productRepairFailure: !/^(?:infra|compile|release)$/i.test(String(last?.failureClass || ''))
2967
- });
2968
- return withWorkflowReadiness({
2969
- action: 'park',
2970
- reason: 'aicoder_v6_repeated_no_progress',
2971
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2972
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2973
- repeatedNoProgressCount,
2974
- budgetExceeded: false,
2975
- ...recoveryFieldsFor(recoveryPlan)
2976
- });
2977
- }
2978
- if (managerDecision.action === 'retry_infra') {
2979
- const compileRepair = managerDecision.recoveryPlan.recoveryClass === 'compile_repair'
2980
- || managerDecision.failureClass === 'compile'
2981
- || last?.failureClass === 'compile';
2982
- return withWorkflowReadiness({
2983
- action: 'infra_retry',
2984
- reason: compileRepair ? 'aicoder_v6_compile_repair_required' : 'aicoder_v6_infra_retry',
2985
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
2986
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
2987
- repeatedNoProgressCount,
2988
- budgetExceeded: false,
2989
- ...managerRecoveryFields()
2990
- });
2991
- }
2992
- if (last?.outcome === 'needs_repair') {
2993
- if (last.failureClass === 'journey') {
2994
- return withWorkflowReadiness({
2995
- action: 'retry_same_step',
2996
- reason: 'aicoder_v6_journey_contract_repair_required',
2997
- nextLane: 'plan',
2998
- nextStep: last.stepType === 'journey_validation' ? 'journey_contract' : last.stepType,
2999
- repeatedNoProgressCount,
3000
- budgetExceeded: false,
3001
- ...managerRecoveryFields()
3002
- });
3003
- }
3004
- if (last.failureClass === 'release') {
3005
- return withWorkflowReadiness({
3006
- action: 'retry_same_step',
3007
- reason: 'aicoder_v6_release_repair_required',
3008
- nextLane: 'publish',
3009
- nextStep: last.stepType,
3010
- repeatedNoProgressCount,
3011
- budgetExceeded: false,
3012
- ...managerRecoveryFields()
3013
- });
3014
- }
3015
- return withWorkflowReadiness({
3016
- action: last.lane === 'repair' ? 'retry_same_step' : 'switch_to_repair',
3017
- reason: 'aicoder_v6_repair_required',
3018
- nextLane: 'repair',
3019
- nextStep: 'repair',
3020
- repeatedNoProgressCount,
3021
- budgetExceeded: false,
3022
- ...managerRecoveryFields()
3023
- });
3024
- }
3025
- if (last?.outcome === 'infra_retry') {
3026
- const recoveryPlan = recoveryPlanFor('infra_retry', 'aicoder_v6_infra_retry', {
3027
- failureClass: 'infra',
3028
- productRepairFailure: false
3029
- });
3030
- return withWorkflowReadiness({
3031
- action: 'infra_retry',
3032
- reason: 'aicoder_v6_infra_retry',
3033
- nextLane: last.lane,
3034
- nextStep: last.stepType,
3035
- repeatedNoProgressCount,
3036
- budgetExceeded: false,
3037
- ...recoveryFieldsFor(recoveryPlan)
3038
- });
3039
- }
3040
- if (last?.outcome === 'ready_to_publish') {
3041
- const recoveryPlan = recoveryPlanFor('ready_to_publish', 'aicoder_v6_ready_to_publish', {
3042
- failureClass: 'release',
3043
- productRepairFailure: false
3044
- });
3045
- return withWorkflowReadiness({
3046
- action: 'ready_to_publish',
3047
- reason: 'aicoder_v6_ready_to_publish',
3048
- nextLane: 'publish',
3049
- nextStep: 'publish',
3050
- repeatedNoProgressCount,
3051
- budgetExceeded: false,
3052
- ...recoveryFieldsFor(recoveryPlan)
3053
- });
3054
- }
3055
- const recoveryPlan = managerDecision.recoveryPlan || recoveryPlanFor('continue', 'aicoder_v6_continue');
3056
- const fallbackCheckpoint = managerDecision.recoveryCheckpoint || recoveryCheckpointFor(recoveryPlan);
3057
- return withWorkflowReadiness({
3058
- action: 'continue',
3059
- reason: 'aicoder_v6_continue',
3060
- nextLane: last?.lane || bundle.aiCoderV6SupervisorState.activeLane,
3061
- nextStep: last?.stepType || bundle.aiCoderV6SupervisorState.activeStep,
3062
- repeatedNoProgressCount,
3063
- budgetExceeded: false,
3064
- ...recoveryFieldsFor(recoveryPlan, fallbackCheckpoint, managerDecision.recoveryEvidenceProbe)
3065
- });
3066
- }
3067
-
3068
- export function buildResolveIOAICoderV6DiagnoseFirstPrompt(lines: {
3069
- goal?: string;
3070
- approvedScope?: string[];
3071
- activeLane?: ResolveIOAICoderV6Lane;
3072
- activeStep?: ResolveIOAICoderV6StepType;
3073
- activeBlocker?: string;
3074
- laneSummary?: string;
3075
- currentQaRow?: ResolveIOAICoderV6LaneMemory['activeQaRow'];
3076
- journeyContractPath?: string;
3077
- activeWorkflowStep?: string;
3078
- artifactPaths?: string[];
3079
- changedFiles?: string[];
3080
- }): string[] {
3081
- return [
3082
- 'AICoder Runner V6 contract: use compact lane memory, diagnose first, then make the smallest proven next move.',
3083
- 'Start with Diagnose First: observed evidence, likely cause, smallest next action, and expected proof.',
3084
- 'Use current artifacts, changed files, and lane memory before asking for broad context.',
3085
- 'Do not spawn duplicate build, QA, browser, server, Mongo, or Codex processes.',
3086
- 'If repairing, inspect logs/artifacts/source/diff first; retest the failed check before advancing.',
3087
- 'If the same blocker repeats without new proof, park with the exact blocker instead of burning more tokens.',
3088
- lines.goal ? `Goal: ${cleanText(lines.goal, 500)}` : '',
3089
- cleanList(lines.approvedScope, 12, 240).length ? `Approved scope: ${cleanList(lines.approvedScope, 12, 240).join(' | ')}` : '',
3090
- lines.activeLane ? `Active lane: ${lines.activeLane}` : '',
3091
- lines.activeStep ? `Active step: ${lines.activeStep}` : '',
3092
- lines.laneSummary ? `Lane memory: ${cleanText(lines.laneSummary, 700)}` : '',
3093
- lines.activeBlocker ? `Active blocker: ${cleanText(lines.activeBlocker, 800)}` : '',
3094
- lines.currentQaRow?.workflow ? `Current QA row: ${cleanText(lines.currentQaRow.workflow, 300)}` : '',
3095
- lines.currentQaRow?.route ? `Current QA route: ${cleanText(lines.currentQaRow.route, 300)}` : '',
3096
- lines.journeyContractPath ? `Journey contract: ${cleanText(lines.journeyContractPath, 240)}` : '',
3097
- lines.activeWorkflowStep ? `Active workflow step: ${cleanText(lines.activeWorkflowStep, 240)}` : '',
3098
- cleanList(lines.changedFiles, 12, 200).length ? `Changed files: ${cleanList(lines.changedFiles, 12, 200).join(', ')}` : '',
3099
- cleanList(lines.artifactPaths, 12, 240).length ? `Artifacts: ${cleanList(lines.artifactPaths, 12, 240).join(', ')}` : ''
3100
- ].filter(Boolean);
3101
- }
3102
-
3103
- export function buildResolveIOAICoderV6Incident(input: {
3104
- incidentClass: string;
3105
- summary: string;
3106
- stepType?: ResolveIOAICoderV6StepType;
3107
- lane?: ResolveIOAICoderV6Lane;
3108
- blocker?: string;
3109
- artifactPaths?: string[];
3110
- now?: Date | string;
3111
- }): ResolveIOAICoderV6RunnerIncident {
3112
- return {
3113
- incidentClass: cleanText(input.incidentClass, 120) || 'aicoder_v6_runner_incident',
3114
- summary: cleanText(input.summary, 1200),
3115
- stepType: input.stepType,
3116
- lane: input.lane,
3117
- blockerFingerprint: input.blocker ? fingerprintResolveIOAICoderV6Blocker(input.blocker) : undefined,
3118
- artifactPaths: cleanList(input.artifactPaths, 40, 500),
3119
- recordedAt: isoNow(input.now)
3120
- };
3121
- }