elanous 0.2.22 → 0.2.24

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (803) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +32 -22
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_buildManifest.js +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  10. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  12. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  13. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  15. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  24. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  25. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  28. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  31. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  36. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  40. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  53. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  54. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  57. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  70. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  72. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  74. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  75. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  79. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  84. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  85. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  86. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  87. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  88. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  91. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  98. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  100. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  102. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  103. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  106. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  111. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  112. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  113. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  117. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  118. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  121. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  124. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  125. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/consult/{page-80ed511e02c81412.js → page-c0ab229673a8b0eb.js} +1 -1
  134. package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/design-check/page-26345242e4049f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b92caddb5c715f30.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  185. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +1 -0
  186. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  187. package/apps/pwa/out/approvals/index.html +1 -1
  188. package/apps/pwa/out/approvals/index.txt +23 -23
  189. package/apps/pwa/out/autopilot/index.html +1 -1
  190. package/apps/pwa/out/autopilot/index.txt +23 -23
  191. package/apps/pwa/out/board/index.html +1 -1
  192. package/apps/pwa/out/board/index.txt +23 -23
  193. package/apps/pwa/out/botlab/index.html +1 -1
  194. package/apps/pwa/out/botlab/index.txt +22 -22
  195. package/apps/pwa/out/bots/index.html +1 -1
  196. package/apps/pwa/out/bots/index.txt +22 -22
  197. package/apps/pwa/out/ceo/index.html +1 -1
  198. package/apps/pwa/out/ceo/index.txt +23 -23
  199. package/apps/pwa/out/chat/index.html +1 -1
  200. package/apps/pwa/out/chat/index.txt +22 -22
  201. package/apps/pwa/out/consult/index.html +1 -1
  202. package/apps/pwa/out/consult/index.txt +23 -23
  203. package/apps/pwa/out/control/index.html +1 -1
  204. package/apps/pwa/out/control/index.txt +23 -23
  205. package/apps/pwa/out/decisions/index.html +1 -1
  206. package/apps/pwa/out/decisions/index.txt +22 -22
  207. package/apps/pwa/out/design-check/index.html +1 -1
  208. package/apps/pwa/out/design-check/index.txt +23 -23
  209. package/apps/pwa/out/editor/index.html +1 -1
  210. package/apps/pwa/out/editor/index.txt +24 -23
  211. package/apps/pwa/out/exec/index.html +1 -1
  212. package/apps/pwa/out/exec/index.txt +23 -23
  213. package/apps/pwa/out/field/index.html +1 -1
  214. package/apps/pwa/out/field/index.txt +23 -23
  215. package/apps/pwa/out/healthz +1 -1
  216. package/apps/pwa/out/index.html +1 -1
  217. package/apps/pwa/out/index.txt +22 -22
  218. package/apps/pwa/out/inside/index.html +1 -1
  219. package/apps/pwa/out/inside/index.txt +22 -22
  220. package/apps/pwa/out/intake/index.html +1 -1
  221. package/apps/pwa/out/intake/index.txt +23 -23
  222. package/apps/pwa/out/live/index.html +1 -1
  223. package/apps/pwa/out/live/index.txt +23 -23
  224. package/apps/pwa/out/live-run/index.html +1 -1
  225. package/apps/pwa/out/live-run/index.txt +24 -23
  226. package/apps/pwa/out/loops/index.html +1 -1
  227. package/apps/pwa/out/loops/index.txt +22 -22
  228. package/apps/pwa/out/market/index.html +1 -1
  229. package/apps/pwa/out/market/index.txt +22 -22
  230. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  231. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  232. package/apps/pwa/out/morning/index.html +1 -1
  233. package/apps/pwa/out/morning/index.txt +23 -23
  234. package/apps/pwa/out/observatory/index.html +1 -1
  235. package/apps/pwa/out/observatory/index.txt +23 -23
  236. package/apps/pwa/out/ops/checklist/index.html +1 -1
  237. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  238. package/apps/pwa/out/ops/release/index.html +1 -1
  239. package/apps/pwa/out/ops/release/index.txt +22 -22
  240. package/apps/pwa/out/ops/seats/index.html +1 -1
  241. package/apps/pwa/out/ops/seats/index.txt +22 -22
  242. package/apps/pwa/out/outputs/index.html +1 -1
  243. package/apps/pwa/out/outputs/index.txt +22 -22
  244. package/apps/pwa/out/reflection/index.html +1 -1
  245. package/apps/pwa/out/reflection/index.txt +23 -23
  246. package/apps/pwa/out/scheduler/index.html +1 -1
  247. package/apps/pwa/out/scheduler/index.txt +23 -23
  248. package/apps/pwa/out/sessions/index.html +1 -1
  249. package/apps/pwa/out/sessions/index.txt +22 -22
  250. package/apps/pwa/out/settings/devices/index.html +1 -1
  251. package/apps/pwa/out/settings/devices/index.txt +23 -23
  252. package/apps/pwa/out/settings/index.html +1 -1
  253. package/apps/pwa/out/settings/index.txt +23 -23
  254. package/apps/pwa/out/setup/done/index.html +1 -1
  255. package/apps/pwa/out/setup/done/index.txt +23 -23
  256. package/apps/pwa/out/setup/index.html +1 -1
  257. package/apps/pwa/out/setup/index.txt +23 -23
  258. package/apps/pwa/out/share/index.html +1 -1
  259. package/apps/pwa/out/share/index.txt +23 -23
  260. package/apps/pwa/out/showroom/index.html +1 -1
  261. package/apps/pwa/out/showroom/index.txt +22 -22
  262. package/apps/pwa/out/tasks/index.html +1 -1
  263. package/apps/pwa/out/tasks/index.txt +23 -23
  264. package/apps/pwa/out/term/index.html +1 -1
  265. package/apps/pwa/out/term/index.txt +23 -23
  266. package/apps/pwa/out/today/index.html +1 -1
  267. package/apps/pwa/out/today/index.txt +23 -23
  268. package/apps/pwa/out/trace/index.html +1 -1
  269. package/apps/pwa/out/trace/index.txt +23 -23
  270. package/apps/pwa/out/vault/index.html +1 -1
  271. package/apps/pwa/out/vault/index.txt +23 -23
  272. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  273. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  274. package/apps/pwa/out/workflows/index.html +1 -1
  275. package/apps/pwa/out/workflows/index.txt +23 -23
  276. package/apps/pwa/out/workspace/index.html +1 -1
  277. package/apps/pwa/out/workspace/index.txt +23 -23
  278. package/apps/pwa/out/worktrees/index.html +1 -1
  279. package/apps/pwa/out/worktrees/index.txt +23 -23
  280. package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
  281. package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
  282. package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
  283. package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
  284. package/catalog/models/openai/gpt-6-astra.yaml +6 -0
  285. package/catalog/models/openai/gpt-6-luna.yaml +6 -0
  286. package/catalog/models/openai/gpt-6-sol.yaml +6 -0
  287. package/catalog/models/openrouter/deepseek-v4-pro-0813.yaml +39 -0
  288. package/catalog/models/openrouter/deepseek-v4.1-flash.yaml +38 -0
  289. package/catalog/models/openrouter/glm-5.3-flash.yaml +35 -0
  290. package/catalog/providers/openrouter.yaml +2 -0
  291. package/graphs/implement-loop.yaml +31 -0
  292. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  293. package/graphs/log-horizon/recipes.yaml +3 -0
  294. package/graphs/ops/harness-gc.yaml +17 -0
  295. package/graphs/ops/recipes.yaml +3 -0
  296. package/graphs/overlays/README.md +1 -1
  297. package/graphs/overlays/stop-heal-ladder.yaml +105 -0
  298. package/graphs/release/recipes.yaml +1 -1
  299. package/graphs/release/release-loop.yaml +6 -2
  300. package/graphs/release-rehearsal/recipes.yaml +12 -0
  301. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  302. package/package.json +4 -1
  303. package/scripts/add-api-key.sh +1 -1
  304. package/scripts/bench-report.ts +82 -3
  305. package/scripts/ci-typecheck-changed.ts +80 -14
  306. package/scripts/fleet/bedrock-pod-secret.ts +122 -0
  307. package/scripts/fleet/node-setup-linux.sh +97 -0
  308. package/scripts/fleet/node-setup.sh +11 -0
  309. package/scripts/fleet/zai-pod-secret.ts +86 -0
  310. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  311. package/scripts/land-global-checks.ts +3 -0
  312. package/scripts/lib/typecheck-ratchet.ts +51 -0
  313. package/scripts/measure-log-diet-2.ts +213 -0
  314. package/scripts/measure-tsc-affected-roots.ts +289 -0
  315. package/scripts/openai-relay-server.ts +5 -1
  316. package/scripts/release-loop/docs-node.ts +258 -43
  317. package/scripts/release-loop/gate-executor.ts +28 -0
  318. package/scripts/release-loop/gate-method.ts +59 -0
  319. package/scripts/release-loop/gate-node.ts +335 -33
  320. package/scripts/release-loop/gate-wall.ts +208 -0
  321. package/scripts/release-loop/known-issues-node.ts +53 -8
  322. package/scripts/release-loop/publish-at.ts +14 -0
  323. package/scripts/release-loop/publish-node.ts +17 -2
  324. package/scripts/release-loop/resume-release.ts +40 -4
  325. package/scripts/release-loop/resume.ts +94 -0
  326. package/scripts/release-loop/shard-plan.ts +3 -11
  327. package/scripts/release-loop/tui-node-checks.ts +22 -0
  328. package/scripts/release-loop/unattended-release.ts +29 -7
  329. package/scripts/rhythm/daily.ts +51 -2
  330. package/scripts/rhythm/weekly.ts +3 -2
  331. package/scripts/tsc-baseline-cache.ts +147 -0
  332. package/scripts/tsc-main-safety-net.ts +189 -0
  333. package/scripts/usage-rollup.ts +64 -8
  334. package/src/acp/codex-plugins.ts +48 -6
  335. package/src/agent/monad-agent-turn.ts +67 -5
  336. package/src/agent/run-context.ts +20 -0
  337. package/src/agent/tool-profile.ts +28 -2
  338. package/src/agent-mission/acp-judge.ts +8 -2
  339. package/src/agent-mission/capabilities-cli.ts +16 -1
  340. package/src/agent-mission/driver.ts +19 -4
  341. package/src/agent-mission/pr-review-watch.ts +6 -2
  342. package/src/agent-mission/resource-ladder.ts +8 -3
  343. package/src/agent-mission/review-loop.ts +41 -7
  344. package/src/agent-substrate/acp-implementer.ts +139 -0
  345. package/src/agent-substrate/acp-reviewer.ts +17 -8
  346. package/src/agent-substrate/pr-reviewer.ts +191 -28
  347. package/src/agent-substrate/review-intent.ts +6 -4
  348. package/src/agent-substrate/self-review-cli.ts +155 -21
  349. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  350. package/src/ask-user-question/pending-questions.ts +8 -2
  351. package/src/autopilot/build/llm-conflict-merge.ts +216 -12
  352. package/src/autopilot/codebase-grounding.ts +44 -0
  353. package/src/autopilot/llm-control-brain.ts +13 -1
  354. package/src/autopilot/mission-codebase-gate.ts +8 -77
  355. package/src/autopilot/mission-critique.ts +18 -5
  356. package/src/autopilot/mission-feasibility-negotiate.ts +11 -10
  357. package/src/autopilot/mission-trace.ts +12 -1
  358. package/src/autopilot/pr-manager.ts +12 -3
  359. package/src/autopilot/system-lookback-run.ts +16 -10
  360. package/src/bench/bench.ts +183 -0
  361. package/src/boot/acp-server.ts +4 -7
  362. package/src/boot/acp-socket-path.ts +7 -0
  363. package/src/briefing/brief-items.ts +21 -13
  364. package/src/budget/fetchers/grok.ts +15 -5
  365. package/src/budget/llm-cost.ts +37 -5
  366. package/src/budget/types.ts +8 -2
  367. package/src/budget/unified-usage.ts +88 -6
  368. package/src/chat/index.ts +12 -3
  369. package/src/cli/agent-cli.ts +20 -0
  370. package/src/cli/bench-cli.ts +34 -0
  371. package/src/cli/brief-cli.ts +27 -21
  372. package/src/cli/cli-user-error.ts +9 -2
  373. package/src/cli/guardian-cli.ts +26 -1
  374. package/src/cli/image-cli.ts +101 -0
  375. package/src/cli/log-event-names.ts +7 -0
  376. package/src/cli/logs-cli.ts +1 -0
  377. package/src/cli/mcp-login.ts +111 -37
  378. package/src/cli/plugin-cli.ts +21 -1
  379. package/src/cli/pod-cli.ts +26 -0
  380. package/src/cli/pr-cli.ts +90 -5
  381. package/src/cli/pr-land-overlap-evidence.ts +279 -0
  382. package/src/cli/release-cli.ts +63 -12
  383. package/src/cli/rfc-status.ts +52 -2
  384. package/src/cli/self-update.ts +277 -10
  385. package/src/cli/skills-cli.ts +12 -3
  386. package/src/cli/tasks-cli.ts +241 -30
  387. package/src/cli/usage-cli.ts +91 -8
  388. package/src/context-bus/context-first.ts +51 -2
  389. package/src/context-bus/context-now-surfaces.ts +13 -2
  390. package/src/context-bus/long-term-memory.ts +3 -1
  391. package/src/context-bus/nightly-condense.ts +3 -2
  392. package/src/core-turn/run-goal-loop.ts +87 -2
  393. package/src/dashboard/ad-run-setup-bindings.ts +279 -0
  394. package/src/dashboard/chat-fold.ts +20 -0
  395. package/src/dashboard/first-screen-band.ts +151 -1
  396. package/src/dashboard/index.ts +45 -281
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
  398. package/src/dashboard/stale-install-check.ts +24 -2
  399. package/src/dashboard/turn-stream-formatter.ts +25 -0
  400. package/src/debug/log-diet.ts +190 -0
  401. package/src/debug/log.ts +70 -17
  402. package/src/display/coordinator.ts +25 -2
  403. package/src/domains/coo-admin-tool.ts +27 -0
  404. package/src/domains/cron-match.ts +1 -0
  405. package/src/domains/outbound-alert.ts +17 -6
  406. package/src/domains/release-tool.ts +158 -10
  407. package/src/domains/schedule-registry.ts +10 -7
  408. package/src/domains/schedule-runner.ts +1 -0
  409. package/src/elanous-config-dir.ts +2 -2
  410. package/src/elanous-daemon.ts +3 -3
  411. package/src/error-report/report.ts +21 -4
  412. package/src/execution-loop/launch-gate.ts +1 -1
  413. package/src/expression/i18n/messages.en.ts +5 -0
  414. package/src/expression/i18n/messages.ja.ts +5 -0
  415. package/src/expression/i18n/messages.ko.ts +5 -0
  416. package/src/expression/i18n/messages.zh.ts +5 -0
  417. package/src/expression/i18n/types.ts +8 -0
  418. package/src/github/pr-labels.ts +2 -0
  419. package/src/graph-runner/graph-cli.ts +42 -1
  420. package/src/graph-runner/runner.ts +218 -8
  421. package/src/grok/usage.ts +23 -2
  422. package/src/grounding/ref-index.ts +253 -0
  423. package/src/harness/dispatch-backpressure.ts +267 -0
  424. package/src/harness/harness-clean.ts +199 -78
  425. package/src/harness/harness-cli-command.ts +229 -35
  426. package/src/harness/harness-gc.ts +331 -0
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-stop.ts +4 -2
  429. package/src/harness/harness-substrate-default.ts +214 -8
  430. package/src/harness/launch-registry.ts +6 -0
  431. package/src/harness/nested-elanous-policy.ts +4 -2
  432. package/src/harness/worktree-branch-prefix.ts +9 -0
  433. package/src/hq/fence-wrapper.ts +7 -0
  434. package/src/hq/fence.ts +187 -0
  435. package/src/hq/hq.ts +33 -2
  436. package/src/hq/lease.ts +13 -0
  437. package/src/hq/seats.ts +133 -21
  438. package/src/images/image-ledger.ts +179 -0
  439. package/src/index.ts +250 -69
  440. package/src/instance/child-scope.ts +32 -1
  441. package/src/instance/dev-project.ts +133 -0
  442. package/src/instance/resolve.ts +24 -0
  443. package/src/instance/spawn-elanous.ts +45 -0
  444. package/src/intake-plane/collect-github.ts +19 -1
  445. package/src/intake-plane/digest.ts +45 -20
  446. package/src/intake-plane/lens.ts +36 -8
  447. package/src/intake-plane/ref-prefetch.ts +110 -0
  448. package/src/intelligence-map/model-alias.ts +6 -0
  449. package/src/intelligence-map/model-catalog.ts +113 -0
  450. package/src/knowledge/kgs/pack.ts +5 -2
  451. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  452. package/src/knowledge/tools/knowledge-query.ts +20 -2
  453. package/src/knowledge/write.ts +234 -2
  454. package/src/llm/bedrock-eventstream.ts +215 -0
  455. package/src/llm/bedrock-provider.ts +248 -0
  456. package/src/llm/bedrock.ts +491 -0
  457. package/src/llm/openrouter-byok-cost.ts +96 -0
  458. package/src/llm/openrouter-deepseek.ts +151 -0
  459. package/src/llm/openrouter-upstream-pins.config.ts +25 -0
  460. package/src/llm/provider-credentials.ts +3 -1
  461. package/src/llm/zai-coding-plan.ts +700 -0
  462. package/src/llm.ts +383 -41
  463. package/src/loops/budget.ts +150 -0
  464. package/src/loops/checker.ts +148 -9
  465. package/src/loops/orchestrator/resync-shadow.ts +34 -7
  466. package/src/loops/orchestrator/seat-share.ts +6 -49
  467. package/src/loops/orchestrator/traffic.ts +5 -81
  468. package/src/market/signed-index.ts +42 -0
  469. package/src/maturity/feature-maturity.ts +2 -2
  470. package/src/mcp/mcp-oauth.ts +136 -17
  471. package/src/model-tier/llm-tier-map.ts +52 -4
  472. package/src/models/prompts.ts +23 -1
  473. package/src/mss/logging/horizon-watch.ts +168 -0
  474. package/src/mss/logging/log-store.ts +262 -26
  475. package/src/native-tool-catalog.ts +1 -1
  476. package/src/nexus/api/consult-requests.ts +7 -10
  477. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  478. package/src/nexus/api/error-reports.ts +30 -8
  479. package/src/nexus/api/http-server.ts +8 -0
  480. package/src/nexus/api/loop-resources.ts +42 -0
  481. package/src/nexus/api/missions.ts +73 -2
  482. package/src/nexus/api/ops-api.ts +18 -0
  483. package/src/nexus/api/outbound-report.ts +8 -3
  484. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  485. package/src/nexus/index.ts +17 -75
  486. package/src/nexus/outbound/format.ts +2 -0
  487. package/src/nexus/outbound/router.ts +198 -13
  488. package/src/nexus/tools-kind.ts +78 -0
  489. package/src/oauth/codex-account-rotation.ts +55 -20
  490. package/src/oauth/codex-account-store.ts +451 -23
  491. package/src/oauth/fallback-chain.ts +75 -15
  492. package/src/onboarding/first-run.ts +37 -18
  493. package/src/onboarding/web-first.ts +20 -2
  494. package/src/onboarding.ts +2 -1
  495. package/src/ops/machine-heartbeat.ts +185 -0
  496. package/src/ops/overview-cache.ts +175 -0
  497. package/src/ops/overview.ts +8 -0
  498. package/src/plugins/adapters/claude-package.ts +4 -12
  499. package/src/plugins/core/capability-policy.ts +141 -0
  500. package/src/plugins/core/host.ts +21 -8
  501. package/src/plugins/core/manifest.ts +19 -2
  502. package/src/plugins/core/trust-store.ts +15 -0
  503. package/src/plugins/core/types.ts +12 -0
  504. package/src/plugins/install/market-fetch.ts +68 -16
  505. package/src/plugins/install/plugin-install.ts +187 -16
  506. package/src/plugins/maker/plugin-maker.ts +25 -20
  507. package/src/plugins/maker/wizard-generate.ts +16 -2
  508. package/src/policy/llm-policy.ts +14 -1
  509. package/src/process/pid-liveness.ts +1 -1
  510. package/src/prompt-cache/openai.ts +13 -6
  511. package/src/prompt-cache/openrouter.ts +94 -0
  512. package/src/prompt-cache/types.ts +5 -0
  513. package/src/prompt-enhance/enhance.ts +69 -5
  514. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  515. package/src/prompt-library/universal-preamble.ts +2 -2
  516. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  517. package/src/registry/loader.ts +6 -1
  518. package/src/release-loop/checklist.ts +24 -9
  519. package/src/release-loop/feature-store.ts +3 -0
  520. package/src/release-loop/gate-shards.ts +48 -4
  521. package/src/release-loop/landed-to-green.ts +81 -0
  522. package/src/release-loop/light-rc.ts +11 -1
  523. package/src/release-loop/merged-pr-checklist.ts +10 -0
  524. package/src/release-loop/placement.ts +107 -23
  525. package/src/release-loop/rehearsal.ts +317 -0
  526. package/src/release-loop/release-schedule.ts +13 -1
  527. package/src/release-loop/rubric-types.ts +1 -0
  528. package/src/release-loop/rubric.ts +2 -2
  529. package/src/requirements/requirement-ledger.ts +536 -0
  530. package/src/retro/daily.ts +26 -12
  531. package/src/seat-loop/seat-loop.ts +66 -11
  532. package/src/seat-loop/traffic-signal.ts +44 -0
  533. package/src/self-dev/ask-launch-flow.ts +2 -2
  534. package/src/self-dev/dev-cli.ts +109 -11
  535. package/src/self-dev/dev-pipeline.ts +11 -8
  536. package/src/self-dev/draft-residue.ts +475 -0
  537. package/src/self-dev/draft-sweep.ts +254 -10
  538. package/src/self-dev/draft-triage-rules.ts +27 -1
  539. package/src/self-dev/graph-journey-route.ts +6 -0
  540. package/src/self-dev/launch-preflight-text.ts +549 -0
  541. package/src/self-dev/launch-preflight.ts +10 -545
  542. package/src/self-dev/orchestrate-cli.ts +82 -5
  543. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  544. package/src/self-dev/orchestrate.ts +49 -141
  545. package/src/self-dev/review-provider-fallback.ts +115 -19
  546. package/src/self-dev/run-store.ts +1 -3
  547. package/src/self-dev/run-supervisor.ts +190 -36
  548. package/src/self-dev/run-types.ts +191 -0
  549. package/src/self-dev/shard-aggregate.ts +61 -13
  550. package/src/self-dev/shard-plan.ts +5 -1
  551. package/src/self-dev/shard-run.ts +23 -5
  552. package/src/self-dev/supervisor-verdict-edges.ts +3 -4
  553. package/src/self-implement/blocked-draft-policy.ts +3 -19
  554. package/src/self-implement/budget-gate.ts +53 -13
  555. package/src/self-implement/child-context-composition.ts +139 -0
  556. package/src/self-implement/child-llm-preference.ts +13 -5
  557. package/src/self-implement/claude-acp-implement.ts +67 -0
  558. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  559. package/src/self-implement/flex-signals.ts +59 -0
  560. package/src/self-implement/follow-up-goals.ts +114 -38
  561. package/src/self-implement/frozen-merges.ts +8 -3
  562. package/src/self-implement/gate-baseline-reap.ts +157 -0
  563. package/src/self-implement/gate-baseline.ts +78 -16
  564. package/src/self-implement/gate-cli.ts +12 -2
  565. package/src/self-implement/gate-remote.ts +17 -6
  566. package/src/self-implement/goal-author-decompose.ts +10 -2
  567. package/src/self-implement/goal-author.ts +48 -13
  568. package/src/self-implement/goal-digest.ts +19 -0
  569. package/src/self-implement/graph-overlay-condition.ts +32 -0
  570. package/src/self-implement/graph-overlay-yaml.ts +41 -7
  571. package/src/self-implement/graph-templates.ts +33 -1
  572. package/src/self-implement/graph-yaml.ts +56 -0
  573. package/src/self-implement/headless-elanous-driver.ts +11 -9
  574. package/src/self-implement/heal-intake.ts +5 -1
  575. package/src/self-implement/host-regate.ts +120 -29
  576. package/src/self-implement/l8-merge-queue.ts +67 -5
  577. package/src/self-implement/merge-train.ts +131 -0
  578. package/src/self-implement/off-diff-evidence.ts +9 -0
  579. package/src/self-implement/orchestrator.ts +271 -25
  580. package/src/self-implement/review-finding-recurrence.ts +28 -0
  581. package/src/self-implement/rework-policy.ts +2 -1
  582. package/src/self-implement/round-summary-card.ts +63 -0
  583. package/src/self-implement/run-ledger.ts +4 -3
  584. package/src/self-implement/run-step-projection.ts +147 -0
  585. package/src/self-implement/run-stop.ts +1 -1
  586. package/src/self-implement/running-runs.ts +75 -5
  587. package/src/self-implement/seams.ts +83 -4
  588. package/src/self-implement/self-implement-cli.ts +12 -5
  589. package/src/self-implement/stop-autoheal.ts +69 -2
  590. package/src/self-implement/train-gate-remote.ts +158 -0
  591. package/src/session-runtime/index.ts +10 -1
  592. package/src/session-runtime/retry-api.ts +11 -1
  593. package/src/session-runtime/retry-policy.ts +2 -1
  594. package/src/skills/gift-install.ts +119 -0
  595. package/src/skills/runner.ts +59 -2
  596. package/src/skills/skill-feedback.ts +31 -1
  597. package/src/skills/skill-tier.ts +1 -0
  598. package/src/smart-wizard/capability-index.ts +231 -0
  599. package/src/smart-wizard/rung.ts +74 -0
  600. package/src/steward/launch.ts +22 -10
  601. package/src/steward/triage-budget.ts +62 -0
  602. package/src/steward/triage.ts +87 -24
  603. package/src/storage/file-lock.ts +8 -1
  604. package/src/task-agent/actions.ts +66 -5
  605. package/src/task-agent/card-evidence.ts +59 -13
  606. package/src/task-agent/completion-evidence.ts +5 -0
  607. package/src/task-agent/cover.ts +101 -3
  608. package/src/task-agent/judge.ts +20 -3
  609. package/src/task-agent/land-order-ledger.ts +95 -0
  610. package/src/task-agent/land-worktree.ts +201 -0
  611. package/src/task-agent/live-move-history.ts +219 -0
  612. package/src/task-agent/live-moves.ts +451 -34
  613. package/src/task-agent/parent-host.ts +117 -8
  614. package/src/task-agent/rejudge-on-head.ts +352 -0
  615. package/src/task-agent/review-prior-fix.ts +146 -0
  616. package/src/task-agent/review-result-capture.ts +218 -0
  617. package/src/task-agent/run-adopt.ts +136 -0
  618. package/src/task-agent/shadow.ts +154 -14
  619. package/src/task-agent/task-hand.ts +186 -14
  620. package/src/task-orchestrator/surfaces/pod-account-broker.ts +38 -5
  621. package/src/task-orchestrator/surfaces/pod-bedrock-child.ts +74 -0
  622. package/src/task-orchestrator/surfaces/pod-child-default.ts +50 -0
  623. package/src/task-orchestrator/surfaces/pod-child-providers.ts +42 -0
  624. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  625. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +94 -7
  626. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  627. package/src/task-orchestrator/surfaces/pod-lease.ts +110 -17
  628. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +32 -3
  629. package/src/task-orchestrator/surfaces/pod-pool.ts +86 -18
  630. package/src/task-orchestrator/surfaces/pod-zai-child.ts +101 -0
  631. package/src/task-orchestrator/surfaces/self-implement-pod.ts +463 -50
  632. package/src/task-orchestrator/surfaces/self-implement.ts +25 -3
  633. package/src/telegram-service.ts +5 -1
  634. package/src/telegram.ts +17 -4
  635. package/src/time/format.ts +13 -4
  636. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  637. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  638. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  639. package/src/typecheck-ratchet.ts +1 -0
  640. package/src/user-config.ts +180 -32
  641. package/src/ux-sim/slash-menu-frames.ts +168 -0
  642. package/src/version/packed-revision.json +1 -1
  643. package/src/web-terminal/preview-tap-registry.ts +5 -2
  644. package/src/workflow-runtime/triggers/registry.ts +59 -0
  645. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  646. package/src/workflow-runtime/triggers/webhook-source.ts +35 -5
  647. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  648. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  649. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  650. package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  652. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  653. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  654. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  656. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  661. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  670. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  671. package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  684. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  692. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  697. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  699. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  703. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  708. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  713. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  714. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  716. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  717. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  725. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  728. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  738. package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  741. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  745. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  746. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  802. package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
  803. /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → Q-7iofoxOEv1WX18S35of}/_ssgManifest.js +0 -0
