elanous 0.2.23 → 0.2.25

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 (688) 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/chunks/1027.a0f04663d24c2779.js +1 -0
  4. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
  8. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
  10. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1454-37fd16f479f5554a.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
  16. package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
  17. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
  19. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
  20. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
  25. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
  28. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
  30. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
  31. package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
  32. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
  36. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
  41. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
  47. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
  51. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
  53. package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
  61. package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
  67. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
  72. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
  74. package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
  77. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
  79. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
  87. package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
  88. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
  96. package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
  98. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
  99. package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
  100. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
  103. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
  105. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
  106. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
  107. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
  111. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
  113. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
  119. package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
  120. package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
  121. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/approvals/page-9360b1285b2a346e.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f08f6529d09ffae1.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/board/page-f000d54d258f9ef6.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-ad3bd8084048bee4.js → page-b12149c51f7d04b1.js} +1 -1
  126. package/apps/pwa/out/_next/static/chunks/app/bots/page-22f674e7e4c2c9d5.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8888733e40cea6d1.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/chat/page-9717ec6964b92276.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/consult/page-44eaad486bc98a45.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/control/page-97fa6cf3d34c7eb9.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/decisions/page-305cd294e754906e.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/design-check/{page-a648bc464c9dc754.js → page-dea4b795741126fd.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/editor/page-35e05d7450461a67.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/exec/page-45889e7070d11126.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/field/page-16a2e893f83ae4d0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/inside/page-b2638013c0bf7dfd.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/intake/page-56888bc744e08dac.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/layout-c44f93a41167536f.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/live/page-952c6ceec6d9de38.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live-run/page-6d0202af568f4c63.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/loops/page-1b810474507f3702.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/market/page-74366ae2693a7d95.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-4fb6fc34e20c07b7.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/morning/page-e9502921f4f01b1f.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/not-found-b6169ea2f09cf287.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6a14333d1b1b3967.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8c91a9a66c9ec90a.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-48fb31810693c357.js → page-4e634c5b98fd4e93.js} +1 -1
  150. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ed3070d637850548.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-cb154acadb025414.js → page-b9cc8a10bc6078b4.js} +1 -1
  152. package/apps/pwa/out/_next/static/chunks/app/page-3d3fc73dd187ed52.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/reflection/page-128458c8d86fbb5f.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-9c04dac0831c2bbb.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/sessions/page-cf0c2b0183991d09.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-04de9ca6d52a3893.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/page-62527677bbc2fdc4.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9a2e09c4a311764c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/page-bfeb35d69e8b24bb.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/share/page-89cb33bced824e4a.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b008aff96be56654.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/tasks/page-814394dcbae789b1.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/term/page-6a87325c87f09dd2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/today/page-6445ac4cbb8dd869.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/trace/page-852170303c6cd755.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/vault/page-087ceeb975ef272b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-97c7361cc2a19319.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/page-20162174b77f96cf.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8c6901833f897496.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-05a4b2c9b91034aa.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
  175. package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
  182. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +1 -0
  183. package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_buildManifest.js +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
  278. package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
  279. package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
  280. package/catalog/providers/openrouter.yaml +2 -0
  281. package/graphs/implement-loop.yaml +31 -0
  282. package/graphs/ops/harness-gc.yaml +17 -0
  283. package/graphs/ops/recipes.yaml +3 -0
  284. package/graphs/overlays/README.md +1 -1
  285. package/graphs/overlays/stop-heal-ladder.yaml +105 -0
  286. package/graphs/release/release-loop.yaml +5 -5
  287. package/graphs/steward/recipes.yaml +4 -0
  288. package/graphs/steward/steward.yaml +10 -1
  289. package/package.json +1 -1
  290. package/scripts/add-api-key.sh +1 -1
  291. package/scripts/bench-report.ts +46 -1
  292. package/scripts/ci-typecheck-changed.ts +73 -14
  293. package/scripts/fleet/bedrock-pod-secret.ts +122 -0
  294. package/scripts/fleet/node-setup-linux.sh +97 -0
  295. package/scripts/fleet/node-setup.sh +11 -0
  296. package/scripts/fleet/zai-pod-secret.ts +86 -0
  297. package/scripts/land-global-checks.ts +3 -0
  298. package/scripts/measure-log-diet-2.ts +213 -0
  299. package/scripts/measure-tsc-affected-roots.ts +289 -0
  300. package/scripts/release-loop/auto-approve-node.ts +6 -0
  301. package/scripts/release-loop/gate-closure.ts +286 -0
  302. package/scripts/release-loop/gate-executor.ts +28 -0
  303. package/scripts/release-loop/gate-node.ts +333 -37
  304. package/scripts/release-loop/gate-partial.ts +34 -6
  305. package/scripts/release-loop/ops-upgrade-node.ts +63 -42
  306. package/scripts/release-loop/publish-node.ts +6 -0
  307. package/scripts/release-loop/resume-release.ts +46 -13
  308. package/scripts/release-loop/resume.ts +110 -4
  309. package/scripts/release-loop/unattended-release.ts +22 -7
  310. package/scripts/tsc-baseline-cache.ts +172 -0
  311. package/scripts/usage-rollup.ts +72 -6
  312. package/scripts/ux-sim.ts +30 -1
  313. package/skills/youtube-master/scripts/main.ts +4 -1
  314. package/skills/youtube-master/src/obsidian.ts +9 -0
  315. package/src/agent/run-context.ts +10 -0
  316. package/src/agent-mission/driver.ts +18 -3
  317. package/src/agent-mission/resource-ladder.ts +8 -3
  318. package/src/agent-mission/review-loop.ts +8 -2
  319. package/src/agent-substrate/acp-implementer.ts +146 -0
  320. package/src/agent-substrate/pr-reviewer.ts +60 -13
  321. package/src/agent-substrate/self-review-cli.ts +170 -15
  322. package/src/autopilot/mission-critique.ts +18 -5
  323. package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
  324. package/src/autopilot/mission-trace.ts +12 -1
  325. package/src/autopilot/system-lookback-run.ts +16 -10
  326. package/src/bench/bench.ts +183 -0
  327. package/src/budget/cost-tier-advisor.ts +91 -0
  328. package/src/budget/fetchers/grok.ts +15 -5
  329. package/src/budget/llm-cost.ts +37 -5
  330. package/src/budget/shadow-arms.ts +77 -0
  331. package/src/budget/types.ts +10 -2
  332. package/src/budget/unified-usage.ts +256 -10
  333. package/src/cli/bench-cli.ts +34 -0
  334. package/src/cli/doctor-cli.ts +21 -0
  335. package/src/cli/friendly-errors.ts +113 -0
  336. package/src/cli/guardian-cli.ts +26 -1
  337. package/src/cli/image-cli.ts +101 -0
  338. package/src/cli/intake-cli.ts +3 -1
  339. package/src/cli/log-event-names.ts +4 -0
  340. package/src/cli/memory-cli.ts +182 -0
  341. package/src/cli/model-watch-cli.ts +4 -1
  342. package/src/cli/pr-cli.ts +62 -5
  343. package/src/cli/pr-land-overlap-evidence.ts +160 -12
  344. package/src/cli/pr-land-pod-shadow.ts +54 -0
  345. package/src/cli/release-cli.ts +27 -16
  346. package/src/cli/release-run-if-ready.ts +11 -0
  347. package/src/cli/resource-cli.ts +48 -0
  348. package/src/cli/retro-cli.ts +12 -3
  349. package/src/cli/rfc-status.ts +52 -2
  350. package/src/cli/seat-requests-cli.ts +25 -0
  351. package/src/cli/self-update.ts +104 -0
  352. package/src/cli/tasks-cli.ts +139 -10
  353. package/src/cli/usage-cli.ts +93 -8
  354. package/src/compact/verify-probe.ts +23 -3
  355. package/src/context-card/index.ts +50 -0
  356. package/src/control/control-status.ts +30 -1
  357. package/src/core-turn/run-goal-loop.ts +5 -4
  358. package/src/dashboard/ad-run-setup-bindings.ts +279 -0
  359. package/src/dashboard/index.ts +18 -276
  360. package/src/dashboard/slash-runtime/dashboard-handlers.ts +4 -138
  361. package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
  362. package/src/dashboard/stale-install-check.ts +11 -0
  363. package/src/debug/log-diet.ts +53 -10
  364. package/src/debug/log.ts +19 -1
  365. package/src/domains/morning-essential.ts +18 -3
  366. package/src/domains/release-tool.ts +43 -0
  367. package/src/error-report/report.ts +21 -4
  368. package/src/execution-loop/launch-gate.ts +158 -2
  369. package/src/fleet/host-doctor.ts +375 -0
  370. package/src/github/pr-labels.ts +1 -0
  371. package/src/goals/judge.ts +20 -6
  372. package/src/graph-runner/graph-cli.ts +42 -1
  373. package/src/graph-runner/runner.ts +176 -11
  374. package/src/graph-wizard/archetypes.ts +14 -8
  375. package/src/graph-wizard/generate.ts +77 -1
  376. package/src/grok/usage.ts +23 -2
  377. package/src/grok.ts +13 -7
  378. package/src/grounding/ref-index.ts +253 -0
  379. package/src/harness/dispatch-backpressure.ts +10 -2
  380. package/src/harness/harness-clean.ts +199 -78
  381. package/src/harness/harness-cli-command.ts +176 -52
  382. package/src/harness/harness-gc.ts +331 -0
  383. package/src/harness/harness-stop.ts +82 -10
  384. package/src/harness/harness-substrate-default.ts +142 -7
  385. package/src/harness/launch-registry.ts +6 -0
  386. package/src/harness/worktree-branch-prefix.ts +9 -0
  387. package/src/hq/fence.ts +187 -0
  388. package/src/hq/seats.ts +38 -22
  389. package/src/images/image-ledger.ts +179 -0
  390. package/src/index.ts +110 -186
  391. package/src/instance/child-scope.ts +32 -1
  392. package/src/instance/dev-project.ts +133 -0
  393. package/src/instance/resolve.ts +24 -0
  394. package/src/instance/spawn-elanous.ts +45 -0
  395. package/src/intake-plane/collect-github.ts +7 -2
  396. package/src/intake-plane/lens.ts +46 -4
  397. package/src/intake-plane/ref-prefetch.ts +110 -0
  398. package/src/intake-plane/requirement-funnel.ts +53 -1
  399. package/src/intelligence-map/catalog-feed.ts +119 -0
  400. package/src/intelligence-map/model-catalog.ts +72 -0
  401. package/src/intelligence-map/model-watch-intake.ts +40 -0
  402. package/src/intelligence-map/model-watch-mission.ts +14 -1
  403. package/src/llm/bedrock-eventstream.ts +215 -0
  404. package/src/llm/bedrock-provider.ts +114 -41
  405. package/src/llm/bedrock.ts +174 -28
  406. package/src/llm/open-weight-discipline.ts +21 -0
  407. package/src/llm/openrouter-byok-cost.ts +96 -0
  408. package/src/llm/openrouter-deepseek.ts +151 -0
  409. package/src/llm/openrouter-upstream-pins.config.ts +25 -0
  410. package/src/llm/zai-coding-plan.ts +700 -0
  411. package/src/llm.ts +91 -24
  412. package/src/loops/checker.ts +148 -9
  413. package/src/loops/orchestrator/resync-shadow.ts +34 -7
  414. package/src/maturity/feature-maturity.ts +3 -3
  415. package/src/model-tier/llm-tier-map.ts +9 -5
  416. package/src/models/prompts.ts +2 -1
  417. package/src/mss/logging/log-store.ts +58 -11
  418. package/src/nexus/api/http-server.ts +22 -0
  419. package/src/nexus/api/missions.ts +73 -2
  420. package/src/nexus/api/ops-api.ts +18 -0
  421. package/src/nexus/index.ts +7 -75
  422. package/src/nexus/tools-kind.ts +78 -0
  423. package/src/oauth/codex-account-rotation.ts +43 -3
  424. package/src/oauth/codex-account-store.ts +339 -27
  425. package/src/oauth/codex-quota-policy.ts +33 -4
  426. package/src/oauth/fallback-chain.ts +53 -15
  427. package/src/onboarding/first-run.ts +37 -18
  428. package/src/onboarding/web-first.ts +20 -2
  429. package/src/ops/machine-heartbeat.ts +185 -0
  430. package/src/ops/overview-cache.ts +175 -0
  431. package/src/ops/overview.ts +8 -0
  432. package/src/preview/terminal.ts +15 -5
  433. package/src/project/project-store.ts +20 -0
  434. package/src/prompt-cache/openai.ts +3 -0
  435. package/src/prompt-cache/types.ts +5 -0
  436. package/src/prompt-enhance/enhance.ts +23 -0
  437. package/src/release-loop/auto-start.ts +7 -5
  438. package/src/release-loop/checklist.ts +11 -1
  439. package/src/release-loop/gate-shards.ts +4 -0
  440. package/src/release-loop/light-rc.ts +84 -13
  441. package/src/release-loop/merged-pr-checklist.ts +35 -5
  442. package/src/release-loop/placement.ts +16 -1
  443. package/src/release-loop/rehearsal.ts +1 -1
  444. package/src/requirements/requirement-ledger.ts +536 -0
  445. package/src/retro/daily.ts +5 -5
  446. package/src/seat-loop/duty-ledger.ts +64 -0
  447. package/src/seat-loop/seat-loop.ts +32 -10
  448. package/src/self-dev/decompose.ts +37 -3
  449. package/src/self-dev/dev-cli.ts +44 -10
  450. package/src/self-dev/dev-pipeline.ts +39 -9
  451. package/src/self-dev/draft-residue.ts +27 -5
  452. package/src/self-dev/draft-sweep.ts +151 -0
  453. package/src/self-dev/fabric-decompose-adapter.ts +9 -2
  454. package/src/self-dev/graph-journey-route.ts +6 -0
  455. package/src/self-dev/orchestrate-cli.ts +25 -3
  456. package/src/self-dev/orchestrate.ts +41 -6
  457. package/src/self-dev/run-supervisor.ts +218 -15
  458. package/src/self-dev/run-types.ts +13 -0
  459. package/src/self-dev/supervisor-verdict-edges.ts +1 -0
  460. package/src/self-implement/budget-gate.ts +53 -13
  461. package/src/self-implement/child-context-composition.ts +139 -0
  462. package/src/self-implement/child-llm-preference.ts +13 -5
  463. package/src/self-implement/claude-acp-implement.ts +67 -0
  464. package/src/self-implement/flex-signals.ts +59 -0
  465. package/src/self-implement/frozen-merges.ts +8 -3
  466. package/src/self-implement/gate-cli.ts +29 -10
  467. package/src/self-implement/gate-remote.ts +4 -1
  468. package/src/self-implement/goal-author-decompose.ts +10 -2
  469. package/src/self-implement/goal-author.ts +36 -11
  470. package/src/self-implement/goal-new-paths.ts +42 -0
  471. package/src/self-implement/graph-overlay-condition.ts +28 -0
  472. package/src/self-implement/graph-overlay-yaml.ts +41 -7
  473. package/src/self-implement/graph-templates.ts +33 -1
  474. package/src/self-implement/graph-yaml.ts +56 -0
  475. package/src/self-implement/heal-intake.ts +5 -1
  476. package/src/self-implement/host-regate.ts +124 -30
  477. package/src/self-implement/importer-test-index.ts +3 -1
  478. package/src/self-implement/l8-merge-queue.ts +80 -2
  479. package/src/self-implement/merge-train.ts +19 -0
  480. package/src/self-implement/off-diff-evidence.ts +40 -1
  481. package/src/self-implement/orchestrator.ts +230 -32
  482. package/src/self-implement/premise-review.ts +159 -0
  483. package/src/self-implement/regate-detail.ts +79 -0
  484. package/src/self-implement/review-deferred-to-host.ts +21 -0
  485. package/src/self-implement/rework-budget-judgment.ts +23 -3
  486. package/src/self-implement/running-runs.ts +75 -5
  487. package/src/self-implement/scope-adjacency.ts +23 -0
  488. package/src/self-implement/seams.ts +89 -8
  489. package/src/self-implement/self-implement-cli.ts +9 -4
  490. package/src/self-implement/stop-autoheal.ts +69 -2
  491. package/src/session-runtime/retry-policy.ts +2 -1
  492. package/src/skills/tools/agent.ts +16 -1
  493. package/src/skills/tools/persistent-grounding.ts +11 -1
  494. package/src/skills/tools/shell.ts +33 -1
  495. package/src/steward/launch.ts +5 -4
  496. package/src/steward/rejudge-tick.ts +142 -0
  497. package/src/steward/triage-budget.ts +62 -0
  498. package/src/steward/triage.ts +83 -22
  499. package/src/task-agent/actions.ts +62 -5
  500. package/src/task-agent/board.ts +92 -3
  501. package/src/task-agent/card-evidence.ts +88 -1
  502. package/src/task-agent/completion-evidence.ts +5 -0
  503. package/src/task-agent/cover.ts +166 -3
  504. package/src/task-agent/judge.ts +16 -0
  505. package/src/task-agent/land-order-ledger.ts +95 -0
  506. package/src/task-agent/live-move-history.ts +87 -1
  507. package/src/task-agent/live-moves.ts +350 -20
  508. package/src/task-agent/parent-host.ts +27 -3
  509. package/src/task-agent/rejudge-on-head.ts +223 -24
  510. package/src/task-agent/review-prior-fix.ts +146 -0
  511. package/src/task-agent/review-result-capture.ts +3 -1
  512. package/src/task-agent/run-adopt.ts +136 -0
  513. package/src/task-agent/shadow.ts +65 -9
  514. package/src/task-agent/task-hand.ts +57 -7
  515. package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
  516. package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
  517. package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
  518. package/src/task-orchestrator/surfaces/pod-child-providers.ts +14 -1
  519. package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
  520. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +79 -6
  521. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
  522. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -5
  523. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +11 -5
  524. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
  525. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -4
  526. package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
  527. package/src/task-orchestrator/surfaces/self-implement-pod.ts +432 -35
  528. package/src/task-orchestrator/surfaces/self-implement.ts +19 -1
  529. package/src/typecheck-ratchet.ts +1 -0
  530. package/src/user-config.ts +69 -15
  531. package/src/ux-sim/fault-cred-expiry.ts +100 -0
  532. package/src/ux-sim/fault-pod-death.ts +74 -0
  533. package/src/ux-sim/fault-pool-cap.ts +81 -0
  534. package/src/version/packed-revision.json +1 -1
  535. package/src/webclone/qa-table.ts +22 -0
  536. package/src/workflow-runtime/triggers/registry.ts +59 -0
  537. package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
  538. package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
  539. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
  540. package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
  542. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
  543. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
  553. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
  554. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
  556. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
  563. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
  567. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
  579. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
  587. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
  591. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
  594. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
  595. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
  599. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
  604. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
  605. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
  606. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
  609. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
  616. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
  622. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
  623. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
  625. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
  627. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
  628. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
  633. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/consult/page-6168a7c43e6ef8f5.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
  687. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +0 -1
  688. /package/apps/pwa/out/_next/static/{rfkMm4movqkqMebBrCXiR → dRS6lEhSRRBr1abbzp7fJ}/_ssgManifest.js +0 -0
