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,10 +4,23 @@ import { getUserConfig } from '../user-config.js';
4
4
  import { getSecretAsync } from '../nexus/config/secrets/index.js';
5
5
  import { fetchLinearProjectIssues, type LinearProjectIssue } from '../connectors/linear.js';
6
6
  import { formatElanousCard } from './elanous-card.js';
7
+ import recordedDateEvidence from './coo-admin-dates.evidence.json';
8
+
9
+ type CooDateEvidence = {
10
+ project: string;
11
+ verifiedIssues: Array<{
12
+ identifier: string;
13
+ title: string;
14
+ url: string;
15
+ officialDeadline: string | null;
16
+ preparationPeriod: string | { start: string } | null;
17
+ representativeActionDate: string | null;
18
+ }>;
19
+ };
7
20
 
8
21
  export const COO_ADMIN_SPEC: LLMToolSpec = {
9
22
  name: 'coo_admin',
10
- description: '읽기 전용 Linear COO 행정 조회 — «행정 뭐 남았어 · COO 할 일 · 마감 다가오는 행정» 질문에 사용. 외부 행정 프로젝트의 열린 일을 마감 순으로 읽는다.',
23
+ description: '읽기 전용 Linear COO 행정 조회 — «행정 뭐 남았어 · COO 할 일 · 마감 다가오는 행정» 질문에 사용. 외부 행정 프로젝트의 열린 일을 우선순위와 확인된 날짜 근거로 브리핑한다.',
11
24
  parameters: { type: 'object', properties: {}, required: [] },
12
25
  };
13
26
 
@@ -16,6 +29,8 @@ export interface CooAdminDeps {
16
29
  fetch?: typeof fetch;
17
30
  project?: string;
18
31
  now?: Date;
32
+ dateEvidence?: CooDateEvidence;
33
+ briefing?: boolean;
19
34
  }
20
35
 
21
36
  /** Reads the configured Linear project without changing any Linear issue. */
