elanous 0.2.38 → 0.2.41

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 (712) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1115.434ae2ecb0ad986d.js +149 -0
  6. package/apps/pwa/out/_next/static/chunks/1121.667cec0bcdbb3fdb.js +36 -0
  7. package/apps/pwa/out/_next/static/chunks/1178.1aa9cad0e7695427.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1197-54da59d250a6e476.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 1219.7e17964e0e7cd8e5.js} +3 -3
  10. package/apps/pwa/out/_next/static/chunks/1245.1cfd13b26dbd71d6.js +287 -0
  11. package/apps/pwa/out/_next/static/chunks/1494-f93046ff5c5a124d.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1609.2b312797599b8e45.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1661.0dd330f3d89f73f3.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/167-0c121e4b47e0f9da.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1700.cdc2bf8cc685e221.js +90 -0
  16. package/apps/pwa/out/_next/static/chunks/1703-78e46acad29f3cfc.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{7573.2376e13c9c21f1f8.js → 1765.679b29625c8e88d4.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 1800.f7ff51dc4978a958.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/1971-7efb628c471dc5a0.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1999-8de7b7bb36801913.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2073.689dcb2680113d76.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2198-557d49184104d165.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/221-440ce67fa9f5c839.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 2263.e09b6edea33bad2d.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2427-8ed8e98624cbd664.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2457-725c5827bc003795.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2491-2718b15a5ccb75a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2527-5c636a43c7cc5dde.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2692-1027cb16fe4ccf49.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2743.5d3f76948be32b34.js +41 -0
  31. package/apps/pwa/out/_next/static/chunks/2773.0e80b9d325fb5635.js +32 -0
  32. package/apps/pwa/out/_next/static/chunks/2873-0f3cb56c8e3528ea.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 2fdf2931.b431eee4fb468bc3.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 2fe2c302.41b517f88d6fe502.js} +1 -1
  35. package/apps/pwa/out/_next/static/chunks/3097.864e92bdaa2f4d15.js +79 -0
  36. package/apps/pwa/out/_next/static/chunks/3136-d6870ba63300a93e.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3173-0289113d434e83b7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3230-49298c3b73ef2268.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/325-dd9208a1a0ab7ce4.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3283.528f430dd043fb4e.js +74 -0
  41. package/apps/pwa/out/_next/static/chunks/3295.cc8cb13b8f0dae1a.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3688-86e3b88abf18cb3b.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3804-7220467a5473a8df.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3808.3e1e247ce7bdf889.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → 385e4574.e9886ab32759eda3.js} +3 -3
  46. package/apps/pwa/out/_next/static/chunks/3927.b5473ad109da44c5.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/3934-98ea94832e194796.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4133.2056bb4d78f621af.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4156.ba4de4a3664f04b4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4297-239ca82f293faab0.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4320-dcc5a7734126f4c9.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4434.94b4c552a2d91e69.js +148 -0
  53. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 4527.a69f2894d1bc9f4a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/4579.03e4092f73950965.js +226 -0
  55. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 4667.97e31aa38c95c475.js} +4 -4
  56. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 4702.4a4adc1f16d7c93b.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/4815.481501c57b3568d9.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/487-d16e698ef14662d9.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4888-7a38bf522c9cc6fe.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5034-30e429d6bb086881.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5040-35c494e60dadd97d.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/50c6ab1e.81a96e419350909d.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5154.4b6a836179356f30.js +94 -0
  64. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 5159.115f1c2ca471386c.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5228-a8200df486278f2d.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/530.d26346e18089640a.js +115 -0
  67. package/apps/pwa/out/_next/static/chunks/5379.97af106d09566f69.js +8 -0
  68. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → 53aeb4ee-51c92f8d683f5220.js} +1 -1
  69. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 5471.1e611302ed3a7c53.js} +2 -2
  70. package/apps/pwa/out/_next/static/chunks/5479-b6372e762719f92f.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5534-699c5cbcbc96c5d7.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 5574.f35accf4f132b29d.js} +1 -1
  73. package/apps/pwa/out/_next/static/chunks/5701.9c4e8f250312eeee.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 5744.b9415e18ad623100.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/{5300.677c97e0393742e6.js → 5892.2526d962339662d8.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/5937.c2df9e3447e1f667.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5941.8210cc93c9202c0a.js +286 -0
  78. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 5947-135e26537d80a6b9.js} +3 -3
  79. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 5964-7e21164a8f2cf0ce.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/5975.4004f820ae3cecd5.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6142-7ccd48795d7abd55.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6160.bf9177b8c1bfb243.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6398.71ba0690c8027555.js +27 -0
  84. package/apps/pwa/out/_next/static/chunks/6492.2bd5c10edc1a064e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/6552.a3840aa7da35ad68.js +62 -0
  86. package/apps/pwa/out/_next/static/chunks/6736.1e36d3ac5fa5e41d.js +24 -0
  87. package/apps/pwa/out/_next/static/chunks/6874.d5cf7eb8edb2cabe.js +2 -0
  88. package/apps/pwa/out/_next/static/chunks/6900.3ccbe069bdd4556a.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/71327eb4.add50b365f94bf3a.js +122 -0
  90. package/apps/pwa/out/_next/static/chunks/7136.deca3e3a2ddaa374.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7139-ee9f8ed2677a40b3.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{2415.738b777642a02233.js → 7191.fdc955f7d96064a4.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7423-e0aa5d9e2962120e.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7453.afc1ea7e05d56a8c.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7503-5e6a3d7fe67e4a0c.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7761-476fd7bf768abd34.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7975.eafb12097a0a9e62.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8050-9b364bdef8f71927.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8152.64e253c35cccfaae.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8190.620f0231b3924bcb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/83184dcd-0ee6247ff41eb3f2.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8448.45b6b1f1a99eeb35.js +104 -0
  103. package/apps/pwa/out/_next/static/chunks/8464-e24f10451b658aac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8477.e4c944bb3aa5d2f3.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8710.ca385257d5ca422e.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8830.627ccf294ec2465c.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8880.64c445592f04acaf.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8981.c706964c8ba27aff.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 9048.212083de42d25be3.js} +2 -2
  110. package/apps/pwa/out/_next/static/chunks/9053.bd0fffaff8d3f836.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9161-c66e723d7ec9d682.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9185.1ecdf9b65c0bb684.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9356.fccd5f58086b4ff5.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9446.dc0406109371d329.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9506.dcf25d467a42627e.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 9507.7026657a2f47eb64.js} +16 -16
  117. package/apps/pwa/out/_next/static/chunks/9541.eb8e2f8480c7feca.js +93 -0
  118. package/apps/pwa/out/_next/static/chunks/9577.ed7582186efa5482.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9579.4a8169600fff2058.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9642-ff2e039eb62e3b92.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9659-8f2323348113ad80.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9724.4c5623af2db43153.js +34 -0
  123. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 9834.63ab2bbc3153172e.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/{3389.012c70767a872f9b.js → 9869.81a1e24ca682d5a0.js} +1 -1
  125. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → a0a01613.6d1cca322238d7fe.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → addc2b32.8c4ff8f0aefe987d.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-8d9d76ea322d855c.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed2c4e59f9f1fe21.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-2dc99e03c5d76ca0.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/board/page-b5a3a788330e920f.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-14949db884bfa672.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea76c85b36388a97.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/ceo/page-01716d20af62d325.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/chat/page-62baf6881a64b1e9.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/consult/page-f89ba590c2af8afa.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/control/page-22f8b0f78d9637e5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/decisions/page-817f9d7e6820be80.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/design-check/page-ffb9bc0d2650249a.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/editor/page-f6d0e64873c0f629.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/exec/page-8bfa0d4ba23a209d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/field/page-f5060462249e32c7.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/healthz/route-8d9d76ea322d855c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2049f8b1ef79117.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/intake/page-1446c5fa93907f11.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/layout-b48a7a07c5204156.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live/page-e974b8c4ca47614c.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/live-run/page-8a919b869bd28594.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/loops/page-d31b8de6bfcd72ed.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/market/page-64765f817909db29.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-d128c8569a36ee9b.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/morning/page-b2679d357e9b9270.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/not-found-6fabec98a9e7b269.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/observatory/page-048f30149dcf1349.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-9113181d6b5a2725.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-40f9e19149024298.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-1e7a755a13227611.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3c8f8b67a203cf07.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/page-18032f5437215062.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/reflection/page-da3b739192fd0ee3.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-d332545571bd6fd1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/sessions/page-5237aa5b3f3b8ec5.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a142dfb0331a05f5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/settings/page-d16e56c3989c147e.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6b6593600869e2cd.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/layout-8d9d76ea322d855c.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/setup/page-29e8b8a8396b55cb.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/share/page-b3414d856a1a7e2f.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c3affa52b7ce961b.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f21dddf9f95b6fab.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/term/page-f5a30a24745bf088.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/today/page-8c8569a09b4d4e34.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/trace/page-2ce32722c0243483.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/vault/page-4767b0d9c0a98c6c.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-116ee1339c387a75.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workflows/page-35e8c50ca4ef7ffc.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/workspace/page-52e17113356bb891.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7458ae05ed2ac1a0.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/b2271e54.c1de3347976e90b0.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → c0c1a699.0ba79f97005965d4.js} +7 -7
  180. package/apps/pwa/out/_next/static/chunks/framework-ad6c9dd524ad6ef8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-2ddd1f2b44d6aa59.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/main-e3d82bdc358d20c5.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_app-71d5aa3896e1655f.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/pages/_error-03ffc54e00438546.js +1 -0
  185. package/apps/pwa/out/_next/static/chunks/webpack-56bb89af5a611d0b.js +1 -0
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +22 -22
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +21 -21
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +22 -22
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +22 -22
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  283. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  284. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  285. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  286. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  287. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +23 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +3 -0
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/video/explainer-line.yaml +4 -1
  298. package/graphs/work/research-report.yaml +11 -1
  299. package/package.json +1 -1
  300. package/scripts/dead-code/report.ts +169 -0
  301. package/scripts/disk-steward.ts +46 -0
  302. package/scripts/fleet/node-setup.sh +50 -0
  303. package/scripts/graph-units/verbs/research.ts +55 -0
  304. package/scripts/lib/morning-report-options.ts +3 -4
  305. package/scripts/lib/tui-regress-evidence.ts +56 -0
  306. package/scripts/llm-cost-ledger.ts +179 -8
  307. package/scripts/measure-nl-routing-corpus.ts +10 -2
  308. package/scripts/morning-report.ts +5 -1
  309. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  310. package/scripts/public-copy-lint.ts +163 -19
  311. package/scripts/public-export.ts +15 -7
  312. package/scripts/ratchets/train-side-invariants.sh +0 -1
  313. package/scripts/release-loop/export-check-node.ts +21 -3
  314. package/scripts/release-loop/gate-autoheal.ts +117 -0
  315. package/scripts/release-loop/gate-baseline-receipt.ts +8 -1
  316. package/scripts/release-loop/gate-diff.ts +22 -3
  317. package/scripts/release-loop/gate-node.ts +583 -64
  318. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  319. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  320. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  321. package/scripts/release-loop/gate-triage-node.ts +70 -10
  322. package/scripts/release-loop/gate-wall.ts +5 -5
  323. package/scripts/release-loop/preflight.ts +6 -2
  324. package/scripts/release-loop/resume-release.ts +267 -20
  325. package/scripts/release-loop/resume.ts +48 -0
  326. package/scripts/release-loop/traffic-node.ts +6 -3
  327. package/scripts/release-loop/unattended-release.ts +4 -2
  328. package/scripts/release-loop/version-node.ts +7 -2
  329. package/scripts/release-story/draft.ts +1 -1
  330. package/scripts/research-bench/README.md +53 -0
  331. package/scripts/research-bench/questions.json +66 -0
  332. package/scripts/research-bench/rubric.md +33 -0
  333. package/scripts/research-bench/run.ts +523 -0
  334. package/scripts/shadow-authoring-probe.ts +20 -0
  335. package/scripts/tui-regress.ts +85 -10
  336. package/scripts/ux-sim.ts +19 -2
  337. package/src/acp/core-turn-bridge.ts +94 -4
  338. package/src/agent/autonomous-tools.ts +10 -3
  339. package/src/agent/monad-agent-turn.ts +4 -1
  340. package/src/agent/registry.ts +26 -2
  341. package/src/agent/shared-app-tools.ts +1 -1
  342. package/src/agent/surface-ux/build.ts +12 -3
  343. package/src/agent/surface-ux/types.ts +1 -1
  344. package/src/agent/task-notification.ts +75 -6
  345. package/src/agent/types.ts +3 -0
  346. package/src/agent-mission/driver.ts +29 -3
  347. package/src/agent-mission/mission-cli.ts +2 -1
  348. package/src/agent-substrate/review-context-pack.ts +365 -0
  349. package/src/agent-substrate/self-review-cli.ts +291 -20
  350. package/src/ask-user-question/index.ts +6 -0
  351. package/src/ask-user-question/inline-resolver.ts +49 -0
  352. package/src/auto-research/question-ladder-contract.ts +22 -3
  353. package/src/auto-research/research-turn.ts +359 -17
  354. package/src/autopilot/agent-loop.ts +1 -1
  355. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  356. package/src/autopilot/pty-control-loop.ts +8 -1
  357. package/src/boot/daemon-tools/index.ts +4 -3
  358. package/src/boot/daemon-tools/self-implement.ts +312 -7
  359. package/src/boot/daemon-tools/types.ts +2 -0
  360. package/src/budget/llm-cost.ts +44 -5
  361. package/src/budget/shadow-arms.ts +52 -0
  362. package/src/budget/unified-usage.ts +17 -1
  363. package/src/capture/tui-self-report.ts +14 -0
  364. package/src/chat/index.ts +33 -7
  365. package/src/chat/pickers/state.ts +7 -1
  366. package/src/cli/agent-cli.ts +43 -8
  367. package/src/cli/intake-cli.ts +22 -1
  368. package/src/cli/lesson-cli.ts +19 -3
  369. package/src/cli/log-event-names.ts +6 -0
  370. package/src/cli/mcp-login.ts +8 -18
  371. package/src/cli/msg-cli.ts +57 -1
  372. package/src/cli/pod-cli.ts +17 -2
  373. package/src/cli/pr-land-heavy-remote.ts +15 -9
  374. package/src/cli/pty-takeover-cli.ts +67 -7
  375. package/src/cli/release-cli.ts +79 -7
  376. package/src/cli/repo-cli.ts +2 -1
  377. package/src/cli/sim-cli.ts +7 -1
  378. package/src/cli/tasks-cli.ts +41 -13
  379. package/src/codex/models.ts +30 -15
  380. package/src/control-plane/ledger.ts +21 -4
  381. package/src/core-turn/run-core-turn.ts +47 -3
  382. package/src/core-turn/run-goal-loop.ts +240 -10
  383. package/src/core-turn/types.ts +9 -0
  384. package/src/dashboard/acp-boot.ts +72 -3
  385. package/src/dashboard/chat/acp-chat.ts +2 -2
  386. package/src/dashboard/classic-sigquit.ts +16 -0
  387. package/src/dashboard/index.ts +327 -27
  388. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  389. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  390. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  391. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  392. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  393. package/src/dashboard/input/external-input-host.ts +2 -0
  394. package/src/dashboard/sidetab-runtime.ts +228 -0
  395. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  396. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  397. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  398. package/src/dashboard/term-slash-runtime.ts +16 -18
  399. package/src/dashboard/turn-preamble.ts +14 -1
  400. package/src/disk-steward/judge.ts +73 -0
  401. package/src/disk-steward/ledger.ts +122 -0
  402. package/src/disk-steward/steward.ts +373 -0
  403. package/src/domains/guardian-tick.ts +191 -2
  404. package/src/domains/knowledge.ts +1 -1
  405. package/src/esc-abort-gate.ts +33 -1
  406. package/src/execution-loop/launch-gate.ts +206 -1
  407. package/src/graph-runner/graph-cli.ts +27 -4
  408. package/src/graph-runner/in-process-registry.ts +37 -0
  409. package/src/graph-runner/runner.ts +63 -11
  410. package/src/graph-wizard/generate.ts +16 -7
  411. package/src/graph-wizard/mission-compose.ts +201 -0
  412. package/src/grok/agent-search.ts +8 -2
  413. package/src/grok/credential.ts +5 -0
  414. package/src/grounding/ref-index.ts +30 -0
  415. package/src/grounding/ref-vector.ts +61 -0
  416. package/src/grounding/sources-cli.ts +11 -3
  417. package/src/grounding/sources.ts +15 -1
  418. package/src/harness/harness-cli-command.ts +305 -23
  419. package/src/harness/harness-incidents.ts +312 -7
  420. package/src/harness/harness-pod-dispatch.ts +7 -1
  421. package/src/harness/harness-space.ts +15 -1
  422. package/src/harness/progress-worker-entry.ts +59 -0
  423. package/src/harness/progress-worker-runtime.ts +11 -0
  424. package/src/index.ts +35 -5
  425. package/src/input/external-input-queue.ts +10 -0
  426. package/src/instance/dev-project.ts +25 -0
  427. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  428. package/src/intake-plane/intake-to-tasks.ts +246 -3
  429. package/src/intelligence-map/model-alias.ts +6 -5
  430. package/src/intelligence-map/model-catalog.ts +59 -2
  431. package/src/lessons/friction-ledger.ts +154 -0
  432. package/src/live-supply/collector.ts +149 -0
  433. package/src/live-supply/probes.ts +52 -0
  434. package/src/live-supply/snapshot.ts +40 -0
  435. package/src/llm/model-defaults.ts +4 -4
  436. package/src/llm.ts +473 -87
  437. package/src/loops/orchestrator/tick.ts +56 -0
  438. package/src/mcp/mcp-oauth.ts +3 -1
  439. package/src/model-tier/llm-tier-map.ts +9 -9
  440. package/src/model-tier/turn-tier.ts +1 -1
  441. package/src/msg/msg-mirror-github.ts +80 -0
  442. package/src/msg/msg-mirror-policy.ts +61 -0
  443. package/src/msg/msg-mirror-runner.ts +219 -0
  444. package/src/msg/msg-mirror-state.ts +33 -0
  445. package/src/msg/msg-store.ts +11 -0
  446. package/src/nexus/api/harness-api.ts +2 -1
  447. package/src/output-truncation.ts +41 -12
  448. package/src/project/project-store.ts +48 -1
  449. package/src/pty/snapshot.py +132 -0
  450. package/src/pty-shell/pty-control-ipc.ts +29 -2
  451. package/src/pty-shell/pty-manifest.ts +59 -3
  452. package/src/pty-shell/registry.ts +2 -0
  453. package/src/pty-shell/tui-run-state.ts +80 -3
  454. package/src/release-loop/gate-host-reservation.ts +157 -4
  455. package/src/release-loop/gate-shard-ledger.ts +68 -0
  456. package/src/release-loop/merged-pr-checklist.ts +25 -2
  457. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  458. package/src/release-loop/rehearsal.ts +27 -0
  459. package/src/release-loop/release-schedule.ts +90 -1
  460. package/src/research/bloom-exemplars.ts +135 -0
  461. package/src/research/edge-decision.ts +124 -15
  462. package/src/research/gap-followup.ts +249 -0
  463. package/src/research/lenses/counter-evidence.ts +100 -0
  464. package/src/research/lenses/working-backwards.ts +89 -0
  465. package/src/research/plugin-discovery.ts +242 -0
  466. package/src/research-bridge/invoke.ts +4 -2
  467. package/src/research-bridge/types.ts +2 -0
  468. package/src/self-dev/ask-launch-flow.ts +73 -131
  469. package/src/self-dev/dev-cli.ts +19 -17
  470. package/src/self-dev/dev-pipeline.ts +8 -4
  471. package/src/self-dev/graph-front-nodes.ts +23 -0
  472. package/src/self-dev/graph-journey-route.ts +10 -2
  473. package/src/self-dev/launch-preflight-text.ts +2 -2
  474. package/src/self-dev/launch-preflight.ts +47 -11
  475. package/src/self-dev/orchestrate-cli.ts +1 -0
  476. package/src/self-dev/orchestrate.ts +15 -0
  477. package/src/self-dev/run-supervisor.ts +204 -3
  478. package/src/self-dev/run-types.ts +3 -0
  479. package/src/self-implement/device-first.ts +8 -2
  480. package/src/self-implement/doctor-visit.ts +76 -58
  481. package/src/self-implement/gate-artifacts.ts +16 -0
  482. package/src/self-implement/gate-baseline.ts +75 -4
  483. package/src/self-implement/gate-cli.ts +368 -30
  484. package/src/self-implement/gate-receipt-registry.ts +180 -0
  485. package/src/self-implement/gate-remote.ts +165 -24
  486. package/src/self-implement/goal-author-clarification.ts +205 -32
  487. package/src/self-implement/goal-author-decompose.ts +24 -15
  488. package/src/self-implement/goal-author.ts +86 -10
  489. package/src/self-implement/graph-stage-units.ts +172 -0
  490. package/src/self-implement/graph-templates.ts +162 -1
  491. package/src/self-implement/graph-variant.ts +37 -4
  492. package/src/self-implement/host-regate.ts +124 -49
  493. package/src/self-implement/impl-findings-feedback.ts +188 -0
  494. package/src/self-implement/knowhow-pack.ts +227 -10
  495. package/src/self-implement/off-diff-evidence.ts +124 -0
  496. package/src/self-implement/orchestrator.ts +320 -28
  497. package/src/self-implement/run-ledger.ts +110 -14
  498. package/src/self-implement/run-stop.ts +33 -2
  499. package/src/self-implement/running-runs.ts +35 -12
  500. package/src/self-implement/seams.ts +6 -3
  501. package/src/self-implement/self-implement-cli.ts +40 -6
  502. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  503. package/src/self-implement/stop-autoheal.ts +15 -6
  504. package/src/session/chat.ts +66 -15
  505. package/src/session/request-size-guard.ts +123 -0
  506. package/src/session-runtime/provider-circuit.ts +140 -0
  507. package/src/shell-runner/file-engine.ts +1 -0
  508. package/src/shell-runner/types.ts +4 -0
  509. package/src/sidetab-core/model.ts +312 -0
  510. package/src/skills/tools/schedule-wakeup.ts +23 -1
  511. package/src/skills/tools/shell.ts +51 -5
  512. package/src/steward/directive-audit.ts +354 -0
  513. package/src/surface/child-process.ts +31 -0
  514. package/src/surface/tui-stderr-owner.ts +48 -0
  515. package/src/task-agent/cover.ts +30 -12
  516. package/src/task-agent/judge.ts +56 -0
  517. package/src/task-agent/parent-host.ts +14 -1
  518. package/src/task-agent/postland-card.ts +35 -2
  519. package/src/task-agent/rejudge-on-head.ts +46 -2
  520. package/src/task-agent/repair-cycle.ts +1 -1
  521. package/src/task-agent/task-hand.ts +133 -25
  522. package/src/task-agent/tier-split.ts +105 -21
  523. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  524. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  525. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +70 -2
  526. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  527. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  528. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  529. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  530. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  531. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  532. package/src/task-orchestrator/surfaces/self-implement-pod.ts +298 -45
  533. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  534. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  535. package/src/tui/entry.ts +25 -5
  536. package/src/tui/inline-choice.ts +188 -0
  537. package/src/tui/sidetab/list.ts +36 -165
  538. package/src/tui/sidetab/nl-tool.ts +2 -136
  539. package/src/tui/sidetab/peek.ts +52 -0
  540. package/src/tui/slash/term.ts +12 -1
  541. package/src/tui-client/dashboard-session.ts +10 -1
  542. package/src/user-config.ts +45 -9
  543. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  544. package/src/ux-sim/fake-land-queue.ts +88 -0
  545. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  546. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  547. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  548. package/src/ux-sim/goal-interim-trace.ts +24 -0
  549. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  550. package/src/ux-sim/release-sim-rig.ts +262 -0
  551. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  552. package/src/ux-sim/subagent-tools-device.ts +2 -2
  553. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  554. package/src/version/packed-revision.json +1 -1
  555. package/src/video-pipeline/recipes/explainer.ts +54 -2
  556. package/src/web-search/grok.ts +32 -6
  557. package/src/web-search/index.ts +8 -7
  558. package/src/workflow-runtime/node-catalog.ts +53 -4
  559. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  560. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +0 -148
  567. package/apps/pwa/out/_next/static/chunks/2104.70e086d5174a4736.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  571. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  572. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  581. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  583. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  586. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  592. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4199-f7c6eb40cd0322f8.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  604. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  605. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  607. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  614. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  617. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  629. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7524.ce973525d30b3d52.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/7628.6b16863ac3972333.js +0 -34
  636. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/7954.4f7a8832663ee979.js +0 -115
  639. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  647. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  648. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +0 -226
  649. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  650. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  654. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +0 -122
  705. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  711. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  712. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → GiOLWmt4MqDZePubBjA4Q}/_ssgManifest.js +0 -0