@@ -0,0 +1,136 @@
1
+ import { existsSync, readFileSync, realpathSync } from 'node:fs';
2
+ import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
3
+ import { debug } from '../debug/log.js';
4
+ import { launchBindingRunIds, launchRegistryDir, readLaunchBinding } from '../harness/launch-registry.js';
5
+ import { launchStampFromLedger } from '../harness/launch-stamp.js';
6
+ import { normalizeRunId } from '../harness/harness-space.js';
7
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
8
+ import { loadRunLedger, runLedgerDir } from '../self-implement/run-ledger.js';
9
+ import { TASK_SEATS, updateTaskCard, type TaskCard, type TaskSeat } from './task-hand.js';
10
+
11
+ export interface RunBirth {
12
+ runId: string;
13
+ goalPath?: string;
14
+ cwd: string;
15
+ runsDir?: string;
16
+ env: Readonly<Record<string, string | undefined>>;
17
+ }
18
+
19
+ export interface RunAdoptDeps {
20
+ /** 카드 상태 파일(시험 주입). 없으면 우주 뿌리(`instanceRoot`) 아래 `task-agent-actions.json` = `taskAgentStatePath()`. */
21
+ statePath?: string;
22
+ /** 우주 뿌리 해석 seam — 기본 `effectiveInstanceRoot()`(state·runsDir 를 만드는 같은 공용 해석). */
23
+ instanceRoot?: () => string;
24
+ registryDir?: string;
25
+ knownChecklistIds?: ReadonlySet<string>;
26
+ now?: () => Date;
27
+ log?: (category: string, event: string, data: Record<string, unknown>) => void;
28
+ }
29
+
30
+ export type RunAdoptSkipReason = 'handed' | 'already-carded' | 'pod-child' | 'other-universe' | 'universe-mismatch';
31
+ export type RunAdoptResult = { card: TaskCard; adopted: true } | { adopted: false; reason: RunAdoptSkipReason };
32
+
33
+ function seatFromGoal(path: string | undefined): TaskSeat | undefined {
34
+ const seat = path?.replaceAll('\\', '/').match(/\/(?:seat-state|seats)\/(OP|TC|MK|UX)\//)?.[1];
35
+ return seat as TaskSeat | undefined;
36
+ }
37
+
38
+ function goalText(path: string | undefined, cwd: string): string {
39
+ if (!path) return '';
40
+ try {
41
+ const fullPath = isAbsolute(path) ? path : resolve(cwd, path);
42
+ return readFileSync(fullPath, 'utf8');
43
+ } catch { return ''; }
44
+ }
45
+
46
+ function checklistFromText(text: string, known: ReadonlySet<string>): string | undefined {
47
+ const explicit = /칸\s+([A-Za-z0-9][A-Za-z0-9_-]*)/.exec(text)?.[1];
48
+ if (explicit) return explicit;
49
+ const title = /(?:^|\n)제목:\s*([A-Za-z0-9][A-Za-z0-9_-]*?)-\d+\s+—/m.exec(text)?.[1];
50
+ return title && known.has(title) ? title : undefined;
51
+ }
52
+
53
+ /** 경로 정규화 — 심볼릭 링크(`/var`↔`/private/var` 등)·상대·후행 슬래시를 같은 값으로. 없는 꼬리는 있는 조상의 실경로에 붙인다. */
54
+ function canonicalPath(path: string): string {
55
+ const absolute = resolve(path);
56
+ let head = absolute;
57
+ const tail: string[] = [];
58
+ while (!existsSync(head)) {
59
+ const parent = dirname(head);
60
+ if (parent === head) return absolute;
61
+ tail.unshift(basename(head));
62
+ head = parent;
63
+ }
64
+ try { return join(realpathSync(head), ...tail); } catch { return absolute; }
65
+ }
66
+
67
+ /** Adopt only a run belonging to this universe. The universe root is resolved once (`effectiveInstanceRoot()` unless a
68
+ * state path is injected) and both the card state file and the run's `runsDir` are compared against it after canonical
69
+ * path resolution. The runId check and write share updateTaskCard's lock.
70
+ * A birth without `runsDir` cannot prove its universe and is skipped as `other-universe` (conservative); a `runsDir` that is
71
+ * not `<root>/self-dev-runs` is skipped as `universe-mismatch` with both paths observed — never silently. */
72
+ export function adoptRunCard(birth: RunBirth, deps: RunAdoptDeps = {}): RunAdoptResult {
73
+ const root = deps.statePath ? dirname(deps.statePath) : (deps.instanceRoot ?? effectiveInstanceRoot)();
74
+ const statePath = deps.statePath ?? join(root, 'task-agent-actions.json');
75
+ const log = deps.log ?? ((category: string, event: string, data: Record<string, unknown>) => debug.log(category, event, data));
76
+ const skip = (reason: RunAdoptSkipReason, extra: Record<string, unknown> = {}): RunAdoptResult => {
77
+ log('task-agent', 'run-adopt-skipped', { runId: birth.runId, reason, ...extra });
78
+ return { adopted: false, reason };
79
+ };
80
+ if (birth.env.ELANOUS_TASK_CARD_ID) return skip('handed');
81
+ if (birth.env.ELANOUS_POD_NAME) return skip('pod-child');
82
+ if (!birth.runsDir) return skip('other-universe', { statePath, runsDir: null });
83
+ const expectedRunsDir = canonicalPath(join(root, 'self-dev-runs'));
84
+ const runsDir = canonicalPath(birth.runsDir);
85
+ if (runsDir !== expectedRunsDir) return skip('universe-mismatch', { statePath, runsDir: birth.runsDir, expectedRunsDir, canonicalRunsDir: runsDir });
86
+ if (!birth.runId || birth.runId !== normalizeRunId(birth.runId) || birth.runId.includes(sep)) throw new Error(`invalid runId: ${birth.runId}`);
87
+ const text = goalText(birth.goalPath, birth.cwd);
88
+ const firstLine = text.split(/\r?\n/).find(line => line.trim())?.trim() ?? `harness run ${birth.runId}`;
89
+ let stamp = launchStampFromLedger(null);
90
+ try { stamp = launchStampFromLedger(loadRunLedger(birth.runId, runLedgerDir(root))); } catch { /* unreadable stamp is unknown */ }
91
+ const origin = stamp.entrance;
92
+ const actor = stamp.actor;
93
+ const seat = TASK_SEATS.find(candidate => candidate === actor) ?? seatFromGoal(birth.goalPath);
94
+ const checklistId = checklistFromText(text, deps.knownChecklistIds ?? new Set());
95
+ const id = `ta-${birth.runId}`;
96
+ let adopted = false;
97
+ const card = updateTaskCard(statePath, id, (current, tasks) => {
98
+ if (current || Object.values(tasks).some(candidate => candidate.runId === birth.runId)) return undefined;
99
+ adopted = true;
100
+ const at = (deps.now ?? (() => new Date()))().toISOString();
101
+ return {
102
+ id, text: firstLine, status: 'launched', runId: birth.runId,
103
+ ...(birth.goalPath ? { goal: birth.goalPath } : {}),
104
+ ...(seat ? { seat } : {}),
105
+ ...(checklistId ? { checklistId } : {}),
106
+ createdAt: at, history: [{ at, event: 'adopted', detail: origin }],
107
+ };
108
+ });
109
+ if (!adopted || !card) return skip('already-carded');
110
+ log('task-agent', 'run-adopted', { card: card.id, runId: birth.runId, origin, seat: seat ?? null, checklistId: checklistId ?? null });
111
+ return { card, adopted: true };
112
+ }
113
+
114
+ /** Explicit backfill for old launch bindings (`elanous tasks adopt-runs`); not part of the launch-time path.
115
+ * The binding's launch-time `podName`/`taskCardId` stand in for the env, so Pod children and handed runs are skipped.
116
+ * Bindings written before those fields existed carry no marker — the host registry is per-host `$TMPDIR`, and a Pod
117
+ * child writes its binding inside its Pod, so such legacy rows are host-launched runs. */
118
+ export function adoptUncardedRuns(deps: RunAdoptDeps = {}): { scanned: number; adopted: number; skipped: Partial<Record<RunAdoptSkipReason, number>> } {
119
+ const dir = deps.registryDir ?? launchRegistryDir();
120
+ const skipped: Partial<Record<RunAdoptSkipReason, number>> = {};
121
+ let scanned = 0;
122
+ let adopted = 0;
123
+ for (const runId of launchBindingRunIds(dir)) {
124
+ scanned++;
125
+ const binding = readLaunchBinding(runId, dir);
126
+ if (!binding?.runsDir) {
127
+ skipped['other-universe'] = (skipped['other-universe'] ?? 0) + 1;
128
+ (deps.log ?? ((category, event, data) => debug.log(category, event, data)))('task-agent', 'run-adopt-skipped', { runId, reason: 'other-universe' });
129
+ continue;
130
+ }
131
+ const result = adoptRunCard({ runId, cwd: binding.cwd, goalPath: binding.goalPath, runsDir: binding.runsDir, env: { ELANOUS_POD_NAME: binding.podName, ELANOUS_TASK_CARD_ID: binding.taskCardId } }, deps);
132
+ if (result.adopted) adopted++;
133
+ else skipped[result.reason] = (skipped[result.reason] ?? 0) + 1;
134
+ }
135
+ return { scanned, adopted, skipped };
136
+ }
@@ -17,6 +17,7 @@ import type { SupervisorJobResult, SupervisorStopReason } from '../self-dev/run-
17
17
  import { executeNextAction, type DeliveryKind, type NextAction } from './actions.js';
18
18
  import { judgeNextMove, type TaskJudgeInput, type TaskJudgement } from './judge.js';
19
19
  import { HARNESS_RUN_ID_ENV } from '../harness/harness-space.js';
20
+ import { collectWiringEvidence, type WiringEvidenceDeps } from './card-evidence.js';
20
21
  import { recordLiveMoveHistory } from './live-move-history.js';
21
22
  import { capturedSelfReview, captureReviewResults, hasCapturedPass } from './review-result-capture.js';
22
23
  import { configuredTaskAgentLiveMoves, defaultPrHead, executeLiveGreenProposal, executeLiveLand, executeLiveReview, type LiveMoveDeps, type LiveMoveResult, type TaskAgentLiveMove } from './live-moves.js';
@@ -58,10 +59,30 @@ export interface TaskAgentShadowDeps {
58
59
  liveMoves?: ReadonlySet<TaskAgentLiveMove>;
59
60
  /** live 수의 부작용(리뷰 띄우기·PR 머리 조회·상태 파일) — 시험은 주입한다. */
60
61
  live?: LiveMoveDeps;
62
+ /** 카드 조회 상태 파일(시험 주입 · 운영 파일을 건드리지 않게). 기본 = `live.statePath` ⊕ `taskAgentStatePath()`. */
63
+ statePath?: string;
64
+ /** TA-WIRING-CHECK — 배선 근거 수집 의존(시험 주입 · 기본 = gh pr diff 한 번 ⊕ 카드 런 원장). */
65
+ wiring?: Omit<WiringEvidenceDeps, 'card'>;
61
66
  /** Process env for the launched-run id (`ELANOUS_RUN_ID`) — test seam; default process.env. */
62
67
  env?: NodeJS.ProcessEnv;
63
68
  }
64
69
 
70
+ /** 카드 조회 상태 파일 — 조회 경로 전부가 같은 파일을 본다. */
71
+ function cardStatePath(deps: TaskAgentShadowDeps): string {
72
+ return deps.statePath ?? deps.live?.statePath ?? taskAgentStatePath();
73
+ }
74
+
75
+ /** 카드 «원장»(기록·회수 대상) — 카드를 읽은 파일과 같다. 주입한 카드 리더(`readCard`)만 있으면 `live.statePath` 가 없을 때 모른다. */
76
+ function cardLedgerPath(deps: TaskAgentShadowDeps): string | undefined {
77
+ return deps.readCard ? deps.live?.statePath : cardStatePath(deps);
78
+ }
79
+
80
+ /** live 수의 의존 — 실행부가 적는 원장(리뷰 요청·착지 시도)도 카드를 읽은 파일과 같게 맞춘다. */
81
+ function liveMoveDeps(deps: TaskAgentShadowDeps): LiveMoveDeps {
82
+ const ledger = cardLedgerPath(deps);
83
+ return { ...(deps.log ? { log: deps.log } : {}), ...deps.live, ...(ledger ? { statePath: ledger } : {}) };
84
+ }
85
+
65
86
  /** 파일 산출물로 전달(elanous-out)하는 종결 종류 — 그 밖의 code-pr 밖 종류는 확인 증거를 판단부에서 기다린다. */
66
87
  const DELIVERY_KINDS: ReadonlySet<CompletionKind> = new Set<CompletionKind>(['research-report', 'artifact', 'content']);
67
88
  function isDeliveryKind(kind: CompletionKind | undefined): kind is DeliveryKind {
@@ -156,7 +177,7 @@ function shadowCompletion(card: TaskCard | undefined, lookupFailed: boolean): Co
156
177
  export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, deps: TaskAgentShadowDeps = {}): Promise<TaskAgentShadowMove> {
157
178
  // TA-REVIEW-RESULT-CAPTURE — 판단 «전»에 지난 live review 의 결과 파일을 회수한다(카드 원장을 아는 때만 · 던지지 않는다).
158
179
  // 대기 중인 요청이 없으면 아무것도 쓰지 않는다(결과 파일 없는 카드의 동작은 종전과 같다).
159
- const reviewLedger = deps.live?.statePath ?? (deps.readCard ? undefined : taskAgentStatePath());
180
+ const reviewLedger = cardLedgerPath(deps);
160
181
  if (reviewLedger) {
161
182
  try { captureReviewResults(reviewLedger, { ...(deps.live?.now ? { now: deps.live.now } : {}), ...(deps.log ? { log: deps.log } : {}) }); } catch (error) {
162
183
  // fail-soft — 판단은 계속하되 원인은 남긴다.
@@ -167,12 +188,14 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
167
188
  let card: TaskCard | undefined;
168
189
  let cardLookupFailed = false;
169
190
  try {
170
- card = successful ? (deps.readCard ?? readTaskCard)(successful.taskId) : undefined;
191
+ card = successful ? (deps.readCard ? deps.readCard(successful.taskId) : readTaskCard(successful.taskId, cardStatePath(deps))) : undefined;
171
192
  if (!card && successful && !deps.readCard) {
172
- const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(taskAgentStatePath()).tasks ?? {};
193
+ const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(cardStatePath(deps)).tasks ?? {};
173
194
  const matches = Object.values(tasks).filter(candidate => candidate.status === 'launched' && candidate.text === successful.feature);
174
195
  if (matches.length === 1) card = matches[0];
175
196
  }
197
+ // TA-OWN-ALL-RUNS — 런 소유 카드: 입력 runId ⊕ 상속 ELANOUS_RUN_ID(Pod 자식의 부모 런) 중 카드 runId 와 «정확히» 같은 것만.
198
+ if (!card && !deps.readCard) card = runCardFor(input.runId, deps);
176
199
  } catch {
177
200
  // Card lookup is optional; preserve the original PR judgement when unavailable — but mark the completion kind as unmeasured.
178
201
  cardLookupFailed = true;
@@ -282,7 +305,7 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
282
305
  ...(prResult.branch ? { branch: prResult.branch } : {}),
283
306
  ...(prResult.prUrl ? { prUrl: prResult.prUrl } : {}),
284
307
  } } : {}),
285
- }, { ...(deps.log ? { log: deps.log } : {}), ...deps.live });
308
+ }, liveMoveDeps(deps));
286
309
  } else if (liveKind === 'propose-land') {
287
310
  liveMove = await executeLiveLand(boundCard, prResult?.prNumber,
288
311
  { runId: input.runId, cycleId: input.cycleId, review: selfReview,
@@ -292,12 +315,12 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
292
315
  ...(prResult.branch ? { branch: prResult.branch } : {}),
293
316
  ...(prResult.prUrl ? { prUrl: prResult.prUrl } : {}),
294
317
  } } : {}),
