elanous 0.2.21 → 0.2.23

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 (780) 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/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  9. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  11. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  12. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  21. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  23. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  27. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  35. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  39. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  52. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  56. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  64. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  69. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  73. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  78. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  83. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  84. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  85. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  87. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  90. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  97. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  99. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  101. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  105. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  110. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  111. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  112. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  114. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  116. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  117. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  120. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  123. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-6168a7c43e6ef8f5.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  184. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
  185. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  186. package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +1 -1
  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/graphs/catalog/catalog.yaml +1 -1
  288. package/graphs/drafts/recipes.yaml +2 -2
  289. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  290. package/graphs/log-horizon/recipes.yaml +3 -0
  291. package/graphs/release/recipes.yaml +1 -1
  292. package/graphs/release/release-loop.yaml +6 -2
  293. package/graphs/release-rehearsal/recipes.yaml +12 -0
  294. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  295. package/graphs/test-diet/recipes.yaml +3 -0
  296. package/graphs/test-diet/test-diet.yaml +3 -1
  297. package/package.json +4 -1
  298. package/scripts/bench-report.ts +82 -3
  299. package/scripts/ci-typecheck-changed.ts +10 -1
  300. package/scripts/f-session-monitor.ts +69 -0
  301. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  302. package/scripts/hq/standby-snapshot.ts +7 -3
  303. package/scripts/knowledge-compress.ts +11 -0
  304. package/scripts/lib/typecheck-ratchet.ts +51 -0
  305. package/scripts/nightly-docops.ts +90 -3
  306. package/scripts/openai-relay-server.ts +5 -1
  307. package/scripts/release-loop/docs-node.ts +258 -43
  308. package/scripts/release-loop/gate-method.ts +59 -0
  309. package/scripts/release-loop/gate-node.ts +73 -7
  310. package/scripts/release-loop/gate-wall.ts +208 -0
  311. package/scripts/release-loop/known-issues-node.ts +53 -8
  312. package/scripts/release-loop/publish-at.ts +14 -0
  313. package/scripts/release-loop/publish-node.ts +17 -2
  314. package/scripts/release-loop/resume-release.ts +34 -4
  315. package/scripts/release-loop/resume.ts +53 -0
  316. package/scripts/release-loop/shard-plan.ts +3 -11
  317. package/scripts/release-loop/tui-node-checks.ts +22 -0
  318. package/scripts/release-loop/unattended-release.ts +8 -1
  319. package/scripts/research-coo-admin-dates.ts +39 -0
  320. package/scripts/rhythm/daily.ts +51 -2
  321. package/scripts/rhythm/weekly.ts +3 -2
  322. package/scripts/skills/public-check.ts +7 -2
  323. package/scripts/smart-merge/resync-shadow.ts +5 -3
  324. package/scripts/test-diet/lib.ts +81 -1
  325. package/scripts/test-diet/node.ts +48 -2
  326. package/scripts/tsc-main-safety-net.ts +189 -0
  327. package/scripts/usage-rollup.ts +8 -4
  328. package/scripts/verify-coo-admin-evidence.ts +83 -0
  329. package/src/acp/client.ts +4 -2
  330. package/src/acp/codex-plugins.ts +48 -6
  331. package/src/agent/monad-agent-turn.ts +67 -5
  332. package/src/agent/run-context.ts +14 -0
  333. package/src/agent/tool-profile.ts +28 -2
  334. package/src/agent-env/profile.ts +25 -5
  335. package/src/agent-mission/acp-judge.ts +8 -2
  336. package/src/agent-mission/capabilities-cli.ts +16 -1
  337. package/src/agent-mission/driver.ts +27 -13
  338. package/src/agent-mission/pr-review-watch.ts +6 -2
  339. package/src/agent-mission/review-loop.ts +33 -5
  340. package/src/agent-mission/supervisor-metrics.ts +17 -2
  341. package/src/agent-substrate/acp-reviewer.ts +25 -9
  342. package/src/agent-substrate/pr-reviewer.ts +175 -32
  343. package/src/agent-substrate/review-intent.ts +106 -5
  344. package/src/agent-substrate/self-review-cli.ts +111 -16
  345. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  346. package/src/ask-user-question/pending-questions.ts +8 -2
  347. package/src/autopilot/build/llm-conflict-merge.ts +238 -20
  348. package/src/autopilot/codebase-grounding.ts +44 -0
  349. package/src/autopilot/llm-control-brain.ts +13 -1
  350. package/src/autopilot/mission-codebase-gate.ts +8 -77
  351. package/src/autopilot/pr-manager.ts +30 -11
  352. package/src/away/release-watch.ts +47 -8
  353. package/src/boot/acp-server.ts +4 -7
  354. package/src/boot/acp-socket-path.ts +7 -0
  355. package/src/briefing/brief-items.ts +123 -22
  356. package/src/chat/index.ts +13 -3
  357. package/src/cli/agent-cli.ts +20 -0
  358. package/src/cli/brief-cli.ts +46 -22
  359. package/src/cli/cli-user-error.ts +9 -2
  360. package/src/cli/config-classify.ts +83 -0
  361. package/src/cli/control-cli.ts +14 -0
  362. package/src/cli/decisions-cli.ts +26 -16
  363. package/src/cli/log-event-names.ts +3 -0
  364. package/src/cli/logs-cli.ts +1 -0
  365. package/src/cli/logs-model-input.ts +1 -1
  366. package/src/cli/mcp-login.ts +111 -37
  367. package/src/cli/plugin-cli.ts +21 -1
  368. package/src/cli/pod-cli.ts +26 -0
  369. package/src/cli/pr-cli.ts +94 -9
  370. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  371. package/src/cli/release-cli.ts +74 -15
  372. package/src/cli/self-update.ts +173 -10
  373. package/src/cli/skills-cli.ts +12 -3
  374. package/src/cli/tasks-cli.ts +241 -28
  375. package/src/connectors/types.ts +6 -6
  376. package/src/context-bus/context-first.ts +51 -2
  377. package/src/context-bus/context-now-surfaces.ts +29 -0
  378. package/src/context-bus/coord-events.ts +32 -4
  379. package/src/context-bus/long-term-memory.ts +26 -7
  380. package/src/context-bus/nightly-condense.ts +170 -21
  381. package/src/control/control-status.ts +87 -0
  382. package/src/control-plane/light-member.ts +5 -3
  383. package/src/control-plane/member.ts +172 -7
  384. package/src/core-turn/run-goal-loop.ts +108 -3
  385. package/src/dashboard/chat-fold.ts +20 -0
  386. package/src/dashboard/first-screen-band.ts +151 -1
  387. package/src/dashboard/index.ts +27 -5
  388. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -3
  389. package/src/dashboard/stale-install-check.ts +13 -2
  390. package/src/dashboard/turn-stream-formatter.ts +25 -0
  391. package/src/debug/log-diet.ts +159 -0
  392. package/src/debug/log.ts +52 -17
  393. package/src/decisions/decision-cards.ts +20 -1
  394. package/src/decisions/decision-ledger.ts +11 -8
  395. package/src/decisions/web-push-decision-cards.ts +19 -3
  396. package/src/discord-self-message.ts +2 -2
  397. package/src/display/coordinator.ts +25 -2
  398. package/src/domains/coo-admin-dates.evidence.json +876 -0
  399. package/src/domains/coo-admin-tool.ts +75 -14
  400. package/src/domains/cron-match.ts +1 -0
  401. package/src/domains/ops-status.ts +53 -0
  402. package/src/domains/outbound-alert.ts +41 -7
  403. package/src/domains/release-tool.ts +119 -10
  404. package/src/domains/schedule-registry.ts +10 -7
  405. package/src/domains/schedule-runner.ts +1 -0
  406. package/src/elanous-config-dir.ts +2 -2
  407. package/src/elanous-daemon.ts +3 -3
  408. package/src/exec-requests/planner.ts +6 -0
  409. package/src/execution-loop/launch-gate.ts +1 -1
  410. package/src/expression/i18n/messages.en.ts +5 -0
  411. package/src/expression/i18n/messages.ja.ts +5 -0
  412. package/src/expression/i18n/messages.ko.ts +5 -0
  413. package/src/expression/i18n/messages.zh.ts +5 -0
  414. package/src/expression/i18n/types.ts +8 -0
  415. package/src/github/pr-labels.ts +1 -0
  416. package/src/graph-kinds/registry.ts +6 -6
  417. package/src/graph-runner/graph-cli.ts +34 -2
  418. package/src/graph-runner/graph-run-api.ts +7 -0
  419. package/src/graph-runner/graph-tick.ts +73 -12
  420. package/src/graph-runner/runner.ts +94 -13
  421. package/src/graph-unify/wf-to-graph.ts +79 -0
  422. package/src/graph-wizard/generate.ts +34 -2
  423. package/src/graph-wizard/steps.ts +13 -0
  424. package/src/harness/dispatch-backpressure.ts +259 -0
  425. package/src/harness/harness-cli-command.ts +227 -50
  426. package/src/harness/harness-queue.ts +58 -14
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-substrate-default.ts +72 -1
  429. package/src/harness/launch-advice.ts +23 -0
  430. package/src/harness/nested-elanous-policy.ts +4 -2
  431. package/src/hq/fence-wrapper.ts +7 -0
  432. package/src/hq/hq.ts +33 -2
  433. package/src/hq/lease.ts +13 -0
  434. package/src/hq/seats.ts +114 -18
  435. package/src/index.ts +199 -71
  436. package/src/intake-plane/collect-github.ts +19 -1
  437. package/src/intake-plane/digest.ts +45 -20
  438. package/src/intake-plane/lens.ts +36 -8
  439. package/src/intelligence-map/model-alias.ts +6 -0
  440. package/src/intelligence-map/model-catalog.ts +41 -0
  441. package/src/knowledge/conclusion-compress.ts +93 -0
  442. package/src/knowledge/kgs/pack.ts +5 -2
  443. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  444. package/src/knowledge/know-find.ts +9 -2
  445. package/src/knowledge/query.ts +20 -0
  446. package/src/knowledge/tools/knowledge-query.ts +20 -2
  447. package/src/knowledge/write.ts +234 -2
  448. package/src/llm/bedrock-provider.ts +175 -0
  449. package/src/llm/bedrock.ts +345 -0
  450. package/src/llm/provider-credentials.ts +3 -1
  451. package/src/llm.ts +332 -51
  452. package/src/loops/budget.ts +150 -0
  453. package/src/loops/neighbor-runtime.ts +88 -0
  454. package/src/loops/orchestrator/author-depth.ts +29 -11
  455. package/src/loops/orchestrator/overlap.ts +7 -1
  456. package/src/loops/orchestrator/resync-shadow.ts +1 -1
  457. package/src/loops/orchestrator/seat-share.ts +6 -49
  458. package/src/loops/orchestrator/tick.ts +35 -2
  459. package/src/loops/orchestrator/traffic.ts +6 -80
  460. package/src/loops/registry.ts +5 -0
  461. package/src/market/publish.ts +17 -1
  462. package/src/market/signed-index.ts +42 -0
  463. package/src/maturity/feature-maturity.ts +2 -1
  464. package/src/mcp/mcp-oauth.ts +136 -17
  465. package/src/model-tier/llm-tier-map.ts +48 -4
  466. package/src/models/prompts.ts +22 -1
  467. package/src/mss/logging/horizon-watch.ts +168 -0
  468. package/src/mss/logging/log-store.ts +204 -15
  469. package/src/mss/logging/redaction.ts +17 -0
  470. package/src/native-tool-catalog.ts +1 -1
  471. package/src/nexus/api/consult-requests.ts +7 -10
  472. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  473. package/src/nexus/api/draft-metrics.ts +22 -8
  474. package/src/nexus/api/error-reports.ts +30 -8
  475. package/src/nexus/api/graph-peer-edit.ts +77 -0
  476. package/src/nexus/api/graph-wizard-api.ts +9 -1
  477. package/src/nexus/api/graphs-api.ts +145 -7
  478. package/src/nexus/api/http-server.ts +101 -8
  479. package/src/nexus/api/loop-resources.ts +42 -0
  480. package/src/nexus/api/outbound-report.ts +8 -3
  481. package/src/nexus/api/plugins-market.ts +24 -0
  482. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  483. package/src/nexus/index.ts +13 -2
  484. package/src/nexus/outbound/format.ts +2 -0
  485. package/src/nexus/outbound/router.ts +198 -13
  486. package/src/oauth/claude-pty-maturity.ts +24 -0
  487. package/src/oauth/codex-account-rotation.ts +16 -18
  488. package/src/oauth/codex-account-store.ts +134 -5
  489. package/src/oauth/fallback-chain.ts +50 -15
  490. package/src/onboarding.ts +2 -1
  491. package/src/plugins/adapters/claude-package.ts +4 -12
  492. package/src/plugins/core/capability-policy.ts +141 -0
  493. package/src/plugins/core/host.ts +21 -8
  494. package/src/plugins/core/manifest.ts +19 -2
  495. package/src/plugins/core/trust-store.ts +15 -0
  496. package/src/plugins/core/types.ts +12 -0
  497. package/src/plugins/install/market-fetch.ts +68 -16
  498. package/src/plugins/install/plugin-install.ts +187 -16
  499. package/src/plugins/maker/market-bundle.ts +9 -0
  500. package/src/plugins/maker/plugin-maker.ts +32 -21
  501. package/src/plugins/maker/wizard-generate.ts +87 -9
  502. package/src/policy/llm-policy.ts +24 -6
  503. package/src/process/pid-liveness.ts +1 -1
  504. package/src/prompt-cache/openai.ts +10 -6
  505. package/src/prompt-cache/openrouter.ts +94 -0
  506. package/src/prompt-enhance/enhance.ts +46 -5
  507. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  508. package/src/prompt-library/universal-preamble.ts +2 -2
  509. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  510. package/src/registry/loader.ts +6 -1
  511. package/src/release-loop/checklist-board.ts +27 -0
  512. package/src/release-loop/checklist.ts +62 -9
  513. package/src/release-loop/feature-store.ts +3 -0
  514. package/src/release-loop/gate-shards.ts +48 -4
  515. package/src/release-loop/landed-to-green.ts +81 -0
  516. package/src/release-loop/light-rc.ts +11 -1
  517. package/src/release-loop/merged-pr-checklist.ts +10 -0
  518. package/src/release-loop/placement.ts +91 -22
  519. package/src/release-loop/rehearsal.ts +317 -0
  520. package/src/release-loop/release-schedule.ts +13 -1
  521. package/src/release-loop/rubric-types.ts +1 -0
  522. package/src/release-loop/rubric.ts +2 -2
  523. package/src/retro/daily.ts +23 -9
  524. package/src/seat-address/seat-address.ts +1 -0
  525. package/src/seat-loop/seat-loop.ts +208 -21
  526. package/src/seat-loop/seat-report.ts +29 -1
  527. package/src/seat-loop/traffic-signal.ts +44 -0
  528. package/src/self-dev/ask-launch-flow.ts +2 -2
  529. package/src/self-dev/dev-cli.ts +157 -11
  530. package/src/self-dev/dev-pipeline.ts +18 -1
  531. package/src/self-dev/draft-residue.ts +463 -0
  532. package/src/self-dev/draft-sweep.ts +195 -17
  533. package/src/self-dev/draft-triage-rules.ts +27 -1
  534. package/src/self-dev/launch-preflight-text.ts +549 -0
  535. package/src/self-dev/launch-preflight.ts +10 -545
  536. package/src/self-dev/orchestrate-cli.ts +57 -2
  537. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  538. package/src/self-dev/orchestrate.ts +9 -133
  539. package/src/self-dev/review-provider-fallback.ts +179 -0
  540. package/src/self-dev/run-store.ts +1 -3
  541. package/src/self-dev/run-supervisor.ts +8 -23
  542. package/src/self-dev/run-types.ts +178 -0
  543. package/src/self-dev/shard-aggregate.ts +61 -13
  544. package/src/self-dev/shard-plan.ts +5 -1
  545. package/src/self-dev/shard-run.ts +23 -5
  546. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  547. package/src/self-implement/blocked-draft-policy.ts +3 -19
  548. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  549. package/src/self-implement/follow-up-goals.ts +114 -38
  550. package/src/self-implement/gate-baseline-reap.ts +157 -0
  551. package/src/self-implement/gate-baseline.ts +78 -16
  552. package/src/self-implement/gate-cli.ts +12 -2
  553. package/src/self-implement/gate-remote.ts +17 -6
  554. package/src/self-implement/goal-author.ts +24 -4
  555. package/src/self-implement/goal-digest.ts +19 -0
  556. package/src/self-implement/graph-overlay-condition.ts +4 -0
  557. package/src/self-implement/harness-policy-gates.ts +7 -5
  558. package/src/self-implement/headless-elanous-driver.ts +11 -9
  559. package/src/self-implement/host-regate.ts +148 -43
  560. package/src/self-implement/l8-merge-queue.ts +147 -13
  561. package/src/self-implement/merge-train.ts +131 -0
  562. package/src/self-implement/off-diff-evidence.ts +9 -0
  563. package/src/self-implement/orchestrator.ts +201 -43
  564. package/src/self-implement/review-finding-recurrence.ts +28 -0
  565. package/src/self-implement/rework-policy.ts +2 -1
  566. package/src/self-implement/round-summary-card.ts +63 -0
  567. package/src/self-implement/run-ledger.ts +4 -3
  568. package/src/self-implement/run-step-projection.ts +147 -0
  569. package/src/self-implement/run-stop.ts +1 -1
  570. package/src/self-implement/seams.ts +41 -6
  571. package/src/self-implement/self-implement-cli.ts +6 -0
  572. package/src/self-implement/train-gate-remote.ts +158 -0
  573. package/src/session-runtime/index.ts +10 -1
  574. package/src/session-runtime/retry-api.ts +11 -1
  575. package/src/shell-env-bootstrap.ts +19 -4
  576. package/src/skills/gift-install.ts +119 -0
  577. package/src/skills/runner.ts +59 -2
  578. package/src/skills/skill-feedback.ts +31 -1
  579. package/src/skills/skill-tier.ts +1 -0
  580. package/src/smart-wizard/capability-index.ts +231 -0
  581. package/src/smart-wizard/rung.ts +74 -0
  582. package/src/steward/launch.ts +20 -9
  583. package/src/steward/triage.ts +29 -10
  584. package/src/storage/file-lock.ts +40 -4
  585. package/src/task-agent/actions.ts +4 -0
  586. package/src/task-agent/card-evidence.ts +59 -13
  587. package/src/task-agent/completion-evidence.ts +31 -3
  588. package/src/task-agent/cover.ts +61 -0
  589. package/src/task-agent/judge.ts +4 -3
  590. package/src/task-agent/land-worktree.ts +201 -0
  591. package/src/task-agent/live-move-history.ts +133 -0
  592. package/src/task-agent/live-moves.ts +222 -12
  593. package/src/task-agent/parent-host.ts +117 -8
  594. package/src/task-agent/rejudge-on-head.ts +297 -0
  595. package/src/task-agent/review-result-capture.ts +218 -0
  596. package/src/task-agent/shadow.ts +118 -7
  597. package/src/task-agent/task-hand.ts +138 -11
  598. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  599. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  600. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  601. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  602. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  603. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  604. package/src/task-orchestrator/surfaces/pod-pool.ts +203 -28
  605. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  606. package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
  607. package/src/telegram-commands.ts +8 -0
  608. package/src/telegram-project-command.ts +6 -0
  609. package/src/telegram-service.ts +5 -1
  610. package/src/telegram.ts +17 -4
  611. package/src/time/format.ts +13 -4
  612. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  613. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  614. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  615. package/src/typecheck-ratchet.ts +2 -1
  616. package/src/user-config.ts +167 -28
  617. package/src/ux-sim/slash-menu-frames.ts +168 -0
  618. package/src/version/packed-revision.json +1 -1
  619. package/src/web-terminal/preview-tap-registry.ts +5 -2
  620. package/src/workflow-runtime/executor.ts +24 -2
  621. package/src/workflow-runtime/triggers/registry.ts +27 -0
  622. package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
  623. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  624. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  625. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  626. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  627. package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  629. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  630. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  631. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  633. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  638. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  647. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  648. package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  661. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  669. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  674. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  676. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  680. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  684. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  689. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  690. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  692. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  693. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  701. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  704. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  714. package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  717. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  721. package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  723. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  779. package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
  780. /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -4,7 +4,7 @@ import { isScalar, parseDocument } from 'yaml';
