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
@@ -13,7 +13,14 @@ export const ELANOUS_MARKET_URL = 'https://elanvitalai.github.io/elanous-plugins
13
13
  const NAME = /^[a-z0-9][a-z0-9-]{1,39}$/;
14
14
  const MAX_INDEX_BYTES = 8 * 1024 * 1024;
15
15
 
16
- export interface MarketConfig { name: string; url: string }
16
+ export interface MarketConfig {
17
+ name: string;
18
+ url: string;
19
+ /** Explicit tenant allowlist for a private market; absent for existing plugin markets. */
20
+ enterpriseIds?: string[];
21
+ /** Keys bound to this private market, never inherited from the global plugin trust pool. */
22
+ trustedKeys?: Array<{ keyId: string; publicKey: string }>;
23
+ }
17
24
  export interface MarketFetchOptions {
18
25
  root?: string;
19
26
  marketDir?: string;
@@ -75,6 +82,24 @@ function configuredMarkets(settings: Record<string, unknown>): MarketConfig[] {
75
82
  return { name, url: marketUrl(url) };
76
83
  });
77
84
  }
85
+ function internalMarkets(settings: Record<string, unknown>): MarketConfig[] {
86
+ const entries = settings.internalMarkets;
87
+ if (entries === undefined) return [];
88
+ if (!Array.isArray(entries)) throw new MarketFetchError('io', 'invalid internal markets configuration');
89
+ const names = new Set<string>();
90
+ return entries.map((entry: unknown) => {
91
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) throw new MarketFetchError('io', 'invalid internal market configuration');
92
+ const { name, url, enterpriseIds, trustedKeys } = entry as Record<string, unknown>;
93
+ if (typeof name !== 'string' || !NAME.test(name) || names.has(name) || name === 'elanous') throw new MarketFetchError('io', `invalid or duplicate internal market name: ${String(name)}`);
94
+ if (!Array.isArray(enterpriseIds) || !enterpriseIds.length || !enterpriseIds.every(id => typeof id === 'string' && id.trim() && id === id.trim())
95
+ || new Set(enterpriseIds).size !== enterpriseIds.length) throw new MarketFetchError('io', `invalid internal market enterprise allowlist: ${name}`);
96
+ if (!Array.isArray(trustedKeys) || !trustedKeys.length || !trustedKeys.every(key => key && typeof key === 'object' && typeof key.keyId === 'string' && /^[a-fA-F0-9]{8}$/.test(key.keyId) && typeof key.publicKey === 'string' && key.publicKey.length > 0)
97
+ || new Set(trustedKeys.map(key => key.keyId)).size !== trustedKeys.length) throw new MarketFetchError('io', `invalid internal market trusted keys: ${name}`);
98
+ names.add(name);
99
+ return { name, url: marketUrl(url), enterpriseIds: enterpriseIds as string[], trustedKeys: trustedKeys as Array<{ keyId: string; publicKey: string }> };
100
+ });
101
+ }
102
+
78
103
  function trust(settings: Record<string, unknown>, opts: MarketFetchOptions): ReadonlyArray<{ keyId: string; publicKey: string }> {
79
104
  const additional = settings.trustedKeys;
80
105
  if (additional !== undefined && (!Array.isArray(additional) || !additional.every(key => key && typeof key.keyId === 'string' && typeof key.publicKey === 'string'))) {
@@ -115,7 +140,7 @@ function location(name: string, opts: MarketFetchOptions): string {
115
140
  return join(resolve(opts.marketDir ?? join(opts.root ?? elanousStateRoot(), 'markets')), name);
116
141
  }
117
142
 
118
- interface CacheState { url: string; lastSequence: number; indexHash: string; signatureHash: string }
143
+ interface CacheState { url: string; lastSequence: number; indexHash: string; signatureHash: string; trustHash?: string }
119
144
 
120
145
  function cacheState(path: string): CacheState | undefined {
121
146
  if (!existsSync(path)) return undefined;
@@ -123,13 +148,14 @@ function cacheState(path: string): CacheState | undefined {
123
148
  try { value = JSON.parse(readFileSync(path, 'utf8')); }
124
149
  catch { throw new MarketFetchError('io', 'invalid market cache state'); }
125
150
  if (!value || typeof value !== 'object' || Array.isArray(value)) throw new MarketFetchError('io', 'invalid market cache state');
126
- const { url, lastSequence, indexHash, signatureHash } = value as Record<string, unknown>;
151
+ const { url, lastSequence, indexHash, signatureHash, trustHash } = value as Record<string, unknown>;
127
152
  if (typeof url !== 'string' || !Number.isSafeInteger(lastSequence) || (lastSequence as number) < 0
128
153
  || typeof indexHash !== 'string' || !/^[a-f0-9]{64}$/.test(indexHash)
129
- || typeof signatureHash !== 'string' || !/^[a-f0-9]{64}$/.test(signatureHash)) {
154
+ || typeof signatureHash !== 'string' || !/^[a-f0-9]{64}$/.test(signatureHash)
155
+ || (trustHash !== undefined && (typeof trustHash !== 'string' || !/^[a-f0-9]{64}$/.test(trustHash)))) {
130
156
  throw new MarketFetchError('io', 'invalid market cache state');
131
157
  }
132
- return { url, lastSequence: lastSequence as number, indexHash, signatureHash };
158
+ return { url, lastSequence: lastSequence as number, indexHash, signatureHash, ...(trustHash === undefined ? {} : { trustHash }) };
133
159
  }
134
160
 
135
161
  function digest(bytes: Uint8Array | string): string {
@@ -147,9 +173,21 @@ function checked(bytes: Uint8Array, signatureText: string, name: string, keys: R
147
173
  const marketIndexQueues = new Map<string, Promise<void>>();
148
174
 
149
175
  export function ensureMarketIndex(name: string, opts: MarketFetchOptions = {}): Promise<MarketIndex> {
150
- const directory = location(name, opts);
176
+ return queuedMarketIndex(name, opts);
177
+ }
178
+
179
+ /** Private indices require a configured market, a bound signing key and an explicitly allowed enterprise. */
180
+ export function ensureInternalMarketIndex(name: string, enterpriseId: string, opts: MarketFetchOptions = {}): Promise<MarketIndex> {
181
+ if (typeof enterpriseId !== 'string' || !enterpriseId.trim() || enterpriseId !== enterpriseId.trim()) {
182
+ return Promise.reject(new MarketFetchError('io', `enterprise not allowed for internal market: ${name}`));
183
+ }
184
+ return queuedMarketIndex(name, opts, enterpriseId);
185
+ }
186
+
187
+ function queuedMarketIndex(name: string, opts: MarketFetchOptions, enterpriseId?: string): Promise<MarketIndex> {
188
+ const directory = enterpriseId === undefined ? location(name, opts) : join(resolve(opts.marketDir ?? join(opts.root ?? elanousStateRoot(), 'markets')), '.internal', name, digest(enterpriseId));
151
189
  const previous = marketIndexQueues.get(directory) ?? Promise.resolve();
152
- const result = previous.then(() => fetchMarketIndex(name, opts));
190
+ const result = previous.then(() => fetchMarketIndex(name, opts, enterpriseId, directory));
153
191
  const tail = result.then(() => {}, () => {});
154
192
  marketIndexQueues.set(directory, tail);
155
193
  void tail.then(() => {
@@ -158,11 +196,25 @@ export function ensureMarketIndex(name: string, opts: MarketFetchOptions = {}):
158
196
  return result;
159
197
  }
160
198
 
161
- async function fetchMarketIndex(name: string, opts: MarketFetchOptions): Promise<MarketIndex> {
162
- const market = listMarkets(opts).find(entry => entry.name === name);
199
+ async function fetchMarketIndex(name: string, opts: MarketFetchOptions, enterpriseId: string | undefined, directory: string): Promise<MarketIndex> {
200
+ const settings = marketSettings(config(opts));
201
+ const market: MarketConfig | undefined = enterpriseId === undefined
202
+ ? [{ name: 'elanous', url: ELANOUS_MARKET_URL }, ...configuredMarkets(settings)].find(entry => entry.name === name)
203
+ : internalMarkets(settings).find(entry => entry.name === name);
163
204
  if (!market) throw new MarketFetchError('io', `market not configured: ${name}`);
164
- const keys = trust(marketSettings(config(opts)), opts);
165
- const directory = location(name, opts);
205
+ if (enterpriseId !== undefined && !market.enterpriseIds?.includes(enterpriseId)) {
206
+ throw new MarketFetchError('io', `enterprise not allowed for internal market: ${name}`);
207
+ }
208
+ const keys = enterpriseId === undefined ? trust(settings, opts) : market.trustedKeys!;
209
+ const verificationOptions = enterpriseId === undefined ? opts : { ...opts, verifySignature: verifyIndex };
210
+ const trustHash = enterpriseId === undefined ? undefined : digest(JSON.stringify(keys));
211
+ const authorized = (verified: ReturnType<typeof checked>): ReturnType<typeof checked> => {
212
+ if (enterpriseId !== undefined && [...(verified.index.knowledgePacks ?? []), ...(verified.index.loopBundles ?? [])]
213
+ .some(entry => entry.visibility !== 'internal' || entry.enterpriseId !== enterpriseId)) {
214
+ throw new MarketFetchError('io', `internal market contains entries outside enterprise allowlist: ${name}`);
215
+ }
216
+ return verified;
217
+ };
166
218
  const indexFile = join(directory, 'marketplace.json');
167
219
  const sigFile = join(directory, 'index.sig');
168
220
  const stateFile = join(directory, 'cache-state.json');
@@ -170,12 +222,12 @@ async function fetchMarketIndex(name: string, opts: MarketFetchOptions): Promise
170
222
  // The URL is part of the cache identity, not just the market name.
171
223
  const lastSequence = state?.url === market.url ? state.lastSequence : undefined;
172
224
  let cached: ReturnType<typeof checked> | undefined;
173
- if (state?.url === market.url && existsSync(indexFile) && existsSync(sigFile)) {
225
+ if (state?.url === market.url && (trustHash === undefined || state.trustHash === trustHash) && existsSync(indexFile) && existsSync(sigFile)) {
174
226
  const indexBytes = readFileSync(indexFile);
175
227
  const signatureText = readFileSync(sigFile, 'utf8');
176
228
  if (digest(indexBytes) === state.indexHash && digest(signatureText) === state.signatureHash) {
177
229
  try {
178
- cached = checked(indexBytes, signatureText, name, keys, opts, lastSequence);
230
+ cached = authorized(checked(indexBytes, signatureText, name, keys, verificationOptions, lastSequence));
179
231
  } catch (error) {
180
232
  if (!(error instanceof MarketFetchError)) throw error;
181
233
  }
@@ -216,13 +268,13 @@ async function fetchMarketIndex(name: string, opts: MarketFetchOptions): Promise
216
268
  };
217
269
  const bytes = await load('marketplace.json');
218
270
  const signature = new TextDecoder('utf-8', { fatal: true }).decode(await load('index.sig'));
219
- const verified = checked(bytes, signature, name, keys, opts, lastSequence);
271
+ const verified = authorized(checked(bytes, signature, name, keys, verificationOptions, lastSequence));
220
272
  mkdirSync(directory, { recursive: true });
221
273
  // Cross-process: another CLI may have published a newer index since we read cache-state. Re-check the high-water
222
274
  // mark under a file lock right before publishing, so a slower process cannot roll the cache back (review R3).
223
275
  return withFileLockSync(join(directory, '.publish.lock'), () => {
224
276
  const current = cacheState(stateFile);
225
- if (current?.url === market.url && current.lastSequence !== undefined && current.lastSequence > verified.index.sequence) {
277
+ if (current?.url === market.url && current.lastSequence > verified.index.sequence) {
226
278
  throw new MarketFetchError('signature', `market index rollback refused: ${name} sequence ${verified.index.sequence} < ${current.lastSequence}`);
227
279
  }
228
280
  const staging = mkdtempSync(join(directory, '.index-'));
@@ -232,7 +284,7 @@ async function fetchMarketIndex(name: string, opts: MarketFetchOptions): Promise
232
284
  const tempState = join(staging, 'cache-state.json');
233
285
  writeFileSync(tempIndex, bytes);
234
286
  writeFileSync(tempSig, signature);
235
- writeFileSync(tempState, JSON.stringify({ url: market.url, lastSequence: verified.index.sequence, indexHash: digest(bytes), signatureHash: digest(signature) } satisfies CacheState));
287
+ writeFileSync(tempState, JSON.stringify({ url: market.url, lastSequence: verified.index.sequence, indexHash: digest(bytes), signatureHash: digest(signature), ...(trustHash === undefined ? {} : { trustHash }) } satisfies CacheState));
236
288
  // Commit the verified high-water mark before replacing either cache file.
237
289
  // An interrupted publication then cannot roll back a previously verified index.
238
290
  renameSync(tempState, stateFile);
@@ -2,14 +2,16 @@ import { createHash, randomUUID } from 'node:crypto';
2
2
  import { spawnSync } from 'node:child_process';
3
3
  import { closeSync, cpSync, existsSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, writeFileSync } from 'node:fs';
4
4
  import { tmpdir } from 'node:os';
5
- import { basename, dirname, isAbsolute, join, resolve, sep } from 'node:path';
5
+ import { basename, dirname, isAbsolute, join, relative, resolve, sep } from 'node:path';
6
6
  import { dlopen, FFIType } from 'bun:ffi';
7
7
  import { loadPluginManifestFromDir, type PluginManifest } from '../core/manifest.js';
8
+ import { inspectPluginSecurity } from '../core/capability-policy.js';
9
+ import { decidePluginInstallation } from '../core/trust-store.js';
8
10
  import { loadPluginNodes } from '../../graph-kinds/plugin-nodes.js';
9
11
  import { getNodeKindRegistration, listNodeKinds, unregisterPluginNodeKind } from '../../graph-kinds/registry.js';
10
12
  import { verifyIndex, type MarketplaceIndex, type VerifyIndexResult } from '../../market/signed-index.js';
11
13
  import { elanousStateRoot } from '../../autopilot/state-paths.js';
12
- import { ensureMarketIndex, MarketFetchError, type MarketFetchOptions } from './market-fetch.js';
14
+ import { ensureInternalMarketIndex, ensureMarketIndex, MarketFetchError, type MarketFetchOptions } from './market-fetch.js';
13
15
 
14
16
  const NAME = /^[a-z0-9][a-z0-9-]{1,39}$/;
15
17
  const VERSION = /^[0-9]+\.[0-9]+\.[0-9]+(?:[-+][a-zA-Z0-9.-]+)?$/;
@@ -48,6 +50,8 @@ export interface InstallOptions {
48
50
  consent?: (capabilities: string[]) => boolean | Promise<boolean>;
49
51
  fetcher?: MarketFetchOptions['fetcher'];
50
52
  configPath?: string;
53
+ /** Enterprise context for knowledge packs in a private market. */
54
+ enterpriseId?: string;
51
55
  }
52
56
 
53
57
  export class PluginInstallError extends Error {
@@ -83,6 +87,53 @@ function safeTree(root: string): void {
83
87
  }
84
88
  }
85
89
 
90
+ function packPathExists(path: string): boolean {
91
+ try { lstatSync(path); return true; }
92
+ catch (error) {
93
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return false;
94
+ throw error;
95
+ }
96
+ }
97
+
98
+ /** Never follow a linked installation root or parent while reusing, moving or rolling back a package. */
99
+ function assertInstallParents(root: string, destination: string): void {
100
+ const parts = relative(root, dirname(destination)).split(sep).filter(Boolean);
101
+ if (parts.some(part => part === '..') || isAbsolute(relative(root, destination))) fail('io', `unsafe installation path: ${destination}`);
102
+ // macOS exposes system aliases such as /var -> /private/var; inspect the
103
+ // canonical path after that alias, without exempting any caller-owned parent.
104
+ const systemAlias = process.platform === 'darwin' && ['/var', '/tmp'].find(path => root === path || root.startsWith(`${path}${sep}`));
105
+ const checkedRoot = systemAlias ? resolve(realpathSync(systemAlias), relative(systemAlias, root)) : root;
106
+ const parents = [checkedRoot];
107
+ while (dirname(parents[0]!) !== parents[0]) parents.unshift(dirname(parents[0]!));
108
+ let parent = checkedRoot;
109
+ for (const part of parts) {
110
+ parent = join(parent, part);
111
+ parents.push(parent);
112
+ }
113
+ for (const path of parents) {
114
+ try {
115
+ const stat = lstatSync(path);
116
+ if (!stat.isDirectory() || stat.isSymbolicLink()) fail('io', `unsafe installation parent: ${path}`);
117
+ } catch (error) {
118
+ if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error;
119
+ }
120
+ }
121
+ }
122
+
123
+ /** Only an unchanged, ordinary extracted tree can satisfy the verified staged artifact. */
124
+ function samePackTree(existing: string, verified: string): boolean {
125
+ if (!lstatSync(existing).isDirectory()) return false;
126
+ const current = readdirSync(existing, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
127
+ const expected = readdirSync(verified, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name));
128
+ if (current.length !== expected.length) return false;
129
+ return current.every((entry, i) => {
130
+ const other = expected[i]!;
131
+ if (entry.name !== other.name || entry.isSymbolicLink() || other.isSymbolicLink()) return false;
132
+ if (entry.isDirectory() && other.isDirectory()) return samePackTree(join(existing, entry.name), join(verified, entry.name));
133
+ return entry.isFile() && other.isFile() && readFileSync(join(existing, entry.name)).equals(readFileSync(join(verified, entry.name)));
134
+ });
135
+ }
136
+
86
137
  function copyPlugin(source: string, destination: string): void {
87
138
  if (!existsSync(source) || !lstatSync(source).isDirectory()) fail('io', `plugin directory not found: ${source}`);
88
139
  safeTree(source);
@@ -189,21 +240,33 @@ async function fetchedMarketSource(spec: string, target: string, opts: InstallOp
189
240
  refresh: opts.refresh, verifySignature: opts.verifySignature, trustedKeys: opts.trustedKeys,
190
241
  });
191
242
  } catch (error) {
192
- if (error instanceof MarketFetchError && /^market not configured: /.test(error.message) && hasLocalMarketIndex(marketName, opts)) {
243
+ if (error instanceof MarketFetchError && /^market not configured: /.test(error.message) && opts.enterpriseId !== undefined) {
244
+ try {
245
+ marketIndex = await ensureInternalMarketIndex(marketName, opts.enterpriseId, {
246
+ root: opts.root, marketDir: opts.marketDir, configPath: opts.configPath, fetcher: opts.fetcher, refresh: opts.refresh,
247
+ });
248
+ } catch (internalError) {
249
+ if (internalError instanceof MarketFetchError) throw new PluginInstallError(internalError.reason, internalError.message);
250
+ throw internalError;
251
+ }
252
+ } else if (error instanceof MarketFetchError && /^market not configured: /.test(error.message) && hasLocalMarketIndex(marketName, opts)) {
193
253
  return localMarketSource(spec, target, opts);
194
- }
195
- if (error instanceof MarketFetchError) throw new PluginInstallError(error.reason, error.message);
196
- throw error;
254
+ } else if (error instanceof MarketFetchError) throw new PluginInstallError(error.reason, error.message);
255
+ else throw error;
197
256
  }
198
257
  const matches = marketIndex.index.plugins.filter(entry => entry.name === name);
199
258
  if (matches.length !== 1) fail('io', `plugin not found or ambiguous in ${marketName}: ${name}`);
200
259
  const entry = matches[0]!;
201
- const artifact = entry.artifact;
260
+ await fetchVerifiedArtifact(entry.artifact, marketIndex.market.url, target, opts);
261
+ return { market: marketName, sha256: entry.artifact.sha256, signature: marketIndex.signature, expectedName: name, expectedVersion: entry.version };
262
+ }
263
+
264
+ async function fetchVerifiedArtifact(artifact: MarketplaceIndex['plugins'][number]['artifact'], marketUrl: string, target: string, opts: InstallOptions): Promise<void> {
202
265
  if (!artifact || typeof artifact.key !== 'string' || !artifact.key || !HASH.test(artifact.sha256)
203
266
  || !Number.isSafeInteger(artifact.bytes) || artifact.bytes < 0) fail('io', 'invalid artifact key, hash or size');
204
267
  // Check the key as written, before URL resolution folds `..`/`.` or percent-encoded separators away.
205
268
  if (!/^[A-Za-z0-9._-]+(?:\/[A-Za-z0-9._-]+)*$/.test(artifact.key) || artifact.key.split('/').some(part => part === '.' || part === '..')) fail('io', 'unsafe artifact key');
206
- const base = new URL(marketIndex.market.url);
269
+ const base = new URL(marketUrl);
207
270
  const url = new URL(artifact.key, base);
208
271
  if (url.protocol !== 'https:' || url.origin !== base.origin || !url.pathname.startsWith(base.pathname)
209
272
  || url.username || url.password || url.search || url.hash || /[\\?#]/.test(artifact.key)) fail('io', 'unsafe artifact key');
@@ -235,7 +298,77 @@ async function fetchedMarketSource(spec: string, target: string, opts: InstallOp
235
298
  fail('scan', 'artifact sha256 or size mismatch');
236
299
  }
237
300
  unpackArchive(bytes, target);
238
- return { market: marketName, sha256: artifact.sha256, signature: marketIndex.signature, expectedName: name, expectedVersion: entry.version };
301
+ }
302
+
303
+ async function stageRequiredKnowledgePacks(names: string[], market: string, stage: string, root: string, opts: InstallOptions): Promise<Array<{ name: string; destination: string; staged: string }>> {
304
+ if (!names.length) return [];
305
+ if (market === 'local') fail('io', 'knowledge pack requires need a signed market');
306
+ const unique = [...new Set(names)];
307
+ if (unique.some(name => !NAME.test(name))) fail('io', 'invalid required knowledge pack name');
308
+ let index: MarketplaceIndex;
309
+ let url: string | undefined;
310
+ let directory: string | undefined;
311
+ let internalVerified = false;
312
+ try {
313
+ const options = { root, marketDir: opts.marketDir, configPath: opts.configPath, fetcher: opts.fetcher,
314
+ refresh: opts.refresh, verifySignature: opts.verifySignature, trustedKeys: opts.trustedKeys };
315
+ let result: Awaited<ReturnType<typeof ensureMarketIndex>>;
316
+ try { result = await ensureMarketIndex(market, options); }
317
+ catch (error) {
318
+ if (!(error instanceof MarketFetchError) || !/^market not configured: /.test(error.message) || opts.enterpriseId === undefined) throw error;
319
+ result = await ensureInternalMarketIndex(market, opts.enterpriseId, options);
320
+ internalVerified = true;
321
+ }
322
+ index = result.index;
323
+ url = result.market.url;
324
+ } catch (error) {
325
+ if (error instanceof MarketFetchError && /^market not configured: /.test(error.message) && hasLocalMarketIndex(market, opts)) {
326
+ const path = indexPath(market, opts);
327
+ directory = dirname(path);
328
+ const sig = join(directory, 'index.sig');
329
+ if (!existsSync(sig)) fail('signature', `missing index.sig: ${market}`);
330
+ const result = (opts.verifySignature ?? verifyIndex)({ marketplaceBytes: readFileSync(path), signatureText: readFileSync(sig, 'utf8'), trustedKeys: opts.trustedKeys ?? [] });
331
+ if (!result.ok) fail('signature', `${result.reason}: ${result.detail}`);
332
+ if (result.index.name !== market) fail('io', `market index name mismatch: ${market}`);
333
+ index = result.index;
334
+ } else if (error instanceof MarketFetchError) throw new PluginInstallError(error.reason, error.message);
335
+ else throw error;
336
+ }
337
+ const packs: Array<{ name: string; destination: string; staged: string }> = [];
338
+ for (const name of unique) {
339
+ const matches = (index.knowledgePacks ?? []).filter(entry => entry.name === name);
340
+ if (matches.length !== 1) fail('io', `required knowledge pack not found or ambiguous: ${name}`);
341
+ const entry = matches[0]!;
342
+ if (!VERSION.test(entry.version)) fail('io', `invalid required knowledge pack version: ${name}`);
343
+ if (entry.visibility === 'internal') {
344
+ if (!opts.enterpriseId || entry.enterpriseId !== opts.enterpriseId) fail('io', `knowledge pack not authorized: ${name}`);
345
+ if (!internalVerified) {
346
+ try {
347
+ const authorized = await ensureInternalMarketIndex(market, opts.enterpriseId, {
348
+ root, marketDir: opts.marketDir, configPath: opts.configPath, fetcher: opts.fetcher, refresh: opts.refresh,
349
+ });
350
+ if (!authorized.index.knowledgePacks?.some(pack => pack.name === name && pack.version === entry.version
351
+ && pack.artifact.sha256 === entry.artifact.sha256 && pack.artifact.bytes === entry.artifact.bytes
352
+ && pack.artifact.key === entry.artifact.key)) fail('io', `knowledge pack not authorized: ${name}`);
353
+ } catch (error) {
354
+ if (error instanceof MarketFetchError) throw new PluginInstallError(error.reason, error.message);
355
+ throw error;
356
+ }
357
+ }
358
+ }
359
+ const staged = join(stage, `knowledge-${packs.length}`);
360
+ if (directory) {
361
+ const artifactPath = inside(directory, entry.artifact.key);
362
+ if (!existsSync(artifactPath) || !realpathSync(artifactPath).startsWith(`${realpathSync(directory)}${sep}`)) fail('scan', `unsafe knowledge pack artifact: ${name}`);
363
+ const bytes = readFileSync(artifactPath);
364
+ if (bytes.length !== entry.artifact.bytes || (opts.hashArtifact ?? (data => createHash('sha256').update(data).digest('hex')))(bytes).toLowerCase() !== entry.artifact.sha256.toLowerCase()) fail('scan', 'artifact sha256 or size mismatch');
365
+ unpackArchive(bytes, staged);
366
+ } else {
367
+ await fetchVerifiedArtifact(entry.artifact, url!, staged, opts);
368
+ }
369
+ packs.push({ name, staged, destination: join(root, 'knowledge-packs', market, name, entry.version) });
370
+ }
371
+ return packs;
239
372
  }
240
373
 
241
374
  export function resolvePluginSource(spec: string, target: string, opts: InstallOptions = {}): ResolvedPluginSource {
@@ -308,7 +441,9 @@ function declaresMain(packageRoot: string): boolean {
308
441
  export async function installPlugin(spec: string, opts: InstallOptions = {}): Promise<InstalledPlugin> {
309
442
  const root = resolve(opts.root ?? elanousStateRoot());
310
443
  const stageRoot = join(root, 'plugins', '.staging');
444
+ assertInstallParents(root, join(stageRoot, 'plugin'));
311
445
  mkdirSync(stageRoot, { recursive: true });
446
+ assertInstallParents(root, join(stageRoot, 'plugin'));
312
447
  const stage = mkdtempSync(join(stageRoot, 'plugin-'));
313
448
  try {
314
449
  const source = marketSpec(spec, opts)
@@ -348,11 +483,20 @@ export async function installPlugin(spec: string, opts: InstallOptions = {}): Pr
348
483
  const destination = join(root, 'plugins', source.market, name, version);
349
484
  const emit = (event: InstallEvent) => opts.onEvent?.(event);
350
485
  emit({ event: 'resolve', plugin: name, version, sha256: source.sha256 });
351
- emit({ event: 'verify', signature: source.signature, scan: 'safe' });
486
+ let security: ReturnType<typeof inspectPluginSecurity>;
487
+ try { security = inspectPluginSecurity(packageRoot); }
488
+ catch { fail('scan', 'plugin static security scan failed'); }
489
+ emit({ event: 'verify', signature: source.signature, scan: security.scan });
352
490
  const capabilities = manifest.capabilities.map(capability => capability.kind);
353
491
  const required = capabilities.length > 0;
492
+ const preConsent = decidePluginInstallation(security, capabilities, false);
493
+ if (!preConsent.ok && preConsent.reason === 'scan') fail('scan', 'plugin static security scan rejected package');
354
494
  emit({ event: 'consent', capabilities, required });
355
- if (required && !(opts.yes || await opts.consent?.(capabilities))) fail('consent-denied', 'plugin capabilities require consent');
495
+ const consented = !required || !!(opts.yes || await opts.consent?.(capabilities));
496
+ const decision = decidePluginInstallation(security, capabilities, consented);
497
+ if (!decision.ok) fail(decision.reason, decision.reason === 'scan'
498
+ ? 'plugin static security scan rejected package' : 'plugin capabilities require consent');
499
+ const packs = await stageRequiredKnowledgePacks(manifest.requires?.knowledgePacks ?? [], source.market, stage, root, opts);
356
500
  emit({ event: 'credentials', connectors: (manifest.contributes.connectors ?? []).map(connector => ({
357
501
  id: connector.id, fields: (connector.fields ?? connector.userConfig?.map(field => ({ name: field.key, secret: field.secret })) ?? [])
358
502
  .map(field => ({ name: field.name, secret: field.secret === true })),
@@ -370,17 +514,44 @@ export async function installPlugin(spec: string, opts: InstallOptions = {}): Pr
370
514
  const { nodes, nodeErrors } = inspectPluginNodes(packageRoot, manifest);
371
515
  emit({ event: 'registered', kinds, nodes, nodeErrors, graphs, skills });
372
516
  const installed = withLedgerLock(root, () => {
517
+ assertInstallParents(root, destination);
373
518
  if (existsSync(destination)) fail('conflict', `plugin already installed: ${name}@${version}`);
374
- mkdirSync(dirname(destination), { recursive: true });
375
- renameSync(join(stage, 'package'), destination);
376
- const item = { name, version, market: source.market, path: destination, sha256: source.sha256, installedAt: new Date().toISOString() };
519
+ for (const pack of packs) {
520
+ assertInstallParents(root, pack.destination);
521
+ if (packPathExists(pack.destination) && !samePackTree(pack.destination, pack.staged)) {
522
+ fail('conflict', `installed knowledge pack differs from verified artifact: ${pack.name}`);
523
+ }
524
+ }
525
+ const moved: string[] = [];
377
526
  try {
527
+ for (const pack of packs) {
528
+ assertInstallParents(root, pack.destination);
529
+ if (packPathExists(pack.destination)) continue;
530
+ mkdirSync(dirname(pack.destination), { recursive: true });
531
+ assertInstallParents(root, pack.destination);
532
+ renameSync(pack.staged, pack.destination);
533
+ moved.push(pack.destination);
534
+ }
535
+ mkdirSync(dirname(destination), { recursive: true });
536
+ assertInstallParents(root, destination);
537
+ renameSync(join(stage, 'package'), destination);
538
+ moved.push(destination);
539
+ const item = { name, version, market: source.market, path: destination, sha256: source.sha256, installedAt: new Date().toISOString() };
540
+ let installedSecurity: ReturnType<typeof inspectPluginSecurity>;
541
+ try { installedSecurity = inspectPluginSecurity(destination); }
542
+ catch { fail('scan', 'plugin package integrity verification failed'); }
543
+ if (installedSecurity.integrity !== security.integrity || installedSecurity.scan === 'dangerous') {
544
+ fail('scan', 'plugin package integrity changed during installation');
545
+ }
378
546
  writeLedger(root, [...listInstalledPlugins(root), item]);
547
+ return item;
379
548
  } catch (error) {
380
- rmSync(destination, { recursive: true, force: true });
549
+ for (const path of moved.reverse()) {
550
+ assertInstallParents(root, path);
551
+ rmSync(path, { recursive: true, force: true });
552
+ }
381
553
  throw error;
382
554
  }
383
- return item;
384
555
  });
385
556
  // The install is committed above; a listener that throws must not turn a finished install into a failure
386
557
  // (the ledger would say «installed» while the caller saw «io», and a retry would hit «conflict»).
@@ -10,6 +10,7 @@ import { dispatchOmniSearch } from '../../skills/tools/omni-search.js';
10
10
  import { runGraph } from '../../graph-runner/runner.js';
11
11
  import { parseGraphTemplateYaml } from '../../self-implement/graph-yaml.js';
12
12
  import { installPlugin } from '../install/plugin-install.js';
13
+ import { inspectPluginSecurity } from '../core/capability-policy.js';
13
14
  import { generateWizardFiles, type WizardResearchDraft } from './wizard-generate.js';
14
15
  import { bundleInstalledWizardPlugin, type MarketBundleResult } from './market-bundle.js';
15
16
 
@@ -127,7 +128,7 @@ export async function validatePluginDir(dir: string): Promise<string[]> {
127
128
  if (lstatSync(file).isSymbolicLink()) errors.push('안전하지 않은 plugin.json 링크');
128
129
  else manifest = JSON.parse(readFileSync(file, 'utf8'));
129
130
  }
130
- catch (error) { errors.push(`plugin.json 파싱 실패: ${String(error)}`); }
131
+ catch { errors.push('plugin.json 파싱 실패'); }
131
132
  const extension = isRecord(manifest) && isRecord(manifest.extensions) ? manifest.extensions['ai.elanous'] : undefined;
132
133
  const graphs = isRecord(extension) ? extension.graphs : undefined;
133
134
  if (isRecord(extension) && extension.contributes !== undefined) errors.push('extension contributes 덮어쓰기 금지');
@@ -143,69 +144,73 @@ export async function validatePluginDir(dir: string): Promise<string[]> {
143
144
  if (lstatSync(file).isSymbolicLink()) errors.push('안전하지 않은 recipes.yaml 링크');
144
145
  else recipes = parseYaml(readFileSync(file, 'utf8'));
145
146
  }
146
- catch (error) { errors.push(`recipes.yaml 파싱 실패: ${String(error)}`); }
147
+ catch { errors.push('recipes.yaml 파싱 실패'); }
147
148
  if (!isRecord(recipes)) errors.push('recipes.yaml 은 맵이어야 한다');
148
149
  else for (const [id, recipe] of Object.entries(recipes)) {
149
150
  if (!isRecord(recipe) ||
150
151
  (!(typeof recipe.command === 'string' && recipe.command.trim()) && !(typeof recipe.approval === 'string' && recipe.approval.trim())) ||
151
152
  (recipe.command !== undefined && (typeof recipe.command !== 'string' || !recipe.command.trim())) ||
152
153
  (recipe.approval !== undefined && (typeof recipe.approval !== 'string' || !recipe.approval.trim())) ||
153
- (recipe.timeout_ms !== undefined && (!Number.isSafeInteger(recipe.timeout_ms) || Number(recipe.timeout_ms) <= 0))) errors.push(`잘못된 recipe: ${id}`);
154
+ (recipe.timeout_ms !== undefined && (!Number.isSafeInteger(recipe.timeout_ms) || Number(recipe.timeout_ms) <= 0))) errors.push(`잘못된 recipe: ${/^[a-zA-Z0-9_-]+$/.test(id) ? id : 'invalid'}`);
154
155
  }
155
156
  for (const graph of Array.isArray(graphs) ? graphs : []) {
156
157
  if (typeof graph !== 'string') continue;
157
158
  const file = inside(dir, graph);
158
- if (!file || !/^\.\/graphs\/[a-zA-Z0-9_-]+\.ya?ml$/.test(graph)) { errors.push(`안전하지 않은 graph 경로: ${graph}`); continue; }
159
+ if (!file || !/^\.\/graphs\/[a-zA-Z0-9_-]+\.ya?ml$/.test(graph)) { errors.push('안전하지 않은 graph 경로'); continue; }
159
160
  try {
160
- if (lstatSync(file).isSymbolicLink()) { errors.push(`안전하지 않은 graph 링크: ${graph}`); continue; }
161
+ if (lstatSync(file).isSymbolicLink()) { errors.push('안전하지 않은 graph 링크'); continue; }
161
162
  const parsed = parseGraphTemplateYaml(readFileSync(file, 'utf8'), file);
162
- errors.push(...parsed.errors.map(issue => `${issue.path}: ${issue.message}`));
163
+ errors.push(...parsed.errors.map(() => 'graph 정의 오류'));
163
164
  const template = parsed.template;
164
165
  if (!template) continue;
165
- if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(template.graphId)) errors.push(`잘못된 graph_id: ${template.graphId}`);
166
+ if (!/^[A-Za-z0-9][A-Za-z0-9._-]*$/.test(template.graphId)) errors.push('잘못된 graph_id');
166
167
  if (template.terminalNodes.length !== 2 || !template.terminalNodes.includes('done') || !template.terminalNodes.includes('failed')) errors.push('terminal_nodes 는 done, failed 이어야 한다');
167
168
  const executionNodes = template.nodes.filter(node => !template.terminalNodes.includes(node.nodeId));
168
169
  if (executionNodes.length < 2) errors.push(`실행 노드는 2개 이상이어야 한다: ${executionNodes.length}개`);
169
170
  for (const node of template.nodes) {
170
171
  if (node.recipe.startsWith('cmd:')) {
171
172
  const id = node.recipe.slice(4);
172
- if (!isRecord(recipes) || !isRecord(recipes[id]) || recipes[id].approval !== undefined || typeof recipes[id].command !== 'string' || !recipes[id].command.trim()) errors.push(`recipe ${id} 없음`);
173
+ if (!isRecord(recipes) || !isRecord(recipes[id]) || recipes[id].approval !== undefined || typeof recipes[id].command !== 'string' || !recipes[id].command.trim()) errors.push(`recipe ${/^[a-zA-Z0-9_-]+$/.test(id) ? id : 'invalid'} 없음`);
173
174
  } else if (node.recipe.startsWith('approval:')) {
174
175
  const id = node.recipe.slice(9);
175
- if (!isRecord(recipes) || !isRecord(recipes[id]) || typeof recipes[id].approval !== 'string' || !recipes[id].approval.trim()) errors.push(`approval recipe ${id} 없음`);
176
- } else if (node.recipe !== 'none') errors.push(`지원하지 않는 recipe: ${node.recipe}`);
176
+ if (!isRecord(recipes) || !isRecord(recipes[id]) || typeof recipes[id].approval !== 'string' || !recipes[id].approval.trim()) errors.push(`approval recipe ${/^[a-zA-Z0-9_-]+$/.test(id) ? id : 'invalid'} 없음`);
177
+ } else if (node.recipe !== 'none') errors.push(`지원하지 않는 recipe: ${/^[a-zA-Z0-9_:-]+$/.test(node.recipe) ? node.recipe : 'invalid'}`);
177
178
  }
178
- } catch (error) { errors.push(`${graph} 파싱 실패: ${String(error)}`); }
179
+ } catch { errors.push('graph 파싱 실패'); }
179
180
  }
180
181
  const visit = (path: string): void => {
181
182
  for (const entry of readdirSync(path, { withFileTypes: true })) {
182
183
  const file = join(path, entry.name);
183
- if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile())) { errors.push(`안전하지 않은 파일: ${file}`); continue; }
184
+ if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile())) { errors.push('안전하지 않은 파일'); continue; }
184
185
  if (entry.isDirectory()) visit(file);
185
186
  else if (/\.[cm]?[jt]sx?$/.test(entry.name)) {
186
187
  const source = readFileSync(file, 'utf8');
187
188
  for (const match of source.matchAll(/\b(?:import|export)\s*(?:[\s\S]*?\s+from\s*)?["']([^"']+)["']|\b(?:import|require)\s*\(\s*["']([^"']+)["']/g)) {
188
189
  const target = match[1] ?? match[2]!;
189
- if (/(?:^|\/)src\//.test(target) && (target.startsWith('/') || target.startsWith('.'))) errors.push(`src import 금지: ${file}: ${target}`);
190
+ if (/(?:^|\/)src\//.test(target) && (target.startsWith('/') || target.startsWith('.'))) errors.push('src import 금지');
190
191
  }
191
192
  }
192
193
  }
193
194
  };
194
- try { visit(dir); } catch (error) { errors.push(`파일 검사 실패: ${String(error)}`); }
195
+ try { visit(dir); } catch { errors.push('파일 검사 실패'); }
195
196
  try {
196
197
  const example = join(dir, 'examples', 'input.json');
197
198
  if (lstatSync(example).isSymbolicLink()) errors.push('안전하지 않은 examples/input.json 링크');
198
199
  else JSON.parse(readFileSync(example, 'utf8'));
199
- } catch (error) { errors.push(`examples/input.json 파싱 실패: ${String(error)}`); }
200
+ } catch { errors.push('examples/input.json 파싱 실패'); }
201
+ let security: ReturnType<typeof inspectPluginSecurity>;
202
+ try { security = inspectPluginSecurity(dir); }
203
+ catch { errors.push('보안 검사 실패'); return errors; }
204
+ if (security.scan === 'dangerous') errors.push(...security.findings.filter(f => f.level === 'dangerous').map(f => `보안 검사 차단: ${f.code}`));
200
205
  const step = join(dir, 'graphs', 'run-step.ts');
201
206
  try {
202
207
  if (!existsSync(step)) errors.push('run-step.ts 없음');
203
- else if (errors.some(error => error.startsWith('안전하지 않은 파일:'))) return errors;
208
+ else if (errors.some(error => error.startsWith('안전하지 않은 파일'))) return errors;
204
209
  else {
205
210
  const build = await Bun.build({ entrypoints: [step], target: 'bun' });
206
- if (!build.success) errors.push(...build.logs.map(log => `run-step.ts 문법 오류: ${log.message}`));
211
+ if (!build.success) errors.push('run-step.ts 문법 오류');
207
212
  }
208
- } catch (error) { errors.push(`run-step.ts 문법 오류: ${String(error)}`); }
213
+ } catch { errors.push('run-step.ts 문법 오류'); }
209
214
  return errors;
210
215
  }
211
216
 
@@ -359,7 +364,7 @@ export async function makePlugin({ request, draftFile, name, parentDir, run, mar
359
364
  const step = async (stage: keyof MakePluginResult['timings'], action: () => void | Promise<void>): Promise<void> => {
360
365
  const start = performance.now();
361
366
  try { await action(); }
362
- finally { const ms = Math.round(performance.now() - start); timings[stage] = ms; debug.log('plugin.maker', stage, { ms, errors: result.errors }); }
367
+ finally { const ms = Math.round(performance.now() - start); timings[stage] = ms; debug.log('plugin.maker', stage, { ms, errors: redactSecrets(result.errors) }); }
363
368
  };
364
369
  try {
365
370
  emit('request', request);
@@ -461,7 +466,7 @@ export async function makePlugin({ request, draftFile, name, parentDir, run, mar
461
466
  }
462
467
  } catch (error) {
463
468
  result.status = 'failed';
464
- result.errors.push(error instanceof Error ? error.message : String(error));
469
+ result.errors.push(redactSecretText(error instanceof Error ? error.message : String(error)));
465
470
  } finally {
466
471
  emit('done', result.status, { errors: result.errors });
467
472
  }
@@ -10,6 +10,7 @@ export interface WizardResearchDraft {
10
10
  credentials?: Array<{ name: string }>;
11
11
  }>;
12
12
  skill?: { description: string; instructions: string; requires?: string[] };
13
+ requires?: { knowledgePacks?: string[] };
13
14
  }
14
15
 
15
16
  const SLUG = /^[a-z0-9][a-z0-9-]{1,31}$/;
@@ -46,9 +47,16 @@ export function generateWizardFiles(dir: string, slug: string, draft: WizardRese
46
47
  if (!Array.isArray(requires) || requires.some(resource => typeof resource !== 'string' || !knownResources.has(resource))) {
47
48
  throw new Error('wizard requires must reference existing resource ids');
48
49
  }
50
+ if (draft.requires !== undefined && (!draft.requires || typeof draft.requires !== 'object' || Array.isArray(draft.requires) ||
51
+ Object.keys(draft.requires).some(key => key !== 'knowledgePacks') ||
52
+ (draft.requires.knowledgePacks !== undefined && (!Array.isArray(draft.requires.knowledgePacks) ||
53
+ draft.requires.knowledgePacks.some(pack => typeof pack !== 'string' || !pack.trim()))))) {
54
+ throw new Error('wizard knowledge packs must be non-empty names');
55
+ }
49
56
  const manifestPath = join(dir, 'plugin.json');
50
57
  const existing = existsSync(manifestPath) ? JSON.parse(readFileSync(manifestPath, 'utf8')) as {
51
- name: string; description?: string; extensions: { 'ai.elanous': { connectors?: unknown[]; graphs?: string[]; researchDraft?: boolean } };
58
+ name: string; description?: string; requires?: { knowledgePacks?: string[]; [key: string]: unknown };
59
+ extensions: { 'ai.elanous': { connectors?: unknown[]; graphs?: string[]; researchDraft?: boolean } };
52
60
  } : undefined;
53
61
  if (existing && (existing.name !== slug || !existing.extensions?.['ai.elanous'])) {
54
62
  throw new Error('wizard scaffold name or extension mismatch');
@@ -69,9 +77,13 @@ export function generateWizardFiles(dir: string, slug: string, draft: WizardRese
69
77
  throw new Error('wizard cannot replace existing scaffold connectors');
70
78
  }
71
79
  const manifest = existing ?? { name: slug, version: '0.1.0', description: draft.description,
80
+ requires: undefined as { knowledgePacks?: string[]; [key: string]: unknown } | undefined,
72
81
  extensions: { 'ai.elanous': { graphs: [`./graphs/${slug}.yaml`],
73
82
  capabilities: ['fs:workdir', 'proc:bun', 'proc:elanous'], connectors: [] as unknown[], researchDraft: true } } };
74
83
  if (options.regenerate) manifest.description = draft.description;
84
+ if (draft.requires?.knowledgePacks !== undefined) {
85
+ manifest.requires = { ...manifest.requires, knowledgePacks: [...new Set(draft.requires.knowledgePacks)] };
86
+ }
75
87
  manifest.extensions['ai.elanous'].connectors = connectors;
76
88
  manifest.extensions['ai.elanous'].researchDraft = true;
77
89
 
@@ -125,7 +137,8 @@ export function listWizardDrafts(parent: string): Array<{ name: string; descript
125
137
  const skillPath = join(skillDir, 'SKILL.md');
126
138
  if (lstatSync(manifestPath).isSymbolicLink() || lstatSync(skillDir).isSymbolicLink() || lstatSync(skillPath).isSymbolicLink()) return [];
127
139
  const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as {
128
- name?: string; description?: string; extensions?: { 'ai.elanous'?: { researchDraft?: boolean; connectors?: Array<{ id: string; fields: Array<{ name: string }> }> } } };
140
+ name?: string; description?: string; requires?: { knowledgePacks?: string[] };
141
+ extensions?: { 'ai.elanous'?: { researchDraft?: boolean; connectors?: Array<{ id: string; fields: Array<{ name: string }> }> } } };
129
142
  if (manifest.name !== entry.name || manifest.extensions?.['ai.elanous']?.researchDraft !== true) return [];
130
143
  const skill = readFileSync(skillPath, 'utf8');
131
144
  const parts = /^---\n([\s\S]*?)---\n\n([\s\S]*)$/.exec(skill);
@@ -134,6 +147,7 @@ export function listWizardDrafts(parent: string): Array<{ name: string; descript
134
147
  return [{ name: entry.name, description: manifest.description, draft: {
135
148
  description: manifest.description,
136
149
  connectors: manifest.extensions['ai.elanous'].connectors?.map(connector => ({ id: connector.id, credentials: connector.fields.map(field => ({ name: field.name })) })) ?? [],
150
+ ...(manifest.requires?.knowledgePacks !== undefined ? { requires: { knowledgePacks: manifest.requires.knowledgePacks } } : {}),
137
151
  skill: { description: meta.description ?? manifest.description, instructions: parts[2]!.trimEnd(), requires: meta.requires ?? [] },
138
152
  } }];
139
153
  } catch { return []; }