elanous 0.2.22 → 0.2.24

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 (803) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +32 -22
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_buildManifest.js +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  10. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  12. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  13. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  15. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  24. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  25. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  28. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  36. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  40. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  53. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  57. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  70. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  72. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  74. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  75. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  79. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  84. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  85. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  86. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  88. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  91. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  98. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  100. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  102. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  103. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  106. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  111. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  112. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  113. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  117. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  118. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  121. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  124. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  125. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/consult/{page-80ed511e02c81412.js → page-c0ab229673a8b0eb.js} +1 -1
  134. package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/design-check/page-26345242e4049f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b92caddb5c715f30.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  185. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +1 -0
  186. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  187. package/apps/pwa/out/approvals/index.html +1 -1
  188. package/apps/pwa/out/approvals/index.txt +23 -23
  189. package/apps/pwa/out/autopilot/index.html +1 -1
  190. package/apps/pwa/out/autopilot/index.txt +23 -23
  191. package/apps/pwa/out/board/index.html +1 -1
  192. package/apps/pwa/out/board/index.txt +23 -23
  193. package/apps/pwa/out/botlab/index.html +1 -1
  194. package/apps/pwa/out/botlab/index.txt +22 -22
  195. package/apps/pwa/out/bots/index.html +1 -1
  196. package/apps/pwa/out/bots/index.txt +22 -22
  197. package/apps/pwa/out/ceo/index.html +1 -1
  198. package/apps/pwa/out/ceo/index.txt +23 -23
  199. package/apps/pwa/out/chat/index.html +1 -1
  200. package/apps/pwa/out/chat/index.txt +22 -22
  201. package/apps/pwa/out/consult/index.html +1 -1
  202. package/apps/pwa/out/consult/index.txt +23 -23
  203. package/apps/pwa/out/control/index.html +1 -1
  204. package/apps/pwa/out/control/index.txt +23 -23
  205. package/apps/pwa/out/decisions/index.html +1 -1
  206. package/apps/pwa/out/decisions/index.txt +22 -22
  207. package/apps/pwa/out/design-check/index.html +1 -1
  208. package/apps/pwa/out/design-check/index.txt +23 -23
  209. package/apps/pwa/out/editor/index.html +1 -1
  210. package/apps/pwa/out/editor/index.txt +24 -23
  211. package/apps/pwa/out/exec/index.html +1 -1
  212. package/apps/pwa/out/exec/index.txt +23 -23
  213. package/apps/pwa/out/field/index.html +1 -1
  214. package/apps/pwa/out/field/index.txt +23 -23
  215. package/apps/pwa/out/healthz +1 -1
  216. package/apps/pwa/out/index.html +1 -1
  217. package/apps/pwa/out/index.txt +22 -22
  218. package/apps/pwa/out/inside/index.html +1 -1
  219. package/apps/pwa/out/inside/index.txt +22 -22
  220. package/apps/pwa/out/intake/index.html +1 -1
  221. package/apps/pwa/out/intake/index.txt +23 -23
  222. package/apps/pwa/out/live/index.html +1 -1
  223. package/apps/pwa/out/live/index.txt +23 -23
  224. package/apps/pwa/out/live-run/index.html +1 -1
  225. package/apps/pwa/out/live-run/index.txt +24 -23
  226. package/apps/pwa/out/loops/index.html +1 -1
  227. package/apps/pwa/out/loops/index.txt +22 -22
  228. package/apps/pwa/out/market/index.html +1 -1
  229. package/apps/pwa/out/market/index.txt +22 -22
  230. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  231. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  232. package/apps/pwa/out/morning/index.html +1 -1
  233. package/apps/pwa/out/morning/index.txt +23 -23
  234. package/apps/pwa/out/observatory/index.html +1 -1
  235. package/apps/pwa/out/observatory/index.txt +23 -23
  236. package/apps/pwa/out/ops/checklist/index.html +1 -1
  237. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  238. package/apps/pwa/out/ops/release/index.html +1 -1
  239. package/apps/pwa/out/ops/release/index.txt +22 -22
  240. package/apps/pwa/out/ops/seats/index.html +1 -1
  241. package/apps/pwa/out/ops/seats/index.txt +22 -22
  242. package/apps/pwa/out/outputs/index.html +1 -1
  243. package/apps/pwa/out/outputs/index.txt +22 -22
  244. package/apps/pwa/out/reflection/index.html +1 -1
  245. package/apps/pwa/out/reflection/index.txt +23 -23
  246. package/apps/pwa/out/scheduler/index.html +1 -1
  247. package/apps/pwa/out/scheduler/index.txt +23 -23
  248. package/apps/pwa/out/sessions/index.html +1 -1
  249. package/apps/pwa/out/sessions/index.txt +22 -22
  250. package/apps/pwa/out/settings/devices/index.html +1 -1
  251. package/apps/pwa/out/settings/devices/index.txt +23 -23
  252. package/apps/pwa/out/settings/index.html +1 -1
  253. package/apps/pwa/out/settings/index.txt +23 -23
  254. package/apps/pwa/out/setup/done/index.html +1 -1
  255. package/apps/pwa/out/setup/done/index.txt +23 -23
  256. package/apps/pwa/out/setup/index.html +1 -1
  257. package/apps/pwa/out/setup/index.txt +23 -23
  258. package/apps/pwa/out/share/index.html +1 -1
  259. package/apps/pwa/out/share/index.txt +23 -23
  260. package/apps/pwa/out/showroom/index.html +1 -1
  261. package/apps/pwa/out/showroom/index.txt +22 -22
  262. package/apps/pwa/out/tasks/index.html +1 -1
  263. package/apps/pwa/out/tasks/index.txt +23 -23
  264. package/apps/pwa/out/term/index.html +1 -1
  265. package/apps/pwa/out/term/index.txt +23 -23
  266. package/apps/pwa/out/today/index.html +1 -1
  267. package/apps/pwa/out/today/index.txt +23 -23
  268. package/apps/pwa/out/trace/index.html +1 -1
  269. package/apps/pwa/out/trace/index.txt +23 -23
  270. package/apps/pwa/out/vault/index.html +1 -1
  271. package/apps/pwa/out/vault/index.txt +23 -23
  272. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  273. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  274. package/apps/pwa/out/workflows/index.html +1 -1
  275. package/apps/pwa/out/workflows/index.txt +23 -23
  276. package/apps/pwa/out/workspace/index.html +1 -1
  277. package/apps/pwa/out/workspace/index.txt +23 -23
  278. package/apps/pwa/out/worktrees/index.html +1 -1
  279. package/apps/pwa/out/worktrees/index.txt +23 -23
  280. package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
  281. package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
  282. package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
  283. package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
  284. package/catalog/models/openai/gpt-6-astra.yaml +6 -0
  285. package/catalog/models/openai/gpt-6-luna.yaml +6 -0
  286. package/catalog/models/openai/gpt-6-sol.yaml +6 -0
  287. package/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
  288. package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
  289. package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
  290. package/catalog/providers/openrouter.yaml +2 -0
  291. package/graphs/implement-loop.yaml +31 -0
  292. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  293. package/graphs/log-horizon/recipes.yaml +3 -0
  294. package/graphs/ops/harness-gc.yaml +17 -0
  295. package/graphs/ops/recipes.yaml +3 -0
  296. package/graphs/overlays/README.md +1 -1
  297. package/graphs/overlays/stop-heal-ladder.yaml +105 -0
  298. package/graphs/release/recipes.yaml +1 -1
  299. package/graphs/release/release-loop.yaml +6 -2
  300. package/graphs/release-rehearsal/recipes.yaml +12 -0
  301. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  302. package/package.json +4 -1
  303. package/scripts/add-api-key.sh +1 -1
  304. package/scripts/bench-report.ts +82 -3
  305. package/scripts/ci-typecheck-changed.ts +80 -14
  306. package/scripts/fleet/bedrock-pod-secret.ts +122 -0
  307. package/scripts/fleet/node-setup-linux.sh +97 -0
  308. package/scripts/fleet/node-setup.sh +11 -0
  309. package/scripts/fleet/zai-pod-secret.ts +86 -0
  310. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  311. package/scripts/land-global-checks.ts +3 -0
  312. package/scripts/lib/typecheck-ratchet.ts +51 -0
  313. package/scripts/measure-log-diet-2.ts +213 -0
  314. package/scripts/measure-tsc-affected-roots.ts +289 -0
  315. package/scripts/openai-relay-server.ts +5 -1
  316. package/scripts/release-loop/docs-node.ts +258 -43
  317. package/scripts/release-loop/gate-executor.ts +28 -0
  318. package/scripts/release-loop/gate-method.ts +59 -0
  319. package/scripts/release-loop/gate-node.ts +335 -33
  320. package/scripts/release-loop/gate-wall.ts +208 -0
  321. package/scripts/release-loop/known-issues-node.ts +53 -8
  322. package/scripts/release-loop/publish-at.ts +14 -0
  323. package/scripts/release-loop/publish-node.ts +17 -2
  324. package/scripts/release-loop/resume-release.ts +40 -4
  325. package/scripts/release-loop/resume.ts +94 -0
  326. package/scripts/release-loop/shard-plan.ts +3 -11
  327. package/scripts/release-loop/tui-node-checks.ts +22 -0
  328. package/scripts/release-loop/unattended-release.ts +29 -7
  329. package/scripts/rhythm/daily.ts +51 -2
  330. package/scripts/rhythm/weekly.ts +3 -2
  331. package/scripts/tsc-baseline-cache.ts +147 -0
  332. package/scripts/tsc-main-safety-net.ts +189 -0
  333. package/scripts/usage-rollup.ts +64 -8
  334. package/src/acp/codex-plugins.ts +48 -6
  335. package/src/agent/monad-agent-turn.ts +67 -5
  336. package/src/agent/run-context.ts +20 -0
  337. package/src/agent/tool-profile.ts +28 -2
  338. package/src/agent-mission/acp-judge.ts +8 -2
  339. package/src/agent-mission/capabilities-cli.ts +16 -1
  340. package/src/agent-mission/driver.ts +19 -4
  341. package/src/agent-mission/pr-review-watch.ts +6 -2
  342. package/src/agent-mission/resource-ladder.ts +8 -3
  343. package/src/agent-mission/review-loop.ts +41 -7
  344. package/src/agent-substrate/acp-implementer.ts +139 -0
  345. package/src/agent-substrate/acp-reviewer.ts +17 -8
  346. package/src/agent-substrate/pr-reviewer.ts +191 -28
  347. package/src/agent-substrate/review-intent.ts +6 -4
  348. package/src/agent-substrate/self-review-cli.ts +155 -21
  349. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  350. package/src/ask-user-question/pending-questions.ts +8 -2
  351. package/src/autopilot/build/llm-conflict-merge.ts +216 -12
  352. package/src/autopilot/codebase-grounding.ts +44 -0
  353. package/src/autopilot/llm-control-brain.ts +13 -1
  354. package/src/autopilot/mission-codebase-gate.ts +8 -77
  355. package/src/autopilot/mission-critique.ts +18 -5
  356. package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
  357. package/src/autopilot/mission-trace.ts +12 -1
  358. package/src/autopilot/pr-manager.ts +12 -3
  359. package/src/autopilot/system-lookback-run.ts +16 -10
  360. package/src/bench/bench.ts +183 -0
  361. package/src/boot/acp-server.ts +4 -7
  362. package/src/boot/acp-socket-path.ts +7 -0
  363. package/src/briefing/brief-items.ts +21 -13
  364. package/src/budget/fetchers/grok.ts +15 -5
  365. package/src/budget/llm-cost.ts +37 -5
  366. package/src/budget/types.ts +8 -2
  367. package/src/budget/unified-usage.ts +88 -6
  368. package/src/chat/index.ts +12 -3
  369. package/src/cli/agent-cli.ts +20 -0
  370. package/src/cli/bench-cli.ts +34 -0
  371. package/src/cli/brief-cli.ts +27 -21
  372. package/src/cli/cli-user-error.ts +9 -2
  373. package/src/cli/guardian-cli.ts +26 -1
  374. package/src/cli/image-cli.ts +101 -0
  375. package/src/cli/log-event-names.ts +7 -0
  376. package/src/cli/logs-cli.ts +1 -0
  377. package/src/cli/mcp-login.ts +111 -37
  378. package/src/cli/plugin-cli.ts +21 -1
  379. package/src/cli/pod-cli.ts +26 -0
  380. package/src/cli/pr-cli.ts +90 -5
  381. package/src/cli/pr-land-overlap-evidence.ts +279 -0
  382. package/src/cli/release-cli.ts +63 -12
  383. package/src/cli/rfc-status.ts +52 -2
  384. package/src/cli/self-update.ts +277 -10
  385. package/src/cli/skills-cli.ts +12 -3
  386. package/src/cli/tasks-cli.ts +241 -30
  387. package/src/cli/usage-cli.ts +91 -8
  388. package/src/context-bus/context-first.ts +51 -2
  389. package/src/context-bus/context-now-surfaces.ts +13 -2
  390. package/src/context-bus/long-term-memory.ts +3 -1
  391. package/src/context-bus/nightly-condense.ts +3 -2
  392. package/src/core-turn/run-goal-loop.ts +87 -2
  393. package/src/dashboard/ad-run-setup-bindings.ts +279 -0
  394. package/src/dashboard/chat-fold.ts +20 -0
  395. package/src/dashboard/first-screen-band.ts +151 -1
  396. package/src/dashboard/index.ts +45 -281
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
  398. package/src/dashboard/stale-install-check.ts +24 -2
  399. package/src/dashboard/turn-stream-formatter.ts +25 -0
  400. package/src/debug/log-diet.ts +190 -0
  401. package/src/debug/log.ts +70 -17
  402. package/src/display/coordinator.ts +25 -2
  403. package/src/domains/coo-admin-tool.ts +27 -0
  404. package/src/domains/cron-match.ts +1 -0
  405. package/src/domains/outbound-alert.ts +17 -6
  406. package/src/domains/release-tool.ts +158 -10
  407. package/src/domains/schedule-registry.ts +10 -7
  408. package/src/domains/schedule-runner.ts +1 -0
  409. package/src/elanous-config-dir.ts +2 -2
  410. package/src/elanous-daemon.ts +3 -3
  411. package/src/error-report/report.ts +21 -4
  412. package/src/execution-loop/launch-gate.ts +1 -1
  413. package/src/expression/i18n/messages.en.ts +5 -0
  414. package/src/expression/i18n/messages.ja.ts +5 -0
  415. package/src/expression/i18n/messages.ko.ts +5 -0
  416. package/src/expression/i18n/messages.zh.ts +5 -0
  417. package/src/expression/i18n/types.ts +8 -0
  418. package/src/github/pr-labels.ts +2 -0
  419. package/src/graph-runner/graph-cli.ts +42 -1
  420. package/src/graph-runner/runner.ts +218 -8
  421. package/src/grok/usage.ts +23 -2
  422. package/src/grounding/ref-index.ts +253 -0
  423. package/src/harness/dispatch-backpressure.ts +267 -0
  424. package/src/harness/harness-clean.ts +199 -78
  425. package/src/harness/harness-cli-command.ts +229 -35
  426. package/src/harness/harness-gc.ts +331 -0
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-stop.ts +4 -2
  429. package/src/harness/harness-substrate-default.ts +214 -8
  430. package/src/harness/launch-registry.ts +6 -0
  431. package/src/harness/nested-elanous-policy.ts +4 -2
  432. package/src/harness/worktree-branch-prefix.ts +9 -0
  433. package/src/hq/fence-wrapper.ts +7 -0
  434. package/src/hq/fence.ts +187 -0
  435. package/src/hq/hq.ts +33 -2
  436. package/src/hq/lease.ts +13 -0
  437. package/src/hq/seats.ts +133 -21
  438. package/src/images/image-ledger.ts +179 -0
  439. package/src/index.ts +250 -69
  440. package/src/instance/child-scope.ts +32 -1
  441. package/src/instance/dev-project.ts +133 -0
  442. package/src/instance/resolve.ts +24 -0
  443. package/src/instance/spawn-elanous.ts +45 -0
  444. package/src/intake-plane/collect-github.ts +19 -1
  445. package/src/intake-plane/digest.ts +45 -20
  446. package/src/intake-plane/lens.ts +36 -8
  447. package/src/intake-plane/ref-prefetch.ts +110 -0
  448. package/src/intelligence-map/model-alias.ts +6 -0
  449. package/src/intelligence-map/model-catalog.ts +113 -0
  450. package/src/knowledge/kgs/pack.ts +5 -2
  451. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  452. package/src/knowledge/tools/knowledge-query.ts +20 -2
  453. package/src/knowledge/write.ts +234 -2
  454. package/src/llm/bedrock-eventstream.ts +215 -0
  455. package/src/llm/bedrock-provider.ts +248 -0
  456. package/src/llm/bedrock.ts +491 -0
  457. package/src/llm/openrouter-byok-cost.ts +96 -0
  458. package/src/llm/openrouter-deepseek.ts +151 -0
  459. package/src/llm/openrouter-upstream-pins.config.ts +25 -0
  460. package/src/llm/provider-credentials.ts +3 -1
  461. package/src/llm/zai-coding-plan.ts +700 -0
  462. package/src/llm.ts +383 -41
  463. package/src/loops/budget.ts +150 -0
  464. package/src/loops/checker.ts +148 -9
  465. package/src/loops/orchestrator/resync-shadow.ts +34 -7
  466. package/src/loops/orchestrator/seat-share.ts +6 -49
  467. package/src/loops/orchestrator/traffic.ts +5 -81
  468. package/src/market/signed-index.ts +42 -0
  469. package/src/maturity/feature-maturity.ts +2 -2
  470. package/src/mcp/mcp-oauth.ts +136 -17
  471. package/src/model-tier/llm-tier-map.ts +52 -4
  472. package/src/models/prompts.ts +23 -1
  473. package/src/mss/logging/horizon-watch.ts +168 -0
  474. package/src/mss/logging/log-store.ts +262 -26
  475. package/src/native-tool-catalog.ts +1 -1
  476. package/src/nexus/api/consult-requests.ts +7 -10
  477. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  478. package/src/nexus/api/error-reports.ts +30 -8
  479. package/src/nexus/api/http-server.ts +8 -0
  480. package/src/nexus/api/loop-resources.ts +42 -0
  481. package/src/nexus/api/missions.ts +73 -2
  482. package/src/nexus/api/ops-api.ts +18 -0
  483. package/src/nexus/api/outbound-report.ts +8 -3
  484. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  485. package/src/nexus/index.ts +17 -75
  486. package/src/nexus/outbound/format.ts +2 -0
  487. package/src/nexus/outbound/router.ts +198 -13
  488. package/src/nexus/tools-kind.ts +78 -0
  489. package/src/oauth/codex-account-rotation.ts +55 -20
  490. package/src/oauth/codex-account-store.ts +451 -23
  491. package/src/oauth/fallback-chain.ts +75 -15
  492. package/src/onboarding/first-run.ts +37 -18
  493. package/src/onboarding/web-first.ts +20 -2
  494. package/src/onboarding.ts +2 -1
  495. package/src/ops/machine-heartbeat.ts +185 -0
  496. package/src/ops/overview-cache.ts +175 -0
  497. package/src/ops/overview.ts +8 -0
  498. package/src/plugins/adapters/claude-package.ts +4 -12
  499. package/src/plugins/core/capability-policy.ts +141 -0
  500. package/src/plugins/core/host.ts +21 -8
  501. package/src/plugins/core/manifest.ts +19 -2
  502. package/src/plugins/core/trust-store.ts +15 -0
  503. package/src/plugins/core/types.ts +12 -0
  504. package/src/plugins/install/market-fetch.ts +68 -16
  505. package/src/plugins/install/plugin-install.ts +187 -16
  506. package/src/plugins/maker/plugin-maker.ts +25 -20
  507. package/src/plugins/maker/wizard-generate.ts +16 -2
  508. package/src/policy/llm-policy.ts +14 -1
  509. package/src/process/pid-liveness.ts +1 -1
  510. package/src/prompt-cache/openai.ts +13 -6
  511. package/src/prompt-cache/openrouter.ts +94 -0
  512. package/src/prompt-cache/types.ts +5 -0
  513. package/src/prompt-enhance/enhance.ts +69 -5
  514. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  515. package/src/prompt-library/universal-preamble.ts +2 -2
  516. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  517. package/src/registry/loader.ts +6 -1
  518. package/src/release-loop/checklist.ts +24 -9
  519. package/src/release-loop/feature-store.ts +3 -0
  520. package/src/release-loop/gate-shards.ts +48 -4
  521. package/src/release-loop/landed-to-green.ts +81 -0
  522. package/src/release-loop/light-rc.ts +11 -1
  523. package/src/release-loop/merged-pr-checklist.ts +10 -0
  524. package/src/release-loop/placement.ts +107 -23
  525. package/src/release-loop/rehearsal.ts +317 -0
  526. package/src/release-loop/release-schedule.ts +13 -1
  527. package/src/release-loop/rubric-types.ts +1 -0
  528. package/src/release-loop/rubric.ts +2 -2
  529. package/src/requirements/requirement-ledger.ts +536 -0
  530. package/src/retro/daily.ts +26 -12
  531. package/src/seat-loop/seat-loop.ts +66 -11
  532. package/src/seat-loop/traffic-signal.ts +44 -0
  533. package/src/self-dev/ask-launch-flow.ts +2 -2
  534. package/src/self-dev/dev-cli.ts +109 -11
  535. package/src/self-dev/dev-pipeline.ts +11 -8
  536. package/src/self-dev/draft-residue.ts +475 -0
  537. package/src/self-dev/draft-sweep.ts +254 -10
  538. package/src/self-dev/draft-triage-rules.ts +27 -1
  539. package/src/self-dev/graph-journey-route.ts +6 -0
  540. package/src/self-dev/launch-preflight-text.ts +549 -0
  541. package/src/self-dev/launch-preflight.ts +10 -545
  542. package/src/self-dev/orchestrate-cli.ts +82 -5
  543. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  544. package/src/self-dev/orchestrate.ts +49 -141
  545. package/src/self-dev/review-provider-fallback.ts +115 -19
  546. package/src/self-dev/run-store.ts +1 -3
  547. package/src/self-dev/run-supervisor.ts +190 -36
  548. package/src/self-dev/run-types.ts +191 -0
  549. package/src/self-dev/shard-aggregate.ts +61 -13
  550. package/src/self-dev/shard-plan.ts +5 -1
  551. package/src/self-dev/shard-run.ts +23 -5
  552. package/src/self-dev/supervisor-verdict-edges.ts +3 -4
  553. package/src/self-implement/blocked-draft-policy.ts +3 -19
  554. package/src/self-implement/budget-gate.ts +53 -13
  555. package/src/self-implement/child-context-composition.ts +139 -0
  556. package/src/self-implement/child-llm-preference.ts +13 -5
  557. package/src/self-implement/claude-acp-implement.ts +67 -0
  558. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  559. package/src/self-implement/flex-signals.ts +59 -0
  560. package/src/self-implement/follow-up-goals.ts +114 -38
  561. package/src/self-implement/frozen-merges.ts +8 -3
  562. package/src/self-implement/gate-baseline-reap.ts +157 -0
  563. package/src/self-implement/gate-baseline.ts +78 -16
  564. package/src/self-implement/gate-cli.ts +12 -2
  565. package/src/self-implement/gate-remote.ts +17 -6
  566. package/src/self-implement/goal-author-decompose.ts +10 -2
  567. package/src/self-implement/goal-author.ts +48 -13
  568. package/src/self-implement/goal-digest.ts +19 -0
  569. package/src/self-implement/graph-overlay-condition.ts +32 -0
  570. package/src/self-implement/graph-overlay-yaml.ts +41 -7
  571. package/src/self-implement/graph-templates.ts +33 -1
  572. package/src/self-implement/graph-yaml.ts +56 -0
  573. package/src/self-implement/headless-elanous-driver.ts +11 -9
  574. package/src/self-implement/heal-intake.ts +5 -1
  575. package/src/self-implement/host-regate.ts +120 -29
  576. package/src/self-implement/l8-merge-queue.ts +67 -5
  577. package/src/self-implement/merge-train.ts +131 -0
  578. package/src/self-implement/off-diff-evidence.ts +9 -0
  579. package/src/self-implement/orchestrator.ts +271 -25
  580. package/src/self-implement/review-finding-recurrence.ts +28 -0
  581. package/src/self-implement/rework-policy.ts +2 -1
  582. package/src/self-implement/round-summary-card.ts +63 -0
  583. package/src/self-implement/run-ledger.ts +4 -3
  584. package/src/self-implement/run-step-projection.ts +147 -0
  585. package/src/self-implement/run-stop.ts +1 -1
  586. package/src/self-implement/running-runs.ts +75 -5
  587. package/src/self-implement/seams.ts +83 -4
  588. package/src/self-implement/self-implement-cli.ts +12 -5
  589. package/src/self-implement/stop-autoheal.ts +69 -2
  590. package/src/self-implement/train-gate-remote.ts +158 -0
  591. package/src/session-runtime/index.ts +10 -1
  592. package/src/session-runtime/retry-api.ts +11 -1
  593. package/src/session-runtime/retry-policy.ts +2 -1
  594. package/src/skills/gift-install.ts +119 -0
  595. package/src/skills/runner.ts +59 -2
  596. package/src/skills/skill-feedback.ts +31 -1
  597. package/src/skills/skill-tier.ts +1 -0
  598. package/src/smart-wizard/capability-index.ts +231 -0
  599. package/src/smart-wizard/rung.ts +74 -0
  600. package/src/steward/launch.ts +22 -10
  601. package/src/steward/triage-budget.ts +62 -0
  602. package/src/steward/triage.ts +87 -24
  603. package/src/storage/file-lock.ts +8 -1
  604. package/src/task-agent/actions.ts +66 -5
  605. package/src/task-agent/card-evidence.ts +59 -13
  606. package/src/task-agent/completion-evidence.ts +5 -0
  607. package/src/task-agent/cover.ts +101 -3
  608. package/src/task-agent/judge.ts +20 -3
  609. package/src/task-agent/land-order-ledger.ts +95 -0
  610. package/src/task-agent/land-worktree.ts +201 -0
  611. package/src/task-agent/live-move-history.ts +219 -0
  612. package/src/task-agent/live-moves.ts +451 -34
  613. package/src/task-agent/parent-host.ts +117 -8
  614. package/src/task-agent/rejudge-on-head.ts +352 -0
  615. package/src/task-agent/review-prior-fix.ts +146 -0
  616. package/src/task-agent/review-result-capture.ts +218 -0
  617. package/src/task-agent/run-adopt.ts +136 -0
  618. package/src/task-agent/shadow.ts +154 -14
  619. package/src/task-agent/task-hand.ts +186 -14
  620. package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
  621. package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
  622. package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
  623. package/src/task-orchestrator/surfaces/pod-child-providers.ts +42 -0
  624. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  625. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +94 -7
  626. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  627. package/src/task-orchestrator/surfaces/pod-lease.ts +110 -17
  628. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +32 -3
  629. package/src/task-orchestrator/surfaces/pod-pool.ts +86 -18
  630. package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
  631. package/src/task-orchestrator/surfaces/self-implement-pod.ts +463 -50
  632. package/src/task-orchestrator/surfaces/self-implement.ts +25 -3
  633. package/src/telegram-service.ts +5 -1
  634. package/src/telegram.ts +17 -4
  635. package/src/time/format.ts +13 -4
  636. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  637. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  638. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  639. package/src/typecheck-ratchet.ts +1 -0
  640. package/src/user-config.ts +180 -32
  641. package/src/ux-sim/slash-menu-frames.ts +168 -0
  642. package/src/version/packed-revision.json +1 -1
  643. package/src/web-terminal/preview-tap-registry.ts +5 -2
  644. package/src/workflow-runtime/triggers/registry.ts +59 -0
  645. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  646. package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
  647. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  648. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  649. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  650. package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  652. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  653. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  654. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  656. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  661. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  670. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  671. package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  684. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  692. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  697. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  699. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  703. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  708. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  713. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  714. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  716. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  717. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  725. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  728. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  738. package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  741. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  745. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  746. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  802. package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
  803. /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_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,6 +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';