4
4
  import { getElanousConfigDir } from '../elanous-config-dir.js';
5
5
  import { DEFAULT_FALLBACK_CHAIN, isFallbackStep, type FallbackStep } from '../oauth/fallback-chain.js';
6
6
  import { isCodexQuotaPolicy } from '../oauth/codex-quota-policy.js';
7
- import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, MODEL_ROLES, RUNTIME_LLM_PROVIDER_NAMES, parseRoleLlmEntry, type RoleLlmConfig } from '../user-config.js';
7
+ import { DEFAULT_BUDGET_GATE_MAX_USED_PERCENT, MODEL_ROLES, RUNTIME_LLM_PROVIDER_NAMES, parseRoleLlmEntry, parseSubscriptionReviewerSpec, type RoleLlmConfig, type SubscriptionReviewerSpec } from '../user-config.js';
8
8
 
9
9
  export interface LlmPolicy {
10
10
  version: 1;
@@ -22,7 +22,7 @@ export interface LlmPolicy {
22
22
  grants: Array<{ account: string; amount: number; expires: string; source: string }>;
23
23
  pace?: { targetPerDay: number; until: string; why?: string };
24
24
  };
25
- caps: { codex: { harness: number; pod: number; tox: number; intake: number; headroom: number }; grok: { weekly: number; tox: number; intake: number } };
25
+ caps: { codex: { harness: number; pod: number; tox: number; intake: number; headroom: number }; grok: { weekly: number; tox: number; intake: number }; claude: { harness: number } };
26
26
  resetCredits: { redeem: 'human' };
27
27
  alerts: { lowRemainingPercent: number; resetCreditExpiryDays: number; creditsStep: number };
28
28
  }