@@ -17,7 +17,7 @@ import { getDefaultLogStore, type LogStore } from '../../mss/logging/log-store.j
17
17
  import { podBunCacheVolume } from './pod-bun-cache.js';
18
18
  import { POD_JOB_TTL_AFTER_FINISHED_SECONDS } from './pod-lease.js';
19
19
  import { podHostDirsCheckScript, podInstallSlotsVolume, prepareHostDirsOnce, type HostDirsPrepResult, podHostDirsScript } from './pod-install-slots.js';
20
- import { type PodPoolMember, PodPoolScheduler, resolvePodPoolSpec, parsePodPool, checkPodPool, syncPoolImages, registryImageRef, type PoolKubectl } from './pod-pool.js';
20
+ import { type PodPoolMember, PodPoolScheduler, defaultRemoteRun, resolvePodPoolSpec, parsePodPool, checkPodPool, syncPoolImages, registryImageRef, type PoolKubectl } from './pod-pool.js';
21
21
  import { podSkillsDigest, readSkillEnvFiles, resolvePodSkills } from './pod-skills.js';
22
22
  import { podSourceScript, type PodSource } from './pod-source-receive.js';
23
23
  import { podProvenanceMetadata, type PodProvenance } from './pod-provenance.js';
@@ -108,6 +108,287 @@ export function memoryRequestWithin(limit: string | undefined): string {
108
108
  return request !== null && max !== null && request > max ? limit! : POD_COMMAND_MEMORY_REQUEST_DEFAULT;
109
109
  }
