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
@@ -118,6 +118,8 @@ export interface EnhanceOpts {
118
118
  * ⭐ 새 LLM 경로를 만들지 않는다 — 이 모듈이 이미 그 자리의 유일한 LLM 단계다.
119
119
  */
120
120
  groundedFacts?: readonly string[];
121
+ /** Relevant prior-failure lessons for goal-authoring prompts only; never part of the original ask. */
122
+ authoringLessons?: string;
121
123
  /** Clock seam for the first-token observation (ms epoch); defaults to `Date.now`. */
122
124
  now?: () => number;
123
125
  }
@@ -434,6 +436,9 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
434
436
  '위 사실을 «옮겨 적지 말고», 그것이 보여 주는 상태(situation)와 문제(complication)를 써라.',
435
437
  ]
436
438
  : []),
439
+ ...(opts.authoringLessons?.trim()
440
+ ? ['', '## 지난 실패에서 배운 것', opts.authoringLessons.trim(), '위 교훈은 현재 ask의 대상 경로와 범위에 맞을 때만 적용하고, 맞지 않으면 무시하라.']
441
+ : []),
437
442
  ].join('\n'),
438
443
  },
439
444
  ];
@@ -0,0 +1,132 @@
1
+ """Capture PTY state and retain the live descriptor for replay comparison."""
2
+
3
+ from dataclasses import dataclass
4
+ import fcntl
5
+ import json
6
+ import os
7
+ from pathlib import Path
8
+ import re
9
+ import select
10
+ import struct
11
+ import tempfile
12
+ import termios
13
+
14
+
15
+ DEFAULT_SNAPSHOT_ID = "pty_dee629e3"
16
+ _SCHEMA = 1
17
+ _LIVE_FDS: dict[str, int] = {}
18
+
19
+
20
+ @dataclass(eq=True)
21
+ class Snapshot:
22
+ snapshot_id: str
23
+ rows: int
24
+ cols: int
25
+ termios_attributes: list
26
+ output: str
27
+
28
+
29
+ @dataclass(eq=True)
30
+ class ReplayState:
31
+ snapshot: Snapshot
32
+ live_rows: int
33
+ live_cols: int
34
+ live_termios_attributes: list
35
+ matches_live: bool
36
+
37
+
38
+ def _location(snapshot_id: str) -> Path:
39
+ if not isinstance(snapshot_id, str) or not re.fullmatch(r"[A-Za-z0-9_-]+", snapshot_id):
40
+ raise ValueError("invalid snapshot id")
41
+ directory = Path(os.environ.get("ELANOUS_PTY_SNAPSHOT_DIR", tempfile.gettempdir() + "/elanous-pty-snapshots"))
42
+ return directory / (snapshot_id + ".json")
43
+
44
+
45
+ def _size(fd: int) -> tuple[int, int]:
46
+ rows, cols, _, _ = struct.unpack("HHHH", fcntl.ioctl(fd, termios.TIOCGWINSZ, b"\0" * 8))
47
+ return rows, cols
48
+
49
+
50
+ def _serialize_attrs(attrs: list) -> list:
51
+ return attrs[:6] + [[
52
+ {"bytes": entry.hex()} if isinstance(entry, bytes) else entry
53
+ for entry in attrs[6]
54
+ ]]
55
+
56
+
57
+ def _deserialize_attrs(value: object) -> list:
58
+ if not isinstance(value, list) or len(value) != 7 or any(
59
+ type(item) is not int for item in value[:6]
60
+ ) or not isinstance(value[6], list):
61
+ raise ValueError("invalid termios attributes")
62
+ controls = []
63
+ for item in value[6]:
64
+ if type(item) is int and 0 <= item <= 255:
65
+ controls.append(item)
66
+ elif isinstance(item, dict) and set(item) == {"bytes"} and isinstance(item["bytes"], str):
67
+ try:
68
+ controls.append(bytes.fromhex(item["bytes"]))
69
+ except ValueError as error:
70
+ raise ValueError("invalid termios control byte") from error
71
+ else:
72
+ raise ValueError("invalid termios control byte")
73
+ return value[:6] + [controls]
74
+
75
+
76
+ def snapshot(pty_fd: int, snapshot_id: str = DEFAULT_SNAPSHOT_ID) -> Snapshot:
77
+ """Drain currently available output from a PTY master and save its state."""
78
+ path = _location(snapshot_id)
79
+ rows, cols = _size(pty_fd)
80
+ attrs = termios.tcgetattr(pty_fd)
81
+ output = bytearray()
82
+ while select.select([pty_fd], [], [], 0)[0]:
83
+ chunk = os.read(pty_fd, 65536)
84
+ if not chunk:
85
+ break
86
+ output.extend(chunk)
87
+ captured = Snapshot(snapshot_id, rows, cols, attrs, output.decode("utf-8"))
88
+ payload = {
89
+ "schema": _SCHEMA,
90
+ "snapshot_id": snapshot_id,
91
+ "rows": rows,
92
+ "cols": cols,
93
+ "termios_attributes": _serialize_attrs(attrs),
94
+ "output": captured.output,
95
+ }
96
+ path.parent.mkdir(parents=True, exist_ok=True)
97
+ with tempfile.NamedTemporaryFile(mode="w", encoding="utf-8", dir=path.parent, delete=False) as file:
98
+ temporary = Path(file.name)
99
+ try:
100
+ json.dump(payload, file, ensure_ascii=False)
101
+ except BaseException:
102
+ temporary.unlink(missing_ok=True)
103
+ raise
104
+ temporary.replace(path)
105
+ _LIVE_FDS[snapshot_id] = pty_fd
106
+ return captured
107
+
108
+
109
+ def restore(snapshot_id: str = DEFAULT_SNAPSHOT_ID) -> ReplayState:
110
+ """Load a validated snapshot and compare it with its live PTY."""
111
+ path = _location(snapshot_id)
112
+ try:
113
+ payload = json.loads(path.read_text(encoding="utf-8"))
114
+ except (json.JSONDecodeError, UnicodeError) as error:
115
+ raise ValueError("invalid snapshot document") from error
116
+ if not isinstance(payload, dict) or set(payload) != {
117
+ "schema", "snapshot_id", "rows", "cols", "termios_attributes", "output"
118
+ } or type(payload["schema"]) is not int or payload["schema"] != _SCHEMA or payload["snapshot_id"] != snapshot_id or any(
119
+ type(payload[field]) is not int or not 0 <= payload[field] <= 65535 for field in ("rows", "cols")
120
+ ) or not isinstance(payload["output"], str):
121
+ raise ValueError("snapshot schema or id mismatch")
122
+ attrs = _deserialize_attrs(payload["termios_attributes"])
123
+ saved = Snapshot(snapshot_id, payload["rows"], payload["cols"], attrs, payload["output"])
124
+ if snapshot_id not in _LIVE_FDS:
125
+ raise RuntimeError("no live PTY registered for snapshot")
126
+ fd = _LIVE_FDS[snapshot_id]
127
+ live_rows, live_cols = _size(fd)
128
+ live_attrs = termios.tcgetattr(fd)
129
+ return ReplayState(
130
+ saved, live_rows, live_cols, live_attrs,
131
+ (live_rows, live_cols, live_attrs) == (saved.rows, saved.cols, saved.termios_attributes),
132
+ )
@@ -15,7 +15,7 @@ import { encodeSgrMouse, mouseModeOffReason, type PtyMouseInput } from './pty-mo
15
15
  import { startPtyRecording, stopPtyRecording } from './pty-recording.js';