@@ -71,6 +71,7 @@ export function defaultLlmPolicy(): LlmPolicy {
71
71
  caps: {
72
72
  codex: { harness: DEFAULT_BUDGET_GATE_MAX_USED_PERCENT['openai-codex']!, pod: 95, tox: 60, intake: 80, headroom: 15 },
73
73
  grok: { weekly: DEFAULT_BUDGET_GATE_MAX_USED_PERCENT.grok!, tox: 50, intake: 48 },
74
+ claude: { harness: 60 },
74
75
  },
75
76
  resetCredits: { redeem: 'human' },
76
77
  alerts: { lowRemainingPercent: 10, resetCreditExpiryDays: 7, creditsStep: 5000 },
@@ -103,8 +104,10 @@ export function validateLlmPolicy(input: unknown): LlmPolicyValidation {
103
104
  const grants = (v: unknown) => Array.isArray(v) && v.every(g => object(g)
104
105
  && Object.keys(g).every(k => ['account', 'amount', 'expires', 'source'].includes(k))
105
106
  && nonempty(g.account) && positive(g.amount) && date(g.expires) && nonempty(g.source));
106
- const roles = (v: unknown) => object(v) && Object.entries(v).every(([role, spec]) => MODEL_ROLES.some(r => r === role)
107
- && object(spec) && Object.keys(spec).every(k => ['provider', 'tier', 'model'].includes(k)) && parseRoleLlmEntry(spec).ok);
107
+ const roles = (v: unknown) => object(v) && Object.entries(v).every(([role, spec]) => role === 'reviewer'
108
+ ? !!parseSubscriptionReviewerSpec(spec)
109
+ : MODEL_ROLES.some(r => r === role) && object(spec)
110
+ && Object.keys(spec).every(k => ['provider', 'tier', 'model'].includes(k)) && parseRoleLlmEntry(spec).ok);
108
111
  check(input, 'policy', {
109
112
  version: (v: unknown) => v === 1,
110
113
  default: { provider: (v: unknown) => nonempty(v) && RUNTIME_LLM_PROVIDER_NAMES.some(p => p === v), model: nonempty },
@@ -122,7 +125,7 @@ export function validateLlmPolicy(input: unknown): LlmPolicyValidation {
122
125
  && Object.keys(v).every(k => ['targetPerDay', 'until', 'why'].includes(k)),
123
126
  },
124
127
  caps: { codex: { harness: percent, pod: percent, tox: percent, intake: percent, headroom: percent },
125
- grok: { weekly: percent, tox: percent, intake: percent } },
128
+ grok: { weekly: percent, tox: percent, intake: percent }, claude: { harness: percent } },
126
129
  resetCredits: { redeem: (v: unknown) => v === 'human' },
127
130
  alerts: { lowRemainingPercent: percent, resetCreditExpiryDays: positive, creditsStep: positive },
128
131
  });
@@ -161,6 +164,19 @@ function removeExpired(input: Obj, now: Date, warnings: string[], prefix = ''):
161
164
  }
162
165
  }
163
166
 