@@ -17,7 +17,8 @@
17
17
  // severity 는 SCHEME(이벤트 접미사) → `level` 컬럼으로 물질화.
18
18
 
19
19
  import { Database } from 'bun:sqlite';
20
- import { mkdirSync } from 'node:fs';
20
+ import { existsSync, mkdirSync, readFileSync, readdirSync, renameSync, rmdirSync, rmSync, writeFileSync } from 'node:fs';
21
+ import { randomUUID } from 'node:crypto';
21
22
  import { elanousStateRoot } from '../../autopilot/state-paths.js';
22
23
  import { dirname, join } from 'node:path';
23
24
 
@@ -81,9 +82,13 @@ export interface LogStoreRetention {
81
82
  maxAgeDays: number;
82
83
  /** DB 상한(MB). 초과 시 오래된 행부터 삭제. 0 이하 = 크기 정리 안 함. 기본 500. */
83
84
  maxDbMb: number;
85
+ /** 🩸 LOGS-RETENTION-WINDOW-1(10-10): size-cap floor in hours — the size pass never deletes rows newer than
86
+ * this; when rows outside the floor are not enough it stops and logs `retention-floor-held`.
87
+ * 0 = legacy behaviour (oldest-first with no floor). Missing = 24. Age pass (`maxAgeDays`) is unaffected. */
88
+ minRetainHours?: number;
84
89
  }
