elanous 0.2.37 → 0.2.38

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 (588) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{2002-a43a3f380df873ec.js → 1026-44010f405704050c.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
  6. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{7424.c0fe2a595d4232b5.js → 1632.7d87f998e714bede.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/{4937-28d437999b77c9dd.js → 1923-5c1695332240246a.js} +1 -1
  13. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
  14. package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
  18. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
  19. package/apps/pwa/out/_next/static/chunks/{3199.6a1a9b0e6cd01dc6.js → 2415.738b777642a02233.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{1262.a89bb27a5b2f844e.js → 3086.fb14b60ce98b53d3.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/3124-561f7f037943cde2.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
  31. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{2283.edd9627b7bdfb546.js → 3291.f6c1005387d514bd.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
  34. package/apps/pwa/out/_next/static/chunks/{6877-84d47b7e85d0c41e.js → 3341-f09b9efbd7a82f70.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
  38. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/{6680.6a693c28aae4cd19.js → 3528.e4b8ab70d339f965.js} +1 -1
  40. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
  45. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
  57. package/apps/pwa/out/_next/static/chunks/{4036.d54e55e1ebf5acdc.js → 4804.6012b5cd33c22792.js} +2 -2
  58. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
  60. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{6819.be5c9c4d67f22922.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
  65. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/{757-4fbaf50942b8c424.js → 5255-1b60d50eabe9f057.js} +1 -1
  67. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
  68. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{7867.e8725745ddd1d940.js → 5307.d7328020227880c2.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
  73. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{5046.7fd5cbd859299448.js → 5638.107314dc479e2f37.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
  80. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6493.27ad77de7aac7966.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/{1224.2ceca6c180d5130b.js → 7000.28157393caaf5343.js} +1 -1
  88. package/apps/pwa/out/_next/static/chunks/{6745-5a63492933959dd9.js → 7161-8f22db3ec5ed005e.js} +3 -3
  89. package/apps/pwa/out/_next/static/chunks/{2479-fe7e188bd9402d14.js → 7311-60a7ea80d23c7521.js} +1 -1
  90. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{5952.294fc574a8625184.js → 7488.966b116789f3d41a.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
  95. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{6252.240578f10952e091.js → 7628.6b16863ac3972333.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{1746.3563617ea64023a3.js → 7954.4f7a8832663ee979.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{4931.95cc6dbd230774ca.js → 8019.21ca554a821dad01.js} +16 -16
  102. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{2375.bf364c85dbb6f085.js → 8487.291666583bebe640.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{4383.18e5c54db3a22c88.js → 8879.ac06755bcf3e44a1.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
  111. package/apps/pwa/out/_next/static/chunks/{9151.a2c51e93f9156dae.js → 8911.bf5e712acb25fb6c.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{58edce7d.f1b0c72acf13b123.js → 8994d93e.33ba491f95345fc2.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/{5f6af561-f90b7a67f4f75d13.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
  116. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
  117. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
  121. package/apps/pwa/out/_next/static/chunks/{de8446d3.31b73eb239fecd7b.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/{page-5c112c6d7c33656e.js → page-c348a3959c5b5fc6.js} +1 -1
  140. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-88a1edbff62eaf1d.js → page-d1d1210f99f620ae.js} +1 -1
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/{page-b9af2ac1c4737ce8.js → page-7f569e533ddeecba.js} +1 -1
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/{page-fb9e639c107f5f72.js → page-a9d9a3e66459c1e0.js} +1 -1
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{709a918c.4fd3b4e2a32cb4e3.js → b7459770.6539b11860eb8a9c.js} +7 -7
  174. package/apps/pwa/out/_next/static/chunks/{d9815f84.4918f682a45a8502.js → b7478fef.5917716286213fcc.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/{4337e36d.f42c3b391b3d8f20.js → bb6987f9.3647e1a23b0e3217.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/de8b930d.d94c0f42acf807fc.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{8c58d09b.e8724a299658d86f.js → eaad0cba.771200940c529df7.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/graphs/release/recipes.yaml +9 -0
  278. package/graphs/release/release-loop.yaml +26 -18
  279. package/package.json +1 -1
  280. package/scripts/ask-op-inbox-once.ts +17 -0
  281. package/scripts/brand/check.ts +13 -4
  282. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  283. package/scripts/gate-0226-failure-census.ts +39 -0
  284. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  285. package/scripts/provision-export-redactions.ts +15 -0
  286. package/scripts/public-copy-lint.ts +122 -0
  287. package/scripts/public-export.ts +69 -2
  288. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  289. package/scripts/ratchets/train-side-invariants.sh +7 -1
  290. package/scripts/release-loop/cut-branch.ts +61 -12
  291. package/scripts/release-loop/gate-node.ts +161 -25
  292. package/scripts/release-loop/gate-partial.ts +82 -3
  293. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  294. package/scripts/release-loop/gate-radius-live.ts +4 -2
  295. package/scripts/release-loop/resume-cap.ts +2 -1
  296. package/scripts/release-loop/resume-release.ts +297 -8
  297. package/scripts/release-loop/resume.ts +13 -5
  298. package/scripts/release-loop/traffic-node.ts +12 -4
  299. package/scripts/release-loop/traffic-transition.ts +53 -13
  300. package/scripts/release-loop/version-node.ts +29 -4
  301. package/scripts/ux-sim.ts +1 -1
  302. package/scripts/video-pipeline.ts +2 -2
  303. package/src/acp/core-turn-bridge.ts +6 -1
  304. package/src/agent/run-context.ts +1 -1
  305. package/src/agent/task-notification.ts +3 -1
  306. package/src/agent-substrate/review-observation.ts +10 -0
  307. package/src/agent-substrate/self-review-cli.ts +195 -27
  308. package/src/auto-research/question-ladder-contract.ts +137 -0
  309. package/src/auto-research/research-turn.ts +134 -0
  310. package/src/autopilot/discovery/doc-lint.ts +1 -1
  311. package/src/bots/screen-probe.ts +1 -1
  312. package/src/capture/tui-self-report.ts +10 -2
  313. package/src/chat/index.ts +1 -0
  314. package/src/chat/tool-render/dispatch.ts +8 -1
  315. package/src/cli/guardian-cli.ts +3 -1
  316. package/src/cli/intake-cli.ts +48 -12
  317. package/src/cli/lesson-cli.ts +69 -9
  318. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  319. package/src/cli/pr-land-refusal.ts +1 -1
  320. package/src/cli/pty-takeover-cli.ts +58 -5
  321. package/src/cli/release-checklist-read-cli.ts +5 -2
  322. package/src/cli/release-cli.ts +47 -9
  323. package/src/cli/review-carry.ts +77 -0
  324. package/src/cli/self-update.ts +1 -1
  325. package/src/cli/tasks-card-show.ts +31 -1
  326. package/src/cli/tasks-cli.ts +62 -23
  327. package/src/cli/tasks-read-cli.ts +13 -5
  328. package/src/context-bus/context-now.ts +86 -2
  329. package/src/core-turn/run-core-turn.ts +9 -2
  330. package/src/core-turn/types.ts +3 -0
  331. package/src/dashboard/index.ts +18 -17
  332. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  333. package/src/dashboard/side-basic-runtime.ts +61 -0
  334. package/src/dashboard/slash-runtime/dashboard-handlers.ts +2 -0
  335. package/src/dashboard/term-slash-runtime.ts +2 -0
  336. package/src/dashboard/turn-preamble.ts +28 -4
  337. package/src/domains/guardian-tick.ts +9 -0
  338. package/src/git-fs/watcher.ts +27 -22
  339. package/src/git-fs/worktree.ts +19 -3
  340. package/src/graph-runner/graph-grow.ts +37 -9
  341. package/src/graph-runner/runner.ts +17 -2
  342. package/src/grok/credential.ts +107 -36
  343. package/src/hq/fence-wrapper.ts +1 -1
  344. package/src/hq/transfer.ts +1 -1
  345. package/src/index.ts +44 -14
  346. package/src/intake-plane/collect-telegram-saved.ts +54 -5
  347. package/src/interactive-terminal-modal.ts +3 -0
  348. package/src/keybindings.ts +17 -22
  349. package/src/llm/provider-credentials.ts +1 -1
  350. package/src/llm-tool-schema.ts +20 -0
  351. package/src/llm.ts +81 -11
  352. package/src/loops/orchestrator/inbox-once.ts +28 -0
  353. package/src/loops/orchestrator/inbox.ts +130 -1
  354. package/src/loops/orchestrator/tick.ts +6 -3
  355. package/src/maturity/feature-maturity.ts +1 -0
  356. package/src/nexus/api/channel-ask-op.ts +96 -0
  357. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  358. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  359. package/src/nexus/api/terminals.ts +28 -6
  360. package/src/patents/ledger.ts +18 -1
  361. package/src/preview/terminal.ts +4 -2
  362. package/src/prompt-cache/anthropic.ts +2 -0
  363. package/src/prompt-enhance/enhance.ts +5 -0
  364. package/src/pty-shell/pty-manifest.ts +16 -2
  365. package/src/release-loop/gate-shards.ts +61 -0
  366. package/src/release-loop/light-rc.ts +7 -4
  367. package/src/release-loop/rehearsal.ts +1 -1
  368. package/src/repl/index.ts +10 -0
  369. package/src/research/axis-fanout.ts +133 -0
  370. package/src/research/edge-decision.ts +88 -0
  371. package/src/research/output-router.ts +127 -0
  372. package/src/research-bridge/format.ts +16 -1
  373. package/src/research-bridge/index.ts +1 -0
  374. package/src/research-bridge/invoke.ts +41 -5
  375. package/src/self-dev/decompose.ts +45 -9
  376. package/src/self-dev/draft-residue.ts +221 -2
  377. package/src/self-dev/draft-sweep.ts +29 -16
  378. package/src/self-dev/orchestrate.ts +1 -0
  379. package/src/self-dev/run-supervisor.ts +22 -7
  380. package/src/self-dev/shard-run.ts +260 -3
  381. package/src/self-implement/comment-only-source.ts +54 -0
  382. package/src/self-implement/doctor-visit.ts +25 -0
  383. package/src/self-implement/gate-artifacts.ts +2 -2
  384. package/src/self-implement/gate-baseline.ts +44 -9
  385. package/src/self-implement/gate-cli.ts +151 -86
  386. package/src/self-implement/gate-failure-signature.ts +44 -0
  387. package/src/self-implement/gate-remote.ts +2 -0
  388. package/src/self-implement/goal-author.ts +74 -3
  389. package/src/self-implement/goal-doc/section.ts +22 -0
  390. package/src/self-implement/goal-supervisor-fill.ts +38 -4
  391. package/src/self-implement/knowhow-pack.ts +120 -7
  392. package/src/self-implement/l8-merge-queue.ts +198 -32
  393. package/src/self-implement/off-diff-evidence.ts +23 -0
  394. package/src/self-implement/orchestrator.ts +55 -12
  395. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  396. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  397. package/src/self-implement/premise-review.ts +7 -5
  398. package/src/self-implement/run-ledger.ts +258 -0
  399. package/src/self-implement/seams.ts +33 -10
  400. package/src/self-implement/self-implement-cli.ts +26 -2
  401. package/src/session/channel-ask-op-envelope.ts +36 -0
  402. package/src/session/channel-op-reply-route.ts +200 -0
  403. package/src/session/chat.ts +3 -0
  404. package/src/session/index.ts +2 -0
  405. package/src/session-runtime/index.ts +9 -22
  406. package/src/skills/runner.ts +7 -3
  407. package/src/skills/tools/dev-harness.ts +2 -2
  408. package/src/skills/tools/schedule-wakeup.ts +1 -6
  409. package/src/status/bar.ts +3 -3
  410. package/src/storage/file-lock.ts +17 -4
  411. package/src/task-agent/adopt-pr.ts +63 -2
  412. package/src/task-agent/evidence-command-normalize.ts +42 -0
  413. package/src/task-agent/export-redactions-provision.ts +43 -0
  414. package/src/task-agent/parent-host.ts +59 -12
  415. package/src/task-agent/repair-cycle.ts +67 -8
  416. package/src/task-agent/repair-worker.ts +37 -1
  417. package/src/task-agent/task-hand.ts +98 -10
  418. package/src/task-agent/tier-split.ts +37 -3
  419. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
  420. package/src/task-orchestrator/surfaces/pod-pool.ts +27 -4
  421. package/src/task-orchestrator/surfaces/self-implement-pod.ts +126 -48
  422. package/src/task-orchestrator/surfaces/self-implement.ts +33 -2
  423. package/src/terminal/session-registry.ts +1 -0
  424. package/src/terminal/terminal-modal-router.ts +156 -0
  425. package/src/tool-hints/gate.ts +6 -4
  426. package/src/tool-hints/signals.ts +33 -1
  427. package/src/tui/chat/background-job-status.ts +8 -2
  428. package/src/tui/entry.ts +469 -31
  429. package/src/tui/sidetab/attach.ts +304 -0
  430. package/src/tui/sidetab/list.ts +176 -0
  431. package/src/tui/sidetab/nl-tool.ts +136 -0
  432. package/src/tui/slash/resume-command.ts +23 -0
  433. package/src/tui/slash/resume.ts +3 -23
  434. package/src/tui/slash/term-next.ts +2 -1
  435. package/src/tui-client/local-chat-turn.ts +29 -8
  436. package/src/user-config.ts +11 -2
  437. package/src/ux-sim/fake-llm.ts +11 -5
  438. package/src/ux-sim/next-tui-seat-scenarios.ts +53 -1
  439. package/src/version/packed-revision.json +1 -1
  440. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +0 -1
  441. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +0 -1
  442. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +0 -1
  443. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +0 -1
  444. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +0 -1
  445. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +0 -1
  446. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +0 -1
  447. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +0 -1
  448. package/apps/pwa/out/_next/static/chunks/1ed5e8af.cf424815c7c0efad.js +0 -1
  449. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +0 -1
  450. package/apps/pwa/out/_next/static/chunks/210.90b2cbd64926cf34.js +0 -32
  451. package/apps/pwa/out/_next/static/chunks/2318-450e75d07605b8fe.js +0 -1
  452. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +0 -148
  454. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +0 -1
  455. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +0 -27
  458. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/3578.4e9f9948a9a6f2f4.js +0 -2
  463. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +0 -36
  465. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +0 -1
  466. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +0 -226
  467. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +0 -287
  468. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/4313.76f232c304a15bde.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/4324.c99ba3e83eb1b691.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/4725-34bed25720cc326b.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/4833-7934c592c5569f00.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +0 -24
  477. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +0 -104
  479. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +0 -93
  486. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +0 -74
  487. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +0 -149
  490. package/apps/pwa/out/_next/static/chunks/6971-fb5f9dc0a2cb5d2d.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +0 -41
  493. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +0 -24
  496. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/7c5ed21f-f286708e57cf88f7.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +0 -8
  508. package/apps/pwa/out/_next/static/chunks/8080-40d781e7704d3671.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +0 -77
  510. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +0 -286
  513. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +0 -79
  517. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/9175-7d383df15a82e2be.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +0 -94
  525. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +0 -64
  527. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/live/page-3337c6a1328c2674.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/morning/page-1e5da297557d2354.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/outputs/page-443364c9e4a23b31.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/term/page-ac2c1e6169cfce57.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +0 -1
  586. package/scripts/migrate-monad-to-elanous.ts +0 -195
  587. package/scripts/rebrand-elanous.ts +0 -242
  588. /package/apps/pwa/out/_next/static/{8kITumG9GAZ1LwT9POrAR → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
@@ -33,6 +33,7 @@ import { mintRunId, normalizeRunId } from '../../harness/harness-space.js';
33
33
  import { TA_LAND_ENV } from '../../task-agent/task-hand.js';
34
34
  import { appendRunLedgerEntry, loadRunLedger, runLedgerDir, runLedgerPath, type RunLedgerEntry } from '../../self-implement/run-ledger.js';
35
35
  import { recordRunStop } from '../../self-implement/run-stop.js';
36
+ import { gateFailureReceipt, gateFailureReceiptLines } from '../../self-implement/gate-failure-signature.js';
36
37
  import { runSuffixKey } from '../../self-implement/salvage-branches.js';
37
38
  import type { GoalExecutionRecord } from '../../self-implement/orchestrator.js';
38
39
  import { hostRepositoryUnavailable, runHostRegate, type HostRegateResult } from '../../self-implement/host-regate.js';
@@ -86,20 +87,21 @@ import { enterJourneyNode, exitJourneyNode, passJourneyNode } from '../../self-d
86
87
  import { routeJourneyEdge } from '../../self-dev/graph-journey-route.js';
87
88
  import { selectLiveDetail } from '../../live/detail-switch.js';
88
89
  import { authStorePath } from '../../oauth/store.js';
89
- import { grokAuthFilePath, isGrokSubscriptionExpiring, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
90
+ import { grokAuthFilePath, isGrokSubscriptionExpiring, readSelectedGrokScope, refreshGrokSubscriptionToken, resolveGrokCredential, type GrokRefreshOutcome } from '../../grok/credential.js';
90
91
  import { defaultGrokModel } from '../../grok/models.js';
91
92
  import { resolveHostId } from '../../platform/host-id.js';
92
93
  import { BUDGET_SNAPSHOT_ENV, encodeBudgetSnapshot, harnessLaunchBudgetDecision, type BudgetSnapshot } from '../../execution-loop/launch-gate.js';
93
94
  import type { ReadBudgetInputsDeps } from '../../self-implement/budget-gate.js';
94
95
  import { envLiteral } from '../../platform/env-literal.js';
95
96
  import { LLM_TIER_MAP_BY_PROVIDER, lookupLlmTierSpec, type LlmTierProvider } from '../../model-tier/llm-tier-map.js';
96
- import { parseSelfImplementJson, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
97
+ import { parseSelfImplementJson, type SelfImplementDisposition, type SelfImplementJobDone, type SelfImplementJobSpawn } from './self-implement.js';
97
98
  import { codexQuotaPolicyFromConfig } from '../../oauth/codex-account-store.js';
98
99
  import { normalizeFallbackChain, type FallbackStep } from '../../oauth/fallback-chain.js';
99
100
  import { goalTypeOf, type GoalType } from '../../../scripts/measure-pod-memory-by-goal.js';
100
101
  import { declaredGoalType, type GoalType as DeclaredGoalType } from '../../self-implement/goal-author.js';
101
102
  import { readPodMemoryAdvice, type PodMemoryAdvice } from '../../cli/pod-memory-advice.js';
102
103
  import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, getUserConfig, roleLlmEnvName, type UserConfig } from '../../user-config.js';
104
+ import { worktreeAddTimeoutSec } from '../../git-fs/worktree.js';
103
105
  import { podChildProviderOf, podChildProviderRefusal, type PodChildProvider } from './pod-child-providers.js';
104
106
  import { BEDROCK_POD_EGRESS_LABEL, bedrockPodEnv, checkBedrockPodSecret, type BedrockPodSpec } from './pod-bedrock-child.js';
105
107
  import { resolveBedrockRegion, validBedrockRegion } from '../../llm/bedrock.js';
@@ -107,7 +109,7 @@ import { ZAI_POD_EGRESS_LABEL, checkZaiPodSecret, countActiveZaiJobs, decideZaiP
107
109
  import { ZAI_CODING_DEFAULT_MODEL, ZAI_OPENROUTER_FALLBACK_MODEL, zaiSettingsFromConfig, type ZaiCodingPlanSettings } from '../../llm/zai-coding-plan.js';
108
110
  import { normalizePlanningFallbackReason, selectEnhanceLlm } from '../../prompt-enhance/enhance.js';
109
111
  import { inferProviderFromModel } from '../../llm.js';
110
- import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
112
+ import { classifyPodExit, extractPodFailureReason, podChildFailureAttribution, podDeadlineResultMarker, podJobConditionReason, podTerminalRow, POD_TERMINATION_JOB_JSONPATH, POD_TERMINATION_PODS_JSONPATH, readPodTermination, type PodExitClass, type PodTermination } from './pod-failure-reason.js';
111
113
  import { kubectlTransientReason, retryKubectlTransient } from './kubectl-transient-retry.js';
112
114
  import { OLD_DOOR_STAMP_ENV } from '../../self-dev/old-door.js';
113
115
  import { resolveDefaultSourceHead, seedMirrorOnce, type MirrorSeedResult } from './pod-mirror-seed.js';
@@ -526,15 +528,6 @@ export function formatGrokRemaining(ms: number | null): string {
526
528
  return m >= 60 ? `${Math.floor(m / 60)}h${String(m % 60).padStart(2, '0')}m` : `${m}m`;
527
529
  }
528
530
 
529
- /** Latest `expires_at` among scopes that carry an access key (the token the Pod would get). */
530
- function grokSubscriptionExpiresAtMs(home?: string): number | null {
531
- try {
532
- const scopes = JSON.parse(readFileSync(grokAuthFilePath(home), 'utf8')) as Record<string, { key?: unknown; expires_at?: unknown }>;
533
- const all = Object.values(scopes).flatMap((s) => (s && typeof s.key === 'string' && s.key && typeof s.expires_at === 'string' && Number.isFinite(Date.parse(s.expires_at)) ? [Date.parse(s.expires_at)] : []));
534
- return all.length ? Math.max(...all) : null;
535
- } catch { return null; }
536
- }
537
-
538
531
  /** POD-GROK-VALIDITY-FIT — this launch's Job deadline for a refresh-less grok subscription copy.
539
532
  * · relay (the Pod can renew from the host) or unknown expiry → the requested deadline as is.
540
533
  * · otherwise → min(requested, remaining − margin); below the minimum Job (time passed since the credential check)
@@ -574,38 +567,46 @@ export function podGhLoginRetryBackoffMs(job: string): number {
574
567
  export function hostGrokCredentials(opts: {
575
568
  home?: string; env?: NodeJS.ProcessEnv; apiKeyOptIn?: boolean; ghToken?: () => string;
576
569
  /** Test seams — the host refresh (read-only `grok models`) and the expiry probe. */
577
- refresh?: () => void; isExpiring?: () => boolean;
570
+ refresh?: () => void; isExpiring?: () => boolean; grokPath?: string;
578
571
  /** Required remaining token life (default POD_GROK_MIN_VALIDITY_MS) — a caller whose Job is not fitted passes its own deadline. */
579
572
  minValidityMs?: number; now?: () => number;
580
573
  } = {}): { grokAuth?: string; grokApiKey?: string; ghToken: string } {
581
574
  let credential = resolveGrokCredential({ home: opts.home, env: opts.env });
582
575
  if (credential?.kind === 'subscription') {
576
+ const initialScope = readSelectedGrokScope(opts.home);
577
+ if (!initialScope) throw new Error('grok: 선택된 구독 scope 없음 — 발사를 거부');
583
578
  const minValidityMs = opts.minValidityMs ?? POD_GROK_MIN_VALIDITY_MS;
584
- const expiring = opts.isExpiring ?? (() => isGrokSubscriptionExpiring({ home: opts.home, bufferMs: minValidityMs, ...(opts.now ? { now: opts.now } : {}) }));
585
- if (expiring()) {
586
- try { (opts.refresh ?? (() => { refreshGrokSubscriptionToken({ home: opts.home }); }))(); } catch { /* judged below */ }
587
- if (expiring()) {
588
- const at = grokSubscriptionExpiresAtMs(opts.home);
589
- const remainingMs = at === null ? null : at - (opts.now ?? Date.now)();
590
- try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: at === null ? null : new Date(at).toISOString() }); } catch { /* fail-soft */ }
591
- throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
579
+ const clock = opts.now ?? Date.now;
580
+ const initialExpiry = initialScope.expiresAt ? Date.parse(initialScope.expiresAt) : NaN;
581
+ const expiring = opts.isExpiring ? opts.isExpiring()
582
+ : !Number.isFinite(initialExpiry) || initialExpiry - clock() < minValidityMs;
583
+ if (expiring) {
584
+ if (!initialScope.hasRefreshToken) {
585
+ throw new Error('grok: 선택된 구독 scope에 refresh token 없음 — 다른 계정으로 대체하지 않고 발사를 거부');
592
586
  }
593
- credential = resolveGrokCredential({ home: opts.home, env: opts.env });
594
- if (credential?.kind !== 'subscription') throw new Error('grok: 갱신 뒤 구독 자격을 다시 읽지 못했다');
587
+ try {
588
+ if (opts.refresh) opts.refresh();
589
+ else refreshGrokSubscriptionToken({ home: opts.home, requireRefreshToken: true,
590
+ requiredValidityMs: minValidityMs, nowMs: clock(), ...(opts.grokPath ? { grokPath: opts.grokPath } : {}) });
591
+ } catch { /* Final snapshot below is the launch decision. */ }
595
592
  }
596
- const scopes = JSON.parse(readFileSync(grokAuthFilePath(opts.home), 'utf8')) as Record<string, unknown>;
597
- const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {};
598
- for (const [name, value] of Object.entries(scopes)) {
599
- if (!value || typeof value !== 'object' || Array.isArray(value)) continue;
600
- const scope = value as Record<string, unknown>;
601
- if (scope.key !== credential.token) continue;
602
- redacted[name] = {
603
- key: scope.key,
604
- ...(typeof scope.expires_at === 'string' ? { expires_at: scope.expires_at } : {}),
605
- ...(typeof scope.user_id === 'string' ? { user_id: scope.user_id } : {}),
606
- };
593
+ const selected = readSelectedGrokScope(opts.home);
594
+ if (!selected || selected.scopeName !== initialScope.scopeName) {
595
+ throw new Error('grok: 자격 확인 중 선택된 구독 scope가 사라졌거나 바뀜 — 발사를 거부');
596
+ }
597
+ const selectedExpiry = selected.expiresAt ? Date.parse(selected.expiresAt) : NaN;
598
+ if (!Number.isFinite(selectedExpiry) || selectedExpiry - clock() < minValidityMs) {
599
+ const remainingMs = Number.isFinite(selectedExpiry) ? selectedExpiry - clock() : null;
600
+ try { debug.log('pod.grok-credentials', 'refused', { remainingMs, minValidityMs, expiresAt: selected.expiresAt }); } catch { /* fail-soft */ }
601
+ throw new Error(`grok: 구독 access 토큰 남은 시간 ${formatGrokRemaining(remainingMs)} < Pod 발사 기준 ${formatGrokRemaining(minValidityMs)} — 호스트 갱신(grok models)도 못 늘렸다 · 다음: 호스트에서 grok login --device-auth 후 다시`);
607
602
  }
608
- if (!Object.keys(redacted).length) throw new Error('grok: 구독 access 토큰 없음');
603
+ const redacted: Record<string, { key: string; expires_at?: string; user_id?: string }> = {
604
+ [selected.scopeName]: {
605
+ key: selected.key,
606
+ ...(selected.expiresAt ? { expires_at: selected.expiresAt } : {}),
607
+ ...(selected.userId ? { user_id: selected.userId } : {}),
608
+ },
609
+ };
609
610
  return { grokAuth: JSON.stringify(redacted), ghToken: (opts.ghToken ?? defaultGhToken)() };
610
611
  }
611
612
  if (credential?.kind === 'api_key' && opts.apiKeyOptIn === true) {
@@ -1192,6 +1193,29 @@ export function podSigtermTrapScript(seqFile: string = POD_USAGE_PARTIAL_SEQ_FIL
1192
1193
  return `trap '{ [ -n "$si_pid" ] && kill "$si_pid" 2>/dev/null || true; [ -n "\${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true; si_seq=$(cat ${seqFile} 2>/dev/null || true); case "$si_seq" in ""|*[!0-9]*) si_seq=0;; esac; si_seq=$((10#$si_seq + 1)); { [ -f scripts/usage-rollup.ts ] && bun scripts/usage-rollup.ts --since 12h --partial --seq "$si_seq"; } & si_rollup_pid=$!; for si_i in 1 2 3 4 5 6 7 8; do kill -0 "$si_rollup_pid" 2>/dev/null || break; sleep 1; done; kill "$si_rollup_pid" 2>/dev/null || true; wait "$si_rollup_pid" 2>/dev/null || true; exit 143; }' TERM`;
1193
1194
  }
1194
1195
 
1196
+ /** Leave enough time for the Pod wrapper to print its result and push a salvage branch before Kubernetes kills the Job. */
1197
+ export function podDeadlineWatchdogScript(input: { deadlineSeconds: number; job: string; runId?: string; prNumber?: number }): string {
1198
+ const leadSeconds = Math.max(1, Math.min(600, Math.floor(input.deadlineSeconds / 10)));
1199
+ const waitSeconds = Math.max(1, input.deadlineSeconds - leadSeconds);
1200
+ const job = /^[A-Za-z0-9_.:-]+$/.test(input.job) ? input.job : 'unknown-job';
1201
+ const runId = input.runId && /^[A-Za-z0-9_.:-]+$/.test(input.runId) ? input.runId : 'unknown-run';
1202
+ const pr = input.prNumber && Number.isSafeInteger(input.prNumber) && input.prNumber > 0 ? String(input.prNumber) : 'unknown';
1203
+ const jsonPr = pr === 'unknown' ? 'null' : pr;
1204
+ return `printf 'clone\\n' > /tmp/si.stage
1205
+ (sleep ${waitSeconds}; [ -f /tmp/si.finished ] && exit 0
1206
+ stage=$(cat /tmp/si.stage 2>/dev/null || true); case "$stage" in clone|setup|run) ;; *) stage=unknown;; esac
1207
+ branch=$(git -C repo branch --show-current 2>/dev/null || true); case "$branch" in ''|*[!A-Za-z0-9_./-]*) branch=unknown;; esac
1208
+ [ -f /tmp/si.finished ] && exit 0
1209
+ si_target=$(cat /tmp/si.pid 2>/dev/null || true)
1210
+ case "$si_target" in ''|*[!0-9]*) ;; *) kill -0 "$si_target" 2>/dev/null || exit 0;; esac
1211
+ printf 'ELANOUS_POD_DEADLINE_RESULT ${job} ${runId} stop-cause=deadline stage=%s pr=${pr} branch=%s\\n' "$stage" "$branch" | tee /tmp/si.deadline-marker
1212
+ printf '{"stage":"deadline","ok":false,"error":"Pod deadline preemption","stopCause":"deadline","prNumber":${jsonPr},"branch":"%s"}\\n' "$branch" > /tmp/si.deadline-result
1213
+ case "$si_target" in ''|*[!0-9]*) ;; *) kill -TERM "$si_target" 2>/dev/null || true;; esac
1214
+ ) & si_deadline_watch_pid=$!`;
1215
+ }
1216
+
1217
+ 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
+
1195
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> {
1196
1220
  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'))) {
1197
1221
  throw new Error('repair commit-only requires matching PR source and no PR/merge flags');
@@ -1252,9 +1276,11 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1252
1276
  // SI-POD-STAGE-MARKERS — Pod 시계 단계 표지(`ELANOUS_POD_STAGE <stage> <start|end> <epoch초>`): 호스트가 Job 로그에서 읽어
1253
1277
  // pod.lifecycle stages 의 clone · mirror · run 을 채운다. 실패한 단계는 끝 표지가 없다(→ missing · 지어내지 않는다).
1254
1278
  // clone 끝 = podSourceScript 전체가 끝난 뒤(갈래마다 마지막 줄이 `ELANOUS_POD_SOURCE` 또는 `cd repo` — 둘 다 소스 받기의 일부).
1279
+ podDeadlineWatchdogScript({ deadlineSeconds: o.deadlineSeconds, job: o.name, runId: o.runId, prNumber: o.boundPrNumber }),
1255
1280
  siTaskPodStageShell('clone', 'start'),
1256
1281
  podSourceScript(o.source ?? { kind: 'default' }, o.repoUrl, undefined, { stageMarkers: true }),
1257
1282
  siTaskPodStageShell('clone', 'end'),
1283
+ `printf 'setup\\n' > /tmp/si.stage`,
1258
1284
  // This image already contains runtime dependencies; there is no child install command.
1259
1285
  // Record that fact before the main command, without treating clone completion as install completion.
1260
1286
  `printf 'ELANOUS_POD_DEPS skipped %s image-prepared-no-install\\n' "$(date +%s)" || true`,
@@ -1278,14 +1304,15 @@ export function podJobManifest(o: { name: string; namespace: string; image: stri
1278
1304
  // 마지막 줄 JSON 이 «맨 끝»이어야 한다(parseSelfImplementJson) — rollup 은 그 앞에.
1279
1305
  // ⛔ `--author-grade` 는 Pod 안 `elanous`(이미지에 깔린 판)가 모를 수 있어 넘기지 않는다 — 10-06 «unknown option» 즉사(#24445 되돌림).
1280
1306
  // AUTHOR-LITE2-POD — 등급은 환경변수 `ELANOUS_AUTHOR_GRADE` 로 싣는다(옛 Pod elanous 는 모르는 환경변수를 무시하고 full 로 돈다).
1307
+ `printf 'run\\n' > /tmp/si.stage`,
1281
1308
  siTaskPodStageShell('run', 'start'),
1282
1309
  o.repairCommitOnly
1283
- ? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi`
1310
+ ? `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json --no-open-pr ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; if elanous self repair-commit-export '${o.repairCommitOnly.pr}' '${o.repairCommitOnly.baseHead}' /tmp/si.out "$PWD" "$HOME/outbox"; then rc=0; elif [ "$rc" -eq 0 ]; then rc=8; fi; ${POD_DEADLINE_AFTER_WAIT}`
1284
1311
  : o.authorSentence
1285
- ? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
1312
+ ? `echo "ELANOUS_AUTHOR_ON_POD started host=$(hostname) at=$(date -u +%Y-%m-%dT%H:%M:%SZ)"; author_t0=$(date +%s); ${o.authorGrade === 'lite' || o.authorGrade === 'full' ? `ELANOUS_AUTHOR_GRADE=${o.authorGrade} ` : ''}elanous harness say --substrate local --json${quotedAsk}${quotedChildLlm} -- "$(cat /creds/feature)" > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; echo "ELANOUS_AUTHOR_ON_POD finished host=$(hostname) rc=$rc seconds=$(( $(date +%s) - author_t0 ))"; ${POD_RESULT_FLATTEN}`
1286
1313
  : goalPath
1287
- ? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`
1288
- : `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; wait "$si_pid"; rc=$?; ${RUN_END}; ${POD_RESULT_FLATTEN}`,
1314
+ ? `elanous harness ask ${goalPath} --json${quotedAsk}${quotedChildLlm} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`
1315
+ : `export ${OLD_DOOR_STAMP_ENV}=self-implement; elanous self implement "$(cat /creds/feature)" --json ${quoted} > /tmp/si.out 2>&1 & si_pid=$!; printf '%s\\n' "$si_pid" > /tmp/si.pid; wait "$si_pid"; rc=$?; touch /tmp/si.finished; ${RUN_END}; rm -f /tmp/si.pid; ${POD_DEADLINE_AFTER_WAIT}; ${POD_RESULT_FLATTEN}`,
1289
1316
  'cat /tmp/si.out',
1290
1317
  ...(o.appCredential && !o.repairCommitOnly ? ['kill "$gh_watch_pid" 2>/dev/null || true'] : []),
1291
1318
  ...(o.repairCommitOnly ? [] : [podSalvageScript()]),
@@ -1352,7 +1379,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1352
1379
  '[ -n "${usage_partial_pid:-}" ] && kill "$usage_partial_pid" 2>/dev/null || true',
1353
1380
  'wait "$mem_sampler_pid" 2>/dev/null || true',
1354
1381
  '[ -n "${usage_partial_pid:-}" ] && wait "$usage_partial_pid" 2>/dev/null || true',
1382
+ 'if [ "$rc" -ne 0 ] && [ -f /tmp/si.deadline-result ]; then rc=124; fi',
1355
1383
  'tail -n 1 /tmp/si.out',
1384
+ 'touch /tmp/si.finished; kill "$si_deadline_watch_pid" 2>/dev/null || true; [ -f /tmp/si.deadline-marker ] && cat /tmp/si.deadline-marker || true',
1356
1385
  // TA-POD-WARMBOOT-PARITY: the last line says «the child is done» so the host need not wait for the Job condition.
1357
1386
  ...(o.resultMarkerLine ? [o.resultMarkerLine] : []),
1358
1387
  'exit $rc',
@@ -1388,6 +1417,9 @@ if [ "$found" -eq 0 ]; then echo ELANOUS_RUN_LEDGER_NONE; fi`,
1388
1417
  ? [{ name: 'ELANOUS_TASK_BOUND_PR', value: String(o.boundPrNumber) }] : []),
1389
1418
  ...(o.workIdentity?.slotId ? [{ name: 'ELANOUS_POD_SLOT_ID', value: o.workIdentity.slotId }] : []),
1390
1419
  { name: 'ELANOUS_SUBSTRATE', value: 'pod' },
1420
+ // POD-INPLACE-WORKTREE: explicit host opt-in only; one Job runs one implementation child.
1421
+ { name: 'ELANOUS_POD_SINGLE_CHILD', value: '1' },
1422
+ { name: 'ELANOUS_POD_INPLACE_WORKTREE', value: process.env.ELANOUS_POD_INPLACE_WORKTREE === '1' ? '1' : '0' },
1391
1423
  ...Object.entries(controlInboxEnv(POD_CONTROL_INBOX_DIR)).map(([name, value]) => ({ name, value })),
1392
1424
  // ⭐ 런 출처(🅣 RFC run-origin §A3 · #20457/#20468 칸 이름) — Pod 는 자기 elanous_id 를 쓰지 않고 «띄운 감독기»의 hostId 를 물려받는다.
1393
1425
  { name: 'ELANOUS_POD_NAME', valueFrom: { fieldRef: { fieldPath: 'metadata.name' } } },
@@ -2501,7 +2533,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2501
2533
  ? Object.fromEntries(codexCredentials.map((candidate, i) => [`codex-${i}.json`, JSON.stringify({ elanousAuth: candidate.elanousAuth, codexAuth: candidate.codexAuth })]))
2502
2534
  : { 'elanous-auth.json': (creds as ReturnType<typeof hostCredentials>).elanousAuth, 'codex-auth.json': (creds as ReturnType<typeof hostCredentials>).codexAuth }),
2503
2535
  'gh-token': podGhToken, feature: input.feature,
2504
- 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps, zaiCodingPlan: { overage: zaiOverage } } }),
2536
+ 'llm-fallback-config.json': JSON.stringify({ llm: { fallbackChain: fallbackChain.steps, zaiCodingPlan: { overage: zaiOverage } }, harness: { worktreeAddTimeoutSec: worktreeAddTimeoutSec(hostConfig.harness?.worktreeAddTimeoutSec) ?? 1200 } }),
2505
2537
  ...(goalDocument !== undefined ? { 'goal-doc': goalDocument } : {}),
2506
2538
  ...Object.fromEntries(Object.entries(skillEnvs).map(([n, text]) => [`skillenv-${n}`, text])),
2507
2539
  ...(grounding ? { [`env-${GROUNDING_TOKEN_ENV}`]: grounding.token } : {}),
@@ -2864,6 +2896,29 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2864
2896
  // JOB-FAILURE-TERMINATION-CAPTURE — this Job's Kubernetes facts, read once at the failure verdict (before GC).
2865
2897
  // Observation only: failedReason · containerReason · containerExitCode keep driving the classification.
2866
2898
  let podTermination: PodTermination | null = null;
2899
+ const refreshPodTermination = async (): Promise<void> => {
2900
+ if (state !== 'failed' || !podTermination || (podTermination.podLookup === 'terminated'
2901
+ && podTermination.containerReason !== 'unknown' && podTermination.exitCode !== 'unknown'
2902
+ && podTermination.finishedAt !== 'unknown')) return;
2903
+ // The result marker and the Job Failed condition can precede container termination status.
2904
+ // Re-read this launch's Pod once; keep the verdict's Job facts even if the Job has since been GC'd.
2905
+ await sleep(1_000);
2906
+ const retry = readPodTermination({ kubectl, namespace, job: name, path: podTermination.path,
2907
+ jobUid: lifecycleJobUid, jobRead: null });
2908
+ const observed = retry.podLookup === 'unavailable' ? podTermination : retry;
2909
+ const complete = observed.podLookup === 'terminated' && observed.containerReason !== 'unknown'
2910
+ && observed.exitCode !== 'unknown' && observed.finishedAt !== 'unknown';
2911
+ const collectionFailureReason: PodTermination['collectionFailureReason'] | undefined = complete ? undefined
2912
+ : retry.podLookup === 'unavailable' ? 'pod-read-unavailable-after-retry'
2913
+ : retry.podLookup === 'absent' ? 'pod-absent-after-retry'
2914
+ : retry.podLookup === 'running' || retry.podLookup === 'pending' ? 'pod-still-running-after-retry'
2915
+ : retry.podLookup === 'terminated' ? 'terminated-fields-missing-after-retry'
2916
+ : 'pod-state-unknown-after-retry';
2917
+ podTermination = { ...podTermination, observedAt: retry.observedAt,
2918
+ podLookup: observed.podLookup, containerReason: observed.containerReason, exitCode: observed.exitCode,
2919
+ finishedAt: observed.finishedAt, oomKilled: observed.oomKilled, collectionAttempts: 2,
2920
+ ...(collectionFailureReason ? { collectionFailureReason } : {}) };
2921
+ };
2867
2922
  // METER-POD-ROLLUP-GAP — abort 때 Job 삭제 «전»에 거둔 로그 사본(삭제 뒤엔 PARTIAL 줄도 못 읽는다).
2868
2923
  let abortLogs = '';
2869
2924
  // ⭐ 런 «도중» 원장 증분 회수 — 호스트 슈퍼바이저가 Pod 걸음을 실시간으로 본다(🅣 요청 · 힐 루프 runtime 성형의 전제).
@@ -2950,7 +3005,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2950
3005
  let jobReadError: unknown;
2951
3006
  try { jobRead = kubectl(['-n', namespace, 'get', 'job', name, '-o', `jsonpath=${POD_TERMINATION_JOB_JSONPATH}`]); }
2952
3007
  catch (error) { jobReadError = error; }
2953
- failedReason = jobRead?.status === 0 ? (jobRead.stdout.split('\t')[0] ?? '').trim() : '';
3008
+ const observedJobReason = jobRead?.status === 0 ? podJobConditionReason(jobRead.stdout.split('\t')[0]) : 'unknown';
3009
+ failedReason = observedJobReason === 'unknown' ? '' : observedJobReason;
2954
3010
  // One Pods read serves both: its first three columns are the classification layout, the rest the termination capture.
2955
3011
  let podsRead: { status: number | null; stdout: string } | null = null;
2956
3012
  try {
@@ -2973,6 +3029,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
2973
3029
  captureFailedJob(liveChildRunId);
2974
3030
  if (jobReadError !== undefined) {
2975
3031
  // Today's outcome stays (the throw ends the spawn as pod-error); the capture is in the ledger first.
3032
+ await refreshPodTermination();
2976
3033
  try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-child-evidence', data: { childEvidence: null, childRunId: liveChildRunId, job: name, podTermination } }, ledgerDir); }
2977
3034
  catch (error) { debug.log('self-implement.pod', 'child-evidence-write-failed', { job: name, childRunId: liveChildRunId, reason: error instanceof Error ? error.message : String(error) }, { level: 'warn' }); }
2978
3035
  debug.log('self-implement.pod', 'pod-termination-captured', { job: name, podTermination, jobReadThrew: true }, { level: 'warn' });
@@ -3045,6 +3102,7 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3045
3102
  }
3046
3103
  await sleep(options.pollMs ?? 15_000);
3047
3104
  }
3105
+ await refreshPodTermination();
3048
3106
  if (!terminalImageRecorded) recordPodImage(true);
3049
3107
  let logs = '';
3050
3108
  let logTailReason: string | undefined;
@@ -3058,6 +3116,14 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3058
3116
  if (!logs && abortLogs) logs = abortLogs;
3059
3117
  // TA-POD-WARMBOOT-PARITY: the marker line is not child output — remove it so the last-line result parse sees the same bytes.
3060
3118
  if (markerWait && markerToken && logs) logs = markerWait.stripPodResultMarker(logs, markerToken);
3119
+ const deadlineMarker = podDeadlineResultMarker(logs, name, liveChildRunId);
3120
+ if (deadlineMarker && state !== 'aborted' && state !== 'complete') {
3121
+ state = 'failed';
3122
+ failedReason = 'DeadlineExceeded';
3123
+ debug.log('self-implement.pod', 'deadline-result-marker', { job: name, childRunId: liveChildRunId, ...deadlineMarker });
3124
+ try { appendRunLedgerEntry({ runId: ledgerRunId, event: 'pod-deadline-result', data: { job: name, childRunId: liveChildRunId, stopCause: 'deadline', ...deadlineMarker } }, ledgerDir); }
3125
+ catch { /* A full ledger must not hide the Pod's terminal marker. */ }
3126
+ }
3061
3127
  let ledgerReason = '';
3062
3128
  let ledgerCollected = false;
3063
3129
  const collection = collectFullLogs('ledger-collect-incomplete', follower.owned ? new Set([liveChildRunId]) : undefined, (event, data) => {
@@ -3117,7 +3183,9 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3117
3183
  continue;
3118
3184
  }
3119
3185
  // Pod 안 경로는 호스트에서 쓸 수 없다.
3120
- let disposition = parsed ? { ...parsed, worktreePath: undefined } : undefined;
3186
+ let disposition: SelfImplementDisposition | undefined = parsed ? { ...parsed, worktreePath: undefined } : deadlineMarker
3187
+ ? { stage: 'deadline', ok: false, ...(deadlineMarker.pr ? { prNumber: deadlineMarker.pr } : {}), ...(deadlineMarker.branch ? { branch: deadlineMarker.branch } : {}) }
3188
+ : undefined;
3121
3189
  if (options.repairCommitOnly && state === 'complete' && !repairArtifactReady) {
3122
3190
  disposition = { ...disposition, worktreePath: undefined, ok: false, stage: 'repair-artifact-missing', detail: 'Pod repair result or bundle was not collected' };
3123
3191
  }
@@ -3261,8 +3329,8 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3261
3329
  // the terminal result line can be followed by the useful stderr that explains the actual exit.
3262
3330
  let noResultLogEvidence: Record<string, unknown> | null = null;
3263
3331
  const shouldCaptureFailureLog = state === 'failed' && !oomKilled && failedReason !== 'DeadlineExceeded';
3264
- if (shouldCaptureFailureLog || noResultDiagnostic?.includes('stage=unknown')) {
3265
- const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
3332
+ const missingStage = noResultDiagnostic?.includes('stage=unknown') ?? false;
3333
+ if (shouldCaptureFailureLog || missingStage) {
3266
3334
  const logRead = readPodNoResultLogTail({ run: kubectl, namespace, job: name, maxLines: POD_NO_RESULT_LOG_TAIL_LINES });
3267
3335
  if ('tail' in logRead) {
3268
3336
  noResultLogEvidence = missingStage
@@ -3272,11 +3340,13 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3272
3340
  job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, lines: logRead.tail.length, logTail: logRead.tail,
3273
3341
  }, { compact: { stringMax: 500 } });
3274
3342
  } else {
3343
+ const unavailable = `log-unavailable: ${logRead.unavailable}`;
3275
3344
  noResultLogEvidence = missingStage
3276
- ? { stderr: `log-unavailable: ${logRead.unavailable}` }
3345
+ ? { stderr: unavailable }
3277
3346
  : { podLogUnavailable: logRead.unavailable };
3278
3347
  debug.log('self-implement.pod', missingStage ? 'no-result-log-tail' : 'failed-pod-log-tail', {
3279
- job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic, logUnavailable: logRead.unavailable,
3348
+ job: name, childRunId: liveChildRunId, diagnostic: noResultDiagnostic,
3349
+ logUnavailable: missingStage ? unavailable : logRead.unavailable,
3280
3350
  }, { level: 'warn' });
3281
3351
  }
3282
3352
  }
@@ -3455,6 +3525,12 @@ export function podSelfImplementSpawn(options: PodSpawnOptions = {}): SelfImplem
3455
3525
  const salvageOutcome = /^ELANOUS_POD_SALVAGE \S+ \S+$/m.test(logs) ? 'pushed' : logs.includes('ELANOUS_POD_SALVAGE_NONE') ? 'none' : 'unknown';
3456
3526
  passJourneyNode('salvage', { provenance: 'self-implement-pod', outcome: salvageOutcome, data: { job: name } });
3457
3527
  }
3528
+ const repairGateReceipt = disposition?.stage === 'gate-failed' ? gateFailureReceipt(disposition.gate) : null;
3529
+ if (repairGateReceipt) {
3530
+ for (const line of gateFailureReceiptLines(repairGateReceipt)) console.log(line);
3531
+ debug.log('self-implement.pod', 'gate-failure-receipt', { job: name, childRunId: liveChildRunId,
3532
+ signature: repairGateReceipt.signature, tests: repairGateReceipt.tests });
3533
+ }
3458
3534
  return {
3459
3535
  exitCode: podExitCode,
3460
3536
  output: tail,
@@ -3610,7 +3686,9 @@ export function podNoResultLogTailLines(source: string, maxLines: number = POD_N
3610
3686
  let chars = 0;
3611
3687
  for (const line of lines.slice(-Math.max(0, maxLines)).reverse()) {
3612
3688
  if (chars >= POD_NO_RESULT_LOG_TAIL_MAX_CHARS) break;
3613
- const bounded = boundedPodLogText(line, Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars));
3689
+ const redacted = redactSecretText(line);
3690
+ const limit = Math.min(POD_NO_RESULT_LOG_TAIL_LINE_CHARS, POD_NO_RESULT_LOG_TAIL_MAX_CHARS - chars);
3691
+ const bounded = redacted.length > limit ? `${redacted.slice(0, limit)}…[truncated]` : redacted;
3614
3692
  if (!bounded) continue;
3615
3693
  result.push(bounded);
3616
3694
  chars += bounded.length;
@@ -3632,7 +3710,7 @@ export function readPodNoResultLogTail(args: {
3632
3710
  }): PodNoResultLogRead {
3633
3711
  const maxLines = args.maxLines ?? POD_NO_RESULT_LOG_TAIL_LINES;
3634
3712
  try {
3635
- const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, `--tail=${maxLines}`]);
3713
+ const result = args.run(['-n', args.namespace, 'logs', `job/${args.job}`, '-c', 'child', `--tail=${maxLines}`]);
3636
3714
  if (result.status !== 0) {
3637
3715
  const reason = boundedPodLogText(result.stderr || result.stdout || '', POD_NO_RESULT_LOG_REASON_MAX_CHARS);
3638
3716
  return { unavailable: reason || `kubectl logs exit ${result.status}` };
@@ -19,7 +19,8 @@
19
19
  * Cf. PLAN-parallel-self-dev-orchestrator-2026-07-21.
20
20
  */
21
21
  import { lstatSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
22
- import type { ReviewRework } from '../../self-dev/run-types.js';
22
+ import type { ReviewRework, SelfDevJobResult } from '../../self-dev/run-types.js';
23
+ import type { SelfImplementGateResult } from '../../self-implement/orchestrator.js';
23
24
  import type { WarmWorkerCommand } from './pod-warm-worker-protocol.js';
24
25
  import { oldDoorInternalEnv } from '../../self-dev/old-door.js';
25
26
  import { selfDevRunsDir } from '../../self-dev/run-store.js';
@@ -52,11 +53,15 @@ export interface SelfImplementJobDone {
52
53
  export interface SelfImplementDisposition {
53
54
  stage?: string;
54
55
  ok?: boolean;
56
+ /** Measured child gate receipt, forwarded only for a failed gate. */
57
+ gate?: SelfImplementGateResult;
55
58
  worktreePath?: string;
56
59
  branch?: string;
57
60
  harvestable?: true;
58
61
  prUrl?: string;
59
62
  prNumber?: number;
63
+ /** Parent-side observation carried from the child's run ledger when available. */
64
+ goalPlanRevision?: SelfDevJobResult['goalPlanRevision'];
60
65
  /** Head SHA checked by the Pod before host regate. */
61
66
  checkedHeadCommit?: string;
62
67
  /** Review verdict only when the child bound a real pass to a clean, unchanged worktree head. */
@@ -99,6 +104,21 @@ export interface SelfImplementDisposition {
99
104
  childEvidence?: PodChildEvidence;
100
105
  }
101
106
 
107
+ function isGoalPlanRevisionObservation(value: unknown): value is NonNullable<SelfDevJobResult['goalPlanRevision']> {
108
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return false;
109
+ const row = value as Record<string, unknown>;
110
+ if (row.status === 'read') {
111
+ return Number.isSafeInteger(row.attempted) && Number(row.attempted) >= 0
112
+ && Number.isSafeInteger(row.applied) && Number(row.applied) >= 0
113
+ && Array.isArray(row.failureReasons) && row.failureReasons.every((reason) => typeof reason === 'string');
114
+ }
115
+ return row.status === 'read-failed'
116
+ && ['directory-missing', 'unreadable-directory', 'unreadable-files'].includes(String(row.reason))
117
+ && Number.isSafeInteger(row.scannedFiles) && Number(row.scannedFiles) >= 0
118
+ && Number.isSafeInteger(row.unreadableFiles) && Number(row.unreadableFiles) >= 0
119
+ && typeof row.ledgerDirectory === 'string';
120
+ }
121
+
102
122
  export interface PodChildEvidence {
103
123
  /** Bounded, redacted diagnostics copied only from a failed child terminal result. */
104
124
  error?: string;
@@ -130,6 +150,10 @@ export interface PodChildEvidence {
130
150
  candidateCardId?: string;
131
151
  blockingCardId?: string;
132
152
  };
153
+ /** Harvest pointer and revision observation copied before the parent Pod stop is finalized. */
154
+ harvestable?: true;
155
+ prNumber?: number;
156
+ goalPlanRevision?: SelfDevJobResult['goalPlanRevision'];
133
157
  }
134
158
 
135
159
  const SCOPE_STOP_REASON_ORDER: readonly ScopeStopReason[] = SCOPE_STOP_REASONS;
@@ -208,6 +232,9 @@ export function podChildEvidenceFromResult(o: Record<string, unknown>): PodChild
208
232
  ...(o.goalCauseObserved === true ? { goalCauseObserved: true } : {}),
209
233
  ...(o.terminationReason !== undefined ? { terminationReason: scrubValue(o.terminationReason) } : {}),
210
234
  ...(accountAvailability ? { accountAvailability } : {}),
235
+ ...(o.harvestable === true && typeof o.branch === 'string' && o.branch.trim() ? { harvestable: true } : {}),
236
+ ...(typeof o.prNumber === 'number' && Number.isSafeInteger(o.prNumber) && o.prNumber > 0 ? { prNumber: o.prNumber } : {}),
237
+ ...(isGoalPlanRevisionObservation(o.goalPlanRevision) ? { goalPlanRevision: o.goalPlanRevision } : {}),
211
238
  };
212
239
  if (o.ok === false && typeof o.error === 'string'
213
240
  && /draft PR 생성 실패|PR (?:gh|guard) 실패|same-cell reuse:/u.test(o.error)) {
@@ -625,11 +652,15 @@ export function parseSelfImplementJson(stdout: string): SelfImplementDisposition
625
652
  const mapped: SelfImplementDisposition = {
626
653
  ...(typeof o.stage === 'string' ? { stage: o.stage } : {}),
627
654
  ...(typeof o.ok === 'boolean' ? { ok: o.ok } : {}),
655
+ ...(o.stage === 'gate-failed' && o.ok === false && o.gate && typeof o.gate === 'object'
656
+ && !Array.isArray(o.gate) && (o.gate as { passed?: unknown }).passed === false
657
+ ? { gate: o.gate as SelfImplementGateResult } : {}),
628
658
  ...(typeof o.worktreePath === 'string' ? { worktreePath: o.worktreePath } : {}),
629
659
  ...(typeof o.branch === 'string' ? { branch: o.branch } : {}),
630
660
  ...(o.harvestable === true && typeof o.branch === 'string' && o.branch.trim() ? { harvestable: true } : {}),
631
661
  ...(typeof o.prUrl === 'string' ? { prUrl: o.prUrl } : {}),
632
- ...(typeof o.prNumber === 'number' ? { prNumber: o.prNumber } : {}),
662
+ ...(Number.isSafeInteger(o.prNumber) && Number(o.prNumber) > 0 ? { prNumber: Number(o.prNumber) } : {}),
663
+ ...(isGoalPlanRevisionObservation(o.goalPlanRevision) ? { goalPlanRevision: o.goalPlanRevision } : {}),
633
664
  ...(typeof o.checkedHeadCommit === 'string' ? { checkedHeadCommit: o.checkedHeadCommit } : {}),
634
665
  ...(o.reviewedHeadCommit && typeof o.reviewedHeadCommit === 'string' && /^[0-9a-f]{40}$/i.test(o.reviewedHeadCommit)
635
666
  && o.review && typeof o.review === 'object' && !Array.isArray(o.review)
@@ -157,6 +157,7 @@ export class TerminalSessionRegistry {
157
157
  shell: spec.shell,
158
158
  shellArgs: spec.shellArgs,
159
159
  env: spec.env,
160
+ unsetEnv: spec.unsetEnv,
160
161
  termName: spec.termName,
161
162
  useRegistry: spec.useRegistry,
162
163
  registryKind: spec.registryKind,
@@ -0,0 +1,156 @@
1
+ // Shared key routing for interactive terminal modals in dashboard and TUI.
2
+ //
3
+ // Holds singleton state for "which interactive terminal modal is
4
+ // currently foregrounded" + the key-intercept policy:
5
+ //
6
+ // • while a modal is present, ESC / Ctrl-G dispose it
7
+ // • all other keys forward to modal.surface.onKey(ev) so the PTY
8
+ // receives them without the chat readKey loop trying to
9
+ // interpret them
10
+ //
11
+ // Kept separate from either renderer so both can use the same routing policy.
12
+ //
13
+ // P10 will extend this with Ctrl-B prefix handling (d=detach,
14
+ // s=switch, etc.) once a session registry exists to act on.
15
+
16
+ import type { InteractiveTerminalModalHandle } from '../interactive-terminal-modal.js';
17
+ import type { KeyEvent } from '../display/types.js';
18
+ import { debug } from '../debug/log.js';
19
+
20
+ export type KeyRouteResult = 'consumed' | 'passthrough' | 'closed';
21
+
22
+ export interface TerminalModalRouter {
23
+ current(): InteractiveTerminalModalHandle | null;
24
+ /** Install a modal handle. Optional closePolicy controls what
25
+ * ESC/Ctrl-G does: 'kill' disposes the modal + PTY (default);
26
+ * 'detach' calls handle.dispose({keepPreview:true}) so the PTY
27
+ * survives for re-attach (session registry flow). An explicit
28
+ * onClose hook wins over closePolicy — that's how dashboard
29
+ * wires the owning session registry's detach action on Esc. */
30
+ set(
31
+ handle: InteractiveTerminalModalHandle | null,
32
+ opts?: { closePolicy?: 'kill' | 'detach'; onClose?: () => void },
33
+ ): void;
34
+ close(): void;
35
+ handleKey(ev: KeyEvent): KeyRouteResult;
36
+ }
37
+
38
+ // `exit` typed cleanly + Enter closes the popup. claude / codex don't
39
+ // recognize plain `exit` (their command is /exit or /quit), so a user
40
+ // typing `exit\n` would otherwise be stuck — the popup stays open
41
+ // because the child never exits, and the typed text just becomes chat
42
+ // input. elanous intercepts the exact sequence at the router so:
43
+ // • plain shell: same end result (we close before shell evaluates)
44
+ // • claude / codex: popup closes as the user expected
45
+ // Sequence is reset on any non-letter key (other than backspace, which
46
+ // rewinds), Ctrl/Alt modifiers, or any character outside `e/x/i/t` —
47
+ // so genuine words containing "exit" (e.g. typing "exit this loop"
48
+ // into a claude prompt without Enter) DON'T trigger the close. The
49
+ // trigger is specifically `e`, `x`, `i`, `t`, Enter with nothing else.
50
+ const EXIT_CHARS = ['e', 'x', 'i', 't'] as const;
51
+
52
+ export function createTerminalModalRouter(): TerminalModalRouter {
53
+ let handle: InteractiveTerminalModalHandle | null = null;
54
+ let closePolicy: 'kill' | 'detach' = 'kill';
55
+ let onClose: (() => void) | null = null;
56
+ let exitProgress = 0; // how many of EXIT_CHARS have been typed in order
57
+
58
+ const close = (): void => {
59
+ if (!handle) return;
60
+ const h = handle;
61
+ const cb = onClose;
62
+ if (debug.enabled) debug.log('window.terminalModalRouter.close', h.id, { id: h.id, closePolicy, hasOnClose: !!cb });
63
+ handle = null;
64
+ onClose = null;
65
+ exitProgress = 0;
66
+ try {
67
+ if (cb) cb();
68
+ else if (closePolicy === 'detach') h.dispose({ keepPreview: true });
69
+ else h.dispose();
70
+ } catch { /* already disposed */ }
71
+ closePolicy = 'kill';
72
+ };
73
+
74
+ return {
75
+ current: () => handle,
76
+ set: (h, opts) => {
77
+ if (handle && h && handle.id !== h.id) close();
78
+ handle = h;
79
+ closePolicy = opts?.closePolicy ?? 'kill';
80
+ onClose = opts?.onClose ?? null;
81
+ exitProgress = 0;
82
+ if (debug.enabled) {
83
+ debug.log('window.terminalModalRouter.set', h?.id ?? '(null)', {
84
+ id: h?.id ?? null,
85
+ closePolicy,
86
+ hasOnClose: !!onClose,
87
+ });
88
+ }
89
+ },
90
+ close,
91
+ handleKey: (ev) => {
92
+ if (!handle) return 'passthrough';
93
+ const name = (ev.name ?? '').toLowerCase();
94
+ // ESC must NOT close the modal — claude / codex inside the popup
95
+ // use ESC to cancel an in-progress chat / tool turn. Closing the
96
+ // wrapper window on ESC made the only-way-to-cancel kill the
97
+ // whole popup. iTerm / ghostty don't close their own windows on
98
+ // ESC either; the wrapper should match. Modal close is reserved
99
+ // for: Ctrl+G (close + focus log), Ctrl+Shift+T (toggle off),
100
+ // typed `exit\n`, and the child's own `exit`. ESC just forwards.
101
+ if (ev.ctrl && (name === 'g' || name === 'ㅎ')) {
102
+ if (debug.enabled) debug.log('window.terminalModalRouter.handleKey.close', 'ctrl-g', { id: handle.id });
103
+ close();
104
+ return 'closed';
105
+ }
106
+
107
+ // Track typed `exit` followed by Enter so the user's natural
108
+ // mental model ("type exit to quit") works inside agent popups
109
+ // (claude / codex) where the child app doesn't recognize a bare
110
+ // `exit` command. See EXIT_CHARS comment above for false-positive
111
+ // avoidance.
112
+ const noMods = !ev.ctrl && !ev.alt;
113
+ if (noMods && name === 'enter' && exitProgress === EXIT_CHARS.length) {
114
+ if (debug.enabled) {
115
+ debug.log('window.terminalModalRouter.handleKey.close', 'typed-exit', {
116
+ id: handle.id,
117
+ });
118
+ }
119
+ close();
120
+ return 'closed';
121
+ }
122
+ if (noMods && name === 'backspace') {
123
+ if (exitProgress > 0) exitProgress--;
124
+ } else if (noMods && name.length === 1 && exitProgress < EXIT_CHARS.length && name === EXIT_CHARS[exitProgress]) {
125
+ exitProgress++;
126
+ } else if (noMods && name === 'enter') {
127
+ // Enter without a complete `exit` prefix — reset and forward.
128
+ exitProgress = 0;
129
+ } else if (name.length === 1 || name === 'space' || ev.ctrl || ev.alt) {
130
+ // Any other printable key OR a modifier keystroke breaks the
131
+ // streak. Multi-char named keys (arrow / fn / etc.) leave the
132
+ // streak alone — the child may consume them without affecting
133
+ // the user's typed prompt buffer.
134
+ exitProgress = 0;
135
+ }
136
+
137
+ if (debug.enabled) {
138
+ debug.log('window.terminalModalRouter.handleKey.forward', name || '(empty)', {
139
+ id: handle.id,
140
+ name,
141
+ ctrl: ev.ctrl ?? false,
142
+ shift: ev.shift ?? false,
143
+ alt: ev.alt ?? false,
144
+ exitProgress,
145
+ });
146
+ }
147
+ try {
148
+ handle.surface.onKey?.(ev);
149
+ } catch { /* surface disposed mid-event; treat as no-op */ }
150
+ return 'consumed';
151
+ },
152
+ };
153
+ }
154
+
155
+ /** Singleton used by renderers; the factory remains available for isolated tests. */
156
+ export const terminalModalRouter = createTerminalModalRouter();