elanous 0.2.24 → 0.2.27

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 (601) 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/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
  9. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
  11. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
  17. package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
  18. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
  20. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
  21. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
  26. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
  29. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
  31. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
  32. package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
  37. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
  42. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
  48. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
  52. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
  54. package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
  55. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
  62. package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
  68. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
  73. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
  75. package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
  78. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
  85. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
  97. package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
  98. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
  99. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
  101. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
  104. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
  106. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
  107. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
  108. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
  112. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
  114. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
  120. package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
  121. package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
  183. package/apps/pwa/out/approvals/index.html +1 -1
  184. package/apps/pwa/out/approvals/index.txt +22 -22
  185. package/apps/pwa/out/autopilot/index.html +1 -1
  186. package/apps/pwa/out/autopilot/index.txt +22 -22
  187. package/apps/pwa/out/board/index.html +1 -1
  188. package/apps/pwa/out/board/index.txt +22 -22
  189. package/apps/pwa/out/botlab/index.html +1 -1
  190. package/apps/pwa/out/botlab/index.txt +21 -21
  191. package/apps/pwa/out/bots/index.html +1 -1
  192. package/apps/pwa/out/bots/index.txt +21 -21
  193. package/apps/pwa/out/ceo/index.html +1 -1
  194. package/apps/pwa/out/ceo/index.txt +22 -22
  195. package/apps/pwa/out/chat/index.html +1 -1
  196. package/apps/pwa/out/chat/index.txt +21 -21
  197. package/apps/pwa/out/consult/index.html +1 -1
  198. package/apps/pwa/out/consult/index.txt +22 -22
  199. package/apps/pwa/out/control/index.html +1 -1
  200. package/apps/pwa/out/control/index.txt +22 -22
  201. package/apps/pwa/out/decisions/index.html +1 -1
  202. package/apps/pwa/out/decisions/index.txt +21 -21
  203. package/apps/pwa/out/design-check/index.html +1 -1
  204. package/apps/pwa/out/design-check/index.txt +22 -22
  205. package/apps/pwa/out/editor/index.html +1 -1
  206. package/apps/pwa/out/editor/index.txt +22 -22
  207. package/apps/pwa/out/exec/index.html +1 -1
  208. package/apps/pwa/out/exec/index.txt +22 -22
  209. package/apps/pwa/out/field/index.html +1 -1
  210. package/apps/pwa/out/field/index.txt +22 -22
  211. package/apps/pwa/out/healthz +1 -1
  212. package/apps/pwa/out/index.html +1 -1
  213. package/apps/pwa/out/index.txt +21 -21
  214. package/apps/pwa/out/inside/index.html +1 -1
  215. package/apps/pwa/out/inside/index.txt +21 -21
  216. package/apps/pwa/out/intake/index.html +1 -1
  217. package/apps/pwa/out/intake/index.txt +22 -22
  218. package/apps/pwa/out/live/index.html +1 -1
  219. package/apps/pwa/out/live/index.txt +22 -22
  220. package/apps/pwa/out/live-run/index.html +1 -1
  221. package/apps/pwa/out/live-run/index.txt +22 -22
  222. package/apps/pwa/out/loops/index.html +1 -1
  223. package/apps/pwa/out/loops/index.txt +21 -21
  224. package/apps/pwa/out/market/index.html +1 -1
  225. package/apps/pwa/out/market/index.txt +21 -21
  226. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  227. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  228. package/apps/pwa/out/morning/index.html +1 -1
  229. package/apps/pwa/out/morning/index.txt +22 -22
  230. package/apps/pwa/out/observatory/index.html +1 -1
  231. package/apps/pwa/out/observatory/index.txt +22 -22
  232. package/apps/pwa/out/ops/checklist/index.html +1 -1
  233. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  234. package/apps/pwa/out/ops/release/index.html +1 -1
  235. package/apps/pwa/out/ops/release/index.txt +21 -21
  236. package/apps/pwa/out/ops/seats/index.html +1 -1
  237. package/apps/pwa/out/ops/seats/index.txt +21 -21
  238. package/apps/pwa/out/outputs/index.html +1 -1
  239. package/apps/pwa/out/outputs/index.txt +21 -21
  240. package/apps/pwa/out/reflection/index.html +1 -1
  241. package/apps/pwa/out/reflection/index.txt +22 -22
  242. package/apps/pwa/out/scheduler/index.html +1 -1
  243. package/apps/pwa/out/scheduler/index.txt +22 -22
  244. package/apps/pwa/out/sessions/index.html +1 -1
  245. package/apps/pwa/out/sessions/index.txt +21 -21
  246. package/apps/pwa/out/settings/devices/index.html +1 -1
  247. package/apps/pwa/out/settings/devices/index.txt +22 -22
  248. package/apps/pwa/out/settings/index.html +1 -1
  249. package/apps/pwa/out/settings/index.txt +22 -22
  250. package/apps/pwa/out/setup/done/index.html +1 -1
  251. package/apps/pwa/out/setup/done/index.txt +22 -22
  252. package/apps/pwa/out/setup/index.html +1 -1
  253. package/apps/pwa/out/setup/index.txt +22 -22
  254. package/apps/pwa/out/share/index.html +1 -1
  255. package/apps/pwa/out/share/index.txt +22 -22
  256. package/apps/pwa/out/showroom/index.html +1 -1
  257. package/apps/pwa/out/showroom/index.txt +21 -21
  258. package/apps/pwa/out/tasks/index.html +1 -1
  259. package/apps/pwa/out/tasks/index.txt +22 -22
  260. package/apps/pwa/out/term/index.html +1 -1
  261. package/apps/pwa/out/term/index.txt +22 -22
  262. package/apps/pwa/out/today/index.html +1 -1
  263. package/apps/pwa/out/today/index.txt +22 -22
  264. package/apps/pwa/out/trace/index.html +1 -1
  265. package/apps/pwa/out/trace/index.txt +22 -22
  266. package/apps/pwa/out/vault/index.html +1 -1
  267. package/apps/pwa/out/vault/index.txt +22 -22
  268. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  269. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  270. package/apps/pwa/out/workflows/index.html +1 -1
  271. package/apps/pwa/out/workflows/index.txt +22 -22
  272. package/apps/pwa/out/workspace/index.html +1 -1
  273. package/apps/pwa/out/workspace/index.txt +22 -22
  274. package/apps/pwa/out/worktrees/index.html +1 -1
  275. package/apps/pwa/out/worktrees/index.txt +22 -22
  276. package/graphs/release/release-loop.yaml +5 -5
  277. package/graphs/steward/recipes.yaml +4 -0
  278. package/graphs/steward/steward.yaml +10 -1
  279. package/package.json +1 -1
  280. package/scripts/bench-report.ts +46 -1
  281. package/scripts/ci-typecheck-changed.ts +88 -7
  282. package/scripts/coord-msg-bridge.ts +209 -0
  283. package/scripts/coord-post.sh +40 -7
  284. package/scripts/coord-requests-bridge.ts +10 -5
  285. package/scripts/expose-rubric-suggest.ts +1 -1
  286. package/scripts/measure-tsc-affected-roots.ts +10 -1
  287. package/scripts/release-loop/auto-approve-node.ts +6 -0
  288. package/scripts/release-loop/export-check-node.ts +8 -5
  289. package/scripts/release-loop/gate-closure.ts +286 -0
  290. package/scripts/release-loop/gate-node.ts +73 -13
  291. package/scripts/release-loop/gate-partial.ts +34 -6
  292. package/scripts/release-loop/node-verdict.ts +7 -2
  293. package/scripts/release-loop/ops-upgrade-node.ts +63 -42
  294. package/scripts/release-loop/publish-node.ts +6 -0
  295. package/scripts/release-loop/resume-release.ts +37 -10
  296. package/scripts/release-loop/resume.ts +69 -4
  297. package/scripts/tsc-baseline-cache.ts +28 -3
  298. package/scripts/usage-rollup.ts +27 -13
  299. package/scripts/ux-sim.ts +30 -1
  300. package/skills/youtube-master/scripts/main.ts +4 -1
  301. package/skills/youtube-master/src/obsidian.ts +9 -0
  302. package/src/agent/task-notification.ts +30 -1
  303. package/src/agent-substrate/acp-implementer.ts +14 -7
  304. package/src/agent-substrate/pr-reviewer.ts +30 -10
  305. package/src/agent-substrate/review-observation.ts +9 -2
  306. package/src/agent-substrate/self-review-cli.ts +154 -16
  307. package/src/boot/daemon-tools/self-implement.ts +72 -4
  308. package/src/budget/cost-tier-advisor.ts +91 -0
  309. package/src/budget/llm-cost.ts +5 -1
  310. package/src/budget/shadow-arms.ts +77 -0
  311. package/src/budget/types.ts +5 -3
  312. package/src/budget/unified-usage.ts +172 -8
  313. package/src/cli/control-cli.ts +29 -0
  314. package/src/cli/doctor-cli.ts +106 -3
  315. package/src/cli/friendly-errors.ts +113 -0
  316. package/src/cli/intake-cli.ts +3 -1
  317. package/src/cli/memory-cli.ts +182 -0
  318. package/src/cli/model-watch-cli.ts +4 -1
  319. package/src/cli/msg-cli.ts +15 -5
  320. package/src/cli/pr-cli.ts +53 -0
  321. package/src/cli/pr-land-overlap-evidence.ts +18 -10
  322. package/src/cli/pr-land-pod-shadow.ts +54 -0
  323. package/src/cli/release-cli.ts +41 -12
  324. package/src/cli/release-run-if-ready.ts +11 -0
  325. package/src/cli/resource-cli.ts +48 -0
  326. package/src/cli/retro-cli.ts +12 -3
  327. package/src/cli/seat-cli.ts +121 -0
  328. package/src/cli/seat-requests-cli.ts +25 -0
  329. package/src/cli/self-utterances-cli.ts +140 -0
  330. package/src/cli/tasks-cli.ts +168 -14
  331. package/src/cli/usage-cli.ts +3 -1
  332. package/src/compact/verify-probe.ts +23 -3
  333. package/src/context-card/cell.ts +40 -0
  334. package/src/context-card/index.ts +50 -0
  335. package/src/control/control-status.ts +30 -1
  336. package/src/dashboard/boot-timing.ts +35 -0
  337. package/src/dashboard/index.ts +86 -24
  338. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
  339. package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
  340. package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
  341. package/src/debug/log-diet.ts +16 -4
  342. package/src/debug/log.ts +1 -1
  343. package/src/domains/morning-essential.ts +18 -3
  344. package/src/domains/release-tool.ts +29 -8
  345. package/src/domains/surface-events.ts +16 -0
  346. package/src/elanous-config-dir.ts +2 -2
  347. package/src/execution-loop/launch-gate.ts +158 -2
  348. package/src/fleet/host-doctor.ts +446 -0
  349. package/src/goals/judge.ts +20 -6
  350. package/src/graph-runner/runner.ts +12 -6
  351. package/src/graph-wizard/archetypes.ts +14 -8
  352. package/src/graph-wizard/generate.ts +77 -1
  353. package/src/grok.ts +13 -7
  354. package/src/harness/harness-cli-command.ts +102 -51
  355. package/src/harness/harness-stop.ts +93 -19
  356. package/src/index.ts +52 -179
  357. package/src/instance/current.ts +2 -6
  358. package/src/instance/resolve.ts +5 -6
  359. package/src/intake-plane/collect-github.ts +7 -2
  360. package/src/intake-plane/lens.ts +46 -4
  361. package/src/intake-plane/requirement-funnel.ts +53 -1
  362. package/src/intelligence-map/catalog-feed.ts +119 -0
  363. package/src/intelligence-map/model-watch-intake.ts +40 -0
  364. package/src/intelligence-map/model-watch-mission.ts +14 -1
  365. package/src/llm/open-weight-discipline.ts +21 -0
  366. package/src/llm/openai-sampling-fields.ts +89 -0
  367. package/src/llm/runtime-model-family.ts +61 -0
  368. package/src/llm/zai-coding-plan.ts +27 -1
  369. package/src/llm.ts +17 -97
  370. package/src/machines/machine-ledger.ts +31 -3
  371. package/src/maturity/cli-maturity.ts +13 -3
  372. package/src/maturity/feature-maturity.ts +1 -1
  373. package/src/msg/msg-store.ts +69 -7
  374. package/src/nexus/api/http-server.ts +22 -0
  375. package/src/oauth/codex-account-rotation.ts +4 -1
  376. package/src/oauth/codex-account-store.ts +20 -7
  377. package/src/oauth/codex-quota-policy.ts +33 -4
  378. package/src/ops/overview-collect.ts +3 -2
  379. package/src/ops/overview-owner.ts +29 -0
  380. package/src/plugin-hooks/shell-hook.ts +17 -2
  381. package/src/plugin-missions/evaluator-runner.ts +18 -2
  382. package/src/plugins/install/plugin-install.ts +11 -1
  383. package/src/preview/terminal.ts +15 -5
  384. package/src/project/project-store.ts +20 -0
  385. package/src/prompt-enhance/enhance.ts +11 -0
  386. package/src/release-loop/auto-start.ts +7 -5
  387. package/src/release-loop/checklist.ts +52 -5
  388. package/src/release-loop/feature-store.ts +10 -9
  389. package/src/release-loop/gate-shards.ts +4 -0
  390. package/src/release-loop/light-rc.ts +84 -13
  391. package/src/release-loop/merged-pr-checklist.ts +35 -5
  392. package/src/release-loop/rehearsal.ts +1 -1
  393. package/src/seat-loop/duty-ledger.ts +64 -0
  394. package/src/seat-loop/seat-loop.ts +5 -1
  395. package/src/self-dev/decompose.ts +37 -3
  396. package/src/self-dev/dev-pipeline.ts +32 -7
  397. package/src/self-dev/draft-residue.ts +16 -6
  398. package/src/self-dev/draft-sweep.ts +75 -18
  399. package/src/self-dev/fabric-decompose-adapter.ts +9 -2
  400. package/src/self-dev/orchestrate.ts +6 -2
  401. package/src/self-dev/run-supervisor.ts +72 -8
  402. package/src/self-implement/gate-cli.ts +29 -10
  403. package/src/self-implement/gate-remote.ts +4 -1
  404. package/src/self-implement/goal-author.ts +15 -29
  405. package/src/self-implement/goal-command-execution.ts +26 -0
  406. package/src/self-implement/goal-new-paths.ts +42 -0
  407. package/src/self-implement/host-regate.ts +124 -30
  408. package/src/self-implement/importer-test-index.ts +3 -1
  409. package/src/self-implement/l8-merge-queue.ts +80 -2
  410. package/src/self-implement/merge-train.ts +19 -0
  411. package/src/self-implement/off-diff-evidence.ts +40 -1
  412. package/src/self-implement/orchestrator.ts +90 -20
  413. package/src/self-implement/premise-review.ts +159 -0
  414. package/src/self-implement/pwa-import-graph.ts +194 -7
  415. package/src/self-implement/regate-detail.ts +79 -0
  416. package/src/self-implement/review-deferred-to-host.ts +21 -0
  417. package/src/self-implement/rework-budget-judgment.ts +23 -3
  418. package/src/self-implement/running-runs.ts +2 -2
  419. package/src/self-implement/scope-adjacency.ts +23 -0
  420. package/src/self-implement/seams.ts +42 -7
  421. package/src/self-implement/self-implement-runtime.ts +126 -21
  422. package/src/session/index.ts +14 -4
  423. package/src/session-runtime/index.ts +55 -11
  424. package/src/skills/tools/agent.ts +16 -1
  425. package/src/skills/tools/persistent-grounding.ts +11 -1
  426. package/src/skills/tools/shell.ts +33 -1
  427. package/src/steward/rejudge-tick.ts +142 -0
  428. package/src/task-agent/board.ts +92 -3
  429. package/src/task-agent/card-evidence.ts +88 -1
  430. package/src/task-agent/cover.ts +85 -1
  431. package/src/task-agent/live-moves.ts +14 -6
  432. package/src/task-agent/parent-host.ts +27 -3
  433. package/src/task-agent/rejudge-on-head.ts +370 -29
  434. package/src/task-agent/review-result-capture.ts +67 -2
  435. package/src/task-agent/shadow.ts +148 -21
  436. package/src/task-agent/task-hand.ts +22 -3
  437. package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
  438. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
  439. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
  440. package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
  441. package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
  442. package/src/tool-runtime/tool-search-runtime.ts +25 -0
  443. package/src/tui.ts +20 -1
  444. package/src/user-config.ts +21 -63
  445. package/src/ux-sim/fault-cred-expiry.ts +100 -0
  446. package/src/ux-sim/fault-pod-death.ts +74 -0
  447. package/src/ux-sim/fault-pool-cap.ts +81 -0
  448. package/src/version/packed-revision.json +1 -1
  449. package/src/webclone/qa-table.ts +22 -0
  450. package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
  452. package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
  454. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
  455. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
  463. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
  465. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
  466. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
  467. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
  468. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
  475. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
  479. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
  491. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
  499. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
  503. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
  506. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
  507. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
  511. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
  516. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
  517. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
  518. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
  521. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
  528. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
  529. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
  534. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
  535. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
  537. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
  539. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
  540. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
  545. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
  601. /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