295
- }, { ...(deps.log ? { log: deps.log } : {}), ...deps.live });
318
+ }, liveMoveDeps(deps));
296
319
  } else {
297
320
  const evidence: Record<string, string> = {};
298
321
  if (boundCard && !delivery && judgeInput.prState === 'MERGED' && prResult) evidence[boundCard.id] = `#${prResult.prNumber}`;
299
322
  else if (boundCard && delivery && deps.mode === 'live' && executorResult === 'done') evidence[boundCard.id] = join(delivery.projectTarget, 'elanous-out', boundCard.id);
300
- liveMove = executeLiveGreenProposal(boundCard, evidence, { ...(deps.log ? { log: deps.log } : {}), ...deps.live });
323
+ liveMove = executeLiveGreenProposal(boundCard, evidence, liveMoveDeps(deps));
301
324
  }
302
325
  }
303
326
  // 판단한 수마다 live/shadow 를 남긴다 — OP 가 «오판 건수»·«그림자 일치율»을 카드·수 종류로 잰다.
@@ -305,6 +328,15 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
305
328
  ...move, completion: shadowCompletion(card, cardLookupFailed), card: liveCard?.id ?? null, live, liveExecuted: liveMove?.executed ?? false, ...(liveMove ? { liveOk: liveMove.ok } : {}),
