elanous 0.2.38 → 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 (615) 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/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7954.4f7a8832663ee979.js → 1060.014f1f01a17aec26.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 1281.d81877e35b9068f4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{2104.70e086d5174a4736.js → 1350.59f40e39e02d91b1.js} +1 -1
  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/2047.8f23e210995d4548.js +2 -0
  16. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.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/{8019.21ca554a821dad01.js → 2177.df8547f9d7215c4e.js} +3 -3
  20. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.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/{6493.27ad77de7aac7966.js → 2499.02fbfd18126c10c0.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/{7628.6b16863ac3972333.js → 2522.f2766b76d22c8bdf.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/{9299.24e2a7d9b6d1f91b.js → 261.0d471e8aded799f3.js} +3 -3
  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/2774-719820e3f5b2a3eb.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +1 -0
  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/{7524.ce973525d30b3d52.js → 3330.7443183b7e6fdbdf.js} +1 -1
  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/{3124-561f7f037943cde2.js → 3746-f80a78f220bf37b5.js} +1 -1
  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/{bb6987f9.3647e1a23b0e3217.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/{8994d93e.33ba491f95345fc2.js → 409c787b.e48c5bec8ec10456.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/{5041-5aada92ca215ffdd.js → 413-24c8284bda08241d.js} +1 -1
  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/{5638.107314dc479e2f37.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/{8487.291666583bebe640.js → 4769.9fd582071301f382.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{8509.3a54d4e61893d7cb.js → 483.725e4a61be922788.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.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/{8879.ac06755bcf3e44a1.js → 5383.bdfa5d886e39a826.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 5436.fdf6fa8ae3e9588d.js} +1 -1
  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/{7161-8f22db3ec5ed005e.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/{3291.f6c1005387d514bd.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/{5203.51e5d8b5f1dcfe53.js → 6749.0744ce6eb08d40e9.js} +3 -3
  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/{1938.0e6c60ee91c4d7f5.js → 6908.06008c67f6380ea9.js} +2 -2
  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/{de8b930d.d94c0f42acf807fc.js → 6cc1d1d6.9a98dd4622f1afc6.js} +1 -1
  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/{1026-44010f405704050c.js → 8272-025653884f9645d2.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.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/{4199-f7c6eb40cd0322f8.js → 8639-92c11d069792429e.js} +1 -1
  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/9175.2de5209a5ce6f68a.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.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-866aac5ff226a7f3.js → page-ba957ff875a026a0.js} +1 -1
  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-4edb8df90f4537ce.js +1 -0
  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-fca2e59a81744d9e.js +1 -0
  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-139d722de1dcd6c1.js +1 -0
  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-ccde99f07aaf71f7.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → b84cad00.594027ebe0531fe2.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → ca3702f8.2913182e73889fa2.js} +7 -7
  177. package/apps/pwa/out/_next/static/chunks/{3f0de3de-2340c532c00395db.js → d5d3cefc-373c4eb722ed848b.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-4b12a946f352cee2.js → framework-002b472a66935d31.js} +1 -1
  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/video/explainer-line.yaml +4 -1
  282. package/package.json +1 -1
  283. package/scripts/dead-code/report.ts +169 -0
  284. package/scripts/lib/morning-report-options.ts +3 -4
  285. package/scripts/lib/tui-regress-evidence.ts +56 -0
  286. package/scripts/morning-report.ts +5 -1
  287. package/scripts/public-export.ts +15 -7
  288. package/scripts/release-loop/export-check-node.ts +21 -3
  289. package/scripts/release-loop/gate-node.ts +379 -48
  290. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  291. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  292. package/scripts/release-loop/gate-wall.ts +5 -5
  293. package/scripts/release-loop/preflight.ts +6 -2
  294. package/scripts/release-loop/resume-release.ts +20 -5
  295. package/scripts/release-loop/resume.ts +48 -0
  296. package/scripts/release-loop/version-node.ts +7 -2
  297. package/scripts/release-story/draft.ts +1 -1
  298. package/scripts/research-bench/README.md +53 -0
  299. package/scripts/research-bench/questions.json +66 -0
  300. package/scripts/research-bench/rubric.md +33 -0
  301. package/scripts/research-bench/run.ts +523 -0
  302. package/scripts/tui-regress.ts +85 -10
  303. package/src/acp/core-turn-bridge.ts +8 -0
  304. package/src/agent/autonomous-tools.ts +10 -3
  305. package/src/agent/monad-agent-turn.ts +4 -1
  306. package/src/agent/registry.ts +26 -2
  307. package/src/agent/shared-app-tools.ts +1 -1
  308. package/src/agent/surface-ux/build.ts +12 -3
  309. package/src/agent/surface-ux/types.ts +1 -1
  310. package/src/agent/task-notification.ts +75 -6
  311. package/src/agent/types.ts +3 -0
  312. package/src/agent-mission/driver.ts +29 -3
  313. package/src/agent-mission/mission-cli.ts +2 -1
  314. package/src/agent-substrate/review-context-pack.ts +365 -0
  315. package/src/agent-substrate/self-review-cli.ts +226 -17
  316. package/src/ask-user-question/index.ts +6 -0
  317. package/src/ask-user-question/inline-resolver.ts +49 -0
  318. package/src/auto-research/question-ladder-contract.ts +22 -3
  319. package/src/auto-research/research-turn.ts +350 -17
  320. package/src/autopilot/agent-loop.ts +1 -1
  321. package/src/autopilot/pty-control-loop.ts +8 -1
  322. package/src/boot/daemon-tools/index.ts +4 -3
  323. package/src/boot/daemon-tools/self-implement.ts +270 -2
  324. package/src/boot/daemon-tools/types.ts +2 -0
  325. package/src/budget/llm-cost.ts +44 -5
  326. package/src/budget/unified-usage.ts +17 -1
  327. package/src/capture/tui-self-report.ts +14 -0
  328. package/src/chat/index.ts +33 -7
  329. package/src/cli/agent-cli.ts +43 -8
  330. package/src/cli/intake-cli.ts +22 -1
  331. package/src/cli/lesson-cli.ts +19 -3
  332. package/src/cli/log-event-names.ts +1 -0
  333. package/src/cli/pod-cli.ts +17 -2
  334. package/src/cli/pty-takeover-cli.ts +67 -7
  335. package/src/cli/release-cli.ts +52 -6
  336. package/src/cli/repo-cli.ts +2 -1
  337. package/src/cli/tasks-cli.ts +36 -9
  338. package/src/control-plane/ledger.ts +21 -4
  339. package/src/core-turn/run-core-turn.ts +44 -3
  340. package/src/core-turn/run-goal-loop.ts +152 -8
  341. package/src/core-turn/types.ts +9 -0
  342. package/src/dashboard/chat/acp-chat.ts +2 -2
  343. package/src/dashboard/classic-sigquit.ts +16 -0
  344. package/src/dashboard/index.ts +321 -27
  345. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  346. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  347. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  348. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  349. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  350. package/src/dashboard/input/external-input-host.ts +2 -0
  351. package/src/dashboard/sidetab-runtime.ts +228 -0
  352. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  353. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  354. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  355. package/src/dashboard/term-slash-runtime.ts +16 -18
  356. package/src/dashboard/turn-preamble.ts +2 -0
  357. package/src/domains/knowledge.ts +1 -1
  358. package/src/esc-abort-gate.ts +33 -1
  359. package/src/execution-loop/launch-gate.ts +206 -1
  360. package/src/graph-runner/graph-cli.ts +6 -4
  361. package/src/graph-runner/runner.ts +31 -9
  362. package/src/graph-wizard/generate.ts +16 -7
  363. package/src/graph-wizard/mission-compose.ts +201 -0
  364. package/src/grok/agent-search.ts +8 -2
  365. package/src/grok/credential.ts +5 -0
  366. package/src/grounding/ref-index.ts +11 -0
  367. package/src/grounding/ref-vector.ts +61 -0
  368. package/src/grounding/sources-cli.ts +2 -2
  369. package/src/grounding/sources.ts +15 -1
  370. package/src/harness/harness-cli-command.ts +38 -9
  371. package/src/harness/harness-pod-dispatch.ts +7 -1
  372. package/src/index.ts +18 -4
  373. package/src/input/external-input-queue.ts +10 -0
  374. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  375. package/src/intake-plane/intake-to-tasks.ts +246 -3
  376. package/src/lessons/friction-ledger.ts +154 -0
  377. package/src/live-supply/collector.ts +149 -0
  378. package/src/live-supply/probes.ts +52 -0
  379. package/src/live-supply/snapshot.ts +40 -0
  380. package/src/llm.ts +431 -76
  381. package/src/loops/orchestrator/tick.ts +8 -0
  382. package/src/nexus/api/harness-api.ts +2 -1
  383. package/src/pty/snapshot.py +132 -0
  384. package/src/pty-shell/pty-control-ipc.ts +29 -2
  385. package/src/pty-shell/pty-manifest.ts +59 -3
  386. package/src/pty-shell/registry.ts +2 -0
  387. package/src/pty-shell/tui-run-state.ts +80 -3
  388. package/src/release-loop/gate-host-reservation.ts +13 -4
  389. package/src/release-loop/gate-shard-ledger.ts +68 -0
  390. package/src/release-loop/merged-pr-checklist.ts +25 -2
  391. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  392. package/src/release-loop/rehearsal.ts +27 -0
  393. package/src/research/edge-decision.ts +124 -15
  394. package/src/research/gap-followup.ts +249 -0
  395. package/src/research/lenses/counter-evidence.ts +100 -0
  396. package/src/research/lenses/working-backwards.ts +89 -0
  397. package/src/research/plugin-discovery.ts +242 -0
  398. package/src/research-bridge/invoke.ts +4 -2
  399. package/src/research-bridge/types.ts +2 -0
  400. package/src/self-dev/ask-launch-flow.ts +34 -106
  401. package/src/self-dev/dev-cli.ts +2 -0
  402. package/src/self-dev/dev-pipeline.ts +8 -4
  403. package/src/self-dev/graph-journey-route.ts +10 -2
  404. package/src/self-dev/launch-preflight-text.ts +2 -2
  405. package/src/self-dev/launch-preflight.ts +38 -7
  406. package/src/self-dev/orchestrate-cli.ts +1 -0
  407. package/src/self-dev/run-supervisor.ts +19 -0
  408. package/src/self-implement/device-first.ts +8 -2
  409. package/src/self-implement/doctor-visit.ts +76 -58
  410. package/src/self-implement/gate-artifacts.ts +3 -0
  411. package/src/self-implement/gate-baseline.ts +75 -4
  412. package/src/self-implement/gate-cli.ts +317 -9
  413. package/src/self-implement/gate-receipt-registry.ts +180 -0
  414. package/src/self-implement/gate-remote.ts +145 -22
  415. package/src/self-implement/goal-author-clarification.ts +178 -24
  416. package/src/self-implement/goal-author-decompose.ts +24 -15
  417. package/src/self-implement/goal-author.ts +9 -5
  418. package/src/self-implement/host-regate.ts +120 -45
  419. package/src/self-implement/impl-findings-feedback.ts +188 -0
  420. package/src/self-implement/knowhow-pack.ts +189 -10
  421. package/src/self-implement/off-diff-evidence.ts +124 -0
  422. package/src/self-implement/orchestrator.ts +85 -7
  423. package/src/self-implement/run-ledger.ts +46 -8
  424. package/src/self-implement/run-stop.ts +12 -0
  425. package/src/self-implement/seams.ts +6 -3
  426. package/src/self-implement/self-implement-cli.ts +4 -2
  427. package/src/session/chat.ts +89 -15
  428. package/src/session-runtime/provider-circuit.ts +140 -0
  429. package/src/shell-runner/file-engine.ts +1 -0
  430. package/src/shell-runner/types.ts +4 -0
  431. package/src/sidetab-core/model.ts +176 -0
  432. package/src/skills/tools/schedule-wakeup.ts +23 -1
  433. package/src/skills/tools/shell.ts +51 -5
  434. package/src/steward/directive-audit.ts +354 -0
  435. package/src/surface/child-process.ts +31 -0
  436. package/src/surface/tui-stderr-owner.ts +48 -0
  437. package/src/task-agent/cover.ts +30 -12
  438. package/src/task-agent/judge.ts +56 -0
  439. package/src/task-agent/postland-card.ts +35 -2
  440. package/src/task-agent/rejudge-on-head.ts +46 -2
  441. package/src/task-agent/repair-cycle.ts +1 -1
  442. package/src/task-agent/task-hand.ts +129 -24
  443. package/src/task-agent/tier-split.ts +105 -21
  444. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  445. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  446. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +27 -2
  447. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  448. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  449. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  450. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  451. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  452. package/src/task-orchestrator/surfaces/self-implement-pod.ts +186 -33
  453. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  454. package/src/tui/entry.ts +15 -2
  455. package/src/tui/inline-choice.ts +188 -0
  456. package/src/tui/sidetab/list.ts +2 -176
  457. package/src/tui/slash/term.ts +12 -1
  458. package/src/tui-client/dashboard-session.ts +7 -1
  459. package/src/user-config.ts +34 -4
  460. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  461. package/src/ux-sim/fake-land-queue.ts +88 -0
  462. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  463. package/src/ux-sim/goal-interim-trace.ts +24 -0
  464. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  465. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  466. package/src/version/packed-revision.json +1 -1
  467. package/src/video-pipeline/recipes/explainer.ts +54 -2
  468. package/src/web-search/grok.ts +32 -6
  469. package/src/web-search/index.ts +8 -7
  470. package/src/workflow-runtime/node-catalog.ts +53 -4
  471. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  472. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  481. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  482. package/apps/pwa/out/_next/static/chunks/2415.738b777642a02233.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  492. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  494. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  498. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  504. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  514. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  515. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  517. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  520. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  523. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  527. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  539. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +0 -77
  544. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  554. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  555. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  556. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  560. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  615. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
@@ -47,7 +47,7 @@ import { executeSiWarmTransport, type SiWarmFixedRunner,
47
47
  type SiWarmPodIdentity } from './pod-si-warm-transport.js';
48
48
 
49
49
  export const POD_CONTROL_INBOX_DIR = '/tmp/elanous-control.inbox';
50
- /** Pod Job 수명 상한(`activeDeadlineSeconds`) — 대표 2026-09-26 90분 → 180분(90분에 `DeadlineExceeded` 로 죽은 런 둘). */
50
+ /** Pod Job 수명 상한(`activeDeadlineSeconds`) — 2026-09-26 대표 지시로 90분 → 180분(90분에 `DeadlineExceeded` 로 죽은 런 둘). */
51
51
  /** Newest pod log bytes returned when the export passes the 5MB artifact limit (headroom under it). */
52
52
  export const POD_LOGS_KEEP_BYTES = 4_500_000;
53
53
 
@@ -61,6 +61,34 @@ export const POD_RESULT_FLATTEN = `ELANOUS_CHILD_RC="$rc" bun -e ' const fs=requ
61
61
 
62
62
  export const POD_JOB_DEADLINE_SECONDS = 10_800;
63
63
 
64
+ /** Record the source-stage IO marker emitted by podSourceScript. */
65
+ export function recordPodSourceIoSummary(logs: string, job: string, runId: string | null | undefined,
66
+ runIdSource: 'explicit-child-id' | 'pod-launch-child-run-id',
67
+ log: typeof debug.log = (category, event, data, options) => debug.log(category, event, data, options),
68
+ hostOriginCalls: number | null = 0): void {
69
+ const ioSummary = /^ELANOUS_POD_SOURCE_IO (\{[^\r\n]+\})\r?$/m.exec(logs)?.[1];
70
+ if (!ioSummary) return;
71
+ try {
72
+ const measured = JSON.parse(ioSummary) as Record<string, unknown>;
73
+ log('pod.source', 'io-summary', { job, runId, runIdSource, ...measured, hostOriginCalls });
74
+ } catch (error) {
75
+ log('pod.source', 'io-summary-invalid', { job, runId, runIdSource, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' });
76
+ }
77
+ }
78
+
79
+ /** Select a timestamp for a DeadlineExceeded observation without making detector time look like Job completion.
80
+ * `podFinishedAt` must come from readPodTermination for the same verified Job uid. */
81
+ export function podJobFinishedTiming(input: { jobCreatedAt: string | null; jobCompletedAt: string | null;
82
+ podFinishedAt: string | null; observedAt: string }): { finishedAt: string; finishedAtSource: 'job-completion' | 'pod-termination' | 'observed-at'; elapsedMs: number | null } {
83
+ const valid = (value: string | null): value is string => typeof value === 'string' && Number.isFinite(Date.parse(value));
84
+ const selected = valid(input.jobCompletedAt) ? { finishedAt: input.jobCompletedAt, finishedAtSource: 'job-completion' as const }
85
+ : valid(input.podFinishedAt) ? { finishedAt: input.podFinishedAt, finishedAtSource: 'pod-termination' as const }
86
+ : { finishedAt: input.observedAt, finishedAtSource: 'observed-at' as const };
87
+ const elapsedMs = valid(input.jobCreatedAt) && Number.isFinite(Date.parse(selected.finishedAt))
88
+ ? Math.max(0, Date.parse(selected.finishedAt) - Date.parse(input.jobCreatedAt)) : null;
89
+ return { ...selected, elapsedMs };
90
+ }
91
+
64
92
  /** 자식 컨테이너 «요청» — 🩸 2026-09-27: limits 만 두면 k8s 가 requests=limits(cpu 4)로 잡아, 32코어 노드에
65
93
  * «자리 요청»이 88% 차서 잡이 Pending 인데 실사용은 14%였다(풀 25 자리 중 ~8 만 떴다). 상한(limits)은 그대로 두고
66
94
  * 예약만 실사용에 맞춘다. */
@@ -201,7 +229,7 @@ export interface PodSpawnOptions {
201
229
  warmPodRequest?: WarmPodRequestHook;
202
230
  /** SI-SEED-DEFAULT — resolves a default source's branch tip for the mirror seed (test seam · default
203
231
  * {@link resolveDefaultSourceHead}; none with an injected kubectl unless given). */
204
- resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string }>;
232
+ resolveSourceHead?: (o: { repoUrl: string; base?: string; cwd: string }) => Promise<{ sha?: string; reason?: string; originCalls?: number }>;
205
233
  /** 설정 읽기(시험 주입). kubectl 주입 시험에서는 기본 사용자 설정을 읽지 않는다. */
206
234
  configHostMirror?: () => string | undefined;
207
235
  /** AUTHOR-POD2 host config seam; Pod itself has no host config. */
@@ -513,7 +541,7 @@ export function hostCredentials(account: string, storePath: string = authStorePa
513
541
  * (POD_GROK_MIN_JOB_SECONDS) plus a margin left, and that launch's `activeDeadlineSeconds` is cut to the token's
514
542
  * remaining life minus the margin (`fitPodDeadlineToGrok`) — so a long run ends as a classified DeadlineExceeded
515
543
  * instead of a silent mid-run 401. With the host credential relay (pod.groundingUrl) the Pod renews mid-run and
516
- * nothing is cut. 90 min = the Job cap before 대표 09-26 raised it (only two runs had reached it). */
544
+ * nothing is cut. 90 min = the Job cap before the 09-26 decision raised it (only two runs had reached it). */
517
545
  export const POD_GROK_MIN_JOB_SECONDS = 90 * 60;
518
546
  /** Slack between the fitted Job end and the token expiry (clock skew · Pod scheduling). */
519
547
  export const POD_GROK_EXPIRY_MARGIN_MS = 15 * 60_000;
@@ -960,7 +988,7 @@ export function podRunLabels(o: { runId?: string; parentRunId?: string }): Recor
960
988
  return { ...(run ? { 'elanous.run': run } : {}), ...(child ? { 'elanous.child-run': child } : {}) };
961
989
  }
962
990
 
963
- /** Pod 메모리 «등급» — 대표 09-27: PWA Pod 골이 16Gi 에서 OOM 으로 죽는다 ⇒ «high» 등급을 옵션으로 고른다.
991
+ /** Pod 메모리 «등급» — 09-27 결정: PWA Pod 골이 16Gi 에서 OOM 으로 죽는다 ⇒ «high» 등급을 옵션으로 고른다.
964
992
  * 등급 = `standard`(`ELANOUS_POD_MEMORY` 또는 16Gi) · `high`(`ELANOUS_POD_MEMORY_HIGH` 또는 32Gi · standard 보다 작아지지 않는다).
965
993
  * 고르는 순서(앞이 이긴다): ① 발사 옵션 `--pod-memory <등급>`(→ `ELANOUS_POD_MEMORY_TIER`) ② 조각 문면 `Pod 메모리: lite|standard|high` ③ 조각의 `apps/pwa/` ④ 부모의 명시 메모리 줄·PWA 경로 ⑤ 실측 권고 ⑥ 권고 없는 research/document 는 lite ⑦ standard.
966
994
  * node-b 노드 할당 가능 약 251Gi. */
@@ -1216,7 +1244,7 @@ export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job:
1216
1244
 
1217
1245
  export const POD_DEADLINE_AFTER_WAIT = `if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then printf '\\n' >> /tmp/si.out; cat /tmp/si.deadline-result >> /tmp/si.out; rc=124; fi`;
1218
1246
 
1219
- export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; boundPrNumber?: number; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec; /** Codex Job may use the same named Secret only for an explicitly admitted ZAI fallback. */ zaiFallback?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' }; /** TA-POD-WARMBOOT-PARITY — the child's final line (podResultMarkerShellLine), just before `exit $rc`. */ resultMarkerLine?: string; /** POD-LAUNCH-PROVENANCE — the shared provenance set (labels ⊕ annotations ⊕ child env) for this si-task Job. */ provenance?: PodProvenanceMetadata }): Record<string, unknown> {
1247
+ export function podJobManifest(o: { name: string; namespace: string; image: string; workIdentity?: PodWorkIdentity; boundPrNumber?: number; /** 레지스트리 이미지면 IfNotPresent(노드가 pull) · 반입 이미지면 Never. */ imagePullPolicy?: 'Never' | 'IfNotPresent'; repoUrl: string; source?: PodSource; repairCommitOnly?: { pr: number; baseHead: string }; hostMirror?: string; args: readonly string[]; passEnv: readonly string[]; deadlineSeconds: number; runId?: string; parentRunId?: string; armEnv?: Readonly<Record<string, string>>; hostId?: string; imageCommit?: string | null; skillEnvs?: readonly string[]; memoryLimit?: string; memoryRequest?: string; goalDoc?: string; /** AUTHOR-POD2 — run `harness say` on /creds/feature inside the Pod (authoring happens off the host). */ authorSentence?: boolean; authorGrade?: 'full' | 'lite'; grokCredential?: 'subscription' | 'api_key'; codexAccounts?: readonly string[]; appCredential?: boolean; /** Test seam — default POD_GH_STALE_SECONDS. */ githubStaleSeconds?: number; /** Which goal execution and attempt this Job is — a resumed host verifies it before following the Job (POD9). */ execution?: { key: string; attempt: number }; hostLeaseAdmitted?: boolean; /** POD-ROLE-LLM — OpenRouter 자식 Pod 에 리뷰어용 codex 자격을 깐다. */ reviewerCodexAuth?: boolean; /** BEDROCK-PROVIDER ② — bedrock 자식만: 이름 있는 AWS Secret 의 키(secretKeyRef) ⊕ 리전 ⊕ 이그레스 라벨. */ bedrock?: BedrockPodSpec; /** ZAI-POD-CHILD — glm(ZAI) 자식만: 이름 있는 ZAI Secret 의 키(secretKeyRef) ⊕ 이그레스·동시 상한 라벨(Pod ⊕ Job). */ zai?: ZaiPodSpec; /** Codex Job may use the same named Secret only for an explicitly admitted ZAI fallback. */ zaiFallback?: ZaiPodSpec; fallbackChain?: { steps: readonly FallbackStep[]; source: 'host' | 'default' }; configSnapshotHash?: string; /** TA-POD-WARMBOOT-PARITY — the child's final line (podResultMarkerShellLine), just before `exit $rc`. */ resultMarkerLine?: string; /** POD-LAUNCH-PROVENANCE — the shared provenance set (labels ⊕ annotations ⊕ child env) for this si-task Job. */ provenance?: PodProvenanceMetadata }): Record<string, unknown> {
1220
1248
  if (o.repairCommitOnly && (o.source?.kind !== 'pr' || o.source.number !== o.repairCommitOnly.pr || !/^[0-9a-f]{40}$/.test(o.repairCommitOnly.baseHead) || o.args.includes('--open-pr') || o.args.includes('--merge-by-host') || o.args.includes('--auto-merge'))) {
1221
1249
  throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
1222
1250
  }
@@ -1247,7 +1275,10 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1247
1275
  const script = [
1248
1276
  'set -u',
1249
1277
  ...(o.fallbackChain ? [
1250
- 'mkdir -p "$HOME/.elanous" && install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json" || exit 6',
1278
+ ...(o.configSnapshotHash ? [
1279
+ 'bun -e \'import { createHash } from "node:crypto"; import { readFileSync } from "node:fs"; const e = JSON.parse(readFileSync("/creds/config-snapshot.json", "utf8")); const c = JSON.parse(readFileSync("/creds/llm-fallback-config.json", "utf8")); const h = createHash("sha256").update(JSON.stringify({ version: e.version, keys: e.keys, sources: e.sources })).digest("hex"); if (h !== e.hash || JSON.stringify(c) !== JSON.stringify(e.keys)) process.exit(1);\' || exit 6',
1280
+ ] : []),
1281
+ 'mkdir -p "$HOME/.elanous" && { [ -e "$HOME/.elanous/config.json" ] || [ -L "$HOME/.elanous/config.json" ] || install -m 600 /creds/llm-fallback-config.json "$HOME/.elanous/config.json"; } || exit 6',
1251
1282
  `echo "ELANOUS_POD_FALLBACK_CHAIN source=${o.fallbackChain.source} steps=${o.fallbackChain.steps.join(',')}"`,
1252
1283
  ] : []),
1253
1284
  openGatewayModel
@@ -1390,7 +1421,7 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1390
1421
  apiVersion: 'batch/v1',
1391
1422
  kind: 'Job',
1392
1423
  metadata: { name: o.name, namespace: o.namespace, labels: { 'elanous.substrate': 'pod', 'elanous.job': o.name, ...podRunLabels(o), ...(o.workIdentity ? podWorkLabels(o.workIdentity) : {}), ...(o.zai || o.zaiFallback ? { [ZAI_POD_EGRESS_LABEL]: 'true' } : {}), ...o.provenance?.labels },
1393
- ...((o.execution || o.hostLeaseAdmitted || o.provenance) ? { annotations: { ...o.provenance?.annotations, ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
1424
+ ...((o.execution || o.hostLeaseAdmitted || o.provenance || o.configSnapshotHash) ? { annotations: { ...o.provenance?.annotations, ...(o.configSnapshotHash ? { 'elanous.config-snapshot-sha256': o.configSnapshotHash } : {}), ...(o.execution ? { [POD_EXECUTION_KEY_ANNOTATION]: o.execution.key, [POD_ATTEMPT_ANNOTATION]: String(o.execution.attempt) } : {}), ...(o.hostLeaseAdmitted ? { [POD_HOST_LEASE_ANNOTATION]: 'true' } : {}) } } : {}) },
1394
1425
  spec: {
1395
1426
  backoffLimit: 0,
1396
1427
  ttlSecondsAfterFinished: POD_JOB_TTL_AFTER_FINISHED_SECONDS,
@@ -1942,6 +1973,35 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1942
1973
  try {
1943
1974
  // Every attempt, including an OOM retry, must acquire a pool slot before applying a Job.
1944
1975
  const stallMs = options.launchStallMs ?? (getUserConfig().harness?.launchStallMinutes ?? 15) * 60_000;
1976
+ const slotNow = options.now ?? Date.now;
1977
+ let slotAttemptNumber = 0;
1978
+ let lastSlotReasonCode: string | undefined;
1979
+ let lastSlotAttempt: { observationKey: string; requestedAtMs: number; requestedAt: string } | undefined;
1980
+ const slotReasonCode = (reason: string | null | undefined): string => {
1981
+ if (!reason) return 'not-measured-yet';
1982
+ if (/no free slot/iu.test(reason)) return 'no-free-slot';
1983
+ if (/memory/iu.test(reason)) return 'memory-capacity';
1984
+ if (/capacity|lease/iu.test(reason)) return 'capacity';
1985
+ return 'pool-slot-unavailable';
1986
+ };
1987
+ const recordSlotObservation = (attempt: { observationKey: string; requestedAtMs: number; requestedAt: string },
1988
+ outcome: 'requested' | 'queued' | 'admitted' | 'rejected', reasonCode: string): void => {
1989
+ const pool = options.pool;
1990
+ let occupants: Record<string, number> | null = null;
1991
+ try { occupants = pool ? pool.snapshot() : null; } catch { /* observation must not change scheduling */ }
1992
+ const poolCapacity = pool?.members?.reduce((total, member) => total + Math.max(0, member.capacity), 0) ?? null;
1993
+ const data = {
1994
+ observationKey: attempt.observationKey, runId: childRunId, host: resolveHostId(env),
1995
+ requestedAt: attempt.requestedAt, waitedMs: Math.max(0, slotNow() - attempt.requestedAtMs),
1996
+ queued: outcome === 'queued', poolCapacity, occupants, reasonCode, parentId: ledgerRunId, outcome,
1997
+ };
1998
+ debug.log('pod.slot', outcome, data, { level: outcome === 'admitted' || outcome === 'requested' ? 'info' : 'warn' });
1999
+ try {
2000
+ appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-observation', data }, ledgerDir);
2001
+ if (outcome === 'rejected') appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-slot-incident', data }, ledgerDir);
2002
+ }
2003
+ catch (error) { debug.log('pod.slot', 'ledger-unavailable', { ...data, writeError: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2004
+ };
1945
2005
  // LAUNCH-STALL (10-06): a stage that waits past the cap says so once — today Pods sat 22 min to 5 h with no event.
1946
2006
  const stalledStages = new Set<string>();
1947
2007
  // pool-slot reason = what THIS launch saw on its last empty tryAcquire; admission reason = the pool-wide lease measurement (one pool, one reading).
@@ -1979,25 +2039,42 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
1979
2039
  };
1980
2040
  const acquireSlot = async (): Promise<PodPoolMember | null> => {
1981
2041
  if (!options.pool) return null;
2042
+ // Each actual acquisition is a separate observation, including the OOM retry in this
2043
+ // same child run. The ordinal keeps keys distinct even with a fixed test clock.
2044
+ const requestedAtMs = slotNow();
2045
+ const attempt = { observationKey: `${childRunId}:pod-slot:${requestedAtMs}:${++slotAttemptNumber}`,
2046
+ requestedAtMs, requestedAt: new Date(requestedAtMs).toISOString() };
2047
+ let firstSlotReasonCode: string | undefined;
2048
+ let slotQueuedRecorded = false;
1982
2049
  const stop = watchStall('pool-slot');
1983
2050
  // MINIH-MODE (0.2.37): the location is declared by the launch env — absent/unknown keeps the configured
1984
2051
  // capacities, so this launch path behaves exactly as before unless the declaration is there.
1985
2052
  const minihLocation = minihLocationFrom(env.ELANOUS_MINIH_LOCATION);
1986
2053
  try {
2054
+ recordSlotObservation(attempt, 'requested', 'pending');
1987
2055
  for (;;) {
1988
2056
  if (input.signal?.aborted) return null;
1989
2057
  // The reason comes back inside this call, so a concurrent launch cannot overwrite it.
1990
2058
  const kind = podPlacementKind(oomRetried ? retryTier : memoryTier, selectedGoalType, requestKind);
1991
- const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => { stageReason['pool-slot'] = reason; },
2059
+ const acquired = await options.pool.tryAcquire(unfitContexts, (reason) => {
2060
+ stageReason['pool-slot'] = reason;
2061
+ firstSlotReasonCode ??= slotReasonCode(reason);
2062
+ },
1992
2063
  { kind, ...(minihLocation ? { minihLocation } : {}), onPlacement: (placement) => { lastPlacement = placement; } });
1993
2064
  if (acquired) {
2065
+ recordSlotObservation(attempt, 'admitted', firstSlotReasonCode ?? 'admitted');
1994
2066
  debug.log('self-implement.pod', 'pool-slot', { spaceId: input.spaceId, context: acquired.context, inflight: options.pool.snapshot(), ...(lastPlacement ? { placement: lastPlacement } : {}) });
1995
2067
  if (lastPlacement) console.warn(`[pod] 배치: ${lastPlacement.reason}`);
1996
2068
  return acquired;
1997
2069
  }
2070
+ firstSlotReasonCode ??= slotReasonCode(stageReason['pool-slot']);
2071
+ if (!slotQueuedRecorded) {
2072
+ slotQueuedRecorded = true;
2073
+ recordSlotObservation(attempt, 'queued', firstSlotReasonCode);
2074
+ }
1998
2075
  await sleep(options.pollMs ?? 15_000);
1999
2076
  }
2000
- } finally { stop(); }
2077
+ } finally { lastSlotReasonCode = firstSlotReasonCode; lastSlotAttempt = attempt; stop(); }
2001
2078
  };
2002
2079
  const acquireAdmission = async (): Promise<boolean> => {
2003
2080
  if (!options.pool || typeof options.pool.acquireAdmission !== 'function') return true;
@@ -2033,8 +2110,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2033
2110
  let member: PodPoolMember | null;
2034
2111
  try { member = await acquireSlot(); } catch (error) { podAdmitError(error); throw error; }
2035
2112
  if (options.pool && !member) {
2113
+ if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted');
2036
2114
  exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'refused', data: { spaceId: input.spaceId, reason: 'no-slot' } });
2037
- return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened' } };
2115
+ return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
2038
2116
  }
2039
2117
  exitJourneyNode('pool-admit', { provenance: 'self-implement-pod', outcome: 'admitted', data: { spaceId: input.spaceId, ...(member ? { context: member.context } : {}) } });
2040
2118
  const currentContext = member ? null : baseKubectl(['config', 'current-context']);
@@ -2062,6 +2140,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2062
2140
  const cleanupSecret = () => { kubectl(['-n', namespace, 'delete', 'secret', `${name}-creds`, '--ignore-not-found']); };
2063
2141
  let repairResultAnnounced = false;
2064
2142
  let repairArtifactReady = false;
2143
+ let hostOriginCalls: number | null = 0;
2144
+ let sourceBaseSha: string | undefined;
2065
2145
  const collectFullLogs = (unavailableEvent: string, replace?: ReadonlySet<string>, onEvent?: (event: string, data: Record<string, unknown>) => void, childId?: string): { status: 'ok' | 'unavailable' | 'incomplete'; childLedgerIncomplete: boolean; samples: ReturnType<typeof parseMemSamples> } => {
2066
2146
  let full: ReturnType<Kubectl>;
2067
2147
  try {
@@ -2078,6 +2158,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2078
2158
  const imageSkip = /^ELANOUS_POD_SOURCE_IMAGE_SKIP ([^\r\n]+)\r?$/m.exec(full.stdout)?.[1];
2079
2159
  const delta = /^ELANOUS_POD_SOURCE_DELTA (mirror|origin)\r?$/m.exec(full.stdout)?.[1];
2080
2160
  if (via) debug.log('self-implement.pod', 'source-via', { job: name, via, ...(mirrorSkip ? { mirrorSkip } : {}), ...(imageSkip ? { imageSkip } : {}), ...(delta ? { delta } : {}) });
2161
+ recordPodSourceIoSummary(full.stdout, name, childId ?? childRunId, childId ? 'explicit-child-id' : 'pod-launch-child-run-id',
2162
+ (category, event, data, logOptions) => debug.log(category, event, data, logOptions), hostOriginCalls);
2081
2163
  let ledgerIncomplete = false;
2082
2164
  let childLedgerIncomplete = false;
2083
2165
  let artifactIncomplete = false;
@@ -2355,20 +2437,43 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2355
2437
  }
2356
2438
  const now = options.now ?? Date.now;
2357
2439
  const issueVerifiedAppCredential = async (fresh = false): Promise<{ token: string; expiresAt: number } | null> => {
2358
- if (!repository) return null;
2440
+ if (!repository) {
2441
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, reason: 'repository-unavailable', fresh });
2442
+ return null;
2443
+ }
2359
2444
  // This is the same repository-scoped, contents+pull_requests installation request on launch and refresh.
2360
- const candidate = (options.githubInstallation ?? ((repo, o) => coalescedInstallationCredential({ repository: repo.split('/')[1]! }, { fresh: o?.fresh })))(repository, { fresh });
2361
- if (!candidate?.token) return null;
2445
+ let candidate: ReturnType<NonNullable<typeof options.githubInstallation>>;
2446
+ try { candidate = (options.githubInstallation ?? ((repo, o) => coalescedInstallationCredential({ repository: repo.split('/')[1]! }, { fresh: o?.fresh })))(repository, { fresh }); }
2447
+ catch {
2448
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-threw', fresh });
2449
+ return null;
2450
+ }
2451
+ if (!candidate?.token) {
2452
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'mint-unavailable', fresh });
2453
+ return null;
2454
+ }
2362
2455
  const expiry = candidate.expires_at ?? ('expiresAt' in candidate ? candidate.expiresAt : undefined);
2363
2456
  const expiresAt = typeof expiry === 'number' ? expiry : Date.parse(expiry ?? '');
2364
- if (!Number.isFinite(expiresAt) || expiresAt <= now()) return null;
2365
- const available = await (options.githubRepositories ?? installationRepositories)(candidate.token);
2366
- return available?.length === 1 && available[0]?.toLowerCase() === repository.toLowerCase()
2367
- ? { token: candidate.token, expiresAt } : null;
2457
+ if (!Number.isFinite(expiresAt) || expiresAt <= now()) {
2458
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: Number.isFinite(expiresAt) ? 'expired' : 'expiry-unavailable', expiresAt: Number.isFinite(expiresAt) ? new Date(expiresAt).toISOString() : null, fresh });
2459
+ return null;
2460
+ }
2461
+ let available: Awaited<ReturnType<NonNullable<typeof options.githubRepositories>>>;
2462
+ try { available = await (options.githubRepositories ?? installationRepositories)(candidate.token); }
2463
+ catch {
2464
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verification-threw', expiresAt: new Date(expiresAt).toISOString(), fresh });
2465
+ return null;
2466
+ }
2467
+ if (available?.length !== 1 || available[0]?.toLowerCase() !== repository.toLowerCase()) {
2468
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'repository-verification-failed', availableCount: available?.length ?? null, expiresAt: new Date(expiresAt).toISOString(), fresh });
2469
+ return null;
2470
+ }
2471
+ debug.log('self-implement.pod', 'github-app-decision', { job: name, repository, reason: 'verified', expiresAt: new Date(expiresAt).toISOString(), fresh });
2472
+ return { token: candidate.token, expiresAt };
2368
2473
  };
2369
2474
  let appCredential: Awaited<ReturnType<typeof issueVerifiedAppCredential>> = null;
2370
2475
  try { appCredential = await issueVerifiedAppCredential(ghLoginRetried); }
2371
- catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, reason: 'mint-or-verification-failed' }); }
2476
+ catch { debug.log('self-implement.pod', 'github-app-unavailable', { job: name, repository, reason: 'mint-or-verification-threw' }); }
2372
2477
  // PODCRED1: a short token is still shipped — the host renews it in the Pod on the first live poll — but it is
2373
2478
  // observed, so an exit-7 burst can be checked against the remaining life the Pods actually started with.
2374
2479
  if (appCredential && appCredential.expiresAt - now() < POD_APP_TOKEN_MIN_START_MS) {
@@ -2384,6 +2489,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2384
2489
  // The host polling loop is a refresh path even when the Pod cannot reach the relay.
2385
2490
  const hostRefresh = Boolean(appCredential);
2386
2491
  const podGhToken = hostRefresh ? appCredential!.token : creds.ghToken;
2492
+ debug.log('self-implement.pod', 'github-credential-source', { job: name, repository, source: hostRefresh ? 'verified-app' : 'human-fallback', expiresAt: hostRefresh ? new Date(appCredential!.expiresAt).toISOString() : null });
2387
2493
  const githubPassKeys = hostRefresh ? passKeys.filter((key) => !['GH_TOKEN', 'GITHUB_TOKEN', 'GH_CONFIG_DIR'].includes(key)) : passKeys;
2388
2494
  let ghTokenExpiresAt = hostRefresh ? appCredential!.expiresAt : null;
2389
2495
  const requestedGoalDoc = env.ELANOUS_POD_GOAL_DOC;
@@ -2515,6 +2621,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2515
2621
  if (!zaiFallbackSpec) fallbackSteps = fallbackSteps.filter(step => step !== 'zai');
2516
2622
  }
2517
2623
  const fallbackChain = { steps: fallbackSteps, source: normalizedFallback.usedDefault ? 'default' as const : 'host' as const };
2624
+ const { buildPodConfigSnapshot } = await import('./pod-config-snapshot.js');
2625
+ const configSnapshot = buildPodConfigSnapshot(hostConfig, {
2626
+ steps: fallbackChain.steps, overage: zaiOverage,
2627
+ worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200,
2628
+ });
2629
+ debug.log('self-implement.pod', 'config-snapshot', { job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount });
2518
2630
  debug.log('self-implement.pod', 'fallback-chain-carried', {
2519
2631
  job: name, source: fallbackChain.source, steps: fallbackChain.steps,
2520
2632
  ...(normalizedFallback.dropped.length ? { droppedCount: normalizedFallback.dropped.length } : {}),
@@ -2533,7 +2645,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2533
2645
  ? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
2534
2646
  : { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
2535
2647
  'gh-token': podGhToken, feature: input.feature,
2536
- 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps, zaiCodingPlan: { overage: zaiOverage } }, harness: { worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200 } }),
2648
+ 'llm-fallback-config.json': configSnapshot.configJson,
2649
+ 'config-snapshot.json': configSnapshot.envelopeJson,
2537
2650
  ...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
2538
2651
  ...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
2539
2652
  ...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
@@ -2547,7 +2660,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2547
2660
  if (missing.length) debug.log('self-implement.pod', 'pass-env-missing', { job: name, missing }, { level: 'warn' });
2548
2661
  // ☸️ 재개(P3 · 2026-09-26): 같은 이름의 Job 이 이미 있으면 «지우지 않고» 붙는다 — 호스트가 끊긴 동안에도 원격은 계속 돌았다.
2549
2662
  // 🩸 종전엔 여기서 delete 부터 해서, 재개가 원격에서 멀쩡히 돌던 Job 을 죽였다. 실패로 끝난 Job 만 지우고 다시 만든다.
2550
- // ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 · 대표 2026-09-26) — 라벨 판정은 로컬 이미지 이름으로 한다.
2663
+ // ☸️ 노드 레지스트리에 이 판이 있으면 그것을 pull 한다(델타 · 2026-09-26) — 라벨 판정은 로컬 이미지 이름으로 한다.
2551
2664
  const jobImage = member?.imageRef ?? image;
2552
2665
  // A pool member may pull a different image than the host's local one.
2553
2666
  // The local Docker label cannot prove that member image's commit.
@@ -2729,12 +2842,21 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2729
2842
  slotId: env.ELANOUS_POD_SLOT_ID,
2730
2843
  work: !goalDoc && env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'authoring' : (oomRetried ? retryTier : memoryTier) === 'lite' ? 'lite' : 'harness',
2731
2844
  };
2732
- // TA-POD-WARMBOOT-PARITY shadow only: record the decision on the existing fresh-Job path.
2733
- // Until a shared warm-candidate contract exists, evidence stays unmeasured and this never changes execution.
2845
+ // TA-POD-WARMBOOT-PARITY shadow only: read injected evidence, then keep the fresh-Job path.
2846
+ // This boundary must not open host configuration or credential files for a warm decision.
2734
2847
  if (workIdentity.taskCard) {
2735
- const warmReuseConfig = options.warmReuseConfig?.() ?? (options.kubectl ? undefined : getUserConfig().pod?.warmReuse);
2736
- const decision = decideWarmReuse('ta', warmReuseConfig, options.warmReuseEvidence?.());
2737
- debug.log('pod.warm', 'ta-shadow-observation', { ...decision, execution: 'fresh-job' });
2848
+ let stage: 'config' | 'evidence' | 'decision' = 'config';
2849
+ try {
2850
+ const config = options.warmReuseConfig?.();
2851
+ stage = 'evidence';
2852
+ const evidence = options.warmReuseEvidence?.();
2853
+ stage = 'decision';
2854
+ const decision = decideWarmReuse('ta', config, evidence);
2855
+ debug.log('pod.warm', 'ta-shadow-observation', { ...decision, execution: 'fresh-job' });
2856
+ } catch {
2857
+ debug.log('pod.warm', 'ta-shadow-unavailable', { spaceId: input.spaceId,
2858
+ reason: stage === 'decision' ? 'warm-decision-failed' : `injected-${stage}-failed`, execution: 'fresh-job' }, { level: 'warn' });
2859
+ }
2738
2860
  }
2739
2861
  // TA-POD-WARMBOOT-PARITY (GATE-WARM-BOOT parity · #27805): a commit-pinned source on a pool host — put that commit into
2740
2862
  // the host mirror first (once per host·commit in this process) so podSourceScript finds it instead of fetching
@@ -2753,12 +2875,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2753
2875
  else if (seedSource.kind !== 'default') seedSkip = `source-${seedSource.kind}`;
2754
2876
  else {
2755
2877
  const resolveHead = options.resolveSourceHead ?? (options.kubectl ? undefined : resolveDefaultSourceHead);
2756
- let head: { sha?: string; reason?: string } | undefined;
2878
+ let head: { sha?: string; reason?: string; originCalls?: number } | undefined;
2757
2879
  try { head = resolveHead ? await resolveHead({ repoUrl, ...(seedSource.base ? { base: seedSource.base } : {}), cwd: seedCwd }) : undefined; }
2758
2880
  catch { head = { reason: 'resolve-threw' }; }
2759
2881
  if (!resolveHead) seedSkip = 'no-head-resolver';
2760
- else if (head?.sha && /^[0-9a-f]{40}$/.test(head.sha)) seedCommit = head.sha;
2761
- else seedSkip = `default-head-${head?.reason ?? 'unresolved'}`;
2882
+ else if (head) hostOriginCalls = typeof head.originCalls === 'number' && Number.isSafeInteger(head.originCalls) && head.originCalls >= 0 ? head.originCalls : null;
2883
+ if (head?.sha && /^[0-9a-f]{40}$/.test(head.sha)) { seedCommit = head.sha; sourceBaseSha = head.sha; }
2884
+ else if (resolveHead) seedSkip = `default-head-${head?.reason ?? 'unresolved'}`;
2762
2885
  }
2763
2886
  if (seedMirror && seedCommit && member?.sshHost) {
2764
2887
  const seedHost = member.sshHost;
@@ -2769,7 +2892,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2769
2892
  } catch (error) {
2770
2893
  seed = { host: seedHost, ok: false, ms: 0, detail: String(error).slice(0, 300) };
2771
2894
  }
2772
- debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
2895
+ debug.log('self-implement.pod', 'mirror-seed', { job: name, host: seedHost, commit: seedCommit, sourceKind: seedSource.kind, ...(sourceBaseSha ? { sourceBaseSha } : {}), ok: seed?.ok ?? false, ms: seed?.ms ?? 0, ...(seed?.detail ? { detail: seed.detail } : {}) }, seed?.ok ? undefined : { level: 'warn' });
2773
2896
  } else {
2774
2897
  debug.log('self-implement.pod', 'mirror-seed-skipped', { job: name, reason: seedSkip ?? 'unknown', sourceKind: seedSource.kind, ...(member?.sshHost ? { host: member.sshHost } : {}) });
2775
2898
  }
@@ -2804,7 +2927,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2804
2927
  cleanupSecret();
2805
2928
  return { exitCode: 1, output: '', error: { code: 'pod-provenance', message } };
2806
2929
  }
2807
- const job = podJobManifest({ provenance, name, namespace, fallbackChain, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...(options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: jobImageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
2930
+ const job = podJobManifest({ provenance, name, namespace, fallbackChain, configSnapshotHash: configSnapshot.hash, ...(resultMarkerLine ? { resultMarkerLine } : {}), image: jobImage, workIdentity, ...(env.ELANOUS_TASK_BOUND_PR && /^[1-9]\d*$/.test(env.ELANOUS_TASK_BOUND_PR) && Number.isSafeInteger(Number(env.ELANOUS_TASK_BOUND_PR)) ? { boundPrNumber: Number(env.ELANOUS_TASK_BOUND_PR) } : {}), ...(member?.imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}), repoUrl, ...((seedSource.kind === 'default' && sourceBaseSha) ? { source: { ...seedSource, baseSha: sourceBaseSha } } : options.source ? { source: options.source } : {}), ...(options.repairCommitOnly ? { repairCommitOnly: options.repairCommitOnly } : {}), ...(hostMirror ? { hostMirror } : {}), args: jobArgs, passEnv: jobPassEnv, deadlineSeconds: jobDeadlineSeconds, ...(goalDoc ? { goalDoc } : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? { authorSentence: true, ...(env.ELANOUS_POD_AUTHOR_GRADE === 'lite' || env.ELANOUS_POD_AUTHOR_GRADE === 'full' ? { authorGrade: env.ELANOUS_POD_AUTHOR_GRADE } : {}) } : {}), runId: launchRunId, ...(parentRunId ? { parentRunId } : {}), ...(jobArmEnv ? { armEnv: jobArmEnv } : {}), hostId: resolveHostId(env), skillEnvs: Object.keys(skillEnvs), memoryLimit, memoryRequest, imageCommit: jobImageCommit, ...(grok ? { grokCredential: 'grokAuth' in creds && creds.grokAuth ? 'subscription' as const : 'api_key' as const } : {}), ...(codexAccounts ? { codexAccounts } : {}), ...(hostRefresh ? { appCredential: true } : {}), execution: { key: executionKey, attempt: oomRetried ? 2 : 1 }, hostLeaseAdmitted: !!releaseAdmission, ...(roleCodexCredential ? { reviewerCodexAuth: true } : {}), ...(bedrockSpec ? { bedrock: bedrockSpec } : {}), ...(zaiSpec ? { zai: zaiSpec } : {}), ...(zaiFallbackSpec ? { zaiFallback: zaiFallbackSpec } : {}) }); // kubectl 주입(=시험)이면 docker 를 부르지 않는다
2808
2931
  const carriedBranch = goalDoc ? 'goal-doc' as const : env.ELANOUS_POD_AUTHOR_ON_POD === '1' && !shard ? 'author' as const : undefined;
2809
2932
  const carriedChildLlm = carriedBranch ? podDelegatedChildLlm(jobArgs) : undefined;
2810
2933
  jobApplyStartedAt = Date.now();
@@ -2812,6 +2935,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2812
2935
  zaiPendingApply.delete(name); // apply 뒤엔 Job 라벨이 센다(성공) · 실패면 셀 것이 없다
2813
2936
  if (a.status !== 0) { cleanupSecret(); return { exitCode: 1, output: a.stderr, error: { code: 'pod-apply', message: a.stderr.trim() } }; }
2814
2937
  releaseAdmission?.applied?.(name, context, namespace);
2938
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-config-snapshot', data: {
2939
+ job: name, hash: configSnapshot.hash, keyCount: configSnapshot.keyCount,
2940
+ } }, ledgerDir); } catch (error) {
2941
+ debug.log('self-implement.pod', 'config-snapshot-ledger-unavailable', {
2942
+ job: name, reason: error instanceof Error ? error.message : String(error),
2943
+ }, { level: 'warn' });
2944
+ }
2815
2945
  const imageFacts = { job: name, childRunId: liveChildRunId, image: jobImage, imageCommit: jobImageCommit, context };
2816
2946
  // POD-LAUNCH-PROVENANCE — append-only «started» row: who · why · when, on the parent's existing run ledger.
2817
2947
  const startedRow = { job: name, run: launchRunId, attempt: oomRetried ? 2 : 1, provenance: provenanceRowFromAnnotations(provenance.annotations) };
@@ -2891,6 +3021,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2891
3021
  debug.log('self-implement.pod', 'job-applied', { job: name, namespace, ...(member ? { context: member.context } : {}), image: jobImage, spaceId: input.spaceId, passEnv, ...(openrouterCredentialRequired ? { openrouterKeyPresent: passEnv.includes('OPENROUTER_API_KEY') } : {}), ...(openGateway ? { openGatewayKeyPresent: passEnv.includes('OPENGATEWAY_API_KEY') } : {}), ...(anthropic ? { anthropicKeyPresent: passEnv.includes('ANTHROPIC_API_KEY') } : {}), ...(bedrockSpec ? { bedrockSecret: bedrockSpec.secretName, bedrockSecretKeys: bedrockSpec.keys, bedrockRegionFrom: bedrockSpec.region.from } : {}), ...(zaiRoute ? { zaiRoute, ...(zaiSpec ? { zaiSecret: zaiSpec.secretName } : {}) } : {}), extraArgs: options.extraArgs ?? [], ...(options.armEnv?.ELANOUS_ARM_ID ? { armId: options.armEnv.ELANOUS_ARM_ID } : {}) });
2892
3022
  let state: 'complete' | 'failed' | 'aborted' = 'failed';
2893
3023
  let failedReason = '';
3024
+ let deadlineJobCreatedAt: string | null = null;
3025
+ let deadlineJobCompletedAt: string | null = null;
2894
3026
  let containerReason: string | null = null;
2895
3027
  let containerExitCode: number | null = null;
2896
3028
  // JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
@@ -3007,6 +3139,11 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3007
3139
  catch (error) { jobReadError = error; }
3008
3140
  const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
3009
3141
  failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
3142
+ if (jobRead?.status === 0) {
3143
+ const [, , , createdText, completedText] = jobRead.stdout.replace(/\r?\n$/, '').split('\t');
3144
+ deadlineJobCreatedAt = createdText && Number.isFinite(Date.parse(createdText)) ? createdText : null;
3145
+ deadlineJobCompletedAt = completedText && Number.isFinite(Date.parse(completedText)) ? completedText : null;
3146
+ }
3010
3147
  // One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
3011
3148
  let podsRead: { status: number | null; stdout: string } | null = null;
3012
3149
  try {
@@ -3102,7 +3239,6 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3102
3239
  }
3103
3240
  await sleep(options.pollMs ?? 15_000);
3104
3241
  }
3105
- await refreshPodTermination();
3106
3242
  if (!terminalImageRecorded) recordPodImage(true);
3107
3243
  let logs = '';
3108
3244
  let logTailReason: string | undefined;
@@ -3354,6 +3490,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3354
3490
  if (noResultDiagnostic && !noResultDiagnostic.includes('stage=unknown')) {
3355
3491
  debug.log('self-implement.pod', 'no-result-ledger-diagnostic', { job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic }, { compact: { stringMax: 500 } });
3356
3492
  }
3493
+ // The marker can precede the container status by several seconds. Read the Pod after
3494
+ // collecting the child logs, before the first terminal evidence row is emitted.
3495
+ await refreshPodTermination();
3357
3496
  // POD-LAUNCH-PROVENANCE — append-only «finished» row paired with its started row on job·run.
3358
3497
  // Keyed on launchRunId like the started row; a reattached Job's inherited child run rides along as childRun.
3359
3498
  // exitCode stays null when the container's code was not read (never filled in as 0).
@@ -3429,7 +3568,10 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3429
3568
  if (unfitRetry) return unfitRetry;
3430
3569
  if (!await acquireAdmission()) return admissionFailure();
3431
3570
  member = await acquireSlot();
3432
- if (options.pool && !member) return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened' } };
3571
+ if (options.pool && !member) {
3572
+ if (lastSlotAttempt) recordSlotObservation(lastSlotAttempt, 'rejected', lastSlotReasonCode ?? 'aborted');
3573
+ return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before a pool slot opened', ...(lastSlotReasonCode ? { reasonCode: lastSlotReasonCode } : {}) } };
3574
+ }
3433
3575
  if (member) context = member.context;
3434
3576
  if (input.signal?.aborted) return { exitCode: null, output: '', error: { code: 'aborted', message: 'aborted before OOM retry' } };
3435
3577
  continue;
@@ -3498,6 +3640,17 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3498
3640
  const deadlineExceeded = state === 'failed' && failedReason === 'DeadlineExceeded';
3499
3641
  const deadlineSeconds = jobDeadlineSeconds;
3500
3642
  if (deadlineExceeded) {
3643
+ const jobCreatedAt = deadlineJobCreatedAt;
3644
+ const timing = podJobFinishedTiming({ jobCreatedAt, jobCompletedAt: deadlineJobCompletedAt,
3645
+ podFinishedAt: typeof podTermination?.finishedAt === 'string' && Number.isFinite(Date.parse(podTermination.finishedAt))
3646
+ ? podTermination.finishedAt : null,
3647
+ observedAt: new Date((options.now ?? Date.now)()).toISOString() });
3648
+ const lastStage = deadlineMarker?.stage ?? disposition?.stage ?? null;
3649
+ debug.log('pod.job', 'finished', {
3650
+ job: name, jobCreatedAt, finishedAt: timing.finishedAt, finishedAtSource: timing.finishedAtSource,
3651
+ elapsedMs: timing.elapsedMs,
3652
+ deadlineSec: deadlineSeconds, tier: oomRetried ? retryTier : memoryTier, lastStage,
3653
+ });
3501
3654
  debug.log('self-implement.pod', 'deadline-exceeded', {
3502
3655
  job: name,
3503
3656
  deadlineSeconds,
@@ -4006,7 +4159,7 @@ export async function rebuildLocalPodImageOnce(deps: {
4006
4159
  });
4007
4160
  });
4008
4161
  });
4009
- const result = await build('docker/harness/build.sh');
4162
+ const result = await build(['docker', 'harness', 'build.sh'].join(sep));
4010
4163
  if (result.status !== 0) {
4011
4164
  return { image, action: 'failed', error: `--substrate pod: 이미지 굽기 실패 rc=${result.status}${result.error ? ` (${(result.error as NodeJS.ErrnoException).code ?? result.error.message})` : ''}: ${(result.stdout + result.stderr).slice(-400)}` };
4012
4165
  }
@@ -7,6 +7,15 @@ import { getUserConfig } from '../user-config.js';
7
7
  import type { LLMToolSpec } from '../llm.js';
8
8
  import type { ToolRuntime } from './types.js';
9
9
 
10
+ /** Whole nested-skill budget; the inner LLM idle timer only bounds one stream. */
11
+ export const SKILL_EXEC_TIMEOUT_MS = 300_000;
12
+
13
+ export interface SkillExecRunOptions {
14
+ signal?: AbortSignal;
15
+ /** Test seam for a short deterministic whole-skill deadline. */
16
+ timeoutMs?: number;
17
+ }
18
+
10
19
  export interface SkillExecArgs {
11
20
  /** Exact name of the skill to execute. */
12
21
  skill: string;
@@ -19,6 +28,11 @@ export interface SkillExecResult extends Record<string, unknown> {
19
28
  output: string;
20
29
  ok: boolean;
21
30
  error?: string;
31
+ discoveryCard?: string;
32
+ }
33
+
34
+ export interface SkillExecDiscoveryDeps {
35
+ discoverPlugin?: (gap: string, deps?: { signal?: AbortSignal }) => Promise<{ card: string }>;
22
36
  }
23
37
 
24
38
  export type SkillExecIndexProvider = () => readonly SkillIndexEntry[];
@@ -76,7 +90,11 @@ export function buildSkillExecTool(): LLMToolSpec {
76
90
  };
77
91
  }
78
92
 
79
- export async function dispatchSkillExec(args: SkillExecArgs): Promise<SkillExecResult> {
93
+ export async function dispatchSkillExec(
94
+ args: SkillExecArgs,
95
+ deps: SkillExecDiscoveryDeps = {},
96
+ options: SkillExecRunOptions = {},
97
+ ): Promise<SkillExecResult> {
80
98
  const { skill, task } = args;
81
99
  const extra = getUserConfig().skillRouter.harnessExecAllowlist;
82
100
  const index = obtainSkillIndex();
@@ -116,11 +134,83 @@ export async function dispatchSkillExec(args: SkillExecArgs): Promise<SkillExecR
116
134
  };
117
135
  }
118
136
 
119
- const result = await invokeResearch(task, { skill });
137
+ if (options.signal?.aborted) {
138
+ return { skill, ok: false, error: 'skill-exec-cancelled', output: '스킬 실행이 취소됐습니다. 현재 근거로 다음 단계를 결정하세요.' };
139
+ }
140
+
141
+ // Race the whole invocation so even a provider that ignores abort gives the
142
+ // parent a failed tool result. Cooperative LLM and child tools get the same
143
+ // signal and stop their own work.
144
+ const child = new AbortController();
145
+ const timeoutMs = options.timeoutMs ?? SKILL_EXEC_TIMEOUT_MS;
146
+ let settled = false;
147
+ let finishEarly: ((reason: 'skill-exec-timeout' | 'skill-exec-cancelled') => void) | undefined;
148
+ const interrupted = new Promise<'skill-exec-timeout' | 'skill-exec-cancelled'>((resolve) => {
149
+ finishEarly = (reason) => {
150
+ if (settled) return;
151
+ settled = true;
152
+ resolve(reason);
153
+ child.abort();
154
+ };
155
+ });
156
+ const onParentAbort = () => finishEarly?.('skill-exec-cancelled');
157
+ options.signal?.addEventListener('abort', onParentAbort, { once: true });
158
+ const timer = setTimeout(() => finishEarly?.('skill-exec-timeout'), timeoutMs);
159
+ observe('started', { skill, timeoutMs });
160
+ let progressChunks = 0;
161
+ let progressBytes = 0;
162
+ let result: Awaited<ReturnType<typeof invokeResearch>> | undefined;
163
+ let interruption: 'skill-exec-timeout' | 'skill-exec-cancelled' | undefined;
164
+ try {
165
+ const outcome = await Promise.race([
166
+ invokeResearch(task, { skill, signal: child.signal, onProgress: (delta) => {
167
+ progressChunks += 1;
168
+ progressBytes += delta.length;
169
+ if (progressChunks === 1 || progressChunks % 32 === 0) {
170
+ observe('progress', { skill, progressChunks, progressBytes });
171
+ }
172
+ } }).then((value) => ({ result: value })),
173
+ interrupted.then((reason) => ({ interruption: reason })),
174
+ ]);
175
+ settled = true;
176
+ if ('interruption' in outcome) interruption = outcome.interruption;
177
+ else result = outcome.result;
178
+ } finally {
179
+ clearTimeout(timer);
180
+ options.signal?.removeEventListener('abort', onParentAbort);
181
+ }
182
+ if (interruption) {
183
+ observe('interrupted', { skill, reason: interruption, timeoutMs });
184
+ return {
185
+ skill,
186
+ ok: false,
187
+ error: interruption,
188
+ output: interruption === 'skill-exec-timeout'
189
+ ? `스킬 실행 시간이 초과됐습니다 (${timeoutMs}ms). 범위를 좁혀 다시 시도하거나 현재 근거로 답하세요.`
190
+ : '스킬 실행이 취소됐습니다. 현재 근거로 다음 단계를 결정하세요.',
191
+ };
192
+ }
193
+ if (!result) throw new Error('skill_exec completed without a result');
194
+ observe('completed', { skill, ok: result.ok, progressChunks, progressBytes, durationMs: result.durationMs });
195
+ // A low-quality research result is a capability gap. Keep the original failure,
196
+ // and attach a bounded discovery card rather than silently switching tools.
197
+ let discoveryCard: string | undefined;
198
+ if (!result.ok && /\b(?:no data|no evidence|missing|unavailable|not found|empty)\b|(?:자료가 없|데이터가 없|자료 부족|미확인|찾지 못)/i
199
+ .test(`${result.output} ${result.error ?? ''}`)) {
200
+ const controller = new AbortController();
201
+ const timer = setTimeout(() => controller.abort(new Error('plugin discovery time budget exhausted')), 10_000);
202
+ try {
203
+ const discovery = deps.discoverPlugin ?? (await import('../research/plugin-discovery.js')).discoverResearchPlugin;
204
+ const found = await discovery(task, { signal: controller.signal });
205
+ discoveryCard = found.card;
206
+ } catch { /* The skill failure remains the authoritative result. */ }
207
+ finally { clearTimeout(timer); }
208
+ }
120
209
  return {
121
210
  skill,
122
211
  ok: result.ok,
123
- output: result.output,
212
+ output: discoveryCard ? `${result.output}\n\n${discoveryCard}` : result.output,
213
+ ...(discoveryCard ? { discoveryCard } : {}),
124
214
  ...(result.error ? { error: result.error } : {}),
125
215
  };
126
216
  }
@@ -128,7 +218,7 @@ export async function dispatchSkillExec(args: SkillExecArgs): Promise<SkillExecR
128
218
  export const skillExecRuntime: ToolRuntime<SkillExecArgs, SkillExecResult> = {
129
219
  id: 'skill_exec',
130
220
  spec: buildSkillExecTool(),
131
- async run(req) {
132
- return dispatchSkillExec(req);
221
+ async run(req, ctx) {
222
+ return dispatchSkillExec(req, {}, { signal: ctx.signal });
133
223
  },
134
224
  };