16
16
  import { withExternalKeyCommand } from '../input/external-input-queue.js';
17
17
 
18
- const OWNER_PTY_CONTROL_ACTIONS = ['takeover', 'release', 'input-text', 'input-key', 'input-mouse', 'resize', 'snapshot', 'rename', 'terminate', 'capabilities', 'record-start', 'record-stop'] as const;
18
+ const OWNER_PTY_CONTROL_ACTIONS = ['takeover', 'release', 'input-text', 'input-key', 'input-mouse', 'resize', 'snapshot', 'rename', 'terminate', 'stop-turn', 'capabilities', 'record-start', 'record-stop'] as const;
19
19
  export type PtyControlAction = typeof OWNER_PTY_CONTROL_ACTIONS[number];
20
20
  type PtyControlStatus = 'success' | 'unknown-pty' | 'denied' | 'failed' | 'write-failed' | 'owner-unreachable';
21
21
 
@@ -42,7 +42,8 @@ export type PtyControlPayload =
42
42
  | { readonly cols: number; readonly rows: number }
43
43
  | { readonly ansi: boolean }
44
44
  | { readonly nickname: string }
45
- | { readonly cols: number; readonly rows: number; readonly title?: string };
45
+ | { readonly cols: number; readonly rows: number; readonly title?: string }
46
+ | { readonly force: true; readonly actorIdentity: string; readonly reason: string };
46
47
 