167
+ /**
168
+ * The reviewer ACP lane (`roleLlm.reviewer`) and its usage cap, resolved once for every caller.
169
+ * The harness (`dev-pipeline`) and `elanous self review` read the same policy row, so the two
170
+ * reviewers cannot drift apart on which config selects the subscription reviewer.
171
+ */
172
+ export function resolveSubscriptionReviewer(
173
+ loaded: LoadedLlmPolicy,
174
+ userRoleLlm?: RoleLlmConfig,
175
+ ): { spec: SubscriptionReviewerSpec; cap: number } | undefined {
176
+ const spec = loaded.policy.roles.reviewer ?? userRoleLlm?.reviewer;
177
+ return spec ? { spec, cap: loaded.policy.caps.claude.harness } : undefined;
178
+ }
179
+
164
180
  export function loadLlmPolicy(opts: LoadLlmPolicyOptions = {}): LoadedLlmPolicy {
165
181
  const configDir = opts.configDir ?? getElanousConfigDir();
166
182
  const path = opts.path ?? join(configDir, 'policy', 'llm.yaml');
@@ -191,7 +207,9 @@ export function loadLlmPolicy(opts: LoadLlmPolicyOptions = {}): LoadedLlmPolicy
191
207
  add('llm.provider', llm.provider, base, 'provider', v => nonempty(v) && RUNTIME_LLM_PROVIDER_NAMES.some(p => p === v));
192
208
  add('llm.model', llm.model, base, 'model', nonempty);
193
209
  if (Object.keys(base).length) overlay.default = base;
194
- add('roleLlm', legacy.roleLlm, overlay, 'roles', v => object(v) && Object.entries(v).every(([r, spec]) => MODEL_ROLES.some(k => k === r) && parseRoleLlmEntry(spec).ok));
210
+ add('roleLlm', legacy.roleLlm, overlay, 'roles', v => object(v) && Object.entries(v).every(([r, spec]) => r === 'reviewer'
211
+ ? !!parseSubscriptionReviewerSpec(spec)
212
+ : MODEL_ROLES.some(k => k === r) && parseRoleLlmEntry(spec).ok));
195
213
  add('llm.fallbackChain', llm.fallbackChain, overlay, 'fallback', v => Array.isArray(v) && v.length > 0 && v.every(isFallbackStep) && new Set(v).size === v.length);
196
214
  const codex: Obj = {};
197
215
  add('llm.codexAccountOrder', llm.codexAccountOrder, codex, 'order', v => Array.isArray(v) && v.every(nonempty));
@@ -14,7 +14,6 @@
14
14
  * ⚠️ 이 판정은 «같은 호스트»에서만 뜻이 있다 — pid 는 호스트 지역 값이다.
15
15
  * 락처럼 호스트가 섞이는 소비자는 호스트를 «먼저» 가른 뒤 이걸 부른다.
16
16
  */
17
- import { debug } from '../debug/log.js';
18
17
 
19
18
  /** ⛔ 두 값이 아니라 «셋»이다 — 「살아 있는데 내가 못 건드린다」는 별도의 사실이다.
20
19
  * 그것을 `alive` 나 `dead` 어느 쪽으로도 접지 않는 것이 이 타입의 존재 이유다. */
@@ -58,6 +57,7 @@ export function pidLiveness(pid: number): PidLiveness {
58
57
  if (verdict === 'alive-not-mine') {
59
58
  // ⛔ 「살아 있는데 남의 것」은 조용히 지나가면 안 된다 — 🅢 요청(2026-09-20):
60
59
  // 원장에 «대상 pid 와 소유자 축»이 남아야 A 구간(남의 트리에서 도는 자식)과 닿는다.
60
+ const { debug } = require('../debug/log.js') as { debug: { log: (category: string, event: string, data: Record<string, unknown>) => void } };
61
61
  debug.log('process.liveness', 'kill-refused', { pid, myUid: myUid(), errno });
62
62
  observer?.({ pid, liveness: verdict, myUid: myUid(), errno });
63
63
  }
@@ -35,7 +35,8 @@ export function parseOpenAIUsage(event: unknown): LLMUsage | null {
35
35
  const r = raw as {
36
36
  prompt_tokens?: number;
37
37
  completion_tokens?: number;
38
- prompt_tokens_details?: { cached_tokens?: number };
38
+ /** OpenRouter 는 캐시 쓰기를 `cache_write_tokens` 로 싣는다(Anthropic 상류 · OR-ANTHROPIC-CACHE). */
39
+ prompt_tokens_details?: { cached_tokens?: number; cache_write_tokens?: number };
39
40
  completion_tokens_details?: { reasoning_tokens?: number };
40
41
  /** Kimi(Moonshot) — 최상위에 싣는다. */
41
42
  cached_tokens?: number;
@@ -50,14 +51,17 @@ export function parseOpenAIUsage(event: unknown): LLMUsage | null {
50
51
  // 캐시 단가로 또 한 번 매겨진다(BACKLOG C4 · opencode openai-chat.ts · hermes normalize_usage 와 같은 처리).
51
52
  const cached = [r.prompt_tokens_details?.cached_tokens, r.cached_tokens, r.prompt_cache_hit_tokens]
52
53
  .find((v): v is number => typeof v === 'number');
53
- if (typeof r.prompt_tokens === 'number') out.inputTokens = Math.max(0, r.prompt_tokens - (cached ?? 0));
54
+ // OR-ANTHROPIC-CACHE — OpenRouter(Anthropic 상류)의 캐시 «쓰기»도 prompt_tokens 에 포함돼 온다 → 새 입력에서 빼고
55
+ // cacheCreationInputTokens 로 옮긴다(Anthropic 규약). 칸이 없으면(OpenAI·Grok·DeepSeek …) 종전과 같다.
56
+ const written = typeof r.prompt_tokens_details?.cache_write_tokens === 'number' ? r.prompt_tokens_details.cache_write_tokens : undefined;
57
+ if (typeof r.prompt_tokens === 'number') out.inputTokens = Math.max(0, r.prompt_tokens - (cached ?? 0) - (written ?? 0));
54
58
  if (typeof r.completion_tokens === 'number') out.outputTokens = r.completion_tokens;
55
- if (cached !== undefined) {
56
- out.cacheReadInputTokens = cached;
59
+ if (cached !== undefined || written !== undefined) {
60
+ out.cacheReadInputTokens = cached ?? 0;
57
61
  // OpenAI caches are free-on-hit and rolled into prompt_tokens for
58
62
  // creation — we set creation to 0 so metrics math (hit-rate) works
59
- // uniformly across providers.
60
- out.cacheCreationInputTokens = 0;
63
+ // uniformly across providers. OpenRouter→Anthropic reports writes.
64
+ out.cacheCreationInputTokens = written ?? 0;
61
65
  }
62
66
  // Reasoning tokens — OpenAI o1/o3, qwen 3.6 (LM Studio surfaces this
63
67
  // even though qwen calls it `reasoning_content` rather than the
@@ -0,0 +1,94 @@
1
+ // OR-ANTHROPIC-CACHE (2026-10-10) — OpenRouter 경유 Anthropic·Moonshot(Kimi) 호출의 프롬프트 캐시 중단점.
2
+ //
3
+ // OpenRouter 는 OpenAI 꼴 본문을 받아 상류(Anthropic·Moonshot)로 옮긴다. 이 두 계열은 «요청이 청해야»
4
+ // 캐시를 쓴다 — 본문에 `cache_control` 이 없으면 적중 0 이다(10-10 벤치: Haiku·Sonnet 5.5 팔 cachedInput 0).
5
+ //
6
+ // 배치(참고 구현 대조):
7
+ // - opencode `provider/transform.ts` applyCaching — system 앞 2 ⊕ 비-system 끝 2 (상한 4).
8
+ // - hermes `agent/prompt_caching.py` envelope layout — OpenRouter 는 «content 파트»의 cache_control 만 따른다.
9
+ // · role:tool 의 «최상위» cache_control 은 OpenRouter 에서 조용히 멎는다 → 파트에만 단다(OpenRouter 가
10
+ // tool_result 블록으로 옮긴다).
11
+ // · content 가 비거나 null 인 assistant(순수 tool_calls)는 중단점을 낭비하므로 건너뛴다.
12
+ // · Kimi(moonshotai/*) 도 같은 envelope 꼴로 적중 1% → 97% (hermes #25970).
13
+ // - tools: 따로 표시하지 않는다. Anthropic 접두 순서가 tools → system → messages 라 system 끝 중단점이
14
+ // 도구 정의까지 덮는다. hermes 도 tools 배열 표시는 «직접 Anthropic» 경로에만 쓴다.
15
+ //
16
+ // ⛔ 순수 함수 — 입력 배열·메시지를 고치지 않고 바뀐 메시지만 새로 만든다.
17
+
18
+ /** Anthropic 상한. */
19
+ export const OPENROUTER_MAX_CACHE_BREAKPOINTS = 4;
20
+
21
+ export type OpenRouterCacheFamily = 'anthropic' | 'moonshotai';
22
+
23
+ /** wire 모델(`anthropic/claude-haiku-5.5`)이 캐시 중단점 대상인가. 대상이 아니면 null. */
24
+ export function openRouterPromptCacheFamily(wireModel: string): OpenRouterCacheFamily | null {
25
+ if (wireModel.startsWith('anthropic/')) return 'anthropic';
26
+ if (wireModel.startsWith('moonshotai/')) return 'moonshotai';
27
+ return null;
28
+ }
29
+
30
+ type WireMessage = Record<string, unknown>;
31
+ type CacheMarker = { type: 'ephemeral'; ttl?: '1h' };
32
+
33
+ function isMarkablePart(part: unknown): boolean {
34
+ // 텍스트 파트에만 단다 — image_url 파트 위 cache_control 의 OpenRouter 전달은 확인하지 않았다(보수).
35
+ return !!part && typeof part === 'object' && (part as { type?: unknown }).type === 'text';
36
+ }
37
+
38
+ function canCarryMarker(msg: WireMessage): boolean {
39
+ const content = msg.content;
40
+ if (typeof content === 'string') return content.length > 0;
41
+ if (Array.isArray(content) && content.length > 0) return isMarkablePart(content[content.length - 1]);
42
+ return false;
43
+ }
44
+
45
+ function withMarker(msg: WireMessage, marker: CacheMarker): WireMessage {
46
+ const content = msg.content;
47
+ if (typeof content === 'string') {
48
+ return { ...msg, content: [{ type: 'text', text: content, cache_control: { ...marker } }] };
49
+ }
50
+ const parts = (content as Array<Record<string, unknown>>).slice();
51
+ parts[parts.length - 1] = { ...parts[parts.length - 1], cache_control: { ...marker } };
52
+ return { ...msg, content: parts };
53
+ }
54
+
55
+ export interface OpenRouterCachePlan {
56
+ messages: WireMessage[];
57
+ /** 실제로 단 중단점 수(0~4). */
58
+ breakpoints: number;
59
+ systemBreakpoints: number;
60
+ tailBreakpoints: number;
61
+ }
62
+
63
+ /** system 앞 2 ⊕ 비-system 끝 2 (합 ≤ 4) 의 마지막 텍스트 파트에 `cache_control` 을 단다.
64
+ * `ttl:'1h'` 은 anthropic 계열에만 싣는다(Moonshot 의 1h 계층은 확인하지 않았다 → 기본 5m). */
65
+ export function applyOpenRouterCacheControl(
66
+ messages: readonly WireMessage[],
67
+ opts: { family: OpenRouterCacheFamily; ttl?: '5m' | '1h' },
68
+ ): OpenRouterCachePlan {
69
+ const marker: CacheMarker = opts.family === 'anthropic' && opts.ttl === '1h'
70
+ ? { type: 'ephemeral', ttl: '1h' }
71
+ : { type: 'ephemeral' };
72
+ const out = messages.slice();
73
+ let systemBreakpoints = 0;
74
+ for (let i = 0; i < out.length && systemBreakpoints < 2; i++) {
75
+ if (out[i]!.role !== 'system') continue;
76
+ if (!canCarryMarker(out[i]!)) continue;
77
+ out[i] = withMarker(out[i]!, marker);
78
+ systemBreakpoints++;
79
+ }
80
+ const remaining = Math.min(2, OPENROUTER_MAX_CACHE_BREAKPOINTS - systemBreakpoints);
81
+ const tail: number[] = [];
82
+ for (let i = out.length - 1; i >= 0 && tail.length < remaining; i--) {
83
+ const m = out[i]!;
84
+ if (m.role === 'system') continue;
85
+ if (canCarryMarker(m)) tail.push(i);
86
+ }
87
+ for (const i of tail) out[i] = withMarker(out[i]!, marker);
88
+ return {
89
+ messages: out,
90
+ breakpoints: systemBreakpoints + tail.length,
91
+ systemBreakpoints,
92
+ tailBreakpoints: tail.length,
93
+ };
94
+ }
@@ -16,6 +16,7 @@ import { streamLLM, type LLMMessage } from '../llm.js';
16
16
  import { debug } from '../debug/log.js';
17
17
  import type { LLMUsage } from '../prompt-cache/types.js';
18
18
  import { llmUsageCostFields } from '../budget/llm-cost.js';
19
+ import { getUserConfig, resolveRoleLlm, type UserConfig } from '../user-config.js';
19
20
 
20
21
  function logLlmUsage(model: string, usage: LLMUsage): void {
21
22
  try {
@@ -97,6 +98,8 @@ export interface EnhanceOpts {
97
98
  */
98
99
  checklistUse?: ChecklistUse;
99
100
  reasoningEffort?: 'low' | 'medium' | 'high';
101
+ /** 호출자의 저작 시점 config. 생략 시 현재 사용자 설정을 읽는다. */
102
+ config?: UserConfig;
100
103
  /** 산출물 유형 힌트(선택) — 예: 'PPT 발표덱', 'PLAN 문서'. 제약 문구 조정. */
101
104
  deliverableHint?: string;
102
105
  /** Optional usage observer for the caller's authoring phase; missing usage stays unknown. */
@@ -115,6 +118,8 @@ export interface EnhanceOpts {
115
118
  * ⭐ 새 LLM 경로를 만들지 않는다 — 이 모듈이 이미 그 자리의 유일한 LLM 단계다.
116
119
  */
117
120
  groundedFacts?: readonly string[];
121
+ /** Clock seam for the first-token observation (ms epoch); defaults to `Date.now`. */
122
+ now?: () => number;
118
123
  }
119
124
 
120
125
  const FENCE = '```';
@@ -129,8 +134,29 @@ function askMarkerCount(ask: string): number {
129
134
  return (ask.match(/(?:^|\s)(?:불변식|경계|판정\s*신호|invariant|boundary|decision\s+signal)\s*:/gi) ?? []).length;
130
135
  }
131
136
 
132
- const defaultModel = (): string =>
133
- process.env.ELANOUS_PROMPT_ENHANCE_MODEL || process.env.ELANOUS_PR_REVIEW_MODEL || tierModel('better');
137
+ type EnhanceSelectionSource = 'opts' | 'env' | 'config-role' | 'default';
138
+
139
+ /** Select the authoring knobs independently; a planning effort alone cannot change the model. */
140
+ export function selectEnhanceLlm(
141
+ opts: Pick<EnhanceOpts, 'model' | 'reasoningEffort' | 'config'> = {},
142
+ env: NodeJS.ProcessEnv = process.env,
143
+ ): { model: string; effort: 'low' | 'medium' | 'high'; modelSource: EnhanceSelectionSource; effortSource: EnhanceSelectionSource } {
144
+ const config = opts.config ?? getUserConfig();
145
+ const planning = config.roleLlm?.planning;
146
+ const configuredModel = opts.model === undefined && !env.ELANOUS_PROMPT_ENHANCE_MODEL
147
+ && planning && (planning.model || planning.tier || planning.provider)
148
+ ? resolveRoleLlm('planning', { config, overrides: {} }).model : undefined;
149
+ const modelSource: EnhanceSelectionSource = opts.model !== undefined ? 'opts'
150
+ : env.ELANOUS_PROMPT_ENHANCE_MODEL ? 'env'
151
+ : configuredModel !== undefined ? 'config-role' : 'default';
152
+ const model = opts.model ?? (env.ELANOUS_PROMPT_ENHANCE_MODEL || configuredModel || env.ELANOUS_PR_REVIEW_MODEL || tierModel('better'));
153
+ const envEffort = env.ELANOUS_PROMPT_ENHANCE_EFFORT;
154
+ const validEnvEffort = envEffort === 'low' || envEffort === 'medium' || envEffort === 'high' ? envEffort : undefined;
155
+ const effortSource: EnhanceSelectionSource = opts.reasoningEffort !== undefined ? 'opts'
156
+ : validEnvEffort !== undefined ? 'env'
157
+ : planning?.effort !== undefined ? 'config-role' : 'default';
158
+ return { model, effort: opts.reasoningEffort ?? validEnvEffort ?? planning?.effort ?? 'high', modelSource, effortSource };
159
+ }
134
160
 
135
161
  /** 스캐폴드 생성 LLM 시스템 프롬프트 — 가산·원문불가침 규율. */
136
162
  const enhanceSystem = (deliverableHint?: string, wantsScqa = false, checklistUse: ChecklistUse = 'coverage-gate'): string =>
@@ -332,7 +358,10 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
332
358
  return { original, enhanced, checklist: [], verbatimPreserved: true, enhancedBy: 'fallback', model: null };
333
359
  }
334
360
 
335
- const model = opts.model ?? defaultModel();
361
+ // Selected only when an LLM call will actually be attempted — the disabled path never records a selection.
362
+ const { model, effort, modelSource, effortSource } = selectEnhanceLlm(opts);
363
+ debug.log('prompt-enhance.model', 'selected', { model, effort, modelSource, effortSource });
364
+
336
365
  let goal = '';
337
366
  let constraints: string[] = [];
338
367
  let checklist: string[] = [];
@@ -367,9 +396,21 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
367
396
  ].join('\n'),
368
397
  },
369
398
  ];
370
- const rawOut = await streamLLM(messages, () => {}, {
399
+ // ⭐ OPENROUTER-OPTIMIZE G13 — 첫 토큰까지 걸린 시간(TTFT)을 호출마다 «한 번» 남긴다.
400
+ // 총 소요만으로는 「대기(큐·라우팅)」와 「생성」을 못 가른다. 본문은 싣지 않는다(길이도 안 싣는다).
401
+ // ⚠️ 첫 «텍스트» 델타까지다 — 추론(reasoning) 토큰을 먼저 내는 모델은 그 생성 시간도 여기 들어간다
402
+ // (순수 대기·라우팅 시간으로 읽지 않는다).
403
+ const now = opts.now ?? Date.now;
404
+ const requestStartedAt = now();
405
+ let firstTokenLogged = false;
406
+ const onChunk = (delta: string): void => {
407
+ if (firstTokenLogged || delta.length === 0) return;
408
+ firstTokenLogged = true;
409
+ debug.log('prompt-enhance.stream', 'first-token', { model, ttftMs: Math.max(0, now() - requestStartedAt) });
410
+ };
411
+ const rawOut = await streamLLM(messages, onChunk, {
371
412
  model,
372
- reasoningEffort: opts.reasoningEffort ?? 'high',
413
+ reasoningEffort: effort,
373
414
  onUsage: (usage) => {
374
415
  logLlmUsage(model, usage);
375
416
  try { opts.onUsage?.(usage); } catch { /* usage observation must not change enhancement */ }
@@ -31,6 +31,7 @@ export const FAMILY_PROBE_MODEL_IDS: Readonly<Record<Exclude<ModelFamily, 'other
31
31
  grok: 'grok-4.7',
32
32
  gemini: 'gemini-3-pro',
33
33
  local: 'local:qwen',
34
+ 'open-weight': 'openrouter/z-ai/glm-5.3',
34
35
  };
35
36
 
36
37
  export interface FamilyPromptCoverage {
@@ -32,11 +32,11 @@ import { buildGrokFamilyAddendum } from './grok-family-addendum.js';
32
32
  import { buildSessionGuidanceAddendum } from './session-guidance.js';
33
33
  import { getHarnessSpace } from '../harness/harness-space.js';
34
34
 
35
- export const PROJECT_ANCHOR_MAX_CHARS = 32 * 1024;
35
+ export const PROJECT_ANCHOR_MAX_CHARS = 36 * 1024; // 10-10 증액(32K→36K) — 줄이기는 AGENTS-CLAUDE-DIET(0.2.24)
36
36
  /** «lean» 예산(BACKLOG L2 · 2026-09-25) — 로컬 모델 구현 자식은 매 턴 이것을 prefill 한다.
37
37
  * 📏 09-25 node-b 기록 프록시: 시스템 50,068자 중 AGENTS.md 앵커 ~32K · 트리 ~8K 가 상위 둘이었다.
38
38
  * ⭐ 켜는 법: env `ELANOUS_PROMPT_BUDGET=lean` — 하니스 구현 자식 spawn 이 child provider 가 local 일 때 준다.
39
- * ⛔ API 모델 경로의 기본(32K·8K)은 그대로다 — 잘 도는 것을 바꾸지 않는다. */
39
+ * ⛔ API 모델 경로의 기본(36K·8K)은 그대로다 — 잘 도는 것을 바꾸지 않는다. */
40
40
  export const PROJECT_ANCHOR_LEAN_MAX_CHARS = 8 * 1024;
41
41
  export const PROJECT_TREE_LEAN_MAX_CHARS = 2 * 1024;
42
42
  function promptBudgetLean(): boolean { return process.env.ELANOUS_PROMPT_BUDGET?.trim() === 'lean'; }
@@ -0,0 +1,122 @@
1
+ // OR-MODEL-NAMESPACE (대표 2026-10-10 «OpenRouter 로 Claude 계열이 안 도는 이유를 먼저 고쳐라»).
2
+ //
3
+ // S: 구현 자식 모델 해석(`resolveImplementationChildModel`)은 `openrouter/<vendor>/<model>` 을 호스트의
4
+ // `discovery-snapshot.json` 에 «있는 id» 로만 받는다.
5
+ // C: 스냅숏은 갱신이 멎으면 늙는다(09-23 판) — 그 뒤 OpenRouter 에 올라온 모델(claude-haiku-5.5 등)은
6
+ // «있는데도» 거부된다. 거부 사유는 「없다」지만 사실은 「우리 스냅숏이 모른다」다.
7
+ // A: 스냅숏에 없을 때만 공개 `/api/v1/models` 를 «한 번» 묻는다(기존 `openrouterSource` 재사용 · 키 불요).
8
+ // 있으면 그 항목을 스냅숏에 합치고 카탈로그를 다시 읽는다. 없으면 지금처럼 거부.
9
+ // ⛔ 네트워크 실패·시간 초과는 «거부»(fail-closed) — 「확인 못 함」을 「있다」로 접지 않는다.
10
+
11
+ import { mkdirSync, renameSync, writeFileSync } from 'node:fs';
12
+ import { dirname } from 'node:path';
13
+ import { debug } from '../../debug/log.js';
14
+ import { isolatedCatalogTestUniverse, reloadCatalog } from '../loader.js';
15
+ import { defaultDiscoveryCachePath, readDiscoveryCache, type DiscoverySnapshot } from './cache.js';
16
+ import { openrouterSource } from './sources/openrouter.js';
17
+ import type { DiscoveredModel } from './types.js';
18
+
19
+ export const OPENROUTER_LIVE_RESOLVE_TIMEOUT_MS = 10_000;
20
+ export const OPENROUTER_SNAPSHOT_STALE_DAYS = 7;
21
+ const NAMESPACED_OPENROUTER_ID = /^openrouter\/([^/\s]+\/[^/\s]+)$/;
22
+ const DAY_MS = 24 * 60 * 60 * 1000;
23
+
24
+ /** 이 프로세스에서 라이브로 확인한 id — 스냅숏 쓰기가 실패해도 같은 프로세스의 재해석은 통과시킨다. */
25
+ const liveVerified = new Set<string>();
26
+
27
+ export function isLiveVerifiedOpenRouterModel(id: string): boolean {
28
+ return liveVerified.has(id);
29
+ }
30
+
31
+ export function __resetOpenRouterLiveResolveForTests(): void {
32
+ liveVerified.clear();
33
+ }
34
+
35
+ /** `openrouter/<vendor>/<model>` → `<vendor>/<model>`(스냅숏·OpenRouter 의 id). 형식이 아니면 undefined. */
36
+ export function upstreamOpenRouterId(id: string): string | undefined {
37
+ return NAMESPACED_OPENROUTER_ID.exec(id)?.[1];
38
+ }
39
+
40
+ /** 카탈로그 로더가 «접는» 스냅숏 경로. 시험 런타임에서 명시 경로가 없으면 undefined(실 `~/.elanous` 를 안 건드린다). */
41
+ export function foldSnapshotPath(): string | undefined {
42
+ const explicit = process.env.ELANOUS_CATALOG_DISCOVERY_SNAPSHOT?.trim();
43
+ if (explicit) return explicit;
44
+ if (isolatedCatalogTestUniverse()) return undefined;
45
+ return defaultDiscoveryCachePath();
46
+ }
47
+
48
+ export function snapshotAgeDays(snapshot: DiscoverySnapshot | null, now: number = Date.now()): number | undefined {
49
+ if (!snapshot?.generatedAt) return undefined;
50
+ const t = Date.parse(snapshot.generatedAt);
51
+ if (!Number.isFinite(t)) return undefined;
52
+ return Math.max(0, Math.floor((now - t) / DAY_MS));
53
+ }
54
+
55
+ export function readFoldSnapshotAgeDays(now: number = Date.now()): number | undefined {
56
+ const path = foldSnapshotPath();
57
+ return path ? snapshotAgeDays(readDiscoveryCache({ cachePath: path }), now) : undefined;
58
+ }
59
+
60
+ function persistMergedModel(path: string, model: DiscoveredModel, now: number): boolean {
61
+ try {
62
+ const existing = readDiscoveryCache({ cachePath: path });
63
+ const snapshot: DiscoverySnapshot = existing ?? {
64
+ version: 1,
65
+ generatedAt: new Date(now).toISOString(),
66
+ sources: [],
67
+ models: [],
68
+ };
69
+ if (!snapshot.models.some((m) => m.provider === 'openrouter' && m.id === model.id)) {
70
+ snapshot.models.push(model);
71
+ }
72
+ mkdirSync(dirname(path), { recursive: true });
73
+ const tmp = `${path}.${process.pid}.tmp`;
74
+ writeFileSync(tmp, JSON.stringify(snapshot, null, 2), 'utf-8');
75
+ renameSync(tmp, path);
76
+ return true;
77
+ } catch {
78
+ return false;
79
+ }
80
+ }
81
+
82
+ export type OpenRouterLiveLookup =
83
+ | { found: true; id: string; merged: DiscoveredModel; persisted: boolean; snapshotAgeDays?: number }
84
+ | { found: false; id: string; error?: string; snapshotAgeDays?: number };
85
+
86
+ /** 스냅숏에 없는 `openrouter/<vendor>/<model>` 을 공개 `/models` 에 «한 번» 묻는다.
87
+ * found → 스냅숏에 합치고(가능하면) 카탈로그를 다시 읽는다. error → 확인 못 함(호출자가 거부). */
88
+ export async function liveLookupOpenRouterModel(
89
+ id: string,
90
+ opts: { fetchImpl?: typeof fetch; timeoutMs?: number; now?: () => number; persist?: boolean } = {},
91
+ ): Promise<OpenRouterLiveLookup> {
92
+ const now = opts.now ?? Date.now;
93
+ const path = foldSnapshotPath();
94
+ const ageDays = path ? snapshotAgeDays(readDiscoveryCache({ cachePath: path }), now()) : undefined;
95
+ const age = ageDays !== undefined ? { snapshotAgeDays: ageDays } : {};
96
+ const upstream = upstreamOpenRouterId(id);
97
+ if (!upstream) {
98
+ debug.log('registry.discovery', 'child-model-live-resolve', { id, found: false, ...age, error: 'not-namespaced' });
99
+ return { found: false, id, error: 'not-namespaced', ...age };
100
+ }
101
+ const result = await openrouterSource.run({
102
+ timeoutMs: opts.timeoutMs ?? OPENROUTER_LIVE_RESOLVE_TIMEOUT_MS,
103
+ ...(opts.fetchImpl ? { fetchImpl: opts.fetchImpl } : {}),
104
+ now,
105
+ });
106
+ if (!result.ok) {
107
+ const error = result.error ?? 'unknown';
108
+ debug.log('registry.discovery', 'child-model-live-resolve', { id, found: false, ...age, error });
109
+ return { found: false, id, error, ...age };
110
+ }
111
+ const merged = result.models.find((m) => m.id === upstream);
112
+ if (!merged) {
113
+ debug.log('registry.discovery', 'child-model-live-resolve', { id, found: false, ...age });
114
+ return { found: false, id, ...age };
115
+ }
116
+ liveVerified.add(id);
117
+ // ⚠️ 잠금 없는 read-modify-write — discovery 크론과 같은 순간이면 한쪽 쓰기가 사라질 수 있다(감시 항목 · 다음 조회가 다시 합친다).
118
+ const persisted = path && opts.persist !== false ? persistMergedModel(path, merged, now()) : false;
119
+ if (persisted) reloadCatalog();
120
+ debug.log('registry.discovery', 'child-model-live-resolve', { id, found: true, ...age, persisted });
121
+ return { found: true, id, merged, persisted, ...age };
122
+ }
@@ -385,13 +385,18 @@ function buildCatalog(): Catalog {
385
385
  };
386
386
  }
387
387
 
388
+ /** 시험 런타임(NODE_ENV=test)은 카탈로그 스냅숏을 기본 경로에서 접지 않는다 — 이 판정을 쓰는 쪽(자식 모델 형식 검사)과 공유한다. */
389
+ export function isolatedCatalogTestUniverse(): boolean {
390
+ return process.env.NODE_ENV === 'test';
391
+ }
392
+
388
393
  /** 폴드할 스냅숏을 고른다. ⛔ 시험 런타임은 preload 가 config-dir 를 격리하지 않아 실제
389
394
  * `~/.elanous/discovery-snapshot.json` 을 읽게 되므로(=기계마다 다른 카탈로그), 경로를 «명시»했을
390
395
  * 때만 접는다. 운영은 기본 경로를 읽고, 없으면 «모른다»(null) — 접을 것이 없을 뿐 오류가 아니다. */
391
396
  function loadFoldSnapshot(): DiscoverySnapshot | null {
392
397
  const explicit = process.env.ELANOUS_CATALOG_DISCOVERY_SNAPSHOT?.trim();
393
398
  if (explicit) return readDiscoveryCache({ cachePath: explicit });
394
- if (process.env.NODE_ENV === 'test') return null;
399
+ if (isolatedCatalogTestUniverse()) return null;
395
400
  return readDiscoveryCache();
396
401
  }
397
402
 
@@ -0,0 +1,27 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { checklistDevVersion, listChecklist, summarizeChecklist, type Checklist } from './checklist.js';
3
+
4
+ /** One text board shared by the Telegram and TUI slash surfaces. */
5
+ export function renderChecklistBoard(checklist: Checklist): string {
6
+ const { green, yellow, red, done, blocked } = summarizeChecklist(checklist);
7
+ const { bySeat } = summarizeChecklist({
8
+ ...checklist,
9
+ items: checklist.items.filter((item) => item.status === 'yellow'),
10
+ });
11
+ return [
12
+ `판 ${checklist.version} · 초록 ${green} · 노랑 ${yellow} · 빨강 ${red} · 끝 ${done}`,
13
+ `빨강 칸: ${blocked.join(', ') || '-'}`,
14
+ `자리별 노랑: ${Object.entries(bySeat).sort(([a], [b]) => a.localeCompare(b)).map(([seat, count]) => `${seat} ${count}`).join(' · ') || '-'}`,
15
+ ].join('\n');
16
+ }
17
+
18
+ /** Read and render the selected board without turning failures into zero counts. */
19
+ export function checklistBoardSlash(args: readonly string[], read: (version: string) => Checklist = listChecklist): string {
20
+ if (args.length > 1) return '사용법: /board [판]';
21
+ try {
22
+ return renderChecklistBoard(read(args[0] ?? checklistDevVersion()));
23
+ } catch (error) {
24
+ debug.log('release.checklist', 'board-read-failed', { version: args[0] ?? null, error: error instanceof Error ? error.message : String(error) });
25
+ return '판 체크리스트를 못 읽었다 — 「없다」가 아니다';
26
+ }
27
+ }
@@ -7,8 +7,9 @@ import { CliUserError } from '../cli/cli-user-error.js';
7
7
 
8
8
  export type ChecklistStatus = 'green' | 'yellow' | 'red' | 'done';
9
9
  export type ChecklistDisposition = 'move' | 'known-issue' | 'block';
10
- /** `screen` = a five-surface feature cell — its evidence carries a `짝:` line (MANUAL-five-surface-parity §A). */
11
- export type ChecklistKind = 'screen';
10
+ /** `screen` = a five-surface feature cell — its evidence carries a `짝:` line (MANUAL-five-surface-parity §A). `postpub` = measured after publication, outside the pre-publication gate. */
11
+ export type ChecklistKind = 'screen' | 'postpub';
12
+ const CHECKLIST_KINDS: readonly ChecklistKind[] = ['screen', 'postpub'];
12
13
  export interface ChecklistItem {
13
14
  id: string;
14
15
  title: string;
@@ -175,6 +176,44 @@ export function cellsReferencingDoc(doc: string, checklists: readonly Checklist[
175
176
  return rows;
176
177
  }
177
178
 
179
+ /** 문서 절과 판 칸의 `#절` 인용을 양방향으로 대조한다. 원장은 전달받은 스냅샷만 읽는다. */
180
+ export function lintDocRefs(docPath: string, docText: string, checklists: readonly Checklist[]): {
181
+ sections: string[];
182
+ uncoveredSections: string[];
183
+ danglingRefs: Array<{ version: string; id: string; ref: string }>;
184
+ } {
185
+ const path = splitRef(docPath.trim()).path;
186
+ const sections: string[] = [];
187
+ let fence: { marker: string; length: number } | null = null;
188
+ for (const line of docText.split(/\r?\n/)) {
189
+ const marker = /^ {0,3}(`{3,}|~{3,})/.exec(line)?.[1];
190
+ if (fence) {
191
+ if (marker?.[0] === fence.marker && marker.length >= fence.length && /^\s*$/.test(line.slice(line.indexOf(marker) + marker.length))) fence = null;
192
+ continue;
193
+ }
194
+ if (marker) { fence = { marker: marker[0]!, length: marker.length }; continue; }
195
+ const heading = /^ {0,3}#{2,4}[ \t]+(\S+)/.exec(line);
196
+ if (heading) {
197
+ const section = heading[1]!.replace(/[.:]$/, '');
198
+ if (!sections.includes(section)) sections.push(section);
199
+ }
200
+ }
201
+ const known = new Set(sections);
202
+ const cited = new Set<string>();
203
+ const danglingRefs: Array<{ version: string; id: string; ref: string }> = [];
204
+ for (const data of checklists) {
205
+ for (const item of data.items) {
206
+ for (const ref of item.refs ?? []) {
207
+ const got = splitRef(ref);
208
+ if (got.path !== path || !got.section) continue;
209
+ if (known.has(got.section)) cited.add(got.section);
210
+ else danglingRefs.push({ version: data.version, id: item.id, ref });
211
+ }
212
+ }
213
+ }
214
+ return { sections, uncoveredSections: sections.filter((section) => !cited.has(section)), danglingRefs };
215
+ }
216
+
178
217
  /** `| 판 | 칸 | 상태 | 절 | 제목 |` 마크다운 표 — 행이 없으면 머리줄 둘만. */
179
218
  export function renderRefsStatus(rows: readonly DocRefRow[]): string {
180
219
  const cell = (value: string) => value.replace(/\|/g, '\\|').replace(/\r?\n/g, ' ');
@@ -189,7 +228,7 @@ export function validateCeoLoad(input: { ceoMinutes?: number; ceoDate?: string }
189
228
  export function addItem(v: string, input: { id: string; title: string; refs?: string[]; owner?: string; kind?: ChecklistKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean }, options: { allowDuplicateId?: boolean } = {}): Checklist {
190
229
  if (!input.id.trim()) throw new CliUserError('칸 id 가 비었다');
191
230
  if (!input.title.trim()) throw new CliUserError('칸 제목이 비었다');
192
- if (input.kind !== undefined && input.kind !== 'screen') throw new CliUserError(`잘못된 종류: ${input.kind}`, 'screen');
231
+ if (input.kind !== undefined && !CHECKLIST_KINDS.includes(input.kind)) throw new CliUserError(`잘못된 종류: ${input.kind}`, 'screen|postpub');
193
232
  if (input.owner !== undefined) parseOwner(input.owner);
194
233
  if (input.priority !== undefined && !['P0', 'P1', 'P2'].includes(input.priority)) throw new CliUserError(`잘못된 우선순위: ${input.priority}`);
195
234
  if (input.predecessors !== undefined && (!Array.isArray(input.predecessors) || input.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === input.id))) throw new CliUserError('잘못된 선행 칸');
@@ -220,7 +259,7 @@ export function setItem(v: string, id: string, patch: { status?: ChecklistStatus
220
259
  if (!item) throw new CliUserError(`없는 칸: ${id}`, 'list 로 칸 목록을 본다');
221
260
  if (patch.status !== undefined && !['green', 'yellow', 'red', 'done'].includes(patch.status)) throw new CliUserError(`잘못된 상태: ${patch.status}`);
222
261
  if (patch.disposition !== undefined && !['move', 'known-issue', 'block'].includes(patch.disposition)) throw new CliUserError(`잘못된 처분: ${patch.disposition}`);
223
- if (patch.kind !== undefined && patch.kind !== 'screen') throw new CliUserError(`잘못된 종류: ${patch.kind}`, 'screen');
262
+ if (patch.kind !== undefined && !CHECKLIST_KINDS.includes(patch.kind)) throw new CliUserError(`잘못된 종류: ${patch.kind}`, 'screen|postpub');
224
263
  if (patch.priority !== undefined && !['P0', 'P1', 'P2'].includes(patch.priority)) throw new CliUserError(`잘못된 우선순위: ${patch.priority}`);
225
264
  if (patch.predecessors !== undefined && (!Array.isArray(patch.predecessors) || patch.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === id))) throw new CliUserError('잘못된 선행 칸');
226
265
  if (patch.deadlineVersion !== undefined) store.validateVersion(patch.deadlineVersion);
@@ -319,6 +358,8 @@ export interface ChecklistGate {
319
358
  blocked: string[];
320
359
  moved: string[];
321
360
  knownIssues: Array<{ id: string; title: string; evidence: string }>;
361
+ /** Post-publication cells excluded from the pre-publication judgement. */
362
+ postpub?: string[];
322
363
  /** Screen cells whose `짝:` line is missing or has an untracked ⏳ — a warning; it never changes `ok`. */
323
364
  parity?: Array<{ id: string; why: string }>;
324
365
  }
@@ -336,8 +377,9 @@ export function parityGap(evidence: string | undefined): string | null {
336
377
  }
337
378
 
338
379
  export function checklistGate(v: string): ChecklistGate {
339
- const result: ChecklistGate = { ok: true, red: [], undecided: [], blocked: [], moved: [], knownIssues: [], parity: [] };
380
+ const result: ChecklistGate = { ok: true, red: [], undecided: [], blocked: [], moved: [], knownIssues: [], postpub: [], parity: [] };
340
381
  for (const item of listChecklist(v).items) {
382
+ if (item.kind === 'postpub') { result.postpub!.push(item.id); continue; }
341
383
  if (item.kind === 'screen') {
342
384
  const why = parityGap(item.evidence);
343
385
  if (why) result.parity!.push({ id: item.id, why });
@@ -350,16 +392,27 @@ export function checklistGate(v: string): ChecklistGate {
350
392
  else result.undecided.push(item.id);
351
393
  }
352
394
  result.ok = result.red.length === 0 && result.undecided.length === 0 && result.blocked.length === 0;
395
+ if (result.postpub!.length) debug.log('release-loop.checklist', 'gate-postpub-excluded', { version: v, ids: result.postpub });
353
396
  return result;
354
397
  }
355
398
 
356
399
  /** GATE-ENTRY-ALIGN: the cut-time judgement shared by `release run`'s entry check and the checklist-gate node —
357
- * past the landing deadline a non-P0 yellow without a disposition is carried (moved), and a P0 yellow always blocks. */
400
+ * past the landing deadline a non-P0 yellow without a disposition is carried (moved); P0 yellow blocks unless OP recorded known-issue. */
358
401
  export function cutChecklistGate(v: string, landBy: string | null | undefined, now: Date = new Date()): ChecklistGate & { autoMoved: string[] } {
359
- const items = listChecklist(v).items;
402
+ const { items, history } = listChecklist(v);
360
403
  const overdue = landBy !== null && landBy !== undefined && now.getTime() > Date.parse(landBy);
361
- const autoMoved = overdue ? items.filter((item) => item.status === 'yellow' && item.priority !== 'P0' && item.disposition === undefined).map((item) => item.id) : [];
362
- const p0 = items.filter((item) => item.status === 'yellow' && item.priority === 'P0').map((item) => item.id);
404
+ const autoMoved = overdue ? items.filter((item) => item.kind !== 'postpub' && item.status === 'yellow' && item.priority !== 'P0' && item.disposition === undefined).map((item) => item.id) : [];
405
+ const p0 = items.filter((item) => {
406
+ if (item.kind === 'postpub' || item.status !== 'yellow' || item.priority !== 'P0') return false;
407
+ if (item.disposition === 'known-issue') {
408
+ const decision = [...history].reverse().find((entry) => entry.id === item.id && entry.field === 'disposition' && entry.to === 'known-issue');
409
+ if (decision?.by === 'OP') {
410
+ debug.log('release-loop.checklist', 'p0-known-issue-allowed', { version: v, id: item.id, by: decision.by, at: decision.at });
411
+ return false;
412
+ }
413
+ }
414
+ return true;
415
+ }).map((item) => item.id);
363
416
  const gate = checklistGate(v);
364
417
  gate.undecided = gate.undecided.filter((id) => !autoMoved.includes(id) && !p0.includes(id));
365
418
  gate.moved = gate.moved.filter((id) => !p0.includes(id)).concat(autoMoved);