elanous 0.2.21 → 0.2.23

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (780) hide show
  1. package/NOTICE +7 -0
  2. package/README.md +32 -22
  3. package/apps/pwa/out/404/index.html +1 -1
  4. package/apps/pwa/out/404.html +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{119fc678.6f591cdb84ca5791.js → 0673cc54.8e2ef1c23e49e190.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{a9f2b54d-40c16bd0efdb04b8.js → 0a09e062-34f747a17d8d8c2e.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/{f8626309.a4e5d362b1d55e59.js → 0e3acd34.d42b2ef87fdf4234.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +77 -0
  9. package/apps/pwa/out/_next/static/chunks/{7175-350f4ce2873bc038.js → 1325-dc3f3c21eb181cb4.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +34 -0
  11. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +24 -0
  12. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/{6767.8e6c5f6e744fcd9f.js → 1505.5826671109111e75.js} +2 -2
  14. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/{7327-2d69fb321ba73389.js → 1669-da843ed73aa301f5.js} +1 -1
  21. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +36 -0
  23. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +122 -0
  24. package/apps/pwa/out/_next/static/chunks/2528.0af5c0e1fad88df6.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +62 -0
  27. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/272-b23d2e92161d11fd.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/{7899.597af4a9996c907f.js → 2721.bc9a8f36bd85c07a.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +149 -0
  35. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3961-fbef064c213b2b18.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +309 -0
  39. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{d70879db.c66c56a95a91efc6.js → 4c5e95ce.83e9b16add6fcd8c.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/{6158.566c890adc06a459.js → 5313.1697309c532b9856.js} +2 -2
  52. package/apps/pwa/out/_next/static/chunks/{79b78388.663188133449d707.js → 53746282.1be36038d1abd949.js} +1 -1
  53. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5578.ac963634373b28c6.js +286 -0
  56. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5967-c0a80f8ffe5d4050.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/{1268.0840ff91e083fcbd.js → 5974.360f8441eb0ac1ec.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +74 -0
  64. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6571-926ddf024a6ad5df.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +64 -0
  69. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{9832.2ab2e818013574c7.js → 6702.ebbd165d5e4a4a14.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +32 -0
  73. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +24 -0
  74. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +93 -0
  78. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6110.1297d4093fdfbb0d.js → 740.90b31555290236a9.js} +2 -2
  83. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +148 -0
  84. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +226 -0
  85. package/apps/pwa/out/_next/static/chunks/{9070.067c106528ec1ae6.js → 7518.49161e8f5814abdb.js} +1 -1
  86. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +27 -0
  87. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +115 -0
  90. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7905.b230b9d06cb4ad5d.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{8194.484f51e273d9abd2.js → 8264.00e434fbd02e9311.js} +16 -16
  97. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +8 -0
  99. package/apps/pwa/out/_next/static/chunks/{088d8e8a.8069543d082bec12.js → 83cfc5c8.349535543c1548b6.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +23 -0
  101. package/apps/pwa/out/_next/static/chunks/{1948.5f35b39eef222a94.js → 8438.ee7f0df3b3f6fcb4.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/{4588.ad3364cb7fb97ada.js → 8532.a86e99acf9b761cb.js} +2 -2
  105. package/apps/pwa/out/_next/static/chunks/8569.b853a8daa8f31d12.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8925-2abfb48af477fb7f.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{88729267.9c6c000157c83f2f.js → 89849432.9eaa2f4c9c010965.js} +3 -3
  110. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +90 -0
  111. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +94 -0
  112. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +41 -0
  114. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +287 -0
  116. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +79 -0
  117. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{3522-1de1319d028ac89c.js → 9502-32c5dc22e8f120f5.js} +3 -3
  120. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +104 -0
  123. package/apps/pwa/out/_next/static/chunks/{7630.2b9a68659053ff4e.js → 9976.8f28864317639fe6.js} +16 -16
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d5341ac96203a983.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-0160ab83c8685a12.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-55c631c032dcc47e.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ad3bd8084048bee4.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-e6784759a2531031.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5c5d0e370f495ef6.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-c325e21543cd48a8.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/{page-111cabe4d1fd69ae.js → page-6168a7c43e6ef8f5.js} +1 -1
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-31417d3604154a6d.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-e9606dc0bdec9305.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-a648bc464c9dc754.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25bb425afdb27541.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-32d72fdef1afe11a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-d27b794c8ba76bbb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-2bd9ce9c020d02d4.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a34096245e63b9f2.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-22170f4f00a15496.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-4cc66d22ca4ec502.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83b14c729fcea837.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-6e2781c523dad761.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-26dd415c8f13f341.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-ccdb83ed40c8d724.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-7ad3de8fa06fdea9.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-015c02c4fec4023e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-6b0ae5b5c42f6d2f.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-786111f30b6f0969.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-48fb31810693c357.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e17cce5e2ed0fee.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-cb154acadb025414.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-16258e956ea93fc2.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-c2dd2b19c93f90ab.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-85f35dd1dd96ae87.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d3c007c8a0ddd7ee.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-7837ce2aacb97b04.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-7350ee93f4fe1033.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-00723458575f2b19.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-745d9b6c015076f8.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-736d33c7414a8a1a.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-119be9a0444d2482.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-fa806c018833e332.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-c782041b5f5199ba.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-d431fbdea6ad93dd.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-0c056abff82b9891.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-242d668e4fbf72c4.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-847c3de6ca8a4416.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-81dd0d8ae923ed72.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-74e69ba2c8e970d4.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-70038f41ae7cf931.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/b4e12462-5fab4a813a63dadd.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{f6b7c9ba.64a895b8b2fedbdc.js → ce383d63.d2ede338788ed18e.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{framework-5c169757551134ed.js → framework-b2763b10dc6b3836.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +1 -0
  184. package/apps/pwa/out/_next/static/css/5619d59e87eddf66.css +1 -0
  185. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +1 -0
  186. package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_buildManifest.js +1 -1
  187. package/apps/pwa/out/approvals/index.html +1 -1
  188. package/apps/pwa/out/approvals/index.txt +23 -23
  189. package/apps/pwa/out/autopilot/index.html +1 -1
  190. package/apps/pwa/out/autopilot/index.txt +23 -23
  191. package/apps/pwa/out/board/index.html +1 -1
  192. package/apps/pwa/out/board/index.txt +23 -23
  193. package/apps/pwa/out/botlab/index.html +1 -1
  194. package/apps/pwa/out/botlab/index.txt +22 -22
  195. package/apps/pwa/out/bots/index.html +1 -1
  196. package/apps/pwa/out/bots/index.txt +22 -22
  197. package/apps/pwa/out/ceo/index.html +1 -1
  198. package/apps/pwa/out/ceo/index.txt +23 -23
  199. package/apps/pwa/out/chat/index.html +1 -1
  200. package/apps/pwa/out/chat/index.txt +22 -22
  201. package/apps/pwa/out/consult/index.html +1 -1
  202. package/apps/pwa/out/consult/index.txt +23 -23
  203. package/apps/pwa/out/control/index.html +1 -1
  204. package/apps/pwa/out/control/index.txt +23 -23
  205. package/apps/pwa/out/decisions/index.html +1 -1
  206. package/apps/pwa/out/decisions/index.txt +22 -22
  207. package/apps/pwa/out/design-check/index.html +1 -1
  208. package/apps/pwa/out/design-check/index.txt +23 -23
  209. package/apps/pwa/out/editor/index.html +1 -1
  210. package/apps/pwa/out/editor/index.txt +24 -23
  211. package/apps/pwa/out/exec/index.html +1 -1
  212. package/apps/pwa/out/exec/index.txt +23 -23
  213. package/apps/pwa/out/field/index.html +1 -1
  214. package/apps/pwa/out/field/index.txt +23 -23
  215. package/apps/pwa/out/healthz +1 -1
  216. package/apps/pwa/out/index.html +1 -1
  217. package/apps/pwa/out/index.txt +22 -22
  218. package/apps/pwa/out/inside/index.html +1 -1
  219. package/apps/pwa/out/inside/index.txt +22 -22
  220. package/apps/pwa/out/intake/index.html +1 -1
  221. package/apps/pwa/out/intake/index.txt +23 -23
  222. package/apps/pwa/out/live/index.html +1 -1
  223. package/apps/pwa/out/live/index.txt +23 -23
  224. package/apps/pwa/out/live-run/index.html +1 -1
  225. package/apps/pwa/out/live-run/index.txt +24 -23
  226. package/apps/pwa/out/loops/index.html +1 -1
  227. package/apps/pwa/out/loops/index.txt +22 -22
  228. package/apps/pwa/out/market/index.html +1 -1
  229. package/apps/pwa/out/market/index.txt +22 -22
  230. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  231. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  232. package/apps/pwa/out/morning/index.html +1 -1
  233. package/apps/pwa/out/morning/index.txt +23 -23
  234. package/apps/pwa/out/observatory/index.html +1 -1
  235. package/apps/pwa/out/observatory/index.txt +23 -23
  236. package/apps/pwa/out/ops/checklist/index.html +1 -1
  237. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  238. package/apps/pwa/out/ops/release/index.html +1 -1
  239. package/apps/pwa/out/ops/release/index.txt +22 -22
  240. package/apps/pwa/out/ops/seats/index.html +1 -1
  241. package/apps/pwa/out/ops/seats/index.txt +22 -22
  242. package/apps/pwa/out/outputs/index.html +1 -1
  243. package/apps/pwa/out/outputs/index.txt +22 -22
  244. package/apps/pwa/out/reflection/index.html +1 -1
  245. package/apps/pwa/out/reflection/index.txt +23 -23
  246. package/apps/pwa/out/scheduler/index.html +1 -1
  247. package/apps/pwa/out/scheduler/index.txt +23 -23
  248. package/apps/pwa/out/sessions/index.html +1 -1
  249. package/apps/pwa/out/sessions/index.txt +22 -22
  250. package/apps/pwa/out/settings/devices/index.html +1 -1
  251. package/apps/pwa/out/settings/devices/index.txt +23 -23
  252. package/apps/pwa/out/settings/index.html +1 -1
  253. package/apps/pwa/out/settings/index.txt +23 -23
  254. package/apps/pwa/out/setup/done/index.html +1 -1
  255. package/apps/pwa/out/setup/done/index.txt +23 -23
  256. package/apps/pwa/out/setup/index.html +1 -1
  257. package/apps/pwa/out/setup/index.txt +23 -23
  258. package/apps/pwa/out/share/index.html +1 -1
  259. package/apps/pwa/out/share/index.txt +23 -23
  260. package/apps/pwa/out/showroom/index.html +1 -1
  261. package/apps/pwa/out/showroom/index.txt +22 -22
  262. package/apps/pwa/out/tasks/index.html +1 -1
  263. package/apps/pwa/out/tasks/index.txt +23 -23
  264. package/apps/pwa/out/term/index.html +1 -1
  265. package/apps/pwa/out/term/index.txt +23 -23
  266. package/apps/pwa/out/today/index.html +1 -1
  267. package/apps/pwa/out/today/index.txt +23 -23
  268. package/apps/pwa/out/trace/index.html +1 -1
  269. package/apps/pwa/out/trace/index.txt +23 -23
  270. package/apps/pwa/out/vault/index.html +1 -1
  271. package/apps/pwa/out/vault/index.txt +23 -23
  272. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  273. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  274. package/apps/pwa/out/workflows/index.html +1 -1
  275. package/apps/pwa/out/workflows/index.txt +23 -23
  276. package/apps/pwa/out/workspace/index.html +1 -1
  277. package/apps/pwa/out/workspace/index.txt +23 -23
  278. package/apps/pwa/out/worktrees/index.html +1 -1
  279. package/apps/pwa/out/worktrees/index.txt +23 -23
  280. package/catalog/models/anthropic/claude-haiku-5-5.yaml +32 -0
  281. package/catalog/models/anthropic/claude-opus-5-5.yaml +5 -0
  282. package/catalog/models/anthropic/claude-sonnet-5-5.yaml +31 -0
  283. package/catalog/models/anthropic/claude-sonnet-5.yaml +8 -2
  284. package/catalog/models/openai/gpt-6-astra.yaml +6 -0
  285. package/catalog/models/openai/gpt-6-luna.yaml +6 -0
  286. package/catalog/models/openai/gpt-6-sol.yaml +6 -0
  287. package/graphs/catalog/catalog.yaml +1 -1
  288. package/graphs/drafts/recipes.yaml +2 -2
  289. package/graphs/log-horizon/log-horizon-watch.yaml +25 -0
  290. package/graphs/log-horizon/recipes.yaml +3 -0
  291. package/graphs/release/recipes.yaml +1 -1
  292. package/graphs/release/release-loop.yaml +6 -2
  293. package/graphs/release-rehearsal/recipes.yaml +12 -0
  294. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  295. package/graphs/test-diet/recipes.yaml +3 -0
  296. package/graphs/test-diet/test-diet.yaml +3 -1
  297. package/package.json +4 -1
  298. package/scripts/bench-report.ts +82 -3
  299. package/scripts/ci-typecheck-changed.ts +10 -1
  300. package/scripts/f-session-monitor.ts +69 -0
  301. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  302. package/scripts/hq/standby-snapshot.ts +7 -3
  303. package/scripts/knowledge-compress.ts +11 -0
  304. package/scripts/lib/typecheck-ratchet.ts +51 -0
  305. package/scripts/nightly-docops.ts +90 -3
  306. package/scripts/openai-relay-server.ts +5 -1
  307. package/scripts/release-loop/docs-node.ts +258 -43
  308. package/scripts/release-loop/gate-method.ts +59 -0
  309. package/scripts/release-loop/gate-node.ts +73 -7
  310. package/scripts/release-loop/gate-wall.ts +208 -0
  311. package/scripts/release-loop/known-issues-node.ts +53 -8
  312. package/scripts/release-loop/publish-at.ts +14 -0
  313. package/scripts/release-loop/publish-node.ts +17 -2
  314. package/scripts/release-loop/resume-release.ts +34 -4
  315. package/scripts/release-loop/resume.ts +53 -0
  316. package/scripts/release-loop/shard-plan.ts +3 -11
  317. package/scripts/release-loop/tui-node-checks.ts +22 -0
  318. package/scripts/release-loop/unattended-release.ts +8 -1
  319. package/scripts/research-coo-admin-dates.ts +39 -0
  320. package/scripts/rhythm/daily.ts +51 -2
  321. package/scripts/rhythm/weekly.ts +3 -2
  322. package/scripts/skills/public-check.ts +7 -2
  323. package/scripts/smart-merge/resync-shadow.ts +5 -3
  324. package/scripts/test-diet/lib.ts +81 -1
  325. package/scripts/test-diet/node.ts +48 -2
  326. package/scripts/tsc-main-safety-net.ts +189 -0
  327. package/scripts/usage-rollup.ts +8 -4
  328. package/scripts/verify-coo-admin-evidence.ts +83 -0
  329. package/src/acp/client.ts +4 -2
  330. package/src/acp/codex-plugins.ts +48 -6
  331. package/src/agent/monad-agent-turn.ts +67 -5
  332. package/src/agent/run-context.ts +14 -0
  333. package/src/agent/tool-profile.ts +28 -2
  334. package/src/agent-env/profile.ts +25 -5
  335. package/src/agent-mission/acp-judge.ts +8 -2
  336. package/src/agent-mission/capabilities-cli.ts +16 -1
  337. package/src/agent-mission/driver.ts +27 -13
  338. package/src/agent-mission/pr-review-watch.ts +6 -2
  339. package/src/agent-mission/review-loop.ts +33 -5
  340. package/src/agent-mission/supervisor-metrics.ts +17 -2
  341. package/src/agent-substrate/acp-reviewer.ts +25 -9
  342. package/src/agent-substrate/pr-reviewer.ts +175 -32
  343. package/src/agent-substrate/review-intent.ts +106 -5
  344. package/src/agent-substrate/self-review-cli.ts +111 -16
  345. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  346. package/src/ask-user-question/pending-questions.ts +8 -2
  347. package/src/autopilot/build/llm-conflict-merge.ts +238 -20
  348. package/src/autopilot/codebase-grounding.ts +44 -0
  349. package/src/autopilot/llm-control-brain.ts +13 -1
  350. package/src/autopilot/mission-codebase-gate.ts +8 -77
  351. package/src/autopilot/pr-manager.ts +30 -11
  352. package/src/away/release-watch.ts +47 -8
  353. package/src/boot/acp-server.ts +4 -7
  354. package/src/boot/acp-socket-path.ts +7 -0
  355. package/src/briefing/brief-items.ts +123 -22
  356. package/src/chat/index.ts +13 -3
  357. package/src/cli/agent-cli.ts +20 -0
  358. package/src/cli/brief-cli.ts +46 -22
  359. package/src/cli/cli-user-error.ts +9 -2
  360. package/src/cli/config-classify.ts +83 -0
  361. package/src/cli/control-cli.ts +14 -0
  362. package/src/cli/decisions-cli.ts +26 -16
  363. package/src/cli/log-event-names.ts +3 -0
  364. package/src/cli/logs-cli.ts +1 -0
  365. package/src/cli/logs-model-input.ts +1 -1
  366. package/src/cli/mcp-login.ts +111 -37
  367. package/src/cli/plugin-cli.ts +21 -1
  368. package/src/cli/pod-cli.ts +26 -0
  369. package/src/cli/pr-cli.ts +94 -9
  370. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  371. package/src/cli/release-cli.ts +74 -15
  372. package/src/cli/self-update.ts +173 -10
  373. package/src/cli/skills-cli.ts +12 -3
  374. package/src/cli/tasks-cli.ts +241 -28
  375. package/src/connectors/types.ts +6 -6
  376. package/src/context-bus/context-first.ts +51 -2
  377. package/src/context-bus/context-now-surfaces.ts +29 -0
  378. package/src/context-bus/coord-events.ts +32 -4
  379. package/src/context-bus/long-term-memory.ts +26 -7
  380. package/src/context-bus/nightly-condense.ts +170 -21
  381. package/src/control/control-status.ts +87 -0
  382. package/src/control-plane/light-member.ts +5 -3
  383. package/src/control-plane/member.ts +172 -7
  384. package/src/core-turn/run-goal-loop.ts +108 -3
  385. package/src/dashboard/chat-fold.ts +20 -0
  386. package/src/dashboard/first-screen-band.ts +151 -1
  387. package/src/dashboard/index.ts +27 -5
  388. package/src/dashboard/slash-runtime/dashboard-handlers.ts +14 -3
  389. package/src/dashboard/stale-install-check.ts +13 -2
  390. package/src/dashboard/turn-stream-formatter.ts +25 -0
  391. package/src/debug/log-diet.ts +159 -0
  392. package/src/debug/log.ts +52 -17
  393. package/src/decisions/decision-cards.ts +20 -1
  394. package/src/decisions/decision-ledger.ts +11 -8
  395. package/src/decisions/web-push-decision-cards.ts +19 -3
  396. package/src/discord-self-message.ts +2 -2
  397. package/src/display/coordinator.ts +25 -2
  398. package/src/domains/coo-admin-dates.evidence.json +876 -0
  399. package/src/domains/coo-admin-tool.ts +75 -14
  400. package/src/domains/cron-match.ts +1 -0
  401. package/src/domains/ops-status.ts +53 -0
  402. package/src/domains/outbound-alert.ts +41 -7
  403. package/src/domains/release-tool.ts +119 -10
  404. package/src/domains/schedule-registry.ts +10 -7
  405. package/src/domains/schedule-runner.ts +1 -0
  406. package/src/elanous-config-dir.ts +2 -2
  407. package/src/elanous-daemon.ts +3 -3
  408. package/src/exec-requests/planner.ts +6 -0
  409. package/src/execution-loop/launch-gate.ts +1 -1
  410. package/src/expression/i18n/messages.en.ts +5 -0
  411. package/src/expression/i18n/messages.ja.ts +5 -0
  412. package/src/expression/i18n/messages.ko.ts +5 -0
  413. package/src/expression/i18n/messages.zh.ts +5 -0
  414. package/src/expression/i18n/types.ts +8 -0
  415. package/src/github/pr-labels.ts +1 -0
  416. package/src/graph-kinds/registry.ts +6 -6
  417. package/src/graph-runner/graph-cli.ts +34 -2
  418. package/src/graph-runner/graph-run-api.ts +7 -0
  419. package/src/graph-runner/graph-tick.ts +73 -12
  420. package/src/graph-runner/runner.ts +94 -13
  421. package/src/graph-unify/wf-to-graph.ts +79 -0
  422. package/src/graph-wizard/generate.ts +34 -2
  423. package/src/graph-wizard/steps.ts +13 -0
  424. package/src/harness/dispatch-backpressure.ts +259 -0
  425. package/src/harness/harness-cli-command.ts +227 -50
  426. package/src/harness/harness-queue.ts +58 -14
  427. package/src/harness/harness-seams.ts +2 -20
  428. package/src/harness/harness-substrate-default.ts +72 -1
  429. package/src/harness/launch-advice.ts +23 -0
  430. package/src/harness/nested-elanous-policy.ts +4 -2
  431. package/src/hq/fence-wrapper.ts +7 -0
  432. package/src/hq/hq.ts +33 -2
  433. package/src/hq/lease.ts +13 -0
  434. package/src/hq/seats.ts +114 -18
  435. package/src/index.ts +199 -71
  436. package/src/intake-plane/collect-github.ts +19 -1
  437. package/src/intake-plane/digest.ts +45 -20
  438. package/src/intake-plane/lens.ts +36 -8
  439. package/src/intelligence-map/model-alias.ts +6 -0
  440. package/src/intelligence-map/model-catalog.ts +41 -0
  441. package/src/knowledge/conclusion-compress.ts +93 -0
  442. package/src/knowledge/kgs/pack.ts +5 -2
  443. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  444. package/src/knowledge/know-find.ts +9 -2
  445. package/src/knowledge/query.ts +20 -0
  446. package/src/knowledge/tools/knowledge-query.ts +20 -2
  447. package/src/knowledge/write.ts +234 -2
  448. package/src/llm/bedrock-provider.ts +175 -0
  449. package/src/llm/bedrock.ts +345 -0
  450. package/src/llm/provider-credentials.ts +3 -1
  451. package/src/llm.ts +332 -51
  452. package/src/loops/budget.ts +150 -0
  453. package/src/loops/neighbor-runtime.ts +88 -0
  454. package/src/loops/orchestrator/author-depth.ts +29 -11
  455. package/src/loops/orchestrator/overlap.ts +7 -1
  456. package/src/loops/orchestrator/resync-shadow.ts +1 -1
  457. package/src/loops/orchestrator/seat-share.ts +6 -49
  458. package/src/loops/orchestrator/tick.ts +35 -2
  459. package/src/loops/orchestrator/traffic.ts +6 -80
  460. package/src/loops/registry.ts +5 -0
  461. package/src/market/publish.ts +17 -1
  462. package/src/market/signed-index.ts +42 -0
  463. package/src/maturity/feature-maturity.ts +2 -1
  464. package/src/mcp/mcp-oauth.ts +136 -17
  465. package/src/model-tier/llm-tier-map.ts +48 -4
  466. package/src/models/prompts.ts +22 -1
  467. package/src/mss/logging/horizon-watch.ts +168 -0
  468. package/src/mss/logging/log-store.ts +204 -15
  469. package/src/mss/logging/redaction.ts +17 -0
  470. package/src/native-tool-catalog.ts +1 -1
  471. package/src/nexus/api/consult-requests.ts +7 -10
  472. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  473. package/src/nexus/api/draft-metrics.ts +22 -8
  474. package/src/nexus/api/error-reports.ts +30 -8
  475. package/src/nexus/api/graph-peer-edit.ts +77 -0
  476. package/src/nexus/api/graph-wizard-api.ts +9 -1
  477. package/src/nexus/api/graphs-api.ts +145 -7
  478. package/src/nexus/api/http-server.ts +101 -8
  479. package/src/nexus/api/loop-resources.ts +42 -0
  480. package/src/nexus/api/outbound-report.ts +8 -3
  481. package/src/nexus/api/plugins-market.ts +24 -0
  482. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  483. package/src/nexus/index.ts +13 -2
  484. package/src/nexus/outbound/format.ts +2 -0
  485. package/src/nexus/outbound/router.ts +198 -13
  486. package/src/oauth/claude-pty-maturity.ts +24 -0
  487. package/src/oauth/codex-account-rotation.ts +16 -18
  488. package/src/oauth/codex-account-store.ts +134 -5
  489. package/src/oauth/fallback-chain.ts +50 -15
  490. package/src/onboarding.ts +2 -1
  491. package/src/plugins/adapters/claude-package.ts +4 -12
  492. package/src/plugins/core/capability-policy.ts +141 -0
  493. package/src/plugins/core/host.ts +21 -8
  494. package/src/plugins/core/manifest.ts +19 -2
  495. package/src/plugins/core/trust-store.ts +15 -0
  496. package/src/plugins/core/types.ts +12 -0
  497. package/src/plugins/install/market-fetch.ts +68 -16
  498. package/src/plugins/install/plugin-install.ts +187 -16
  499. package/src/plugins/maker/market-bundle.ts +9 -0
  500. package/src/plugins/maker/plugin-maker.ts +32 -21
  501. package/src/plugins/maker/wizard-generate.ts +87 -9
  502. package/src/policy/llm-policy.ts +24 -6
  503. package/src/process/pid-liveness.ts +1 -1
  504. package/src/prompt-cache/openai.ts +10 -6
  505. package/src/prompt-cache/openrouter.ts +94 -0
  506. package/src/prompt-enhance/enhance.ts +46 -5
  507. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  508. package/src/prompt-library/universal-preamble.ts +2 -2
  509. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  510. package/src/registry/loader.ts +6 -1
  511. package/src/release-loop/checklist-board.ts +27 -0
  512. package/src/release-loop/checklist.ts +62 -9
  513. package/src/release-loop/feature-store.ts +3 -0
  514. package/src/release-loop/gate-shards.ts +48 -4
  515. package/src/release-loop/landed-to-green.ts +81 -0
  516. package/src/release-loop/light-rc.ts +11 -1
  517. package/src/release-loop/merged-pr-checklist.ts +10 -0
  518. package/src/release-loop/placement.ts +91 -22
  519. package/src/release-loop/rehearsal.ts +317 -0
  520. package/src/release-loop/release-schedule.ts +13 -1
  521. package/src/release-loop/rubric-types.ts +1 -0
  522. package/src/release-loop/rubric.ts +2 -2
  523. package/src/retro/daily.ts +23 -9
  524. package/src/seat-address/seat-address.ts +1 -0
  525. package/src/seat-loop/seat-loop.ts +208 -21
  526. package/src/seat-loop/seat-report.ts +29 -1
  527. package/src/seat-loop/traffic-signal.ts +44 -0
  528. package/src/self-dev/ask-launch-flow.ts +2 -2
  529. package/src/self-dev/dev-cli.ts +157 -11
  530. package/src/self-dev/dev-pipeline.ts +18 -1
  531. package/src/self-dev/draft-residue.ts +463 -0
  532. package/src/self-dev/draft-sweep.ts +195 -17
  533. package/src/self-dev/draft-triage-rules.ts +27 -1
  534. package/src/self-dev/launch-preflight-text.ts +549 -0
  535. package/src/self-dev/launch-preflight.ts +10 -545
  536. package/src/self-dev/orchestrate-cli.ts +57 -2
  537. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  538. package/src/self-dev/orchestrate.ts +9 -133
  539. package/src/self-dev/review-provider-fallback.ts +179 -0
  540. package/src/self-dev/run-store.ts +1 -3
  541. package/src/self-dev/run-supervisor.ts +8 -23
  542. package/src/self-dev/run-types.ts +178 -0
  543. package/src/self-dev/shard-aggregate.ts +61 -13
  544. package/src/self-dev/shard-plan.ts +5 -1
  545. package/src/self-dev/shard-run.ts +23 -5
  546. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  547. package/src/self-implement/blocked-draft-policy.ts +3 -19
  548. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  549. package/src/self-implement/follow-up-goals.ts +114 -38
  550. package/src/self-implement/gate-baseline-reap.ts +157 -0
  551. package/src/self-implement/gate-baseline.ts +78 -16
  552. package/src/self-implement/gate-cli.ts +12 -2
  553. package/src/self-implement/gate-remote.ts +17 -6
  554. package/src/self-implement/goal-author.ts +24 -4
  555. package/src/self-implement/goal-digest.ts +19 -0
  556. package/src/self-implement/graph-overlay-condition.ts +4 -0
  557. package/src/self-implement/harness-policy-gates.ts +7 -5
  558. package/src/self-implement/headless-elanous-driver.ts +11 -9
  559. package/src/self-implement/host-regate.ts +148 -43
  560. package/src/self-implement/l8-merge-queue.ts +147 -13
  561. package/src/self-implement/merge-train.ts +131 -0
  562. package/src/self-implement/off-diff-evidence.ts +9 -0
  563. package/src/self-implement/orchestrator.ts +201 -43
  564. package/src/self-implement/review-finding-recurrence.ts +28 -0
  565. package/src/self-implement/rework-policy.ts +2 -1
  566. package/src/self-implement/round-summary-card.ts +63 -0
  567. package/src/self-implement/run-ledger.ts +4 -3
  568. package/src/self-implement/run-step-projection.ts +147 -0
  569. package/src/self-implement/run-stop.ts +1 -1
  570. package/src/self-implement/seams.ts +41 -6
  571. package/src/self-implement/self-implement-cli.ts +6 -0
  572. package/src/self-implement/train-gate-remote.ts +158 -0
  573. package/src/session-runtime/index.ts +10 -1
  574. package/src/session-runtime/retry-api.ts +11 -1
  575. package/src/shell-env-bootstrap.ts +19 -4
  576. package/src/skills/gift-install.ts +119 -0
  577. package/src/skills/runner.ts +59 -2
  578. package/src/skills/skill-feedback.ts +31 -1
  579. package/src/skills/skill-tier.ts +1 -0
  580. package/src/smart-wizard/capability-index.ts +231 -0
  581. package/src/smart-wizard/rung.ts +74 -0
  582. package/src/steward/launch.ts +20 -9
  583. package/src/steward/triage.ts +29 -10
  584. package/src/storage/file-lock.ts +40 -4
  585. package/src/task-agent/actions.ts +4 -0
  586. package/src/task-agent/card-evidence.ts +59 -13
  587. package/src/task-agent/completion-evidence.ts +31 -3
  588. package/src/task-agent/cover.ts +61 -0
  589. package/src/task-agent/judge.ts +4 -3
  590. package/src/task-agent/land-worktree.ts +201 -0
  591. package/src/task-agent/live-move-history.ts +133 -0
  592. package/src/task-agent/live-moves.ts +222 -12
  593. package/src/task-agent/parent-host.ts +117 -8
  594. package/src/task-agent/rejudge-on-head.ts +297 -0
  595. package/src/task-agent/review-result-capture.ts +218 -0
  596. package/src/task-agent/shadow.ts +118 -7
  597. package/src/task-agent/task-hand.ts +138 -11
  598. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  599. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  600. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  601. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  602. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  603. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  604. package/src/task-orchestrator/surfaces/pod-pool.ts +203 -28
  605. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  606. package/src/task-orchestrator/surfaces/self-implement.ts +11 -0
  607. package/src/telegram-commands.ts +8 -0
  608. package/src/telegram-project-command.ts +6 -0
  609. package/src/telegram-service.ts +5 -1
  610. package/src/telegram.ts +17 -4
  611. package/src/time/format.ts +13 -4
  612. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  613. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  614. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  615. package/src/typecheck-ratchet.ts +2 -1
  616. package/src/user-config.ts +167 -28
  617. package/src/ux-sim/slash-menu-frames.ts +168 -0
  618. package/src/version/packed-revision.json +1 -1
  619. package/src/web-terminal/preview-tap-registry.ts +5 -2
  620. package/src/workflow-runtime/executor.ts +24 -2
  621. package/src/workflow-runtime/triggers/registry.ts +27 -0
  622. package/src/workflow-runtime/triggers/schedule-source.ts +30 -3
  623. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  624. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  625. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  626. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  627. package/apps/pwa/out/_next/static/chunks/1307-c97eba9fb72a9a5e.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  629. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  630. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  631. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  633. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  638. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  647. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  648. package/apps/pwa/out/_next/static/chunks/2489-ff55a35b202c0f94.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  661. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/3857-995ea9f5ef33d71e.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  669. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  674. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  676. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  680. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  684. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/5977-59fedea50d13c762.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  689. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  690. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  692. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  693. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  701. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  704. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  714. package/apps/pwa/out/_next/static/chunks/8857-f1762140ef9a96b1.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  717. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/9247-7581825d511a64c0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  721. package/apps/pwa/out/_next/static/chunks/9497-b0e758d1cd4ae8d7.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  723. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/approvals/page-937c92292a4ab4f0.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d781be3e3a9cfd74.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/board/page-b0a80997903852d8.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2b1263165630d9c8.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/bots/page-ea998f7f5d156bea.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/ceo/page-33c328b64ca508f8.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/chat/page-e2d6bed48ac20120.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/control/page-544dd4bd4847eeb7.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/decisions/page-3ee191319bf97d87.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e4bcb2c503dab04b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/editor/page-300897dcbbd5ed76.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/exec/page-a449f1ed472b81c2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/field/page-9045094d6d3b5cd0.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/inside/page-c06673596849ef45.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/intake/page-103fa3191c1b2e08.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/layout-9f81233f29dcd409.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/live/page-be8b4615c919e36c.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/live-run/page-c685b104e0dfa609.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/loops/page-8d693331cfbb6add.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/market/page-cef4f30a4c22fae1.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66ea1b54fc83fa15.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/morning/page-7a12f61be4a579d1.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/not-found-c85b0589591a99c9.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/observatory/page-725a4da02dd129eb.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-8cc707bd09a497d9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-90b55be1f15ce0e8.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-cb16606e08be65db.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/outputs/page-16dc64b74ed6a40a.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/page-21bec4afeb2f0917.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/reflection/page-dc39ee7a36d26385.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-84ae759f76053672.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/sessions/page-3db58ddb61fe2be9.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c5315e30f3528dc4.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/settings/page-2fe368efb6de3b6a.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8d04132dd0ac5e10.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/setup/page-f23484de467c9ea3.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/share/page-c69762987b751174.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5456692bda39aafb.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d75f7cd65845ce98.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/term/page-5603f5e568b25ce3.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/today/page-d2cc0f4e89f42028.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/trace/page-a6eb73b8a4840f1c.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/vault/page-c0a3f4d10edb83fa.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6c0b88068c143f15.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/workflows/page-7f8d7fcdf058a845.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/workspace/page-22163556cd38bc88.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-141436fd26dd56fc.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  779. package/apps/pwa/out/_next/static/css/e81df11490b4413b.css +0 -1
  780. /package/apps/pwa/out/_next/static/{MObU8ujkMciAKr6ljAV05 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -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»).
@@ -4,6 +4,7 @@ import { spawnSync } from 'node:child_process';
4
4
  import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, rmSync, writeFileSync } from 'node:fs';
5
5
  import { dirname, join, resolve, sep } from 'node:path';
6
6
  import { userConfigPath } from '../../user-config.js';
7
+ import { scanKnowledgePackDlp } from '../../mss/logging/redaction.js';
7
8
  import { loadPluginManifestFromDir } from '../core/manifest.js';
8
9
  import { LEAK_MARKERS, loadPrivateRedactions, privateIdentifierMarkers, scanLeaks } from '../../../scripts/public-export.js';
9
10
 
@@ -56,6 +57,14 @@ export function bundleInstalledWizardPlugin(installedPath: string, outputDir: st
56
57
  if (!redactions) throw new Error('private export redaction list unavailable; market bundle refused');
57
58
  const hits = scanLeaks(source, files, [...LEAK_MARKERS, ...privateIdentifierMarkers(redactions)]);
58
59
  if (hits.length) throw new Error(`market bundle leak: ${hits.map(hit => `${hit.file}:${hit.line} ${hit.marker}`).join(', ')}`);
60
+ const dlpHits: string[] = [];
61
+ for (const file of files) {
62
+ const text = readFileSync(join(source, file), 'utf8');
63
+ const reasons = scanKnowledgePackDlp(text);
64
+ if (text.includes('\u0000')) reasons.push('unscannable-content');
65
+ if (reasons.length) dlpHits.push(`${file}: ${reasons.join(', ')}`);
66
+ }
67
+ if (dlpHits.length) throw new Error(`market bundle DLP: ${dlpHits.join('; ')}`);
59
68
  const config: unknown = existsSync(configPath) ? JSON.parse(readFileSync(configPath, 'utf8')) : {};
60
69
  if (!config || typeof config !== 'object' || Array.isArray(config)) throw new Error('invalid market signing config');
61
70
  const signing = (config as { market?: { signing?: { keyId?: unknown; privateKey?: unknown } } }).market?.signing;
@@ -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,63 +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
- if (!isRecord(recipe) || typeof recipe.command !== 'string' || !recipe.command.trim() ||
150
- (recipe.timeout_ms !== undefined && (!Number.isSafeInteger(recipe.timeout_ms) || Number(recipe.timeout_ms) <= 0))) errors.push(`잘못된 recipe: ${id}`);
150
+ if (!isRecord(recipe) ||
151
+ (!(typeof recipe.command === 'string' && recipe.command.trim()) && !(typeof recipe.approval === 'string' && recipe.approval.trim())) ||
152
+ (recipe.command !== undefined && (typeof recipe.command !== 'string' || !recipe.command.trim())) ||
153
+ (recipe.approval !== undefined && (typeof recipe.approval !== 'string' || !recipe.approval.trim())) ||
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'}`);
151
155
  }
152
156
  for (const graph of Array.isArray(graphs) ? graphs : []) {
153
157
  if (typeof graph !== 'string') continue;
154
158
  const file = inside(dir, graph);
155
- 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; }
156
160
  try {
157
- if (lstatSync(file).isSymbolicLink()) { errors.push(`안전하지 않은 graph 링크: ${graph}`); continue; }
161
+ if (lstatSync(file).isSymbolicLink()) { errors.push('안전하지 않은 graph 링크'); continue; }
158
162
  const parsed = parseGraphTemplateYaml(readFileSync(file, 'utf8'), file);
159
- errors.push(...parsed.errors.map(issue => `${issue.path}: ${issue.message}`));
163
+ errors.push(...parsed.errors.map(() => 'graph 정의 오류'));
160
164
  const template = parsed.template;
161
165
  if (!template) continue;
162
- 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');
163
167
  if (template.terminalNodes.length !== 2 || !template.terminalNodes.includes('done') || !template.terminalNodes.includes('failed')) errors.push('terminal_nodes 는 done, failed 이어야 한다');
164
168
  const executionNodes = template.nodes.filter(node => !template.terminalNodes.includes(node.nodeId));
165
- if (executionNodes.length < 2 || executionNodes.length > 6) errors.push(`실행 노드는 2~6개여야 한다: ${executionNodes.length}개`);
169
+ if (executionNodes.length < 2) errors.push(`실행 노드는 2개 이상이어야 한다: ${executionNodes.length}개`);
166
170
  for (const node of template.nodes) {
167
171
  if (node.recipe.startsWith('cmd:')) {
168
172
  const id = node.recipe.slice(4);
169
- if (!isRecord(recipes) || !isRecord(recipes[id]) || typeof recipes[id].command !== 'string' || !recipes[id].command) errors.push(`recipe ${id} 없음`);
170
- } else if (node.recipe !== 'none') errors.push(`지원하지 않는 recipe: ${node.recipe}`);
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'} 없음`);
174
+ } else if (node.recipe.startsWith('approval:')) {
175
+ const id = node.recipe.slice(9);
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'}`);
171
178
  }
172
- } catch (error) { errors.push(`${graph} 파싱 실패: ${String(error)}`); }
179
+ } catch { errors.push('graph 파싱 실패'); }
173
180
  }
174
181
  const visit = (path: string): void => {
175
182
  for (const entry of readdirSync(path, { withFileTypes: true })) {
176
183
  const file = join(path, entry.name);
177
- if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile())) { errors.push(`안전하지 않은 파일: ${file}`); continue; }
184
+ if (entry.isSymbolicLink() || (!entry.isDirectory() && !entry.isFile())) { errors.push('안전하지 않은 파일'); continue; }
178
185
  if (entry.isDirectory()) visit(file);
179
186
  else if (/\.[cm]?[jt]sx?$/.test(entry.name)) {
180
187
  const source = readFileSync(file, 'utf8');
181
188
  for (const match of source.matchAll(/\b(?:import|export)\s*(?:[\s\S]*?\s+from\s*)?["']([^"']+)["']|\b(?:import|require)\s*\(\s*["']([^"']+)["']/g)) {
182
189
  const target = match[1] ?? match[2]!;
183
- 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 금지');
184
191
  }
185
192
  }
186
193
  }
187
194
  };
188
- try { visit(dir); } catch (error) { errors.push(`파일 검사 실패: ${String(error)}`); }
195
+ try { visit(dir); } catch { errors.push('파일 검사 실패'); }
189
196
  try {
190
197
  const example = join(dir, 'examples', 'input.json');
191
198
  if (lstatSync(example).isSymbolicLink()) errors.push('안전하지 않은 examples/input.json 링크');
192
199
  else JSON.parse(readFileSync(example, 'utf8'));
193
- } 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}`));
194
205
  const step = join(dir, 'graphs', 'run-step.ts');
195
206
  try {
196
207
  if (!existsSync(step)) errors.push('run-step.ts 없음');
197
- else if (errors.some(error => error.startsWith('안전하지 않은 파일:'))) return errors;
208
+ else if (errors.some(error => error.startsWith('안전하지 않은 파일'))) return errors;
198
209
  else {
199
210
  const build = await Bun.build({ entrypoints: [step], target: 'bun' });
200
- if (!build.success) errors.push(...build.logs.map(log => `run-step.ts 문법 오류: ${log.message}`));
211
+ if (!build.success) errors.push('run-step.ts 문법 오류');
201
212
  }
202
- } catch (error) { errors.push(`run-step.ts 문법 오류: ${String(error)}`); }
213
+ } catch { errors.push('run-step.ts 문법 오류'); }
203
214
  return errors;
204
215
  }
205
216
 
@@ -353,7 +364,7 @@ export async function makePlugin({ request, draftFile, name, parentDir, run, mar
353
364
  const step = async (stage: keyof MakePluginResult['timings'], action: () => void | Promise<void>): Promise<void> => {
354
365
  const start = performance.now();
355
366
  try { await action(); }
356
- 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) }); }
357
368
  };
358
369
  try {
359
370
  emit('request', request);
@@ -455,7 +466,7 @@ export async function makePlugin({ request, draftFile, name, parentDir, run, mar
455
466
  }
456
467
  } catch (error) {
457
468
  result.status = 'failed';
458
- result.errors.push(error instanceof Error ? error.message : String(error));
469
+ result.errors.push(redactSecretText(error instanceof Error ? error.message : String(error)));
459
470
  } finally {
460
471
  emit('done', result.status, { errors: result.errors });
461
472
  }
@@ -1,5 +1,5 @@
1
- import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
2
- import { join } from 'node:path';
1
+ import { existsSync, lstatSync, mkdirSync, readFileSync, readdirSync, realpathSync, writeFileSync } from 'node:fs';
2
+ import { join, resolve, sep } from 'node:path';
3
3
  import { parse as parseYaml, stringify as stringifyYaml } from 'yaml';
4
4
 
5
5
  /** Research is descriptive. Credential values are never an input to the generator. */
@@ -10,13 +10,14 @@ 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}$/;
16
17
  const FIELD = /^[A-Za-z_][A-Za-z0-9_-]*$/;
17
18
 
18
19
  /** Materialize a research draft; its graph steps fail until the requested processing is implemented. */
19
- export function generateWizardFiles(dir: string, slug: string, draft: WizardResearchDraft): string[] {
20
+ export function generateWizardFiles(dir: string, slug: string, draft: WizardResearchDraft, options: { regenerate?: boolean } = {}): string[] {
20
21
  if (!SLUG.test(slug)) throw new Error(`invalid wizard plugin name: ${slug}`);
21
22
  if (!draft || typeof draft.description !== 'string' || !draft.description.trim()) throw new Error('wizard description is required');
22
23
  if (draft.connectors !== undefined && !Array.isArray(draft.connectors)) throw new Error('invalid wizard connectors');
@@ -46,23 +47,43 @@ 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; 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');
55
63
  }
56
- if (existsSync(join(dir, `skills/${slug}/SKILL.md`))) {
64
+ const skillPath = join(dir, `skills/${slug}/SKILL.md`);
65
+ const readmePath = join(dir, 'README.md');
66
+ const wizardReadme = options.regenerate && existsSync(readmePath) &&
67
+ readFileSync(readmePath, 'utf8').includes('Research draft only. Connector declarations contain credential names, not values.');
68
+ if (options.regenerate) {
69
+ if (!existing || existing.extensions['ai.elanous'].researchDraft !== true || !existsSync(skillPath)) {
70
+ throw new Error('wizard regeneration requires an existing research draft');
71
+ }
72
+ } else if (existsSync(skillPath)) {
57
73
  throw new Error(`wizard file already exists: skills/${slug}/SKILL.md`);
58
74
  }
59
75
  const scaffoldConnectors = existing?.extensions['ai.elanous'].connectors;
60
- if (scaffoldConnectors !== undefined && (!Array.isArray(scaffoldConnectors) || scaffoldConnectors.length > 0)) {
76
+ if (!options.regenerate && scaffoldConnectors !== undefined && (!Array.isArray(scaffoldConnectors) || scaffoldConnectors.length > 0)) {
61
77
  throw new Error('wizard cannot replace existing scaffold connectors');
62
78
  }
63
79
  const manifest = existing ?? { name: slug, version: '0.1.0', description: draft.description,
80
+ requires: undefined as { knowledgePacks?: string[]; [key: string]: unknown } | undefined,
64
81
  extensions: { 'ai.elanous': { graphs: [`./graphs/${slug}.yaml`],
65
82
  capabilities: ['fs:workdir', 'proc:bun', 'proc:elanous'], connectors: [] as unknown[], researchDraft: true } } };
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
+ }
66
87
  manifest.extensions['ai.elanous'].connectors = connectors;
67
88
  manifest.extensions['ai.elanous'].researchDraft = true;
68
89
 
@@ -90,14 +111,71 @@ process.exitCode = 1;
90
111
  ['README.md', `# ${slug}\n\n${draft.description}\n\nResearch draft only. Connector declarations contain credential names, not values. The graph cannot perform the requested processing yet: implement and validate its steps, then remove extensions["ai.elanous"].researchDraft from plugin.json before installing or running it. No messages are sent.\n`],
91
112
  [`skills/${slug}/SKILL.md`, `---\n${stringifyYaml({ name: slug, description: draft.skill?.description ?? draft.description, requires: [...new Set(requires)] })}---\n\n${draft.skill?.instructions ?? draft.description}\n`],
92
113
  ];
93
- const generated = existing ? files.filter(([path]) => path === 'plugin.json' || path.startsWith('skills/')) : files;
114
+ const generated = existing ? files.filter(([path]) => path === 'plugin.json' || path.startsWith('skills/') ||
115
+ (options.regenerate && wizardReadme && path === 'README.md')) : files;
94
116
  for (const [path] of generated) {
95
- if (path !== 'plugin.json' && existsSync(join(dir, path))) throw new Error(`wizard file already exists: ${path}`);
117
+ if (path !== 'plugin.json' && !(options.regenerate && (path === 'README.md' || path.startsWith('skills/'))) && existsSync(join(dir, path))) {
118
+ throw new Error(`wizard file already exists: ${path}`);
119
+ }
96
120
  }
97
121
  for (const [path, content] of generated) {
98
122
  const target = join(dir, path);
99
123
  mkdirSync(join(target, '..'), { recursive: true });
100
- writeFileSync(target, content, { flag: path === 'plugin.json' && existing ? 'w' : 'wx' });
124
+ writeFileSync(target, content, { flag: existing && (path === 'plugin.json' || options.regenerate) ? 'w' : 'wx' });
101
125
  }
102
126
  return generated.map(([path]) => path);
103
127
  }
128
+
129
+ /** Browser wizard drafts are stored outside the install ledger. Only wizard-owned directories are listed. */
130
+ export function listWizardDrafts(parent: string): Array<{ name: string; description: string; draft: WizardResearchDraft }> {
131
+ if (!existsSync(parent)) return [];
132
+ return readdirSync(parent, { withFileTypes: true }).filter(entry => entry.isDirectory() && SLUG.test(entry.name)).flatMap(entry => {
133
+ const dir = join(parent, entry.name);
134
+ try {
135
+ const manifestPath = join(dir, 'plugin.json');
136
+ const skillDir = join(dir, 'skills', entry.name);
137
+ const skillPath = join(skillDir, 'SKILL.md');
138
+ if (lstatSync(manifestPath).isSymbolicLink() || lstatSync(skillDir).isSymbolicLink() || lstatSync(skillPath).isSymbolicLink()) return [];
139
+ const manifest = JSON.parse(readFileSync(manifestPath, 'utf8')) as {
140
+ name?: string; description?: string; requires?: { knowledgePacks?: string[] };
141
+ extensions?: { 'ai.elanous'?: { researchDraft?: boolean; connectors?: Array<{ id: string; fields: Array<{ name: string }> }> } } };
142
+ if (manifest.name !== entry.name || manifest.extensions?.['ai.elanous']?.researchDraft !== true) return [];
143
+ const skill = readFileSync(skillPath, 'utf8');
144
+ const parts = /^---\n([\s\S]*?)---\n\n([\s\S]*)$/.exec(skill);
145
+ if (!parts || typeof manifest.description !== 'string') return [];
146
+ const meta = parseYaml(parts[1]!) as { description?: string; requires?: string[] };
147
+ return [{ name: entry.name, description: manifest.description, draft: {
148
+ description: manifest.description,
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 } } : {}),
151
+ skill: { description: meta.description ?? manifest.description, instructions: parts[2]!.trimEnd(), requires: meta.requires ?? [] },
152
+ } }];
153
+ } catch { return []; }
154
+ }).sort((a, b) => a.name.localeCompare(b.name));
155
+ }
156
+
157
+ export function saveWizardDraft(parent: string, slug: string, draft: WizardResearchDraft, regenerate = false): string[] {
158
+ if (!SLUG.test(slug)) throw new Error(`invalid wizard plugin name: ${slug}`);
159
+ const requested = resolve(parent);
160
+ if (existsSync(requested) && lstatSync(requested).isSymbolicLink()) throw new Error('wizard parent cannot be a symlink');
161
+ // Ancestors may be symlinks (macOS /var -> /private/var); compare the draft directory against the real parent.
162
+ const base = existsSync(requested) ? realpathSync(requested) : requested;
163
+ const dir = resolve(base, slug);
164
+ if (!dir.startsWith(`${base}${sep}`)) throw new Error('invalid wizard directory');
165
+ if (existsSync(dir) && (lstatSync(dir).isSymbolicLink() || !lstatSync(dir).isDirectory() || realpathSync(dir) !== dir)) {
166
+ throw new Error('wizard directory must be a local directory');
167
+ }
168
+ if (regenerate && existsSync(join(dir, 'skills')) && lstatSync(join(dir, 'skills')).isSymbolicLink()) {
169
+ throw new Error('wizard skills cannot be a symlink');
170
+ }
171
+ if (!regenerate && existsSync(dir)) throw new Error('wizard directory already exists');
172
+ if (regenerate && existsSync(join(dir, 'skills', slug)) && lstatSync(join(dir, 'skills', slug)).isSymbolicLink()) {
173
+ throw new Error('wizard skills cannot be a symlink');
174
+ }
175
+ if (regenerate && ['plugin.json', 'README.md', `skills/${slug}/SKILL.md`].some(file => {
176
+ const path = join(dir, file);
177
+ return existsSync(path) && lstatSync(path).isSymbolicLink();
178
+ })) throw new Error('wizard regeneration cannot follow symlinks');
179
+ if (!existsSync(base) && !regenerate) mkdirSync(base, { recursive: true });
180
+ return generateWizardFiles(dir, slug, draft, { regenerate });
181
+ }