26
+ import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeWaiver, type AcceptedRegression, type GateExecutorOverride } from '../../scripts/release-loop/resume.js';
25
27
 
26
28
  type BashRun = WorkflowDeps['runBash'];
27
29
 
@@ -38,7 +40,8 @@ export interface GraphRunState {
38
40
  path: string[];
39
41
  /** startedAt/endedAt (ISO) and seconds are written when the node runs; ledgers before GRAPH-NODE-TIMES (0.2.19) have none. */
40
42
  nodes: Array<{ nodeId: string; ok: boolean; exit: number | null; executed: boolean; output?: unknown; error?: string; decidedBy?: string; decidedAt?: string;
41
- startedAt?: string; endedAt?: string; seconds?: number }>;
43
+ startedAt?: string; endedAt?: string; seconds?: number;
44
+ waiver?: { reason: string; at: string; original: { exit: number | null; output?: unknown; error?: string } } }>;
42
45
  /** The node now running and when it started; cleared when its record is written. */
43
46
  currentNode?: { nodeId: string; startedAt: string };
44
47
  input?: unknown;
@@ -49,10 +52,14 @@ export interface GraphRunState {
49
52
  graphSnapshot?: { graphSha: string; recipesSha: string };
50
53
  graphPath?: string;
51
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 }>;
52
57
  growth?: GraphGrowth[];