47
48
  export interface PtyControlRequestOptions {
48
49
  /** 요청자가 주장하는 쓰기 주체. `'agent'` 는 run-identity 일치를 요구한다(`resolveRemoteControlActor`). */
@@ -609,6 +610,19 @@ async function processPtyControlRequestsOnce(getHandle: (id: string) => PtyContr
609
610
  else if (!isOwnerPtyControlAction(row.action)) result = { status: 'denied', reason: 'unsupported-action' };
610
611
  else if (row.action === 'capabilities') result = { status: 'success', actions: OWNER_PTY_CONTROL_ACTIONS };
611
612
  else if (row.action === 'terminate') result = await terminatePty(handle);
613
+ else if (row.action === 'stop-turn') {
614
+ const payload = parsePayload(row);
615
+ const targetRunId = getPtyManifest(row.pty_id)?.runId?.trim() ?? '';
616
+ const requesterRunId = row.requester_run_id?.trim() ?? '';
617
+ if (requested === null) result = { status: 'denied', reason: 'invalid-actor' };
618
+ else if (payload === null || typeof payload !== 'object' || Array.isArray(payload) || !('force' in payload) || payload.force !== true) result = { status: 'denied', reason: 'force-required' };
619
+ else if (!('actorIdentity' in payload) || typeof payload.actorIdentity !== 'string' || !payload.actorIdentity.trim()) result = { status: 'denied', reason: 'actor-identity-required' };
620
+ else if (!('reason' in payload) || typeof payload.reason !== 'string' || !payload.reason.trim()) result = { status: 'denied', reason: 'reason-required' };
621
+ else if (!requesterRunId || !targetRunId) result = { status: 'denied', reason: 'run-identity-unavailable' };
622
+ else if (requesterRunId === targetRunId) result = { status: 'denied', reason: 'self-turn-refused' };
623
+ else if (!handle.stopTurn) result = { status: 'denied', reason: 'force-stop-unsupported' };
624
+ else result = handle.stopTurn(true) ? { status: 'success' } : { status: 'denied', reason: 'no-active-turn' };
625
+ }
612
626
  else if (row.action === 'record-start' || row.action === 'record-stop') {
613
627
  if (requested === null) result = { status: 'denied', reason: 'invalid-actor' };
614
628
  else if (row.action === 'record-stop') {
@@ -733,6 +747,19 @@ async function processPtyControlRequestsOnce(getHandle: (id: string) => PtyContr
733
747
  result = { status: 'failed', reason: 'control-processing-error' };
734
748
  debug.log('pty.takeover', 'control-processing-error', { id: row.pty_id, action: row.action, actor: requested ?? row.actor, error: (error as Error).message });
735
749
  }
750
+ if (row.action === 'stop-turn') {
751
+ const payload = parsePayload(row);
752
+ debug.log('pty.turn', 'force-stop-settled', {
753
+ ptyId: row.pty_id,
754
+ actor: requested ?? row.actor ?? 'unknown',
755
+ actorIdentity: payload && 'actorIdentity' in payload && typeof payload.actorIdentity === 'string' ? payload.actorIdentity.trim() || null : null,
756
+ reason: payload && 'reason' in payload && typeof payload.reason === 'string' ? payload.reason.trim() || null : null,
757
+ requesterRunId: row.requester_run_id?.trim() || null,
758
+ targetRunId: getPtyManifest(row.pty_id)?.runId?.trim() || null,
759
+ outcome: result.status,
760
+ refusal: result.reason ?? null,
761
+ });
762
+ }
736
763
  d.run("UPDATE pty_control_requests SET status=?, result_json=?, updated_at=? WHERE request_id=? AND status='processing'", [result.status, JSON.stringify(result), Date.now(), row.request_id]);
737
764
  debug.log('pty.arbiter', 'control-settled', { id: row.pty_id, action: row.action, actor: requested ?? row.actor, outcome: result.status, reason: result.reason });
738
765
  }
@@ -75,7 +75,10 @@ export interface PtyManifestRow {
75
75
  exitCode: number | null;
76
76
  snapshot: string;
77
77
  snapshotAt: number;
78
- outputBytesTotal: number;
78
+ /** Cumulative output bytes recorded for this PTY. `undefined` = the row never recorded a total
79
+ * (legacy schema before `output_bytes_total`, or NULL) — that is *unknown*, not 0. A genuinely
80
+ * recorded zero from a fresh spawn stays 0. */
81
+ outputBytesTotal?: number;
79
82
  lastControlAt?: number;
80
83
  updatedAt: number;
81
84
  frame: string;
@@ -101,6 +104,10 @@ export interface PtyManifestRow {
101
104
  /** TUI 턴 상태 — TUI 가 턴 시작·끝에 스스로 적는다(화면 글자 추정 아님). 없으면 기록 안 하는 행/옛 판. */
102
105
  turnState?: PtyTurnState;
103
106
  turnAt?: number;
107
+ /** 마지막 진전 시각(epoch ms) — 스트림 텍스트·도구 시작/끝·상태 줄에서 갱신(SURVIVAL-PROGRESS-CLOCK). */
108
+ progressAt?: number;
109
+ /** Esc 로 턴 중단을 청한 시각(epoch ms) — 이후 busy 가 지속되면 abort-ignored 판정 재료. */
110
+ abortRequestedAt?: number;
104
111
  /** 행 소유 프로세스가 «기동 때» 실은 코드 판 — 트리 HEAD(`codeSha`)와 다른 축이다. */
105
112
  build?: PtyBuildIdentity;
106
113
  }
@@ -125,6 +132,7 @@ let _dbFailed = false;
125
132
  let _dbPathForTesting: string | null = null;
126
133
  const _lastSnapshotAt = new Map<string, number>();
127
134
  const _lastFrameAt = new Map<string, number>();
135
+ const _lastProgressAt = new Map<string, number>();
128
136
 
129
137
  export function setPtyManifestDbPathForTesting(path: string | null): void {
130
138
  _db?.close();
@@ -133,6 +141,7 @@ export function setPtyManifestDbPathForTesting(path: string | null): void {
133
141
  _dbPathForTesting = path;
134
142
  _lastSnapshotAt.clear();
135
143
  _lastFrameAt.clear();
144
+ _lastProgressAt.clear();
136
145
  }
137
146
 
138
147
  function db(): Database | null {
@@ -169,6 +178,11 @@ function db(): Database | null {
169
178
  }
170
179
 
171
180
  export function migratePtyManifestSchema(d: Database): void {
181
+ // 이행 문장 전체를 한 트랜잭션에 묶는다 — 문장별 autocommit fsync(첫 열기 ~35회)를 없애
182
+ // 매니페스트 DB 를 처음 여는 비용을 크게 줄인다. 이미 트랜잭션 안이면 그대로 진행한다.
183
+ let ownsTxn = false;
184
+ try { d.run('BEGIN'); ownsTxn = true; } catch { /* caller transaction */ }
185
+ try {
172
186
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN nickname TEXT'); } catch { /* already exists */ }
173
187
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN purpose TEXT'); } catch { /* already exists */ }
174
188
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN seat TEXT'); } catch { /* already exists */ }
@@ -198,12 +212,19 @@ export function migratePtyManifestSchema(d: Database): void {
198
212
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN last_control_at INTEGER'); } catch { /* already exists */ }
199
213
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN turn_state TEXT'); } catch { /* already exists */ }
200
214
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN turn_at INTEGER'); } catch { /* already exists */ }
215
+ try { d.run('ALTER TABLE pty_manifest ADD COLUMN progress_at INTEGER'); } catch { /* already exists */ }
216
+ try { d.run('ALTER TABLE pty_manifest ADD COLUMN abort_requested_at INTEGER'); } catch { /* already exists */ }
201
217
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_version TEXT'); } catch { /* already exists */ }
202
218
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_sha TEXT'); } catch { /* already exists */ }
203
219
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_source TEXT'); } catch { /* already exists */ }
204
220
  try { d.run('ALTER TABLE pty_manifest ADD COLUMN build_code_root TEXT'); } catch { /* already exists */ }
205
221
  try { d.run('ALTER TABLE pty_manifest DROP COLUMN chain_depth'); } catch { /* legacy schema has no duplicate column */ }
206
222
  try { d.run('UPDATE pty_manifest SET closed_at=updated_at WHERE alive=0 AND closed_at=0'); } catch { /* fail-soft */ }
223
+ } finally {
224
+ if (ownsTxn) {
225
+ try { d.run('COMMIT'); } catch { try { d.run('ROLLBACK'); } catch { /* fail-soft */ } }
226
+ }
227
+ }
207
228
  }
208
229
 
209
230
  function codeShaForWorkdir(workdir: string | undefined): string {
@@ -287,6 +308,7 @@ export function upsertPtyManifest(row: {
287
308
  // 행을 (다시) 세우면 snapshot·frame 칸이 비워진다 — 같은 프로세스의 쓰기 스로틀도 비워 다음 쓰기가 바로 닿게 한다.
288
309
  _lastSnapshotAt.delete(row.id);
289
310
  _lastFrameAt.delete(row.id);
311
+ _lastProgressAt.delete(row.id);
290
312
  const d = db(); if (!d) return;
291
313
  const runId = getHarnessRunId(process.env);
292
314
  const runIdSource = getHarnessRunIdSource();
@@ -340,7 +362,7 @@ export function upsertPtyManifest(row: {
340
362
  terminal_origin_reason=excluded.terminal_origin_reason, external_tool_name=excluded.external_tool_name,
341
363
  started_at=excluded.started_at, alive=1, exit_code=NULL,
342
364
  snapshot='', snapshot_at=0, frame='', frame_at=0, closed_at=0, updated_at=excluded.updated_at,
343
- turn_state=NULL, turn_at=NULL, build_version=NULL, build_sha=NULL, build_source=NULL, build_code_root=NULL`,
365
+ turn_state=NULL, turn_at=NULL, progress_at=NULL, abort_requested_at=NULL, build_version=NULL, build_sha=NULL, build_source=NULL, build_code_root=NULL`,
344
366
  values,
345
367
  );
346
368
  d.run('COMMIT');
@@ -420,11 +442,57 @@ export function updatePtyManifestNickname(id: string, nickname: string | undefin
420
442
  } catch { /* fail-soft */ }
421
443
  }
422
444
 
423
- /** 턴 상태 기록 — 행이 없거나 db 를 못 열면 false(호출자가 관측을 남긴다). */
445
+ /** Update the conversation currently shown by a TUI surface without replacing its manifest row. */
446
+ export function updatePtyManifestSession(id: string, sessionId: string, now: number = Date.now()): boolean {
447
+ try {
448
+ const d = db(); if (!d) return false;
449
+ const result = d.run('UPDATE pty_manifest SET session_id=?, updated_at=? WHERE id=? AND kind=\'tui\' AND session_id<>?', [sessionId, now, id, sessionId]);
450
+ return (result.changes ?? 0) > 0;
451
+ } catch {
452
+ return false;
453
+ }
454
+ }
455
+
456
+ /** 턴 상태 기록 — 행이 없거나 db 를 못 열면 false(호출자가 관측을 남긴다). 새 busy 턴은 이전 Esc 청구를 비운다. */
424
457
  export function updatePtyManifestTurn(id: string, turn: PtyTurnState, at: number): boolean {
425
458
  try {
426
459
  const d = db(); if (!d) return false;
427
- return d.run('UPDATE pty_manifest SET turn_state=?, turn_at=? WHERE id=?', [turn, at, id]).changes > 0;
460
+ const result = turn === 'busy'
461
+ ? d.run('UPDATE pty_manifest SET turn_state=?, turn_at=?, progress_at=?, abort_requested_at=NULL WHERE id=?', [turn, at, at, id])
462
+ : d.run('UPDATE pty_manifest SET turn_state=?, turn_at=? WHERE id=?', [turn, at, id]);
463
+ if ((result.changes ?? 0) > 0 && turn === 'busy') _lastProgressAt.set(id, at);
464
+ return (result.changes ?? 0) > 0;
465
+ } catch {
466
+ return false;
467
+ }
468
+ }
469
+
470
+ /** 진전 기록 스로틀 — 같은 행은 이만큼 안에 다시 쓰지 않는다. */
471
+ export const PTY_MANIFEST_PROGRESS_THROTTLE_MS = 5_000;
472
+
473
+ /**
474
+ * 마지막 진전 시각 기록(SURVIVAL-PROGRESS-CLOCK). 같은 행을 5초 안에 다시 쓰면 생략하지만
475
+ * «실패가 아니다» — true 를 돌려 호출자의 실패 관측을 일으키지 않는다. 실패(0행·db 오류)만 false.
476
+ */
477
+ export function updatePtyManifestProgress(id: string, at: number): boolean {
478
+ try {
479
+ const last = _lastProgressAt.get(id);
480
+ if (last !== undefined && at - last < PTY_MANIFEST_PROGRESS_THROTTLE_MS) return true;
481
+ const d = db(); if (!d) return false;
482
+ const result = d.run('UPDATE pty_manifest SET progress_at=?, updated_at=? WHERE id=?', [at, at, id]);
483
+ const ok = (result.changes ?? 0) > 0;
484
+ if (ok) _lastProgressAt.set(id, at);
485
+ return ok;
486
+ } catch {
487
+ return false;
488
+ }
489
+ }
490
+
491
+ /** Esc 로 턴 중단을 청한 시각 기록 — busy 턴이 이 뒤로 계속되면 abort-ignored 판정 재료가 된다. */
492
+ export function updatePtyManifestAbortRequested(id: string, at: number): boolean {
493
+ try {
494
+ const d = db(); if (!d) return false;
495
+ return (d.run('UPDATE pty_manifest SET abort_requested_at=?, updated_at=? WHERE id=?', [at, at, id]).changes ?? 0) > 0;
428
496
  } catch {
429
497
  return false;
430
498
  }
@@ -866,7 +934,7 @@ function mapRow(r: Record<string, unknown>): PtyManifestRow {
866
934
  exitCode: r.exit_code === null || r.exit_code === undefined ? null : Number(r.exit_code),
867
935
  snapshot: String(r.snapshot ?? ''),
868
936
  snapshotAt: Number(r.snapshot_at ?? 0),
869
- outputBytesTotal: Number(r.output_bytes_total ?? 0),
937
+ ...(r.output_bytes_total === null || r.output_bytes_total === undefined ? {} : { outputBytesTotal: Number(r.output_bytes_total) }),
870
938
  ...(r.last_control_at === null || r.last_control_at === undefined ? {} : { lastControlAt: Number(r.last_control_at) }),
871
939
  frame: String(r.frame ?? ''),
872
940
  frameAt: Number(r.frame_at ?? 0),
@@ -889,6 +957,8 @@ function mapRow(r: Record<string, unknown>): PtyManifestRow {
889
957
  closedAt: Number(r.closed_at ?? 0),
890
958
  codeSha: String(r.code_sha ?? ''),
891
959
  ...(r.turn_state === 'busy' || r.turn_state === 'idle' ? { turnState: r.turn_state, turnAt: Number(r.turn_at ?? 0) } : {}),
960
+ ...(r.progress_at === null || r.progress_at === undefined ? {} : { progressAt: Number(r.progress_at) }),
961
+ ...(r.abort_requested_at === null || r.abort_requested_at === undefined ? {} : { abortRequestedAt: Number(r.abort_requested_at) }),
892
962
  ...(typeof r.build_sha === 'string' ? { build: mapBuild(r) } : {}),
893
963
  updatedAt: Number(r.updated_at),
894
964
  };
@@ -180,6 +180,8 @@ export interface PtyControlTarget {
180
180
  isAlive(): boolean;
181
181
  /** Registry-backed PTY targets expose termination; non-PTY control targets omit it. */
182
182
  kill?(signal?: NodeJS.Signals): void;
183
+ /** TUI owners may expose an explicit, forceful cancellation of the active turn. */
184
+ stopTurn?(force: true): boolean;
183
185
  canWrite(actor?: PtyWriteActor): boolean;
184
186
  write(chars: string, actor?: PtyWriteActor): void;
185
187
  resize(cols: number, rows: number): void;
@@ -27,7 +27,7 @@ import {
27
27
  versionedDashboardInstallDir,
28
28
  } from './stale-install-check.js';
29
29
  import {
30
- updatePtyManifestBuild, updatePtyManifestTurn,
30
+ updatePtyManifestAbortRequested, updatePtyManifestBuild, updatePtyManifestProgress, updatePtyManifestTurn,
31
31
  type PtyBuildIdentity, type PtyManifestRow, type PtyTurnState,
32
32
  } from './pty-manifest.js';
33
33
 
@@ -231,6 +231,10 @@ export type PtyTurnView = PtyTurnState | 'unknown';
231
231
  export interface PtyRunStateView {
232
232
  readonly turn: PtyTurnView;
233
233
  readonly turnAt?: number;
234
+ /** 마지막 진전 시각(SURVIVAL-PROGRESS-CLOCK) — 기록 없는 행·옛 판은 undefined. */
235
+ readonly progressAt?: number;
236
+ /** Esc 로 턴 중단을 청한 시각 — 이 뒤로 busy 가 지속되면 abort-ignored 판정 재료. */
237
+ readonly abortRequestedAt?: number;
234
238
  readonly build: PtyBuildIdentity | null;
235
239
  readonly installed: string | null;
236
240
  readonly stale: boolean | null;
@@ -244,7 +248,7 @@ export interface DescribeRunStateDeps {
244
248
 
245
249
  /** manifest 행 하나의 턴 ⊕ 판 ⊕ stale. 행이 없거나 죽었으면 턴은 unknown. */
246
250
  export function describePtyRunState(
247
- row: Pick<PtyManifestRow, 'alive' | 'startedAt' | 'kind' | 'turnState' | 'turnAt' | 'build'> | null,
251
+ row: Pick<PtyManifestRow, 'alive' | 'startedAt' | 'kind' | 'turnState' | 'turnAt' | 'progressAt' | 'abortRequestedAt' | 'build'> | null,
248
252
  deps: DescribeRunStateDeps = {},
249
253
  ): PtyRunStateView {
250
254
  let installed: InstalledRecord = {};
@@ -265,6 +269,8 @@ export function describePtyRunState(
265
269
  const turnView = ptyTurnViewOfRow(row);
266
270
  return {
267
271
  ...turnView,
272
+ ...(row?.alive && row.progressAt !== undefined ? { progressAt: row.progressAt } : {}),
273
+ ...(row?.alive && row.abortRequestedAt !== undefined ? { abortRequestedAt: row.abortRequestedAt } : {}),
268
274
  build: build ?? null,
269
275
  installed: installed.sha ?? null,
270
276
  stale: staleness.stale,
@@ -446,6 +452,50 @@ export const spawnTuiRelaunch = (sessionId: string): Promise<void> => {
446
452
  });
447
453
  };
448
454
 
455
+ // ── SURVIVAL-PROGRESS-CLOCK — «마지막 진전 시각»로 느림·정체·Esc 무시를 가른다 ──
456
+ //
457
+ // `turnAt` 은 턴 값이 «바뀔 때만» 적히므로 busy 경과만으로는 «일하는 중»인지 «죽었다»인지를 못 가른다.
458
+ // 진전 신호(스트림 텍스트·도구 시작/끝·상태 줄)가 `progress_at` 를 계속 올리면 긴 턴도 «느리지만 가는 중»이
459
+ // 되고, 진전이 끊기면 «정체», Esc 청구 뒤에도 busy 가 지속되면 «Esc 무시»로 판정한다.
460
+
461
+ export const DEFAULT_TURN_STALL_MS = 12 * 60 * 1000;
462
+ export const DEFAULT_SLOW_TURN_MS = 20 * 60 * 1000;
463
+ export const DEFAULT_ABORT_IGNORE_MS = 30 * 1000;
464
+
465
+ export type TurnProgressJudgment = 'progressing' | 'slow' | 'stalled' | 'abort-ignored' | 'unknown';
466
+
467
+ export interface TurnProgressInput {
468
+ readonly turn: PtyTurnView;
469
+ readonly turnAt?: number;
470
+ readonly progressAt?: number;
471
+ readonly abortRequestedAt?: number;
472
+ readonly now: number;
473
+ /** 정체 임계 — 진전이 이만큼 끊기면 stalled. 기본 12분. */
474
+ readonly stallMs?: number;
475
+ /** 느린 턴 임계 — 턴 경과가 이만큼이면 slow. 기본 20분. */
476
+ readonly slowTurnMs?: number;
477
+ /** Esc 무시 임계 — 청구 뒤 이만큼 busy 면 abort-ignored. 기본 30초. */
478
+ readonly abortIgnoreMs?: number;
479
+ }
480
+
481
+ /** 순수 판정: busy 턴의 진전·정체·Esc 무시를 임계로 가른다. 재료가 없으면 unknown(«괜찮다»가 아니다). */
482
+ export function judgeTurnProgress(input: TurnProgressInput): TurnProgressJudgment {
483
+ const { turn, turnAt, progressAt, abortRequestedAt, now } = input;
484
+ if (turn !== 'busy') return 'unknown';
485
+ if (!Number.isFinite(now)) return 'unknown';
486
+ // Esc 청구 뒤에도 busy 가 지속되면 무시 — 정체보다 구체적이므로 먼저 가른다.
487
+ if (abortRequestedAt !== undefined && Number.isFinite(abortRequestedAt)) {
488
+ if (now - abortRequestedAt >= (input.abortIgnoreMs ?? DEFAULT_ABORT_IGNORE_MS)) return 'abort-ignored';
489
+ }
490
+ // 진전 시각이 없으면 턴 시작(turnAt)이 진전의 0초다.
491
+ const since = progressAt !== undefined && Number.isFinite(progressAt) ? progressAt : turnAt;
492
+ if (since === undefined || !Number.isFinite(since)) return 'unknown';
493
+ const elapsed = Math.max(0, now - since);
494
+ if (elapsed >= (input.stallMs ?? DEFAULT_TURN_STALL_MS)) return 'stalled';
495
+ if (turnAt !== undefined && Number.isFinite(turnAt) && now - turnAt >= (input.slowTurnMs ?? DEFAULT_SLOW_TURN_MS)) return 'slow';
496
+ return 'progressing';
497
+ }
498
+
449
499
  // ── 기록(TUI) ──
450
500
 
451
501
  export interface TuiRunStateRecorderDeps {
@@ -453,6 +503,10 @@ export interface TuiRunStateRecorderDeps {
453
503
  readonly build?: () => PtyBuildIdentity;
454
504
  readonly writeBuild?: (id: string, build: PtyBuildIdentity) => boolean;
455
505
  readonly writeTurn?: (id: string, turn: PtyTurnState, at: number) => boolean;
506
+ /** 진전 시각 기록 — 생략하면 `updatePtyManifestProgress`(같은 행 5초 스로틀). */
507
+ readonly writeProgress?: (id: string, at: number) => boolean;
508
+ /** Esc 청구 시각 기록 — 생략하면 `updatePtyManifestAbortRequested`. */
509
+ readonly writeAbortRequested?: (id: string, at: number) => boolean;
456
510
  readonly log?: (event: string, data: Record<string, unknown>) => void;
457
511
  /**
458
512
  * herdr pane 신고기. 생략 시: `writeTurn` 을 주입하지 않은 기본 녹음기만
@@ -476,6 +530,8 @@ interface ActiveRecorder {
476
530
  readonly surfaceId: string;
477
531
  readonly now: () => number;
478
532
  readonly writeTurn: (id: string, turn: PtyTurnState, at: number) => boolean;
533
+ readonly writeProgress: (id: string, at: number) => boolean;
534
+ readonly writeAbortRequested: (id: string, at: number) => boolean;
479
535
  readonly log: (event: string, data: Record<string, unknown>) => void;
480
536
  readonly herdr: HerdrAgentReporterLike | null;
481
537
  /** manifest 에 실제로 적힌 마지막 턴. 실패면 안 바뀐다(재시도). */
@@ -495,6 +551,8 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
495
551
  const now = deps.now ?? Date.now;
496
552
  const log = deps.log ?? defaultLog;
497
553
  const writeTurn = deps.writeTurn ?? updatePtyManifestTurn;
554
+ const writeProgress = deps.writeProgress ?? updatePtyManifestProgress;
555
+ const writeAbortRequested = deps.writeAbortRequested ?? updatePtyManifestAbortRequested;
498
556
  // 기본 신고기는 기본 manifest 쓰기와 짝일 때만. writeTurn 주입(시험)은 herdr 를 안 만든다.
499
557
  const herdr = deps.herdr !== undefined
500
558
  ? deps.herdr
@@ -508,7 +566,7 @@ export function startTuiRunStateRecorder(surfaceId: string, deps: TuiRunStateRec
508
566
  log(ok ? 'build-recorded' : 'build-write-failed', { ptyId: surfaceId, sha: build.sha, version: build.version, source: build.source });
509
567
  }
510
568
  // 기동 순서: 판 → manifest 초기 idle → herdr 신고. herdr start 가 idle 을 신고하므로 초기 idle 을 turn 으로 다시 안 보낸다.
511
- const recorder: ActiveRecorder = { surfaceId, now, writeTurn, log, herdr, herdrLast: herdr ? 'idle' : undefined };
569
+ const recorder: ActiveRecorder = { surfaceId, now, writeTurn, writeProgress, writeAbortRequested, log, herdr, herdrLast: herdr ? 'idle' : undefined };
512
570
  active = recorder;
513
571
  writeTurnState(recorder, 'idle');
514
572
  if (herdr) { try { herdr.start(); } catch { /* 신고 실패가 녹음기를 깨지 않는다 */ } }
@@ -614,6 +672,25 @@ export function reportTuiTurn(turn: PtyTurnState): void {
614
672
  writeTurnState(active, turn);
615
673
  }
616
674
 
675
+ /** 진전 신호(스트림 텍스트·도구 시작/끝·상태 줄)에서 부른다 — 마지막 진전 시각을 올린다. 녹음기가 없으면 아무것도 안 한다. */
676
+ export function reportTuiProgress(): void {
677
+ if (!active) return;
678
+ const at = active.now();
679
+ let ok = false;
680
+ try { ok = active.writeProgress(active.surfaceId, at); } catch { ok = false; }
681
+ // 실패(0행·예외)는 관측으로만 남긴다 — 진전 기록이 턴을 막지 않는다. 스로틀 생략(false 아님 실패만)은 조용히 지나간다.
682
+ if (!ok) active.log('progress-write-failed', { ptyId: active.surfaceId, at });
683
+ }
684
+
685
+ /** Esc 게이트가 턴 중단을 청할 때 부른다 — 청구 시각을 남긴다(busy 가 지속되면 abort-ignored 판정 재료). */
686
+ export function reportTuiAbortRequested(): void {
687
+ if (!active) return;
688
+ const at = active.now();
689
+ let ok = false;
690
+ try { ok = active.writeAbortRequested(active.surfaceId, at); } catch { ok = false; }
691
+ if (!ok) active.log('abort-requested-write-failed', { ptyId: active.surfaceId, at });
692
+ }
693
+
617
694
  function writeTurnState(recorder: ActiveRecorder, turn: PtyTurnState): void {
618
695
  const at = recorder.now();
619
696
  let ok = false;
@@ -11,11 +11,13 @@ interface GateHostClaim {
11
11
  hosts: string[];
12
12
  pid: number;
13
13
  pidStartedAt: number | null;
14
+ /** Wall-clock claim time. Claims written before this field existed stay readable (optional on read). */
15
+ reservedAt?: number;
14
16
  }
15
17
 
16
18
  export type GateHostReservation =
17
19
  | { status: 'free' }
18
- | { status: 'reserved' | 'unknown'; reason: string; runId?: string };
20
+ | { status: 'reserved' | 'unknown'; reason: string; runId?: string; reservedAt?: number };
19
21
 
20
22
  const hostName = /^[A-Za-z0-9][A-Za-z0-9._-]*$/;
21
23
  const claimsDir = (root: string) => join(root, 'release', 'gate-host-reservations');
@@ -44,7 +46,7 @@ export function reserveReleaseGateHosts(root: string, runId: string, hosts: read
44
46
  const token = randomUUID();
45
47
  const pidStartedAt = psProcessStartMs(process.pid);
46
48
  if (pidStartedAt === null) throw new Error('release gate owner start time unmeasured');
47
- const claim: GateHostClaim = { token, runId, hosts: unique, pid: process.pid, pidStartedAt };
49
+ const claim: GateHostClaim = { token, runId, hosts: unique, pid: process.pid, pidStartedAt, reservedAt: Date.now() };
48
50
  const path = join(dir, `${token}.json`);
49
51
  const temp = join(dir, `.${token}.tmp`);
50
52
  try {
@@ -82,7 +84,9 @@ export function inspectReleaseGateHost(root: string, host: string): GateHostRese
82
84
  || !Number.isSafeInteger(claim.pid) || claim.pid <= 0 || typeof claim.token !== 'string'
83
85
  || typeof claim.runId !== 'string' || !claim.runId
84
86
  || (claim.pidStartedAt !== null && (!Number.isSafeInteger(claim.pidStartedAt)
85
- || claim.pidStartedAt <= 0 || claim.pidStartedAt > Date.now()))) throw new Error('invalid claim');
87
+ || claim.pidStartedAt <= 0 || claim.pidStartedAt > Date.now()))
88
+ || (claim.reservedAt !== undefined && (!Number.isSafeInteger(claim.reservedAt)
89
+ || claim.reservedAt <= 0 || claim.reservedAt > Date.now()))) throw new Error('invalid claim');
86
90
  } catch (error) { return { status: 'unknown', reason: `reservation unreadable: ${name}: ${String(error)}` }; }
87
91
  const live = claimAlive(claim);
88
92
  if (live === 'dead') {
@@ -91,7 +95,12 @@ export function inspectReleaseGateHost(root: string, host: string): GateHostRese
91
95
  continue;
92
96
  }
93
97
  if (!claim.hosts.includes(host) && !claim.hosts.includes('*')) continue;
94
- return { status: live === 'unknown' ? 'unknown' : 'reserved', reason: `release gate ${claim.runId} holds ${host}`, runId: claim.runId };
98
+ return {
99
+ status: live === 'unknown' ? 'unknown' : 'reserved',
100
+ reason: `release gate ${claim.runId} holds ${host}`,
101
+ runId: claim.runId,
102
+ ...(claim.reservedAt !== undefined ? { reservedAt: claim.reservedAt } : {}),
103
+ };
95
104
  }
96
105
  return { status: 'free' };
97
106
  }
@@ -0,0 +1,68 @@
1
+ // One append-only observation per gate shard transition. The live board is a projection, not evidence for reuse.
2
+ import { appendFileSync, existsSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { dirname, join } from 'node:path';
4
+ import { releaseLedgerRoot } from '../instance/resolve.js';
5
+
6
+ export interface GateShardLedgerRow {
7
+ v: 1;
8
+ version: string;
9
+ phase: 'cut' | 'baseline';
10
+ shardId: string;
11
+ files: string[];
12
+ host: string | null;
13
+ executor: 'pod' | 'host';
14
+ imageDigest: string | null;
15
+ commit: string;
16
+ envFingerprint: string;
17
+ startedAt: string | null;
18
+ endedAt: string | null;
19
+ observedAt: string;
20
+ state: 'pending' | 'running' | 'done' | 'retry' | 'timeout' | 'failed';
21
+ rc: number | null;
22
+ pass: number | null;
23
+ fail: number | null;
24
+ errors: number | null;
25
+ ran: number | null;
26
+ failureIds: string[] | null;
27
+ errorIds: string[] | null;
28
+ attribution: 'complete' | 'unmeasured';
29
+ logPath: string | null;
30
+ junitPath: string | null;
31
+ stopReason: string | null;
32
+ attemptId: string | null;
33
+ }
34
+
35
+ export function gateShardLedgerPath(version: string, root = releaseLedgerRoot()): string {
36
+ if (!/^\d+\.\d+\.\d+(?:[-.][A-Za-z0-9.-]+)?$/.test(version)) throw new Error('invalid release version');
37
+ return join(root, 'release', version, 'gate-logs', 'shard-ledger.jsonl');
38
+ }
39
+
40
+ /** Each newline is a complete event, so an observer can read while the gate is running. */
41
+ export function appendGateShardLedger(path: string, row: GateShardLedgerRow): void {
42
+ if (!/^[a-f0-9]{40}$/i.test(row.commit) || !/^[a-f0-9]{64}$/i.test(row.envFingerprint)) throw new Error('invalid shard ledger identity');
43
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(row.shardId) || row.files.some((file) => file.startsWith('/') || file.split('/').includes('..'))) throw new Error('invalid shard ledger path');
44
+ mkdirSync(dirname(path), { recursive: true });
45
+ appendFileSync(path, `${JSON.stringify(row)}\n`, { mode: 0o600 });
46
+ }
47
+
48
+ export function readGateShardLedger(path: string): { rows: GateShardLedgerRow[]; malformed: number } | null {
49
+ if (!existsSync(path)) return null;
50
+ const rows: GateShardLedgerRow[] = [];
51
+ let malformed = 0;
52
+ for (const line of readFileSync(path, 'utf8').split('\n')) {
53
+ if (!line.trim()) continue;
54
+ try {
55
+ const row = JSON.parse(line) as GateShardLedgerRow;
56
+ if (row.v !== 1 || typeof row.shardId !== 'string' || !Array.isArray(row.files) || typeof row.observedAt !== 'string') throw new Error('invalid row');
57
+ rows.push(row);
58
+ } catch { malformed++; }
59
+ }
60
+ return { rows, malformed };
61
+ }
62
+
63
+ /** The newest event for each phase/shard. Preserve every attempt in the underlying ledger. */
64
+ export function latestGateShardLedger(rows: readonly GateShardLedgerRow[]): GateShardLedgerRow[] {
65
+ const latest = new Map<string, GateShardLedgerRow>();
66
+ for (const row of rows) latest.set(`${row.phase}:${row.shardId}`, row);
67
+ return [...latest.values()].sort((a, b) => a.phase.localeCompare(b.phase) || a.shardId.localeCompare(b.shardId, undefined, { numeric: true }));
68
+ }