elanous 0.2.37 → 0.2.40

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 (727) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 1060.014f1f01a17aec26.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 1281.d81877e35b9068f4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/1350.59f40e39e02d91b1.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +286 -0
  10. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +149 -0
  12. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +90 -0
  14. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +104 -0
  15. package/apps/pwa/out/_next/static/chunks/{3578.4e9f9948a9a6f2f4.js → 2047.8f23e210995d4548.js} +2 -2
  16. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 2066.a77257c8c350770a.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 2177.df8547f9d7215c4e.js} +16 -16
  20. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 2226.2cf61ec781827219.js} +2 -2
  22. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 2522.f2766b76d22c8bdf.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/261.0d471e8aded799f3.js +226 -0
  27. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +27 -0
  30. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{2318-450e75d07605b8fe.js → 2774-719820e3f5b2a3eb.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{4725-34bed25720cc326b.js → 2829-734fe8bf2eee7347.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3330.7443183b7e6fdbdf.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3746-f80a78f220bf37b5.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +24 -0
  45. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +77 -0
  46. package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → 3b355b3d.6f73c98bf6f9c749.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +36 -0
  48. package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 409c787b.e48c5bec8ec10456.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +287 -0
  52. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4351.0f37a6db2b34d50b.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 470.51a72a2348306455.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 4769.9fd582071301f382.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 4864a2ca.1c1c280a7772c5e5.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 5383.bdfa5d886e39a826.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/5436.fdf6fa8ae3e9588d.js +64 -0
  65. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +8 -0
  70. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +62 -0
  72. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +94 -0
  76. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 6051-0ae955eedb10adb9.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 6257.c0037b8949239f5e.js} +2 -2
  80. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +32 -0
  85. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 6749.0744ce6eb08d40e9.js} +16 -16
  87. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +148 -0
  90. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +93 -0
  96. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 8272-025653884f9645d2.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 8357.1aaa713b052a78b1.js} +4 -4
  110. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{4313.76f232c304a15bde.js → 9175.2de5209a5ce6f68a.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → 9189505a.980427ac048c8c60.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +79 -0
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/{page-3337c6a1328c2674.js → page-4edb8df90f4537ce.js} +1 -1
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/{page-1e5da297557d2354.js → page-fca2e59a81744d9e.js} +1 -1
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/{page-ac2c1e6169cfce57.js → page-139d722de1dcd6c1.js} +1 -1
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/{page-c1c80e345fa9d6f5.js → page-ccde99f07aaf71f7.js} +1 -1
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b84cad00.594027ebe0531fe2.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → ca3702f8.2913182e73889fa2.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +22 -22
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +22 -22
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +22 -22
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +21 -21
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +21 -21
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +22 -22
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +21 -21
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +22 -22
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +22 -22
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +21 -21
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +22 -22
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +22 -22
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +22 -22
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +22 -22
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +21 -21
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +21 -21
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +22 -22
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +22 -22
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +22 -22
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +21 -21
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +21 -21
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +22 -22
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +22 -22
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +21 -21
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +21 -21
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +21 -21
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +22 -22
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +22 -22
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +21 -21
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +22 -22
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +22 -22
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +22 -22
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +22 -22
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +22 -22
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +21 -21
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +22 -22
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +22 -22
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +22 -22
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +22 -22
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +22 -22
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +22 -22
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +22 -22
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +22 -22
  278. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  279. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  280. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  281. package/graphs/release/recipes.yaml +9 -0
  282. package/graphs/release/release-loop.yaml +26 -18
  283. package/graphs/video/explainer-line.yaml +4 -1
  284. package/package.json +1 -1
  285. package/scripts/ask-op-inbox-once.ts +17 -0
  286. package/scripts/brand/check.ts +13 -4
  287. package/scripts/dead-code/report.ts +169 -0
  288. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  289. package/scripts/gate-0226-failure-census.ts +39 -0
  290. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  291. package/scripts/lib/morning-report-options.ts +3 -4
  292. package/scripts/lib/tui-regress-evidence.ts +56 -0
  293. package/scripts/morning-report.ts +5 -1
  294. package/scripts/provision-export-redactions.ts +15 -0
  295. package/scripts/public-copy-lint.ts +122 -0
  296. package/scripts/public-export.ts +77 -2
  297. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  298. package/scripts/ratchets/train-side-invariants.sh +7 -1
  299. package/scripts/release-loop/cut-branch.ts +61 -12
  300. package/scripts/release-loop/export-check-node.ts +21 -3
  301. package/scripts/release-loop/gate-node.ts +527 -60
  302. package/scripts/release-loop/gate-partial.ts +82 -3
  303. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  304. package/scripts/release-loop/gate-radius-live.ts +4 -2
  305. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  306. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  307. package/scripts/release-loop/gate-wall.ts +5 -5
  308. package/scripts/release-loop/preflight.ts +6 -2
  309. package/scripts/release-loop/resume-cap.ts +2 -1
  310. package/scripts/release-loop/resume-release.ts +317 -13
  311. package/scripts/release-loop/resume.ts +61 -5
  312. package/scripts/release-loop/traffic-node.ts +12 -4
  313. package/scripts/release-loop/traffic-transition.ts +53 -13
  314. package/scripts/release-loop/version-node.ts +35 -5
  315. package/scripts/release-story/draft.ts +1 -1
  316. package/scripts/research-bench/README.md +53 -0
  317. package/scripts/research-bench/questions.json +66 -0
  318. package/scripts/research-bench/rubric.md +33 -0
  319. package/scripts/research-bench/run.ts +523 -0
  320. package/scripts/tui-regress.ts +85 -10
  321. package/scripts/ux-sim.ts +1 -1
  322. package/scripts/video-pipeline.ts +2 -2
  323. package/src/acp/core-turn-bridge.ts +14 -1
  324. package/src/agent/autonomous-tools.ts +10 -3
  325. package/src/agent/monad-agent-turn.ts +4 -1
  326. package/src/agent/registry.ts +26 -2
  327. package/src/agent/run-context.ts +1 -1
  328. package/src/agent/shared-app-tools.ts +1 -1
  329. package/src/agent/surface-ux/build.ts +12 -3
  330. package/src/agent/surface-ux/types.ts +1 -1
  331. package/src/agent/task-notification.ts +78 -7
  332. package/src/agent/types.ts +3 -0
  333. package/src/agent-mission/driver.ts +29 -3
  334. package/src/agent-mission/mission-cli.ts +2 -1
  335. package/src/agent-substrate/review-context-pack.ts +365 -0
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +419 -42
  338. package/src/ask-user-question/index.ts +6 -0
  339. package/src/ask-user-question/inline-resolver.ts +49 -0
  340. package/src/auto-research/question-ladder-contract.ts +156 -0
  341. package/src/auto-research/research-turn.ts +467 -0
  342. package/src/autopilot/agent-loop.ts +1 -1
  343. package/src/autopilot/discovery/doc-lint.ts +1 -1
  344. package/src/autopilot/pty-control-loop.ts +8 -1
  345. package/src/boot/daemon-tools/index.ts +4 -3
  346. package/src/boot/daemon-tools/self-implement.ts +270 -2
  347. package/src/boot/daemon-tools/types.ts +2 -0
  348. package/src/bots/screen-probe.ts +1 -1
  349. package/src/budget/llm-cost.ts +44 -5
  350. package/src/budget/unified-usage.ts +17 -1
  351. package/src/capture/tui-self-report.ts +24 -2
  352. package/src/chat/index.ts +34 -7
  353. package/src/chat/tool-render/dispatch.ts +8 -1
  354. package/src/cli/agent-cli.ts +43 -8
  355. package/src/cli/guardian-cli.ts +3 -1
  356. package/src/cli/intake-cli.ts +70 -13
  357. package/src/cli/lesson-cli.ts +86 -10
  358. package/src/cli/log-event-names.ts +1 -0
  359. package/src/cli/pod-cli.ts +17 -2
  360. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  361. package/src/cli/pr-land-refusal.ts +1 -1
  362. package/src/cli/pty-takeover-cli.ts +125 -12
  363. package/src/cli/release-checklist-read-cli.ts +5 -2
  364. package/src/cli/release-cli.ts +99 -15
  365. package/src/cli/repo-cli.ts +2 -1
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +1 -1
  368. package/src/cli/tasks-card-show.ts +31 -1
  369. package/src/cli/tasks-cli.ts +98 -32
  370. package/src/cli/tasks-read-cli.ts +13 -5
  371. package/src/context-bus/context-now.ts +86 -2
  372. package/src/control-plane/ledger.ts +21 -4
  373. package/src/core-turn/run-core-turn.ts +51 -3
  374. package/src/core-turn/run-goal-loop.ts +152 -8
  375. package/src/core-turn/types.ts +12 -0
  376. package/src/dashboard/chat/acp-chat.ts +2 -2
  377. package/src/dashboard/classic-sigquit.ts +16 -0
  378. package/src/dashboard/index.ts +339 -44
  379. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  380. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  381. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  382. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  383. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  384. package/src/dashboard/input/external-input-host.ts +2 -0
  385. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  386. package/src/dashboard/side-basic-runtime.ts +61 -0
  387. package/src/dashboard/sidetab-runtime.ts +228 -0
  388. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  389. package/src/dashboard/slash-runtime/dashboard-handlers.ts +22 -8
  390. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  391. package/src/dashboard/term-slash-runtime.ts +18 -18
  392. package/src/dashboard/turn-preamble.ts +30 -4
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/knowledge.ts +1 -1
  395. package/src/esc-abort-gate.ts +33 -1
  396. package/src/execution-loop/launch-gate.ts +206 -1
  397. package/src/git-fs/watcher.ts +27 -22
  398. package/src/git-fs/worktree.ts +19 -3
  399. package/src/graph-runner/graph-cli.ts +6 -4
  400. package/src/graph-runner/graph-grow.ts +37 -9
  401. package/src/graph-runner/runner.ts +48 -11
  402. package/src/graph-wizard/generate.ts +16 -7
  403. package/src/graph-wizard/mission-compose.ts +201 -0
  404. package/src/grok/agent-search.ts +8 -2
  405. package/src/grok/credential.ts +112 -36
  406. package/src/grounding/ref-index.ts +11 -0
  407. package/src/grounding/ref-vector.ts +61 -0
  408. package/src/grounding/sources-cli.ts +2 -2
  409. package/src/grounding/sources.ts +15 -1
  410. package/src/harness/harness-cli-command.ts +38 -9
  411. package/src/harness/harness-pod-dispatch.ts +7 -1
  412. package/src/hq/fence-wrapper.ts +1 -1
  413. package/src/hq/transfer.ts +1 -1
  414. package/src/index.ts +60 -16
  415. package/src/input/external-input-queue.ts +10 -0
  416. package/src/intake-plane/collect-telegram-saved.ts +90 -6
  417. package/src/intake-plane/intake-to-tasks.ts +246 -3
  418. package/src/interactive-terminal-modal.ts +3 -0
  419. package/src/keybindings.ts +17 -22
  420. package/src/lessons/friction-ledger.ts +154 -0
  421. package/src/live-supply/collector.ts +149 -0
  422. package/src/live-supply/probes.ts +52 -0
  423. package/src/live-supply/snapshot.ts +40 -0
  424. package/src/llm/provider-credentials.ts +1 -1
  425. package/src/llm-tool-schema.ts +20 -0
  426. package/src/llm.ts +486 -61
  427. package/src/loops/orchestrator/inbox-once.ts +28 -0
  428. package/src/loops/orchestrator/inbox.ts +130 -1
  429. package/src/loops/orchestrator/tick.ts +14 -3
  430. package/src/maturity/feature-maturity.ts +1 -0
  431. package/src/nexus/api/channel-ask-op.ts +96 -0
  432. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  433. package/src/nexus/api/harness-api.ts +2 -1
  434. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  435. package/src/nexus/api/terminals.ts +28 -6
  436. package/src/patents/ledger.ts +18 -1
  437. package/src/preview/terminal.ts +4 -2
  438. package/src/prompt-cache/anthropic.ts +2 -0
  439. package/src/prompt-enhance/enhance.ts +5 -0
  440. package/src/pty/snapshot.py +132 -0
  441. package/src/pty-shell/pty-control-ipc.ts +29 -2
  442. package/src/pty-shell/pty-manifest.ts +75 -5
  443. package/src/pty-shell/registry.ts +2 -0
  444. package/src/pty-shell/tui-run-state.ts +80 -3
  445. package/src/release-loop/gate-host-reservation.ts +13 -4
  446. package/src/release-loop/gate-shard-ledger.ts +68 -0
  447. package/src/release-loop/gate-shards.ts +61 -0
  448. package/src/release-loop/light-rc.ts +7 -4
  449. package/src/release-loop/merged-pr-checklist.ts +25 -2
  450. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  451. package/src/release-loop/rehearsal.ts +28 -1
  452. package/src/repl/index.ts +10 -0
  453. package/src/research/axis-fanout.ts +133 -0
  454. package/src/research/edge-decision.ts +197 -0
  455. package/src/research/gap-followup.ts +249 -0
  456. package/src/research/lenses/counter-evidence.ts +100 -0
  457. package/src/research/lenses/working-backwards.ts +89 -0
  458. package/src/research/output-router.ts +127 -0
  459. package/src/research/plugin-discovery.ts +242 -0
  460. package/src/research-bridge/format.ts +16 -1
  461. package/src/research-bridge/index.ts +1 -0
  462. package/src/research-bridge/invoke.ts +45 -7
  463. package/src/research-bridge/types.ts +2 -0
  464. package/src/self-dev/ask-launch-flow.ts +34 -106
  465. package/src/self-dev/decompose.ts +45 -9
  466. package/src/self-dev/dev-cli.ts +2 -0
  467. package/src/self-dev/dev-pipeline.ts +8 -4
  468. package/src/self-dev/draft-residue.ts +221 -2
  469. package/src/self-dev/draft-sweep.ts +29 -16
  470. package/src/self-dev/graph-journey-route.ts +10 -2
  471. package/src/self-dev/launch-preflight-text.ts +2 -2
  472. package/src/self-dev/launch-preflight.ts +38 -7
  473. package/src/self-dev/orchestrate-cli.ts +1 -0
  474. package/src/self-dev/orchestrate.ts +1 -0
  475. package/src/self-dev/run-supervisor.ts +41 -7
  476. package/src/self-dev/shard-run.ts +260 -3
  477. package/src/self-implement/comment-only-source.ts +54 -0
  478. package/src/self-implement/device-first.ts +8 -2
  479. package/src/self-implement/doctor-visit.ts +100 -57
  480. package/src/self-implement/gate-artifacts.ts +5 -2
  481. package/src/self-implement/gate-baseline.ts +119 -13
  482. package/src/self-implement/gate-cli.ts +466 -93
  483. package/src/self-implement/gate-failure-signature.ts +44 -0
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +147 -22
  486. package/src/self-implement/goal-author-clarification.ts +178 -24
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +82 -7
  489. package/src/self-implement/goal-doc/section.ts +22 -0
  490. package/src/self-implement/goal-supervisor-fill.ts +38 -4
  491. package/src/self-implement/host-regate.ts +120 -45
  492. package/src/self-implement/impl-findings-feedback.ts +188 -0
  493. package/src/self-implement/knowhow-pack.ts +301 -9
  494. package/src/self-implement/l8-merge-queue.ts +198 -32
  495. package/src/self-implement/off-diff-evidence.ts +147 -0
  496. package/src/self-implement/orchestrator.ts +137 -16
  497. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  498. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  499. package/src/self-implement/premise-review.ts +7 -5
  500. package/src/self-implement/run-ledger.ts +304 -8
  501. package/src/self-implement/run-stop.ts +12 -0
  502. package/src/self-implement/seams.ts +39 -13
  503. package/src/self-implement/self-implement-cli.ts +30 -4
  504. package/src/session/channel-ask-op-envelope.ts +36 -0
  505. package/src/session/channel-op-reply-route.ts +200 -0
  506. package/src/session/chat.ts +92 -15
  507. package/src/session/index.ts +2 -0
  508. package/src/session-runtime/index.ts +9 -22
  509. package/src/session-runtime/provider-circuit.ts +140 -0
  510. package/src/shell-runner/file-engine.ts +1 -0
  511. package/src/shell-runner/types.ts +4 -0
  512. package/src/sidetab-core/model.ts +176 -0
  513. package/src/skills/runner.ts +7 -3
  514. package/src/skills/tools/dev-harness.ts +2 -2
  515. package/src/skills/tools/schedule-wakeup.ts +24 -7
  516. package/src/skills/tools/shell.ts +51 -5
  517. package/src/status/bar.ts +3 -3
  518. package/src/steward/directive-audit.ts +354 -0
  519. package/src/storage/file-lock.ts +17 -4
  520. package/src/surface/child-process.ts +31 -0
  521. package/src/surface/tui-stderr-owner.ts +48 -0
  522. package/src/task-agent/adopt-pr.ts +63 -2
  523. package/src/task-agent/cover.ts +30 -12
  524. package/src/task-agent/evidence-command-normalize.ts +42 -0
  525. package/src/task-agent/export-redactions-provision.ts +43 -0
  526. package/src/task-agent/judge.ts +56 -0
  527. package/src/task-agent/parent-host.ts +59 -12
  528. package/src/task-agent/postland-card.ts +35 -2
  529. package/src/task-agent/rejudge-on-head.ts +46 -2
  530. package/src/task-agent/repair-cycle.ts +68 -9
  531. package/src/task-agent/repair-worker.ts +37 -1
  532. package/src/task-agent/task-hand.ts +226 -33
  533. package/src/task-agent/tier-split.ts +142 -24
  534. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  535. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  536. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +57 -5
  537. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  538. package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
  539. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  540. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  541. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  542. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  543. package/src/task-orchestrator/surfaces/self-implement-pod.ts +310 -79
  544. package/src/task-orchestrator/surfaces/self-implement.ts +33 -2
  545. package/src/terminal/session-registry.ts +1 -0
  546. package/src/terminal/terminal-modal-router.ts +156 -0
  547. package/src/tool-hints/gate.ts +6 -4
  548. package/src/tool-hints/signals.ts +33 -1
  549. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  550. package/src/tui/chat/background-job-status.ts +8 -2
  551. package/src/tui/entry.ts +483 -32
  552. package/src/tui/inline-choice.ts +188 -0
  553. package/src/tui/sidetab/attach.ts +304 -0
  554. package/src/tui/sidetab/list.ts +2 -0
  555. package/src/tui/sidetab/nl-tool.ts +136 -0
  556. package/src/tui/slash/resume-command.ts +23 -0
  557. package/src/tui/slash/resume.ts +3 -23
  558. package/src/tui/slash/term-next.ts +2 -1
  559. package/src/tui/slash/term.ts +12 -1
  560. package/src/tui-client/dashboard-session.ts +7 -1
  561. package/src/tui-client/local-chat-turn.ts +29 -8
  562. package/src/user-config.ts +42 -3
  563. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  564. package/src/ux-sim/fake-land-queue.ts +88 -0
  565. package/src/ux-sim/fake-llm.ts +11 -5
  566. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  567. package/src/ux-sim/goal-interim-trace.ts +24 -0
  568. package/src/ux-sim/next-tui-seat-scenarios.ts +61 -14
  569. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  570. package/src/version/packed-revision.json +1 -1
  571. package/src/video-pipeline/recipes/explainer.ts +54 -2
  572. package/src/web-search/grok.ts +32 -6
  573. package/src/web-search/index.ts +8 -7
  574. package/src/workflow-runtime/node-catalog.ts +53 -4
  575. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +0 -62
  579. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +0 -32
  587. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +0 -148
  590. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +0 -27
  594. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/3199.6a1a9b0e6cd01dc6.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +0 -90
  603. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +0 -226
  604. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +0 -287
  605. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +0 -104
  615. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +0 -93
  622. package/apps/pwa/out/_next/static/chunks/5952.294fc574a8625184.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +0 -74
  624. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +0 -149
  627. package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +0 -41
  631. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +0 -24
  634. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/7c5ed21f-f286708e57cf88f7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +0 -8
  647. package/apps/pwa/out/_next/static/chunks/8080-40d781e7704d3671.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +0 -77
  649. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +0 -286
  652. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +0 -79
  656. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +0 -94
  664. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +0 -64
  666. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-88a1edbff62eaf1d.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +0 -1
  725. package/scripts/migrate-monad-to-elanous.ts +0 -195
  726. package/scripts/rebrand-elanous.ts +0 -242
  727. /package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
@@ -12,6 +12,12 @@ export type ShardState = typeof SHARD_STATES[number];
12
12
  export interface GateShard {
13
13
  id: string;
14
14
  state: ShardState;
15
+ /** Kubernetes Job for the current attempt; lets the gate watchdog reconcile a lost completion callback. */
16
+ job?: string;
17
+ /** Attempt identity associated with the currently recorded Job/result marker. */
18
+ attemptId?: string;
19
+ /** Result JSON for the current attempt; retries replace this so an older marker cannot close a new Job. */
20
+ resultFile?: string;
15
21
  startedAt?: string;
16
22
  endedAt?: string;
17
23
  /** 설치(install) 단계에 쓴 초. */
@@ -61,8 +67,14 @@ function shardOf(value: unknown): GateShard | null {
61
67
  const waitReason = str(raw.waitReason);
62
68
  const plannedMin = num(raw.plannedMin);
63
69
  const host = str(raw.host, 120);
70
+ const job = str(raw.job, 120);
71
+ const attemptId = str(raw.attemptId, 120);
72
+ const resultFile = str(raw.resultFile, 200);
64
73
  return {
65
74
  id, state,
75
+ ...(job ? { job } : {}),
76
+ ...(attemptId ? { attemptId } : {}),
77
+ ...(resultFile ? { resultFile } : {}),
66
78
  ...(startedAt ? { startedAt } : {}), ...(endedAt ? { endedAt } : {}),
67
79
  ...(installSec !== undefined ? { installSec } : {}), ...(rc !== undefined ? { rc } : {}),
68
80
  ...(waitReason ? { waitReason } : {}), ...(plannedMin !== undefined ? { plannedMin } : {}),
@@ -70,6 +82,55 @@ function shardOf(value: unknown): GateShard | null {
70
82
  };
71
83
  }
72
84
 
85
+ export type GateJobTerminal = 'complete' | 'failed';
86
+
87
+ /** Forget the prior child Job before a shard descends into a retry/split attempt. */
88
+ export function beginGateShardAttempt(shard: GateShard, now = new Date()): GateShard {
89
+ const next: GateShard = { ...shard, state: 'retry', startedAt: now.toISOString() };
90
+ delete next.endedAt;
91
+ delete next.waitReason;
92
+ delete next.host;
93
+ delete next.job;
94
+ delete next.resultFile;
95
+ delete next.attemptId;
96
+ return next;
97
+ }
98
+
99
+ /**
100
+ * Close each stale running row when its result marker or Kubernetes Job has terminal evidence.
101
+ * A result marker can close a row even when the Kubernetes status read is unavailable.
102
+ */
103
+ export function finalizeTerminalGateShards(
104
+ file: GateShardsFile,
105
+ terminalJobs: ReadonlyMap<string, GateJobTerminal>,
106
+ results: ReadonlyMap<string, { completed?: boolean; jobName?: string; attemptId?: string; jobFailed?: boolean; rc?: number | null; reason?: 'timeout' | 'stall' }>,
107
+ now: Date = new Date(),
108
+ staleAfterMs = 120_000,
109
+ ): GateShardsFile {
110
+ const active = file.shards.filter((shard) => shard.state === 'running' || shard.state === 'retry');
111
+ if (!active.length) return file;
112
+ const at = now.getTime();
113
+ const ready = active.map((shard) => {
114
+ const result = results.get(shard.id);
115
+ const resultTerminal = result?.completed === true && result.jobName === shard.job && result.attemptId === shard.attemptId;
116
+ const k8sTerminal = shard.job ? terminalJobs.get(shard.job) : undefined;
117
+ const startedAt = shard.startedAt ? Date.parse(shard.startedAt) : Number.NaN;
118
+ if (!resultTerminal && !k8sTerminal) return undefined;
119
+ if (!Number.isFinite(startedAt) || at - startedAt < staleAfterMs) return undefined;
120
+ return { shard, result, state: resultTerminal
121
+ ? (result!.reason === 'timeout' ? 'timeout' as const : result!.reason === 'stall' || result!.jobFailed === true ? 'failed' as const : 'done' as const)
122
+ : k8sTerminal === 'failed' ? 'failed' as const : 'done' as const };
123
+ });
124
+ const finalized = ready.filter((entry): entry is NonNullable<typeof entry> => entry !== undefined);
125
+ if (!finalized.length) return file;
126
+ const byId = new Map(finalized.map(({ shard, result, state }) => {
127
+ const current = { ...shard };
128
+ delete current.waitReason;
129
+ return [shard.id, { ...current, state, endedAt: now.toISOString(), ...(result && typeof result.rc === 'number' ? { rc: result.rc } : {}) } satisfies GateShard];
130
+ }));
131
+ return { ...file, updatedAt: now.toISOString(), shards: file.shards.map((shard) => byId.get(shard.id) ?? shard) };
132
+ }
133
+
73
134
  function verdictOf(value: unknown): GateShardsVerdict | undefined {
74
135
  if (!value || typeof value !== 'object') return undefined;
75
136
  const raw = value as Record<string, unknown>;
@@ -7,7 +7,7 @@ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
7
7
  import { tmpdir } from 'node:os';
8
8
  import { join } from 'node:path';
9
9
  import { debug } from '../debug/log.js';
10
- import { runSelfGateCli, type SelfGateCliOptions, type SelfGateCliResult } from '../self-implement/gate-cli.js';
10
+ import { runSelfGateCliAsync, type SelfGateCliOptions, type SelfGateCliResult } from '../self-implement/gate-cli.js';
11
11
  import { dispatchHeavyCheck, isValidGateHost, type DispatchDeps, type DispatchOptions } from '../self-implement/gate-remote.js';
12
12
  import { latestPublishedPreviousVersion } from '../../scripts/release-loop/unattended-release.js';
13
13
  import { baseVersion, isReleaseVersion } from '../../scripts/release-loop/release-version.js';
@@ -29,6 +29,8 @@ export interface LightRcOptions {
29
29
  /** Run on this machine (the remote child is re-invoked with it). */
30
30
  local?: boolean;
31
31
  shards?: number;
32
+ /** Maximum simultaneously active gate bundles, including per-file RSS samples (default three). */
33
+ shardConcurrency?: number;
32
34
  /** OP FU — pass `--fixed-shard-distribution` to self gate (sorted round-robin into `shards`, no RSS pre-measurement).
33
35
  * Opt-in; absent = the measured planner, unchanged. Also carried to the remote child. */
34
36
  fixedShardDistribution?: boolean;
@@ -71,7 +73,7 @@ export interface LightRcDeps {
71
73
  git?: (args: string[], cwd: string) => { rc: number | null; stdout: string };
72
74
  previousVersion?: (version: string, ledgerRoot?: string) => string;
73
75
  readFile?: (path: string) => string | undefined;
74
- runGate?: (cwd: string, options: SelfGateCliOptions) => SelfGateCliResult;
76
+ runGate?: (cwd: string, options: SelfGateCliOptions) => SelfGateCliResult | Promise<SelfGateCliResult>;
75
77
  dispatch?: (opts: DispatchOptions, deps?: DispatchDeps) => Promise<number>;
76
78
  /** Extra dispatch deps (runner · settings) — tests drive the real dispatch with a fake host. */
77
79
  dispatchDeps?: Omit<DispatchDeps, 'write'>;
@@ -175,6 +177,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
175
177
  if (!isReleaseVersion(version)) throw new Error(`release version must be x.y.z: ${version}`);
176
178
  const shards = opts.shards ?? LIGHT_RC_DEFAULT_SHARDS;
177
179
  if (!Number.isSafeInteger(shards) || shards < 1) throw new Error(`invalid --shards count: ${opts.shards}`);
180
+ if (opts.shardConcurrency !== undefined && (!Number.isSafeInteger(opts.shardConcurrency) || opts.shardConcurrency < 1 || opts.shardConcurrency > 4)) throw new Error(`invalid --shard-concurrency: ${opts.shardConcurrency}`);
178
181
  if (opts.remote !== undefined && !isValidGateHost(opts.remote)) throw new Error(`invalid --remote host: ${opts.remote}`);
179
182
  const log = opts.log ?? ((line: string) => process.stderr.write(`${line}\n`));
180
183
  const cwd = repoRoot(deps);
@@ -195,7 +198,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
195
198
  try {
196
199
  const dir = checkout?.dir ?? cwd;
197
200
  if (checkout) alwaysInclude = readList(dir);
198
- local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), alwaysInclude, includeImporterTests: true });
201
+ local = await (deps.runGate ?? runSelfGateCliAsync)(dir, { base, shards, ...(opts.shardConcurrency !== undefined ? { shardConcurrency: opts.shardConcurrency } : {}), ...(opts.fixedShardDistribution ? { fixedShardDistribution: true } : {}), alwaysInclude, includeImporterTests: true });
199
202
  if (opts.rehearsalTui) {
200
203
  const command = async (cmd: string, args: string[], tree: string, limitMs?: number) => {
201
204
  const run = spawnSync(cmd, args, { cwd: tree, encoding: 'utf8', timeout: limitMs });
@@ -212,7 +215,7 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
212
215
  // Keep the self-gate contract: an unavailable remote leaves this release check unmeasured; do not start a heavy gate locally.
213
216
  tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
214
217
  // The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
215
- remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), ...(opts.fixedShardDistribution ? ['--fixed-shard-distribution'] : []), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
218
+ remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), ...(opts.shardConcurrency !== undefined ? ['--shard-concurrency', String(opts.shardConcurrency)] : []), ...(opts.fixedShardDistribution ? ['--fixed-shard-distribution'] : []), '--local', '--json', ...(opts.rehearsalTui ? ['--rehearsal-tui'] : [])],
216
219
  flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
217
220
  runLocal,
218
221
  }, {
@@ -7,7 +7,7 @@ import { listChecklist, setItem } from './checklist.js';
7
7
  import { judgeLandedCell } from './landed-to-green.js';
8
8
  import { evidencePlan, landedButYellow, type MergedChecklistPr } from './landed-but-yellow.js';
9
9
  import { assignedVersions, evidenceAdd } from './feature-store.js';
10
- import { boundMergedTaskCells, candidateMergedTaskCells, closeMergedTaskCard } from '../task-agent/postland-card.js';
10
+ import { boundMergedTaskCells, candidateMergedTaskCells, closeMergedTaskCard, recordMergedTaskImplFindings } from '../task-agent/postland-card.js';
11
11
 
12
12
  export interface MergedPrChecklistDeps {
13
13
  readPr?: (number: number, cwd: string) => { state: string; baseRefName: string; title: string; body: string | null; mergedAt: string; url?: string; headRefOid?: string; files?: Array<{ path: string }> };
@@ -19,13 +19,19 @@ export interface MergedPrChecklistDeps {
19
19
  closeTaskCard?: typeof closeMergedTaskCard;
20
20
  boundTaskCells?: typeof boundMergedTaskCells;
21
21
  candidateTaskCells?: typeof candidateMergedTaskCells;
22
+ feedbackStatePath?: string;
23
+ feedbackFollowUp?: NonNullable<Parameters<typeof recordMergedTaskImplFindings>[2]>['followUp'];
22
24
  log?: typeof debug.log;
23
25
  }
24
26
 
27
+ function readMergedPr(number: number, cwd: string): NonNullable<MergedPrChecklistDeps['readPr']> extends (number: number, cwd: string) => infer T ? T : never {
28
+ return JSON.parse(execFileSync('gh', ['pr', 'view', String(number), '--json', 'state,baseRefName,title,body,mergedAt,url,headRefOid,files'], { cwd, encoding: 'utf8', timeout: 30_000 }));
29
+ }
30
+
25
31
  /** A confirmed main merge is the only entry. The existing checklist matcher owns PR-to-cell decisions. */
26
32
  export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: string, deps: MergedPrChecklistDeps = {}): void {
27
33
  const log = deps.log ?? debug.log.bind(debug);
28
- const pr = (deps.readPr ?? ((n, dir) => JSON.parse(execFileSync('gh', ['pr', 'view', String(n), '--json', 'state,baseRefName,title,body,mergedAt,url,headRefOid,files'], { cwd: dir, encoding: 'utf8', timeout: 30_000 })) as ReturnType<NonNullable<MergedPrChecklistDeps['readPr']>>))(number, cwd);
34
+ const pr = (deps.readPr ?? readMergedPr)(number, cwd);
29
35
  if (pr.state !== 'MERGED' || pr.baseRefName !== 'main') return;
30
36
  const merged: MergedChecklistPr = { number, title: pr.title, body: pr.body, mergedAt: pr.mergedAt };
31
37
  const versions = deps.versions?.() ?? (() => {
@@ -116,6 +122,23 @@ export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: st
116
122
  for (const id of missing) log('release.checklist', 'merged-pr-cell-not-found', { pr: number, id });
117
123
  }
118
124
 
125
+ /** Production merge entry: reconcile synchronously, then await idempotent PR-body feedback before returning. */
126
+ export async function syncMergedPrChecklistWithFeedback(
127
+ number: number,
128
+ cwd: string,
129
+ goalFile?: string,
130
+ deps: MergedPrChecklistDeps = {},
131
+ ): Promise<Awaited<ReturnType<typeof recordMergedTaskImplFindings>>> {
132
+ const pr = (deps.readPr ?? readMergedPr)(number, cwd);
133
+ syncMergedPrChecklist(number, cwd, goalFile, { ...deps, readPr: () => pr });
134
+ if (pr.url && pr.headRefOid) {
135
+ return await recordMergedTaskImplFindings({ ...pr, number, url: pr.url, headRefOid: pr.headRefOid }, cwd,
136
+ { ...(deps.feedbackStatePath ? { statePath: deps.feedbackStatePath } : {}),
137
+ ...(deps.feedbackFollowUp ? { followUp: deps.feedbackFollowUp } : {}) });
138
+ }
139
+ return null;
140
+ }
141
+
119
142
  const LABEL_IDS = '([A-Za-z0-9_-]+(?:[ \\t]*(?:,|·)[ \\t]*[A-Za-z0-9_-]+)*)';
120
143
  const LABEL_END = '(?=[ \\t]*$|[ \\t]+[—–·(-])';
121
144
  const DESIGNATION = new RegExp(`^ {0,3}(?:#{1,6}[ \\t]+|[-*][ \\t]+)?칸[ \\t]*:[ \\t]*${LABEL_IDS}${LABEL_END}`);
@@ -87,7 +87,12 @@ export function planRehearsalShards(version: string, root: string, checkout: str
87
87
  let gatePlanShards: number | null = null;
88
88
  try {
89
89
  const board = (deps.board ?? readGateShards)(gateShardsPath(version, root));
90
- gatePlanShards = board?.version === version && board.shards.length && new Set(board.shards.map(shard => shard.id)).size === board.shards.length ? board.shards.length : null;
90
+ if (board?.version === version && board.shards.length
91
+ && new Set(board.shards.map(shard => shard.id)).size === board.shards.length) {
92
+ // Split/retry/tail rows are observations, not extra planned shards. Older boards used arbitrary IDs.
93
+ const roots = board.shards.filter(shard => /^pod-\d+$/.test(shard.id));
94
+ gatePlanShards = roots.length || (board.shards.some(shard => /^pod-\d+/.test(shard.id)) ? null : board.shards.length);
95
+ }
91
96
  } catch (error) { reasons.push(`persisted gate shard plan unreadable: ${error instanceof Error ? error.message : String(error)}`); }
92
97
  let testFiles: number | null = null;
93
98
  let measuredFiles = 0;
@@ -67,6 +67,15 @@ export function planRehearsal(schedules: readonly ReleaseSchedule[], now: Date,
67
67
  return { status: 'not-yet', version, cutAt, nextStepAt: new Date(cut - open[0]!.minutes * minute).toISOString() };
68
68
  }
69
69
 
70
+ export interface RehearsalRecovery {
71
+ failedShard: string;
72
+ remeasuredFiles: number | null;
73
+ durationMs: number | null;
74
+ poolOverwriteApplied: boolean | null;
75
+ outcome: 'ok' | 'failed';
76
+ error?: string;
77
+ }
78
+
70
79
  export interface RehearsalStamp {
71
80
  version: string;
72
81
  step: StepId;
@@ -79,6 +88,7 @@ export interface RehearsalStamp {
79
88
  regressionFiles?: string[];
80
89
  result?: LightRcResult;
81
90
  hardGate?: HardGateResult;
91
+ recovery?: RehearsalRecovery;
82
92
  hardGateRunId?: string;
83
93
  hardGateLog?: string;
84
94
  /** B6: an unmeasured hard gate always retains a cause, run id and durable local evidence path. */
@@ -94,6 +104,7 @@ export interface RehearsalOptions {
94
104
  apply?: boolean;
95
105
  checkout?: string;
96
106
  ledgerRoot?: string;
107
+ recoveryRun?: string;
97
108
  shards?: number;
98
109
  remote?: string;
99
110
  }
@@ -109,6 +120,7 @@ export interface RehearsalDeps {
109
120
  notify?: (text: string) => void | boolean | Promise<void | boolean>;
110
121
  git?: (args: string[], cwd: string) => { rc: number | null; stdout: string; stderr?: string };
111
122
  leakCheck?: (checkout: string) => { status: number | null; detail?: string };
123
+ resumeGate?: (runId: string, checkout: string) => Promise<{ files: number; durationMs: number; poolOverwriteApplied: boolean; ok: boolean }>;
112
124
  }
113
125
 
114
126
  export type RehearsalTickResult = RehearsalPlan & { applied?: boolean; stamps?: RehearsalStamp[]; notificationFailures?: number };
@@ -495,7 +507,7 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
495
507
  const introducedCount: number | null = stamp.outcome === 'unmeasured' || stamp.outcome === 'error' ? null : hard.introduced.length;
496
508
  const preexistingCount: number | null = introducedCount === null ? null : hard.preexisting;
497
509
  const totalFailures: number | null = introducedCount === null || preexistingCount === null ? null : introducedCount + preexistingCount;
498
- stamp.summary = oneLine(`hard gate ${hard.outcome} · introduced ${introducedCount ?? 'UNKNOWN'} · preexisting ${preexistingCount ?? 'UNKNOWN'} · total failures ${totalFailures ?? 'UNKNOWN'} · node-b Pod · 12 shards · runId ${hardGateRunId} · evidence ${hardGateLog}${cause ? ` · ${cause}` : ''}`);
510
+ stamp.summary = oneLine(`hard gate ${hard.outcome} · introduced ${introducedCount ?? 'UNKNOWN'} · preexisting ${preexistingCount ?? 'UNKNOWN'} · total failures ${totalFailures ?? 'UNKNOWN'} · 원격 Pod · 12 shards · runId ${hardGateRunId} · evidence ${hardGateLog}${cause ? ` · ${cause}` : ''}`);
499
511
  } else {
500
512
  const shardPlan = opts.shards === undefined ? (deps.shardPlan ?? planRehearsalShards)(plan.version, root, checkout, { ...deps.shardPlanDeps, remoteGate: true }) : undefined;
501
513
  if (shardPlan) stamp.shardPlan = shardPlan;
@@ -520,6 +532,21 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
520
532
  console.error(line);
521
533
  } }, { cwd })))(plan.version, checkout, selection);
522
534
  stamp.result = result;
535
+ if (opts.recoveryRun && result.unmeasured !== null) {
536
+ const failedShard = result.unmeasured;
537
+ const started = Date.now();
538
+ try {
539
+ const recovered = await deps.resumeGate?.(opts.recoveryRun, checkout);
540
+ if (!recovered) throw new Error('release resume --from gate is unavailable for this rehearsal');
541
+ stamp.recovery = { failedShard, remeasuredFiles: recovered.files, durationMs: recovered.durationMs,
542
+ poolOverwriteApplied: recovered.poolOverwriteApplied, outcome: recovered.ok ? 'ok' : 'failed',
543
+ ...(!recovered.ok ? { error: 'resumed gate did not pass' } : {}) };
544
+ } catch (error) {
545
+ stamp.recovery = { failedShard, remeasuredFiles: null, durationMs: Math.max(0, Date.now() - started),
546
+ poolOverwriteApplied: null, outcome: 'failed',
547
+ error: oneLine(error instanceof Error ? error.message : String(error)) };
548
+ }
549
+ }
523
550
  if (regressionFiles.length) stamp.regressionFiles = regressionFiles;
524
551
  const shardMismatch = selection.shards !== undefined && result.shards !== selection.shards
525
552
  ? `selected shards ${selection.shards} but RC reported ${result.shards}` : null;
package/src/repl/index.ts CHANGED
@@ -198,6 +198,7 @@ function buildReplTools(): {
198
198
  specs.push(wakeup.spec);
199
199
  dispatchByName.set(wakeup.spec.name, wakeup.dispatch);
200
200
  }
201
+ (require('../tui/sidetab/nl-tool.js') as typeof import('../tui/sidetab/nl-tool.js')).registerNextSidetabReplTool(specs, dispatchByName, process as unknown as import('../tui/sidetab/nl-tool.js').NextSidetabIpcProcess);
201
202
  const planner = sr.createSearchPlannerState({ maxAutoNarrowCandidates: 2 });
202
203
  const dispatch = async (name: string, args: Record<string, unknown>): Promise<unknown> => {
203
204
  try {
@@ -342,6 +343,7 @@ async function runOneTurn(
342
343
  jsonOutput: boolean,
343
344
  nextTuiDelivery?: { pending: PendingTaskNotification[] },
344
345
  onJsonDelta?: (delta: string) => void,
346
+ onJsonStatus?: (line: string) => void,
345
347
  ): Promise<{ reply: string; provider: string; model: string | null; durationMs: number; logPath: string | null }> {
346
348
  const startedAt = Date.now();
347
349
  const replyChunks: string[] = [];
@@ -374,6 +376,10 @@ async function runOneTurn(
374
376
  userText,
375
377
  systemPrompt,
376
378
  userImages: userImages.length > 0 ? userImages : undefined,
379
+ ...(process.env.ELANOUS_TEST_FAKE_LLM === '1' && Number.isFinite(Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS))
380
+ && Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS) > 0
381
+ ? { llmOpts: { streamIdleTimeoutMs: Number(process.env.ELANOUS_TEST_FAKE_LLM_IDLE_TIMEOUT_MS) } }
382
+ : {}),
377
383
  onDelta: (d) => {
378
384
  if (jsonOutput) {
379
385
  replyChunks.push(d);
@@ -381,6 +387,7 @@ async function runOneTurn(
381
387
  }
382
388
  else process.stdout.write(d);
383
389
  },
390
+ onStatusLine: (line) => { onJsonStatus?.(line); },
384
391
  tools: replToolSpecs,
385
392
  dispatchTool: tools?.dispatch,
386
393
  onToolCall: (call) => {
@@ -785,6 +792,9 @@ export async function runRepl(opts: ReplOpts): Promise<number> {
785
792
  process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
786
793
  ? (delta) => { process.stdout.write(`${JSON.stringify({ event: 'delta', turnId: turn.id, text: delta })}\n`); }
787
794
  : undefined,
795
+ process.env.ELANOUS_NEXT_TUI_STREAM === '1' && typeof turn.id === 'string'
796
+ ? (text) => { process.stdout.write(`${JSON.stringify({ event: 'status', turnId: turn.id, text })}\n`); }
797
+ : undefined,
788
798
  );
789
799
  } catch (error) {
790
800
  if (!backgroundBridge) throw error;
@@ -0,0 +1,133 @@
1
+ // Research-only native fanout. The caller supplies Bloom's question ladder;
2
+ // each axis gets its own direct tool call and evidence stays attributed to it.
3
+ import type { BloomResearchQuestion, ResearchEvidenceEnvelope } from '../auto-research/question-ladder-contract.js';
4
+ import type { WebSearchHit } from '../web-search/provider.js';
5
+
6
+ export interface AxisToolCallPlan {
7
+ questionId: string;
8
+ tool: 'OmniSearch';
9
+ query: string;
10
+ }
11
+
12
+ export interface AxisEvidenceGroup {
13
+ questionId: string;
14
+ evidence: ResearchEvidenceEnvelope[];
15
+ error?: string;
16
+ }
17
+
18
+ export interface AxisFanoutResult {
19
+ plan: AxisToolCallPlan[];
20
+ axes: AxisEvidenceGroup[];
21
+ }
22
+
23
+ export type AxisSearchHit = WebSearchHit & { engine?: string };
24
+ export interface AxisSearchResult {
25
+ hits: AxisSearchHit[];
26
+ errors: string[];
27
+ }
28
+ export type AxisSearch = (query: string) => Promise<AxisSearchHit[] | AxisSearchResult>;
29
+
30
+ export interface AxisFanoutDeps {
31
+ search?: AxisSearch;
32
+ }
33
+
34
+ /** Keep every query attached to the Bloom question that produced it. */
35
+ export function planAxisToolCalls(questions: readonly BloomResearchQuestion[]): AxisToolCallPlan[] {
36
+ return questions.flatMap(question => question.searchTerms
37
+ .map(query => query.trim())
38
+ .filter(Boolean)
39
+ .map(query => ({ questionId: question.id, tool: 'OmniSearch' as const, query })));
40
+ }
41
+
42
+ async function directOmniSearch(query: string): Promise<AxisSearchResult> {
43
+ const { dispatchOmniSearch } = await import('../skills/tools/omni-search.js');
44
+ const hits: AxisSearchHit[] = [];
45
+ const result = await dispatchOmniSearch({ query }, { onSource: hit => { hits.push(hit); } });
46
+ if (Object.keys(result.metadata.perEngine).length === 0) {
47
+ throw new Error('no available web-search providers');
48
+ }
49
+ const errors = Object.entries(result.metadata.perEngine)
50
+ .flatMap(([engine, info]) => info.error ? [`${engine}: ${info.error}`] : []);
51
+ return { hits, errors };
52
+ }
53
+
54
+ function evidenceFromHit(question: BloomResearchQuestion, hit: AxisSearchHit): ResearchEvidenceEnvelope {
55
+ const published = hit.publishedAt;
56
+ const date = published !== undefined && Number.isFinite(published) && published > 0
57
+ ? new Date(published) : undefined;
58
+ const observedAt = date && Number.isFinite(date.getTime()) ? date.toISOString() : undefined;
59
+ return {
60
+ questionId: question.id,
61
+ sourceKind: hit.engine ? `web-search:${hit.engine}` : 'web-search',
62
+ source: hit.url,
63
+ ...(question.requestedWindow ? { requestedWindow: question.requestedWindow } : {}),
64
+ ...(observedAt ? { observedAt } : {}),
65
+ content: [hit.title, hit.snippet].filter(Boolean).join(' — '),
66
+ outcome: hit.snippet ? 'complete' : 'partial',
67
+ truncated: true, // Search snippets are excerpts, not the complete source page.
68
+ };
69
+ }
70
+
71
+ function failedEvidence(question: BloomResearchQuestion, query: string, message: string): ResearchEvidenceEnvelope {
72
+ return {
73
+ questionId: question.id,
74
+ sourceKind: 'search-query',
75
+ source: query,
76
+ ...(question.requestedWindow ? { requestedWindow: question.requestedWindow } : {}),
77
+ content: message,
78
+ outcome: 'failed',
79
+ truncated: false,
80
+ };
81
+ }
82
+
83
+ /** Invoke all axis queries concurrently, preserving ladder order and partial failures. */
84
+ export async function fanOutAxisEvidence(
85
+ questions: readonly BloomResearchQuestion[],
86
+ deps: AxisFanoutDeps = {},
87
+ ): Promise<AxisFanoutResult> {
88
+ const plan = planAxisToolCalls(questions);
89
+ if (new Set(questions.map(question => question.id)).size !== questions.length) {
90
+ throw new Error('research axis question IDs must be unique');
91
+ }
92
+ const search = deps.search ?? directOmniSearch;
93
+ const settled = await Promise.allSettled(plan.map(call => search(call.query)));
94
+ const axes: AxisEvidenceGroup[] = questions.map(question => ({ questionId: question.id, evidence: [] }));
95
+ const groups = new Map(axes.map(axis => [axis.questionId, axis]));
96
+ const byQuestion = new Map(questions.map(question => [question.id, question]));
97
+ for (const question of questions) {
98
+ if (!plan.some(call => call.questionId === question.id)) {
99
+ const group = groups.get(question.id)!;
100
+ group.error = 'no search terms';
101
+ group.evidence.push(failedEvidence(question, question.prompt, group.error));
102
+ }
103
+ }
104
+ settled.forEach((outcome, index) => {
105
+ const call = plan[index]!;
106
+ const group = groups.get(call.questionId)!;
107
+ const question = byQuestion.get(call.questionId)!;
108
+ if (outcome.status === 'fulfilled') {
109
+ const response = Array.isArray(outcome.value) ? { hits: outcome.value, errors: [] } : outcome.value;
110
+ if (response.hits.length === 0 && response.errors.length === 0) {
111
+ group.evidence.push({ ...failedEvidence(question, call.query, 'no hits returned'), outcome: 'partial' });
112
+ }
113
+ for (const hit of response.hits) {
114
+ try {
115
+ group.evidence.push(evidenceFromHit(question, hit));
116
+ } catch (err) {
117
+ const message = err instanceof Error ? err.message : String(err);
118
+ group.error = group.error ? `${group.error}; ${message}` : message;
119
+ group.evidence.push(failedEvidence(question, call.query, message));
120
+ }
121
+ }
122
+ for (const message of response.errors) {
123
+ group.error = group.error ? `${group.error}; ${message}` : message;
124
+ group.evidence.push(failedEvidence(question, call.query, message));
125
+ }
126
+ } else {
127
+ const message = outcome.reason instanceof Error ? outcome.reason.message : String(outcome.reason);
128
+ group.error = group.error ? `${group.error}; ${message}` : message;
129
+ group.evidence.push(failedEvidence(question, call.query, message));
130
+ }
131
+ });
132
+ return { plan, axes };
133
+ }
@@ -0,0 +1,197 @@
1
+ import type { GraphNodeSpec } from '../self-implement/graph-yaml.js';
2
+
3
+ /** Opaque Bloom 4/5 output. The hook owns the decision boundary, not analysis policy. */
4
+ export interface BloomEdgeAssessment {
5
+ gaps: readonly unknown[];
6
+ contradictions: readonly unknown[];
7
+ verdicts: readonly unknown[];
8
+ }
9
+
10
+ export type ResearchEdgeAction = 'add' | 'prune' | 'deepen' | 'stop';
11
+
12
+ export interface ResearchEdgeProposal {
13
+ node: GraphNodeSpec;
14
+ returnTo?: string;
15
+ reason: string;
16
+ }
17
+
18
+ export interface ResearchEdgeDecision {
19
+ action: ResearchEdgeAction;
20
+ reason: string;
21
+ evidence: readonly string[];
22
+ /** Ordinal-free, explicitly supplied strength on [0, 1]; never inferred from votes. */
23
+ evidenceStrength?: number;
24
+ /** Optional T3 record-only confidence; never changes the live edge decision. */
25
+ confidence?: number;
26
+ counterEvidenceRefs?: readonly string[];
27
+ outsideViewRefs?: readonly string[];
28
+ proposal?: ResearchEdgeProposal;
29
+ }
30
+
31
+ export interface ResolvedResearchEdgeDecision extends ResearchEdgeDecision {
32
+ provider: string;
33
+ }
34
+
35
+ /** T3 evidence is retained beside the current live decision, never applied to it. */
36
+ export interface ResearchEdgeDecisionEnvelope extends ResolvedResearchEdgeDecision {
37
+ recommendation?: ResolvedResearchEdgeDecision;
38
+ votes: readonly ResolvedResearchEdgeDecision[];
39
+ dissent: readonly ResolvedResearchEdgeDecision[];
40
+ counterEvidenceRefs: readonly string[];
41
+ outsideViewRefs: readonly string[];
42
+ agreesWithLive?: boolean;
43
+ mode: 'record-only';
44
+ }
45
+
46
+ export type ResearchEdgeDecisionProvider = (
47
+ assessment: BloomEdgeAssessment,
48
+ ) => ResearchEdgeDecision | Promise<ResearchEdgeDecision>;
49
+
50
+ export interface ResearchEdgeDecisionRegistry {
51
+ register(provider: ResearchEdgeDecisionProvider, name?: string, options?: { priority?: number }): () => void;
52
+ decide(assessment: BloomEdgeAssessment): Promise<ResearchEdgeDecisionEnvelope>;
53
+ }
54
+
55
+ const noOpDecision: ResearchEdgeDecision = {
56
+ action: 'stop',
57
+ reason: 'no edge decision provider registered',
58
+ evidence: [],
59
+ };
60
+
61
+ /** One registry belongs to one run. With no provider, the graph takes one round and stops. */
62
+ export function createResearchEdgeDecisionRegistry(): ResearchEdgeDecisionRegistry {
63
+ const providers = new Map<symbol, { name: string; decide: ResearchEdgeDecisionProvider; priority?: number }>();
64
+ return {
65
+ register(provider, name = 'registered', options = {}) {
66
+ if (options.priority !== undefined && !Number.isFinite(options.priority)) {
67
+ throw new TypeError('research edge provider priority must be finite when supplied');
68
+ }
69
+ const key = Symbol('research-edge-decision-provider');
70
+ providers.set(key, { name, decide: provider, ...(options.priority === undefined ? {} : { priority: options.priority }) });
71
+ return () => { providers.delete(key); };
72
+ },
73
+ async decide(assessment) {
74
+ const entries = [...providers.values()];
75
+ if (!entries.length) return envelope({ ...noOpDecision, provider: 'default-noop' }, []);
76
+ const results = await Promise.all(entries.map(async (entry) => {
77
+ try {
78
+ const decision = await entry.decide(assessment);
79
+ return isResearchEdgeDecision(decision)
80
+ ? { entry, decision }
81
+ : { entry, error: 'returned an invalid decision' };
82
+ } catch (error) {
83
+ return { entry, error: `failed: ${String(error)}` };
84
+ }
85
+ }));
86
+ const valid = results.filter((result): result is { entry: typeof entries[number]; decision: ResearchEdgeDecision } => 'decision' in result);
87
+ const failures = results.filter((result): result is { entry: typeof entries[number]; error: string } => 'error' in result);
88
+ if (!valid.length) return envelope({ action: 'stop', reason: `all edge decision providers failed: ${failures.map(({ entry, error }) => `${entry.name} ${error}`).join('; ')}`, evidence: [], provider: 'composition' }, []);
89
+ if (valid.length === 1 && !failures.length) {
90
+ const [{ entry, decision }] = valid;
91
+ const live = { ...decision, evidence: [...decision.evidence], provider: entry.name };
92
+ return envelope(live, votes(valid));
93
+ }
94
+
95
+ // Agreement composes evidence. Disagreement is resolved by declared evidence strength,
96
+ // then explicit provider priority; an unresolved tie fails closed instead of voting.
97
+ const actions = new Set(valid.map(({ decision }) => decision.action));
98
+ const proposalKeys = new Set(valid.filter(({ decision }) => decision.action === 'add')
99
+ .map(({ decision }) => JSON.stringify(decision.proposal)));
100
+ const conflict = actions.size > 1 || proposalKeys.size > 1;
101
+ let candidates = valid;
102
+ if (conflict) {
103
+ const ranked = valid.map((result) => ({ ...result,
104
+ strength: result.decision.evidenceStrength ?? -1,
105
+ })).sort((a, b) => b.strength - a.strength);
106
+ const top = ranked[0]!;
107
+ const tiedStrength = ranked.filter((item) => item.strength === top.strength);
108
+ if (tiedStrength.length > 1 && tiedStrength.some((item) => item.entry.priority === undefined)) return envelope({
109
+ action: 'stop', reason: `unresolved edge decision conflict: ${tiedStrength.map(({ entry }) => entry.name).join(', ')} (priority unspecified)`,
110
+ evidence: [...new Set(valid.flatMap(({ decision }) => decision.evidence))], provider: 'composition',
111
+ }, votes(valid));
112
+ tiedStrength.sort((a, b) => (b.entry.priority ?? 0) - (a.entry.priority ?? 0));
113
+ const winner = tiedStrength[0]!;
114
+ const tied = tiedStrength.filter((item) => item.entry.priority === winner.entry.priority);
115
+ if (tied.length > 1) return envelope({
116
+ action: 'stop', reason: `unresolved edge decision conflict: ${tied.map(({ entry }) => entry.name).join(', ')}`,
117
+ evidence: [...new Set(valid.flatMap(({ decision }) => decision.evidence))], provider: 'composition',
118
+ }, votes(valid));
119
+ candidates = [winner];
120
+ }
121
+ const winner = candidates[0]!;
122
+ const evidence = [...new Set(valid.flatMap(({ decision }) => decision.evidence))];
123
+ const contributors = valid.map(({ entry }) => entry.name).join(', ');
124
+ const notes = failures.map(({ entry, error }) => `${entry.name} ${error}`);
125
+ const reason = conflict
126
+ ? `conflict resolved by ${winner.entry.name} (strength=${winner.decision.evidenceStrength ?? 'unspecified'}, priority=${winner.entry.priority ?? 'unspecified'}); ${winner.decision.reason}`
127
+ : `composed ${contributors}: ${winner.decision.reason}`;
128
+ const evidenceNote = evidence.length ? `; evidence=${evidence.join(' | ')}` : '';
129
+ const live = { ...winner.decision, reason: [...notes, `${reason}${evidenceNote}`].join('; '), evidence, provider: conflict ? winner.entry.name : `composition[${contributors}]` };
130
+ return envelope(live, votes(valid));
131
+ },
132
+ };
133
+ }
134
+
135
+ function isResearchEdgeDecision(value: unknown): value is ResearchEdgeDecision {
136
+ if (!isRecord(value) || !['add', 'prune', 'deepen', 'stop'].includes(String(value.action))
137
+ || typeof value.reason !== 'string' || !value.reason.trim()
138
+ || !Array.isArray(value.evidence) || !value.evidence.every((item) => typeof item === 'string')
139
+ || (value.evidenceStrength !== undefined && (typeof value.evidenceStrength !== 'number'
140
+ || !Number.isFinite(value.evidenceStrength) || value.evidenceStrength < 0 || value.evidenceStrength > 1))) {
141
+ return false;
142
+ }
143
+ if (value.action === 'add') return isResearchEdgeProposal(value.proposal);
144
+ return value.proposal === undefined;
145
+ }
146
+
147
+ function votes(valid: readonly { entry: { name: string }; decision: ResearchEdgeDecision }[]): ResolvedResearchEdgeDecision[] {
148
+ return valid.map(({ entry, decision }) => {
149
+ const confidence = typeof decision.confidence === 'number' && Number.isFinite(decision.confidence)
150
+ && decision.confidence >= 0 && decision.confidence <= 1 ? decision.confidence : undefined;
151
+ const counterEvidenceRefs = Array.isArray(decision.counterEvidenceRefs)
152
+ ? decision.counterEvidenceRefs.filter((item): item is string => typeof item === 'string') : [];
153
+ const outsideViewRefs = Array.isArray(decision.outsideViewRefs)
154
+ ? decision.outsideViewRefs.filter((item): item is string => typeof item === 'string') : [];
155
+ return {
156
+ ...decision,
157
+ ...(confidence === undefined ? { confidence: undefined } : { confidence }),
158
+ counterEvidenceRefs,
159
+ outsideViewRefs,
160
+ evidence: [...decision.evidence],
161
+ provider: entry.name,
162
+ };
163
+ });
164
+ }
165
+
166
+ function envelope(live: ResolvedResearchEdgeDecision, recordedVotes: readonly ResolvedResearchEdgeDecision[]): ResearchEdgeDecisionEnvelope {
167
+ const scored = recordedVotes.filter((vote) => vote.confidence !== undefined);
168
+ const strongest = scored.length ? Math.max(...scored.map((vote) => vote.confidence!)) : undefined;
169
+ const leaders = strongest === undefined ? [] : scored.filter((vote) => vote.confidence === strongest);
170
+ const leaderActions = new Set(leaders.map(({ action }) => action));
171
+ const leaderPayloads = new Set(leaders.map(({ action, proposal }) => JSON.stringify({ action, proposal })));
172
+ const recommendation = !leaders.length ? undefined
173
+ : leaderActions.size > 1 || leaderPayloads.size > 1
174
+ ? { action: 'stop' as const, reason: 'conflicting strongest evidence', evidence: [...new Set(leaders.flatMap(({ evidence }) => evidence))], confidence: strongest, provider: 'evidence-composer' }
175
+ : leaders[0];
176
+ const sameLive = (vote: ResolvedResearchEdgeDecision) => vote.action === live.action && JSON.stringify(vote.proposal) === JSON.stringify(live.proposal);
177
+ return {
178
+ ...live,
179
+ votes: [...recordedVotes],
180
+ dissent: recommendation ? recordedVotes.filter((vote) => vote.action !== recommendation.action || JSON.stringify(vote.proposal) !== JSON.stringify(recommendation.proposal)) : [],
181
+ counterEvidenceRefs: [...new Set(recordedVotes.flatMap((vote) => vote.counterEvidenceRefs ?? []))],
182
+ outsideViewRefs: [...new Set(recordedVotes.flatMap((vote) => vote.outsideViewRefs ?? []))],
183
+ ...(recommendation ? { recommendation, agreesWithLive: sameLive(recommendation) } : {}),
184
+ mode: 'record-only',
185
+ };
186
+ }
187
+
188
+ function isResearchEdgeProposal(value: unknown): value is ResearchEdgeProposal {
189
+ return isRecord(value) && isRecord(value.node) && typeof value.node.nodeId === 'string'
190
+ && typeof value.node.kind === 'string' && typeof value.node.recipe === 'string'
191
+ && typeof value.reason === 'string' && value.reason.trim().length > 0
192
+ && (value.returnTo === undefined || typeof value.returnTo === 'string');
193
+ }
194
+
195
+ function isRecord(value: unknown): value is Record<string, unknown> {
196
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
197
+ }