110
110
 
111
+ // ═══════════ POD-CPU-REQUEST-RIGHTSIZE-2-FU ═══════════
112
+ // CPU 요청량(기본 request 1)을 바꾸려면 «gate16+harness40 이 같은 호스트에서 함께 도는» 측정값이 있어야 한다.
113
+ // 그 측정을 내는 발사는 두 관문을 지난다 — ①발사 선행 조건(풀 슬롯·SSH·Pod admission·allocatable/request 기준선)을
114
+ // 먼저 읽어 기록하고 하나라도 불가하면 발사 0 · 사유 · HITL(local substrate 대체 없음) ②측정이 없는 같은 조건의
115
+ // 재발사 금지(run-477b2ee2·run-7bc13989 는 CPU 측정 전에 no-launch(pod-error)로 끝났다). 측정이 모자라면 yellow —
116
+ // 기본 요청량 그대로다.
117
+
118
+ /** POD-CPU-REQUEST-RIGHTSIZE-2-FU — 이 요청량을 정당화하는 공존 조건(게이트 조각 16 ⊕ 하니스 40 동시 실행). */
119
+ export const POD_RIGHTSIZE_CONDITION = 'gate16+harness40';
120
+ /** 측정 사용량 위에 남기는 여유 — 조정 요청량은 100m 단위로 올린다. */
121
+ export const POD_RIGHTSIZE_HEADROOM = 1.25;
122
+ /** 스케줄 대기가 이보다 길면 그 요청은 그 호스트에 «너무 크다» — 조정 사유에 원문을 남긴다. */
123
+ export const POD_RIGHTSIZE_WAIT_LIMIT_MS = 120_000;
124
+
125
+ /** 한 발사의 결과 기록 — `no-launch` 는 CPU 측정 «전에» 끝난 발사다(pod-error). */
126
+ export interface PodRightsizeLaunchRecord {
127
+ run: string;
128
+ condition: string;
129
+ outcome: 'no-launch' | 'launched';
130
+ reason?: string;
131
+ /** 그 발사가 CPU 사용량을 쟀나 — no-launch 면 false. */
132
+ cpuMeasured?: boolean;
133
+ }
134
+
135
+ /** run-477b2ee2·run-7bc13989 — CPU 측정 전에 no-launch(pod-error)로 끝나 gate16+harness40 공존 증거가 0 인 두 발사. */
136
+ export const POD_RIGHTSIZE_VOID_LAUNCHES: readonly PodRightsizeLaunchRecord[] = [
137
+ { run: 'run-477b2ee2', condition: POD_RIGHTSIZE_CONDITION, outcome: 'no-launch', reason: 'pod-error', cpuMeasured: false },
138
+ { run: 'run-7bc13989', condition: POD_RIGHTSIZE_CONDITION, outcome: 'no-launch', reason: 'pod-error', cpuMeasured: false },
139
+ ];
140
+
141
+ /** 동일 호스트 동시 실행 한 표본 — 요청량·사용량·스케줄 대기·eviction 원문을 그대로 든다. */
142
+ export interface PodCpuSample {
143
+ /** 이 표본을 낸 실행(게이트 조각 16 · 하니스 40). */
144
+ label: string;
145
+ /** 매니페스트에 실려 실제로 발사된 CPU 요청(millis). */
146
+ requestMillis: number;
147
+ /** 실행 중 측정된 CPU 사용량(millis) — 못 쟀으면 null. */
148
+ usageMillis: number | null;
149
+ /** 스케줄 대기(ms) — 못 쟀으면 null. */
150
+ waitMs: number | null;
151
+ /** eviction 원문(있으면 그대로 · 없으면 null/빈 문자열). */
152
+ eviction?: string | null;
153
+ }
154
+
155
+ /** `runPodCommand` 에 붙는 재측정 요청 — 어떤 조건의 표본인지, 앞선 발사 기록, 이번 발사의 호스트 이름. */
156
+ export interface PodCpuRightsizeRequest {
157
+ /** 공존 조건 이름 — 기본 {@link POD_RIGHTSIZE_CONDITION}. */
158
+ condition?: string;
159
+ /** 같은 호스트 동시 실행 표본. 비었거나 사용량을 못 쟀으면 yellow(기본 요청량 유지). */
160
+ samples?: readonly PodCpuSample[];
161
+ /** 앞선 발사 기록 — 기본 {@link POD_RIGHTSIZE_VOID_LAUNCHES}(측정 전 no-launch 두 건). */
162
+ priorLaunches?: readonly PodRightsizeLaunchRecord[];
163
+ /** 기록·사유에 남길 대상 호스트(없으면 임차한 멤버의 ssh 호스트). */
164
+ host?: string;
165
+ }
166
+
167
+ /**
168
+ * CLI(`elanous pod run --cpu-rightsize`)가 받는 JSON → 재측정 요청. `{ condition?, samples?, priorLaunches?, host? }` 만 받고
169
+ * 모르는 키·잘못된 수량은 사유와 함께 거부한다(발사 전에 막는다). 비었으면 undefined = 종전 발사.
170
+ */
171
+ export function parseCpuRightsizeRequest(value: unknown, label = 'cpuRightsize'): PodCpuRightsizeRequest | undefined {
172
+ if (value === undefined || value === null) return undefined;
173
+ if (typeof value !== 'object' || Array.isArray(value)) throw new Error(`${label} must be { condition?, samples?, priorLaunches?, host? }`);
174
+ const raw = value as Record<string, unknown>;
175
+ const unknownKeys = Object.keys(raw).filter((key) => !['condition', 'samples', 'priorLaunches', 'host'].includes(key));
176
+ if (unknownKeys.length) throw new Error(`${label} has unknown keys: ${unknownKeys.join(', ')}`);
177
+ const text = (v: unknown, key: string): string | undefined => {
178
+ if (v === undefined || v === null || v === '') return undefined;
179
+ if (typeof v !== 'string') throw new Error(`${label}.${key} must be a string`);
180
+ return v.trim() || undefined;
181
+ };
182
+ const millis = (v: unknown, key: string, allowZero = false): number | null => {
183
+ if (v === undefined || v === null) return null;
184
+ if (typeof v !== 'number' || !Number.isSafeInteger(v) || (allowZero ? v < 0 : v <= 0)) {
185
+ throw new Error(`${label}.${key} must be ${allowZero ? 'non-negative' : 'positive'} whole millicores`);
186
+ }
187
+ return v;
188
+ };
189
+ const sampleList = raw.samples === undefined || raw.samples === null ? [] : raw.samples;
190
+ if (!Array.isArray(sampleList)) throw new Error(`${label}.samples must be an array`);
191
+ const samples = sampleList.map((entry, i) => {
192
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) throw new Error(`${label}.samples[${i}] must be an object`);
193
+ const row = entry as Record<string, unknown>;
194
+ const name = text(row.label, `samples[${i}].label`);
195
+ if (!name) throw new Error(`${label}.samples[${i}].label is required`);
196
+ const requestMillis = millis(row.requestMillis, `samples[${i}].requestMillis`);
197
+ if (requestMillis === null) throw new Error(`${label}.samples[${i}].requestMillis is required`);
198
+ return {
199
+ label: name, requestMillis,
200
+ usageMillis: millis(row.usageMillis, `samples[${i}].usageMillis`),
201
+ waitMs: millis(row.waitMs, `samples[${i}].waitMs`, true),
202
+ eviction: text(row.eviction, `samples[${i}].eviction`) ?? null,
203
+ };
204
+ });
205
+ const launchList = raw.priorLaunches === undefined || raw.priorLaunches === null ? [] : raw.priorLaunches;
206
+ if (!Array.isArray(launchList)) throw new Error(`${label}.priorLaunches must be an array`);
207
+ const priorLaunches = launchList.map((entry, i) => {
208
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) throw new Error(`${label}.priorLaunches[${i}] must be an object`);
209
+ const row = entry as Record<string, unknown>;
210
+ const run = text(row.run, `priorLaunches[${i}].run`);
211
+ if (!run) throw new Error(`${label}.priorLaunches[${i}].run is required`);
212
+ const rawOutcome = row.outcome;
213
+ if (rawOutcome !== 'no-launch' && rawOutcome !== 'launched') throw new Error(`${label}.priorLaunches[${i}].outcome must be no-launch or launched`);
214
+ const outcome: 'no-launch' | 'launched' = rawOutcome === 'launched' ? 'launched' : 'no-launch';
215
+ const condition = text(row.condition, `priorLaunches[${i}].condition`) ?? POD_RIGHTSIZE_CONDITION;
216
+ const reason = text(row.reason, `priorLaunches[${i}].reason`);
217
+ return { run, condition, outcome, ...(reason ? { reason } : {}) };
218
+ });
219
+ const condition = text(raw.condition, 'condition');
220
+ const host = text(raw.host, 'host');
221
+ return {
222
+ ...(condition ? { condition } : {}),
223
+ samples,
224
+ ...(priorLaunches.length ? { priorLaunches } : {}),
225
+ ...(host ? { host } : {}),
226
+ };
227
+ }
228
+
229
+ /** millis → 쿠버네티스 수량(`2000` → `2` · `2800` → `2800m`). */
230
+ export function podCpuQuantity(millis: number): string {
231
+ if (!Number.isSafeInteger(millis) || millis <= 0) throw new Error(`pod cpu quantity needs positive millicores: ${millis}`);
232
+ return millis % 1000 === 0 ? String(millis / 1000) : `${millis}m`;
233
+ }
234
+
235
+ export interface PodCpuRightsizeVerdict {
236
+ /** green = 측정값이 요청량을 정한다 · yellow = 재측정 불가(기본 요청량 유지). */
237
+ status: 'green' | 'yellow';
238
+ /** 이번 발사에 실을 요청량(yellow 면 기본값). */
239
+ request: string;
240
+ requestMillis: number;
241
+ reason: string;
242
+ /** 판정에 쓴 표본(사용량을 잰 것만). */
243
+ measured: Array<{ label: string; requestMillis: number; usageMillis: number; waitMs: number | null; eviction: string | null }>;
244
+ }
245
+
246
+ /**
247
+ * 측정값 → 요청량. 표본이 하나도 없거나, 사용량을 못 쟀거나, eviction 원문이 있으면 yellow 로 기본 요청량을 지킨다
248
+ * (재측정 불가 = 결함 없음이 아니다). 그 밖에는 표본들의 최대 사용량 ⊕ 여유(POD_RIGHTSIZE_HEADROOM)를 100m 로
249
+ * 올린 값이 요청량이고, 한도(POD_COMMAND_CPU_LIMIT_DEFAULT)를 넘지 않는다.
250
+ */
251
+ export function podCpuRightsize(samples: readonly PodCpuSample[]): PodCpuRightsizeVerdict {
252
+ const yellow = (reason: string): PodCpuRightsizeVerdict => ({
253
+ status: 'yellow', request: POD_COMMAND_CPU_REQUEST_DEFAULT,
254
+ requestMillis: podCpuMillis(POD_COMMAND_CPU_REQUEST_DEFAULT)!, reason, measured: [],
255
+ });
256
+ if (samples.length === 0) return yellow('no same-host co-residency samples');
257
+ const evicted = samples.find((s) => (s.eviction ?? '').trim().length > 0);
258
+ if (evicted) return yellow(`eviction on ${evicted.label}: ${evicted.eviction!.trim().replace(/\s+/g, ' ').slice(0, 200)}`);
259
+ const unmeasured = samples.find((s) => s.usageMillis === null);
260
+ if (unmeasured) return yellow(`usage unmeasured on ${unmeasured.label}`);
261
+ const measured = samples.map((s) => ({
262
+ label: s.label, requestMillis: s.requestMillis, usageMillis: s.usageMillis!, waitMs: s.waitMs, eviction: null,
263
+ }));
264
+ const peak = Math.max(...measured.map((s) => s.usageMillis));
265
+ const limitMillis = podCpuMillis(POD_COMMAND_CPU_LIMIT_DEFAULT)!;
266
+ const sized = Math.min(Math.ceil((peak * POD_RIGHTSIZE_HEADROOM) / 100) * 100, limitMillis);
267
+ const waits = measured.map((s) => s.waitMs).filter((ms): ms is number => ms !== null);
268
+ const slow = waits.filter((ms) => ms > POD_RIGHTSIZE_WAIT_LIMIT_MS);
269
+ const waitNote = waits.length === 0
270
+ ? 'wait unreadable'
271
+ : `waited ${Math.max(...waits)}ms${slow.length ? ` (over ${POD_RIGHTSIZE_WAIT_LIMIT_MS}ms on ${slow.length})` : ''}`;
272
+ return {
273
+ status: 'green', request: podCpuQuantity(sized), requestMillis: sized,
274
+ reason: `peak usage ${peak}m over ${measured.length} samples · ${waitNote} · no eviction → request ${podCpuQuantity(sized)}`,
275
+ measured,
276
+ };
277
+ }
278
+
279
+ /**
280
+ * 같은 조건의 «무효 재발사» 금지 — 그 조건의 발사가 CPU 측정 전에 no-launch(pod-error)로 끝났고 아직 사용량을 잰
281
+ * 표본이 없으면, 같은 조건을 다시 쏘는 것은 같은 무효를 한 번 더 사는 일이다.
282
+ */
283
+ export function podRightsizeRefusal(o: {
284
+ condition: string;
285
+ samples: readonly PodCpuSample[];
286
+ priorLaunches?: readonly PodRightsizeLaunchRecord[];
287
+ }): { refused: boolean; reason: string; priorVoid: PodRightsizeLaunchRecord[] } {
288
+ // Only a no-launch that measured nothing is a void — a launch that died after a reading is not «no evidence».
289
+ const priorVoid = (o.priorLaunches ?? POD_RIGHTSIZE_VOID_LAUNCHES)
290
+ .filter((r) => r.condition === o.condition && r.outcome === 'no-launch' && r.cpuMeasured !== true);
291
+ if (priorVoid.length === 0) return { refused: false, reason: 'no no-launch record for this condition', priorVoid };
292
+ if (o.samples.some((s) => s.usageMillis !== null)) return { refused: false, reason: 'a measured sample exists', priorVoid };
293
+ const seen = priorVoid.map((r) => `${r.run}:${r.reason ?? r.outcome}`).join('·');
294
+ return {
295
+ refused: true,
296
+ reason: `same condition ${o.condition} re-launch refused — ${seen} ended before any CPU measurement`,
297
+ priorVoid,
298
+ };
299
+ }
300
+
301
+ /** 발사 선행 조건 기록 — 풀 슬롯 · SSH · Pod admission · allocatable/request 기준선. 하나라도 ok=false 면 발사하지 않는다. */
302
+ export interface PodLaunchPreconditions {
303
+ slots: { ok: boolean; ready: number; capacity: number; detail?: string };
304
+ ssh: { ok: boolean; host: string | null; detail?: string };
305
+ admission: { ok: boolean; detail?: string };
306
+ baseline: {
307
+ ok: boolean; node: string | null;
308
+ allocatableCpuMillis: number | null; requestedCpuMillis: number | null;
309
+ requestCpuMillis: number | null; freeCpuMillis: number | null;
310
+ detail?: string;
311
+ };
312
+ }
313
+
314
+ export interface PodLaunchPreconditionsDeps {
315
+ kubectl: Kubectl;
316
+ namespace: string;
317
+ member?: PodPoolMember | null;
318
+ /** 발사할 풀의 자리 — 풀이 없으면 null(단일 컨텍스트 하나). */
319
+ pool?: { ready: number; capacity: number } | null;
320
+ /** 이번 발사가 요청할 CPU(millis) — 기준선 여유와 비교한다. */
321
+ requestCpuMillis: number;
322
+ /** 원격 멤버 SSH 도달 시험. null/생략 = 못 잼(원격이면 불가로 센다). */
323
+ sshProbe?: ((host: string) => { status: number | null; stdout: string; stderr: string }) | null;
324
+ }
325
+
326
+ /** 대상 호스트의 선행 조건을 실제 클러스터에서 읽어 기록한다 — 판정하지 않고 «읽은 그대로» 남긴다. */
327
+ export function podLaunchPreconditions(o: PodLaunchPreconditionsDeps): PodLaunchPreconditions {
328
+ const slots: PodLaunchPreconditions['slots'] = o.pool
329
+ ? { ok: o.pool.ready > 0, ready: o.pool.ready, capacity: o.pool.capacity, ...(o.pool.ready > 0 ? {} : { detail: 'no ready pool member' }) }
330
+ : { ok: true, ready: 1, capacity: 1, detail: 'single context (no pool)' };
331
+
332
+ const host = o.member?.sshHost ?? null;
333
+ let ssh: PodLaunchPreconditions['ssh'];
334
+ if (!host) ssh = { ok: true, host: null, detail: 'this machine (no ssh)' };
335
+ else if (!o.sshProbe) ssh = { ok: false, host, detail: 'ssh probe unavailable' };
336
+ else {
337
+ const probed = o.sshProbe(host);
338
+ ssh = probed.status === 0
339
+ ? { ok: true, host }
340
+ : { ok: false, host, detail: (probed.stderr.trim().split('\n').pop() ?? '').slice(0, 200) || `ssh exit ${probed.status}` };
341
+ }
342
+
343
+ const cani = o.kubectl(['-n', o.namespace, 'auth', 'can-i', 'create', 'jobs.batch']);
344
+ const admission: PodLaunchPreconditions['admission'] = cani.status === 0 && /^yes$/i.test(cani.stdout.trim())
345
+ ? { ok: true, detail: 'can-i create jobs.batch' }
346
+ : { ok: false, detail: (cani.stderr.trim().split('\n').pop() ?? '').slice(0, 200) || `can-i ${cani.stdout.trim() || `exit ${cani.status}`}` };
347
+
348
+ const nodes = o.kubectl(['get', 'nodes', '-o', 'json']);
349
+ const pods = o.kubectl(['get', 'pods', '--all-namespaces', '-o', 'json']);
350
+ let allocatable: Array<{ name: string; cpu: number }> = [];
351
+ let perNode: Record<string, number> = {};
352
+ let baselineError: string | null = null;
353
+ try {
354
+ const parsed = JSON.parse(nodes.stdout) as { items?: Array<{ metadata?: { name?: string }; status?: { allocatable?: { cpu?: string } } }> };
355
+ allocatable = (parsed.items ?? []).flatMap((item) => {
356
+ const name = item.metadata?.name;
357
+ const cpu = podCpuMillis(item.status?.allocatable?.cpu ?? '');
358
+ return name && cpu !== null ? [{ name, cpu }] : [];
359
+ });
360
+ } catch { baselineError = `node list unreadable: ${(nodes.stderr.trim() || 'invalid json').slice(0, 200)}`; }
361
+ if (!baselineError) {
362
+ try {
363
+ const parsed = JSON.parse(pods.stdout) as { items?: Array<{ spec?: { nodeName?: string; containers?: Array<{ resources?: { requests?: { cpu?: string } } }> } }> };
364
+ for (const pod of parsed.items ?? []) {
365
+ const node = pod.spec?.nodeName;
366
+ if (!node) continue;
367
+ for (const container of pod.spec?.containers ?? []) {
368
+ perNode[node] = (perNode[node] ?? 0) + (podCpuMillis(container.resources?.requests?.cpu ?? '') ?? 0);
369
+ }
370
+ }
371
+ } catch { baselineError = `pod list unreadable: ${(pods.stderr.trim() || 'invalid json').slice(0, 200)}`; }
372
+ }
373
+ const ranked = [...allocatable]
374
+ .map((node) => ({ ...node, requested: perNode[node.name] ?? 0 }))
375
+ .sort((a, b) => (b.cpu - b.requested) - (a.cpu - a.requested) || a.name.localeCompare(b.name));
376
+ const chosen = baselineError ? undefined : ranked[0];
377
+ const baseline: PodLaunchPreconditions['baseline'] = !chosen
378
+ ? {
379
+ ok: false, node: null, allocatableCpuMillis: null, requestedCpuMillis: null,
380
+ requestCpuMillis: o.requestCpuMillis, freeCpuMillis: null,
381
+ detail: baselineError ?? (nodes.status !== 0 ? `node list exit ${nodes.status}` : 'no node reports an allocatable cpu'),
382
+ }
383
+ : {
384
+ ok: chosen.cpu - chosen.requested >= o.requestCpuMillis,
385
+ node: chosen.name, allocatableCpuMillis: chosen.cpu, requestedCpuMillis: chosen.requested,
386
+ requestCpuMillis: o.requestCpuMillis, freeCpuMillis: chosen.cpu - chosen.requested,
387
+ ...(chosen.cpu - chosen.requested >= o.requestCpuMillis ? {} : { detail: `free ${chosen.cpu - chosen.requested}m < request ${o.requestCpuMillis}m` }),
388
+ };
389
+ return { slots, ssh, admission, baseline };
390
+ }
391
+
111
392
  /** POD7 must-fix: the skill list alone can't tell a network-only job from one that needs ffmpeg/browser — so lite is
112
393
  * only ever chosen when the caller says so (`lite`), and then only for network skills without a clone. Anything we
113
394
  * can't judge keeps the full image. A lite request that doesn't fit is refused with the reason, not silently widened. */