306
329
  ...(reviewFromCapture ? { reviewSource: 'captured-review-result' } : {}),
307
330
  });
331
+ // TA-WIRING-CHECK — 병합 PR 은 판단한 «뒤» 배선 근거를 관측만 한다(move 불변 · 실패는 unknown 으로 남기고 던지지 않는다).
332
+ if (judgeInput.prState === 'MERGED' && typeof judgeInput.pr === 'number' && !delivery && liveCard) {
333
+ try {
334
+ const wiring = await collectWiringEvidence(judgeInput.pr, { ...deps.wiring, card: liveCard });
335
+ (deps.log ?? ((category, event, data) => debug.log(category, event, data)))('task-agent', 'wiring-shadow', {
336
+ card: liveCard.id, pr: judgeInput.pr, required: wiring.required, liveRunRecorded: wiring.liveRunRecorded, unknown: wiring.unknown,
337
+ });
338
+ } catch { /* fail-soft — 관측일 뿐 판단을 막지 않는다 */ }
339
+ }
308
340
  // TA-LIVE-MOVE-CARD-HISTORY — live-move 수(review·propose-green·propose-land)는 실행이든 그림자든 그 카드 history 에 한 줄.
309
341
  // 결정·실행이 끝난 «뒤»에 덧붙이기만 한다(반환값·관측 무변경) · 실패는 관측만(live-move 를 막지 않는다).
