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
@@ -0,0 +1,175 @@
1
+ import { debug } from '../debug/log.js';
2
+ import { parentPort, Worker } from 'node:worker_threads';
3
+ import { collectOverview, type CollectOptions } from './overview-collect.js';
4
+ import { computeVerdict, unmeasured, okCell, type OverviewSnapshot, type PodMemberRow } from './overview.js';
5
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
6
+ import { getElanousConfigDirOverride, setElanousConfigDir } from '../elanous-config-dir.js';
7
+
8
+ const SNAPSHOT_MS = 10_000;
9
+ const POD_MS = 60_000;
10
+ const POD_STALE_MS = 2 * POD_MS;
11
+ /** Bounds for distinct (version, owner, since) keys: memo entries kept and collections in flight. */
12
+ const MAX_MEMO = 32;
13
+ const MAX_PENDING = 2;
14
+
15
+ type PodReading = { context: string; occupied: number | null; reason: string | null; observedAt: number };
16
+ type OverviewData = OverviewSnapshot & ReturnType<typeof computeVerdict> & { cacheAgeMs: number; durationMs: number; sources: string[]; refreshFailed: string | null };
17
+ type WorkerMessage = ({ kind: 'pods' } | { kind: 'snapshot'; options: CollectOptions }) & { configDir?: string };
18
+
19
+ /** The kubectl-capable grid reader lives in a worker, never on the HTTP event loop. */
20
+ const port = parentPort;
21
+ if (port) {
22
+ port.on('message', async (message: WorkerMessage) => {
23
+ try {
24
+ // A worker does not share the main thread's module state: carry the daemon's universe in.
25
+ if (message.configDir) setElanousConfigDir(message.configDir);
26
+ if (message.kind === 'pods') {
27
+ const { buildGridData } = await import('../nexus/api/grid.js');
28
+ const rows = buildGridData().members.map((m) => ({ context: m.context, occupied: m.occupied, reason: m.reason, observedAt: Date.now() }));
29
+ port.postMessage({ rows });
30
+ } else port.postMessage({ snapshot: await collectOverview(message.options) });
31
+ } catch (error) {
32
+ port.postMessage({ error: error instanceof Error ? error.message : String(error) });
33
+ }
34
+ });
35
+ }
36
+
37
+ function workerRead<T>(message: WorkerMessage, timeoutMs: number, field: 'rows' | 'snapshot'): Promise<T> {
38
+ return new Promise((resolve, reject) => {
39
+ const worker = new Worker(new URL('./overview-cache.ts', import.meta.url));
40
+ let settled = false;
41
+ const finish = (error?: Error, result?: T) => {
42
+ if (settled) return;
43
+ settled = true;
44
+ clearTimeout(timeout);
45
+ void worker.terminate();
46
+ if (error) reject(error);
47
+ else resolve(result!);
48
+ };
49
+ const timeout = setTimeout(() => finish(new Error(`${field} 측정 시간 초과`)), timeoutMs);
50
+ worker.on('message', (result: { rows?: PodReading[]; snapshot?: OverviewSnapshot; error?: string }) => {
51
+ if (result.error) finish(new Error(result.error));
52
+ else finish(undefined, result[field] as T);
53
+ });
54
+ worker.on('error', (error) => finish(error instanceof Error ? error : new Error(String(error))));
55
+ const configDir = getElanousConfigDirOverride();
56
+ worker.postMessage({ ...message, ...(configDir ? { configDir } : {}) });
57
+ });
58
+ }
59
+
60
+ const measurePodsInWorker = () => workerRead<PodReading[]>({ kind: 'pods' }, 55_000, 'rows');
61
+ const collectInWorker = (options: CollectOptions) => workerRead<OverviewSnapshot>({ kind: 'snapshot', options: { ...options, root: options.root ?? effectiveInstanceRoot() } }, 30_000, 'snapshot');
62
+
63
+ function pendingSnapshot(at: number, since: string, reason: string): OverviewSnapshot {
64
+ const missing = <T>(name: string) => unmeasured<T>(name, reason);
65
+ return {
66
+ // Same resolution the collector uses; never the daemon's cwd.
67
+ generatedAt: new Date(at).toISOString(), instanceRoot: effectiveInstanceRoot(), since,
68
+ release: { version: missing('release.version'), run: missing('release.run'), schedule: missing('release.schedule'), checklist: missing('release.checklist') },
69
+ tasks: { byOwner: missing('tasks.byOwner'), done: missing('tasks.done'), launchable: missing('tasks.launchable'), capacity: missing('tasks.capacity') },
70
+ machines: { hosts: [], pods: [], parents: missing('machines.parents') },
71
+ landings: missing('landings'), loops: [],
72
+ };
73
+ }
74
+
75
+ export function createOverviewCache(deps: {
76
+ collect?: (opts: CollectOptions) => Promise<OverviewSnapshot>;
77
+ measurePods?: () => Promise<PodReading[]>;
78
+ now?: () => number;
79
+ schedule?: (tick: () => void, ms: number) => NodeJS.Timeout;
80
+ } = {}) {
81
+ const now = deps.now ?? Date.now;
82
+ const collect = deps.collect ?? collectInWorker;
83
+ const backgroundSnapshot = !deps.collect;
84
+ const measurePods = deps.measurePods ?? measurePodsInWorker;
85
+ const schedule = deps.schedule ?? ((tick: () => void, ms: number): NodeJS.Timeout => setInterval(tick, ms));
86
+ // The memo holds the collected snapshot only; Pod occupancy and the verdict are
87
+ // overlaid at response time so a failed or stale (120 s) measurement shows at once.
88
+ type Entry = { at: number; snapshot: OverviewSnapshot; durationMs: number; failure?: string; retryAt?: number };
89
+ const memo = new Map<string, Entry>();
90
+ const pending = new Map<string, Promise<void>>();
91
+ let podRows: PodReading[] = [];
92
+ let podFailure: string | null = null;
93
+ let podTimer: ReturnType<typeof setInterval> | null = null;
94
+ let podPending = false;
95
+
96
+ const refreshPods = async () => {
97
+ if (podPending) return;
98
+ podPending = true;
99
+ try { podRows = await measurePods(); podFailure = null; }
100
+ catch (error) { podRows = []; podFailure = error instanceof Error ? error.message : String(error); }
101
+ finally { podPending = false; }
102
+ };
103
+ const start = () => {
104
+ if (podTimer) return;
105
+ // The timer starts on the first authorized read; measurement never runs on the request stack.
106
+ podTimer = schedule(() => { void refreshPods(); }, POD_MS);
107
+ podTimer.unref();
108
+ };
109
+ const present = (entry: Entry): OverviewData => {
110
+ const at = now();
111
+ const byContext = new Map(podRows.map((row) => [row.context, row]));
112
+ const pods: PodMemberRow[] = entry.snapshot.machines.pods.map((pod) => {
113
+ const row = byContext.get(pod.context);
114
+ const stale = row && at - row.observedAt >= POD_STALE_MS;
115
+ const occupied = !podFailure && row && !stale && row.occupied !== null
116
+ ? okCell(row.occupied, 'pod pool background measure', new Date(row.observedAt).toISOString())
117
+ : unmeasured<number>('pod pool background measure', podFailure ?? (stale ? '낡음(120초)' : row?.reason ?? '측정 대기'), row ? new Date(row.observedAt).toISOString() : null);
118
+ return { ...pod, occupied };
119
+ });
120
+ const full = { ...entry.snapshot, machines: { ...entry.snapshot.machines, pods } };
121
+ return { ...full, ...computeVerdict(full), durationMs: entry.durationMs,
122
+ sources: [full.release.run.source, full.tasks.launchable.source, full.tasks.capacity.source],
123
+ cacheAgeMs: Math.max(0, at - entry.at), refreshFailed: entry.failure ?? null };
124
+ };
125
+ const get = async (options: Pick<CollectOptions, 'version' | 'owner'> & { sinceMs?: number; sinceLabel?: string } = {}): Promise<OverviewData> => {
126
+ start();
127
+ const key = JSON.stringify([options.version ?? null, options.owner ?? null, options.sinceMs ?? 3_600_000]);
128
+ const at = now();
129
+ // Drop expired entries of other keys, then cap the memo (oldest first).
130
+ for (const [other, entry] of memo) if (other !== key && !pending.has(other) && at - entry.at >= SNAPSHOT_MS && (entry.retryAt ?? 0) <= at) memo.delete(other);
131
+ const cached = memo.get(key);
132
+ // A failed refresh keeps the original collection time (true age) and only delays the retry.
133
+ if (cached && (at - cached.at < SNAPSHOT_MS || backgroundSnapshot && pending.has(key) || (cached.retryAt ?? 0) > at)) return present(cached);
134
+ let current = pending.get(key);
135
+ if (!current && pending.size >= MAX_PENDING) {
136
+ // Collections in flight are capped; answer from what we have instead of starting another worker.
137
+ const entry = cached ?? { at, snapshot: pendingSnapshot(at, options.sinceLabel ?? '최근 1h', '동시 수집 상한'), durationMs: 0 };
138
+ return present({ ...entry, failure: entry.failure ?? `동시 수집 상한(${MAX_PENDING})` });
139
+ }
140
+ if (!current) {
141
+ // Evict only when a new key is about to be stored, never on a hit for an existing key.
142
+ if (!memo.has(key)) while (memo.size >= MAX_MEMO) { const oldest = [...memo.keys()].find((other) => !pending.has(other)); if (!oldest) break; memo.delete(oldest); }
143
+ if (backgroundSnapshot && !cached) {
144
+ // Placeholder until the worker answers; it is not a collection.
145
+ memo.set(key, { at, snapshot: pendingSnapshot(at, options.sinceLabel ?? '최근 1h', '백그라운드 스냅숏 수집 대기'), durationMs: 0 });
146
+ }
147
+ current = (async () => {
148
+ const startAt = now();
149
+ const snapshot = await collect({ sinceMs: options.sinceMs ?? 3_600_000, sinceLabel: options.sinceLabel ?? '최근 1h',
150
+ ...(options.version ? { version: options.version } : {}), ...(options.owner ? { owner: options.owner } : {}), now: startAt });
151
+ // Age counts from when collection started (= snapshot.generatedAt), not when it finished.
152
+ const entry = { at: startAt, snapshot, durationMs: now() - startAt };
153
+ memo.set(key, entry);
154
+ const verdict = present(entry);
155
+ debug.log('ops.overview', 'verdict', { verdict: verdict.verdict, reasons: verdict.reasons, cacheAgeMs: verdict.cacheAgeMs, durationMs: entry.durationMs });
156
+ })();
157
+ pending.set(key, current);
158
+ void current.then(
159
+ () => { pending.delete(key); },
160
+ (error) => {
161
+ pending.delete(key);
162
+ debug.log('ops.overview', 'refresh-failed', { reason: error instanceof Error ? error.message : String(error) });
163
+ const prior = memo.get(key);
164
+ if (prior) memo.set(key, { ...prior, failure: error instanceof Error ? error.message : String(error), retryAt: now() + SNAPSHOT_MS });
165
+ },
166
+ );
167
+ }
168
+ if (!backgroundSnapshot) {
169
+ try { await current; }
170
+ catch (error) { if (!memo.has(key)) throw error; }
171
+ }
172
+ return present(memo.get(key)!);
173
+ };
174
+ return { get, memoSize: () => memo.size, stop: () => { if (podTimer) clearInterval(podTimer); podTimer = null; memo.clear(); } };
175
+ }
@@ -6,6 +6,8 @@
6
6
  * ⛔ «못 잼»은 `value:null` ⊕ `reason` 이다 — 절대 0 으로 읽지 않는다(판정도 그렇다).