53
58
  growthRejections?: Array<{ from: string; outcome: string; reason: string }>;
54
59
  growthPark?: { from: string; outcome: string; reason: string; decisionId: string; decisionRef: string; growth: GraphGrowth; command?: GrowthCommand; approval?: string };
55
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[];
56
63
  executed: number;
57
64
  dryRun: boolean;
58
65
  statePath: string;
@@ -68,7 +75,15 @@ export interface GraphRunOptions {
68
75
  resumeRunId?: string;
69
76
  resumeGraphId?: string;
70
77
  fromNodeId?: string;
78
+ /** 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
+ /** Release-only: add accepted issues independently of a waiver at a restart boundary. */
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 };
71
84
  useCurrentGraph?: boolean;
85
+ /** Internal unit invocation context, propagated only by runGraph. */
86
+ unitContext?: { parentRunId: string; ancestors: readonly string[]; remainingSteps: number };
72
87
  /**
73
88
  * RELEASE-LEDGER-UNIVERSE — stamp every cmd: child with this run's ledger root (`ELANOUS_STATE_DIR`).
74
89
  * Without it a child launched from a non-leader tree (`bun scripts/...` with cwd = that tree) re-resolves
@@ -383,11 +398,63 @@ function nextNode(edges: readonly GraphEdgeSpec[], nodeId: string, exitOutcome:
383
398
  return edge.map?.[exitOutcome] ?? edge.fallback?.[0]?.node;
384
399
  }
385
400
 
401
+ type ResolvedUnit = { path: string; template: GraphTemplateSpec; hash: string };
402
+
403
+ function resolveUnit(call: string, callerPath: string): ResolvedUnit {
404
+ const [id, requested] = call.split('@');
405
+ const repo = join(dirname(fileURLToPath(import.meta.url)), '..', '..');
406
+ const directories = [join(dirname(callerPath), 'units'), dirname(callerPath), join(repo, 'graphs', 'units'), join(getElanousConfigDir(), 'graphs', 'units')];
407
+ for (const dir of directories) {
408
+ if (!existsSync(dir)) continue;
409
+ const matches = readdirSync(dir).filter(file => /\.ya?ml$/.test(file) && file !== 'recipes.yaml' && file !== 'recipes.yml').flatMap(file => {
410
+ const path = join(dir, file);
411
+ const source = readFileSync(path, 'utf8');
412
+ const header: unknown = parseYaml(source);
413
+ if (!header || typeof header !== 'object' || Array.isArray(header) || (header as Record<string, unknown>).graph_id !== id) return [];
414
+ const parsed = parseGraphTemplateYaml(source, path);
415
+ if (parsed.errors.length) throw new Error(parsed.errors.map(e => `${e.path}: ${e.message}`).join('\n'));
416
+ const template = parsed.template!;
417
+ return template.unit && (requested === String(template.version) || requested === `^${template.version}`)
418
+ ? [{ path, template, hash: createHash('sha256').update(source).digest('hex') }] : [];
419
+ });
420
+ if (matches.length > 1) throw new Error(`ambiguous unit: ${call}`);
421
+ if (matches.length) return matches[0]!;
422
+ }
423
+ throw new Error(`unit not found: ${call}`);
424
+ }
425
+
426
+ function validateUnitCalls(graph: GraphTemplateSpec, path: string, ancestors: readonly string[] = []): Map<string, ResolvedUnit> {
427
+ if (ancestors.includes(graph.graphId)) throw new Error(`unit cycle: ${[...ancestors, graph.graphId].join(' -> ')}`);
428
+ if (ancestors.length > 3) throw new Error('unit nesting exceeds depth 3');
429
+ const result = new Map<string, ResolvedUnit>();
430
+ for (const node of graph.nodes) {
431
+ if (node.kind !== 'subgraph' || node.call === undefined) continue;
432
+ const unit = resolveUnit(node.call!, path);
433
+ const contract = node.contract!;
434
+ const edge = graph.edges.find(e => e.from === node.nodeId);
435
+ if (!unit.template.unit || contract.inputs.length !== unit.template.unit.inputs.length ||
436
+ contract.inputs.some(key => !unit.template.unit!.inputs.includes(key)) ||
437
+ contract.outputs.length !== unit.template.unit.outputs.length ||
438
+ contract.outputs.some(key => !unit.template.unit!.outputs.includes(key)) || edge?.on !== 'outcome' ||
439
+ !edge.map || Object.keys(edge.map).length !== unit.template.unit.exits.length ||
440
+ unit.template.unit.exits.some(exit => !Object.hasOwn(edge.map!, exit))) {
441
+ debug.log('graph.unit', 'contract-mismatch', { graphId: graph.graphId, nodeId: node.nodeId, call: node.call });
442
+ throw new Error(`unit contract mismatch: ${node.nodeId} -> ${node.call}`);
443
+ }
444
+ validateUnitCalls(unit.template, unit.path, [...ancestors, graph.graphId]);
445
+ result.set(node.nodeId, unit);
446
+ }
447
+ return result;
448
+ }
449
+
386
450
  export async function runGraph(path: string, options: GraphRunOptions = {}): Promise<GraphRunState> {
387
451
  if (options.resumeRunId && options.runId) throw new Error('runId and resumeRunId cannot be combined');
388
452
  if (options.fromNodeId && !options.resumeRunId) throw new Error('--from requires --resume');
389
453
  if (options.useCurrentGraph && !options.resumeRunId) throw new Error('--use-current-graph requires --resume');
390
454
  if (options.variant && options.resumeRunId) throw new Error('variant cannot be combined with --resume');
455
+ if (options.releaseWaiver && (!options.resumeRunId || options.fromNodeId !== options.releaseWaiver.nodeId)) throw new Error('release waiver requires --resume --from <waived node>');
456
+ if (options.releaseAcceptedRegressions && (!options.resumeRunId || !options.fromNodeId || options.releaseWaiver)) throw new Error('accepted regressions require a release resume boundary');
457
+ if (options.releaseGateExecutor && (!options.resumeRunId || !options.fromNodeId)) throw new Error('gate executor override requires a release resume boundary');
391
458
  const root = options.deps?.root ?? effectiveInstanceRoot();
392
459
  const matchingRuns = options.resumeRunId && !options.resumeGraphId
393
460
  ? listGraphRuns(root).runs.filter((run) => run.runId === options.resumeRunId && run.graphPath === resolve(path)) : [];
@@ -420,6 +487,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
420
487
  const variant = options.variant ? createGraphVariant({ template: graph, ...options.variant }) : undefined;
421
488
  if (variant && !variant.ok) throw new Error(`graph variant rejected: ${JSON.stringify(variant.rejections)}`);
422
489
  if (variant?.ok) graph = variant.template;
490
+ const units = validateUnitCalls(graph, path, options.unitContext?.ancestors);
423
491
  const variantSource = variant?.ok ? stringifyYaml({ ...document,
424
492
  nodes: graph.nodes.map((node, index) => ({
425
493
  ...((document.nodes as Record<string, unknown>[])[index] ?? {}), node_id: node.nodeId, kind: node.kind,
@@ -498,7 +566,12 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
498
566
  if (options.resumeRunId && state.growth?.length && graphMode === 'current' && state.sourceHash !== approvalSourceHash) {
499
567
  throw new Error('graph or recipes changed since grown run');
500
568
  }
569
+ if (options.unitContext) {
570
+ if (state.parentRunId !== undefined && state.parentRunId !== options.unitContext.parentRunId) throw new Error('unit parent run changed');
571
+ state.parentRunId = options.unitContext.parentRunId;
572
+ }
501
573
  if (state.growth?.length) graph = withGrowth(graph, state.growth);
574
+ let waivedRecord: GraphRunState['nodes'][number] | undefined;
502
575
  if (options.fromNodeId) {
503
576
  if (state.status !== 'failed' || state.pending || state.dryRun) throw new Error('--from requires a failed, non-dry run without pending approval');
504
577
  if (graphMode === 'current' && (!state.sourceHash || state.sourceHash !== approvalSourceHash)) throw new Error('graph or recipes changed since failed run');
@@ -535,6 +608,55 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
535
608
  if (resolveNodeRecipe(graph.nodes.find((node) => node.nodeId === options.fromNodeId)!, recipes, catalogRoles).approval) {
536
609
  throw new Error('--from cannot restart an approval node');
537
610
  }
611
+ if (options.releaseWaiver) {
612
+ if (graphId !== 'release-loop') throw new Error('release waiver requires the release-loop graph');
613
+ 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');
615
+ const route = new Set<string>();
616
+ let cursor: string | undefined = nextNode(graph.edges, options.fromNodeId, 'ok', 'ok');
617
+ while (cursor && !route.has(cursor) && cursor !== 'known-issues') {
618
+ route.add(cursor);
619
+ cursor = nextNode(graph.edges, cursor, 'ok', 'ok');
620
+ }
621
+ if (cursor !== 'known-issues' || route.has('publish') || route.has('approve-publish')) throw new Error('waived node must reach known-issues before publication');
622
+ }
623
+ if (options.releaseAcceptedRegressions) {
624
+ if (graphId !== 'release-loop') throw new Error('accepted regressions require the release-loop graph');
625
+ const route = new Set<string>();
626
+ let cursor: string | undefined = options.fromNodeId;
627
+ while (cursor && !route.has(cursor) && cursor !== 'known-issues') {
628
+ route.add(cursor);
629
+ cursor = nextNode(graph.edges, cursor, 'ok', 'ok');
630
+ }
631
+ if (cursor !== 'known-issues' || route.has('publish') || route.has('approve-publish')) throw new Error('accepted regressions must reach known-issues before publication');
632
+ const checked = releaseResumeAcceptedRegressions(state, options.releaseAcceptedRegressions.requested, options.fromNodeId);
633
+ if (JSON.stringify(checked) !== JSON.stringify(options.releaseAcceptedRegressions.acceptedRegressions)) throw new Error('accepted regressions changed before restart');
634
+ state.input = { ...(state.input as Record<string, unknown>), acceptedRegressions: checked };
635
+ }
636
+ if (options.releaseWaiver) {
637
+ waivedRecord = state.nodes[from];
638
+ state.input = { ...(state.input as Record<string, unknown>), acceptedRegressions: options.releaseWaiver.acceptedRegressions };
639
+ } else if (graphId === 'release-loop' && state.nodes.slice(from).some((record) => record.waiver)) {
640
+ // Restarting at or before a waived node drops its waiver record, so its accepted issue goes with it.
641
+ state.input = { ...(state.input as Record<string, unknown>),
642
+ acceptedRegressions: releaseResumeAcceptedRegressions(state, [], options.fromNodeId) };
643
+ }
644
+ if (options.releaseGateExecutor) {
645
+ if (graphId !== 'release-loop') throw new Error('gate executor override requires the release-loop graph');
646
+ const override = releaseResumeGateExecutor(state, { from: options.fromNodeId, executor: options.releaseGateExecutor.executor, host: options.releaseGateExecutor.host });
647
+ const next: Record<string, unknown> = { ...(state.input as Record<string, unknown>), ...override.set };
648
+ for (const key of override.unset ?? []) delete next[key];
649
+ state.input = next;
650
+ state.inputOverrides = [...(state.inputOverrides ?? []), override];
651
+ debug.log('graph.runs', 'input-override', { graphId, runId, ...override });
652
+ }
653
+ if (state.unitCalls) {
654
+ const calls = state.unitCalls;
655
+ state.unitCalls = calls.filter(call => {
656
+ const keep = state.path.slice(0, from).filter(nodeId => nodeId === call.node).length;
657
+ return calls.filter(item => item.node === call.node).indexOf(call) < keep;
658
+ });
659
+ }
538
660
  state.path = state.path.slice(0, from);
539
661
  state.nodes = state.nodes.slice(0, from);
540
662
  state.executed = state.nodes.filter((node) => node.executed).length;
@@ -617,7 +739,11 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
617
739
  if (state.status === 'done' || state.status === 'failed' || state.status === 'budget-exceeded') state.finishedAt ??= new Date().toISOString();
618
740
  persistOwnedRun(state, runnerOwner);
619
741
  };
620
- const log = options.deps?.log ?? ((event: string, data: Record<string, unknown>) => debug.log('graph.runner', event, data));
742
+ const baseLog = options.deps?.log ?? ((event: string, data: Record<string, unknown>) => debug.log('graph.runner', event, data));
743
+ // RFC §U: every event of a unit (child) run carries its parentRunId.
744
+ const log = options.unitContext
745
+ ? (event: string, data: Record<string, unknown>) => baseLog(event, { ...data, parentRunId: options.unitContext!.parentRunId })
746
+ : baseLog;
621
747
  const visits = new Map<string, number>();
622
748
  for (const nodeId of state.path) visits.set(nodeId, (visits.get(nodeId) ?? 0) + 1);
623
749
  let current: string | undefined = options.fromNodeId ?? state.pending?.nodeId ?? state.path.at(-1) ?? graph.entryNode;
@@ -643,7 +769,9 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
643
769
  const completed = state.nodes.at(-1);
644
770
  const resumingCompleted = options.resumeRunId !== undefined && !options.fromNodeId && completed?.nodeId === current &&
645
771
  state.path.at(-1) === current && !resumingPending;
646
- if (!resumingPending && !resumingCompleted && (visits.get(current) ?? 0) >= node.maxVisits) {
772
+ const usedSteps = state.path.length + (state.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
773
+ if (!resumingPending && !resumingCompleted && ((visits.get(current) ?? 0) >= node.maxVisits ||
774
+ (options.unitContext && usedSteps >= options.unitContext.remainingSteps))) {
647
775
  state.status = 'budget-exceeded';
648
776
  log('budget-exceeded', { graphId, runId, nodeId: current });
649
777
  persist();
@@ -692,7 +820,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
692
820
  let exit: number | null = null;
693
821
  let error: string | undefined;
694
822
  let output: unknown;
695
- if (command && (!approval || state.dryRun || ok) && (!state.dryRun || command.dry_run_command) && !resumingCompleted) {
823
+ const waiving = options.releaseWaiver?.nodeId === current && waivedRecord !== undefined;
824
+ if (command && !waiving && (!approval || state.dryRun || ok) && (!state.dryRun || command.dry_run_command) && !resumingCompleted) {
696
825
  const outputs: Record<string, unknown> = Object.create(null);
697
826
  // 구조 산출(마지막 JSON 줄)이 있으면 그것을, 없으면 원문을 준다 — 다음 노드가 판단을 «값»으로 받는다.
698
827
  for (const previous of state.nodes) outputs[previous.nodeId] = lastJsonObject(previous.output) ?? previous.output ?? null;
@@ -752,7 +881,82 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
752
881
  error = result.error ? redactCredentials(result.error) : undefined;
753
882
  state.executed++;
754
883
  }
755
- if (prompt && !state.dryRun && !resumingCompleted) {
884
+ let unitExecuted = false;
885
+ if (units.has(current) && !waiving && state.dryRun && !resumingCompleted) {
886
+ // Dry run plans the walk only: no child run, no unit event, no unitCalls entry; the first declared exit stands in.
887
+ output = JSON.stringify({ outcome: units.get(current)!.template.unit!.exits[0], dryRun: true });
888
+ } else if (units.has(current) && !waiving && !resumingCompleted) {
889
+ const unit = units.get(current)!;
890
+ const contract = node.contract!;
891
+ const previous: Record<string, unknown> = Object.create(null);
892
+ for (const record of state.nodes) previous[record.nodeId] = lastJsonObject(record.output) ?? record.output;
893
+ const supplied = state.input && typeof state.input === 'object' && !Array.isArray(state.input)
894
+ ? state.input as Record<string, unknown> : {};
895
+ const inputs: Record<string, unknown> = Object.create(null);
896
+ for (const key of contract.inputs) {
897
+ const value = Object.hasOwn(supplied, key) ? supplied[key] : previous[key];
898
+ if (value !== undefined) inputs[key] = value;
899
+ }
900
+ const alreadySpent = state.path.length + (state.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
901
+ const remaining = options.unitContext ? options.unitContext.remainingSteps - alreadySpent : Infinity;
902
+ const childRunId = randomUUID();
903
+ const info = { graphId, runId, nodeId: current, unit: unit.template.graphId, childRunId, parentRunId: runId };
904
+ let entered = false;
905
+ try {
906
+ for (const key of contract.inputs) if (!Object.hasOwn(inputs, key)) throw new Error(`unit input missing: ${current}.${key}`);
907
+ if (createHash('sha256').update(readFileSync(unit.path, 'utf8')).digest('hex') !== unit.hash)
908
+ throw new Error(`unit source changed before call: ${current}`);
909
+ debug.log('graph.unit', 'enter', info);
910
+ log('graph.unit', { ...info, phase: 'enter' });
911
+ entered = true;
912
+ const child = await runGraph(unit.path, { runId: childRunId, input: inputs, dryRun: false,
913
+ pinChildUniverse: options.pinChildUniverse,
914
+ unitContext: { parentRunId: runId, ancestors: [...(options.unitContext?.ancestors ?? []), graphId],
915
+ remainingSteps: Math.min(node.budget!.innerSteps, remaining) }, deps: options.deps });
916
+ const steps = child.path.length + (child.unitCalls ?? []).reduce((sum, call) => sum + call.steps, 0);
917
+ const childExit = child.status === 'done' || child.status === 'failed' ? child.path.at(-1) : undefined;
918
+ // The last successful record carrying every contracted output is the source;
919
+ // intervening nodes (including terminal gates) need not reproduce those fields.
920
+ const values = child.nodes.reduce<Record<string, unknown> | undefined>((found, record) => {
921
+ if (!record.ok || !record.executed) return found;
922
+ const value = lastJsonObject(record.output) ??
923
+ (record.output && typeof record.output === 'object' && !Array.isArray(record.output)
924
+ ? record.output as Record<string, unknown> : undefined);
925
+ return value && contract.outputs.every(key => Object.hasOwn(value, key)) ? value : found;
926
+ }, undefined) ?? {};
927
+ state.unitCalls ??= [];
928
+ state.unitCalls.push({ node: current, unit: unit.template.graphId, version: unit.template.version,
929
+ hash: unit.hash, childRunId, exit: childExit ?? child.status, steps });
930
+ if (child.status === 'awaiting-approval') throw new Error(`unit cannot pause for approval: ${current}`);
931
+ if (child.status === 'budget-exceeded' || steps > node.budget!.innerSteps || steps > remaining) {
932
+ debug.log('graph.unit', 'budget-exhausted', { ...info, steps, innerSteps: node.budget!.innerSteps });
933
+ log('graph.unit', { ...info, phase: 'budget-exhausted', steps });
934
+ throw new Error(`unit inner_steps exceeded: ${current}`);
935
+ }
936
+ if (!childExit || !unit.template.unit!.exits.includes(childExit)) throw new Error(`unit exit missing: ${current}`);
937
+ if (child.status === 'done' && childExit === 'failed') throw new Error(`unit exit mismatch: ${current}`);
938
+ const result: Record<string, unknown> = { outcome: childExit };
939
+ for (const key of contract.outputs) {
940
+ if (!Object.hasOwn(values, key)) throw new Error(`unit output missing: ${current}.${key}`);
941
+ result[key] = values[key];
942
+ }
943
+ output = JSON.stringify(result);
944
+ ok = child.status === 'done';
945
+ debug.log('graph.unit', 'exit', { ...info, exit: childExit, steps });
946
+ log('graph.unit', { ...info, phase: 'exit', exit: childExit, steps });
947
+ } catch (cause) {
948
+ ok = false;
949
+ error = cause instanceof Error ? cause.message : String(cause);
950
+ if (entered) {
951
+ debug.log('graph.unit', 'exit', { ...info, error });
952
+ log('graph.unit', { ...info, phase: 'exit', error });
953
+ }
954
+ }
955
+ // A rejected invocation has no child ledger and did not execute a unit.
956
+ unitExecuted = existsSync(graphRunPath(unit.template.graphId, childRunId, root));
957
+ if (unitExecuted) state.executed++;
958
+ }
959
+ if (prompt && !waiving && !state.dryRun && !resumingCompleted) {
756
960
  const outputs: Record<string, { ok: boolean; output: unknown; durationMs: number }> = Object.create(null);
757
961
  for (const previous of state.nodes) outputs[previous.nodeId] = { ok: previous.ok, output: lastJsonObject(previous.output) ?? previous.output ?? null, durationMs: 0 };
758
962
  try {
@@ -775,6 +979,11 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
775
979
  // A wall clock stepped back mid-node must not record an end before the start.
776
980
  const nodeEndedAt = new Date(Math.max(Date.now(), Date.parse(nodeStartedAt))).toISOString();
777
981
  delete state.currentNode;
982
+ if (waiving) {
983
+ output = JSON.stringify({ outcome: 'ok', verdict: 'waived', summary: `waived ${current}`, reason: options.releaseWaiver!.reason });
984
+ ok = true;
985
+ exit = 0;
986
+ }
778
987
  if (resumingCompleted && completed) {
779
988
  ok = completed.ok;
780
989
  exit = completed.exit;
@@ -785,7 +994,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
785
994
  if (approval && !state.dryRun && !command) {
786
995
  output = JSON.stringify({ outcome: ok ? 'approved' : 'rejected', ...(state.pending?.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending?.decidedAt ?? null });
787
996
  }
788
- state.nodes.push({ nodeId: current, ok, exit, executed: (!!command && (!state.dryRun || !!command.dry_run_command)) || (!!prompt && !state.dryRun), ...((command || prompt || approval) && (!state.dryRun || !!command?.dry_run_command) && output !== undefined ? { output } : {}), ...(error ? { error } : {}),
997
+ 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 }) } } } : {}),
789
999
  ...(approval && state.pending ? { ...(state.pending.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending.decidedAt } : {}),
790
1000
  startedAt: nodeStartedAt, endedAt: nodeEndedAt, seconds });
791
1001
  }
@@ -793,7 +1003,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
793
1003
  delete state.pending;
794
1004
  delete state.approvalSourceHash;
795
1005
  }
796
- const reported = (prompt && !state.dryRun) || (command && (!state.dryRun || command.dry_run_command)) ? lastJsonObject(resumingCompleted ? completed?.output : output)?.outcome : undefined;
1006
+ const reported = waiving || units.has(current) || (prompt && !state.dryRun) || (command && (!state.dryRun || command.dry_run_command)) ? lastJsonObject(resumingCompleted ? completed?.output : output)?.outcome : undefined;
797
1007
  const namedOutcome = typeof reported === 'string' ? reported : undefined;
798
1008
  console.error(`[graph] ${current} ${ok ? 'ok' : 'fail'} (${seconds.toFixed(2)}s)`);
799
1009
  debug.log('graph.run', 'node', { graphId, runId, nodeId: current, phase: ok ? 'ok' : 'fail', seconds, exit });
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;
@@ -0,0 +1,253 @@
1
+ // Reference card builder — L0 card + L1 listing for one local-repo / local-docs source.
2
+ //
3
+ // Pure value out: nothing is written. File access goes through the injected
4
+ // `RefIndexFs`, and every read is capped (file count, bytes per file), so a
5
+ // full file body is never loaded. Persistence (`grounding index` → jsonl) and
6
+ // BM25 are deliberately not here — they are the next slice.
7
+
8
+ import { spawnSync } from 'node:child_process';
9
+ import { closeSync, openSync, readSync, readdirSync, statSync } from 'node:fs';
10
+ import { basename, join } from 'node:path';
11
+ import { GroundingSourceError, type GroundingSource } from './sources.js';
12
+
13
+ export interface RefIndexDirEntry {
14
+ name: string;
15
+ isDirectory: boolean;
16
+ }
17
+
18
+ export interface RefIndexFs {
19
+ /** Names directly under `dir`. Unreadable dir → empty list. */
20
+ readDir(dir: string): RefIndexDirEntry[];
21
+ /** At most `maxBytes` from the start of the file. `truncated` when the file is longer. */
22
+ readHead(file: string, maxBytes: number): { text: string; truncated: boolean } | undefined;
23
+ /** Modified time of a path, ms since epoch. */
24
+ mtimeMs(path: string): number | undefined;
25
+ /** Last commit time (ISO) of a git repo, when it has one. */
26
+ lastCommitAt(repoDir: string): string | undefined;
27
+ }
28
+
29
+ export interface RefIndexLimits {
30
+ /** Max markdown/readme/package files opened for one source. */
31
+ maxFiles: number;
32
+ /** Max bytes read from the head of any one file. */
33
+ maxBytesPerFile: number;
34
+ }
35
+
36
+ export const DEFAULT_REF_INDEX_LIMITS: RefIndexLimits = { maxFiles: 200, maxBytesPerFile: 16 * 1024 };
37
+
38
+ const ONE_LINE_MAX = 200;
39
+ const SKIP_DIRS = new Set(['node_modules']);
40
+
41
+ export interface ReferenceTitle {
42
+ /** Path relative to the source root. */
43
+ file: string;
44
+ title: string;
45
+ }
46
+
47
+ export interface ReferenceCard {
48
+ /** L0 — `name` is the repository's own name (package.json `name`, else its directory name), not the registry `id`. */
49
+ id: string;
50
+ kind: GroundingSource['kind'];
51
+ name: string;
52
+ oneLine: string;
53
+ directories: string[];
54
+ receivedAt?: string;
55
+ /** L1 */
56
+ titles: ReferenceTitle[];
57
+ commands: string[];
58
+ /** A file-count or byte limit cut the read short — the lists may be incomplete. */
59
+ truncated: boolean;
60
+ }
61
+
62
+ export function buildReferenceCard(
63
+ source: GroundingSource,
64
+ fs: RefIndexFs,
65
+ limits: Partial<RefIndexLimits> = {},
66
+ ): ReferenceCard {
67
+ if ((source.kind !== 'local-repo' && source.kind !== 'local-docs') || !source.path) {
68
+ throw new GroundingSourceError(`reference card needs a local-repo/local-docs path: ${source.id}`);
69
+ }
70
+ const root = source.path;
71
+ // A missing root would otherwise yield an empty, untruncated card indistinguishable from an empty repo.
72
+ if (fs.mtimeMs(root) === undefined) {
73
+ throw new GroundingSourceError(`reference card source path is not readable: ${source.id} (${root})`);
74
+ }
75
+ const { maxFiles, maxBytesPerFile } = { ...DEFAULT_REF_INDEX_LIMITS, ...limits };
76
+ let opened = 0;
77
+ let truncated = false;
78
+
79
+ const open = (file: string): string | undefined => {
80
+ if (opened >= maxFiles) {
81
+ truncated = true;
82
+ return undefined;
83
+ }
84
+ opened += 1;
85
+ const head = fs.readHead(file, maxBytesPerFile);
86
+ if (!head) return undefined;
87
+ if (head.truncated) truncated = true;
88
+
89
+ return head.text;
90
+ };
91
+
92
+ const top = fs.readDir(root).sort((a, b) => a.name.localeCompare(b.name));
93
+ const directories = top
94
+ .filter((e) => e.isDirectory && !e.name.startsWith('.') && !SKIP_DIRS.has(e.name))
95
+ .map((e) => e.name);
96
+
97
+ const titles: ReferenceTitle[] = [];
98
+ const readme = top.find((e) => !e.isDirectory && /^readme(\.[a-z]+)?$/i.test(e.name));
99
+ let oneLine = '';
100
+ if (readme) {
101
+ const text = open(join(root, readme.name));
102
+ if (text !== undefined) {
103
+ oneLine = firstParagraphLine(text);
104
+ for (const title of headingTitles(text)) titles.push({ file: readme.name, title });
105
+ }
106
+ }
107
+
108
+ const docRoots = source.kind === 'local-docs' ? [''] : directories.includes('docs') ? ['docs'] : [];
109
+ for (const rel of docRoots) {
110
+ for (const file of markdownFiles(fs, root, rel, maxFiles + 2)) {
111
+ if (file === readme?.name) continue;
112
+ const text = open(join(root, file));
113
+ if (text === undefined) continue;
114
+ for (const title of headingTitles(text)) titles.push({ file, title });
115
+ }
116
+ }
117
+
118
+ const commands: string[] = [];
119
+ let packageName: string | undefined;
120
+ if (top.some((e) => !e.isDirectory && e.name === 'package.json')) {
121
+ const raw = open(join(root, 'package.json'));
122
+ if (raw !== undefined) {
123
+ const pkg = parsePackage(raw);
124
+ packageName = pkg.name;
125
+ commands.push(...pkg.commands);
126
+ }
127
+ }
128
+
129
+ const receivedAt = receivedAtOf(source, fs, root);
130
+ return {
131
+ id: source.id,
132
+ kind: source.kind,
133
+ name: packageName ?? basename(root),
134
+ oneLine,
135
+ directories,
136
+ ...(receivedAt ? { receivedAt } : {}),
137
+ titles,
138
+ commands,
139
+ truncated,
140
+ };
141
+ }
142
+
143
+ function receivedAtOf(source: GroundingSource, fs: RefIndexFs, root: string): string | undefined {
144
+ if (source.kind === 'local-repo') {
145
+ const commit = fs.lastCommitAt(root);
146
+ if (commit) return commit;
147
+ }
148
+ const mtime = fs.mtimeMs(root);
149
+ return mtime === undefined ? undefined : new Date(mtime).toISOString();
150
+ }
151
+
152
+ /**
153
+ * Markdown paths (relative to `root`) under `rel`, sorted. Directory listing only — no bodies.
154
+ * The walk stops once `cap` paths are found: past the file budget the caller only needs to know
155
+ * «there was more» (→ truncated), not the whole tree.
156
+ */
157
+ function markdownFiles(fs: RefIndexFs, root: string, rel: string, cap: number): string[] {
158
+ const found: string[] = [];
159
+ const walk = (dirRel: string): void => {
160
+ if (found.length >= cap) return;
161
+ const entries = fs.readDir(dirRel ? join(root, dirRel) : root).sort((a, b) => a.name.localeCompare(b.name));
162
+ for (const e of entries) {
163
+ const childRel = dirRel ? join(dirRel, e.name) : e.name;
164
+ if (found.length >= cap) return;
165
+ if (e.isDirectory) {
166
+ if (!e.name.startsWith('.') && !SKIP_DIRS.has(e.name)) walk(childRel);
167
+ } else if (/\.md$/i.test(e.name)) {
168
+ found.push(childRel);
169
+ }
170
+ }
171
+ };
172
+ walk(rel);
173
+ return found;
174
+ }
175
+
176
+ function firstParagraphLine(text: string): string {
177
+ const lines: string[] = [];
178
+ for (const raw of text.split(/\r?\n/)) {
179
+ const line = raw.trim();
180
+ if (!line) {
181
+ if (lines.length > 0) break;
182
+ continue;
183
+ }
184
+ if (line.startsWith('#') || line.startsWith('![') || line.startsWith('[![') || line.startsWith('<') || line.startsWith('```')) {
185
+ if (lines.length > 0) break;
186
+ continue;
187
+ }
188
+ lines.push(line);
189
+ }
190
+ const joined = lines.join(' ');
191
+ return joined.length > ONE_LINE_MAX ? `${joined.slice(0, ONE_LINE_MAX - 1)}…` : joined;
192
+ }
193
+
194
+ function headingTitles(text: string): string[] {
195
+ const out: string[] = [];
196
+ let fenced = false;
197
+ for (const raw of text.split(/\r?\n/)) {
198
+ if (/^\s*(```|~~~)/.test(raw)) {
199
+ fenced = !fenced;
200
+ continue;
201
+ }
202
+ if (fenced) continue;
203
+ const m = /^#{1,6}\s+(.+?)(?:\s+#+)?\s*$/.exec(raw);
204
+ if (m?.[1]) out.push(m[1]);
205
+ }
206
+ return out;
207
+ }
208
+
209
+ function parsePackage(packageJson: string): { name?: string; commands: string[] } {
210
+ let pkg: unknown;
211
+ try { pkg = JSON.parse(packageJson); } catch { return { commands: [] }; }
212
+ if (!pkg || typeof pkg !== 'object') return { commands: [] };
213
+ const { bin, name } = pkg as { bin?: unknown; name?: unknown };
214
+ const pkgName = typeof name === 'string' && name.trim() ? name.trim() : undefined;
215
+ const base = pkgName ? { name: pkgName } : {};
216
+ if (typeof bin === 'string') return { ...base, commands: pkgName ? [pkgName.replace(/^@[^/]+\//, '')] : [] };
217
+ if (bin && typeof bin === 'object' && !Array.isArray(bin)) return { ...base, commands: Object.keys(bin).sort() };
218
+ return { ...base, commands: [] };
219
+ }
220
+
221
+ /** Real filesystem + local git. `git log` reads local refs only. */
222
+ export const nodeRefIndexFs: RefIndexFs = {
223
+ readDir(dir) {
224
+ try {
225
+ return readdirSync(dir, { withFileTypes: true }).map((e) => ({ name: e.name, isDirectory: e.isDirectory() }));
226
+ } catch {
227
+ return [];
228
+ }
229
+ },
230
+ readHead(file, maxBytes) {
231
+ let fd: number | undefined;
232
+ try {
233
+ const size = statSync(file).size;
234
+ const length = Math.min(size, maxBytes);
235
+ const buf = Buffer.alloc(length);
236
+ fd = openSync(file, 'r');
237
+ readSync(fd, buf, 0, length, 0);
238
+ return { text: buf.toString('utf8'), truncated: size > maxBytes };
239
+ } catch {
240
+ return undefined;
241
+ } finally {
242
+ if (fd !== undefined) closeSync(fd);
243
+ }
244
+ },
245
+ mtimeMs(path) {
246
+ try { return statSync(path).mtimeMs; } catch { return undefined; }
247
+ },
248
+ lastCommitAt(repoDir) {
249
+ const result = spawnSync('git', ['-C', repoDir, 'log', '-1', '--format=%cI'], { encoding: 'utf8', timeout: 10_000 });
250
+ const out = result.status === 0 ? (result.stdout ?? '').trim() : '';
251
+ return out || undefined;
252
+ },
253
+ };