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
@@ -2,8 +2,9 @@ import { createHash, randomUUID } from 'node:crypto';
2
2
  import { execFile } from 'node:child_process';
3
3
  import { existsSync, linkSync, lstatSync, mkdirSync, readFileSync, readdirSync, readlinkSync, realpathSync, renameSync, rmdirSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync } from 'node:fs';
4
4
  import { dirname, join, resolve, sep } from 'node:path';
5
+ import { fileURLToPath } from 'node:url';
5
6
  import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
6
- import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
7
+ import { getElanousConfigDir, getElanousConfigDirOverride } from '../elanous-config-dir.js';
7
8
  import { debug } from '../debug/log.js';
8
9
  import { observeModelInputTokens } from '../harness/model-input-observation.js';
9
10
  import { publishInsideEvent } from '../nexus/api/inside-events.js';
@@ -22,7 +23,7 @@ import { psProcessStartMs, START_TOLERANCE_MS } from '../harness/harness-stop.js
22
23
  import { executeBashNode } from '../workflow-runtime/nodes/bash.js';
23
24
  import { interpolate } from '../workflow-runtime/variables.js';
24
25
  import type { BashNode, NodeExecContext, WorkflowDeps } from '../workflow-runtime/types.js';
25
- import { releaseResumeAcceptedRegressions, releaseResumeWaiver, type AcceptedRegression } from '../../scripts/release-loop/resume.js';
26
+ import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeWaiver, type AcceptedRegression, type GateExecutorOverride } from '../../scripts/release-loop/resume.js';
26
27
 
27
28
  type BashRun = WorkflowDeps['runBash'];
28
29
 
@@ -40,7 +41,7 @@ export interface GraphRunState {
40
41
  /** startedAt/endedAt (ISO) and seconds are written when the node runs; ledgers before GRAPH-NODE-TIMES (0.2.19) have none. */
41
42
  nodes: Array<{ nodeId: string; ok: boolean; exit: number | null; executed: boolean; output?: unknown; error?: string; decidedBy?: string; decidedAt?: string;
42
43
  startedAt?: string; endedAt?: string; seconds?: number;
43
- waiver?: { reason: string; at: string; original: { exit: number | null; output?: unknown; error?: string } } }>;
44
+ waiver?: { reason: string; at: string; /** RELEASE-WAIVE-UNMEASURED — why the waived gate had no verdict. */ unmeasured?: string; original: { exit: number | null; output?: unknown; error?: string } } }>;
44
45
  /** The node now running and when it started; cleared when its record is written. */
45
46
  currentNode?: { nodeId: string; startedAt: string };
46
47
  input?: unknown;