7
7
  */
8
8
 
9
+ import { formatLandingThroughput, type LandingThroughput } from '../task-agent/cover.js';
10
+
9
11
  export type CellStatus = 'ok' | 'unmeasured' | 'partial';
10
12
  export interface Cell<T> {
11
13
  value: T | null;
@@ -84,6 +86,8 @@ export interface OverviewSnapshot {
84
86
  parents: Cell<ParentsInfo>;
85
87
  };
86
88
  landings: Cell<{ count: number; recent: string[] }>;
89
+ /** Optional until launch/PR/age sources are wired; existing snapshots keep their exact output. */
90
+ throughput?: Cell<LandingThroughput>;
87
91
  loops: LoopRow[];
88
92
  }
89
93
 
@@ -176,6 +180,7 @@ export function unmeasuredCells(s: OverviewSnapshot): string[] {
176
180
  for (const h of s.machines.hosts) visit(`machines.${h.name}`, h.load);
177
181
  for (const p of s.machines.pods) visit(`pods.${p.context}`, p.occupied);
178
182
  visit('machines.parents', s.machines.parents); visit('landings', s.landings);
183
+ if (s.throughput) visit('throughput', s.throughput);
179
184
  for (const l of s.loops) visit(`loops.${l.name}`, l.beat);
180
185
  return out;
181
186
  }