@@ -0,0 +1,446 @@
1
+ import { spawnSync } from 'node:child_process';
2
+ import { debug } from '../debug/log.js';
3
+ import type { ResourceView } from '../control-plane/ledger.js';
4
+ import type { MachineLedger, MachineFleetIntent } from '../machines/machine-ledger.js';
5
+
6
+ /**
7
+ * 호스트 닥터 — 첫 조각(FLEET-DOCTOR-1 · 읽기 전용).
8
+ * 설계 정본 = 내부 문서 `RFC-fleet-host-doctor-2026-10-11` §A1·A2·A4·A5.
9
+ * 점검은 코드 분기가 아니라 선언 표(HOST_DOCTOR_CHECKS)다.
10
+ */
11
+
12
+ export type HostDoctorPlatform = 'darwin' | 'linux' | 'wsl';
13
+ export type HostDoctorRole = 'worker' | 'hq';
14
+ export type HostDoctorFixKind = 'auto' | 'sudo' | 'approval' | 'human';
15
+ export type HostDoctorCheckStatus = 'pass' | 'fail' | 'unmeasured';
16
+ export type HostDoctorBundle = 'access' | 'engine' | 'platform';
17
+
18
+ /** 원격 한 발의 결과. `null` = 그 발을 아예 못 쐈다(→ unmeasured). */
19
+ export interface HostDoctorRun {
20
+ status: number | null;
21
+ stdout: string;
22
+ stderr: string;
23
+ }
24
+
25
+ /** 주입 가능한 원격 실행 — 기본 = ssh BatchMode · `<host>=local` 이면 이 기계(bash -c). */
26
+ export type HostDoctorRemote = (host: string, probe: string) => HostDoctorRun | null;
27
+
28
+ /** HQ 실측값(본부의 설치 판 · 이미지 핀) — 없으면 그 점검은 unmeasured 다. */
29
+ export interface HostDoctorExpected {
30
+ installVersion?: string;
31
+ imagePin?: string;
32
+ }
33
+
34
+ export interface HostDoctorExpectContext {
35
+ platform: HostDoctorPlatform | null;
36
+ arch: string | null;
37
+ expected: HostDoctorExpected;
38
+ }
39
+
40
+ export type HostDoctorExpectResult =
41
+ | { status: 'pass' | 'fail'; observed: string; expected: string }
42
+ | { status: 'unmeasured'; observed: string; expected: string };
43
+
44
+ export interface HostDoctorCheckSpec {
45
+ id: string;
46
+ bundle: HostDoctorBundle;
47
+ platforms: readonly HostDoctorPlatform[];
48
+ roles: readonly HostDoctorRole[];
49
+ /** 원격 셸 한 줄. */
50
+ probe: string;
51
+ expect: (run: HostDoctorRun, ctx: HostDoctorExpectContext) => HostDoctorExpectResult;
52
+ fixKind: HostDoctorFixKind;
53
+ fix?: string;
54
+ }
55
+
56
+ export interface HostDoctorCheckResult {
57
+ id: string;
58
+ status: HostDoctorCheckStatus;
59
+ observed: string;
60
+ expected: string;
61
+ fixKind: HostDoctorFixKind;
62
+ fix?: string;
63
+ }
64
+
65
+ /** 대장 레코드 종류 `setup-status {id, ok, missing[], fixHref}` 의 몸 ⊕ 확장 칸(RFC-fleet-host-doctor §A0 · 독자 이름 fleet.host.v1 은 쓰지 않는다). */
66
+ export interface HostDoctorReport {
67
+ /** setup-status.id — 호스트 이름. */
68
+ id: string;
69
+ /** setup-status.ok — fail 0 ⊕ unmeasured 0 일 때만. */
70
+ ok: boolean;
71
+ /** setup-status.missing — fail ⊕ unmeasured 점검 id. */
72
+ missing: string[];
73
+ /** setup-status.fixHref — 고치는 길(빠진 것이 없으면 null). */
74
+ fixHref: string | null;
75
+ // ── 확장 칸 ──
76
+ platform: HostDoctorPlatform | null;
77
+ arch: string | null;
78
+ role: HostDoctorRole;
79
+ measuredAt: string;
80
+ checks: HostDoctorCheckResult[];
81
+ }
82
+
83
+ /** 빠진 점검이 있을 때의 고치는 길 — 사람 손 처방은 RFC 표, 자동 처방은 node-setup(다음 조각 FLEET-DOCTOR-FIX 가 --fix 로 잇는다). */
84
+ export const HOST_DOCTOR_FIX_HREF = 'docs/RFC-fleet-host-doctor-2026-10-11.md';
85
+
86
+ const ALL_PLATFORMS: readonly HostDoctorPlatform[] = ['darwin', 'linux', 'wsl'];
87
+ const ALL_ROLES: readonly HostDoctorRole[] = ['worker', 'hq'];
88
+
89
+ function line(value: string): string {
90
+ return value.trim().split('\n')[0] ?? '';
91
+ }
92
+
93
+ function nonEmpty(value: string | null | undefined): value is string {
94
+ return typeof value === 'string' && value.trim().length > 0;
95
+ }
96
+
97
+ /** uname -m 과 docker 의 아키텍처 이름을 한 이름으로 — x86_64≡amd64 · aarch64≡arm64(10-11 WSL 실물: «x86_64 vs docker amd64» 오판). */
98
+ export function normalizeArch(arch: string): string {
99
+ const lower = arch.trim().toLowerCase();
100
+ if (lower === 'x86_64' || lower === 'x64') return 'amd64';
101
+ if (lower === 'aarch64' || lower === 'arm64v8') return 'arm64';
102
+ return lower;
103
+ }
104
+
105
+ /** 묶음 셋(접근 · 엔진 · 판)의 선언 표 — 첫 조각. */
106
+ export const HOST_DOCTOR_CHECKS: readonly HostDoctorCheckSpec[] = [
107
+ // ── 접근 ──
108
+ {
109
+ id: 'ssh.batch',
110
+ bundle: 'access',
111
+ platforms: ALL_PLATFORMS,
112
+ roles: ALL_ROLES,
113
+ // 원격 한 발 자체가 `ssh -o BatchMode=yes <host>` 로 간다 — 그 발이 «ok» 를 돌려주면 그게 증거다.
114
+ // (원격 안에서 다시 `ssh localhost` 를 치면 «그 호스트가 자기 자신에게» 붙는지를 재게 된다 · 10-11 실물 오판)
115
+ probe: 'echo ok',
116
+ expect: (run) => ({
117
+ status: run.status === 0 && line(run.stdout) === 'ok' ? 'pass' : 'fail',
118
+ observed: run.status === 0 ? line(run.stdout) || '(empty)' : `exit ${run.status ?? 'none'}`,
119
+ expected: 'ssh -o BatchMode=yes works without a password prompt',
120
+ }),
121
+ fixKind: 'human',
122
+ fix: 'put this host key in ~/.ssh/authorized_keys of the host user',
123
+ },
124
+ {
125
+ id: 'tailnet.online',
126
+ bundle: 'access',
127
+ platforms: ALL_PLATFORMS,
128
+ roles: ALL_ROLES,
129
+ probe: 'command -v tailscale >/dev/null 2>&1 || { echo no-cli; exit 0; }; tailscale status >/dev/null 2>&1 && echo online || echo offline',
130
+ expect: (run) => {
131
+ const out = line(run.stdout);
132
+ if (out === 'no-cli') return { status: 'unmeasured', observed: 'tailscale CLI not on the non-interactive PATH', expected: 'tailscale is up and logged in' };
133
+ return { status: out === 'online' ? 'pass' : 'fail', observed: out || `exit ${run.status ?? 'none'}`, expected: 'tailscale is up and logged in' };
134
+ },
135
+ fixKind: 'human',
136
+ fix: 'run `tailscale up` on the host',
137
+ },
138
+ {
139
+ id: 'path.noninteractive',
140
+ bundle: 'access',
141
+ platforms: ALL_PLATFORMS,
142
+ roles: ALL_ROLES,
143
+ probe: 'command -v bun; command -v codex',
144
+ expect: (run) => {
145
+ const found = run.stdout.trim().split('\n').map((entry) => entry.trim()).filter(nonEmpty);
146
+ return {
147
+ status: found.length >= 2 ? 'pass' : 'fail',
148
+ observed: found.length ? found.join(' ') : 'none on PATH',
149
+ expected: 'bun and codex reachable on the default non-interactive PATH',
150
+ };
151
+ },
152
+ fixKind: 'human',
153
+ fix: 'install bun/codex into a PATH a non-interactive shell already sees (no ~/.bashrc edits)',
154
+ },
155
+ // ── 엔진 ──
156
+ {
157
+ id: 'docker.engine',
158
+ bundle: 'engine',
159
+ platforms: ALL_PLATFORMS,
160
+ roles: ALL_ROLES,
161
+ probe: "docker info --format '{{.ServerVersion}}' 2>/dev/null",
162
+ expect: (run) => ({
163
+ status: run.status === 0 && nonEmpty(line(run.stdout)) ? 'pass' : 'fail',
164
+ observed: run.status === 0 ? line(run.stdout) || '(empty)' : `docker info exit ${run.status ?? 'none'}`,
165
+ expected: 'a real docker engine answers (not a desktop shim)',
166
+ }),
167
+ fixKind: 'human',
168
+ fix: 'start the docker engine on the host',
169
+ },
170
+ {
171
+ id: 'k3d.cluster',
172
+ bundle: 'engine',
173
+ platforms: ALL_PLATFORMS,
174
+ roles: ALL_ROLES,
175
+ // ⛔ `--no-header` 는 k3d v5 에 없는 플래그다(«unknown flag» → 빈 출력 → «클러스터 없음» 오판 · 10-11 node-c·WSL 실물).
176
+ probe: 'command -v k3d >/dev/null 2>&1 || { echo no-cli; exit 0; }; out=$(k3d cluster list -o json 2>/dev/null) || { echo error; exit 0; }; printf %s "$out" | grep -q \'"name"\' && echo present || echo none',
177
+ expect: (run) => {
178
+ const out = line(run.stdout);
179
+ if (out === 'no-cli') return { status: 'unmeasured', observed: 'k3d not on the non-interactive PATH', expected: 'at least one k3d cluster exists' };
180
+ if (out === 'error') return { status: 'unmeasured', observed: 'k3d cluster list failed', expected: 'at least one k3d cluster exists' };
181
+ return { status: out === 'present' ? 'pass' : 'fail', observed: out === 'present' ? 'present' : 'no k3d cluster', expected: 'at least one k3d cluster exists' };
182
+ },
183
+ fixKind: 'human',
184
+ fix: 'create the k3d cluster (scripts/fleet/node-setup.sh)',
185
+ },
186
+ {
187
+ id: 'registry.local',
188
+ bundle: 'engine',
189
+ platforms: ALL_PLATFORMS,
190
+ roles: ALL_ROLES,
191
+ // 풀 레지스트리는 k3d-elanous-registry:5050 이다(호스트 포트 5050) · 5000 은 맨 docker registry 관례라 대체로만 본다.
192
+ probe: 'for port in 5050 5000; do curl -fsS --max-time 3 "http://localhost:$port/v2/" >/dev/null 2>&1 && { echo "reachable:$port"; exit 0; }; done; echo unreachable',
193
+ expect: (run) => {
194
+ const out = line(run.stdout);
195
+ return {
196
+ status: out.startsWith('reachable:') ? 'pass' : 'fail',
197
+ observed: out.startsWith('reachable:') ? `localhost:${out.slice('reachable:'.length)} reachable` : 'localhost:5050/5000 /v2 unreachable',
198
+ expected: 'local registry answers on localhost:5050 (or 5000)',
199
+ };
200
+ },
201
+ fixKind: 'human',
202
+ fix: 'start the local registry container',
203
+ },
204
+ // ── 판 ──
205
+ {
206
+ id: 'install.version',
207
+ bundle: 'platform',
208
+ platforms: ALL_PLATFORMS,
209
+ roles: ALL_ROLES,
210
+ probe: 'elanous --version 2>/dev/null || echo none',
211
+ expect: (run, ctx) => {
212
+ const observed = line(run.stdout) || 'none';
213
+ if (!nonEmpty(ctx.expected.installVersion)) {
214
+ return { status: 'unmeasured', observed, expected: 'HQ install version (not supplied)' };
215
+ }
216
+ return { status: observed === ctx.expected.installVersion ? 'pass' : 'fail', observed, expected: ctx.expected.installVersion };
217
+ },
218
+ fixKind: 'auto',
219
+ fix: 'reinstall this host from the HQ install line',
220
+ },
221
+ {
222
+ id: 'image.pin',
223
+ bundle: 'platform',
224
+ platforms: ALL_PLATFORMS,
225
+ roles: ALL_ROLES,
226
+ probe: "docker ps --format '{{.Image}}' 2>/dev/null | grep -m1 elanous || true",
227
+ expect: (run, ctx) => {
228
+ const observed = line(run.stdout);
229
+ if (!nonEmpty(ctx.expected.imagePin)) {
230
+ return { status: 'unmeasured', observed: observed || 'none', expected: 'HQ image pin (not supplied)' };
231
+ }
232
+ return { status: nonEmpty(observed) && observed === ctx.expected.imagePin ? 'pass' : 'fail', observed: observed || 'no elanous image running', expected: ctx.expected.imagePin };
233
+ },
234
+ fixKind: 'auto',
235
+ fix: 'restart the pod from the pinned image',
236
+ },
237
+ {
238
+ id: 'image.arch',
239
+ bundle: 'platform',
240
+ platforms: ALL_PLATFORMS,
241
+ roles: ALL_ROLES,
242
+ probe: "uname -m; docker version --format '{{.Server.Arch}}' 2>/dev/null",
243
+ expect: (run) => {
244
+ const [hostArch, engineArch] = run.stdout.trim().split('\n').map((entry) => entry.trim());
245
+ // docker 가 답하지 않으면 엔진 쪽을 «못 쟀다» — fail 이 아니라 unmeasured(k3d·tailscale 과 같은 원칙).
246
+ if (!nonEmpty(engineArch)) {
247
+ return { status: 'unmeasured', observed: `${hostArch || 'none'} vs docker (no answer)`, expected: 'image architecture matches uname -m' };
248
+ }
249
+ return {
250
+ status: nonEmpty(hostArch) && nonEmpty(engineArch) && normalizeArch(hostArch) === normalizeArch(engineArch) ? 'pass' : 'fail',
251
+ observed: nonEmpty(hostArch) || nonEmpty(engineArch) ? `${hostArch ?? 'none'} vs docker ${engineArch ?? 'none'}` : 'none',
252
+ expected: 'image architecture matches uname -m',
253
+ };
254
+ },
255
+ fixKind: 'auto',
256
+ fix: 'pull the image pinned to this host architecture',
257
+ },
258
+ {
259
+ id: 'node.present',
260
+ bundle: 'platform',
261
+ platforms: ALL_PLATFORMS,
262
+ roles: ALL_ROLES,
263
+ probe: 'command -v node || echo none',
264
+ expect: (run) => {
265
+ const observed = line(run.stdout) || 'none';
266
+ return { status: observed !== 'none' && nonEmpty(observed) ? 'pass' : 'fail', observed, expected: 'node is on PATH (codex shebang)' };
267
+ },
268
+ fixKind: 'auto',
269
+ fix: 'install node (scripts/fleet/node-setup.sh)',
270
+ },
271
+ ];
272
+
273
+ /** 기본 원격 실행 — `<host>=local` 이면 이 기계의 비대화형 셸, 아니면 ssh BatchMode. 못 쏘면 null. */
274
+ export function defaultHostDoctorRemote(host: string, probe: string): HostDoctorRun | null {
275
+ const viaSsh = host !== 'local';
276
+ const spawned = viaSsh
277
+ // `--` 로 host 를 끊는다(«-o…» 로 시작하는 인자가 ssh 옵션으로 읽히지 않게) · ConnectTimeout 으로 패킷을 떨구는 호스트의 대기를 줄인다.
278
+ ? spawnSync('ssh', ['-o', 'BatchMode=yes', '-o', 'ConnectTimeout=5', '--', host, probe], { encoding: 'utf8', timeout: 20_000, stdio: ['ignore', 'pipe', 'pipe'] })
279
+ : spawnSync('bash', ['-c', probe], { encoding: 'utf8', timeout: 15_000, stdio: ['ignore', 'pipe', 'pipe'] });
280
+ return hostDoctorRunFromSpawn(spawned, viaSsh);
281
+ }
282
+
283
+ /** spawn 결과 → 원격 한 발. ⛔ ssh 는 «연결 자체» 실패(거부·이름 못 풂·키 거절)를 exit 255 로 낸다 — 그건 탐침이
284
+ * «못 쐈다» 이므로 null(→ unmeasured)이다. 그대로 넘기면 모든 점검이 «✗ fail» 로 읽힌다(10-11 리뷰 must-fix). */
285
+ export function hostDoctorRunFromSpawn(
286
+ spawned: { error?: Error; status: number | null; stdout?: string | null; stderr?: string | null },
287
+ viaSsh: boolean,
288
+ ): HostDoctorRun | null {
289
+ if (spawned.error || spawned.status === null) return null;
290
+ if (viaSsh && spawned.status === 255) return null;
291
+ return { status: spawned.status, stdout: spawned.stdout ?? '', stderr: spawned.stderr ?? '' };
292
+ }
293
+
294
+ export interface HostDoctorOptions {
295
+ host: string;
296
+ role?: HostDoctorRole;
297
+ remote?: HostDoctorRemote;
298
+ expected?: HostDoctorExpected;
299
+ now?: () => Date;
300
+ /** HQ observations: null means the source could not be read; [] means a successful empty reading. */
301
+ membership?: {
302
+ intent: MachineLedger | null;
303
+ machines: readonly ResourceView[] | null;
304
+ parentHosts: readonly { host?: string; podPool?: string; approvalCapacity?: number }[] | null;
305
+ intentError?: string;
306
+ machinesError?: string;
307
+ parentHostsError?: string;
308
+ };
309
+ }
310
+
311
+ function membershipCheck(id: string, status: HostDoctorCheckStatus, observed: string, expected: string): HostDoctorCheckResult {
312
+ return { id, status, observed, expected, fixKind: 'human', fix: 'compare Nexus machine registration, machines.yaml intent, and taskAgent.parentHost' };
313
+ }
314
+
315
+ /** Pure HQ comparison. A failed query is null (unmeasured); a successful empty result is a real missing host. */
316
+ export function checkHostMembership(host: string, platform: HostDoctorPlatform | null, membership: NonNullable<HostDoctorOptions['membership']>): HostDoctorCheckResult[] {
317
+ const intent: MachineFleetIntent | undefined = membership.intent?.machines.find((row) => row.fleet?.sshName === host)?.fleet;
318
+ const registryExpected = intent ? `live machine ${host} · role ${intent.role}` : `machines.yaml fleet intent for ${host}`;
319
+ let registry: HostDoctorCheckResult;
320
+ if (membership.intent === null || membership.machines === null) {
321
+ registry = membershipCheck('registry.member', 'unmeasured', membership.intent === null
322
+ ? `intent ledger unavailable (repository checkout required)${membership.intentError ? `: ${membership.intentError}` : ''}`
323
+ : `Nexus machine query unavailable${membership.machinesError ? `: ${membership.machinesError}` : ''}`, registryExpected);
324
+ } else if (!intent) {
325
+ registry = membershipCheck('registry.member', 'fail', 'host absent from fleet intent', registryExpected);
326
+ } else {
327
+ // `machine` is the Nexus identity; `name` is a display label. A missing/expired record
328
+ // is a measured failure even when the remote platform probe did not run.
329
+ const rows = membership.machines.filter((row) => row.kind === 'machine' && row.machine === host && !row.expired);
330
+ const row = rows[0];
331
+ const role = row?.attrs.role;
332
+ if (!row) registry = membershipCheck('registry.member', 'fail', 'no live Nexus machine record', registryExpected);
333
+ else if (rows.length !== 1) registry = membershipCheck('registry.member', 'fail', `${rows.length} live machine records`, registryExpected);
334
+ else if (typeof role !== 'string') registry = membershipCheck('registry.member', 'unmeasured', 'machine attrs.role unavailable', registryExpected);
335
+ else if (role !== intent.role) registry = membershipCheck('registry.member', 'fail', `machine role ${role}`, registryExpected);
336
+ // Existence and role have been measured above; a pass still needs the platform probe.
337
+ else if (platform === null) registry = membershipCheck('registry.member', 'unmeasured', 'host platform unavailable', `intent platform ${intent.platform}`);
338
+ else if (platform !== intent.platform) registry = membershipCheck('registry.member', 'fail', `host platform ${platform}`, `intent platform ${intent.platform}`);
339
+ else registry = membershipCheck('registry.member', 'pass', `live machine ${host} · role ${role}`, registryExpected);
340
+ }
341
+
342
+ const parentExpected = intent ? `taskAgent.parentHost ${host} · ${intent.podPool} · cap ${intent.cap}` : `machines.yaml fleet intent for ${host}`;
343
+ let parent: HostDoctorCheckResult;
344
+ if (membership.intent === null || membership.parentHosts === null) {
345
+ parent = membershipCheck('parentHost.member', 'unmeasured', membership.intent === null
346
+ ? `intent ledger unavailable (repository checkout required)${membership.intentError ? `: ${membership.intentError}` : ''}`
347
+ : `taskAgent.parentHost unavailable${membership.parentHostsError ? `: ${membership.parentHostsError}` : ''}`, parentExpected);
348
+ } else if (!intent) {
349
+ parent = membershipCheck('parentHost.member', 'fail', 'host absent from fleet intent', parentExpected);
350
+ } else {
351
+ const rows = membership.parentHosts.filter((row) => row.host === host);
352
+ const row = rows[0];
353
+ if (intent.cap === 0) parent = membershipCheck('parentHost.member', rows.length === 0 ? 'pass' : 'fail', rows.length === 0 ? 'disabled in both intent and parent config' : 'disabled host still in parent config', 'host absent from taskAgent.parentHost (cap 0)');
354
+ else if (!row) parent = membershipCheck('parentHost.member', 'fail', 'host absent from taskAgent.parentHost', parentExpected);
355
+ else if (rows.length !== 1 || row.podPool !== intent.podPool || row.approvalCapacity !== intent.cap) {
356
+ parent = membershipCheck('parentHost.member', 'fail', `host entries ${rows.length} · pool ${row.podPool ?? '(missing)'} · cap ${row.approvalCapacity ?? '(missing)'}`, parentExpected);
357
+ } else parent = membershipCheck('parentHost.member', 'pass', `host ${host} · pool ${row.podPool} · cap ${row.approvalCapacity}`, parentExpected);
358
+ }
359
+ return [registry, parent];
360
+ }
361
+
362
+ /** 원격 `uname -s` ⊕ `/proc/version` 의 microsoft 로 darwin|linux|wsl. 못 재면 null. */
363
+ export function detectHostDoctorPlatform(remote: HostDoctorRemote, host: string): HostDoctorPlatform | null {
364
+ const uname = remote(host, 'uname -s');
365
+ if (!uname || uname.status !== 0) return null;
366
+ const kernel = line(uname.stdout).toLowerCase();
367
+ if (kernel === 'darwin') return 'darwin';
368
+ if (kernel === 'linux') {
369
+ const procVersion = remote(host, 'cat /proc/version 2>/dev/null || true');
370
+ return procVersion && procVersion.status === 0 && /microsoft/i.test(procVersion.stdout) ? 'wsl' : 'linux';
371
+ }
372
+ return null;
373
+ }
374
+
375
+ /** 원격 아키텍처(`uname -m`). 못 재면 null. */
376
+ export function detectHostDoctorArch(remote: HostDoctorRemote, host: string): string | null {
377
+ const run = remote(host, 'uname -m');
378
+ if (!run || run.status !== 0) return null;
379
+ const arch = line(run.stdout);
380
+ return nonEmpty(arch) ? arch : null;
381
+ }
382
+
383
+ /** 못 쏜 점검 — 기대값 칸엔 셸 탐침이 아니라 그 점검의 «기대 문장»을 싣는다(다른 경로와 같은 뜻). */
384
+ function unmeasuredBecauseUnreached(spec: HostDoctorCheckSpec, options: { platform: HostDoctorPlatform | null; arch: string | null; expected: HostDoctorExpected }): HostDoctorCheckResult {
385
+ const expected = spec.expect({ status: 1, stdout: '', stderr: '' }, { platform: options.platform, arch: options.arch, expected: options.expected }).expected;
386
+ return { id: spec.id, fixKind: spec.fixKind, ...(spec.fix !== undefined ? { fix: spec.fix } : {}), status: 'unmeasured', observed: 'remote probe did not run', expected };
387
+ }
388
+
389
+ /** 점검 하나를 돌린다 — 원격 실패는 «pass 가 아닌» unmeasured 로만 간다. */
390
+ function runCheck(spec: HostDoctorCheckSpec, options: Required<Pick<HostDoctorOptions, 'host'>> & { remote: HostDoctorRemote; role: HostDoctorRole; platform: HostDoctorPlatform | null; arch: string | null; expected: HostDoctorExpected }): HostDoctorCheckResult {
391
+ const run = options.remote(options.host, spec.probe);
392
+ const base = { id: spec.id, fixKind: spec.fixKind, ...(spec.fix !== undefined ? { fix: spec.fix } : {}) };
393
+ if (run === null) return unmeasuredBecauseUnreached(spec, options);
394
+ const verdict = spec.expect(run, { platform: options.platform, arch: options.arch, expected: options.expected });
395
+ return { ...base, status: verdict.status, observed: verdict.observed, expected: verdict.expected };
396
+ }
397
+
398
+ /** `elanous doctor host <host>` — 읽기 전용. ok 는 fail 0 ⊕ unmeasured 0 일 때만. */
399
+ export function runHostDoctor(options: HostDoctorOptions): HostDoctorReport {
400
+ const host = options.host;
401
+ const role: HostDoctorRole = options.role === 'hq' ? 'hq' : 'worker';
402
+ const remote = options.remote ?? defaultHostDoctorRemote;
403
+ const expected = options.expected ?? {};
404
+ // 첫 발(uname -s)부터 못 쏘면 그 호스트에 «닿지 않는다» — 남은 탐침을 하나씩 기다리지 않고 전부 unmeasured 로 둔다.
405
+ const reached = remote(host, 'uname -s') !== null;
406
+ const platform = reached ? detectHostDoctorPlatform(remote, host) : null;
407
+ const arch = reached ? detectHostDoctorArch(remote, host) : null;
408
+ const specs = HOST_DOCTOR_CHECKS.filter((spec) => spec.roles.includes(role));
409
+ const remoteChecks = reached
410
+ ? specs.map((spec) => runCheck(spec, { host, remote, role, platform, arch, expected }))
411
+ : specs.map((spec) => unmeasuredBecauseUnreached(spec, { platform, arch, expected }));
412
+ const checks = [...remoteChecks, ...(role === 'worker' && options.membership ? checkHostMembership(host, platform, options.membership) : [])];
413
+ const mismatch = checks.filter((check) => (check.id === 'registry.member' || check.id === 'parentHost.member') && check.status === 'fail');
414
+ if (mismatch.length) debug.log('fleet.doctor', 'membership-mismatch', { host, checks: mismatch.map((check) => ({ id: check.id, observed: check.observed, expected: check.expected })) });
415
+ const membershipUnmeasured = checks.filter((check) => (check.id === 'registry.member' || check.id === 'parentHost.member') && check.status === 'unmeasured');
416
+ if (membershipUnmeasured.length) debug.log('fleet.doctor', 'membership-unmeasured', { host, checks: membershipUnmeasured.map((check) => ({ id: check.id, observed: check.observed })) });
417
+ const fail = checks.filter((check) => check.status === 'fail').map((check) => check.id);
418
+ const unmeasured = checks.filter((check) => check.status === 'unmeasured').map((check) => check.id);
419
+ const measuredAt = (options.now ?? (() => new Date()))().toISOString();
420
+ debug.log('fleet.doctor', 'host-checked', { host, platform, role, fail, unmeasured });
421
+ const missing = [...fail, ...unmeasured];
422
+ return {
423
+ id: host,
424
+ ok: missing.length === 0,
425
+ missing,
426
+ fixHref: missing.length === 0 ? null : HOST_DOCTOR_FIX_HREF,
427
+ platform,
428
+ arch,
429
+ role,
430
+ measuredAt,
431
+ checks,
432
+ };
433
+ }
434
+
435
+ /** 사람 출력 한 줄씩 — 기본은 «✓|✗|→ <id> <한 줄>»(node-setup.sh --check),
436
+ * membership 미측정은 눈에 보이는 «⚠ <id> unmeasured: <원인>»을 쓴다. */
437
+ export function formatHostDoctorLines(report: HostDoctorReport): string[] {
438
+ return report.checks.map((check) => {
439
+ if ((check.id === 'registry.member' || check.id === 'parentHost.member') && check.status === 'unmeasured') {
440
+ return `⚠ ${check.id} unmeasured: ${check.observed}`;
441
+ }
442
+ const mark = check.status === 'pass' ? '✓' : check.status === 'fail' ? '✗' : '→';
443
+ const detail = check.status === 'fail' ? `${check.observed} (expected: ${check.expected})` : check.observed;
444
+ return `${mark} ${check.id} ${detail}`;
445
+ });
446
+ }
@@ -11,7 +11,8 @@
11
11
  // PAUSE+ASK in the loop. Drift is more dangerous than a confirm.