@@ -32,27 +47,73 @@ export async function dispatchCooAdmin(_args: Record<string, unknown>, deps: Coo
32
47
  const issues = await fetchLinearProjectIssues({ apiKey, project, fetch: deps.fetch ?? fetch });
33
48
  const today = deps.now ?? new Date();
34
49
  const todayUtc = Date.UTC(today.getUTCFullYear(), today.getUTCMonth(), today.getUTCDate());
35
- const daysUntil = (date: string) => Math.round((Date.parse(`${date.slice(0, 10)}T00:00:00Z`) - todayUtc) / 86_400_000);
50
+ const daysUntil = (date: string) => Math.round((Date.parse(`${date}T00:00:00Z`) - todayUtc) / 86_400_000);
51
+ const dateEvidence = deps.dateEvidence ?? (recordedDateEvidence as CooDateEvidence);
52
+ const verifiedDate = (date: string | null | undefined): string | null => {
53
+ if (!date || !/^\d{4}-\d{2}-\d{2}$/.test(date)) return null;
54
+ const time = Date.parse(`${date}T00:00:00Z`);
55
+ return Number.isFinite(time) && new Date(time).toISOString().slice(0, 10) === date ? date : null;
56
+ };
57
+ const evidenceFor = (item: LinearProjectIssue) => dateEvidence.project === project
58
+ ? dateEvidence.verifiedIssues.find(row => row.identifier === item.identifier && row.url === item.url && row.title === item.title)
59
+ : undefined;
60
+ const deadlineFor = (item: LinearProjectIssue) => verifiedDate(evidenceFor(item)?.officialDeadline);
61
+ const rank = (item: LinearProjectIssue) => item.priority === 0 ? 5 : item.priority;
62
+ if (deps.briefing) {
63
+ const todayKst = new Date(today.getTime() + 9 * 3_600_000).toISOString().slice(0, 10);
64
+ const day = (date: string) => Date.parse(`${date}T00:00:00Z`);
65
+ const todayDay = day(todayKst);
66
+ const byDeadline = (a: LinearProjectIssue, b: LinearProjectIssue) =>
67
+ day(deadlineFor(a)!) - day(deadlineFor(b)!) || rank(a) - rank(b) || a.identifier.localeCompare(b.identifier);
68
+ const dated = issues.filter(item => deadlineFor(item) !== null).sort(byDeadline);
69
+ const format = (item: LinearProjectIssue) => {
70
+ const due = deadlineFor(item);
71
+ const representative = verifiedDate(evidenceFor(item)?.representativeActionDate);
72
+ const priority = item.priority === 1 ? 'Urgent' : item.priority === 2 ? 'High' : `우선순위 ${item.priority || '미지정'}`;
73
+ const title = item.title.replace(/[\r\n\u2028\u2029]+/g, ' ').trim();
74
+ const url = item.url.replace(/[\r\n\u2028\u2029]+/g, '');
75
+ return `- ${due ? `확인된 마감일 ${due}` : '기한 미확인'} · ${priority} · ${title}${representative ? ` · 대표 손이 필요한 날 ${representative}` : ''}\n ${url}`;
76
+ };
77
+ const overdueItems = dated.filter(item => day(deadlineFor(item)!) < todayDay);
78
+ const upcoming = dated.filter(item => day(deadlineFor(item)!) >= todayDay && day(deadlineFor(item)!) <= todayDay + 14 * 86_400_000);
79
+ const later = dated.filter(item => day(deadlineFor(item)!) > todayDay + 14 * 86_400_000);
80
+ const unknown = issues.filter(item => deadlineFor(item) === null).sort((a, b) => rank(a) - rank(b) || a.identifier.localeCompare(b.identifier));
81
+ debug.log('coo.admin', 'read', { count: issues.length, overdue: overdueItems.length, reason: 'ok' });
82
+ return [issues.truncated ? '조회 상한 250건 · 아래 목록은 일부이며 빠진 항목의 기한은 측정 불가' : '',
83
+ `지난 기한 ${overdueItems.length}건\n${overdueItems.map(format).join('\n') || '없음'}`,
84
+ `14일 안 기한 ${upcoming.length}건\n${upcoming.map(format).join('\n') || '없음'}`,
85
+ ...(later.length || unknown.length ? [`그 밖 · 14일 이후 ${later.length}건 · 기한 미확인 ${unknown.length}건\n${[...later, ...unknown].map(format).join('\n')}`] : []),
86
+ ].filter(Boolean).join('\n');
87
+ }
36
88
  issues.sort((a, b) => {
37
- const deadlineOrder = a.dueDate == null ? (b.dueDate == null ? 0 : 1)
38
- : b.dueDate == null ? -1 : daysUntil(a.dueDate) - daysUntil(b.dueDate);
39
- return deadlineOrder || (a.priority === 0 ? 5 : a.priority) - (b.priority === 0 ? 5 : b.priority);
89
+ const aDue = deadlineFor(a);
90
+ const bDue = deadlineFor(b);
91
+ return rank(a) - rank(b) || (aDue === null ? (bDue === null ? 0 : 1)
92
+ : bDue === null ? -1 : daysUntil(aDue) - daysUntil(bDue));
40
93
  });
41
94
  count = issues.length;
42
95
  const lines = issues.map((item: LinearProjectIssue) => {
43
- const days = item.dueDate ? daysUntil(item.dueDate) : null;
96
+ const evidence = evidenceFor(item);
97
+ const due = deadlineFor(item);
98
+ const days = due ? daysUntil(due) : null;
44
99
  if (days !== null && days < 0) overdue++;
45
- const deadline = days === null ? '마감 없음' : days < 0 ? `지남 ${-days}일` : `D-${days}`;
46
- return `${deadline} · ${item.title} · ${item.state.name} · ${item.assignee?.name ?? '미배정'}\n${item.url}`;
100
+ const deadline = due ? `확인된 마감일 ${due} (${days !== null && days < 0 ? `지남 ${-days}일` : `D-${days}`})` : '기한 미확인 · 확인 예정일 미정';
101
+ const preparation = verifiedDate(typeof evidence?.preparationPeriod === 'string'
102
+ ? evidence.preparationPeriod : evidence?.preparationPeriod?.start);
103
+ const representative = verifiedDate(evidence?.representativeActionDate);
104
+ const dates = [preparation && `준비 시작일 ${preparation}`, representative && `대표 손이 필요한 날 ${representative}`].filter(Boolean);
105
+ return `${deadline} · 우선순위 ${item.priority || '미지정'} · ${item.title} · ${item.state.name} · ${item.assignee?.name ?? '미배정'}${dates.length ? ` · ${dates.join(' · ')}` : ''}\n${item.url}`;
47
106
  });
48
107
  debug.log('coo.admin', 'read', { count, overdue, reason: 'ok' });
49
- const scope = issues.truncated ? '최대 250건 중 조회한 항목만 마감 순으로 표시 (이후 항목은 포함되지 않음)\n' : '';
108
+ const scope = issues.truncated ? '최대 250건 중 조회한 항목만 우선순위·확인된 마감 순으로 표시 (이후 항목은 포함되지 않음)\n' : '';
50
109
  const prose = lines.length ? `${scope}${lines.join('\n')}` : '남은 행정 0건';
51
- const card = formatElanousCard({ kind: 'coo-admin', items: issues.map(item => ({
52
- title: item.title, due: item.dueDate?.slice(0, 10) ?? null,
53
- daysLeft: item.dueDate ? daysUntil(item.dueDate) : null,
54
- state: item.state.name, owner: item.assignee?.name ?? '미배정', url: item.url,
55
- })) });
110
+ const card = formatElanousCard({ kind: 'coo-admin', items: issues.map(item => {
111
+ const due = deadlineFor(item);
112
+ return {
113
+ title: item.title, due, daysLeft: due ? daysUntil(due) : null,
114
+ state: item.state.name, owner: item.assignee?.name ?? '미배정', url: item.url,
115
+ };
116
+ }) });
56
117
  return `${prose}\n${card}`;
57
118
  } catch (error) {
58
119
  const reason = error instanceof Error ? error.message : String(error);
@@ -13,6 +13,7 @@
13
13
  // 레포 내부 계약(src/time/format.ts)에 위임한다. 로컬 게터로 시/분/요일을 뽑으면
14
14
  // 프로세스 주변 TZ 에 종속돼 launchd 환경에서 조용히 어긋나기 때문.
15
15
  import { calendarFields, resolveTimeZone } from '../time/format.js';
16
+ import '../user-config.js'; // Standalone catch-up queries share the saved timezone with the scheduler.
16
17
 
17
18
  // 한 파트 매칭 — 지원: 별표, 별표+스텝, 범위 a-b, 범위+스텝, 단일 값 n.
18
19
  function matchPart(part: string, value: number, min: number, max: number): boolean {
@@ -26,6 +26,7 @@ import { loadMandate, type TradeMandate } from './trade-mandate.js';
26
26
  import { debug, redactSecretText } from '../debug/log.js';
27
27
  import { LogStore, logsDbPath, type LogStoreRow } from '../mss/logging/log-store.js';
28
28
  import { detectRepeatedFailures, explainFailure } from './repeated-failure.js';
29
+ import { listLoops, loopRecentRuns, type LoopRun } from '../loops/registry.js';
29
30
 
30
31
  /** 예약 레지스트리 조회 관측 — 실패가 0으로 접히지 않게 남기는 창구. */
31
32
  export const OPS_STATUS_LOG_CATEGORY = 'ops.status';
@@ -34,6 +35,29 @@ export const OPS_SCHEDULES_LOOKUP_FAILED_EVENT = 'schedules.lookup-failed';
34
35
  /** 예약 레지스트리 행 조회 seam — 미지정 시 실 레지스트리 reader. */
35
36
  export type ListScheduleRows = () => ScheduleRow[];
36
37
 
38
+ /** Graph-loop health input — run history is newest first. */
39
+ export type GraphLoopRuns = () => Array<{
40
+ id: string;
41
+ enabled: boolean;
42
+ runs: Array<Pick<LoopRun, 'at' | 'status' | 'failedNodes'>>;
43
+ }>;
44
+
45
+ /** Bounded window per loop: a streak whose oldest read run is already >24h old is flagged; a longer
46
+ * all-failed history than this window can only under-report (never over-report) the streak length. */
47
+ export const GRAPH_LOOP_HEALTH_RUN_WINDOW = 50;
48
+
49
+ function defaultGraphLoopRuns(): ReturnType<GraphLoopRuns> {
50
+ const out: ReturnType<GraphLoopRuns> = [];
51
+ for (const loop of listLoops().filter(entry => entry.enabled)) {
52
+ // One unreadable run history must not hide the other loops.
53
+ try { out.push({ id: loop.id, enabled: loop.enabled, runs: loopRecentRuns(loop.id, {}, GRAPH_LOOP_HEALTH_RUN_WINDOW) }); }
54
+ catch (err) {
55
+ debug.log('ops.health', 'graph-loop-failure-skipped', { loop: loop.id, reason: redactSecretText(err instanceof Error ? err.message : String(err)) });
56
+ }
57
+ }
58
+ return out;
59
+ }
60
+
37
61
  /** 조회 seam(테스트) — 미지정 시 실 스토어. */
38
62
  export interface OpsStatusOpts {
39
63
  now?: Date;
@@ -47,6 +71,8 @@ export interface OpsStatusOpts {
47
71
  planDraftFor?: (missionId: string) => string;
48
72
  /** Health-only log reader seam; the default reads the current instance's last ten minutes read-only. */
49
73
  recentLogs?: () => LogStoreRow[];
74
+ /** Health-only graph-loop registry reader; injection avoids the real state directory. */
75
+ graphLoopRuns?: GraphLoopRuns;
50
76
  }
51
77
 
52
78
  export interface CountByStatus { [status: string]: number }
@@ -341,6 +367,33 @@ export function opsHealth(opts: OpsStatusOpts = {}): OpsHealthReport {
341
367
  }
342
368
  }
343
369
 
370
+ // Graph-run history is independent of ops_events loops and of log-store failures.
371
+ try {
372
+ const loops = (opts.graphLoopRuns ?? defaultGraphLoopRuns)();
373
+ const nowMs = (opts.now ?? new Date()).getTime();
374
+ let flagged = 0;
375
+ for (const loop of loops) {
376
+ if (!loop.enabled) continue;
377
+ const runs = [...loop.runs].sort((a, b) => Date.parse(b.at) - Date.parse(a.at));
378
+ const failures = [] as typeof runs;
379
+ for (const run of runs) {
380
+ if (run.status !== 'failed') break;
381
+ failures.push(run);
382
+ }
383
+ const first = failures.at(-1);
384
+ if (failures.length < 2 || !first || !Number.isFinite(Date.parse(first.at)) || nowMs - Date.parse(first.at) <= 24 * 3600_000) continue;
385
+ anomalies.push({
386
+ kind: 'repeated_failure', entity: `loop:${loop.id}`,
387
+ detail: `그래프 루프 ${loop.id} 연속 실패 ${failures.length}회 · ${first.at} 부터 · 마지막 실패 노드 ${failures[0]!.failedNodes.join(', ')}`,
388
+ since: first.at,
389
+ });
390
+ flagged++;
391
+ }
392
+ debug.log('ops.health', 'graph-loop-failure', { loops: loops.length, flagged });
393
+ } catch (err) {
394
+ debug.log('ops.health', 'graph-loop-failure-skipped', { reason: redactSecretText(err instanceof Error ? err.message : String(err)) });
395
+ }
396
+
344
397
  // Independent log check: an unreadable log store must not hide task/loop/schedule anomalies.
345
398
  try {
346
399
  const recentLogs = opts.recentLogs ?? (() => {
@@ -17,6 +17,7 @@ import { getUserConfig, type UserConfig } from '../user-config.js';
17
17
  import { resolveChannelBotToken } from '../channel-bot-token.js';
18
18
  import { explainReportRoute, isOperationalKind, kindRouteTarget, logKindRouteFallback, mainHomeTarget } from './telegram-kind-route.js';
19
19
  import { debug } from '../debug/log.js';
20
+ import type { AddBriefItem } from '../briefing/brief-items.js';
20
21
  import { registerLogStoreSink, setLogInstanceName } from '../mss/logging/log-store.js';
21
22
  import type { LogSink } from '../mss/logging/sink.js';
22
23
  import { resolveDaemonEndpoint } from '../nexus/daemon-endpoint.js';
@@ -25,7 +26,7 @@ import { effectiveInstanceRoot, prodInstanceRoot } from '../instance/resolve.js'
25
26
  // import 라 런타임 순환 없음(발송 로직은 이 파일에 self-contained). origin 없으면 report 폴백.
26
27
  import type { MissionOrigin } from '../autopilot/mission-origin.js';
27
28
  import { conatusDataDir, conatusPath } from './conatus-data-dir.js';
28
- import { assertNoRealSendFromTest, assertNotTestWritingOps, isTestDouble } from '../instance/test-write-guard.js';
29
+ import { assertNoRealSendFromTest, assertNotTestWritingOps, isTestDouble, TestOpsWriteRefusedError } from '../instance/test-write-guard.js';
29
30
 
30
31
  /** Explicit `ELANOUS_NEXUS_URL` wins. Otherwise ask the daemon endpoint resolver.
31
32
  * A missing daemon is not a guessed port — the caller falls through to direct send. */
@@ -626,6 +627,7 @@ export function deliver(text: string, kind = 'alert', onBot?: (bot: string) => v
626
627
  }
627
628
  // 2) fallback: 텔레그램 sendMessage 직접(3900자 분할) — 데몬 미경유라 클라가 원장 기록.
628
629
  // The same config judges the route and explains a failure (review r1).
630
+ // deliver → sendTelegramDirect: the refusal propagates to the caller instead of becoming «undeliverable».
629
631
  let cfg: UserConfig | undefined;
630
632
  try { cfg = getUserConfig(); } catch { /* sendTelegramDirect fails closed without config */ }
631
633
  if (sendTelegramDirect(text, kind, cfg ? { config: cfg } : {}, onBot)) return 'direct';
@@ -633,6 +635,13 @@ export function deliver(text: string, kind = 'alert', onBot?: (bot: string) => v
633
635
  return false;
634
636
  }
635
637
 
638
+ type UndeliverableRecorder = (item: AddBriefItem) => void;
639
+ let undeliverableRecorder: UndeliverableRecorder | null = null;
640
+ /** Replace the ledger writer in tests; null restores the production ledger. */
641
+ export function setUndeliverableRecorder(recorder: UndeliverableRecorder | null): void {
642
+ undeliverableRecorder = recorder;
643
+ }
644
+
636
645
  /** OB8b — both paths failed: say so loudly, with the universe this process resolved, instead of a silent false.
637
646
  * The usual cause (10-01 · MK): an ad-hoc `bun -e` or a script from a source tree resolves a cwd-derived test
638
647
  * universe, so it finds neither the production daemon nor the production bot token. */
@@ -647,7 +656,22 @@ function reportUndeliverable(kind: string, daemonPath: DaemonPathClass | 'not-fo
647
656
  let route: ReturnType<typeof explainReportRoute> | null = null;
648
657
  try { if (cfg) route = explainReportRoute(cfg, kind); } catch { /* the report still goes out */ }
649
658
  ensureOutboundLogSink();
650
- try { debug.log('outbound.send', 'undeliverable', { kind: safeObservationLabel(kind), daemonPath, universe, root, route: route?.reason ?? 'unknown' }); } catch { /* fail-soft */ }
659
+ const reason = route?.reason ?? 'unknown';
660
+ try { debug.log('outbound.send', 'undeliverable', { kind: safeObservationLabel(kind), daemonPath, universe, root, route: reason }); } catch { /* fail-soft */ }
661
+ try {
662
+ const record = undeliverableRecorder ?? ((item: AddBriefItem) => {
663
+ const { BriefItemsLedger } = require('../briefing/brief-items.js') as typeof import('../briefing/brief-items.js');
664
+ new BriefItemsLedger().add(item);
665
+ });
666
+ record({
667
+ domain: '운영', priority: 'P1', source: 'outbound.undeliverable',
668
+ text: `미전달: kind ${kind} · 데몬 ${daemonPath} · 경로 ${reason} · 우주 ${universe}`,
669
+ evidence: 'elanous logs --category outbound.send --event undeliverable',
670
+ dedupeKey: `${kind} · ${reason}`, dedupeWithinMs: 60 * 60_000,
671
+ });
672
+ } catch (error) {
673
+ try { debug.log('outbound.send', 'undeliverable-record-failed', { kind: safeObservationLabel(kind), route: reason, error: error instanceof Error ? error.message : String(error) }); } catch { /* fail-soft */ }
674
+ }
651
675
  const hint = universe === 'prod'
652
676
  ? '운영 데몬이 떠 있는지 확인: elanous nexus show'
653
677
  : '운영으로 보내려면 설치본 elanous 로 실행하거나 ELANOUS_STATE_DIR=~/.elanous 와 --config-dir ~/.elanous 를 준다';
@@ -681,16 +705,26 @@ export function sendTelegramDirect(
681
705
  deps: { config?: UserConfig; sendRaw?: typeof sendTelegramRaw; legacyEnv?: typeof conatusEnv } = {},
682
706
  onBot?: (bot: string) => void,
683
707
  ): boolean {
684
- const sendRaw = deps.sendRaw ?? sendTelegramRaw;
685
- // An injected sender still may not run in a test that resolved the ops universe.
686
- if (deps.sendRaw) assertTestSendFaked('send a Telegram message from the ops universe', false);
708
+ const sendRaw = (token: string, chatId: string | number, body: string): boolean => {
709
+ // The transport is checked only after a route is eligible; a test double cannot target the ops universe.
710
+ assertTestSendFaked('send a real Telegram message', !deps.sendRaw);
711
+ return (deps.sendRaw ?? sendTelegramRaw)(token, chatId, body);
712
+ };
687
713
  let cfg: UserConfig | undefined;
688
714
  try { cfg = deps.config ?? getUserConfig(); } catch { /* unavailable config: operational delivery still fails closed */ }
689
715
  if (cfg) {
690
716
  try {
691
717
  const target = kindRouteTarget(cfg, kind);
692
- if (target) { onBot?.(botLabel(target.botToken)); return sendRaw(target.botToken, String(target.chatId), text); }
693
- } catch { /* unavailable channel routing: fall through */ }
718
+ if (target) {
719
+ // Refusal must escape the routing fallback; other routing/callback/transport failures retain that fallback.
720
+ assertTestSendFaked('send a real Telegram message', !deps.sendRaw);
721
+ onBot?.(botLabel(target.botToken));
722
+ return (deps.sendRaw ?? sendTelegramRaw)(target.botToken, String(target.chatId), text);
723
+ }
724
+ } catch (error) {
725
+ if (error instanceof TestOpsWriteRefusedError) throw error;
726
+ /* unavailable channel routing: fall through */
727
+ }
694
728
  // A declared table is authoritative: missing roles cannot escape to an env bot.
695
729
  if (cfg.telegram.channels?.length) {
696
730
  logKindRouteFallback(kind, 'none', false);
@@ -1,17 +1,31 @@
1
+ import { readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
1
3
  import type { LLMToolSpec } from '../llm.js';
4
+ import { releaseLedgerRoot } from '../instance/resolve.js';
5
+ import { contextNow, type ContextNowAnswer, type ContextFact } from '../context-bus/context-now.js';
2
6
  import type { ToolRuntimeContext } from '../tool-runtime/types.js';
3
7
  import { debug } from '../debug/log.js';
4
8
  import { requestConfirmation, type ConfirmOpts, type ConfirmResult } from '../hitl/confirm.js';
5
- import { devVersion, checklistDevVersion, listChecklist, summarizeChecklist, type Checklist } from '../release-loop/checklist.js';
9
+ import { devVersion, checklistDevVersion, listChecklist, summarizeChecklist, type Checklist, type ChecklistItem } from '../release-loop/checklist.js';
6
10
  import { add, move, validateVersion } from '../release-loop/feature-store.js';
7
- import { formatKst, getSchedule, setSchedule, type ReleaseSchedule } from '../release-loop/release-schedule.js';
11
+ import { formatKst, formatSchedule, getSchedule, listSchedules, setSchedule, type ReleaseSchedule } from '../release-loop/release-schedule.js';
8
12
  import { latestGraphRun, type GraphRunState } from '../graph-runner/runner.js';
9
13
  import { formatElanousCard, type ElanousCard } from './elanous-card.js';
10
14
 
11
15
  export const RELEASE_STATUS_SPEC: LLMToolSpec = {
12
16
  name: 'release_status',
13
- description: '판 어디까지 · 컷 언제 · 릴리스 상황 · 판올림 · 체크리스트 · 남은 칸을 읽는다. 판 일정, 빨강 칸, 담당별 노랑, 최근 발행 런을 조회하는 읽기 전용 도구. 행정 업무는 coo_admin.',
14
- parameters: { type: 'object', properties: { version: { type: 'string', description: '조회할 판. 생략하면 개발 판과 다음 판.' } }, required: [] },
17
+ description: '판 어디까지 · 컷 언제 · 릴리스 상황 · 판올림 · 체크리스트 · 남은 칸을 읽는다. 판 일정, 빨강 칸, 담당별 노랑, 최근 발행 런을 조회하는 읽기 전용 도구. 행정 업무는 coo_admin.\n'
18
+ + 'topic=status(기본): 개발·다음 판 현황과 발행 원장.\n'
19
+ + 'topic=features: 지정 판의 모든 피처·칸(끝난 칸 포함).\n'
20
+ + 'topic=cell: id 칸 하나의 상태·근거와 살핀 판.\n'
21
+ + 'topic=schedule: 발행 이후 판의 컷·착지·발행·동결 일정.\n'
22
+ + 'topic=ops: 도는 런·발행·늦은 스케줄·자리·열린 결정의 출처 있는 개관.\n'
23
+ + '발행·버전·피처·체크리스트·칸·컷·일정·운영 상태 질문은 Grep·ListDir·파일 검색보다 이 도구를 먼저 부른다 — 그 답은 파일이 아니라 원장에 있다.',
24
+ parameters: { type: 'object', properties: {
25
+ version: { type: 'string', description: '조회할 판. 생략하면 개발 판과 다음 판.' },
26
+ topic: { type: 'string', enum: ['status', 'features', 'cell', 'schedule', 'ops'], description: '읽을 대상(기본 status).' },
27
+ id: { type: 'string', description: 'topic=cell 때 찾을 칸 id(필수).' },
28
+ }, required: [] },
15
29
  };
16
30
 
17
31
  export const RELEASE_CHANGE_SPEC: LLMToolSpec = {
@@ -35,6 +49,9 @@ export interface ReleaseToolDeps {
35
49
  devVersion?: () => string;
36
50
  checklist?: (version: string) => Checklist;
37
51
  schedule?: (version: string) => ReleaseSchedule | null;
52
+ schedules?: () => ReleaseSchedule[];
53
+ publishedRecord?: (version: string) => unknown;
54
+ contextNow?: (options: { topic?: string }) => ContextNowAnswer;
38
55
  latestRun?: (graphId: string) => GraphRunState | null;
39
56
  confirm?: (options: ConfirmOpts) => Promise<ConfirmResult>;
40
57
  add?: typeof add;
@@ -61,18 +78,106 @@ function dDay(days: number): string {
61
78
  return days < 0 ? `D+${-days}` : days === 0 ? 'D-day' : `D-${days}`;
62
79
  }
63
80
 
81
+ type Published = { version: string | null; publishedAt: string | null; state: 'published' | 'no-record' | 'unreadable' | 'unknown' };
82
+
83
+ function readPublishedRecord(version: string): unknown {
84
+ return JSON.parse(readFileSync(join(releaseLedgerRoot(), 'release', version, 'release.json'), 'utf8'));
85
+ }
86
+
87
+ function publishedStatus(released: string, deps: ReleaseToolDeps): Published {
88
+ if (!released) return { version: null, publishedAt: null, state: 'unknown' };
89
+ try {
90
+ const raw: unknown = (deps.publishedRecord ?? readPublishedRecord)(released);
91
+ if (raw === undefined || raw === null) return { version: released, publishedAt: null, state: 'no-record' };
92
+ const record: unknown = typeof raw === 'string' ? JSON.parse(raw) : raw;
93
+ if (record && typeof record === 'object' && 'version' in record && 'publishedAt' in record
94
+ && record.version === released && typeof record.publishedAt === 'string' && Number.isFinite(Date.parse(record.publishedAt))) {
95
+ return { version: released, publishedAt: record.publishedAt, state: 'published' };
96
+ }
97
+ throw new Error('release.json 의 version 또는 publishedAt 가 잘못됨');
98
+ } catch (error) {
99
+ if ((error as NodeJS.ErrnoException)?.code === 'ENOENT') return { version: released, publishedAt: null, state: 'no-record' };
100
+ const reason = error instanceof Error ? error.message : String(error);
101
+ debug.log('release.tool', 'published-unreadable', { version: released, reason });
102
+ return { version: released, publishedAt: null, state: 'unreadable' };
103
+ }
104
+ }
105
+
106
+ function firstLine(text: string): string { return text.split(/\r?\n/, 1)[0] ?? ''; }
107
+
108
+ function versionOrder(a: string, b: string): number {
109
+ const left = a.split('.').map(Number), right = b.split('.').map(Number);
110
+ return (left[0]! - right[0]!) || (left[1]! - right[1]!) || (left[2]! - right[2]!);
111
+ }
112
+
113
+ function cellView(item: ChecklistItem) {
114
+ return { id: item.id, title: firstLine(item.title), status: item.status,
115
+ owner: item.owner ?? null, priority: item.priority ?? null, evidence: item.evidence ? firstLine(item.evidence) : null };
116
+ }
117
+
64
118
  export function dispatchReleaseStatus(args: Record<string, unknown>, deps: ReleaseToolDeps = {}): { text: string; structured: Record<string, unknown> } {
119
+ const topic = args.topic === undefined ? 'status' : args.topic;
120
+ if (typeof topic !== 'string' || !['status', 'features', 'cell', 'schedule', 'ops'].includes(topic)) throw new Error('topic 은 status, features, cell, schedule, ops 중 하나');
65
121
  const requested = args.version;
66
122
  if (requested !== undefined && (typeof requested !== 'string' || !requested.trim())) throw new Error('판 이름이 필요합니다');
67
- const version = requested ? null : checklistDevVersion(deps.devVersion?.() ?? devVersion());
123
+ const checklist = deps.checklist ?? listChecklist;
124
+ if (topic === 'ops') {
125
+ const answer = (deps.contextNow ?? contextNow)({});
126
+ const kinds: ContextFact['kind'][] = ['run', 'release', 'schedule-late', 'seat', 'decision'];
127
+ const facts = answer.facts.filter(fact => kinds.includes(fact.kind));
128
+ debug.log('release.tool', 'status', { action: 'status', topic, version: requested ?? null });
129
+ return { text: facts.length ? facts.map(fact => JSON.stringify(fact)).join('\n') : '운영 개관: 관측된 사실 없음', structured: { facts } };
130
+ }
131
+ const dev = checklistDevVersion(deps.devVersion?.() ?? devVersion());
132
+ if (topic === 'features' || topic === 'cell' || topic === 'schedule') {
133
+ let result: { text: string; structured: Record<string, unknown> };
134
+ if (topic === 'features') {
135
+ const target = (requested as string | undefined) ?? dev;
136
+ validateVersion(target);
137
+ const data = checklist(target);
138
+ const counts = summarizeChecklist(data);
139
+ const items = data.items.slice(0, 60).map(({ id, title, status, owner, priority }) =>
140
+ ({ id, title: firstLine(title), status, owner: owner ?? null, priority: priority ?? null }));
141
+ const total = data.items.length;
142
+ result = { text: `${target} 판 피처 ${total}칸 · 초록 ${counts.green} · 노랑 ${counts.yellow} · 빨강 ${counts.red} · 끝 ${counts.done}\n${items.map(item => `${item.id} ${item.title} · ${item.status} · ${item.owner ?? '미배정'}`).join('\n')}${total > 60 ? `\n앞 60칸만 표시(전체 ${total}칸)` : ''}`,
143
+ structured: { version: target, items, counts: { green: counts.green, yellow: counts.yellow, red: counts.red, done: counts.done }, total, truncated: total > 60 } };
144
+ } else if (topic === 'cell') {
145
+ const id = requiredString(args, 'id');
146
+ const searched = requested ? [requested as string] : [...new Set([dev, nextVersion(dev), checklist(dev).released].filter(Boolean))];
147
+ let found: { version: string; item: ChecklistItem } | undefined;
148
+ const examined: string[] = [];
149
+ for (const v of searched) {
150
+ validateVersion(v);
151
+ examined.push(v);
152
+ const item = checklist(v).items.find(item => item.id === id);
153
+ if (item) { found = { version: v, item }; break; }
154
+ }
155
+ result = found
156
+ ? { text: `${found.version} · ${id} ${firstLine(found.item.title)} · ${found.item.status} · 담당 ${found.item.owner ?? '미배정'}${found.item.evidence ? ` · 근거 ${firstLine(found.item.evidence)}` : ''}`,
157
+ structured: { found: true, version: found.version, item: cellView(found.item) } }
158
+ : { text: `${id} · 살핀 판(${examined.join(', ')})에 없음`, structured: { found: false, searched: examined } };
159
+ } else {
160
+ const released = checklist(dev).released;
161
+ const schedules = (deps.schedules ?? listSchedules)().filter(row => !released || versionOrder(row.version, released) > 0)
162
+ .sort((a, b) => versionOrder(a.version, b.version));
163
+ result = { text: schedules.length ? schedules.map(formatSchedule).join('\n') : '살핀 판에 일정 없음',
164
+ structured: { schedules: schedules.map(row => ({ version: row.version, cutAt: row.cutAt, landBy: row.landBy,
165
+ publishAt: row.publishAt ?? null, freezeFrom: row.freezeFrom ?? null, freezeUntil: row.freezeUntil ?? null })) } };
166
+ }
167
+ debug.log('release.tool', 'status', { action: 'status', topic, version: requested ?? dev });
168
+ return result;
169
+ }
170
+ const version = requested ? null : dev;
68
171
  const versions = requested ? [requested as string] : [version!, nextVersion(version!)];
69
172
  const now = deps.now ?? new Date();
70
173
  const run = (deps.latestRun ?? latestGraphRun)('release-loop');
71
174
  const latest = run ? { status: run.status, lastNode: run.path.at(-1) ?? null, startedAt: run.startedAt ?? null } : null;
175
+ let devChecklist: Checklist | undefined;
72
176
  const entries = versions.map(v => {
73
177
  validateVersion(v);
74
178
  const schedule = (deps.schedule ?? getSchedule)(v);
75
179
  const data = (deps.checklist ?? listChecklist)(v);
180
+ if (v === dev) devChecklist = data;
76
181
  const summary = summarizeChecklist(data);
77
182
  const red = data.items.filter(item => item.status === 'red').map(({ id, title, owner }) => ({ id, title, owner: owner ?? '미배정' }));
78
183
  const yellowByOwner: Record<string, number> = {};
@@ -84,12 +189,12 @@ export function dispatchReleaseStatus(args: Record<string, unknown>, deps: Relea
84
189
  const landDaysLeft = schedule?.landBy ? daysLeft(schedule.landBy, now) : null;
85
190
  const cutHoursLeft = schedule ? Math.ceil((Date.parse(schedule.cutAt) - now.getTime()) / 3_600_000) : null;
86
191
  const landHoursLeft = schedule?.landBy ? Math.ceil((Date.parse(schedule.landBy) - now.getTime()) / 3_600_000) : null;
87
- return { version: v, schedule: schedule ? { cutAt: schedule.cutAt, landBy: schedule.landBy, cutDaysLeft, landDaysLeft, cutHoursLeft, landHoursLeft } : null,
192
+ return { version: v, schedule: schedule ? { cutAt: schedule.cutAt, landBy: schedule.landBy, publishAt: schedule.publishAt ?? null, cutDaysLeft, landDaysLeft, cutHoursLeft, landHoursLeft } : null,
88
193
  counts: { green: summary.green, yellow: summary.yellow, red: summary.red, done: summary.done }, red, yellowByOwner };
89
194
  });
90
195
  const lines = entries.map(entry => {
91
196
  const schedule = entry.schedule;
92
- return `${entry.version} · 컷 ${schedule ? formatKst(schedule.cutAt) : '미정'}${schedule?.landBy ? ` · 착지 마감 ${formatKst(schedule.landBy)}` : ' · 착지 마감 미정'}${schedule ? ` · 컷 ${dDay(schedule.cutDaysLeft!)} (${schedule.cutHoursLeft}시간)${schedule.landDaysLeft !== null ? ` · 착지 ${dDay(schedule.landDaysLeft)} (${schedule.landHoursLeft}시간)` : ''}` : ''}\n` +
197
+ return `${entry.version} · 컷 ${schedule ? formatKst(schedule.cutAt) : '미정'}${schedule?.landBy ? ` · 착지 마감 ${formatKst(schedule.landBy)}` : ' · 착지 마감 미정'}${schedule ? ` · 컷 ${dDay(schedule.cutDaysLeft!)} (${schedule.cutHoursLeft}시간)${schedule.landDaysLeft !== null ? ` · 착지 ${dDay(schedule.landDaysLeft)} (${schedule.landHoursLeft}시간)` : ''}` : ''}${schedule?.publishAt ? ` · 발행 ${formatKst(schedule.publishAt).split(' ')[1]} KST` : ''}\n` +
93
198
  `초록 ${entry.counts.green} · 노랑 ${entry.counts.yellow} · 빨강 ${entry.counts.red} · 끝 ${entry.counts.done}\n` +
94
199
  `빨강 칸: ${entry.red.length ? entry.red.map(item => `${item.id} ${item.title} (${item.owner})`).join(', ') : '없음'}\n` +
95
200
  `담당별 노랑: ${Object.keys(entry.yellowByOwner).length ? Object.entries(entry.yellowByOwner).map(([owner, count]) => `${owner} ${count}`).join(', ') : '없음'}`;
@@ -99,9 +204,13 @@ export function dispatchReleaseStatus(args: Record<string, unknown>, deps: Relea
99
204
  { kind: 'release-schedule', items: entries.map(entry => ({ title: `${entry.version} 컷`, due: entry.schedule ? kstDate(entry.schedule.cutAt) : null, daysLeft: entry.schedule?.cutDaysLeft ?? null, state: entry.schedule ? 'scheduled' : 'undecided', owner: 'release' })), meta: { versions: entries.map(entry => entry.version) } },
100
205
  { kind: 'release-checklist', items: entries.flatMap(entry => entry.red.map(item => ({ title: `${item.id} ${item.title}`, due: null, daysLeft: null, state: 'red', owner: item.owner }))), meta: { counts: entries.map(entry => ({ version: entry.version, ...entry.counts })) } },
101
206
  ];
102
- const structured = { releases: entries, latestRun: latest };
103
- debug.log('release.tool', 'status', { action: 'status', version: versions.join(',') });
104
- return { text: `${lines.join('\n\n')}\n${cards.map(formatElanousCard).join('\n')}`, structured };
207
+ const published = publishedStatus((devChecklist ?? checklist(dev)).released, deps);
208
+ const publishedLine = published.state === 'published' ? `발행 판 ${published.version} · 발행 ${formatKst(published.publishedAt!)}`
209
+ : published.state === 'no-record' ? `발행 판 ${published.version} · 발행 기록 없음`
210
+ : published.state === 'unreadable' ? `발행 판 ${published.version} · 발행 기록 못 읽음` : '발행 판 모름';
211
+ const structured = { releases: entries, latestRun: latest, published };
212
+ debug.log('release.tool', 'status', { action: 'status', topic, version: versions.join(',') });
213
+ return { text: `${lines.join('\n\n')}\n${cards.map(formatElanousCard).join('\n')}\n${publishedLine}`, structured };
105
214
  }
106
215
 
107
216
  function requiredString(args: Record<string, unknown>, key: string): string {
@@ -289,14 +289,17 @@ export function cronEntryId(cron: string, effectiveCommand: string): string {
289
289
  return createHash('sha1').update(cron + '|' + effectiveCommand).digest('hex').slice(0, 12);
290
290
  }
291
291
 
292
- /** ★ 관측성 래퍼 unwrap (RFC-scheduler-execution-observability·2026-07-15) — crontab 라인이
293
- * `bun scripts/cron-run.ts --schedule-id <id> scripts/X.ts --a` 로 래핑돼도 id/name 파생은 안쪽 실제 target 기준으로.
294
- * 래퍼와 그 id 인자만 제거 → 래핑 전 원본과 동일 문자열 → id(sha1) 불변·마이그레이션 0.
295
- * 순수·멱등(비래핑 라인은 그대로 반환). */
292
+ /** ★ 관측성 래퍼 unwrap (RFC-scheduler-execution-observability·2026-07-15) — hq-fence 한 겹을
293
+ * 먼저 벗긴 뒤 cron-run.ts 래퍼와 id 인자를 제거한다. id/name 파생은 안쪽 target 기준.
294
+ * 감싸지 않은 명령은 그대로 반환하며, 결과는 다시 unwrap 해도 같다. */
296
295
  export function unwrapCronCommand(command: string): string {
297
- const shell = command.replace(/(?:\S*\/)?bun\s+(?:\S*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?--shell\s+/, '');
298
- if (shell !== command) return shell;
299
- return command.replace(/(?:[^\s]*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?/, '');
296
+ // 작은따옴표 인코딩('"'"' · '\'')만 복원한다. 닫힌 인용 뒤의 바깥 로그 리다이렉트는 버리고,
297
+ // 줄 끝 `# 주석` 은 감싸기 전 줄과 같은 꼴이 되도록 안쪽 명령 뒤에 그대로 붙인다.
298
+ const fence = /^(?:\S*\/)?hq-fence\s+(?:--role\s+[^\s'"]+(?:\s+--)?|[^\s'"]+)\s+'((?:[^']|'"'"'|'\\'')*)'(?:\s+(?:\d*>>?\s*\S+|\d+>&\d+))*(\s+#.*)?$/.exec(command);
299
+ const inner = fence ? fence[1]!.replaceAll(`'"'"'`, "'").replaceAll(`'\\''`, "'") + (fence[2] ?? '') : command;
300
+ const shell = inner.replace(/(?:\S*\/)?bun\s+(?:\S*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?--shell\s+/, '');
301
+ if (shell !== inner) return shell;
302
+ return inner.replace(/(?:[^\s]*\/)?cron-run\.ts\s+(?:--schedule-id\s+\S+\s+)?/, '');
300
303
  }
301
304
 
302
305
  /** crontab 라인을 관측성 래퍼로 감싼다(P3) — `bun scripts/X.ts` → `bun scripts/cron-run.ts --schedule-id <id> scripts/X.ts`.
@@ -26,6 +26,7 @@ import { openSchedulesDb, listSchedules, readCrontab, parseCronLine, scriptName,
26
26
  import { recordScheduledExecution } from './schedule-observability.js';
27
27
  import { prevScheduledFire } from './cron-match.js';
28
28
  import { resolveTimeZone } from '../time/format.js';
29
+ import '../user-config.js'; // Register the saved timezone before selecting the firing and catch-up clock.
29
30
  import { debug } from '../debug/log.js';
30
31
 
31
32
  interface CronTaskLike { stop(): void }
@@ -37,7 +37,7 @@ function warnIfIgnoredEnv(resolved: string, source: 'flag' | 'state-dir' | 'defa
37
37
  if (env === undefined || normalizedDir(env) === normalizedDir(resolved)) return;
38
38
  console.error(`ELANOUS_CONFIG_DIR 는 읽지 않습니다 — 설정 폴더 = ${resolved} · 그 폴더를 쓰려면 --config-dir ${normalizedDir(env)}`);
39
39
  try {
40
- const { debug } = require('./debug/log.js') as typeof import('./debug/log.js');
40
+ const { debug } = require('./debug/log.js') as { debug: { log: (category: string, event: string, data: Record<string, unknown>) => void } };
41
41
  debug.log('config.dir', 'env-ignored', { env, resolved, source });
42
42
  } catch { /* logging must not change config resolution */ }
43
43
  }
@@ -63,7 +63,7 @@ export function getElanousConfigDir(): string {
63
63
  // 두 축이 한 뿌리로 수렴한다. 로직을 여기 중복 구현하지 않는다.
64
64
  // (`configDirFollowingStateDir` 은 §4d 계약을 문서화·테스트하는 순수 함수로 남는다 —
65
65
  // 실제 해석 경로는 이 리졸버 하나다.)
66
- const { effectiveInstanceRoot } = require('./instance/resolve.js') as typeof import('./instance/resolve.js');
66
+ const { effectiveInstanceRoot } = require('./instance/resolve.js') as { effectiveInstanceRoot: () => string };
67
67
  const resolved = effectiveInstanceRoot();
68
68
  warnIfIgnoredEnv(resolved, process.env.ELANOUS_STATE_DIR?.trim() ? 'state-dir' : 'default');
69
69
  return resolved;
@@ -33,7 +33,7 @@ import {
33
33
  type LockMeta,
34
34
  } from './telegram-lock.js';
35
35
 
36
- import { defaultUnixSocketPath } from './boot/acp-server.js';
36
+ import { defaultUnixSocketPath } from './boot/acp-socket-path.js';
37
37
 
38
38
  export type ElanousDaemonLockMeta = LockMeta;
39
39
  export class ElanousDaemonLockError extends TelegramLockError {}
@@ -56,8 +56,8 @@ export function elanousDaemonLogPath(): string {
56
56
  return joinPath(elanousDaemonDir(), 'elanous.log');
57
57
  }
58
58
 
59
- /** Default unix socket path the daemon binds. Re-exported from
60
- * `boot/acp-server.ts` so callers don't have to chase the source. */
59
+ /** Default unix socket path the daemon binds. Resolved from
60
+ * `boot/acp-socket-path.ts` without loading the ACP server. */
61
61
  export function elanousDaemonSocketPath(): string {
62
62
  return defaultUnixSocketPath();
63
63
  }
@@ -7,6 +7,7 @@ import { defaultGraphsDir } from '../self-implement/graph-templates.js';
7
7
  import { getElanousConfigDir } from '../elanous-config-dir.js';
8
8
  import type { ExecAttachment } from './store.js';
9
9
  import { debug } from '../debug/log.js';
10
+ import { peerEditRunGate } from '../nexus/api/graph-peer-edit.js';
10
11
  import { OUTPUT_KINDS, pickDefaultOutput, type OutputKind } from './default-outputs.js';
11
12
 
12
13
  export interface InstalledGraph {
@@ -105,6 +106,11 @@ async function coreAndMineGraphs(coreDir: string, mineDir: string): Promise<Inst
105
106
  const id = doc?.graph_id;
106
107
  if (typeof id !== 'string' || !/^[a-z0-9-]+$/.test(id) || seen.has(id)) continue;
107
108
  if (core && doc?.loop?.exec_request !== true) continue;
109
+ // W9c — a «mine» graph a peer changed is not runnable until the owner approves it (fail closed).
110
+ if (!core) {
111
+ const gate = peerEditRunGate(dir, id);
112
+ if (!gate.ok) { debug.log('exec-requests', 'skipped-peer-edit', { id, error: gate.error }); continue; }
113
+ }
108
114
  const inputs = doc?.loop?.inputs;
109
115
  const inputKeys = core && Array.isArray(inputs)
110
116
  ? inputs.filter((key): key is string => typeof key === 'string')
@@ -22,7 +22,7 @@ export interface ActiveRunsForGoalDeps {
22
22
  /** Only a live process with an exact goal ID or verbatim authored ask is a duplicate. Incomplete observation is not absence. */
23
23
  export function activeRunsForGoal(goalId: string, deps: ActiveRunsForGoalDeps = {}): ActiveRunsForGoal {
24
24
  try {
25
- const observation = (deps.queryRuns ?? (() => queryRunningRuns({ includeTest: true, caller: 'execution-loop.launch-gate', noCache: true })))();
25
+ const observation = (deps.queryRuns ?? (() => queryRunningRuns({ includeTest: true, caller: 'execution-loop.launch-gate' })))();
26
26
  const loadLedger = deps.loadLedger ?? loadRunLedger;
27
27
  const readGoalDocument = deps.readGoalDocument ?? ((path: string) => readFileSync(path, 'utf8'));
28
28
  let unknown = observation.completeness !== 'complete' || observation.pty.unreadable.length > 0;
@@ -39,6 +39,10 @@ export const messagesEn: Messages = {
39
39
  rangeError: 'Value must be between {min} and {max}.',
40
40
  patternError: '"{value}" does not match the expected pattern.',
41
41
 
42
+ // Chat fallback
43
+ chatNoSynthesisLead: 'I could not finish the answer — the time to summarize ran out after {n} tool calls. Please ask a narrower question (for example, just one thing).',
44
+ chatFoldedInternalTail: '● Internal notes folded · {n} lines · press f to expand',
45
+
42
46
  // Async + status
43
47
  loading: 'Loading…',
44
48
  saving: 'Saving…',
@@ -76,6 +80,7 @@ export const messagesEn: Messages = {
76
80
  setupBanner: 'elanous — setup wizard',
77
81
  setupWritingTo: 'Writing to: {path}',
78
82
  setupComplete: 'Setup complete',
83
+ setupErrorReportNotice: 'If something breaks, elanous reports the error to our team automatically (error details, version and a random install ID — never your name or email). To turn it off: elanous config set errorReports.enabled false',
79
84
  setupRerunHint: 'Re-run: {cmd}',
80
85
 
81
86
  // Setup wizard — Step 1 (LLM provider)