@@ -429,6 +710,11 @@ export interface RunPodCommandOptions {
429
710
  memoryLimit?: string;
430
711
  /** GATE-SPEED A3①: CPU request/limit override — only the release gate passes it. Omitted = request 1 / limit 4. */
431
712
  cpu?: PodCpu;
713
+ /**
714
+ * POD-CPU-REQUEST-RIGHTSIZE-2-FU — this launch is a co-residency CPU measurement (게이트 조각 16 ⊕ 하니스 40 on one host).
715
+ * Omitted callers keep today's behaviour byte for byte: no precondition read, no measurement-driven request.
716
+ */
717
+ cpuRightsize?: PodCpuRightsizeRequest;
432
718
  /** W5 — memory-backed TMPDIR sizeLimit mounted at {@link POD_TMPFS_MOUNT_PATH}; only the release gate passes it. Omitted = image `/tmp`. */
433
719
  tmpfsSizeLimit?: string;
434
720
  /** POD7: 호출부가 «네트워크 스킬만 쓰는 명령»이라고 말할 때만 lite 이미지 ⊕ 2Gi. */
@@ -465,6 +751,8 @@ export interface RunPodCommandOptions {
465
751
  mirrorSeedCwd?: string;
466
752
  /** GATE-WARM-BOOT-NO-INIT — hands the hostPath dirs to uid 1000 on the member's nodes (test seam · default {@link prepareHostDirsOnce}). */
467
753
  prepareHostDirs?: (o: { member: PodPoolMember; hostPaths: readonly string[] }) => Promise<HostDirsPrepResult | undefined>;
754
+ /** POD-CPU-REQUEST-RIGHTSIZE-2-FU — SSH 도달 시험(test seam · 기본 `ssh <host> true`; 주입된 kubectl 이면 기본 없음). */
755
+ sshProbe?: (host: string) => { status: number | null; stdout: string; stderr: string };
468
756
  checkPool?: typeof checkPodPool;
469
757
  syncImages?: typeof syncPoolImages;
470
758
  imageCommit?: string | null;
@@ -641,9 +929,48 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
641
929
  const artifactRoot = options.artifactsRoot ?? `${effectiveInstanceRoot()}/pod-artifacts`;
642
930
  const artifactsDir = `${artifactRoot}/${name}`;
643
931
  let jobApplied = false;
932
+ /** POD-CPU-REQUEST-RIGHTSIZE-2-FU — 측정값이 정한 요청량(yellow 면 undefined = 기본값 그대로). */
933
+ let rightsizeCpu: PodCpu | undefined;
644
934
  try {
645
935
  ensureLive();
646
936
  if (!context && !options.kubectl) throw new Error('pod command: kubectl context 를 확인할 수 없다');
937
+ if (options.cpuRightsize) {
938
+ const condition = options.cpuRightsize.condition?.trim() || POD_RIGHTSIZE_CONDITION;
939
+ const samples = [...(options.cpuRightsize.samples ?? [])];
940
+ const priorLaunches = [...(options.cpuRightsize.priorLaunches ?? POD_RIGHTSIZE_VOID_LAUNCHES)];
941
+ const targetHost = options.cpuRightsize.host?.trim() || member?.sshHost || null;
942
+ // A no-launch(pod-error) run never produced a reading — firing the same condition again would buy the same void.
943
+ const refusal = podRightsizeRefusal({ condition, samples, priorLaunches });
944
+ if (refusal.refused) {
945
+ log('pod.command-job', 'rightsize-relaunch-refused', {
946
+ condition, host: targetHost, reason: refusal.reason, substrate: 'pod', launched: false, fallback: 'none',
947
+ hitl: true, priorVoid: refusal.priorVoid,
948
+ });
949
+ throw new Error(`pod command: ${refusal.reason}`);
950
+ }
951
+ const requestCpuMillis = podCpuMillis(resolvePodCpu(options.cpu).request)!;
952
+ const members = (pool as { members?: readonly PodPoolMember[] } | undefined)?.members;
953
+ const preconditions = podLaunchPreconditions({
954
+ kubectl, namespace, member,
955
+ pool: members ? { ready: members.filter((m) => m.capacity > 0).length, capacity: members.reduce((sum, m) => sum + Math.max(0, m.capacity), 0) } : null,
956
+ requestCpuMillis,
957
+ sshProbe: options.sshProbe ?? (options.kubectl ? null : (host) => defaultRemoteRun(host, 'true')),
958
+ });
959
+ log('pod.command-job', 'rightsize-preconditions', { condition, host: targetHost, job: name, context, preconditions });
960
+ const blocked = (['slots', 'ssh', 'admission', 'baseline'] as const).filter((key) => !preconditions[key].ok);
961
+ if (blocked.length) {
962
+ log('pod.command-job', 'rightsize-launch-refused', {
963
+ condition, host: targetHost, job: name, context, blocked, preconditions,
964
+ substrate: 'pod', launched: false, fallback: 'none', hitl: true,
965
+ });
966
+ throw new Error(`pod command: 발사 선행 조건 미충족(${blocked.join(', ')}) — 발사 0 · HITL`);
967
+ }
968
+ const verdict = podCpuRightsize(samples);
969
+ log('pod.command-job', 'cpu-rightsize', {
970
+ condition, host: targetHost, job: name, status: verdict.status, request: verdict.request, reason: verdict.reason, samples: verdict.measured,
971
+ });
972
+ if (verdict.status === 'green') rightsizeCpu = { request: verdict.request };
973
+ }
647
974
  let grokAuth: string | undefined;
648
975
  if (llm === 'grok') {
649
976
  // POD-GROK-VALIDITY-FIT — this Job's deadline is not fitted to the token, so the copy must outlive the whole Job.
@@ -750,12 +1077,13 @@ export async function runPodCommand(options: RunPodCommandOptions): Promise<PodC
750
1077
  const applied = kubectl(['apply', '-f', '-'], JSON.stringify(secret));
751
1078
  if (applied.status !== 0) throw new Error(applied.stderr.trim() || 'pod command: Secret 적용 실패');
752
1079
  }
1080
+ const effectiveCpu = options.cpu ?? rightsizeCpu;
753
1081
  const manifest = podCommandJobManifest({
754
1082
  name, namespace, launch, image: imageRef ?? image,
755
1083
  provenance: options.provenance, provenanceGate: options.provenanceGate,
756
1084
  ...(imageRef ? { imagePullPolicy: 'IfNotPresent' as const } : {}),
757
1085
  repoUrl, command, skills, ...(options.returnLogs ? { returnLogs: true } : {}), ...(llm ? { llm } : {}), ...(options.clone ? { clone: true } : {}),
758
- ...(options.source ? { source: options.source } : {}), ...(options.warmProducer ? { warmFiles: options.warmProducer.files } : {}), ...(hostMirror ? { hostMirror } : {}), ...(bunCache ? { bunCache } : {}), ...(installSlots ? { installSlots } : {}), ...(memoryLimit ? { memoryLimit } : {}), ...(options.cpu ? { cpu: options.cpu } : {}), ...(options.tmpfsSizeLimit ? { tmpfsSizeLimit: options.tmpfsSizeLimit } : {}), deadlineSeconds,
1086
+ ...(options.source ? { source: options.source } : {}), ...(options.warmProducer ? { warmFiles: options.warmProducer.files } : {}), ...(hostMirror ? { hostMirror } : {}), ...(bunCache ? { bunCache } : {}), ...(installSlots ? { installSlots } : {}), ...(memoryLimit ? { memoryLimit } : {}), ...(effectiveCpu ? { cpu: effectiveCpu } : {}), ...(options.tmpfsSizeLimit ? { tmpfsSizeLimit: options.tmpfsSizeLimit } : {}), deadlineSeconds,
759
1087
  ...(options.runId ? { runId: options.runId } : {}),
760
1088
  ...(hostDirsInit ? { hostDirsInit: true } : {}),
761
1089
  });
@@ -0,0 +1,123 @@
1
+ import { createHash } from 'node:crypto';
2
+ import type { UserConfig } from '../../user-config.js';
3
+
4
+ type JsonValue = null | boolean | number | string | JsonValue[] | { [key: string]: JsonValue };
5
+ type JsonObject = { [key: string]: JsonValue };
6
+ type SnapshotSource = 'host-effective' | 'runtime';
7
+ type Allowlist = { readonly [key: string]: true | Allowlist };
8
+
9
+ const ROLE = { provider: true, tier: true, model: true, effort: true } as const;
10
+ /** Adding a setting requires naming its path here. Arbitrary host config never reaches a Pod. */
11
+ const POD_CONFIG_ALLOWLIST = {
12
+ llm: {
13
+ provider: true, model: true, streamIdleTimeoutMs: true,
14
+ codexAccountRotation: true, codexQuotaPolicy: true, codexCreditReserve: true,
15
+ grokWeeklyCapPct: true, fallbackChain: true,
16
+ zaiCodingPlan: { overage: true, maxConcurrent: true },
17
+ openrouter: { fallbackModel: true },
18
+ },
19
+ roleLlm: { implement: ROLE, review: ROLE, research: ROLE, planning: ROLE, audit: ROLE, classify: ROLE },
20
+ harness: { worktreeAddTimeoutSec: true, knowhowChildInjection: true, authorGrade: true,
21
+ exposeGate: true, difficultyPlacement: true, substrate: true, authorOnPod: true },
22
+ tools: { selfImplement: { childInstanceMode: true, observeOnly: true, fabricDecompose: true,
23
+ autoOpenPr: true } },
24
+ loops: { orchestrator: { enabled: true, mode: true, trafficMode: true, idleRequest: true,
25
+ finishGate: true, handToTaskAgent: true, degradationSignal: true, maxDelegatePerTick: true,
26
+ dispatch: { podTarget: true, localLane: true } } },
27
+ } as const satisfies Allowlist;
28
+
29
+ function scalar(value: unknown): JsonValue | undefined {
30
+ if (value === null || typeof value === 'string' || typeof value === 'boolean') return value;
31
+ if (typeof value === 'number') return Number.isFinite(value) ? value : undefined;
32
+ if (Array.isArray(value)) {
33
+ const items = value.map(scalar);
34
+ return items.every((item) => item !== undefined) ? items as JsonValue[] : undefined;
35
+ }
36
+ return undefined;
37
+ }
38
+
39
+ function allowed(value: unknown, schema: true | Allowlist): JsonValue | undefined {
40
+ if (schema === true) return scalar(value);
41
+ if (!value || typeof value !== 'object' || Array.isArray(value)) return undefined;
42
+ const out: JsonObject = {};
43
+ for (const key of Object.keys(schema).sort()) {
44
+ const item = allowed((value as Record<string, unknown>)[key], schema[key]!);
45
+ if (item !== undefined) out[key] = item;
46
+ }
47
+ return out;
48
+ }
49
+
50
+ function objectAt(value: unknown): JsonObject {
51
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as JsonObject : {};
52
+ }
53
+
54
+ function canonical(value: JsonValue): JsonValue {
55
+ if (Array.isArray(value)) return value.map(canonical);
56
+ if (value && typeof value === 'object') {
57
+ const out: JsonObject = {};
58
+ for (const key of Object.keys(value).sort()) {
59
+ const item = canonical(value[key]!);
60
+ if (typeof item !== 'object' || item === null || Array.isArray(item) || Object.keys(item).length > 0) out[key] = item;
61
+ }
62
+ return out;
63
+ }
64
+ return value;
65
+ }
66
+
67
+ function sourcesOf(value: JsonValue, path: string, sources: Record<string, SnapshotSource>): void {
68
+ if (value && typeof value === 'object' && !Array.isArray(value)) {
69
+ for (const key of Object.keys(value).sort()) sourcesOf(value[key]!, path ? `${path}.${key}` : key, sources);
70
+ } else sources[path] = 'host-effective';
71
+ }
72
+
73
+ /** A Pod receives only these effective, non-credential settings. The envelope is evidence;
74
+ * configJson is the plain config consumed by the child. Neither contains host credentials. */
75
+ export function buildPodConfigSnapshot(config: UserConfig, runtime: {
76
+ steps: readonly string[];
77
+ overage: 'stop' | 'balance' | 'openrouter';
78
+ worktreeAddTimeoutSec: number;
79
+ }): {
80
+ version: 1;
81
+ keys: JsonObject & { llm: JsonObject; harness: JsonObject };
82
+ sources: Record<string, SnapshotSource>;
83
+ hash: string;
84
+ envelopeJson: string;
85
+ configJson: string;
86
+ keyCount: number;
87
+ } {
88
+ const host = config as unknown as Record<string, unknown>;
89
+ const selected = objectAt(allowed(host, POD_CONFIG_ALLOWLIST));
90
+ const tools = objectAt(selected.tools);
91
+ const loops = objectAt(selected.loops);
92
+ const keys = {
93
+ harness: objectAt(selected.harness),
94
+ llm: objectAt(selected.llm),
95
+ loops: { orchestrator: objectAt(loops.orchestrator) },
96
+ roleLlm: objectAt(selected.roleLlm),
97
+ tools: { selfImplement: objectAt(tools.selfImplement) },
98
+ };
99
+ const rawDefault = objectAt(host.tools).selfImplement;
100
+ const preference = objectAt(rawDefault).podChildDefault;
101
+ if (preference === 'off' || preference === false) keys.tools.selfImplement.podChildDefault = 'off';
102
+ else if (preference && typeof preference === 'object' && !Array.isArray(preference)) {
103
+ const raw = preference as Record<string, unknown>;
104
+ const provider = typeof raw.provider === 'string' ? raw.provider.trim() : '';
105
+ const model = typeof raw.model === 'string' ? raw.model.trim() : '';
106
+ if (provider) keys.tools.selfImplement.podChildDefault = { provider, ...(model ? { model } : {}) };
107
+ }
108
+ keys.llm.fallbackChain = [...runtime.steps];
109
+ const zai = objectAt(keys.llm.zaiCodingPlan);
110
+ zai.overage = runtime.overage;
111
+ keys.llm.zaiCodingPlan = zai;
112
+ keys.harness.worktreeAddTimeoutSec = runtime.worktreeAddTimeoutSec;
113
+ const canonicalKeys = canonical(keys) as JsonObject & { llm: JsonObject; harness: JsonObject };
114
+ const sources: Record<string, SnapshotSource> = {};
115
+ sourcesOf(canonicalKeys, '', sources);
116
+ sources['llm.fallbackChain'] = 'runtime';
117
+ sources['llm.zaiCodingPlan.overage'] = 'runtime';
118
+ sources['harness.worktreeAddTimeoutSec'] = 'runtime';
119
+ const version = 1 as const;
120
+ const body = { version, keys: canonicalKeys, sources };
121
+ const hash = createHash('sha256').update(JSON.stringify(body)).digest('hex');
122
+ return { ...body, hash, envelopeJson: JSON.stringify({ ...body, hash }), configJson: JSON.stringify(canonicalKeys), keyCount: Object.keys(sources).length };
123
+ }
@@ -42,7 +42,32 @@ function ledgerString(value: unknown): string {
42
42
  return typeof value === 'string' && value.trim().length > 0 ? value : '';
43
43
  }
44
44
 
45
- type PreflightCheck = { reasonCode: string; checkName: string; targetPath?: string };
45
+ export type PreflightCheck = { reasonCode: string; checkName: string; targetPath?: string };
46
+
47
+ /**
48
+ * A Pod failure's structured ledger axes: the rejection's own reason code, check name and *untruncated* target
49
+ * path, kept apart from the human-readable reason text — and, separately from all of them, whether the child's
50
+ * terminal result line was absent at all.
51
+ */
52
+ export interface PodFailureLedgerAxes {
53
+ readonly reasonCode?: string;
54
+ readonly checkName?: string;
55
+ readonly targetPath?: string;
56
+ readonly preflightChecks?: readonly PreflightCheck[];
57
+ /** `true` = the child wrote no terminal result line. Absence is never folded into the rejection reason. */
58
+ readonly noResultLine?: true;
59
+ }
60
+
61
+ /** Keep the failure's structured facts as their own ledger fields; absent facts stay omitted (never `''`). */
62
+ export function podFailureLedgerAxes(exit: PodFailureLedgerAxes): PodFailureLedgerAxes {
63
+ return {
64
+ ...(exit.reasonCode ? { reasonCode: exit.reasonCode } : {}),
65
+ ...(exit.checkName ? { checkName: exit.checkName } : {}),
66
+ ...(exit.targetPath ? { targetPath: exit.targetPath } : {}),
67
+ ...(exit.preflightChecks?.length ? { preflightChecks: exit.preflightChecks } : {}),
68
+ ...(exit.noResultLine ? { noResultLine: true as const } : {}),
69
+ };
70
+ }
46
71
 
47
72
  /** Keep each structured check paired with its own path; legacy blockers retain their name/detail diagnostic. */
48
73
  function preflightBlockerText(blockers: unknown): { error: string; preflightChecks: PreflightCheck[] } {
@@ -100,6 +125,49 @@ export const POD_EXIT_CLASSES = ['oom-killed', 'deadline-exceeded', 'gh-login-fa
100
125
 
101
126
  export type PodExitClass = typeof POD_EXIT_CLASSES[number];
102
127
 
128
+ /** Build the parent-ledger row for a terminal child attempt. A Job can complete
129
+ * successfully while its child result is still unsuccessful (for example,
130
+ * report-deficit after preserving a partial PR); retain both facts together. */
131
+ export function podChildEvidenceLedgerRow(input: {
132
+ job: string;
133
+ childRunId: string;
134
+ state: 'complete' | 'failed' | 'aborted';
135
+ result?: {
136
+ stage?: unknown;
137
+ ok?: unknown;
138
+ failureClassification?: unknown;
139
+ completionDisposition?: unknown;
140
+ error?: unknown;
141
+ childEvidence?: unknown;
142
+ } | null;
143
+ noResultDiagnostic?: string | null;
144
+ noResultLogEvidence?: Record<string, unknown> | null;
145
+ podTermination?: PodTermination | null;
146
+ }): Record<string, unknown> | null {
147
+ const { result } = input;
148
+ const persist = input.state === 'failed' || input.state === 'aborted' || input.noResultLogEvidence != null
149
+ || (input.state === 'complete' && (input.noResultDiagnostic != null || result?.ok === false));
150
+ if (!persist) return null;
151
+
152
+ const childEvidence = input.noResultLogEvidence
153
+ ? { ...(result?.childEvidence && typeof result.childEvidence === 'object' && !Array.isArray(result.childEvidence)
154
+ ? result.childEvidence as Record<string, unknown> : {}), ...input.noResultLogEvidence }
155
+ : result?.childEvidence ?? null;
156
+ const completedButUnsuccessful = input.state === 'complete' && result?.ok === false;
157
+ const childResult = completedButUnsuccessful && result ? Object.fromEntries([
158
+ ['stage', result.stage], ['ok', result.ok], ['failureClassification', result.failureClassification],
159
+ ['completionDisposition', result.completionDisposition], ['error', result.error],
160
+ ].filter(([, value]) => value !== undefined)) : null;
161
+
162
+ return {
163
+ childEvidence,
164
+ childRunId: input.childRunId,
165
+ job: input.job,
166
+ ...(input.podTermination ? { podTermination: input.podTermination } : {}),
167
+ ...(childResult && Object.keys(childResult).length > 0 ? { childResult } : {}),
168
+ };
169
+ }
170
+
103
171
  const isPodBookkeepingLine = (line: string): boolean =>
104
172
  /^(?:ELANOUS_(?:MEM|RUN_LEDGER|USAGE_ROLLUP|POD_)|\[graph\] |\[ask\]\s+\d+\)\s)/u.test(line) || /^(?:at\s+\S|\.\.\.\s+\d+\s+more\b|cleanup\s+(?:complete|done|finished)\b)/iu.test(line);
105
173
 
@@ -341,7 +409,7 @@ export interface PodTermination {
341
409
  }
342
410
 
343
411
  /** FailureTarget can precede Failed at the deadline. Read both in the same Job snapshot. */
344
- export const POD_TERMINATION_JOB_JSONPATH = '{.status.conditions[?(@.type=="Failed")].reason}{"|"}{.status.conditions[?(@.type=="FailureTarget")].reason}{"\\t"}{.spec.activeDeadlineSeconds}{"\\t"}{.metadata.uid}';
412
+ export const POD_TERMINATION_JOB_JSONPATH = '{.status.conditions[?(@.type=="Failed")].reason}{"|"}{.status.conditions[?(@.type=="FailureTarget")].reason}{"\\t"}{.spec.activeDeadlineSeconds}{"\\t"}{.metadata.uid}{"\\t"}{.metadata.creationTimestamp}{"\\t"}{.status.completionTime}';
345
413
 
346
414
  export function podJobConditionReason(value: string | undefined): string {
347
415
  const [failed, target] = (value ?? '').split('|');