12
12
 
13
13
  import { debug } from '../debug/log.js';
14
- import { getProvider, resolveDefaultProvider, type LLMMessage, type LLMOpts } from '../llm.js';
14
+ import { getProvider, logAgentTurnUsage, resolveDefaultProvider, type LLMMessage, type LLMOpts } from '../llm.js';
15
+ import type { LLMUsage } from '../prompt-cache/types.js';
15
16
  import type { GoalJudgeVerdict } from './types.js';
16
17
 
17
18
  export interface JudgeInput {
@@ -180,15 +181,28 @@ export async function judgeGoalTurn(
180
181
  });
181
182
 
182
183
  let text = '';
184
+ let usage: LLMUsage = {};
183
185
  try {
184
- const stream = provider.chat(messages, llmOpts);
185
186
  const t0 = Date.now();
186
- for await (const chunk of stream) {
187
- text += chunk;
188
- if (opts.timeoutMs && Date.now() - t0 > opts.timeoutMs) {
189
- throw new Error(`judge timeout after ${opts.timeoutMs}ms`);
187
+ if (provider.streamChat) {
188
+ for await (const ev of provider.streamChat(messages, llmOpts)) {
189
+ if (ev.type === 'text' && ev.delta) text += ev.delta;
190
+ else if (ev.type === 'usage') usage = { ...usage, ...ev.usage };
191
+ if (opts.timeoutMs && Date.now() - t0 > opts.timeoutMs) {
192
+ throw new Error(`judge timeout after ${opts.timeoutMs}ms`);
193
+ }
194
+ }
195
+ } else {
196
+ for await (const chunk of provider.chat(messages, llmOpts)) {
197
+ text += chunk;
198
+ if (opts.timeoutMs && Date.now() - t0 > opts.timeoutMs) {
199
+ throw new Error(`judge timeout after ${opts.timeoutMs}ms`);
200
+ }
190
201
  }
191
202
  }
203
+ try {
204
+ logAgentTurnUsage(opts.model ?? provider.defaultModel, usage, { providerName: provider.name, site: 'goals.judge' });
205
+ } catch { /* best-effort observation */ }
192
206
  } catch (err) {
193
207
  debug.log('goal', 'judge.error', { attempt, message: (err as Error).message }, { level: 'error' });
194
208
  // On timeout / abort, return null so the loop can pause-ask
@@ -26,6 +26,7 @@ import type { BashNode, NodeExecContext, WorkflowDeps } from '../workflow-runtim
26
26
  import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeWaiver, type AcceptedRegression, type GateExecutorOverride } from '../../scripts/release-loop/resume.js';
27
27
 
28
28
  type BashRun = WorkflowDeps['runBash'];
29
+ const DEFAULT_BASH_TIMEOUT_MS = 5 * 60 * 1_000;
29
30
 
30
31
  export interface GraphRunState {
31
32
  graphId: string;
@@ -41,7 +42,7 @@ export interface GraphRunState {
41
42
  /** startedAt/endedAt (ISO) and seconds are written when the node runs; ledgers before GRAPH-NODE-TIMES (0.2.19) have none. */
42
43
  nodes: Array<{ nodeId: string; ok: boolean; exit: number | null; executed: boolean; output?: unknown; error?: string; decidedBy?: string; decidedAt?: string;
43
44
  startedAt?: string; endedAt?: string; seconds?: number;
44
- waiver?: { reason: string; at: string; original: { exit: number | null; output?: unknown; error?: string } } }>;
45
+ 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 } } }>;
45
46
  /** The node now running and when it started; cleared when its record is written. */
46
47
  currentNode?: { nodeId: string; startedAt: string };
47
48
  input?: unknown;
@@ -76,7 +77,7 @@ export interface GraphRunOptions {
76
77
  resumeGraphId?: string;
77
78
  fromNodeId?: string;
78
79
  /** Release-only: accept the recorded failed node without executing it, and expose its regression to known-issues. */
79
- releaseWaiver?: { nodeId: string; reason: string; requestedRegressions: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[] };
80
+ releaseWaiver?: { nodeId: string; reason: string; requestedRegressions: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[]; unmeasured?: string };
80
81
  /** Release-only: add accepted issues independently of a waiver at a restart boundary. */
81
82
  releaseAcceptedRegressions?: { requested: AcceptedRegression[]; acceptedRegressions: AcceptedRegression[] };
82
83
  /** Release-only (GATE-HOST-EXECUTOR): run the restarted gate on this executor — recorded in `inputOverrides`, never a waiver. */
@@ -358,6 +359,9 @@ export function decideGraphApproval(graphId: string, runId: string, decision: 'a
358
359
  return applyRecordedDecision(state);
359
360
  }
360
361
 
362
+ /** The record `graph runs stop` writes for the node it cut (release resume reads it as an unmeasured gate). */
363
+ export const STOPPED_NODE_ERROR = 'stopped before node completed';
364
+
361
365
  /** 노드 stdout 의 «마지막 비어 있지 않은 줄»이 JSON 객체면 그것을 구조 산출로 본다(아니면 없음). */
362
366
  export function lastJsonObject(stdout: unknown): Record<string, unknown> | undefined {
363
367
  if (typeof stdout !== 'string') return undefined;
@@ -611,7 +615,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
611
615
  if (options.releaseWaiver) {
612
616
  if (graphId !== 'release-loop') throw new Error('release waiver requires the release-loop graph');
613
617
  const checked = releaseResumeWaiver(state, { from: options.fromNodeId, waive: options.releaseWaiver.nodeId, reason: options.releaseWaiver.reason, acceptedRegressions: options.releaseWaiver.requestedRegressions });
614
- if (!checked || JSON.stringify(checked.acceptedRegressions) !== JSON.stringify(options.releaseWaiver.acceptedRegressions)) throw new Error('release waiver input changed before restart');
618
+ if (!checked || JSON.stringify(checked.acceptedRegressions) !== JSON.stringify(options.releaseWaiver.acceptedRegressions) ||
619
+ checked.unmeasured !== options.releaseWaiver.unmeasured) throw new Error('release waiver input changed before restart');
615
620
  const route = new Set<string>();
616
621
  let cursor: string | undefined = nextNode(graph.edges, options.fromNodeId, 'ok', 'ok');
617
622
  while (cursor && !route.has(cursor) && cursor !== 'known-issues') {
@@ -874,7 +879,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
874
879
  env.ELANOUS_GRAPH_DRY_RUN = state.dryRun ? '1' : '0';
875
880
  env.ELANOUS_GRAPH_DIR = dirname(resolve(path));
876
881
  const ctx = { arguments: '', artifactsDir: dirname(statePath), outputs: {}, resolvedProvider: undefined, resolvedModel: undefined, toolPolicy: {}, env } as NodeExecContext;
877
- const result = await executeBashNode({ id: current, type: 'bash', bash: state.dryRun ? command.dry_run_command! : command.command, ...(command.timeout_ms ? { idle_timeout: command.timeout_ms } : {}) } as BashNode, ctx, { runBash } as WorkflowDeps);
882
+ const result = await executeBashNode({ id: current, type: 'bash', bash: state.dryRun ? command.dry_run_command! : command.command,
883
+ idle_timeout: command.timeout_ms ?? DEFAULT_BASH_TIMEOUT_MS } as BashNode, ctx, { runBash } as WorkflowDeps);
878
884
  output = result.output;
879
885
  ok = result.ok;
880
886
  exit = code;
@@ -995,7 +1001,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
995
1001
  output = JSON.stringify({ outcome: ok ? 'approved' : 'rejected', ...(state.pending?.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending?.decidedAt ?? null });
996
1002
  }
997
1003
  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 } : {}),
998
- ...(waiving ? { waiver: { reason: options.releaseWaiver!.reason, at: nodeEndedAt, original: { exit: waivedRecord!.exit, ...(waivedRecord!.output === undefined ? {} : { output: waivedRecord!.output }), ...(waivedRecord!.error === undefined ? {} : { error: waivedRecord!.error }) } } } : {}),
1004
+ ...(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 }) } } } : {}),
999
1005
  ...(approval && state.pending ? { ...(state.pending.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending.decidedAt } : {}),
1000
1006
  startedAt: nodeStartedAt, endedAt: nodeEndedAt, seconds });
1001
1007
  }
@@ -1160,7 +1166,7 @@ export function manageGraphRun(graphId: string, runId: string, action: 'stop' |
1160
1166
  // One stop instant for the node end, finishedAt and stoppedAt — never before the running node's start.
1161
1167
  const stopMs = running === undefined ? Date.now() : Math.max(Date.now(), Date.parse(running));
1162
1168
  if (state.path.length === state.nodes.length + 1) {
1163
- state.nodes.push({ nodeId: state.path.at(-1)!, ok: false, exit: null, executed: false, error: 'stopped before node completed',
1169
+ state.nodes.push({ nodeId: state.path.at(-1)!, ok: false, exit: null, executed: false, error: STOPPED_NODE_ERROR,
1164
1170
  // The stop instant is always the node end; a start (and so seconds) exists only when the ledger named the running
1165
1171
  // node — a run begun by a runner before GRAPH-NODE-TIMES did not, and a guessed start would be a false time.
1166
1172
  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
  `,