310
342
  if (liveKind !== null) recordLiveMoveOnCard({
@@ -315,6 +347,29 @@ export async function recordTaskAgentShadowMove(input: TaskAgentShadowInput, dep
315
347
  return liveMove ? { ...move, liveMove } : move;
316
348
  }
317
349
 
350
+ /**
351
+ * 런 id 폴백 — 입력 runId(슈퍼바이저 · Pod 면 자식 런) → 상속 `ELANOUS_RUN_ID`(발사기가 넘긴 부모 런) 순으로,
352
+ * 카드 runId 와 정확히 같고 그 카드가 하나뿐일 때만 쓴다. 못 찾으면 추측하지 않고 이유 한 줄을 남긴다(조용한 미스 0).
353
+ */
354
+ function runCardFor(runId: string | null | undefined, deps: TaskAgentShadowDeps): TaskCard | undefined {
355
+ const own = runId?.trim() || undefined;
356
+ const inherited = (deps.env ?? process.env)[HARNESS_RUN_ID_ENV]?.trim() || undefined;
357
+ if (!own && !inherited) return undefined;
358
+ const tasks = Object.values(readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(cardStatePath(deps)).tasks ?? {});
359
+ const tried: Array<{ source: 'run' | 'env'; id: string; bound: number }> = [];
360
+ for (const [source, id] of [['run', own], ['env', inherited]] as const) {
361
+ if (!id || tried.some((entry) => entry.id === id)) continue;
362
+ const bound = tasks.filter((candidate) => candidate.runId === id);
363
+ if (bound.length === 1) return bound[0];
364
+ tried.push({ source, id, bound: bound.length });
365
+ }
366
+ const reason = tried.map((entry) => `${entry.source === 'env' ? `env ${HARNESS_RUN_ID_ENV}` : 'runId'} ${entry.id}: ${entry.bound === 0 ? 'no card has this runId' : `${entry.bound} cards share this runId (ambiguous)`}`).join(' · ');
367
+ try {
368
+ (deps.log ?? ((c: string, e: string, d: Record<string, unknown>) => debug.log(c, e, d)))('task-agent', 'run-card-fallback-missed', { runId: own ?? null, inheritedRunId: inherited ?? null, tried, reason });
369
+ } catch { /* fail-soft */ }
370
+ return undefined;
371
+ }
372
+
318
373
  /**
319
374
  * 카드 history 에 live-move 한 줄 — 상태 파일은 카드를 읽은 곳과 같아야 한다: 주입한 경로(`live.statePath`) 또는
320
375
  * 기본 리더를 썼을 때의 기본 경로. 주입한 카드 리더(`readCard`)만 있고 경로가 없으면 그 카드의 원장을 모른다 — 적지 않는다.
@@ -334,7 +389,7 @@ function recordLiveMoveOnCard(
334
389
  };
335
390
  try {
336
391
  if (!move.card) { fail('no task card bound to this move'); return; }
337
- const statePath = deps.live?.statePath ?? (deps.readCard ? undefined : taskAgentStatePath());
392
+ const statePath = cardLedgerPath(deps);
338
393
  if (!statePath) { fail('card ledger unknown (injected readCard without live.statePath)'); return; }
339
394
  const card = move.card;
340
395
  // live 인데 실행부 결과가 없으면 «무엇이 일어났는지» 모른다 — 줄을 지어내지 않고 이유를 남긴다.
@@ -358,11 +413,11 @@ function recordLiveMoveOnCard(
358
413
  function liveCardFor(results: readonly SupervisorJobResult[], deps: TaskAgentShadowDeps, runId?: string | null): TaskCard | undefined {
359
414
  try {
360
415
  for (const result of results) {
361
- const found = deps.readCard ? deps.readCard(result.taskId) : readTaskCard(result.taskId, deps.live?.statePath);
416
+ const found = deps.readCard ? deps.readCard(result.taskId) : readTaskCard(result.taskId, cardStatePath(deps));
362
417
  if (found) return found;
363
418
  }
364
419
  if (deps.readCard) return undefined;
365
- const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(deps.live?.statePath ?? taskAgentStatePath()).tasks ?? {};
420
+ const tasks = readTaskAgentState<{ tasks?: Record<string, TaskCard> }>(cardStatePath(deps)).tasks ?? {};
366
421
  // TA-LIVE-LAND-2 — a Pod run's results carry the orchestrator task id, not the card id, and its feature may be the
367
422
  // authored goal rather than the handed sentence. `tasks hand --live` launched this process with ELANOUS_RUN_ID = the
368
423
  // card's runId (TA-CARD-RUN-LINK); the supervisor's runId may be the Pod child's. Either id bound to exactly one card is the match.
@@ -373,6 +428,7 @@ function liveCardFor(results: readonly SupervisorJobResult[], deps: TaskAgentSha
373
428
  }
374
429
  const features = new Set(results.map((result) => result.feature));
375
430
  const matches = Object.values(tasks).filter(candidate => candidate.status === 'launched' && features.has(candidate.text));
431
+ // runId ⊕ 상속 ELANOUS_RUN_ID 는 위에서 이미 봤다(판단부의 runCardFor 가 미스 이유를 남긴다).
376
432
  return matches.length === 1 ? matches[0] : undefined;
377
433
  } catch { return undefined; }
378
434
  }
@@ -16,6 +16,8 @@ import { HARNESS_RUN_ID_ENV, mintRunId, normalizeRunId } from '../harness/harnes
16
16
  import { debug } from '../debug/log.js';
17
17
  import { effectiveInstanceRoot } from '../instance/resolve.js';
18
18
  import { withFileLockSync } from '../storage/file-lock.js';
19
+ import { checkCompletionEvidence, deliverableReceiptEvidence } from './completion-evidence.js';
20
+ import { judgeNextMove } from './judge.js';
19
21
 
20
22
  export interface ResolveHandTextDeps {
21
23
  cwd: string;
@@ -83,7 +85,7 @@ export function taskCardLabelContext(card: Pick<TaskCard, 'id'>): TaskCardLabelC
83
85
  * 과제 종결 종류(RFC-loop-agent-map §A4b③) — 비면 code-pr(PR 병합)로 읽는다.
84
86
  * code-pr 밖의 종류는 «확인 증거»(`judge.ts` TaskJudgeInput.evidence)로 종결한다 — 증거를 만드는 일은 DEFAULT-HANDS 몫.
85
87
  */
86
- export const COMPLETION_KINDS = ['code-pr', 'artifact', 'research-report', 'ops-action', 'content', 'watch-brief', 'decision-support'] as const;
88
+ export const COMPLETION_KINDS = ['code-pr', 'artifact', 'research-report', 'ops-action', 'content', 'watch-brief', 'decision-support', 'deliverable'] as const;
87
89
  export type CompletionKind = typeof COMPLETION_KINDS[number];
88
90
 
89
91
  /**
@@ -92,6 +94,8 @@ export type CompletionKind = typeof COMPLETION_KINDS[number];
92
94
  */
93
95
  export interface TaskCardEvent {
94
96
  at: string; event: string; detail?: string; runId?: string; pr?: number;
97
+ /** `closed-by-hand` 줄만 — 닫은 사유 · 닫은 자리(`closeTaskCard`). */
98
+ reason?: string; by?: string;
95
99
  kind?: string; executed?: boolean; ok?: boolean; executorResult?: 'shadow' | 'live'; head?: string; effect?: string;
96
100
  /** TA-REVIEW-RESULT-CAPTURE — review live-move 줄 · 결과 줄(`live-move-result`)의 결과 파일 경로. */
97
101
  resultPath?: string;
@@ -102,6 +106,8 @@ export interface TaskCardEvent {
102
106
  export const LIVE_MOVE_HISTORY_EVENT = 'live-move';
103
107
  /** TA-REVIEW-RESULT-CAPTURE — 떼어 띄운 리뷰의 결과(또는 «결과 없음») 줄 — live-move 줄처럼 상태 사유 판정에서 뺀다. */
104
108
  export const LIVE_MOVE_RESULT_EVENT = 'live-move-result';
109
+ /** HAND-MOVE-LEDGER — 자리가 손으로 마무리한 수 줄(`recordHandMove`) — 관측 기록이라 live-move 줄처럼 상태 사유 판정에서 뺀다. */
110
+ export const HAND_MOVE_HISTORY_EVENT = 'hand-move';
105
111
  export interface TaskCardMove { kind: 'launch' | 'wait'; command?: string[]; reason: string }
106
112
  export interface TaskCard {
107
113
  id: string;
@@ -159,9 +165,17 @@ export interface TaskCard {
159
165
  * TA-REJUDGE-ON-HEAD — 런 멈춤 «뒤» 머리마다 한 번 돌린 호스트 재게이트(병합 없음 · 떼어 띄움). 결과는 `resultPath` 파일에서
160
166
  * 다음 틱이 회수해 passed·status·baseCommit·detail 을 채운다(비어 있으면 아직 도는 중 · 없는 칸을 «통과»로 읽지 않는다).
161
167
  */
162
- regates?: Array<{ pr: number; head: string; at: string; resultPath?: string; passed?: boolean; status?: string; baseCommit?: string; detail?: string }>;
163
- /** Live land attempts, claimed before invocation, once per PR head even if the command fails. */
164
- landAttempts?: Array<{ pr: number; head: string; at: string; ok?: boolean; detail?: string }>;
168
+ regates?: Array<{ pr: number; head: string; at: string; resultPath?: string; passed?: boolean; status?: string; baseCommit?: string; detail?: string;
169
+ /** REJUDGE base-stale — 같은 머리를 새 base 위에서 다시 잰 재게이트면, land 가 낡았다고 거절한 앞 재게이트의 base(멱등 키 = 머리 ⊕ 이 base). */
170
+ staleBase?: string }>;
171
+ /**
172
+ * Live land attempts, claimed before invocation, once per PR head even if the command fails.
173
+ * TA-LAND-RETRY-ON-INFRA — a failed attempt carries `class`/`reason`: `infra` (TA-side, allow-listed) leaves one more attempt on
174
+ * the same head (`LAND_ATTEMPTS_PER_HEAD_ON_INFRA`); `judgement` · unknown reason · no class (older record) closes the head.
175
+ * REJUDGE base-stale — `base-stale` (overlap evidence gate base went stale with PR-file overlap) waits for a re-gate on a new base;
176
+ * only after that re-gate passes is the attempt consumed (`openLandAttempts`) and the same head may land once more.
177
+ */
178
+ landAttempts?: Array<{ pr: number; head: string; at: string; ok?: boolean; detail?: string; class?: 'infra' | 'judgement' | 'base-stale'; reason?: string }>;
165
179
  /** TA-LIVE-LAND-2 — `tasks hand --ta-land`: this card's run leaves the merge to the task agent (propose-land). */
166
180
  taLand?: true;
167
181
  /** TASKS-HAND-CHILD-LLM — `tasks hand --child-llm <provider>/<model> [--child-llm-effort <level>]` → 발사 인자 `--child-llm-provider/-model/-effort`. */
@@ -279,6 +293,16 @@ export function readTaskCard(id: string, path = taskAgentStatePath()): TaskCard
279
293
  return readState(path).tasks?.[id];
280
294
  }
281
295
 
296
+ export const CLOSED_BY_HAND_EVENT = 'closed-by-hand';
297
+
298
+ /** 카드를 손으로 닫는다 — 상태를 `failed` 로 두고 history 에 한 줄(`closed-by-hand`)을 남긴다. 이미 손으로 닫은 카드는 그대로 돌려준다(멱등). */
299
+ export function closeTaskCard(card: TaskCard, input: { reason: string; by: string; at: string }): TaskCard {
300
+ const reason = input.reason.trim();
301
+ if (!reason) throw new Error('닫는 사유(reason)가 비어 있다');
302
+ if (card.status === 'failed' && card.history.some((item) => item.event === CLOSED_BY_HAND_EVENT)) return card;
303
+ return { ...card, status: 'failed', history: [...card.history, { at: input.at, event: CLOSED_BY_HAND_EVENT, kind: CLOSED_BY_HAND_EVENT, detail: reason, reason, by: input.by }] };
304
+ }
305
+
282
306
  /** 첫 수의 elanous 인자(진입점·--config-dir 앞붙임은 launcher 몫). */
283
307
  export function launchArgs(card: Pick<TaskCard, 'text' | 'seat' | 'childLlm'>): string[] {
284
308
  const child = card.childLlm
@@ -298,8 +322,8 @@ export function nextMoveFor(card: TaskCard, landed?: ReadonlySet<string>): TaskC
298
322
  if (card.status !== 'launched' && unmet.length > 0) return { kind: 'wait', reason: `after ${unmet.join(', ')}${landed ? '' : ' · 착지 미확인'}` };
299
323
  if (card.status === 'handed') return { kind: 'launch', command: launchArgs(card), reason: '넘겨받은 과제 — 첫 발사' };
300
324
  if (card.status === 'launch-failed') return { kind: 'launch', command: launchArgs(card), reason: '직전 발사 실패 — 다시 발사' };
301
- // live-move 줄(관측 기록)은 실패 사유가 아니다 — 그 줄을 뺀 마지막 칸이 사유다(live-move 줄 없는 카드는 종전과 같다).
302
- if (card.status === 'failed') return { kind: 'wait', reason: card.history.filter((item) => item.event !== LIVE_MOVE_HISTORY_EVENT && item.event !== LIVE_MOVE_RESULT_EVENT).at(-1)?.detail ?? '런 실패 — PR·수확 가지 없음' };
325
+ // live-move·hand-move 줄(관측 기록)은 실패 사유가 아니다 — 그 줄을 뺀 마지막 칸이 사유다(live-move 줄 없는 카드는 종전과 같다).
326
+ if (card.status === 'failed') return { kind: 'wait', reason: card.history.filter((item) => item.event !== LIVE_MOVE_HISTORY_EVENT && item.event !== LIVE_MOVE_RESULT_EVENT && item.event !== HAND_MOVE_HISTORY_EVENT).at(-1)?.detail ?? '런 실패 — PR·수확 가지 없음' };
303
327
  return { kind: 'wait', reason: '발사됨 — 런 멈춤을 슈퍼바이저 그림자 판단(task-agent.shadow-move)이 받는다' };
304
328
  }
305
329
 
@@ -370,6 +394,29 @@ export class TaskLaunchError extends Error {
370
394
 
371
395
  export interface HandTaskResult { card: TaskCard; move: TaskCardMove; mode: 'shadow' | 'live'; launched: boolean; cwd?: string }
372
396
 
397
+ /** Dispatch evidence for a handed deliverable card; unlike handTask, this never launches work. */
398
+ export function dispatchDeliverableCompletion(id: string, input: { ref: string; receipt?: boolean }, path: string, now: () => Date = () => new Date()): boolean {
399
+ const card = readTaskCard(id, path);
400
+ if (card?.completion !== 'deliverable' || !card.project?.target || card.pr !== undefined || card.status === 'failed' || card.status === 'launch-failed') return false;
401
+ const evidence = checkCompletionEvidence('deliverable', { dir: card.project.target, ...input });
402
+ if (judgeNextMove({ completion: card.completion, evidence }).move !== 'propose-green') {
403
+ try { debug.log('task-agent', 'deliverable-rejected', { taskId: id, ref: input.ref, missing: evidence.missing }); } catch { /* fail-soft */ }
404
+ return false;
405
+ }
406
+ const receiptEvidence = deliverableReceiptEvidence(evidence.ref);
407
+ const at = now().toISOString();
408
+ let closed = false;
409
+ updateTaskCard(path, id, (current) => {
410
+ if (current?.completion !== 'deliverable' || current.pr !== undefined || current.greenProposal || !current.project || current.project.target !== card.project?.target || current.status === 'failed' || current.status === 'launch-failed') return undefined;
411
+ const fresh = checkCompletionEvidence('deliverable', { dir: current.project.target, ...input });
412
+ if (judgeNextMove({ completion: current.completion, evidence: fresh }).move !== 'propose-green') return undefined;
413
+ closed = true;
414
+ return { ...current, greenProposal: { at, checklistId: current.checklistId ?? null, evidence: { [id]: receiptEvidence } } };
415
+ });
416
+ try { debug.log('task-agent', closed ? 'deliverable-closed' : 'deliverable-rejected', { taskId: id, ref: evidence.ref, ...(closed ? {} : { missing: ['already-proposed-or-changed'] }) }); } catch { /* fail-soft */ }
417
+ return closed;
418
+ }
419
+
373
420
  export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
374
421
  const text = opts.text.trim();
375
422
  if (!text) throw new Error('과제 한 줄이 비어 있다');
@@ -440,7 +487,10 @@ export async function handTask(opts: HandTaskOptions): Promise<HandTaskResult> {
440
487
  if (!opts.launcher) throw new Error('--live 인데 launcher 가 없다');
441
488
  const runId = mintRunId();
442
489
  const launchId = `tl-${randomBytes(6).toString('hex')}`;
443
- const context: TaskLaunchContext = { runId, launchId, env: { [HARNESS_RUN_ID_ENV]: runId, ...(card.taLand ? { [TA_LAND_ENV]: '1' } : {}) }, cardLabelContext: taskCardLabelContext(card) };
490
+ const context: TaskLaunchContext = { runId, launchId, env: { [HARNESS_RUN_ID_ENV]: runId, ELANOUS_TASK_CARD_ID: card.id,
491
+ ...(card.checklistId ? { ELANOUS_POD_SLOT_ID: card.checklistId } : {}),
492
+ ...(card.seat ? { ELANOUS_POD_OWNER_KIND: 'seat', ELANOUS_POD_OWNER_ID: card.seat } : {}),
493
+ ...(card.taLand ? { [TA_LAND_ENV]: '1' } : {}) }, cardLabelContext: taskCardLabelContext(card) };
444
494
  let receipt: void | TaskLaunchReceipt;
445
495
  try {
446
496
  receipt = await opts.launcher(move.command!, project?.target, context);
@@ -5,14 +5,15 @@
5
5
  // «모른다»라서 뒤로 보내되 빼지 않는다(못 읽었다고 갈 곳을 없애지 않는다 — 회전 규칙과 같다).
6
6
  // ⛔ `--pod-account` 를 명시하면 브로커를 쓰지 않는다 — 사람의 의도가 이긴다.
7
7
 
8
- import { codexAccountThresholdPercent, type RotationCandidate } from '../../oauth/codex-account-rotation.js';
8
+ import { CODEX_CREDIT_RESERVE_DEFAULT, codexAccountThresholdPercent, creditCandidatesByBalance, type RotationCandidate } from '../../oauth/codex-account-rotation.js';
9
+ import { debug } from '../../debug/log.js';
9
10
 
10
11
  export const POD_ACCOUNT_EXCLUDE_AT_PERCENT = 95;
11
12
 
12
13
  export interface PodAccountPlan { usable: string[]; excluded: Array<{ name: string; why: string }>; /** 크레딧으로 쓰는 계정(구독 잔량 0 · 대표 허가) — 로그에 «크레딧» 으로 보이게. */ creditAccounts?: string[] }
13
14
 
14
15
  export type PodProviderPlan =
15
- | { provider: 'openai-codex'; accounts: string[]; excluded: PodAccountPlan['excluded']; grokSubscriptionEligible: boolean; creditAccounts?: string[] }
16
+ | { provider: 'openai-codex'; accounts: string[]; excluded: PodAccountPlan['excluded']; grokSubscriptionEligible: boolean; creditAccounts?: string[]; /** CODEX-CREDITS-STEP — 체인 마지막 칸으로 크레딧에 왔다. */ codexCreditsStep?: true; /** 그 칸에 온 이유(관측). */ skipped?: string[] }
16
17
  | { provider: 'grok'; excluded: PodAccountPlan['excluded']; grokSubscriptionEligible: boolean }
17
18
  | { provider: null; reasons: string[]; grokSubscriptionEligible: boolean };
18
19
 
@@ -26,14 +27,39 @@ export function planPodProvider(input: {
26
27
  thresholdPercentByAccount?: Readonly<Record<string, unknown>>;
27
28
  /** 대표 크레딧 허가(`llm.codexCreditsAllowed`) — 구독 잔량 계정이 없으면 찬 계정을 크레딧으로 쓴다. */
28
29
  creditsAllowed?: boolean;
30
+ /** SUBSCRIPTION-EXHAUST-REROUTE — `llm.codexCreditReserve`. 잔액이 «알려져» 이 값 이하인 계정은 크레딧으로 쓰지 않는다. */
31
+ creditReserve?: number;
32
+ /** CODEX-CREDITS-STEP — `llm.fallbackChain` 에 `codex-credits` 칸이 있고 정책이 폴백을 허용한다(호출자가 확정). */
33
+ codexCreditsStep?: boolean;
34
+ /** grok «잔량» — `exhausted` 일 때만 grok 을 건너뛴다(「모른다」는 종전대로 grok · 돈을 쓰는 쪽으로 기울지 않는다). */
35
+ grokQuota?: 'usable' | 'exhausted' | 'unknown';
29
36
  }): PodProviderPlan {
30
37
  const accounts = planPodAccounts(input.codexCandidates, {
31
38
  excludeAt: input.excludeAt,
32
39
  thresholdPercentByAccount: input.thresholdPercentByAccount,
33
40
  creditsAllowed: input.creditsAllowed,
41
+ ...(input.creditReserve !== undefined ? { creditReserve: input.creditReserve } : {}),
34
42
  });
35
43
  if (accounts.usable.length) return { provider: 'openai-codex', accounts: accounts.usable, excluded: accounts.excluded, grokSubscriptionEligible: input.grokSubscription, ...(accounts.creditAccounts ? { creditAccounts: accounts.creditAccounts } : {}) };
36
- if (input.grokSubscription || (input.grokApiKey && input.grokApiKeyOptIn)) return { provider: 'grok', excluded: accounts.excluded, grokSubscriptionEligible: input.grokSubscription };
44
+ const grokEligible = input.grokSubscription || (input.grokApiKey && input.grokApiKeyOptIn);
45
+ const grokSkippedAsExhausted = input.codexCreditsStep === true && input.grokQuota === 'exhausted';
46
+ if (grokEligible && !grokSkippedAsExhausted) return { provider: 'grok', excluded: accounts.excluded, grokSubscriptionEligible: input.grokSubscription };
47
+ if (input.codexCreditsStep === true) {
48
+ // 체인 마지막 칸 — 크레딧 잔액이 «확인된» 계정만, 많은 순(모르면 안 쓴다 · 돈이라 fail-closed).
49
+ const credit = creditCandidatesByBalance(input.codexCandidates, input.creditReserve ?? CODEX_CREDIT_RESERVE_DEFAULT).map((c) => c.name); // 회전 수집기와 같은 자
50
+ if (credit.length > 0) {
51
+ return {
52
+ // 구독 기준 제외 사유는 진단용으로 남긴다(계정 선택은 credit 순서가 정한다).
53
+ provider: 'openai-codex', accounts: credit, excluded: accounts.excluded, creditAccounts: credit, codexCreditsStep: true,
54
+ grokSubscriptionEligible: input.grokSubscription,
55
+ skipped: ['codex-rotate:no-candidate', grokEligible ? 'grok:grok-exhausted' : 'grok:grok-unavailable'],
56
+ };
57
+ }
58
+ // 칸에 «닿았지만» 잔액 확인된 계정이 없다 — 실패한 도달도 남긴다.
59
+ try { debug.log('self-implement.pod', 'codex-credits-step', { outcome: 'skipped', why: 'codex-credits-unavailable', grokEligible }); } catch { /* observation is fail-soft */ }
60
+ // 크레딧도 못 쓰면 종전 그대로 — 소진 신호가 있어도 grok 으로(새로 막지 않는다).
61
+ if (grokEligible) return { provider: 'grok', excluded: accounts.excluded, grokSubscriptionEligible: input.grokSubscription };
62
+ }
37
63
  return {
38
64
  provider: null,
39
65
  grokSubscriptionEligible: false,
@@ -50,10 +76,11 @@ export function planPodAccounts(
50
76
  thresholdPercentByAccount?: Readonly<Record<string, unknown>>;
51
77
  excludeAt?: number;
52
78
  creditsAllowed?: boolean;
79
+ creditReserve?: number;
53
80
  } = {},
54
81
  ): PodAccountPlan {
55
- const { thresholdPercentByAccount, excludeAt = POD_ACCOUNT_EXCLUDE_AT_PERCENT, creditsAllowed = false } =
56
- typeof options === 'number' ? { excludeAt: options } : options;
82
+ const { thresholdPercentByAccount, excludeAt = POD_ACCOUNT_EXCLUDE_AT_PERCENT, creditsAllowed = false, creditReserve } =
83
+ typeof options === 'number' ? { excludeAt: options } as { thresholdPercentByAccount?: undefined; excludeAt: number; creditsAllowed?: boolean; creditReserve?: number } : options;
57
84
  const excluded: PodAccountPlan['excluded'] = [];
58
85
  const known: RotationCandidate[] = [];
59
86
  const unknown: RotationCandidate[] = [];
@@ -70,11 +97,17 @@ export function planPodAccounts(
70
97
  const usable = [...known, ...unknown].map((c) => c.name);
71
98
  // 대표 크레딧 허가: 구독 잔량이 남은 계정이 «하나도» 없을 때만 찬 계정을 크레딧으로 쓴다(사용률 낮은 순) — 잔량 계정이 있으면 그쪽이 먼저다.
72
99
  if (usable.length === 0 && creditsAllowed) {
100
+ // SUBSCRIPTION-EXHAUST-REROUTE — 잔액이 «알려져» 예비분 이하인 계정은 크레딧 후보가 아니다(모르면 종전대로 남긴다).
101
+ const reserve = typeof creditReserve === 'number' && Number.isFinite(creditReserve) && creditReserve >= 0 ? creditReserve : undefined;
73
102
  const credit = candidates
74
103
  .filter((c) => excluded.some((e) => e.name === c.name))
104
+ .filter((c) => reserve === undefined || typeof c.creditBalance !== 'number' || c.creditBalance > reserve)
75
105
  // 크레딧 잔액이 많은 계정부터(09-28 · 한 계정 크레딧만 타던 것) — 잔액을 모르면 사용률 낮은 순.
76
106
  .sort((a, b) => ((b.creditBalance ?? -1) - (a.creditBalance ?? -1)) || ((a.usedPercent ?? 100) - (b.usedPercent ?? 100)) || a.name.localeCompare(b.name))
77
107
  .map((c) => c.name);
108
+ if (credit.length === 0 && reserve !== undefined && excluded.length > 0) {
109
+ return { usable, excluded: excluded.map((e) => ({ ...e, why: `${e.why} · credits ≤ reserve ${reserve}` })) };
110
+ }
78
111
  return { usable: credit, excluded: [], creditAccounts: credit };
79
112
  }
80
113
  return { usable, excluded };
@@ -0,0 +1,74 @@
1
+ /**
2
+ * BEDROCK-PROVIDER ② (0.2.24 · MK) — bedrock 자식 Pod 의 자격·리전·이그레스.
3
+ *
4
+ * 대표 10-10 승인: AWS 자격은 «bedrock Pod 에만» `secretKeyRef` 로 싣는다 · 값은 어디에도 내보내지 않는다 ·
5
+ * 다른 Pod 의 매니페스트는 바이트 하나 안 바뀐다.
6
+ *
7
+ * ⭐ 자격은 «작업별 creds Secret» 이 아니라 클러스터에 미리 둔 «이름 있는 Secret»(`elanous-bedrock-aws`)에서 온다.
8
+ * 호스트는 그 Secret 의 «키 이름»만 읽는다(값은 kubectl 밖으로 안 나온다) — 만들기는 `scripts/fleet/bedrock-pod-secret.ts`(사람 승인 뒤).
9
+ * ⛔ SSO 캐시는 Pod 안에서 못 쓴다 — Pod 용 정적 키(또는 베어러 토큰)가 그 Secret 에 있어야 한다.
10
+ * ⛔ Secret 이 없거나 자격 키가 모자라면 «발사 전에» 거부한다(아무것도 apply 하지 않는다 · fail-closed).
11
+ * ⛔ 이 모듈은 가볍게 둔다(무거운 import 0).
12
+ */
13
+
14
+ /** 클러스터(풀 노드마다)·네임스페이스(Pod 와 같은 곳)에 미리 둔 Secret 이름. */
15
+ export const BEDROCK_POD_SECRET_NAME = 'elanous-bedrock-aws';
16
+
17
+ /** bedrock Pod 만 다는 이그레스 라벨 — `docker/h1/policy-bedrock.yaml` 이 이 라벨에만 443 을 연다. */
18
+ export const BEDROCK_POD_EGRESS_LABEL = 'elanous.egress/bedrock';
19
+
20
+ /** Secret 에서 Pod env 로 «이름 그대로» 싣는 키(있는 것만). 값은 secretKeyRef 로만 간다. */
21
+ export const BEDROCK_POD_SECRET_KEYS = ['AWS_ACCESS_KEY_ID', 'AWS_SECRET_ACCESS_KEY', 'AWS_SESSION_TOKEN', 'AWS_BEARER_TOKEN_BEDROCK', 'AWS_REGION'] as const;
22
+ export type BedrockPodSecretKey = typeof BEDROCK_POD_SECRET_KEYS[number];
23
+
24
+ /** Secret 의 «키 이름»만 뽑는 kubectl 인자 — go-template 이 값을 찍지 않는다. */
25
+ export function bedrockPodSecretKeyNamesArgs(namespace: string, secretName = BEDROCK_POD_SECRET_NAME): string[] {
26
+ return ['-n', namespace, 'get', 'secret', secretName, '-o', 'go-template={{range $k, $v := .data}}{{$k}}{{"\\n"}}{{end}}'];
27
+ }
28
+
29
+ export interface BedrockPodSpec {
30
+ secretName: string;
31
+ /** Secret 에 «있는» 자격 키 이름(값 아님). */
32
+ keys: BedrockPodSecretKey[];
33
+ /** 리전 — Secret 의 `AWS_REGION` 키가 있으면 그것(secretKeyRef), 없으면 호스트가 푼 리전(평문 · 비밀 아님). */
34
+ region: { from: 'secret' } | { from: 'host'; value: string };
35
+ }
36
+
37
+ export type BedrockPodCheck = { ok: true; spec: BedrockPodSpec } | { ok: false; reason: string };
38
+
39
+ type KubectlLike = (args: string[], stdin?: string) => { status: number | null; stdout: string; stderr: string };
40
+
41
+ const AWS_REGION_SHAPE = /^[a-z]{2,4}(?:-[a-z]+)+-\d{1,2}$/;
42
+
43
+ /**
44
+ * 발사 «전» 판정 — Secret 이 있나 · 자격 키가 갖춰졌나 · 리전이 풀리나. 어느 하나라도 아니면 거부 사유.
45
+ * ⛔ 사유 문면에 값·kubectl stderr 원문을 싣지 않는다(이름·고정 문면만).
46
+ */
47
+ export function checkBedrockPodSecret(kubectl: KubectlLike, namespace: string, hostRegion: string | undefined, secretName = BEDROCK_POD_SECRET_NAME): BedrockPodCheck {
48
+ const fix = `scripts/fleet/bedrock-pod-secret.ts 로 ${namespace}/${secretName} 을 만든다(승인 뒤)`;
49
+ const got = kubectl(bedrockPodSecretKeyNamesArgs(namespace, secretName));
50
+ if (got.status !== 0) {
51
+ return { ok: false, reason: /not ?found/i.test(got.stderr) ? `pod: bedrock 자격 Secret 없음 — ${namespace}/${secretName} · ${fix}` : `pod: bedrock 자격 Secret 을 못 읽었다 — ${namespace}/${secretName} (kubectl rc=${got.status}) · 발사하지 않는다` };
52
+ }
53
+ const present = new Set(got.stdout.split('\n').map((line) => line.trim()).filter(Boolean));
54
+ const keys = BEDROCK_POD_SECRET_KEYS.filter((key) => present.has(key));
55
+ const staticPair = keys.includes('AWS_ACCESS_KEY_ID') && keys.includes('AWS_SECRET_ACCESS_KEY');
56
+ const bearer = keys.includes('AWS_BEARER_TOKEN_BEDROCK');
57
+ if (!staticPair && !bearer) {
58
+ return { ok: false, reason: `pod: bedrock 자격 Secret ${namespace}/${secretName} 에 자격 키가 없다 — AWS_ACCESS_KEY_ID ⊕ AWS_SECRET_ACCESS_KEY 또는 AWS_BEARER_TOKEN_BEDROCK 필요 · ${fix}` };
59
+ }
60
+ const host = hostRegion?.trim();
61
+ const region: BedrockPodSpec['region'] | undefined = keys.includes('AWS_REGION') ? { from: 'secret' }
62
+ : host && AWS_REGION_SHAPE.test(host) ? { from: 'host', value: host } : undefined;
63
+ if (!region) return { ok: false, reason: `pod: bedrock 리전 없음 — Secret ${namespace}/${secretName} 의 AWS_REGION 또는 호스트 AWS_REGION(·~/.aws/config) 필요` };
64
+ return { ok: true, spec: { secretName, keys: keys.filter((key) => key !== 'AWS_REGION' || region.from === 'secret'), region } };
65
+ }
66
+
67
+ /** bedrock 자식 컨테이너 env — 자격은 secretKeyRef, 리전은 secretKeyRef 또는 평문. IMDS 탐색은 끈다(Pod 에 인스턴스 역할 없음). */
68
+ export function bedrockPodEnv(spec: BedrockPodSpec): Array<Record<string, unknown>> {
69
+ return [
70
+ ...spec.keys.map((key) => ({ name: key, valueFrom: { secretKeyRef: { name: spec.secretName, key } } })),
71
+ ...(spec.region.from === 'host' ? [{ name: 'AWS_REGION', value: spec.region.value }] : []),
72
+ { name: 'AWS_EC2_METADATA_DISABLED', value: 'true' },
73
+ ];
74
+ }