85
90
 
86
- export const LOG_RETENTION_DEFAULTS: LogStoreRetention = { maxAgeDays: 7, maxDbMb: 500 };
91
+ export const LOG_RETENTION_DEFAULTS: LogStoreRetention = { maxAgeDays: 7, maxDbMb: 500, minRetainHours: 24 };
87
92
 
88
93
  /** 스토어 OOM 백스톱 — 정책 상한이 아니다. 정책은 각 경계(HTTP·툴)가 갖는다. */
89
94
  export const STORE_SAFETY_MAX = 100_000;
@@ -96,13 +101,27 @@ export const STORE_SAFETY_MAX = 100_000;
96
101
  export const LOG_STORE_READONLY_BUSY_TIMEOUT_MS = 2_000;
97
102
  const LOG_STORE_WRITE_BUSY_TIMEOUT_MS = 5_000;
98
103
  const LOG_STORE_OPEN_RETRY_DELAYS_MS = [100, 200, 400, 800, 1600] as const;
104
+ const LOG_STORE_BUSY_RETRY_MAX_ATTEMPTS = 3;
105
+ const LOG_STORE_BUSY_RETRY_BUFFER_MAX_ROWS = 2_000;
106
+ type LogStoreInsertRow = { rec: LogRecord; surface: string };
107
+ type LogStoreRetryBatch = { rows: LogStoreInsertRow[]; attempts: number; preserveRows: boolean };
99
108
  const sqliteOpenWait = new Int32Array(new SharedArrayBuffer(4));