@@ -215,6 +220,9 @@ export function renderOverview(s: OverviewSnapshot, v: VerdictResult, meta: { el
215
220
  lines.push(` Pod ${s.machines.pods.map((p) => `${p.context} ${show(p.occupied, String)}/${p.capacity}`).join(' · ') || '못 잼(풀 설정 없음)'}`);
216
221
  lines.push(` 하니스 부모(이 기계) ${show(s.machines.parents, (p) => `${p.count} · 6h 넘음 ${p.staleOver6h}${p.oldestHours !== null ? ` · 최고 ${p.oldestHours}h` : ''}`)}`);
217
222
  lines.push(`착지 ${s.since} ${show(s.landings, (l) => `${l.count}`)} [${s.landings.source}]`);
223
+ if (s.throughput) {
224
+ lines.push(`${show(s.throughput, formatLandingThroughput)} [${s.throughput.source}]`);
225
+ }
218
226
  for (const l of s.loops) {
219
227
  lines.push(`루프 ${l.name}${l.era === 'seat-era' ? ' [자리 시대 원천]' : ''} ${show(l.beat, (b) => `${kst(b.lastAt)} (${Math.round(b.ageSeconds / 60)}분 전)${b.alive === null ? '' : b.alive ? ' 살아 있음' : ' 프로세스 없음'}${l.staleAfterSeconds === null ? ' · 주기 미상(판정 제외)' : ''}`)}`);
220
228
  }
@@ -72,25 +72,17 @@ export function readClaudePackageLedger(
72
72
  return { status: 'installed-plugins-unreadable', packages: [] };
73
73
  }
74
74
 
75
- const marketplacesRaw = readJsonFile(marketplacesPath);
76
- if (marketplacesRaw === undefined) {
77
- return { status: 'known-marketplaces-unreadable', packages: [] };
78
- }
79
-
80
75
  const plugins = asPluginMap(installedRaw);
81
76
  if (plugins === undefined) {
82
77
  return { status: 'installed-plugins-unreadable', packages: [] };
83
78
  }
84
79
 
85
- const marketplaces = asMarketplaceMap(marketplacesRaw);
86
- if (marketplaces === undefined) {
87
- return { status: 'known-marketplaces-unreadable', packages: [] };
88
- }
89
-
80
+ const marketplaces = asMarketplaceMap(readJsonFile(marketplacesPath));
81
+ const status: ClaudePackageLedgerStatus = marketplaces === undefined ? 'known-marketplaces-unreadable' : 'ok';
90
82
  const packages: ClaudeInstalledPackage[] = [];
91
83
  for (const [key, records] of Object.entries(plugins)) {
92
84
  const { plugin, marketplace } = splitClaudePluginKey(key);
93
- const source = formatMarketplaceSource(marketplaces[marketplace]);
85
+ const source = formatMarketplaceSource(marketplaces?.[marketplace]);
94
86
  for (const record of records) {
95
87
  packages.push({
96
88
  name: key,
@@ -104,7 +96,7 @@ export function readClaudePackageLedger(
104
96
  }
105
97
  }
106
98
 
107
- return { status: 'ok', packages };
99
+ return { status, packages };
108
100
  }
109
101
 
110
102
  function readJsonFile(path: string): unknown {
@@ -1,3 +1,6 @@
1
+ import { createHash } from 'node:crypto';
2
+ import { readFileSync, readdirSync, statSync } from 'node:fs';
3
+ import { join, relative, resolve, sep } from 'node:path';
1
4
  import type { ExecutionSurfaceSpec } from '../../display/index.js';
2
5
  import type { PluginCapability, PluginSource } from './manifest.js';
3
6
 
@@ -83,6 +86,144 @@ export class PluginCapabilityPolicy {
83
86
  }
84
87
  }
85
88
 
89
+ export type PluginScanLevel = 'safe' | 'caution' | 'dangerous';
90
+ export interface PluginSecurityFinding { level: Exclude<PluginScanLevel, 'safe'>; code: string }
91
+ export interface PluginSecurityDecision {
92
+ scan: PluginScanLevel;
93
+ findings: PluginSecurityFinding[];
94
+ integrity: string;
95
+ license: 'redistributable' | 'restricted' | 'unknown';
96
+ }
97
+
98
+ /** Scan bytes before consent or installation. Only non-identifying codes leave this boundary. */
99
+ export function inspectPluginSecurity(dir: string): PluginSecurityDecision {
100
+ const findings: PluginSecurityFinding[] = [];
101
+ const hash = createHash('sha256');
102
+ let license: PluginSecurityDecision['license'] = 'unknown';
103
+ // Code files are collected first; import/exec checks run after we know which files are reachable at runtime.
104
+ const code = new Map<string, { text: string; test: boolean }>();
105
+ const entrypoints: string[] = [];
106
+ const visit = (folder: string): void => {
107
+ for (const entry of readdirSync(folder, { withFileTypes: true }).sort((a, b) => a.name < b.name ? -1 : a.name > b.name ? 1 : 0)) {
108
+ const file = join(folder, entry.name);
109
+ const rel = relative(dir, file).replaceAll('\\', '/');
110
+ if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile())) {
111
+ findings.push({ level: 'dangerous', code: 'unsafe-entry' });
112
+ hash.update(rel).update('!\0');
113
+ continue;
114
+ }
115
+ if (entry.isDirectory()) { hash.update(rel).update('/\0'); visit(file); continue; }
116
+ hash.update(rel).update('\0');
117
+ // Size is checked before reading so an oversized import cannot exhaust memory in the scanner.
118
+ const size = statSync(file).size;
119
+ if (size > 2_000_000) {
120
+ hash.update(String(size)).update('\0').update('oversize');
121
+ findings.push({ level: 'dangerous', code: 'unscannable-file' });
122
+ continue;
123
+ }
124
+ const bytes = readFileSync(file);
125
+ hash.update(String(bytes.length)).update('\0').update(bytes);
126
+ if (/(?:^|\/)(?:\.env(?:\.|$)|id_rsa$|credentials?\.json$)/i.test(rel)) {
127
+ findings.push({ level: 'dangerous', code: 'credential-file' });
128
+ }
129
+ if (/(?:api[_-]?key|secret|token)\s*[:=]\s*[A-Za-z0-9_-]{16,}/i.test(rel)) {
130
+ findings.push({ level: 'dangerous', code: 'credential-filename' });
131
+ }
132
+ if (/^(?:LICENSE|LICENCE)(?:\.[^/]*)?$/i.test(rel)) {
133
+ if (/\b(?:MIT License|Apache License, Version 2\.0|BSD [23]-Clause|ISC License)\b/i.test(bytes.toString('utf8'))) license = 'redistributable';
134
+ else if (license !== 'redistributable') license = 'restricted';
135
+ }
136
+ if (bytes.includes(0)) {
137
+ findings.push({ level: 'dangerous', code: 'unscannable-file' });
138
+ continue;
139
+ }
140
+ const text = bytes.toString('utf8');
141
+ if (/^plugin\.json$/.test(rel)) {
142
+ try {
143
+ const manifest: unknown = JSON.parse(text);
144
+ if (manifest && typeof manifest === 'object' && !Array.isArray(manifest)) {
145
+ const raw = manifest as Record<string, unknown>;
146
+ const ext = raw.extensions && typeof raw.extensions === 'object' ? (raw.extensions as Record<string, unknown>)['ai.elanous'] : undefined;
147
+ for (const main of [raw.main, ext && typeof ext === 'object' ? (ext as Record<string, unknown>).main : undefined]) {
148
+ if (typeof main === 'string' && main.trim()) entrypoints.push(resolve(dir, main));
149
+ }
150
+ if (typeof raw.license === 'string' && raw.license.trim()) {
151
+ license = /^(?:MIT|Apache-2\.0|BSD-2-Clause|BSD-3-Clause|ISC|0BSD|CC0-1\.0)$/.test(raw.license.trim())
152
+ ? 'redistributable' : 'restricted';
153
+ }
154
+ const contributes = raw.contributes ?? (ext && typeof ext === 'object' ? (ext as Record<string, unknown>).contributes : undefined);
155
+ if (contributes && typeof contributes === 'object' && Array.isArray((contributes as Record<string, unknown>).hooks)
156
+ && ((contributes as Record<string, unknown>).hooks as unknown[]).length) {
157
+ findings.push({ level: 'caution', code: 'hooks-disabled' });
158
+ }
159
+ }
160
+ } catch { findings.push({ level: 'dangerous', code: 'invalid-manifest' }); }
161
+ }
162
+ // Quotes may be JSON-escaped (a value nested inside a JSON string field), so allow a backslash before them.
163
+ const sensitive = /(?:-----BEGIN (?:RSA |EC |OPENSSH )?PRIVATE KEY-----|(?:\\?["'])?(?:api[_-]?key|secret|token)(?:\\?["'])?\s*[:=]\s*(\\?["'])?([A-Za-z0-9_\-]{16,})(\(?))/gi;
164
+ // Two narrow non-secrets: a documented placeholder (`tvly-YOUR_API_KEY`, `xxxxxxxx…`, `REPLACE_ME`) and an
165
+ // unquoted call result (`apiKey = getUpstageApiKey()`). Anything else that matches — quoted or not — still counts.
166
+ // Both exemptions look at the WHOLE value: a placeholder shape (optional vendor prefix), or a digit-free
167
+ // camelCase function name immediately called. A key with `xxxxxxxx` or `YOUR_` inside it still counts.
168
+ const placeholder = /^(?:[A-Za-z0-9]+[_-])*(?:YOUR[_-][A-Za-z_-]+|PLACEHOLDER[A-Za-z_-]*|REPLACE[_-]?ME[A-Za-z_-]*|x{8,})$/i;
169
+ const callee = /^[a-z_$][A-Za-z_$]*[a-z][A-Z][A-Za-z_$]*$/;
170
+ const hasSecret = [...text.matchAll(sensitive)].some(([, quote, value, call]) => value === undefined
171
+ || !(placeholder.test(value) || (!quote && call === '(' && callee.test(value))));
172
+ if (/(?:^|\/)(?:knowledge|knowledge-packs?)(?:\/|$)/i.test(rel) && hasSecret) {
173
+ findings.push({ level: 'dangerous', code: 'knowledge-dlp' });
174
+ } else if (hasSecret && !/\.lock$/.test(rel)) {
175
+ findings.push({ level: 'dangerous', code: 'embedded-secret' });
176
+ }
177
+ if (/\.[cm]?[jt]sx?$/.test(rel)) code.set(resolve(file), { text, test: /(?:^|\/)[^/]+\.(?:test|spec)\.[cm]?[jt]sx?$/.test(rel) });
178
+ if (/(?:curl|wget)\b[^\n|]*\|\s*(?:sh|bash)\b|\b(?:rm\s+-rf|sudo)\b/i.test(text)) {
179
+ findings.push({ level: 'dangerous', code: 'unsafe-command' });
180
+ }
181
+ }
182
+ };
183
+ visit(dir);
184
+ if (!entrypoints.length) entrypoints.push(resolve(dir, 'plugin.ts'));
185
+ // Shipped test fixtures are skipped only while nothing executable reaches them: the manifest `main`
186
+ // and every non-test code file are roots, and any test file they import (transitively) is scanned too.
187
+ const importsOf = (text: string): string[] =>
188
+ [...text.matchAll(/\b(?:import|export)\s*(?:[\s\S]*?\s+from\s*)?["']([^"']+)["']|\b(?:import|require)\s*\(\s*["']([^"']+)["']/g)]
189
+ .map(match => match[1] ?? match[2] ?? '').filter(Boolean);
190
+ const resolveLocal = (from: string, target: string): string | undefined => {
191
+ if (!target.startsWith('.')) return undefined;
192
+ const base = resolve(from, '..', target);
193
+ const swapped = base.replace(/\.([cm]?)js(x?)$/, '.$1ts$2');
194
+ return [base, swapped, `${base}.ts`, `${base}.tsx`, `${base}.js`, `${base}.mjs`, join(base, 'index.ts'), join(base, 'index.js')]
195
+ .find(candidate => code.has(candidate));
196
+ };
197
+ const reachable = new Set<string>();
198
+ const queue = [...entrypoints.filter(path => code.has(path)), ...[...code].filter(([, info]) => !info.test).map(([path]) => path)];
199
+ while (queue.length) {
200
+ const file = queue.pop()!;
201
+ if (reachable.has(file)) continue;
202
+ reachable.add(file);
203
+ for (const target of importsOf(code.get(file)!.text)) {
204
+ const next = resolveLocal(file, target);
205
+ if (next && !reachable.has(next)) queue.push(next);
206
+ }
207
+ }
208
+ for (const file of reachable) {
209
+ const text = code.get(file)!.text;
210
+ if (/\b(?:eval\s*\(|new\s+Function\s*\(|child_process\b|Bun\.spawn\s*\()/i.test(text)) {
211
+ findings.push({ level: 'caution', code: 'executable-code' });
212
+ }
213
+ for (const target of importsOf(text)) {
214
+ // A relative or absolute import must stay inside the package; the package's own `./src/…` is fine,
215
+ // while `../…/src/`, `/abs/…/src/` or a `file:` URL that can leave the package root is unsafe.
216
+ if (/^file:/i.test(target)
217
+ || ((target.startsWith('.') || target.startsWith('/')) && !resolve(file, '..', target).startsWith(`${resolve(dir)}${sep}`))) {
218
+ findings.push({ level: 'dangerous', code: 'unsafe-import' });
219
+ }
220
+ }
221
+ }
222
+ if ((license as PluginSecurityDecision['license']) !== 'redistributable') findings.push({ level: 'caution', code: 'private-only-license' });
223
+ return { scan: findings.some(f => f.level === 'dangerous') ? 'dangerous' : findings.length ? 'caution' : 'safe',
224
+ findings, integrity: hash.digest('hex'), license };
225
+ }
226
+
86
227
  export function assertCapability(decision: CapabilityDecision): void {
87
228
  if (!decision.ok) throw new Error(decision.reason);
88
229
  }
@@ -38,7 +38,7 @@ import { debug } from '../../debug/log.js';
38
38
  import { getSessionCwd } from '../../session/working-dir.js';
39
39
  import { CommandRegistry, type CommandDisposable, type RegisteredCommand } from '../../command-registry.js';
40
40
  import { PluginCapabilityPolicy, assertCapability } from './capability-policy.js';
41
- import { PluginTrustStore } from './trust-store.js';
41
+ import { PluginTrustStore, enabledPluginHooks } from './trust-store.js';
42
42
  import { PluginTaskService } from './task-service.js';
43
43
  import { readClipboardText, writeClipboard } from '../../clipboard/index.js';
44
44
  import {
@@ -54,6 +54,7 @@ import { getGlobalElementRegistry, publishElementEvent } from '../../element-reg
54
54
  import { mintPluginUri } from '../../mss/uri/builder.js';
55
55
  import type { PluginUri } from '../../mss/uri/brand.js';
56
56
  import { loadPluginNodes } from '../../graph-kinds/plugin-nodes.js';
57
+ import { registerOutboundAdapter } from '../../nexus/outbound/router.js';
57
58
  import { getNodeKindRegistration, listNodeKinds, unregisterPluginNodeKind, type NodeKindEntry } from '../../graph-kinds/registry.js';
58
59
 
59
60
  /** Clamp a tool handler's return value to something short enough for
@@ -113,8 +114,10 @@ export interface ActivePlugin {
113
114
  ownedCommandDisposables: CommandDisposable[];
114
115
  /** Task registrations for this activation. */
115
116
  ownedTaskDisposables: Array<{ dispose(): void }>;
116
- /** PX-3: hook registrations (from manifest.contributes.hooks[] +
117
- * ctx.hooks.register calls). Disposed on deactivate. */
117
+ /** Connector registrations are owner-scoped and removed on deactivate. */
118
+ ownedChannelDisposers: Array<() => void>;
119
+ /** Hook registrations from manifest.contributes.hooks[]; disposed on deactivate.
120
+ * PluginContext does not expose a programmatic hooks registration API. */
118
121
  ownedHookDisposers: Array<() => void>;
119
122
  /** PX-4: mission registrations (one per contributes.missions[] entry).
120
123
  * Disposers tear down globalMissionRegistry entries on deactivate. */
@@ -369,13 +372,12 @@ export class PluginHost {
369
372
  }
370
373
  }
371
374
 
372
- /** PX-3 P4: register all manifest-declared shell hooks for the
373
- * plugin we're activating. Disposers are tracked on the active
374
- * entry so deactivate() unregisters them. In-process hooks go
375
- * through ctx.hooks.register inside onActivate (see buildContext). */
375
+ /** Register manifest-declared shell hooks for the plugin being activated.
376
+ * Installed plugins' hooks stay off (no approval path); disposers unregister them on deactivate. */
376
377
  private registerManifestHooks(entry: PluginEntry): void {
377
378
  if (!this.activeEntry) return;
378
- const specs = entry.manifest.contributes.hooks ?? [];
379
+ const declared = entry.manifest.contributes.hooks ?? [];
380
+ const specs = enabledPluginHooks(declared, entry.source);
379
381
  if (specs.length === 0) return;
380
382
  // Lazy imports so headless tests that don't exercise hooks never
381
383
  // pull in the dispatcher stack.
@@ -770,6 +772,7 @@ export class PluginHost {
770
772
  ownedDisplayDisposables: [],
771
773
  ownedCommandDisposables: [],
772
774
  ownedTaskDisposables: [],
775
+ ownedChannelDisposers: [],
773
776
  ownedHookDisposers: [],
774
777
  ownedMissionDisposers: [],
775
778
  ownedRouteDisposers: [],
@@ -822,6 +825,13 @@ export class PluginHost {
822
825
  const ctx = this.buildContext();
823
826
  try {
824
827
  await plugin.onActivate?.(ctx);
828
+ for (const adapter of plugin.channelAdapters ?? []) {
829
+ if (!entry.manifest.contributes.connectors?.some(connector => connector.id === adapter.type)) {
830
+ throw new Error(`channel connector ${adapter.type} must be declared in contributes.connectors`);
831
+ }
832
+ // The manifest declaration alone is not an active channel.
833
+ this.activeEntry.ownedChannelDisposers.push(registerOutboundAdapter(adapter));
834
+ }
825
835
  // Resolve layout after onActivate so the plugin can initialize
826
836
  // state first (e.g. fetch remote rows). buildLayout can spawn
827
837
  // widgets via the tracked helper — we record ids for dispose.
@@ -848,6 +858,7 @@ export class PluginHost {
848
858
  for (const d of this.activeEntry.ownedDisplayDisposables) d.dispose();
849
859
  for (const d of this.activeEntry.ownedCommandDisposables) d.dispose();
850
860
  for (const d of this.activeEntry.ownedTaskDisposables) d.dispose();
861
+ for (const d of this.activeEntry.ownedChannelDisposers) d();
851
862
  for (const d of this.activeEntry.ownedHookDisposers) d();
852
863
  for (const d of this.activeEntry.ownedMissionDisposers) d();
853
864
  for (const d of this.activeEntry.ownedRouteDisposers) d();
@@ -880,6 +891,7 @@ export class PluginHost {
880
891
  for (const d of this.activeEntry.ownedDisplayDisposables) d.dispose();
881
892
  for (const d of this.activeEntry.ownedCommandDisposables) d.dispose();
882
893
  for (const d of this.activeEntry.ownedTaskDisposables) d.dispose();
894
+ for (const d of this.activeEntry.ownedChannelDisposers) d();
883
895
  const promptStore = getPromptBankStore();
884
896
  for (const id of this.activeEntry.promptFragmentIds) promptStore.delete(id);
885
897
  // PX-3: dispose hook registrations for this plugin.
@@ -1746,6 +1758,7 @@ function normalizePluginExport(plugin: Partial<ElanousPlugin>, manifest: PluginM
1746
1758
  ...(plugin.slashCommands ? { slashCommands: plugin.slashCommands } : {}),
1747
1759
  ...(plugin.keybindings ? { keybindings: plugin.keybindings } : {}),
1748
1760
  ...(plugin.llmTools ? { llmTools: plugin.llmTools } : {}),
1761
+ ...(plugin.channelAdapters ? { channelAdapters: plugin.channelAdapters } : {}),
1749
1762
  ...(plugin.onActivate ? { onActivate: plugin.onActivate } : {}),
1750
1763
  ...(plugin.onDeactivate ? { onDeactivate: plugin.onDeactivate } : {}),
1751
1764
  ...(plugin.isBusy ? { isBusy: plugin.isBusy } : {}),
@@ -1,6 +1,6 @@
1
1
  import { existsSync, readFileSync } from 'fs';
2
2
  import { join } from 'path';
3
- import type { Keybinding, SlashCommand } from './types.js';
3
+ import type { Keybinding, PluginDependency, SlashCommand } from './types.js';
4
4
  import type { PromptKind, PromptScope, PromptTargetSlot } from '../../prompt-bank/types.js';
5
5
  import type {
6
6
  MissionDefinition,
@@ -223,6 +223,8 @@ export interface PluginManifest {
223
223
  activationEvents: string[];
224
224
  contributes: PluginManifestContributes;
225
225
  capabilities: PluginCapability[];
226
+ /** `plugin.json` requirement metadata; does not trigger installation. */
227
+ requires?: PluginDependency;
226
228
  dependencies?: {
227
229
  widgets?: string[];
228
230
  plugins?: string[];
@@ -328,6 +330,7 @@ export function parsePluginManifest(
328
330
  ? raw.capabilities
329
331
  : [...parseCapabilities(raw.capabilities), ...parseCapabilities(extension.capabilities)]);
330
332
  const dependencies = parseDependencies(raw.dependencies);
333
+ const requires = parsePluginRequires(raw.requires === undefined ? extension.requires : raw.requires);
331
334
  const description = typeof raw.description === 'string' ? raw.description : undefined;
332
335
  const allowMultiActive = typeof raw.allowMultiActive === 'boolean' ? raw.allowMultiActive : undefined;
333
336
  const activePeerCompat = parseActivePeerCompat(raw.activePeerCompat);
@@ -341,6 +344,7 @@ export function parsePluginManifest(
341
344
  activationEvents,
342
345
  contributes,
343
346
  capabilities,
347
+ ...(requires ? { requires } : {}),
344
348
  ...(dependencies ? { dependencies } : {}),
345
349
  ...(allowMultiActive !== undefined ? { allowMultiActive } : {}),
346
350
  ...(activePeerCompat ? { activePeerCompat } : {}),
@@ -354,7 +358,7 @@ function objectOrEmpty(value: unknown, label: string): Record<string, unknown> {
354
358
  return value as Record<string, unknown>;
355
359
  }
356
360
 
357
- function parseElanousExtension(value: unknown): { contributes: Record<string, unknown>; capabilities?: unknown } {
361
+ function parseElanousExtension(value: unknown): { contributes: Record<string, unknown>; capabilities?: unknown; requires?: unknown } {
358
362
  const extensions = objectOrEmpty(value, 'extensions');
359
363
  const extension = objectOrEmpty(extensions['ai.elanous'], 'extensions["ai.elanous"]');
360
364
  const contributes = objectOrEmpty(extension.contributes, 'extensions["ai.elanous"].contributes');
@@ -365,6 +369,7 @@ function parseElanousExtension(value: unknown): { contributes: Record<string, un
365
369
  .map(key => [key, extension[key]])),
366
370
  },
367
371
  capabilities: extension.capabilities,
372
+ requires: extension.requires,
368
373
  };
369
374
  }
370
375
 
@@ -1117,6 +1122,18 @@ function parseCapabilities(value: unknown): PluginCapability[] {
1117
1122
  });
1118
1123
  }
1119
1124
 
1125
+ function parsePluginRequires(value: unknown): PluginDependency | undefined {
1126
+ if (value === undefined) return undefined;
1127
+ const raw = objectOrEmpty(value, 'requires');
1128
+ return {
1129
+ ...(raw.elanous !== undefined ? { elanous: stringOr(raw.elanous) } : {}),
1130
+ ...(raw.tools !== undefined ? { tools: stringArrayOr(raw.tools, []) } : {}),
1131
+ ...(raw.optionalTools !== undefined ? { optionalTools: stringArrayOr(raw.optionalTools, []) } : {}),
1132
+ ...(raw.optionalPython !== undefined ? { optionalPython: stringArrayOr(raw.optionalPython, []) } : {}),
1133
+ ...(raw.knowledgePacks !== undefined ? { knowledgePacks: stringArrayOr(raw.knowledgePacks, []) } : {}),
1134
+ };
1135
+ }
1136
+
1120
1137
  function parseDependencies(value: unknown): PluginManifest['dependencies'] | undefined {
1121
1138
  if (value === undefined) return undefined;
1122
1139
  if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error('dependencies must be an object');
@@ -1,6 +1,7 @@
1
1
  import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
2
2
  import { dirname, join } from 'node:path';
3
3
  import { DATA_DIR } from '../../config.js';
4
+ import type { PluginSecurityDecision } from './capability-policy.js';
4
5
 
5
6
  export type PluginTrustScope = 'user' | 'workspace';
6
7
 
@@ -16,6 +17,20 @@ interface PluginTrustFile {
16
17
  records: PluginTrustRecord[];
17
18
  }
18
19
 
20
+ /** Ephemeral installation decision; never persisted as a trust record or a credential. */
21
+ export function decidePluginInstallation(security: PluginSecurityDecision, capabilities: readonly string[], consent: boolean):
22
+ { ok: true } | { ok: false; reason: 'scan' | 'consent-denied' } {
23
+ if (security.scan === 'dangerous') return { ok: false, reason: 'scan' };
24
+ if (capabilities.length > 0 && !consent) return { ok: false, reason: 'consent-denied' };
25
+ return { ok: true };
26
+ }
27
+
28
+ /** Hooks default off for installed (imported/generated) plugins: there is no approval path yet, so none run.
29
+ * Built-in and user-dir plugins keep their declared hooks unchanged. */
30
+ export function enabledPluginHooks<T>(hooks: readonly T[], source: string): T[] {
31
+ return source === 'installed' ? [] : [...hooks];
32
+ }
33
+
19
34
  export class PluginTrustStore {
20
35
  constructor(private readonly path = defaultPluginTrustPath()) {}
21
36
 
@@ -26,6 +26,15 @@ import type {
26
26
 
27
27
  export type PaneSlot = 'skills' | 'files' | 'preview' | 'log' | 'hud';
28
28
 
29
+ /** Requirements declared by a plugin.json `requires` block. This is metadata, not an install request. */
30
+ export interface PluginDependency {
31
+ elanous?: string;
32
+ tools?: string[];
33
+ optionalTools?: string[];
34
+ optionalPython?: string[];
35
+ knowledgePacks?: string[];
36
+ }
37
+
29
38
  export interface DashboardPaneSummary {
30
39
  pane: string;
31
40
  visible: boolean;
@@ -327,6 +336,9 @@ export interface ElanousPlugin<S = unknown> {
327
336
  slashCommands?: SlashCommand[];
328
337
  keybindings?: Keybinding[];
329
338
  llmTools?: LLMToolDef[];
339
+ /** Host registers only adapters also declared in contributes.connectors;
340
+ * registration is disposed with this plugin activation. */
341
+ channelAdapters?: import('../../nexus/outbound/router.js').ChannelAdapter[];
330
342
  onActivate?(ctx: PluginContext): void | Promise<void>;
331
343
  onDeactivate?(ctx: PluginContext): void | Promise<void>;
332
344
  /** Plugin is executing a long-running op — host blocks input while true.