@@ -51,10 +52,14 @@ export interface GraphRunState {
51
52
  graphSnapshot?: { graphSha: string; recipesSha: string };
52
53
  graphPath?: string;
53
54
  variant?: { overlayId: string; goal: string; plan: GraphVariantPlan };
55
+ parentRunId?: string;
56
+ unitCalls?: Array<{ node: string; unit: string; version: number; hash: string; childRunId: string; exit: string; steps: number }>;
54
57
  growth?: GraphGrowth[];
55
58
  growthRejections?: Array<{ from: string; outcome: string; reason: string }>;
56
59
  growthPark?: { from: string; outcome: string; reason: string; decisionId: string; decisionRef: string; growth: GraphGrowth; command?: GrowthCommand; approval?: string };
57
60
  resume?: { from: string; at: string; previousStatus: GraphRunState['status']; graph?: 'snapshot' | 'current' };
61
+ /** GATE-HOST-EXECUTOR — every explicit input change a resume made (what was set and what it replaced), oldest first. */
62
+ inputOverrides?: GateExecutorOverride[];
58
63
  executed: number;
59
64
  dryRun: boolean;
60
65
  statePath: string;
@@ -71,10 +76,14 @@ export interface GraphRunOptions {
71
76
  resumeGraphId?: string;
72
77
  fromNodeId?: string;
73
78
  /** Release-only: accept the recorded failed node without executing it, and expose its regression to known-issues. */
74
- releaseWaiver?: { nodeId: string; reason: string; requestedRegressions: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[] };
79
+ releaseWaiver?: { nodeId: string; reason: string; requestedRegressions: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[]; unmeasured?: string };
75
80
  /** Release-only: add accepted issues independently of a waiver at a restart boundary. */
76
81
  releaseAcceptedRegressions?: { requested: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[] };
82
+ /** Release-only (GATE-HOST-EXECUTOR): run the restarted gate on this executor — recorded in `inputOverrides`, never a waiver. */
83
+ releaseGateExecutor?: { executor: string; host?: string };
77
84
  useCurrentGraph?: boolean;
85
+ /** Internal unit invocation context, propagated only by runGraph. */
86
+ unitContext?: { parentRunId: string; ancestors: readonly string[]; remainingSteps: number };
78
87
  /**
79
88
  * RELEASE-LEDGER-UNIVERSE — stamp every cmd: child with this run's ledger root (`ELANOUS_STATE_DIR`).
80
89
  * Without it a child launched from a non-leader tree (`bun scripts/...` with cwd = that tree) re-resolves
@@ -349,6 +358,9 @@ export function decideGraphApproval(graphId: string, runId: string, decision: 'a
349
358
  return applyRecordedDecision(state);
350
359
  }
351
360
 
361
+ /** The record `graph runs stop` writes for the node it cut (release resume reads it as an unmeasured gate). */
362
+ export const STOPPED_NODE_ERROR = 'stopped before node completed';
363
+
352
364
  /** 노드 stdout 의 «마지막 비어 있지 않은 줄»이 JSON 객체면 그것을 구조 산출로 본다(아니면 없음). */
353
365
  export function lastJsonObject(stdout: unknown): Record<string, unknown> | undefined {
354
366
  if (typeof stdout !== 'string') return undefined;
@@ -389,6 +401,55 @@ function nextNode(edges: readonly GraphEdgeSpec[], nodeId: string, exitOutcome:
389
401
  return edge.map?.[exitOutcome] ?? edge.fallback?.[0]?.node;
390
402
  }
391
403
 
404
+ type ResolvedUnit = { path: string; template: GraphTemplateSpec; hash: string };
405
+
406
+ function resolveUnit(call: string, callerPath: string): ResolvedUnit {
407
+ const [id, requested] = call.split('@');
408
+ const repo = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
409
+ const directories = [join(dirname(callerPath), 'units'), dirname(callerPath), join(repo, 'graphs', 'units'), join(getElanousConfigDir(), 'graphs', 'units')];
410
+ for (const dir of directories) {
411
+ if (!existsSync(dir)) continue;
412
+ const matches = readdirSync(dir).filter(file => /\.ya?ml$/.test(file) && file !== 'recipes.yaml' && file !== 'recipes.yml').flatMap(file => {
413
+ const path = join(dir, file);
414
+ const source = readFileSync(path, 'utf8');
415
+ const header: unknown = parseYaml(source);
416
+ if (!header || typeof header !== 'object' || Array.isArray(header) || (header as Record<string, unknown>).graph_id !== id) return [];
417
+ const parsed = parseGraphTemplateYaml(source, path);
418
+ if (parsed.errors.length) throw new Error(parsed.errors.map(e => `${e.path}: ${e.message}`).join('\n'));
419
+ const template = parsed.template!;
420
+ return template.unit && (requested === String(template.version) || requested === `^${template.version}`)
421
+ ? [{ path, template, hash: createHash('sha256').update(source).digest('hex') }] : [];
422
+ });
423
+ if (matches.length > 1) throw new Error(`ambiguous unit: ${call}`);
424
+ if (matches.length) return matches[0]!;
425
+ }
426
+ throw new Error(`unit not found: ${call}`);
427
+ }
428
+
429
+ function validateUnitCalls(graph: GraphTemplateSpec, path: string, ancestors: readonly string[] = []): Map<string, ResolvedUnit> {
430
+ if (ancestors.includes(graph.graphId)) throw new Error(`unit cycle: ${[...ancestors, graph.graphId].join(' -> ')}`);
431
+ if (ancestors.length > 3) throw new Error('unit nesting exceeds depth 3');
432
+ const result = new Map<string, ResolvedUnit>();
433
+ for (const node of graph.nodes) {
434
+ if (node.kind !== 'subgraph' || node.call === undefined) continue;
435
+ const unit = resolveUnit(node.call!, path);
436
+ const contract = node.contract!;
437
+ const edge = graph.edges.find(e => e.from === node.nodeId);
438
+ if (!unit.template.unit || contract.inputs.length !== unit.template.unit.inputs.length ||
439
+ contract.inputs.some(key => !unit.template.unit!.inputs.includes(key)) ||
440
+ contract.outputs.length !== unit.template.unit.outputs.length ||
441
+ contract.outputs.some(key => !unit.template.unit!.outputs.includes(key)) || edge?.on !== 'outcome' ||
442
+ !edge.map || Object.keys(edge.map).length !== unit.template.unit.exits.length ||
443
+ unit.template.unit.exits.some(exit => !Object.hasOwn(edge.map!, exit))) {
444
+ debug.log('graph.unit', 'contract-mismatch', { graphId: graph.graphId, nodeId: node.nodeId, call: node.call });
445
+ throw new Error(`unit contract mismatch: ${node.nodeId} -> ${node.call}`);
446
+ }
447
+ validateUnitCalls(unit.template, unit.path, [...ancestors, graph.graphId]);
448
+ result.set(node.nodeId, unit);
449
+ }
450
+ return result;
451
+ }
452
+
392
453
  export async function runGraph(path: string, options: GraphRunOptions = {}): Promise<GraphRunState> {
393
454
  if (options.resumeRunId && options.runId) throw new Error('runId and resumeRunId cannot be combined');
394
455
  if (options.fromNodeId && !options.resumeRunId) throw new Error('--from requires --resume');
@@ -396,6 +457,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
396
457
  if (options.variant && options.resumeRunId) throw new Error('variant cannot be combined with --resume');
397
458
  if (options.releaseWaiver && (!options.resumeRunId || options.fromNodeId !== options.releaseWaiver.nodeId)) throw new Error('release waiver requires --resume --from <waived node>');
398
459
  if (options.releaseAcceptedRegressions && (!options.resumeRunId || !options.fromNodeId || options.releaseWaiver)) throw new Error('accepted regressions require a release resume boundary');
460
+ if (options.releaseGateExecutor && (!options.resumeRunId || !options.fromNodeId)) throw new Error('gate executor override requires a release resume boundary');
399
461
  const root = options.deps?.root ?? effectiveInstanceRoot();
400
462
  const matchingRuns = options.resumeRunId && !options.resumeGraphId
401
463
  ? listGraphRuns(root).runs.filter((run) => run.runId === options.resumeRunId && run.graphPath === resolve(path)) : [];
@@ -428,6 +490,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
428
490
  const variant = options.variant ? createGraphVariant({ template: graph, ...options.variant }) : undefined;
429
491
  if (variant && !variant.ok) throw new Error(`graph variant rejected: ${JSON.stringify(variant.rejections)}`);
430
492
  if (variant?.ok) graph = variant.template;
493
+ const units = validateUnitCalls(graph, path, options.unitContext?.ancestors);
431
494
  const variantSource = variant?.ok ? stringifyYaml({ ...document,
432
495
  nodes: graph.nodes.map((node, index) => ({
433
496
  ...((document.nodes as Record<string, unknown>[])[index] ?? {}), node_id: node.nodeId, kind: node.kind,
@@ -506,6 +569,10 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
506
569
  if (options.resumeRunId && state.growth?.length && graphMode === 'current' && state.sourceHash !== approvalSourceHash) {
507
570
  throw new Error('graph or recipes changed since grown run');
508
571
  }
572
+ if (options.unitContext) {
573
+ if (state.parentRunId !== undefined && state.parentRunId !== options.unitContext.parentRunId) throw new Error('unit parent run changed');
574
+ state.parentRunId = options.unitContext.parentRunId;
575
+ }
509
576
  if (state.growth?.length) graph = withGrowth(graph, state.growth);
510
577
  let waivedRecord: GraphRunState['nodes'][number] | undefined;
511
578
  if (options.fromNodeId) {
@@ -547,7 +614,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
547
614
  if (options.releaseWaiver) {
548
615
  if (graphId !== 'release-loop') throw new Error('release waiver requires the release-loop graph');
549
616
  const checked = releaseResumeWaiver(state, { from: options.fromNodeId, waive: options.releaseWaiver.nodeId, reason: options.releaseWaiver.reason, acceptedRegressions: options.releaseWaiver.requestedRegressions });
550
- if (!checked || JSON.stringify(checked.acceptedRegressions) !== JSON.stringify(options.releaseWaiver.acceptedRegressions)) throw new Error('release waiver input changed before restart');
617
+ if (!checked || JSON.stringify(checked.acceptedRegressions) !== JSON.stringify(options.releaseWaiver.acceptedRegressions) ||
618
+ checked.unmeasured !== options.releaseWaiver.unmeasured) throw new Error('release waiver input changed before restart');
551
619
  const route = new Set<string>();
552
620
  let cursor: string | undefined = nextNode(graph.edges, options.fromNodeId, 'ok', 'ok');
553
621
  while (cursor && !route.has(cursor) && cursor !== 'known-issues') {
@@ -577,6 +645,22 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
577
645
  state.input = { ...(state.input as Record<string, unknown>),
578
646
  acceptedRegressions: releaseResumeAcceptedRegressions(state, [], options.fromNodeId) };
579
647
  }
648
+ if (options.releaseGateExecutor) {
649
+ if (graphId !== 'release-loop') throw new Error('gate executor override requires the release-loop graph');
650
+ const override = releaseResumeGateExecutor(state, { from: options.fromNodeId, executor: options.releaseGateExecutor.executor, host: options.releaseGateExecutor.host });
651
+ const next: Record<string, unknown> = { ...(state.input as Record<string, unknown>), ...override.set };
652
+ for (const key of override.unset ?? []) delete next[key];
653
+ state.input = next;
654
+ state.inputOverrides = [...(state.inputOverrides ?? []), override];
655
+ debug.log('graph.runs', 'input-override', { graphId, runId, ...override });
656
+ }
657
+ if (state.unitCalls) {
658
+ const calls = state.unitCalls;
659
+ state.unitCalls = calls.filter(call => {
660
+ const keep = state.path.slice(0, from).filter(nodeId => nodeId === call.node).length;
661
+ return calls.filter(item => item.node === call.node).indexOf(call) < keep;
662
+ });
663
+ }
580
664
  state.path = state.path.slice(0, from);
581
665
  state.nodes = state.nodes.slice(0, from);
582
666
  state.executed = state.nodes.filter((node) => node.executed).length;
@@ -659,7 +743,11 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
659
743
  if (state.status === 'done' || state.status === 'failed' || state.status === 'budget-exceeded') state.finishedAt ??= new Date().toISOString();
660
744
  persistOwnedRun(state, runnerOwner);
661
745
  };
662
- const log = options.deps?.log ?? ((event: string, data: Record<string, unknown>) => debug.log('graph.runner', event, data));
746
+ const baseLog = options.deps?.log ?? ((event: string, data: Record<string, unknown>) => debug.log('graph.runner', event, data));
747
+ // RFC §U: every event of a unit (child) run carries its parentRunId.
748
+ const log = options.unitContext
749
+ ? (event: string, data: Record<string, unknown>) => baseLog(event, { ...data, parentRunId: options.unitContext!.parentRunId })
750
+ : baseLog;
663
751
  const visits = new Map<string, number>();
664
752
  for (const nodeId of state.path) visits.set(nodeId, (visits.get(nodeId) ?? 0) + 1);
665
753
  let current: string | undefined = options.fromNodeId ?? state.pending?.nodeId ?? state.path.at(-1) ?? graph.entryNode;
@@ -685,7 +773,9 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
685
773
  const completed = state.nodes.at(-1);
686
774
  const resumingCompleted = options.resumeRunId !== undefined && !options.fromNodeId && completed?.nodeId === current &&
687
775
  state.path.at(-1) === current && !resumingPending;
688
- if (!resumingPending && !resumingCompleted && (visits.get(current) ?? 0) >= node.maxVisits) {
776
+ const usedSteps = state.path.length + (state.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
777
+ if (!resumingPending && !resumingCompleted && ((visits.get(current) ?? 0) >= node.maxVisits ||
778
+ (options.unitContext && usedSteps >= options.unitContext.remainingSteps))) {
689
779
  state.status = 'budget-exceeded';
690
780
  log('budget-exceeded', { graphId, runId, nodeId: current });
691
781
  persist();
@@ -795,6 +885,81 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
795
885
  error = result.error ? redactCredentials(result.error) : undefined;
796
886
  state.executed++;
797
887
  }
888
+ let unitExecuted = false;
889
+ if (units.has(current) && !waiving && state.dryRun && !resumingCompleted) {
890
+ // Dry run plans the walk only: no child run, no unit event, no unitCalls entry; the first declared exit stands in.
891
+ output = JSON.stringify({ outcome: units.get(current)!.template.unit!.exits[0], dryRun: true });
892
+ } else if (units.has(current) && !waiving && !resumingCompleted) {
893
+ const unit = units.get(current)!;
894
+ const contract = node.contract!;
895
+ const previous: Record<string, unknown> = Object.create(null);
896
+ for (const record of state.nodes) previous[record.nodeId] = lastJsonObject(record.output) ?? record.output;
897
+ const supplied = state.input && typeof state.input === 'object' && !Array.isArray(state.input)
898
+ ? state.input as Record<string, unknown> : {};
899
+ const inputs: Record<string, unknown> = Object.create(null);
900
+ for (const key of contract.inputs) {
901
+ const value = Object.hasOwn(supplied, key) ? supplied[key] : previous[key];
902
+ if (value !== undefined) inputs[key] = value;
903
+ }
904
+ const alreadySpent = state.path.length + (state.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
905
+ const remaining = options.unitContext ? options.unitContext.remainingSteps - alreadySpent : Infinity;
906
+ const childRunId = randomUUID();
907
+ const info = { graphId, runId, nodeId: current, unit: unit.template.graphId, childRunId, parentRunId: runId };
908
+ let entered = false;
909
+ try {
910
+ for (const key of contract.inputs) if (!Object.hasOwn(inputs, key)) throw new Error(`unit input missing: ${current}.${key}`);
911
+ if (createHash('sha256').update(readFileSync(unit.path, 'utf8')).digest('hex') !== unit.hash)
912
+ throw new Error(`unit source changed before call: ${current}`);
913
+ debug.log('graph.unit', 'enter', info);
914
+ log('graph.unit', { ...info, phase: 'enter' });
915
+ entered = true;
916
+ const child = await runGraph(unit.path, { runId: childRunId, input: inputs, dryRun: false,
917
+ pinChildUniverse: options.pinChildUniverse,
918
+ unitContext: { parentRunId: runId, ancestors: [...(options.unitContext?.ancestors ?? []), graphId],
919
+ remainingSteps: Math.min(node.budget!.innerSteps, remaining) }, deps: options.deps });
920
+ const steps = child.path.length + (child.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
921
+ const childExit = child.status === 'done' || child.status === 'failed' ? child.path.at(-1) : undefined;
922
+ // The last successful record carrying every contracted output is the source;
923
+ // intervening nodes (including terminal gates) need not reproduce those fields.
924
+ const values = child.nodes.reduce<Record<string, unknown> | undefined>((found, record) => {
925
+ if (!record.ok || !record.executed) return found;
926
+ const value = lastJsonObject(record.output) ??
927
+ (record.output && typeof record.output === 'object' && !Array.isArray(record.output)
928
+ ? record.output as Record<string, unknown> : undefined);
929
+ return value && contract.outputs.every(key => Object.hasOwn(value, key)) ? value : found;
930
+ }, undefined) ?? {};
931
+ state.unitCalls ??= [];
932
+ state.unitCalls.push({ node: current, unit: unit.template.graphId, version: unit.template.version,
933
+ hash: unit.hash, childRunId, exit: childExit ?? child.status, steps });
934
+ if (child.status === 'awaiting-approval') throw new Error(`unit cannot pause for approval: ${current}`);
935
+ if (child.status === 'budget-exceeded' || steps > node.budget!.innerSteps || steps > remaining) {
936
+ debug.log('graph.unit', 'budget-exhausted', { ...info, steps, innerSteps: node.budget!.innerSteps });
937
+ log('graph.unit', { ...info, phase: 'budget-exhausted', steps });
938
+ throw new Error(`unit inner_steps exceeded: ${current}`);
939
+ }
940
+ if (!childExit || !unit.template.unit!.exits.includes(childExit)) throw new Error(`unit exit missing: ${current}`);
941
+ if (child.status === 'done' && childExit === 'failed') throw new Error(`unit exit mismatch: ${current}`);
942
+ const result: Record<string, unknown> = { outcome: childExit };
943
+ for (const key of contract.outputs) {
944
+ if (!Object.hasOwn(values, key)) throw new Error(`unit output missing: ${current}.${key}`);
945
+ result[key] = values[key];
946
+ }
947
+ output = JSON.stringify(result);
948
+ ok = child.status === 'done';
949
+ debug.log('graph.unit', 'exit', { ...info, exit: childExit, steps });
950
+ log('graph.unit', { ...info, phase: 'exit', exit: childExit, steps });
951
+ } catch (cause) {
952
+ ok = false;
953
+ error = cause instanceof Error ? cause.message : String(cause);
954
+ if (entered) {
955
+ debug.log('graph.unit', 'exit', { ...info, error });
956
+ log('graph.unit', { ...info, phase: 'exit', error });
957
+ }
958
+ }
959
+ // A rejected invocation has no child ledger and did not execute a unit.
960
+ unitExecuted = existsSync(graphRunPath(unit.template.graphId, childRunId, root));
961
+ if (unitExecuted) state.executed++;
962
+ }
798
963
  if (prompt && !waiving && !state.dryRun && !resumingCompleted) {
799
964
  const outputs: Record<string, { ok: boolean; output: unknown; durationMs: number }> = Object.create(null);
800
965
  for (const previous of state.nodes) outputs[previous.nodeId] = { ok: previous.ok, output: lastJsonObject(previous.output) ?? previous.output ?? null, durationMs: 0 };
@@ -833,8 +998,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
833
998
  if (approval && !state.dryRun && !command) {
834
999
  output = JSON.stringify({ outcome: ok ? 'approved' : 'rejected', ...(state.pending?.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending?.decidedAt ?? null });
835
1000
  }
836
- state.nodes.push({ nodeId: current, ok, exit, executed: !waiving && ((!!command && (!state.dryRun || !!command.dry_run_command)) || (!!prompt && !state.dryRun)), ...((waiving || ((command || prompt || approval) && (!state.dryRun || !!command?.dry_run_command))) && output !== undefined ? { output } : {}), ...(error ? { error } : {}),
837
- ...(waiving ? { waiver: { reason: options.releaseWaiver!.reason, at: nodeEndedAt, original: { exit: waivedRecord!.exit, ...(waivedRecord!.output === undefined ? {} : { output: waivedRecord!.output }), ...(waivedRecord!.error === undefined ? {} : { error: waivedRecord!.error }) } } } : {}),
1001
+ state.nodes.push({ nodeId: current, ok, exit, executed: !waiving && ((!!command && (!state.dryRun || !!command.dry_run_command)) || (!!prompt && !state.dryRun) || unitExecuted), ...((waiving || units.has(current) || ((command || prompt || approval) && (!state.dryRun || !!command?.dry_run_command))) && output !== undefined ? { output } : {}), ...(error ? { error } : {}),
1002
+ ...(waiving ? { waiver: { reason: options.releaseWaiver!.reason, at: nodeEndedAt, ...(options.releaseWaiver!.unmeasured === undefined ? {} : { unmeasured: options.releaseWaiver!.unmeasured }), original: { exit: waivedRecord!.exit, ...(waivedRecord!.output === undefined ? {} : { output: waivedRecord!.output }), ...(waivedRecord!.error === undefined ? {} : { error: waivedRecord!.error }) } } } : {}),
838
1003
  ...(approval && state.pending ? { ...(state.pending.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending.decidedAt } : {}),
839
1004
  startedAt: nodeStartedAt, endedAt: nodeEndedAt, seconds });
840
1005
  }
@@ -842,7 +1007,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
842
1007
  delete state.pending;
843
1008
  delete state.approvalSourceHash;
844
1009
  }
845
- const reported = waiving || (prompt && !state.dryRun) || (command && (!state.dryRun || command.dry_run_command)) ? lastJsonObject(resumingCompleted ? completed?.output : output)?.outcome : undefined;
1010
+ const reported = waiving || units.has(current) || (prompt && !state.dryRun) || (command && (!state.dryRun || command.dry_run_command)) ? lastJsonObject(resumingCompleted ? completed?.output : output)?.outcome : undefined;
846
1011
  const namedOutcome = typeof reported === 'string' ? reported : undefined;
847
1012
  console.error(`[graph] ${current} ${ok ? 'ok' : 'fail'} (${seconds.toFixed(2)}s)`);
848
1013
  debug.log('graph.run', 'node', { graphId, runId, nodeId: current, phase: ok ? 'ok' : 'fail', seconds, exit });
@@ -999,7 +1164,7 @@ export function manageGraphRun(graphId: string, runId: string, action: 'stop' |
999
1164
  // One stop instant for the node end, finishedAt and stoppedAt — never before the running node's start.
1000
1165
  const stopMs = running === undefined ? Date.now() : Math.max(Date.now(), Date.parse(running));
1001
1166
  if (state.path.length === state.nodes.length + 1) {
1002
- state.nodes.push({ nodeId: state.path.at(-1)!, ok: false, exit: null, executed: false, error: 'stopped before node completed',
1167
+ state.nodes.push({ nodeId: state.path.at(-1)!, ok: false, exit: null, executed: false, error: STOPPED_NODE_ERROR,
1003
1168
  // The stop instant is always the node end; a start (and so seconds) exists only when the ledger named the running
1004
1169
  // node — a run begun by a runner before GRAPH-NODE-TIMES did not, and a guessed start would be a false time.
1005
1170
  endedAt: new Date(stopMs).toISOString(),
@@ -2,18 +2,20 @@
2
2
  * 마법사 «원형» — 사람이 말로 자주 시키는 일의 뼈대 셋. graphs/** 의 운영 템플릿(개발·출시 루프)은
3
3
  * «모아서 요약해 보내기» 같은 말과 낱말이 안 겹쳐 엉뚱한 기반(lecture-note)을 골랐다(10-08 라이브 실측).
4
4
  * 원형은 기반 후보 «맨 앞»에 서고, 키워드가 겹치는 만큼 점수를 얻는다.
5
+ * 각 원형은 그래프 값어치 신호를 둘 이상 실린다(G1 검증 judge · G2 되돌림 간선 ⊕ max_visits ≥ 2 · G3 승인 hitl · G4 갈래) —
6
+ * 단순 나열은 스킬 사슬이지 그래프가 아니다(RFC SW-GRAPH-SMELL · generate.ts graphSignals 로 잰다).
5
7
  */
6
8
  export interface WizardArchetype { id: string; description: string; keywords: string[]; text: string }
7
9
 
8
10
  export const WIZARD_ARCHETYPES: readonly WizardArchetype[] = [
9
11
  {
10
12
  id: 'wizard-collect-summarize-send',
11
- description: '모아서 요약해 보내기 — 검색·수집 → 요약 → 텔레그램/알림 발송 (브리핑·다이제스트·동향)',
13
+ description: '모아서 요약해 보내기 — 검색·수집 → 요약 → 출처 대조(판정·되돌림) → 텔레그램/알림 발송 (브리핑·다이제스트·동향)',
12
14
  keywords: ['뉴스', '모아', '수집', '검색', '찾아', '요약', '정리', '보내', '알려', '텔레그램', '브리핑', '동향', '소식', 'news', 'digest', 'summary'],
13
15
  text: `graph_id: wizard-collect-summarize-send
14
16
  loop:
15
17
  title: 모아서 요약해 보내기
16
- description: 검색으로 모은 내용을 요약해 텔레그램으로 보낸다
18
+ description: 검색으로 모은 내용을 요약하고 출처와 대조해 텔레그램으로 보낸다
17
19
  trigger:
18
20
  cron: "0 8 * * *"
19
21
  version: 1
@@ -21,13 +23,15 @@ entry_node: collect
21
23
  terminal_nodes: [done, failed]
22
24
  nodes:
23
25
  - { node_id: collect, kind: agent, recipe: 'cmd:collect', max_visits: 1 } # 수집 | web-search | 검색어
24
- - { node_id: summarize, kind: agent, recipe: 'cmd:summarize', max_visits: 1 } # 요약 | summarize | 핵심 5줄 한국어
26
+ - { node_id: summarize, kind: agent, recipe: 'cmd:summarize', max_visits: 2 } # 요약 | summarize | 핵심 5줄 한국어
27
+ - { node_id: check, kind: judge, recipe: 'cmd:check', max_visits: 2 } # 출처 대조 | check | 요약이 수집 결과와 일치하는가
25
28
  - { node_id: send, kind: agent, recipe: 'cmd:send', max_visits: 1 } # 텔레그램 발송 | telegram-send
26
29
  - { node_id: done, kind: gate, recipe: none, max_visits: 1 } # 완료
27
30
  - { node_id: failed, kind: gate, recipe: none, max_visits: 1 } # 실패
28
31
  edges:
29
32
  - { from: collect, on: outcome, map: { ok: summarize, fail: failed } }
30
- - { from: summarize, on: outcome, map: { ok: send, fail: failed } }
33
+ - { from: summarize, on: outcome, map: { ok: check, fail: failed } }
34
+ - { from: check, on: outcome, map: { ok: send, rework: summarize, fail: failed } }
31
35
  - { from: send, on: outcome, map: { ok: done, fail: failed } }
32
36
  `,
33
37
  },
@@ -60,12 +64,12 @@ edges:
60
64
  },
61
65
  {
62
66
  id: 'wizard-research-approve-publish',
63
- description: '조사해 정리하고 승인 뒤 게시 — 조사 → 표/초안 정리 → 사람 승인 → 게시',
67
+ description: '조사해 정리하고 승인 뒤 게시 — 조사 → 표/초안 정리 → 출처 대조(판정·되돌림) → 사람 승인 → 게시',
64
68
  keywords: ['조사', '가격', '경쟁', '표', '정리', '승인', '올려', '게시', '노션', '초안', '블로그', '보고서'],
65
69
  text: `graph_id: wizard-research-approve-publish
66
70
  loop:
67
71
  title: 조사해 정리하고 승인 뒤 게시
68
- description: 조사한 내용을 표로 정리하고 사람 승인 뒤 게시한다
72
+ description: 조사한 내용을 표로 정리하고 출처와 대조해 사람 승인 뒤 게시한다
69
73
  trigger:
70
74
  events: [manual]
71
75
  version: 1
@@ -73,14 +77,16 @@ entry_node: research
73
77
  terminal_nodes: [done, failed]
74
78
  nodes:
75
79
  - { node_id: research, kind: agent, recipe: 'cmd:research', max_visits: 1 } # 조사 | web-search | 조사 주제
76
- - { node_id: tabulate, kind: agent, recipe: 'cmd:tabulate', max_visits: 1 } # 표로 정리 | llm | 결과를 마크다운 표로 정리
80
+ - { node_id: tabulate, kind: agent, recipe: 'cmd:tabulate', max_visits: 2 } # 표로 정리 | llm | 결과를 마크다운 표로 정리
81
+ - { node_id: check, kind: judge, recipe: 'cmd:check', max_visits: 2 } # 출처 대조 | check | 표가 조사 결과와 일치하는가
77
82
  - { node_id: approve, kind: hitl, recipe: 'approval:approve', max_visits: 1 } # 게시 승인 | approval
78
83
  - { node_id: publish, kind: agent, recipe: 'cmd:publish', max_visits: 1 } # 게시 | custom | 게시처에 올리기
79
84
  - { node_id: done, kind: gate, recipe: none, max_visits: 1 } # 완료
80
85
  - { node_id: failed, kind: gate, recipe: none, max_visits: 1 } # 실패
81
86
  edges:
82
87
  - { from: research, on: outcome, map: { ok: tabulate, fail: failed } }
83
- - { from: tabulate, on: outcome, map: { ok: approve, fail: failed } }
88
+ - { from: tabulate, on: outcome, map: { ok: check, fail: failed } }
89
+ - { from: check, on: outcome, map: { ok: approve, rework: tabulate, fail: failed } }
84
90
  - { from: approve, on: outcome, map: { ok: publish, fail: failed } }
85
91
  - { from: publish, on: outcome, map: { ok: done, fail: failed } }
86
92
  `,
@@ -52,6 +52,8 @@ export interface GraphWizardResult {
52
52
  recipes?: string;
53
53
  /** 실행 가능성 증명: 그 recipes 로 `graph run --dry-run` 을 걸어 본 결과. 하니스만. */
54
54
  dryRun?: { status: string; path: string[] };
55
+ /** 검증을 통과했지만 곁들인 경고(생성 실패 아님) — 예: «smell: linear-chain» 과 칸 내리기·유닛 끼우기 제안. */
56
+ warnings?: string[];
55
57
  }
56
58
 
57
59
  export interface GraphWizardDeps {
@@ -303,6 +305,74 @@ export function validateWizardYaml(kind: GraphKind, yaml: string): string[] {
303
305
  return issues;
304
306
  }
305
307
 
308
+ /** 그래프 값어치 신호(RFC SW-GRAPH-SMELL · G1~G7) — 기계로 셀 수 있는 넷만 센다. */
309
+ export interface GraphSignals {
310
+ /** G1 검증 노드 = kind judge|gate 비종단 노드의 결과 map 이 둘 이상으로 갈림 · G2 되돌림 루프 = 뒤로 가는 간선(이미 지난 노드로) ⊕ 그 노드 max_visits ≥ 2 · G3 승인 지점 = kind hitl 노드 · G4 갈래 = 비종단 노드의 결과 map 이 종단 아닌 서로 다른 둘 이상으로 갈림 */
311
+ counted: { G1: number; G2: number; G3: number; G4: number };
312
+ /** 못 셈 표시 — G5(재개)·G6(병렬)·G7(해상도). 0 으로 지어내지 않는다. */
313
+ notCounted: readonly ['G5', 'G6', 'G7'];
314
+ /** counted 넷의 합 — 둘 이상이면 그래프 값어치가 있다. */
315
+ total: number;
316
+ }
317
+
318
+ const GRAPH_SIGNALS_NOT_COUNTED = ['G5', 'G6', 'G7'] as const;
319
+
320
+ /** 순수 함수 — YAML 텍스트만 받아 센다(LLM·파일·실행 0). 못 세는 신호는 0 으로 지어내지 않고 «못 셈»으로 둔다. */
321
+ export function graphSignals(yaml: string): GraphSignals {
322
+ const counted = { G1: 0, G2: 0, G3: 0, G4: 0 };
323
+ const none = (): GraphSignals => ({ counted, notCounted: GRAPH_SIGNALS_NOT_COUNTED, total: 0 });
324
+ let doc: {
325
+ entry_node?: unknown; terminal_nodes?: unknown;
326
+ nodes?: Array<{ node_id?: unknown; kind?: unknown; max_visits?: unknown }>;
327
+ edges?: Array<{ from?: unknown; to?: unknown; map?: unknown }>;
328
+ } | null;
329
+ try { doc = parseYaml(yaml) as typeof doc; } catch { return none(); }
330
+ if (!doc) return none();
331
+ const nodes = (Array.isArray(doc.nodes) ? doc.nodes : []).filter((n) => n != null && typeof n.node_id === 'string');
332
+ const ids = new Set(nodes.map((n) => n.node_id as string));
333
+ const kindOf = new Map(nodes.map((n) => [n.node_id as string, typeof n.kind === 'string' ? n.kind : '']));
334
+ const visitsOf = new Map(nodes.map((n) => [n.node_id as string, Number(n.max_visits) || 0]));
335
+ const terminals = new Set((Array.isArray(doc.terminal_nodes) ? doc.terminal_nodes : []).map((t) => String(t)));
336
+ const targetsOf = new Map<string, Set<string>>();
337
+ for (const edge of Array.isArray(doc.edges) ? doc.edges : []) {
338
+ if (edge == null || typeof edge.from !== 'string' || !ids.has(edge.from)) continue;
339
+ const tos = typeof edge.to === 'string' ? [edge.to]
340
+ : edge.map && typeof edge.map === 'object'
341
+ ? Object.values(edge.map as Record<string, unknown>).filter((to): to is string => typeof to === 'string') : [];
342
+ const targets = targetsOf.get(edge.from) ?? new Set<string>();
343
+ for (const to of tos) if (ids.has(to)) targets.add(to);
344
+ if (targets.size > 0) targetsOf.set(edge.from, targets);
345
+ }
346
+ const entry = typeof doc.entry_node === 'string' && ids.has(doc.entry_node) ? doc.entry_node : undefined;
347
+ /** entry 에서 avoid 노드를 거치지 않고 닿는 노드들 = «이미 지난 노드»(avoid = 되돌림 간선의 출발 노드). entry 자신도 지난 노드로 센다. */
348
+ const passedBefore = (avoid?: string): ReadonlySet<string> => {
349
+ if (!entry) return new Set<string>();
350
+ const visited = new Set<string>([entry]);
351
+ const queue = [entry];
352
+ while (queue.length > 0) {
353
+ const current = queue.shift()!;
354
+ if (current === avoid) continue;
355
+ for (const to of targetsOf.get(current) ?? []) if (!visited.has(to)) { visited.add(to); queue.push(to); }
356
+ }
357
+ return visited;
358
+ };
359
+ for (const node of nodes) {
360
+ const id = node.node_id as string;
361
+ const targets = targetsOf.get(id) ?? new Set<string>();
362
+ if (kindOf.get(id) === 'hitl') counted.G3 += 1;
363
+ if (terminals.has(id)) continue;
364
+ if ((kindOf.get(id) === 'judge' || kindOf.get(id) === 'gate') && targets.size >= 2) counted.G1 += 1;
365
+ if ([...targets].filter((to) => !terminals.has(to)).length >= 2) counted.G4 += 1;
366
+ }
367
+ for (const [from, targets] of targetsOf) {
368
+ for (const to of targets) {
369
+ if (terminals.has(to) || (visitsOf.get(to) ?? 0) < 2) continue;
370
+ if (to === from ? passedBefore().has(from) : passedBefore(from).has(to)) counted.G2 += 1;
371
+ }
372
+ }
373
+ return { counted, notCounted: GRAPH_SIGNALS_NOT_COUNTED, total: counted.G1 + counted.G2 + counted.G3 + counted.G4 };
374
+ }
375
+
306
376
  /** 노드 줄 끝 주석 `# 이름 | 단계 | 인자` 를 읽는다. 흐름식 노드 줄에서만. */
307
377
  export function parseNodeAnnotations(yaml: string): Record<string, WizardNodeStep> {
308
378
  const out: Record<string, WizardNodeStep> = {};
@@ -562,11 +632,17 @@ export async function generateGraphFromPrompt(req: GraphWizardRequest, deps: Gra
562
632
  }
563
633
  attempts = Math.min(attempts, maxAttempts);
564
634
  const ok = issues.length === 0;
635
+ // «선형 사슬» 냄새(SW-GRAPH-SMELL) — 경고만, 생성 실패가 아니다. 값어치 신호가 둘 이하면 칸 내리기·유닛 끼우기를 제안한다.
636
+ const warnings: string[] = [];
637
+ if (kind === 'harness' && ok) {
638
+ const signals = graphSignals(yaml);
639
+ if (signals.total <= 1) warnings.push(`smell: linear-chain — G 신호 ${signals.total} · 칸 내리기(스킬 사슬) 또는 유닛 끼우기(unit-verify = G1·G2 · 승인 노드 = G3) 제안`);
640
+ }
565
641
  const counted = summarizeChange(kind, editing ? req.currentYaml : undefined, yaml);
566
642
  const summary = llmSummary ? `${llmSummary} (${counted})` : counted;
567
643
  debug.log('graph.wizard', ok ? 'validated' : 'failed', { id, kind, base, attempts, editing, issues: issues.slice(0, 10), summary, dryRun: dryRun?.status, ms: Date.now() - startedAt });
568
644
  const labels = Object.fromEntries(Object.entries(steps).filter(([, v]) => v.label).map(([k, v]) => [k, v.label!]));
569
- return { ok, id, yaml, ...(base ? { base } : {}), ...(base && baseReason ? { baseReason } : {}), issues, attempts, summary, labels, steps, ...(recipes ? { recipes } : {}), ...(dryRun ? { dryRun } : {}) };
645
+ return { ok, id, yaml, ...(base ? { base } : {}), ...(base && baseReason ? { baseReason } : {}), issues, attempts, summary, labels, steps, ...(recipes ? { recipes } : {}), ...(dryRun ? { dryRun } : {}), ...(warnings.length ? { warnings } : {}) };
570
646
  }
571
647
 
572
648
  /** v1 이름 유지 — 생성 YAML 의 노드 주석(단계·인자)으로 실제 recipes.yaml 을 낸다(v1 의 «미구현» 자리표시를 대체). */
package/src/grok/usage.ts CHANGED
@@ -182,13 +182,34 @@ export async function fetchGrokUsage(
182
182
  }
183
183
  }
184
184
 
185
- /** 이 조회는 구독 풀 잔량·리셋을 주지 않는다. 0·빈칸·미상과 다른 값. */
185
+ /** 주간 사용률·리셋이 없거나 유효하지 않은 응답에서 구독 축이 제공되지 않음을 나타낸다. */
186
186
  export const GROK_SUBSCRIPTION_AXIS = {
187
187
  status: 'unavailable',
188
188
  reason: 'query-does-not-supply',
189
189
  } as const;
190
190
 
191
- /** 원본 크레딧 사용률·창·금액류 → 크레딧 축. ⛔ 구독 축으로 전용하지 않는다. */
191
+ /** billing 쿼리가 주간 창과 사용률을 함께 돌려준 경우에만 실제 구독 잔량을 구성한다. */
192
+ export function grokUsageToSubscriptionAxis(usage: GrokUsage):
193
+ | { readonly status: 'available'; readonly remainingPercent: number; readonly resetsAt: number; readonly windowKind: 'weekly' }
194
+ | typeof GROK_SUBSCRIPTION_AXIS {
195
+ const end = usage.periodEnd === null ? Number.NaN : Date.parse(usage.periodEnd);
196
+ if (
197
+ usage.periodType !== 'USAGE_PERIOD_TYPE_WEEKLY'
198
+ || usage.usedPercent === null
199
+ || !Number.isFinite(usage.usedPercent)
200
+ || usage.usedPercent < 0
201
+ || usage.usedPercent > 100
202
+ || !Number.isFinite(end)
203
+ ) return GROK_SUBSCRIPTION_AXIS;
204
+ return {
205
+ status: 'available',
206
+ remainingPercent: 100 - usage.usedPercent,
207
+ resetsAt: end,
208
+ windowKind: 'weekly',
209
+ };
210
+ }
211
+
212
+ /** 원본 크레딧 사용률·창·금액류 → 크레딧 축. ⛔ 크레딧 숫자만으로 구독 잔량을 만들지 않는다. */
192
213
  export function grokUsageToCreditAxis(usage: GrokUsage): {
193
214
  readonly status: 'ok';
194
215
  readonly usedPercent: number | null;
package/src/grok.ts CHANGED
@@ -14,7 +14,8 @@
14
14
  import type { GrokAnalysis, DiffResult, EnvDelta } from './types.js';
15
15
  import * as ui from './ui.js';
16
16
  import { getUserConfig } from './user-config.js';
17
- import { getProviderForConfig, anyProviderAvailable, textOnly, type LLMMessage } from './llm.js';
17
+ import { getProviderForConfig, anyProviderAvailable, logAgentTurnUsage, type LLMMessage } from './llm.js';
18
+ import type { LLMUsage } from './prompt-cache/types.js';
18
19
 
19
20
  /** True when any provider (env OR user-config, including Codex OAuth)
20
21
  * can answer. Thin wrapper around llm.anyProviderAvailable() kept
@@ -34,19 +35,24 @@ async function callAnalyzer(prompt: string, systemPrompt?: string): Promise<stri
34
35
  if (systemPrompt) messages.push({ role: 'system', content: systemPrompt });
35
36
  messages.push({ role: 'user', content: prompt });
36
37
 
37
- const events = provider.streamChat
38
- ? provider.streamChat(messages, { temperature: 0.1, maxTokens: 1024 })
39
- : null;
38
+ const llmOpts = { temperature: 0.1, maxTokens: 1024 };
40
39
  let text = '';
41
- if (events) {
42
- for await (const delta of textOnly(events)) text += delta;
40
+ let usage: LLMUsage = {};
41
+ if (provider.streamChat) {
42
+ for await (const ev of provider.streamChat(messages, llmOpts)) {
43
+ if (ev.type === 'text' && ev.delta) text += ev.delta;
44
+ else if (ev.type === 'usage') usage = { ...usage, ...ev.usage };
45
+ }
43
46
  } else {
44
47
  // Fallback to text-only chat (shouldn't happen — every provider
45
48
  // ships streamChat now).
46
- for await (const chunk of provider.chat(messages, { temperature: 0.1, maxTokens: 1024 })) {
49
+ for await (const chunk of provider.chat(messages, llmOpts)) {
47
50
  text += chunk;
48
51
  }
49
52
  }
53
+ try {
54
+ logAgentTurnUsage(provider.defaultModel, usage, { providerName: provider.name, site: 'grok.direct' });
55
+ } catch { /* best-effort observation */ }
50
56
  return text;
51
57
  }
52
58