100
109
  let pendingBusyOpenLosses: Array<{ path: string; loss: { store: 'logs'; op: 'open'; waitedMs: number } }> = [];
101
-
102
110
  function sqliteBusy(error: unknown): boolean {
103
111
  return /SQLITE_BUSY|SQLITE_LOCKED|database is locked|database is busy/i.test(String(error));
104
112
  }
105
113
 
114
+ function emitInsertBusyLost(data: Record<string, unknown>): void {
115
+ try { process.stderr.write(`[store.sqlite] busy-lost ${JSON.stringify(data)}\n`); } catch { /* diagnostics must not block callers */ }
116
+ try { debug.log('store.sqlite', 'busy-lost', data); } catch { /* diagnostics must not block callers */ }
117
+ }
118
+
119
+ function topCategories(rows: readonly LogStoreInsertRow[]): string[] {
120
+ const counts = new Map<string, number>();
121
+ for (const { rec } of rows) counts.set(rec.category, (counts.get(rec.category) ?? 0) + 1);
122
+ return [...counts].sort((a, b) => b[1] - a[1] || a[0].localeCompare(b[0])).slice(0, 3).map(([category]) => category);
123
+ }
124
+
106
125
  export class LogCursorNotFoundError extends Error {
107
126
  constructor(public readonly beforeId: number) {
108
127
  super(`page cursor row ${beforeId} not found in this store`);
@@ -191,6 +210,7 @@ export class LogStore {
191
210
  readonly instance: string;
192
211
  /** read-only open (LF7-b 연합 조회) — 스키마 생성/마이그레이션/insert 불가. */
193
212
  readonly readonly: boolean;
213
+ private busyRetryBuffer: LogStoreRetryBatch[] = [];
194
214
 
195
215
  /** 타 인스턴스 스토어의 연합 조회용 read-only open — "연합은 read-only 로만"
196
216
  * 불변식의 구조적 집행(마이그레이션 포함 어떤 write 도 발생 불가). */
@@ -291,10 +311,12 @@ export class LogStore {
291
311
  })();
292
312
  }
293
313
 
294
- /** 배치 insert(단일 트랜잭션). 실패는 throw — fail-soft 는 호출측(StoreSink)
295
- * 책임(ops-log 의 recordOpsEvent/Safe 분업 동형). */
314
+ /** 배치 insert(단일 트랜잭션). SQLITE_BUSY 는 bounded in-memory buffer 후 throw — fail-soft 는 호출측(StoreSink) 책임. */
296
315
  insertBatch(rows: Array<{ rec: LogRecord; surface: string }>, opts: { preserveRows?: boolean } = {}): void {
297
316
  if (rows.length === 0) return;
317
+ const retrying = this.busyRetryBuffer;
318
+ const current: LogStoreRetryBatch = { rows, attempts: 0, preserveRows: opts.preserveRows === true };
319
+ const batches = [...retrying, current];
298
320
  const stmt = this.db.prepare(
299
321
  `INSERT INTO logs (ts, ts_ms, level, instance, host_id, surface, category, event, session_id, trace_id, data)
300
322
  VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)`,
@@ -302,8 +324,8 @@ export class LogStore {
302
324
  const decisionRow = this.db.prepare(`SELECT id FROM logs WHERE instance = ? AND category = 'loop.steward' AND event = 'decision'
303
325
  AND json_valid(data) AND json_extract(data, '$.runId') = ? ORDER BY id DESC LIMIT 1`);
304
326
  const updateDecision = this.db.prepare(`UPDATE logs SET ts = ?, ts_ms = ?, level = ?, surface = ?, data = ? WHERE id = ?`);
305
- const insertAll = this.db.transaction((batch: Array<{ rec: LogRecord; surface: string }>) => {
306
- for (const { rec, surface } of batch) {
327
+ const insertAll = this.db.transaction((batch: Array<{ row: LogStoreInsertRow; preserveRows: boolean }>) => {
328
+ for (const { row: { rec, surface }, preserveRows } of batch) {
307
329
  const tsMs = Date.parse(rec.ts);
308
330
  const timestamp = Number.isFinite(tsMs) ? tsMs : Date.now();
309
331
  const level = deriveLogLevel(rec);
@@ -311,7 +333,7 @@ export class LogStore {
311
333
  const runId = rec.category === 'loop.steward' && rec.event === 'decision' &&
312
334
  rec.data && typeof rec.data === 'object' && !Array.isArray(rec.data)
313
335
  ? (rec.data as Record<string, unknown>).runId : undefined;
314
- const existing = !opts.preserveRows && typeof runId === 'string' && runId
336
+ const existing = !preserveRows && typeof runId === 'string' && runId
315
337
  ? decisionRow.get(this.instance, runId) as { id: number } | undefined : undefined;
316
338
  if (existing) {
317
339
  updateDecision.run(rec.ts, timestamp, level, surface, data, existing.id);
@@ -335,14 +357,43 @@ export class LogStore {
335
357
  );
336
358
  }
337
359
  });
360
+ const allRows = batches.flatMap((batch) => batch.rows.map((row) => ({ row, preserveRows: batch.preserveRows })));
338
361
  const startedAt = Date.now();
339
362
  try {
340
- insertAll(rows);
363
+ insertAll(allRows);
364
+ this.busyRetryBuffer = [];
365
+ for (const batch of retrying) {
366
+ try { debug.log('store.sqlite', 'busy-recovered', { rows: batch.rows.length, attempts: batch.attempts + 1 }); }
367
+ catch { /* diagnostics must not affect writes */ }
368
+ }
341
369
  } catch (error) {
342
- if (sqliteBusy(error)) {
343
- const loss = { store: 'logs', op: 'insertBatch', waitedMs: Date.now() - startedAt };
344
- try { process.stderr.write(`[store.sqlite] busy-lost ${JSON.stringify(loss)}\n`); } catch { /* diagnostics must not block callers */ }
345
- debug.log('store.sqlite', 'busy-lost', loss);
370
+ if (!sqliteBusy(error)) throw error;
371
+ emitInsertBusyLost({
372
+ store: 'logs', op: 'insertBatch', waitedMs: Date.now() - startedAt,
373
+ rows: allRows.length, categories: topCategories(allRows.map(({ row }) => row)),
374
+ });
375
+ const retained: LogStoreRetryBatch[] = [];
376
+ for (const batch of batches) {
377
+ const attempts = batch.attempts + 1;
378
+ if (attempts >= LOG_STORE_BUSY_RETRY_MAX_ATTEMPTS) {
379
+ emitInsertBusyLost({ store: 'logs', op: 'insertBatch', reason: 'retry-exhausted', droppedRows: batch.rows.length });
380
+ } else {
381
+ retained.push({ ...batch, attempts });
382
+ }
383
+ }
384
+ let bufferedRows = retained.reduce((count, batch) => count + batch.rows.length, 0);
385
+ let droppedRows = 0;
386
+ while (bufferedRows > LOG_STORE_BUSY_RETRY_BUFFER_MAX_ROWS && retained.length > 0) {
387
+ const oldest = retained[0]!;
388
+ const drop = Math.min(bufferedRows - LOG_STORE_BUSY_RETRY_BUFFER_MAX_ROWS, oldest.rows.length);
389
+ oldest.rows.splice(0, drop);
390
+ bufferedRows -= drop;
391
+ droppedRows += drop;
392
+ if (oldest.rows.length === 0) retained.shift();
393
+ }
394
+ this.busyRetryBuffer = retained;
395
+ if (droppedRows > 0) {
396
+ emitInsertBusyLost({ store: 'logs', op: 'insertBatch', reason: 'retry-buffer-full', droppedRows });
346
397
  }
347
398
  throw error;
348
399
  }
@@ -360,22 +411,65 @@ export class LogStore {
360
411
  }
361
412
  if (policy.maxDbMb > 0) {
362
413
  const pageCount = (this.db.query('PRAGMA page_count').get() as { page_count: number }).page_count;
414
+ const freePages = (this.db.query('PRAGMA freelist_count').get() as { freelist_count: number }).freelist_count;
363
415
  const pageSize = (this.db.query('PRAGMA page_size').get() as { page_size: number }).page_size;
364
- const sizeMb = (pageCount * pageSize) / (1024 * 1024);
416
+ // 🩸 OBS-RET-RATCHET(2026-10-09): 빈 페이지까지 세면 VACUUM 없는 파일은 안 줄어든다 → 뜰 때마다 오래된 행 ≈5% 를
417
+ // 또 지우는 래칫이 됐다(운영 logs.db 528MB · 01:08Z 이전 행 소실). 상한은 «쓰는 페이지»로 잰다.
418
+ const sizeMb = ((pageCount - freePages) * pageSize) / (1024 * 1024);
365
419
  if (sizeMb > policy.maxDbMb) {
366
420
  // 초과분 비율만큼 오래된 행 삭제(대략 — 정밀 계산보다 반복 수렴 선호).
367
421
  const total = (this.db.query('SELECT COUNT(*) AS c FROM logs').get() as { c: number }).c;
368
422
  const dropCount = Math.max(1, Math.floor(total * Math.min(0.5, 1 - policy.maxDbMb / sizeMb)));
369
- const r = this.db.run(
370
- 'DELETE FROM logs WHERE id IN (SELECT id FROM logs ORDER BY ts_ms ASC LIMIT ?)',
371
- [dropCount],
372
- );
373
- deletedBySize = Number(r.changes ?? 0);
423
+ // 🩸 LOGS-RETENTION-WINDOW-1(10-10): prod write volume made this pass keep only ≈2h of rows, so evidence
424
+ // for incidents a few hours old read as «0 rows». Rows inside the floor are never size-deleted.
425
+ const floorHours = policy.minRetainHours ?? LOG_RETENTION_DEFAULTS.minRetainHours ?? 0;
426
+ if (floorHours > 0) {
427
+ const floorCutoff = Date.now() - floorHours * 3_600_000;
428
+ // Byte-weighted split (payload text + fixed per-row overhead) — row counts alone misjudge mixed row sizes.
429
+ const split = this.db.query(
430
+ `SELECT COALESCE(SUM(CASE WHEN ts_ms < ? THEN w ELSE 0 END), 0) AS outsideBytes, COALESCE(SUM(w), 0) AS allBytes
431
+ FROM (SELECT ts_ms, 64 + LENGTH(ts) + LENGTH(category) + LENGTH(event) + COALESCE(LENGTH(data), 0) AS w FROM logs)`,
432
+ ).get(floorCutoff) as { outsideBytes: number; allBytes: number };
433
+ const r = this.db.run(
434
+ 'DELETE FROM logs WHERE id IN (SELECT id FROM logs WHERE ts_ms < ? ORDER BY ts_ms ASC LIMIT ?)',
435
+ [floorCutoff, dropCount],
436
+ );
437
+ deletedBySize = Number(r.changes ?? 0);
438
+ // dropCount is capped at 50% per run; judge the floor against the full overshoot (by bytes) so a cap the
439
+ // floor can never reach is reported even when this run's capped batch was fully served from outside rows.
440
+ const neededShare = 1 - policy.maxDbMb / sizeMb;
441
+ const outsideShare = split.allBytes > 0 ? split.outsideBytes / split.allBytes : 0;
442
+ if (outsideShare < neededShare) {
443
+ debug.log('mss.logging', 'retention-floor-held', {
444
+ totalMb: Math.round(sizeMb * 10) / 10, maxTotalMb: policy.maxDbMb, floorHours,
445
+ neededShare: Math.round(neededShare * 1000) / 1000, outsideShare: Math.round(outsideShare * 1000) / 1000,
446
+ deletedRows: deletedBySize,
447
+ });
448
+ }
449
+ } else {
450
+ const r = this.db.run(
451
+ 'DELETE FROM logs WHERE id IN (SELECT id FROM logs ORDER BY ts_ms ASC LIMIT ?)',
452
+ [dropCount],
453
+ );
454
+ deletedBySize = Number(r.changes ?? 0);
455
+ }
374
456
  }
375
457
  }
458
+ if (deletedByAge > 0 || deletedBySize > 0) {
459
+ const oldest = (this.db.query('SELECT MIN(ts_ms) AS t FROM logs').get() as { t: number | null }).t;
460
+ debug.log('log-store.retention', 'deleted', { deletedByAge, deletedBySize, oldestTs: oldest === null ? null : new Date(oldest).toISOString() });
461
+ }
376
462
  return { deletedByAge, deletedBySize };
377
463
  }
378
464
 
465
+ /** Reclaim a bounded number of free pages after retention; legacy databases with auto_vacuum=NONE remain unchanged. */
466
+ reclaimFreePages(): void {
467
+ const mode = (this.db.query('PRAGMA auto_vacuum').get() as { auto_vacuum: number }).auto_vacuum;
468
+ if (mode !== 2) return;
469
+ const free = (this.db.query('PRAGMA freelist_count').get() as { freelist_count: number }).freelist_count;
470
+ if (free > 0) this.db.run(`PRAGMA incremental_vacuum(${Math.min(free, 128)})`);
471
+ }
472
+
379
473
  /**
380
474
  * ⛔⭐⭐⭐ **이 스토어에 «실제로 뜬» 카테고리와 그 수**(2026-08-19 · `OBS-T122`).
381
475
  *
@@ -658,6 +752,12 @@ export class LogStore {
658
752
  return (this.db.query('SELECT COUNT(*) AS c FROM logs').get() as { c: number }).c;
659
753
  }
660
754
 
755
+ /** Earliest retained event timestamp, regardless of insertion order. No schema or row writes. */
756
+ horizon(): { status: 'present'; oldestTsMs: number } | { status: 'empty' } {
757
+ const { oldestTsMs } = this.db.query('SELECT MIN(ts_ms) AS oldestTsMs FROM logs').get() as { oldestTsMs: number | null };
758
+ return oldestTsMs === null ? { status: 'empty' } : { status: 'present', oldestTsMs };
759
+ }
760
+
661
761
  close(): void {
662
762
  try { this.db.close(); } catch { /* noop */ }
663
763
  }
@@ -781,6 +881,7 @@ export class StoreSink implements LogSink {
781
881
  const batch = this.buf;
782
882
  this.buf = [];
783
883
  try {
884
+ // insertBatch retries SQLITE_BUSY batches on the next write; this sink remains fail-soft on final failure.
784
885
  this.store.insertBatch(batch);
785
886
  } catch {
786
887
  /* fail-soft — 파일 트레일이 진실원. 배치는 버린다(재시도 루프 금지 —
@@ -850,28 +951,163 @@ export class StoreSink implements LogSink {
850
951
  }
851
952
  }
852
953
 
954
+ const RETENTION_INTERVAL_MS = 6 * 3600 * 1000;
955
+ type RetentionLockOwner = { token: string; pid: number; start: string | null };
956
+
957
+ /** PID reuse must not let a new process inherit a dead process's ownership. */
958
+ function processStart(pid: number): string | null {
959
+ try {
960
+ const stat = readFileSync(`/proc/${pid}/stat`, 'utf8');
961
+ return stat.slice(stat.lastIndexOf(')') + 2).split(' ')[19] ?? null;
962
+ } catch { return null; }
963
+ }
964
+
965
+ function ownerDead(owner: RetentionLockOwner): boolean {
966
+ if (!Number.isSafeInteger(owner.pid) || owner.pid <= 0) return false;
967
+ try {
968
+ process.kill(owner.pid, 0);
969
+ const currentStart = processStart(owner.pid);
970
+ if (owner.start !== null && currentStart !== null && owner.start !== currentStart) return true;
971
+ // A zombie still answers kill(pid, 0), but can no longer run retention.
972
+ try {
973
+ const stat = readFileSync(`/proc/${owner.pid}/stat`, 'utf8');
974
+ return stat.slice(stat.lastIndexOf(')') + 2).startsWith('Z ');
975
+ } catch { return false; }
976
+ } catch (error) {
977
+ return (error as NodeJS.ErrnoException).code === 'ESRCH';
978
+ }
979
+ }
980
+
981
+ /** Only the guard row can authorize removal. A pre-publication temp file belongs to its row's token. */
982
+ function removeRetentionLockDirectory(lockPath: string, token: string, interrupted: boolean): void {
983
+ if (!existsSync(lockPath)) return;
984
+ const marker = join(lockPath, 'owner');
985
+ const temporaryName = `owner.${token}.tmp`;
986
+ if (readdirSync(lockPath).some((name) => name !== 'owner' && name !== temporaryName)) {
987
+ throw new Error('retention lock has unknown entries');
988
+ }
989
+ if (existsSync(marker)) {
990
+ const published = readFileSync(marker, 'utf8');
991
+ if (published !== token && !(interrupted && token.startsWith(published))) {
992
+ throw new Error('retention lock owner changed');
993
+ }
994
+ rmSync(marker);
995
+ }
996
+ rmSync(join(lockPath, temporaryName), { force: true });
997
+ rmdirSync(lockPath);
998
+ }
999
+
1000
+ /** The SQLite guard serializes stale-lock recovery and ownership changes, including process death mid-acquisition. */
1001
+ function acquireRetentionLock(lockPath: string): (() => void) | null {
1002
+ const guard = new Database(`${lockPath}.db`);
1003
+ const token = randomUUID();
1004
+ let handedOff = false;
1005
+ try {
1006
+ guard.run('PRAGMA busy_timeout = 100');
1007
+ guard.run('CREATE TABLE IF NOT EXISTS owner (slot INTEGER PRIMARY KEY CHECK(slot = 1), token TEXT NOT NULL, pid INTEGER NOT NULL, start TEXT)');
1008
+ let acquired = false;
1009
+ guard.run('BEGIN IMMEDIATE');
1010
+ try {
1011
+ const previous = guard.query('SELECT token, pid, start FROM owner WHERE slot = 1').get() as RetentionLockOwner | null;
1012
+ if (previous && !ownerDead(previous)) return null;
1013
+ if (existsSync(lockPath)) {
1014
+ // A pre-guard lock has no provable owner: never remove it.
1015
+ if (!previous) return null;
1016
+ try { removeRetentionLockDirectory(lockPath, previous.token, true); }
1017
+ catch { return null; }
1018
+ }
1019
+ guard.run('INSERT OR REPLACE INTO owner (slot, token, pid, start) VALUES (1, ?, ?, ?)', [token, process.pid, processStart(process.pid)]);
1020
+ guard.run('COMMIT');
1021
+ acquired = true;
1022
+ } finally {
1023
+ if (!acquired) guard.run('ROLLBACK');
1024
+ }
1025
+ // The ownership row is committed before mkdir: a crash in this gap is recoverable too.
1026
+ try {
1027
+ mkdirSync(lockPath);
1028
+ const temporary = join(lockPath, `owner.${token}.tmp`);
1029
+ writeFileSync(temporary, token, { flag: 'wx' });
1030
+ renameSync(temporary, join(lockPath, 'owner'));
1031
+ } catch (error) {
1032
+ guard.run('BEGIN IMMEDIATE');
1033
+ try {
1034
+ // Keep the ownership row if cleanup fails: the next process can then
1035
+ // prove who left the directory behind and recover it after this PID dies.
1036
+ removeRetentionLockDirectory(lockPath, token, true);
1037
+ guard.run('DELETE FROM owner WHERE slot = 1 AND token = ?', [token]);
1038
+ guard.run('COMMIT');
1039
+ } catch { guard.run('ROLLBACK'); }
1040
+ throw error;
1041
+ }
1042
+ handedOff = true;
1043
+ return () => {
1044
+ try {
1045
+ guard.run('BEGIN IMMEDIATE');
1046
+ try {
1047
+ const current = guard.query('SELECT token FROM owner WHERE slot = 1').get() as { token: string } | null;
1048
+ if (current?.token === token) {
1049
+ removeRetentionLockDirectory(lockPath, token, false);
1050
+ guard.run('DELETE FROM owner WHERE slot = 1 AND token = ?', [token]);
1051
+ }
1052
+ guard.run('COMMIT');
1053
+ } catch (error) { guard.run('ROLLBACK'); throw error; }
1054
+ } finally { guard.close(); }
1055
+ };
1056
+ } finally { if (!handedOff) guard.close(); }
1057
+ }
1058
+
1059
+ /** A shared stamp prevents short-lived non-owner processes from repeatedly pruning the same DB. */
1060
+ function runStampedRetention(store: LogStore, retention: LogStoreRetention, owner: boolean): void {
1061
+ const stampPath = `${store.path}.retention.stamp`;
1062
+ const lockPath = `${store.path}.retention.lock`;
1063
+ const isFresh = (): boolean => {
1064
+ try {
1065
+ const age = Date.now() - Number(readFileSync(stampPath, 'utf8'));
1066
+ return age >= 0 && age < RETENTION_INTERVAL_MS;
1067
+ } catch { return false; }
1068
+ };
1069
+ if (!owner && isFresh()) return;
1070
+ const release = acquireRetentionLock(lockPath);
1071
+ if (!release) return;
1072
+ try {
1073
+ if (!owner && isFresh()) return;
1074
+ store.enforceRetention(retention);
1075
+ try { store.reclaimFreePages(); }
1076
+ catch (error) { debug.log('log-store.retention', 'reclaim-failed', { reason: error instanceof Error ? error.message : String(error) }); }
1077
+ const temporary = `${stampPath}.${process.pid}.${randomUUID()}.tmp`;
1078
+ try {
1079
+ writeFileSync(temporary, String(Date.now()));
1080
+ renameSync(temporary, stampPath);
1081
+ } finally { rmSync(temporary, { force: true }); }
1082
+ } finally { release(); }
1083
+ }
1084
+
853
1085
  /** 부팅 1줄 등록 헬퍼 — 데몬/TUI/러너가 자기 surface 를 선언하고 스토어
854
1086
  * 싱크를 단다. retention 은 호출측이 config 에서 읽어 전달(user-config
855
- * 순환 의존 회피). 반환 = unregister(테스트용) 또는 null(store 불가). */
1087
+ * 순환 의존 회피). 반환 = unregister(테스트용) 또는 null(store 불가).
1088
+ * nexus owns the periodic job unless the caller explicitly opts in. */
856
1089
  export function registerLogStoreSink(
857
1090
  registerSink: (sink: LogSink) => () => void,
858
1091
  surface: string,
859
1092
  retention: LogStoreRetention = LOG_RETENTION_DEFAULTS,
1093
+ opts: { retentionOwner?: boolean } = {},
860
1094
  ): (() => void) | null {
861
1095
  const store = getDefaultLogStore();
862
1096
  if (!store) return null;
863
1097
  const sink = new StoreSink(store, surface, { installExitHandlers: true });
864
1098
  const off = registerSink(sink);
865
1099
  try { nestDepth.observeNestAtBoot(); } catch { /* fail-soft — 관측 실패가 싱크 등록을 막지 않는다. */ }
866
- // 보존정책 — 부팅 직후 1회(디퍼) + 6시간 주기. 실패는 조용히.
1100
+ const owner = opts.retentionOwner ?? surface === 'nexus';
867
1101
  const runRetention = (): void => {
868
- try { store.enforceRetention(retention); } catch { /* fail-soft */ }
1102
+ try { runStampedRetention(store, retention, owner); }
1103
+ catch (error) { debug.log('log-store.retention', 'failed', { reason: error instanceof Error ? error.message : String(error) }); }
869
1104
  };
870
- setImmediate(runRetention);
871
- const h = setInterval(runRetention, 6 * 3600 * 1000);
872
- (h as unknown as { unref?: () => void }).unref?.();
1105
+ const startup = setImmediate(runRetention);
1106
+ const h = owner ? setInterval(runRetention, RETENTION_INTERVAL_MS) : null;
1107
+ (h as unknown as { unref?: () => void } | null)?.unref?.();
873
1108
  return () => {
874
- clearInterval(h);
1109
+ clearImmediate(startup);
1110
+ if (h) clearInterval(h);
875
1111
  sink.close();
876
1112
  off();
877
1113
  };
@@ -9,7 +9,7 @@ import type { VerifierSpec } from './verifier/types.js';
9
9
  import type { GuardianSpec } from './guardian/types.js';
10
10
  import { ptyAvailable } from './pty-shell/registry.js';
11
11
  import { krFlowAvailable } from './skills/tools/kr-flow.js';
12
- import { SELF_COGNITION_MCP_CATALOG_ENTRIES } from './tool-runtime/self-cognition-runtimes.js';
12
+ import { SELF_COGNITION_MCP_CATALOG_ENTRIES } from './tool-runtime/self-cognition-catalog.js';
13
13
  import { SKILLS_LIST_DESCRIPTION } from './onboarding/entry-hints.js';
14
14
 
15
15
  export type { NativeToolHost } from './tool-surface.js';
@@ -2,7 +2,7 @@ import { closeSync, existsSync, fsyncSync, mkdirSync, openSync, readFileSync, re
2
2
  import { randomUUID } from 'node:crypto';
3
3
  import { dirname, join } from 'node:path';
4
4
  import { debug } from '../../debug/log.js';
5
- import { routeOutbound } from '../outbound/router.js';
5
+ import { sendTelegramReport } from '../../telegram-report.js';
6
6
  import { getUserConfig } from '../../user-config.js';
7
7
  import { effectiveInstanceRoot } from '../../instance/resolve.js';
8
8
  import { jsonResponse } from './json-response.js';
@@ -23,7 +23,7 @@ interface ConsultRequest {
23
23
  export interface ConsultRequestsDeps {
24
24
  root?: () => string;
25
25
  now?: () => string;
26
- /** Owner alert. Default = the daemon's own in-process router (the same one `/v1/outbound` uses).
26
+ /** Owner alert. Default = the daemon's in-process Telegram sender (operations role only).
27
27
  * ⛔ Never `sendOutbound` here: it is a synchronous curl to this very daemon's `/v1/outbound`, so inside the
28
28
  * daemon it blocks the event loop until it times out (~25 s · `unreachable`) and the alert is lost (CS1 · 10-01). */
29
29
  send?: (text: string, kind: string) => unknown;
@@ -88,9 +88,9 @@ export async function handleConsultRequests(req: Request, deps: ConsultRequestsD
88
88
  if (!body || typeof body !== 'object' || Array.isArray(body)) return rejected('body');
89
89
  const input = body as Record<string, unknown>;
90
90
  for (const field of ['name', 'contact'] as const) {
91
- if (typeof input[field] !== 'string' || !input[field].trim()) return rejected(field);
91
+ if (typeof input[field] !== 'string' || !input[field].trim() || input[field].length > (field === 'name' ? 256 : 512)) return rejected(field);
92
92
  }
93
- if (input.org !== undefined && (typeof input.org !== 'string' || !input.org.trim())) return rejected('org');
93
+ if (input.org !== undefined && (typeof input.org !== 'string' || !input.org.trim() || input.org.length > 256)) return rejected('org');
94
94
  if (input.kind !== 'company' && input.kind !== 'personal') return rejected('kind');
95
95
  if (input.interest !== 'A' && input.interest !== 'B') return rejected('interest');
96
96
  if (input.consent !== true) return rejected('consent');
@@ -114,15 +114,12 @@ export async function handleConsultRequests(req: Request, deps: ConsultRequestsD
114
114
  const alert = `📮 상담 문의 ${entry.receiptId} · ${entry.name}(${entry.kind === 'personal' ? '개인' : (entry.org ?? '회사')}) · 관심 ${entry.interest}\n앱에서 보기`;
115
115
  // Fire and forget — the receipt is already on disk; the answer must not wait for the channel.
116
116
  void Promise.resolve()
117
- .then(() => (deps.send ?? notifyInProcess)(alert, 'alert'))
117
+ .then(() => (deps.send ?? notifyInProcess)(alert, 'ops-alert'))
118
118
  .catch((error: unknown) => { debug.log('consult.request', 'notify-failed', { receiptId: entry.receiptId, reason: error instanceof Error ? error.message : String(error) }); });
119
119
  return jsonResponse({ receiptId: entry.receiptId, receivedAt: entry.receivedAt }, 202);
120
120
  }
121
121
 
122
122
  async function notifyInProcess(text: string, kind: string): Promise<void> {
123
- const result = await routeOutbound(getUserConfig(), { text, markdown: false, kind });
124
- debug.log('consult.request', result.delivered ? 'notified' : 'notify-failed', {
125
- delivered: result.delivered,
126
- channels: result.channels.map((channel) => `${channel.type}:${channel.ok ? 'ok' : 'fail'}`),
127
- });
123
+ const delivered = await sendTelegramReport(getUserConfig(), text, { markdown: false, kind });
124
+ debug.log('consult.request', delivered ? 'notified' : 'notify-failed', { delivered, channels: [`telegram:${delivered ? 'ok' : 'fail'}`] });
128
125
  }
@@ -36,6 +36,7 @@ import { parseDiscordEndpoint, isOwnInstanceEndpoint } from '../../session/sessi
36
36
  import { createDiscordStreamSink } from '../../session/streaming/discord-stream-sink.js';
37
37
  import { splitForDiscord } from '../../discord.js';
38
38
  import { formatForDiscord } from '../../discord-markdown.js';
39
+ import { receiveChannelEvent } from '../outbound/router.js';
39
40
 
40
41
  export interface NexusDiscordTriggerBotOpts {
41
42
  /** Bot token (without `Bot ` prefix). Production reads
@@ -109,11 +110,13 @@ export function createDiscordTriggerLogger(
109
110
  * (`src/discord.ts:160-172` comment) so the wire is a near-identity
110
111
  * with `raw` carrying the full gateway payload for debugging. */
111
112
  export function toDiscordEvent(tap: DcTriggerEvent): DiscordEvent {
113
+ const envelope = receiveChannelEvent('discord', tap);
114
+ if (!envelope || envelope instanceof Promise) throw new Error('discord connector cannot normalize accepted tap');
112
115
  return {
113
116
  kind: tap.kind,
114
- channel: tap.channel,
115
- user: tap.user,
116
- body: tap.body,
117
+ channel: envelope.channel ?? tap.channel,
118
+ user: envelope.senderId ?? tap.user,
119
+ body: envelope.text,
117
120
  raw: tap,
118
121
  };
119
122
  }
@@ -25,19 +25,21 @@ function storeDir(root: string): string { return join(root, 'error-reports'); }
25
25
  /** Removes day folders older than the keep window. Returns how many days were removed. */
26
26
  export function pruneErrorReports(root: string, now: number): number {
27
27
  const base = storeDir(root);
28
- if (!existsSync(base)) return 0;
29
28
  let removed = 0;
30
- for (const year of readdirSync(base).filter((n) => /^\d{4}$/.test(n))) {
31
- for (const month of readdirSync(join(base, year)).filter((n) => /^\d{2}$/.test(n))) {
32
- for (const day of readdirSync(join(base, year, month)).filter((n) => /^\d{2}$/.test(n))) {
33
- const at = Date.parse(`${year}-${month}-${day}T00:00:00Z`);
34
- if (Number.isFinite(at) && now - at > ERROR_REPORT_KEEP_DAYS * DAY_MS + DAY_MS) {
35
- rmSync(join(base, year, month, day), { recursive: true, force: true });
36
- removed++;
29
+ if (existsSync(base)) {
30
+ for (const year of readdirSync(base).filter((n) => /^\d{4}$/.test(n))) {
31
+ for (const month of readdirSync(join(base, year)).filter((n) => /^\d{2}$/.test(n))) {
32
+ for (const day of readdirSync(join(base, year, month)).filter((n) => /^\d{2}$/.test(n))) {
33
+ const at = Date.parse(`${year}-${month}-${day}T00:00:00Z`);
34
+ if (Number.isFinite(at) && now - at > ERROR_REPORT_KEEP_DAYS * DAY_MS + DAY_MS) {
35
+ rmSync(join(base, year, month, day), { recursive: true, force: true });
36
+ removed++;
37
+ }
37
38
  }
38
39
  }
39
40
  }
40
41
  }
42
+ debug.log('error-report.prune', 'done', { pruned: removed });
41
43
  return removed;
42
44
  }
43
45
 
@@ -77,6 +79,26 @@ function count24h(root: string, dedupe: string, now: number): number {
77
79
  return n;
78
80
  }
79
81
 
82
+ /** Retention without a receipt: prune once at daemon boot and then once a day (the ingest path still prunes too). */
83
+ export function startErrorReportPruneTick(deps: {
84
+ root?: () => string;
85
+ now?: () => number;
86
+ schedule?: (tick: () => void, ms: number) => { unref?: () => void };
87
+ } = {}): { stop(): void } {
88
+ const root = deps.root ?? effectiveInstanceRoot;
89
+ const now = deps.now ?? Date.now;
90
+ const run = (trigger: 'boot' | 'tick') => {
91
+ // pruneErrorReports emits error-report.prune/done { pruned }; only a failure is logged here.
92
+ try { pruneErrorReports(root(), now()); }
93
+ catch (error) { debug.log('error-report.prune', 'failed', { trigger, reason: error instanceof Error ? error.message : String(error) }); }
94
+ };
95
+ run('boot');
96
+ let stopped = false;
97
+ const handle = (deps.schedule ?? ((tick, ms) => setInterval(tick, ms)))(() => { if (!stopped) run('tick'); }, DAY_MS);
98
+ handle.unref?.();
99
+ return { stop: () => { stopped = true; if (!deps.schedule) clearInterval(handle as ReturnType<typeof setInterval>); } };
100
+ }
101
+
80
102
  /** POST /v1/reports/ingest — the caller (router) has already checked the ingest token. */
81
103
  export async function handleErrorReportIngest(req: Request, deps: ErrorReportIngestDeps = {}): Promise<Response> {
82
104
  const root = (deps.root ?? effectiveInstanceRoot)();
@@ -170,6 +170,7 @@ import { handleBuildsGet, parseBuildsPath } from './builds-api.js';
170
170
  import { handleHarnessAskPost, handleHarnessAskStatusGet, handleHarnessRunEventsGet, handleHarnessRunScreenGet, handleHarnessRunsGet, handleHarnessStopPost } from './harness-api.js';
171
171
  import { handleHarnessRunTraversalGet } from './harness-traversal.js';
172
172
  import { handleLoopEdgesGet } from './loop-edges.js';
173
+ import { handleLoopResourcesGet } from './loop-resources.js';
173
174
  import { handleFabricPlans, type FabricPlansRouteOpts } from './fabric-plans.js';
174
175
  import { dispatchPersonaRoute } from './personas.js';
175
176
  import { handleMe, operatorSignal } from './operator.js';
@@ -498,6 +499,8 @@ export interface NexusHttpServerOpts {
498
499
  outputs?: OutputsDeps;
499
500
  /** Read-only grid measurement seam; omitted in production for live HQ and Pod pool reads. */
500
501
  grid?: GridDeps;
502
+ /** Resource observation seam; production reads the same ORCH traffic decision. */
503
+ loopResources?: Parameters<typeof handleLoopResourcesGet>[0];
501
504
  /** DRAFT-METRIC cached source seam; omitted in production for the process-wide TTL cache. */
502
505
  draftMetrics?: DraftMetricsSource;
503
506
  decisions?: Pick<DecisionsRouteDeps, 'ledger'>;
@@ -1396,6 +1399,11 @@ export async function routeRequest(
1396
1399
 
1397
1400
  // Same owner auth as the neighbouring GETs (short-lived owner tokens · same-origin PWA); #23932 compared the admin
1398
1401
  // bearer only, so a PWA on a short-lived token got 401 and the loop map stayed empty.
1402
+ if (pathname === '/v1/loops/resources' && method === 'GET') {
1403
+ if (!opts.metaApi) return jsonResponse({ error: 'meta-api-runtime-not-wired' }, 503);
1404
+ if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
1405
+ return handleLoopResourcesGet(opts.loopResources);
1406
+ }
1399
1407
  if (pathname === '/v1/loops/edges' && method === 'GET') {
1400
1408
  if (!opts.metaApi) return jsonResponse({ error: 'meta-api-runtime-not-wired' }, 503);
1401
1409
  if (!checkAuth(req, opts.metaApi)) return jsonResponse({ error: 'unauthorized' }, 401);
@@ -0,0 +1,42 @@
1
+ import { defaultListHarnessProcesses } from '../../harness/harness-cli-command.js';
2
+ import { devVersion, listChecklist } from '../../release-loop/checklist.js';
3
+ import { listSchedules } from '../../release-loop/release-schedule.js';
4
+ import { releaseLedgerRoot } from '../../instance/resolve.js';
5
+ import { getUserConfig, ORCHESTRATOR_DEFAULTS } from '../../user-config.js';
6
+ import { seatOfTree, trafficTick, TRAFFIC_SEATS, type TrafficCell, type TrafficResult } from '../../loops/orchestrator/traffic.js';
7
+ import { finishAdvice, measureFinish } from '../../loops/orchestrator/finish-rate.js';
8
+ import { jsonResponse } from './json-response.js';
9
+
10
+ /** Read-only snapshot of the same ORCH traffic decision used by the scheduled tick. */
11
+ export function observeLoopResources(deps: {
12
+ now?: Date;
13
+ processes?: ReturnType<typeof defaultListHarnessProcesses>;
14
+ version?: string;
15
+ openCells?: readonly TrafficCell[];
16
+ nextRound?: readonly TrafficCell[];
17
+ totalSlots?: number;
18
+ } = {}): TrafficResult {
19
+ const now = deps.now ?? new Date();
20
+ const cfg = getUserConfig().loops?.orchestrator ?? ORCHESTRATOR_DEFAULTS;
21
+ const observation = deps.processes ?? defaultListHarnessProcesses();
22
+ if (observation.status !== 'ok') throw new Error(`process observation ${observation.status}`);
23
+ const version = deps.version ?? devVersion().replace(/-dev\.\d+$/, '');
24
+ const upcoming = deps.nextRound === undefined ? listSchedules(releaseLedgerRoot()).filter(row => Date.parse(row.cutAt) > now.getTime())
25
+ .sort((a, b) => Date.parse(a.cutAt) - Date.parse(b.cutAt)) : [];
26
+ const currentIndex = upcoming.findIndex(row => row.version === version);
27
+ const nextVersion = currentIndex < 0 ? upcoming[0]?.version : upcoming[currentIndex + 1]?.version;
28
+ const totalSlots = deps.totalSlots ?? finishAdvice(measureFinish({}, now),
29
+ TRAFFIC_SEATS.reduce((sum, seat) => sum + cfg.seatCaps[seat], 0)).launchSlots;
30
+ return trafficTick({
31
+ processes: observation.records.map(process => ({ ...process, seat: seatOfTree(process.cwdStatus === 'unknown' ? undefined : process.cwd, cfg) })),
32
+ now, caps: cfg.seatCaps, openCells: deps.openCells ?? listChecklist(version).items, totalSlots,
33
+ ...(deps.nextRound !== undefined ? { nextRound: deps.nextRound }
34
+ : nextVersion ? { nextRound: listChecklist(nextVersion).items } : {}),
35
+ retainQueuedCells: true,
36
+ });
37
+ }
38
+
39
+ export function handleLoopResourcesGet(observe: () => TrafficResult = observeLoopResources): Response {
40
+ try { return jsonResponse({ resource: observe() }); }
41
+ catch { return jsonResponse({ error: 'resource-unavailable' }, 503); }
42
+ }