elanous 0.2.22 → 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 (705) 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-80ed511e02c81412.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/{aBi6EyMtLsrl7J8eH4kF7 → 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/log-horizon/log-horizon-watch.yaml +25 -0
  288. package/graphs/log-horizon/recipes.yaml +3 -0
  289. package/graphs/release/recipes.yaml +1 -1
  290. package/graphs/release/release-loop.yaml +6 -2
  291. package/graphs/release-rehearsal/recipes.yaml +12 -0
  292. package/graphs/release-rehearsal/release-rehearsal.yaml +17 -0
  293. package/package.json +4 -1
  294. package/scripts/bench-report.ts +82 -3
  295. package/scripts/ci-typecheck-changed.ts +10 -1
  296. package/scripts/hq/hq-fence-wrapper.sh +148 -0
  297. package/scripts/lib/typecheck-ratchet.ts +51 -0
  298. package/scripts/openai-relay-server.ts +5 -1
  299. package/scripts/release-loop/docs-node.ts +258 -43
  300. package/scripts/release-loop/gate-method.ts +59 -0
  301. package/scripts/release-loop/gate-node.ts +73 -7
  302. package/scripts/release-loop/gate-wall.ts +208 -0
  303. package/scripts/release-loop/known-issues-node.ts +53 -8
  304. package/scripts/release-loop/publish-at.ts +14 -0
  305. package/scripts/release-loop/publish-node.ts +17 -2
  306. package/scripts/release-loop/resume-release.ts +34 -4
  307. package/scripts/release-loop/resume.ts +53 -0
  308. package/scripts/release-loop/shard-plan.ts +3 -11
  309. package/scripts/release-loop/tui-node-checks.ts +22 -0
  310. package/scripts/release-loop/unattended-release.ts +8 -1
  311. package/scripts/rhythm/daily.ts +51 -2
  312. package/scripts/rhythm/weekly.ts +3 -2
  313. package/scripts/tsc-main-safety-net.ts +189 -0
  314. package/scripts/usage-rollup.ts +8 -4
  315. package/src/acp/codex-plugins.ts +48 -6
  316. package/src/agent/monad-agent-turn.ts +67 -5
  317. package/src/agent/run-context.ts +10 -0
  318. package/src/agent/tool-profile.ts +28 -2
  319. package/src/agent-mission/acp-judge.ts +8 -2
  320. package/src/agent-mission/capabilities-cli.ts +16 -1
  321. package/src/agent-mission/driver.ts +1 -1
  322. package/src/agent-mission/pr-review-watch.ts +6 -2
  323. package/src/agent-mission/review-loop.ts +33 -5
  324. package/src/agent-substrate/acp-reviewer.ts +17 -8
  325. package/src/agent-substrate/pr-reviewer.ts +164 -28
  326. package/src/agent-substrate/review-intent.ts +6 -4
  327. package/src/agent-substrate/self-review-cli.ts +111 -16
  328. package/src/agent-substrate/shard-boundary-intent.ts +92 -26
  329. package/src/ask-user-question/pending-questions.ts +8 -2
  330. package/src/autopilot/build/llm-conflict-merge.ts +216 -12
  331. package/src/autopilot/codebase-grounding.ts +44 -0
  332. package/src/autopilot/llm-control-brain.ts +13 -1
  333. package/src/autopilot/mission-codebase-gate.ts +8 -77
  334. package/src/autopilot/pr-manager.ts +12 -3
  335. package/src/boot/acp-server.ts +4 -7
  336. package/src/boot/acp-socket-path.ts +7 -0
  337. package/src/briefing/brief-items.ts +21 -13
  338. package/src/chat/index.ts +12 -3
  339. package/src/cli/agent-cli.ts +20 -0
  340. package/src/cli/brief-cli.ts +27 -21
  341. package/src/cli/cli-user-error.ts +9 -2
  342. package/src/cli/log-event-names.ts +3 -0
  343. package/src/cli/logs-cli.ts +1 -0
  344. package/src/cli/mcp-login.ts +111 -37
  345. package/src/cli/plugin-cli.ts +21 -1
  346. package/src/cli/pod-cli.ts +26 -0
  347. package/src/cli/pr-cli.ts +30 -2
  348. package/src/cli/pr-land-overlap-evidence.ts +131 -0
  349. package/src/cli/release-cli.ts +53 -11
  350. package/src/cli/self-update.ts +173 -10
  351. package/src/cli/skills-cli.ts +12 -3
  352. package/src/cli/tasks-cli.ts +133 -27
  353. package/src/context-bus/context-first.ts +51 -2
  354. package/src/context-bus/context-now-surfaces.ts +13 -2
  355. package/src/context-bus/long-term-memory.ts +3 -1
  356. package/src/context-bus/nightly-condense.ts +3 -2
  357. package/src/core-turn/run-goal-loop.ts +86 -2
  358. package/src/dashboard/chat-fold.ts +20 -0
  359. package/src/dashboard/first-screen-band.ts +151 -1
  360. package/src/dashboard/index.ts +27 -5
  361. package/src/dashboard/slash-runtime/dashboard-handlers.ts +5 -3
  362. package/src/dashboard/stale-install-check.ts +13 -2
  363. package/src/dashboard/turn-stream-formatter.ts +25 -0
  364. package/src/debug/log-diet.ts +159 -0
  365. package/src/debug/log.ts +52 -17
  366. package/src/display/coordinator.ts +25 -2
  367. package/src/domains/coo-admin-tool.ts +27 -0
  368. package/src/domains/cron-match.ts +1 -0
  369. package/src/domains/outbound-alert.ts +17 -6
  370. package/src/domains/release-tool.ts +119 -10
  371. package/src/domains/schedule-registry.ts +10 -7
  372. package/src/domains/schedule-runner.ts +1 -0
  373. package/src/elanous-config-dir.ts +2 -2
  374. package/src/elanous-daemon.ts +3 -3
  375. package/src/execution-loop/launch-gate.ts +1 -1
  376. package/src/expression/i18n/messages.en.ts +5 -0
  377. package/src/expression/i18n/messages.ja.ts +5 -0
  378. package/src/expression/i18n/messages.ko.ts +5 -0
  379. package/src/expression/i18n/messages.zh.ts +5 -0
  380. package/src/expression/i18n/types.ts +8 -0
  381. package/src/github/pr-labels.ts +1 -0
  382. package/src/graph-runner/runner.ts +54 -5
  383. package/src/harness/dispatch-backpressure.ts +259 -0
  384. package/src/harness/harness-cli-command.ts +107 -28
  385. package/src/harness/harness-seams.ts +2 -20
  386. package/src/harness/harness-substrate-default.ts +72 -1
  387. package/src/harness/nested-elanous-policy.ts +4 -2
  388. package/src/hq/fence-wrapper.ts +7 -0
  389. package/src/hq/hq.ts +33 -2
  390. package/src/hq/lease.ts +13 -0
  391. package/src/hq/seats.ts +114 -18
  392. package/src/index.ts +163 -64
  393. package/src/intake-plane/collect-github.ts +19 -1
  394. package/src/intake-plane/digest.ts +45 -20
  395. package/src/intake-plane/lens.ts +36 -8
  396. package/src/intelligence-map/model-alias.ts +6 -0
  397. package/src/intelligence-map/model-catalog.ts +41 -0
  398. package/src/knowledge/kgs/pack.ts +5 -2
  399. package/src/knowledge/kgs/sqlite-store.ts +15 -0
  400. package/src/knowledge/tools/knowledge-query.ts +20 -2
  401. package/src/knowledge/write.ts +234 -2
  402. package/src/llm/bedrock-provider.ts +175 -0
  403. package/src/llm/bedrock.ts +345 -0
  404. package/src/llm/provider-credentials.ts +3 -1
  405. package/src/llm.ts +306 -35
  406. package/src/loops/budget.ts +150 -0
  407. package/src/loops/orchestrator/seat-share.ts +6 -49
  408. package/src/loops/orchestrator/traffic.ts +5 -81
  409. package/src/market/signed-index.ts +42 -0
  410. package/src/mcp/mcp-oauth.ts +136 -17
  411. package/src/model-tier/llm-tier-map.ts +48 -4
  412. package/src/models/prompts.ts +22 -1
  413. package/src/mss/logging/horizon-watch.ts +168 -0
  414. package/src/mss/logging/log-store.ts +204 -15
  415. package/src/native-tool-catalog.ts +1 -1
  416. package/src/nexus/api/consult-requests.ts +7 -10
  417. package/src/nexus/api/discord-trigger-bot.ts +6 -3
  418. package/src/nexus/api/error-reports.ts +30 -8
  419. package/src/nexus/api/http-server.ts +8 -0
  420. package/src/nexus/api/loop-resources.ts +42 -0
  421. package/src/nexus/api/outbound-report.ts +8 -3
  422. package/src/nexus/api/telegram-trigger-bot.ts +6 -3
  423. package/src/nexus/index.ts +10 -0
  424. package/src/nexus/outbound/format.ts +2 -0
  425. package/src/nexus/outbound/router.ts +198 -13
  426. package/src/oauth/codex-account-rotation.ts +16 -18
  427. package/src/oauth/codex-account-store.ts +134 -5
  428. package/src/oauth/fallback-chain.ts +28 -6
  429. package/src/onboarding.ts +2 -1
  430. package/src/plugins/adapters/claude-package.ts +4 -12
  431. package/src/plugins/core/capability-policy.ts +141 -0
  432. package/src/plugins/core/host.ts +21 -8
  433. package/src/plugins/core/manifest.ts +19 -2
  434. package/src/plugins/core/trust-store.ts +15 -0
  435. package/src/plugins/core/types.ts +12 -0
  436. package/src/plugins/install/market-fetch.ts +68 -16
  437. package/src/plugins/install/plugin-install.ts +187 -16
  438. package/src/plugins/maker/plugin-maker.ts +25 -20
  439. package/src/plugins/maker/wizard-generate.ts +16 -2
  440. package/src/policy/llm-policy.ts +14 -1
  441. package/src/process/pid-liveness.ts +1 -1
  442. package/src/prompt-cache/openai.ts +10 -6
  443. package/src/prompt-cache/openrouter.ts +94 -0
  444. package/src/prompt-enhance/enhance.ts +46 -5
  445. package/src/prompt-library/family-prompt-coverage.ts +1 -0
  446. package/src/prompt-library/universal-preamble.ts +2 -2
  447. package/src/registry/discovery/openrouter-live-resolve.ts +122 -0
  448. package/src/registry/loader.ts +6 -1
  449. package/src/release-loop/checklist.ts +24 -9
  450. package/src/release-loop/feature-store.ts +3 -0
  451. package/src/release-loop/gate-shards.ts +48 -4
  452. package/src/release-loop/landed-to-green.ts +81 -0
  453. package/src/release-loop/light-rc.ts +11 -1
  454. package/src/release-loop/merged-pr-checklist.ts +10 -0
  455. package/src/release-loop/placement.ts +91 -22
  456. package/src/release-loop/rehearsal.ts +317 -0
  457. package/src/release-loop/release-schedule.ts +13 -1
  458. package/src/release-loop/rubric-types.ts +1 -0
  459. package/src/release-loop/rubric.ts +2 -2
  460. package/src/retro/daily.ts +23 -9
  461. package/src/seat-loop/seat-loop.ts +34 -1
  462. package/src/seat-loop/traffic-signal.ts +44 -0
  463. package/src/self-dev/ask-launch-flow.ts +2 -2
  464. package/src/self-dev/dev-cli.ts +67 -3
  465. package/src/self-dev/dev-pipeline.ts +4 -6
  466. package/src/self-dev/draft-residue.ts +463 -0
  467. package/src/self-dev/draft-sweep.ts +151 -10
  468. package/src/self-dev/draft-triage-rules.ts +27 -1
  469. package/src/self-dev/launch-preflight-text.ts +549 -0
  470. package/src/self-dev/launch-preflight.ts +10 -545
  471. package/src/self-dev/orchestrate-cli.ts +57 -2
  472. package/src/self-dev/orchestrate-summary-line.ts +13 -0
  473. package/src/self-dev/orchestrate.ts +8 -135
  474. package/src/self-dev/review-provider-fallback.ts +115 -19
  475. package/src/self-dev/run-store.ts +1 -3
  476. package/src/self-dev/run-supervisor.ts +3 -22
  477. package/src/self-dev/run-types.ts +178 -0
  478. package/src/self-dev/shard-aggregate.ts +61 -13
  479. package/src/self-dev/shard-plan.ts +5 -1
  480. package/src/self-dev/shard-run.ts +23 -5
  481. package/src/self-dev/supervisor-verdict-edges.ts +2 -4
  482. package/src/self-implement/blocked-draft-policy.ts +3 -19
  483. package/src/self-implement/draft-on-stop-mode.ts +18 -0
  484. package/src/self-implement/follow-up-goals.ts +114 -38
  485. package/src/self-implement/gate-baseline-reap.ts +157 -0
  486. package/src/self-implement/gate-baseline.ts +78 -16
  487. package/src/self-implement/gate-cli.ts +12 -2
  488. package/src/self-implement/gate-remote.ts +17 -6
  489. package/src/self-implement/goal-author.ts +24 -4
  490. package/src/self-implement/goal-digest.ts +19 -0
  491. package/src/self-implement/graph-overlay-condition.ts +4 -0
  492. package/src/self-implement/headless-elanous-driver.ts +11 -9
  493. package/src/self-implement/host-regate.ts +120 -29
  494. package/src/self-implement/l8-merge-queue.ts +67 -5
  495. package/src/self-implement/merge-train.ts +131 -0
  496. package/src/self-implement/off-diff-evidence.ts +9 -0
  497. package/src/self-implement/orchestrator.ts +133 -16
  498. package/src/self-implement/review-finding-recurrence.ts +28 -0
  499. package/src/self-implement/rework-policy.ts +2 -1
  500. package/src/self-implement/round-summary-card.ts +63 -0
  501. package/src/self-implement/run-ledger.ts +4 -3
  502. package/src/self-implement/run-step-projection.ts +147 -0
  503. package/src/self-implement/run-stop.ts +1 -1
  504. package/src/self-implement/seams.ts +36 -3
  505. package/src/self-implement/self-implement-cli.ts +3 -1
  506. package/src/self-implement/train-gate-remote.ts +158 -0
  507. package/src/session-runtime/index.ts +10 -1
  508. package/src/session-runtime/retry-api.ts +11 -1
  509. package/src/skills/gift-install.ts +119 -0
  510. package/src/skills/runner.ts +59 -2
  511. package/src/skills/skill-feedback.ts +31 -1
  512. package/src/skills/skill-tier.ts +1 -0
  513. package/src/smart-wizard/capability-index.ts +231 -0
  514. package/src/smart-wizard/rung.ts +74 -0
  515. package/src/steward/launch.ts +20 -9
  516. package/src/steward/triage.ts +4 -2
  517. package/src/storage/file-lock.ts +8 -1
  518. package/src/task-agent/actions.ts +4 -0
  519. package/src/task-agent/card-evidence.ts +59 -13
  520. package/src/task-agent/judge.ts +4 -3
  521. package/src/task-agent/land-worktree.ts +201 -0
  522. package/src/task-agent/live-move-history.ts +133 -0
  523. package/src/task-agent/live-moves.ts +106 -19
  524. package/src/task-agent/parent-host.ts +117 -8
  525. package/src/task-agent/rejudge-on-head.ts +297 -0
  526. package/src/task-agent/review-result-capture.ts +218 -0
  527. package/src/task-agent/shadow.ts +103 -7
  528. package/src/task-agent/task-hand.ts +136 -11
  529. package/src/task-orchestrator/surfaces/pod-child-providers.ts +29 -0
  530. package/src/task-orchestrator/surfaces/pod-command-job.ts +6 -3
  531. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +16 -2
  532. package/src/task-orchestrator/surfaces/pod-image-source.ts +212 -0
  533. package/src/task-orchestrator/surfaces/pod-lease.ts +93 -12
  534. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +25 -2
  535. package/src/task-orchestrator/surfaces/pod-pool.ts +66 -14
  536. package/src/task-orchestrator/surfaces/self-implement-pod.ts +259 -36
  537. package/src/task-orchestrator/surfaces/self-implement.ts +6 -2
  538. package/src/telegram-service.ts +5 -1
  539. package/src/telegram.ts +17 -4
  540. package/src/time/format.ts +13 -4
  541. package/src/tool-runtime/goal-author-runtime.ts +1 -0
  542. package/src/tool-runtime/self-cognition-catalog.ts +23 -0
  543. package/src/tool-runtime/self-cognition-runtimes.ts +2 -24
  544. package/src/user-config.ts +132 -24
  545. package/src/ux-sim/slash-menu-frames.ts +168 -0
  546. package/src/version/packed-revision.json +1 -1
  547. package/src/web-terminal/preview-tap-registry.ts +5 -2
  548. package/src/workflow-runtime/triggers/scheduler.ts +1 -0
  549. package/apps/pwa/out/_next/static/chunks/1109.78a7a3288c0259d9.js +0 -148
  550. package/apps/pwa/out/_next/static/chunks/115.1c6690b8604f81c4.js +0 -32
  551. package/apps/pwa/out/_next/static/chunks/1262.76a3f08e67c5f816.js +0 -309
  552. package/apps/pwa/out/_next/static/chunks/1307-08b716476f1d50af.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/1358d292.5c87f12cad6eaa91.js +0 -122
  554. package/apps/pwa/out/_next/static/chunks/1438.27a1a7b8f2308004.js +0 -149
  555. package/apps/pwa/out/_next/static/chunks/1442.02d85cd88f4c1eac.js +0 -79
  556. package/apps/pwa/out/_next/static/chunks/1501-1aad662d82ba43f7.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/1584.9e2dd53da6e6d4b1.js +0 -24
  558. package/apps/pwa/out/_next/static/chunks/1586.b989b0614afb77e6.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/1609.2ad355062870151f.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/1612-f6df0fc0eed7157b.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/1826-5d279da64bbbc2de.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/1923.37f1d5fe7ebe3860.js +0 -27
  563. package/apps/pwa/out/_next/static/chunks/195-fb1d7690bf30bab4.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1986-33e13d648a9df765.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1993.3fd074a2a246234e.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/211-9c9090c59e2c5907.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/2140.d2daf9ee96e295d1.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/2196-4700653d12a44b40.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/2212.0359851457473efc.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/224.583e562365a52f74.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/2328.0f37465646bafa7d.js +0 -36
  572. package/apps/pwa/out/_next/static/chunks/2372.bf71372184991937.js +0 -286
  573. package/apps/pwa/out/_next/static/chunks/2489-d238d3e2eb5b2bf5.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/2537-6c289376caa88ca1.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/2549-a8515c86f9e8cb96.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/2655.72cc6a97276c5acc.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2699-325cc923ba7b8631.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/2743-ef6e8c3ced74cce5.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/2840-5458ad50c49cac6a.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/2856.f75d5baef7f49b74.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/311.e685738f92e6e2ec.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/3194-807b212fb8eae065.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/3324-d1d2979821dfa845.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/3344.0de4b0ec5a454b7a.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/335.a13f339e97893437.js +0 -94
  586. package/apps/pwa/out/_next/static/chunks/3394.646348f34b2500be.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3443.6276909b53d72d53.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/3495.abd4254d808bf2dc.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3558-bbb5ab553a0471d3.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3721.ba5b82db0d9a5572.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/3857-5985236d9307f676.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/3916-3d02dd1fc257dd3c.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/3919.9ff7dc25afefee33.js +0 -74
  594. package/apps/pwa/out/_next/static/chunks/3998.bd9a69d9b50e9bd2.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4003.ab6db1dc266576c9.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4144-fad095b48a1862ee.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4216.e8ac94b9fe6b96ab.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/4327.c44dc2b55cb43ee5.js +0 -34
  599. package/apps/pwa/out/_next/static/chunks/4401.94257d497b6d26bc.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/4559.17ca2cdbaa8d414f.js +0 -115
  601. package/apps/pwa/out/_next/static/chunks/4565-3d7e3fdeb43686a8.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/4706.97e734bd4c9816ca.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/4795-f372490b178583fc.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/4982.6e44352f751b9a1b.js +0 -77
  605. package/apps/pwa/out/_next/static/chunks/5342.49c5c5a530e62b50.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5360-08a80abdf3a4da99.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5431.66c58ab1327ee0b7.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5633-d6852385000738ef.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5717.bcfcb96e701b82e0.js +0 -90
  610. package/apps/pwa/out/_next/static/chunks/5755-30d102586789bf7f.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5957.3f1a4012388dd962.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/5977-5b9e8a45a5b0c823.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/602.9bf02ac8e9502598.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/6020.3a1b347e2d2dfacc.js +0 -8
  615. package/apps/pwa/out/_next/static/chunks/6375.fce1d174ba6d0324.js +0 -64
  616. package/apps/pwa/out/_next/static/chunks/6546.92a828aef441271f.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/658.957fdb0a8c6c6c8e.js +0 -287
  618. package/apps/pwa/out/_next/static/chunks/6706.323590aabb8b1293.js +0 -226
  619. package/apps/pwa/out/_next/static/chunks/6747.b67947f293a4c02d.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/6868.000b24a3045c5574.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6877-74399f69c7da1433.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6946.bba74e9c96050f30.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/7033.a558f1b2f6912a53.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/7065.46029c26c53eac50.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/7087.6fae577d09249bc1.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/722.de8d9801e0f6d414.js +0 -41
  627. package/apps/pwa/out/_next/static/chunks/726.83532d69452ee24b.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7290-f09c928a06c52e2d.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7497.57981e9d7a75a52a.js +0 -24
  630. package/apps/pwa/out/_next/static/chunks/7672.4af122ad892117c7.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/771.6ab889a233e7dae7.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7797-df5aa0381fdc078f.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/8060-cc008cc6fedfa818.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/8085-d065d0393c1760f5.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/8096.f7da0776cfde6300.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8401-35e94e9091f5eb8d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8682-7061dd4fa7bd62ed.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8695-846034ce44852c70.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8769.815ca69879f608b4.js +0 -104
  640. package/apps/pwa/out/_next/static/chunks/8857-aa1cc4ac90af4d40.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8f835b4f.048eeb02299e3e12.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/9068.5f2764fccf86c1b2.js +0 -93
  643. package/apps/pwa/out/_next/static/chunks/9103-60fbef33e66f0a46.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/9247-55bcfbb0e8057f59.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/935.4ddaa99fc1d1126c.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/9451.ebfb0dcc9c02250f.js +0 -23
  647. package/apps/pwa/out/_next/static/chunks/9559.e648369b1d57cf9a.js +0 -62
  648. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c1a96669158471ec.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/approvals/page-88459e0903da2803.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-d85c43f46f58716b.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/board/page-4e645600579ae952.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/botlab/page-87edbfd19117823b.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/bots/page-7f0c2b7801ac6a54.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/ceo/page-bf1f030a9d1adffd.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/chat/page-cbaf66b1e1804adf.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/control/page-9f5610caaa06178c.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/decisions/page-ec8f3575e339de74.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/design-check/page-86d753e460f1a989.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/editor/page-4166a7d51cf0a57d.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/exec/page-2a19c5cd3b562580.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/field/page-b6a09cde2e07521a.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c1a96669158471ec.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/inside/page-f7eae1518ca0c353.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/intake/page-456a8573ad811381.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/layout-8462d6a543cbb2d9.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/live/page-2974cdfb87c0f9c9.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f927ffa25f3c86d1.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/loops/page-abd86cd832aaa011.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/market/page-79daf68f6256adaa.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8c3f168fc3f91939.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/morning/page-786fb4504d0f2fa9.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/not-found-75209f14597dcb8f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/observatory/page-bf30affe3a85af7e.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1187a44b7515434b.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-3d0910185a66ed54.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f401ee1dd5a26e25.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5dfe7604fd842784.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/page-76cf838050a8d681.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7ec8e289b4c14df6.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-8c8ac17d52be2a79.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/sessions/page-d359ab048d63a9d9.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-b8b345c880bf78d1.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/settings/page-f151cc10ad026940.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-9875f103057da433.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c1a96669158471ec.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/setup/page-9789328af9a9aa62.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/share/page-bf495a1e284f4e00.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/showroom/page-a263d94bca4be22a.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/tasks/page-3962eab8ec58d16e.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/term/page-9abcfac07e02a542.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/today/page-bee49f927c333abb.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/trace/page-bac2d56dcb02d955.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/vault/page-937cbcc13176295c.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-d09495594f7f480d.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/workflows/page-69cb93d1a2e57e0e.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/workspace/page-72ec543928d67c3e.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-82906eeda0186a7b.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/f6231284-45726550aba08fca.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/main-59fe95fed40c7a01.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/main-app-4ca74dbbee7057c6.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/pages/_app-13a0a886df4d97a1.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/pages/_error-6af8591cd3a3f038.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/webpack-f2b4016b9b981bc8.js +0 -1
  704. package/apps/pwa/out/_next/static/css/f2bd5257e6af88d8.css +0 -1
  705. /package/apps/pwa/out/_next/static/{aBi6EyMtLsrl7J8eH4kF7 → rfkMm4movqkqMebBrCXiR}/_ssgManifest.js +0 -0
@@ -3,6 +3,9 @@
3
3
  // substitute template variables, and run them through the selected LLM provider.
4
4
 
5
5
  import { debug } from '../debug/log.js';
6
+ import type { SkillTier } from './skill-tier.js';
7
+ import { randomUUID } from 'node:crypto';
8
+ import { recordSkillRunSafe, type SkillRun } from './skill-feedback.js';
6
9
  import { readFileSync, readdirSync, existsSync, statSync } from 'fs';
7
10
  import { join } from 'path';
8
11
  import { LOCAL_SKILLS_DIR } from '../config.js';
@@ -307,7 +310,7 @@ export interface SkillManifest {
307
310
  }
308
311
 
309
312
  /** Ordered weak→strong. Session 21. */
310
- export type SkillTier = 'T3' | 'T2' | 'T1';
313
+ export type { SkillTier } from './skill-tier.js';
311
314
  const TIER_RANK: Record<SkillTier, number> = { T3: 1, T2: 2, T1: 3 };
312
315
 
313
316
  /** True when `active` is at least as strong as `min`. Missing `min`
@@ -690,6 +693,9 @@ export interface ExecuteSkillOpts {
690
693
  * pure-builder input so tests and future callers can reason about
691
694
  * the final message shape without opening the SQLite store. */
692
695
  promptBankContext?: string;
696
+ /** Use this provider instead of resolving one from config/model hint
697
+ * (tests and hosts that already hold a provider). */
698
+ provider?: LLMProvider;
693
699
  }
694
700
 
695
701
  export interface ExecuteSkillResult {
@@ -968,6 +974,57 @@ export async function executeSkill(
968
974
  args: string,
969
975
  onChunk: (delta: string, full: string) => void,
970
976
  opts: ExecuteSkillOpts = {},
977
+ ): Promise<ExecuteSkillResult> {
978
+ // SK1: one feedback ledger line per run. Recording is fail-soft — the
979
+ // result returned and the exception thrown are exactly the run's own.
980
+ let started: number | undefined;
981
+ try { started = Date.now(); } catch { /* clock trouble must not block the skill */ }
982
+ const feedback = (outcome: SkillRun['outcome'], failureKind?: string): SkillRun => ({
983
+ skill: manifest.name,
984
+ runId: randomUUID(),
985
+ outcome,
986
+ ...(failureKind ? { failureKind } : {}),
987
+ userCorrected: false,
988
+ retries: 0,
989
+ durationMs: started === undefined ? 0 : Math.max(0, Date.now() - started),
990
+ at: new Date().toISOString(),
991
+ });
992
+ const record = (outcome: SkillRun['outcome'], failureKind?: string): void => {
993
+ try {
994
+ recordSkillRunSafe(feedback(outcome, failureKind));
995
+ } catch (error) {
996
+ // Building the record itself failed — still fail-soft, still observed.
997
+ try {
998
+ debug.log('skill.feedback', 'record-failed', { skill: manifest.name, error: String(error) }, { level: 'warn' });
999
+ } catch { /* never let observation change the skill outcome */ }
1000
+ }
1001
+ };
1002
+ let result: ExecuteSkillResult;
1003
+ try {
1004
+ result = await executeSkillUnrecorded(manifest, args, onChunk, opts);
1005
+ } catch (error) {
1006
+ record('failure', skillFailureKind(error));
1007
+ throw error;
1008
+ }
1009
+ record('success');
1010
+ return result;
1011
+ }
1012
+
1013
+ /** Failure kind for the feedback ledger: the exception's name, else 'error'. */
1014
+ function skillFailureKind(error: unknown): string {
1015
+ try {
1016
+ const name = (error as { name?: unknown } | null)?.name;
1017
+ return typeof name === 'string' && name !== '' ? name : 'error';
1018
+ } catch {
1019
+ return 'error';
1020
+ }
1021
+ }
1022
+
1023
+ async function executeSkillUnrecorded(
1024
+ manifest: SkillManifest,
1025
+ args: string,
1026
+ onChunk: (delta: string, full: string) => void,
1027
+ opts: ExecuteSkillOpts,
971
1028
  ): Promise<ExecuteSkillResult> {
972
1029
  debug.log('skill.router', 'executeSkill', {
973
1030
  skill: manifest.name,
@@ -982,7 +1039,7 @@ export async function executeSkill(
982
1039
  // vars. Previously getProvider(modelHint) — env-only — meant a user
983
1040
  // with config.provider=openai-codex but XAI_API_KEY still in env
984
1041
  // would see every skill fall back to Grok.
985
- const provider: LLMProvider = resolveDefaultProvider(rawModelHint);
1042
+ const provider: LLMProvider = opts.provider ?? resolveDefaultProvider(rawModelHint);
986
1043
  // If the skill's declared model belongs to a DIFFERENT provider
987
1044
  // family than the one user-config resolved to, drop it. Example:
988
1045
  // user has openai-codex configured but a skill's SKILL.md says
@@ -1,5 +1,7 @@
1
- import { appendFileSync, readFileSync } from 'node:fs';
1
+ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
2
+ import { join } from 'node:path';
2
3
  import { debug } from '../debug/log.js';
4
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
3
5
 
4
6
  export interface SkillRun {
5
7
  skill: string;
@@ -25,6 +27,34 @@ export function appendSkillRun(ledgerPath: string, run: SkillRun): void {
25
27
  appendFileSync(ledgerPath, `${JSON.stringify(run)}\n`, 'utf8');
26
28
  }
27
29
 
30
+ /**
31
+ * Ledger for skill runs: `<root>/skills/feedback.jsonl`, root defaulting to the
32
+ * effective instance (state) root — never a skill folder. Creates the directory.
33
+ */
34
+ export function skillFeedbackLedgerPath(root: string = effectiveInstanceRoot()): string {
35
+ const dir = join(root, 'skills');
36
+ mkdirSync(dir, { recursive: true });
37
+ return join(dir, 'feedback.jsonl');
38
+ }
39
+
40
+ /**
41
+ * Fail-soft record of one skill run: resolving or writing the ledger never
42
+ * throws to the caller; a failure leaves a single `record-failed` observation.
43
+ */
44
+ export function recordSkillRunSafe(run: SkillRun, ledgerPath?: string): void {
45
+ try {
46
+ appendSkillRun(ledgerPath ?? skillFeedbackLedgerPath(), run);
47
+ } catch (error) {
48
+ try {
49
+ debug.log('skill.feedback', 'record-failed', { skill: run.skill, error: String(error) }, { level: 'warn' });
50
+ } catch { /* observation must not break the skill result either */ }
51
+ return;
52
+ }
53
+ try {
54
+ debug.log('skill.feedback', 'recorded', { skill: run.skill, outcome: run.outcome, durationMs: run.durationMs });
55
+ } catch { /* fail-soft */ }
56
+ }
57
+
28
58
  /** Read the JSONL ledger in append order; an absent ledger has no runs. */
29
59
  export function readSkillRuns(ledgerPath: string): SkillRun[] {
30
60
  let text: string;
@@ -0,0 +1 @@
1
+ export type SkillTier = 'T3' | 'T2' | 'T1';
@@ -0,0 +1,231 @@
1
+ import { Database } from 'bun:sqlite';
2
+ import { existsSync, readFileSync, readdirSync, statSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
4
+ import { elanousStateRoot } from '../autopilot/state-paths.js';
5
+ import { buildCapabilityMatrix } from '../agent-mission/capability-matrix.js';
6
+ import { createCapabilityReaders } from '../agent-mission/capability-readers.js';
7
+ import type { CapabilityEntry } from '../agent-mission/capability-types.js';
8
+ import { readCodexPluginsFromAppServer, type CodexPluginObservation } from '../acp/codex-plugins.js';
9
+ import { kgsDefaultDbPath } from '../knowledge/kgs/sqlite-store.js';
10
+ import { OFFICIAL_INDEX_KEYS } from '../market/official-keys.js';
11
+ import { verifyIndex, type MarketplaceIndex } from '../market/signed-index.js';
12
+ import { readClaudePackageLedger, type ClaudePackageLedger } from '../plugins/adapters/claude-package.js';
13
+ import { ELANOUS_MARKET_URL } from '../plugins/install/market-fetch.js';
14
+ import { buildSkillIndex, skillIndexProblems, type SkillIndexEntry } from '../skills/index.js';
15
+ import { defaultSkillDirs } from '../user-config.js';
16
+
17
+ export type CapabilitySource = 'skills' | 'plugins' | 'knowledge' | 'codex' | 'claude' | 'market';
18
+ export type CapabilityAuth = 'subscription' | 'free' | 'api-key' | 'paid' | 'unknown';
19
+ export interface IndexedCapability {
20
+ readonly id: string;
21
+ readonly kind: 'skill' | 'plugin' | 'knowledge' | 'connector';
22
+ readonly source: CapabilitySource;
23
+ readonly provenance: string;
24
+ readonly auth: CapabilityAuth;
25
+ readonly state: 'installed' | 'candidate' | 'ready' | 'unavailable' | 'unknown';
26
+ readonly capabilities: readonly string[];
27
+ }
28
+ export interface CapabilityIndex {
29
+ readonly sources: Record<CapabilitySource, 'ok' | 'unknown'>;
30
+ readonly entries: readonly IndexedCapability[];
31
+ }
32
+
33
+ export interface CapabilityIndexReaders {
34
+ skills?: () => readonly SkillIndexEntry[];
35
+ skillProblems?: () => readonly { name: string; dir: string }[];
36
+ plugins?: () => readonly { name: string; market: string }[];
37
+ knowledge?: () => readonly { name: string; provenance: string }[];
38
+ codex?: () => Promise<CodexPluginObservation>;
39
+ claude?: () => ClaudePackageLedger;
40
+ /** Production verifies fetched bytes; tests may inject a checked fixture. */
41
+ market?: () => Promise<MarketplaceIndex>;
42
+ matrix?: () => readonly CapabilityEntry[];
43
+ /** Default-path observations (used only when `skills` / `plugins` are not injected). */
44
+ localSkills?: () => LocalSkillsObservation;
45
+ localPlugins?: () => LocalPluginsObservation;
46
+ /** Already verified by the caller (never accepts unverified JSON). */
47
+ verifiedMarket?: MarketplaceIndex;
48
+ }
49
+
50
+ export interface LocalSkillsObservation {
51
+ readonly entries: readonly SkillIndexEntry[];
52
+ /** Roots that exist (or could not be proven absent) but could not be read. */
53
+ readonly unreadableRoots: readonly string[];
54
+ }
55
+
56
+ /** Per-root read: an unreadable root is reported, readable roots keep their candidates. */
57
+ export function readLocalSkills(dirs: readonly string[] = defaultSkillDirs()): LocalSkillsObservation {
58
+ // A missing root is optional; any other stat/read failure must remain unknown.
59
+ const readable: string[] = [];
60
+ const unreadableRoots: string[] = [];
61
+ for (const dir of dirs) {
62
+ try {
63
+ if (!statSync(dir).isDirectory()) throw new Error('skill root is not a directory');
64
+ readdirSync(dir);
65
+ readable.push(dir);
66
+ } catch (error) {
67
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') continue;
68
+ unreadableRoots.push(dir);
69
+ }
70
+ }
71
+ return { entries: readable.length ? buildSkillIndex(readable) : [], unreadableRoots };
72
+ }
73
+
74
+ /** Strict form: throws when any root is unreadable. */
75
+ export function listLocalSkills(dirs: readonly string[] = defaultSkillDirs()): readonly SkillIndexEntry[] {
76
+ const observed = readLocalSkills(dirs);
77
+ if (observed.unreadableRoots.length) throw new Error(`unreadable skill roots: ${observed.unreadableRoots.join(', ')}`);
78
+ return observed.entries;
79
+ }
80
+
81
+ export interface LocalPluginsObservation {
82
+ readonly plugins: readonly { name: string; market: string }[];
83
+ /** `absent` = ENOENT (no installs recorded); `unreadable` = exists but stat/read/parse failed. */
84
+ readonly ledger: 'ok' | 'absent' | 'unreadable';
85
+ /** Plugin directories that exist (or could not be proven absent) but could not be listed. */
86
+ readonly unreadableDirs: readonly string[];
87
+ }
88
+
89
+ /** ENOENT → absent; every other failure is a read failure, never "no candidates". */
90
+ function statKind(path: string, want: 'any' | 'file' = 'any'): 'present' | 'absent' | 'unreadable' {
91
+ try { const stat = statSync(path); return want === 'file' && !stat.isFile() ? 'absent' : 'present'; }
92
+ catch (error) { return (error as NodeJS.ErrnoException).code === 'ENOENT' ? 'absent' : 'unreadable'; }
93
+ }
94
+
95
+ export function readLocalPlugins(
96
+ ledgerPath: string = join(elanousStateRoot(), 'plugins', 'installed.json'),
97
+ localDirs: readonly string[] = [resolve(import.meta.dir, '../../plugins')],
98
+ ): LocalPluginsObservation {
99
+ const plugins: { name: string; market: string }[] = [];
100
+ let ledger: LocalPluginsObservation['ledger'] = 'absent';
101
+ const ledgerKind = statKind(ledgerPath);
102
+ if (ledgerKind === 'unreadable') ledger = 'unreadable';
103
+ else if (ledgerKind === 'present') {
104
+ try {
105
+ const rows: unknown = JSON.parse(readFileSync(ledgerPath, 'utf8'));
106
+ if (!Array.isArray(rows) || !rows.every(row => row && typeof row.name === 'string' && typeof row.market === 'string')) throw new Error('invalid installed plugin ledger');
107
+ plugins.push(...rows.map(row => ({ name: row.name as string, market: row.market as string })));
108
+ ledger = 'ok';
109
+ } catch { ledger = 'unreadable'; }
110
+ }
111
+ const unreadableDirs: string[] = [];
112
+ for (const dir of localDirs) {
113
+ const kind = statKind(dir);
114
+ if (kind === 'absent') continue;
115
+ const found: { name: string; market: string }[] = [];
116
+ try {
117
+ if (kind === 'unreadable') throw new Error('plugin directory unreadable');
118
+ for (const item of readdirSync(dir, { withFileTypes: true })) {
119
+ if (!item.isDirectory()) continue;
120
+ const path = join(dir, item.name);
121
+ const manifests = [statKind(join(path, 'plugin.ts'), 'file'), statKind(join(path, 'plugin.json'), 'file')];
122
+ if (manifests.includes('present')) found.push({ name: item.name, market: dir });
123
+ else if (manifests.includes('unreadable')) unreadableDirs.push(path);
124
+ }
125
+ plugins.push(...found);
126
+ } catch { unreadableDirs.push(dir); }
127
+ }
128
+ return { plugins, ledger, unreadableDirs };
129
+ }
130
+
131
+ function listLocalKnowledge(): readonly { name: string; provenance: string }[] {
132
+ const path = kgsDefaultDbPath();
133
+ if (!existsSync(path)) throw new Error('knowledge store unavailable');
134
+ const db = new Database(path, { readonly: true, create: false });
135
+ try {
136
+ return (db.query('SELECT slug, version FROM kgs_pack ORDER BY slug, version').all() as Array<{ slug: string; version: string }>)
137
+ .map(row => ({ name: `${row.slug}@${row.version}`, provenance: path }));
138
+ } finally { db.close(); }
139
+ }
140
+
141
+ async function readOfficialMarket(): Promise<MarketplaceIndex> {
142
+ const url = new URL('marketplace.json', ELANOUS_MARKET_URL);
143
+ const [raw, sig] = await Promise.all([fetch(url), fetch(new URL('index.sig', url))]);
144
+ if (!raw.ok || !sig.ok) throw new Error('official index unavailable');
145
+ const checked = verifyIndex({ marketplaceBytes: new Uint8Array(await raw.arrayBuffer()), signatureText: await sig.text(), trustedKeys: OFFICIAL_INDEX_KEYS });
146
+ if (!checked.ok || checked.index.name !== 'elanous') throw new Error('official index unverified');
147
+ return checked.index;
148
+ }
149
+
150
+ function marketAuth(entry: MarketplaceIndex['plugins'][number]): CapabilityAuth {
151
+ const policy = entry.policy?.authentication?.toLowerCase();
152
+ if (policy === 'api-key' || policy === 'api_key') return 'api-key';
153
+ if (policy === 'subscription') return 'subscription';
154
+ if (policy === 'paid') return 'paid';
155
+ if (policy === 'none' || policy === 'free') return 'free';
156
+ return 'unknown';
157
+ }
158
+
159
+ /** Read-only, per-source index. No source failure is interpreted as an empty inventory. */
160
+ export async function buildCapabilityIndex(readers: CapabilityIndexReaders = {}): Promise<CapabilityIndex> {
161
+ const sources: CapabilityIndex['sources'] = { skills: 'ok', plugins: 'ok', knowledge: 'ok', codex: 'ok', claude: 'ok', market: 'ok' };
162
+ const entries: IndexedCapability[] = [];
163
+ const attempt = async (source: CapabilitySource, read: () => Promise<void> | void): Promise<void> => {
164
+ const start = entries.length;
165
+ try { await read(); } catch { sources[source] = 'unknown'; entries.splice(start); }
166
+ };
167
+ await attempt('skills', () => {
168
+ const observed: LocalSkillsObservation = readers.skills
169
+ ? { entries: readers.skills(), unreadableRoots: [] }
170
+ : (readers.localSkills ?? readLocalSkills)();
171
+ for (const skill of observed.entries) entries.push({ id: skill.name, kind: 'skill', source: 'skills', provenance: skill.rootDir, auth: 'unknown', state: 'installed', capabilities: [skill.name] });
172
+ if (observed.unreadableRoots.length) {
173
+ sources.skills = 'unknown';
174
+ for (const dir of observed.unreadableRoots) entries.push({ id: dir, kind: 'skill', source: 'skills', provenance: dir, auth: 'unknown', state: 'unknown', capabilities: [] });
175
+ }
176
+ const problems = (readers.skillProblems ?? skillIndexProblems)();
177
+ if (problems.length) {
178
+ sources.skills = 'unknown';
179
+ for (const problem of problems) entries.push({ id: problem.name, kind: 'skill', source: 'skills', provenance: problem.dir, auth: 'unknown', state: 'unknown', capabilities: [problem.name] });
180
+ }
181
+ });
182
+ let installed: readonly { name: string; market: string }[] | undefined;
183
+ await attempt('plugins', () => {
184
+ if (readers.plugins) installed = readers.plugins();
185
+ else {
186
+ const observed = (readers.localPlugins ?? readLocalPlugins)();
187
+ installed = observed.plugins;
188
+ // Absent ledger keeps the earlier contract (unknown); unreadable ledger/dirs never read as "no installs".
189
+ if (observed.ledger !== 'ok' || observed.unreadableDirs.length) sources.plugins = 'unknown';
190
+ for (const dir of observed.unreadableDirs) entries.push({ id: dir, kind: 'plugin', source: 'plugins', provenance: dir, auth: 'unknown', state: 'unknown', capabilities: [] });
191
+ }
192
+ for (const plugin of installed) entries.push({ id: plugin.name, kind: 'plugin', source: 'plugins', provenance: plugin.market, auth: 'unknown', state: 'installed', capabilities: [plugin.name] });
193
+ });
194
+ await attempt('knowledge', () => {
195
+ for (const pack of (readers.knowledge ?? listLocalKnowledge)()) entries.push({ id: pack.name, kind: 'knowledge', source: 'knowledge', provenance: pack.provenance, auth: 'unknown', state: 'installed', capabilities: [pack.name] });
196
+ });
197
+ await attempt('codex', async () => {
198
+ const observation = await (readers.codex ?? readCodexPluginsFromAppServer)();
199
+ if (observation.status === 'unknown') { sources.codex = 'unknown'; return; }
200
+ for (const plugin of observation.plugins) entries.push({ id: plugin.name, kind: 'plugin', source: 'codex', provenance: plugin.marketplace, auth: 'unknown', state: plugin.enabled ? 'installed' : 'unavailable', capabilities: [plugin.name] });
201
+ });
202
+ await attempt('claude', () => {
203
+ const ledger = (readers.claude ?? readClaudePackageLedger)();
204
+ if (ledger.status !== 'ok') sources.claude = 'unknown';
205
+ for (const pkg of ledger.packages) entries.push({ id: pkg.plugin, kind: 'plugin', source: 'claude', provenance: `${pkg.marketplace}:${pkg.source}`, auth: 'unknown', state: 'installed', capabilities: [pkg.plugin] });
206
+ });
207
+ await attempt('market', async () => {
208
+ const index = readers.verifiedMarket ?? await (readers.market ?? readOfficialMarket)();
209
+ if (index.name !== 'elanous') throw new Error('not official market');
210
+ for (const plugin of index.plugins) {
211
+ entries.push({ id: plugin.name, kind: 'plugin', source: 'market', provenance: `${index.name}:${plugin.source.source}`, auth: marketAuth(plugin),
212
+ state: sources.plugins === 'unknown' ? 'unknown' : installed?.some(row => row.name === plugin.name && row.market === index.name) ? 'installed' : 'candidate',
213
+ capabilities: [plugin.name, ...plugin['ai.elanous'].capabilities, ...(plugin['ai.elanous'].vocab ?? [])] });
214
+ for (const connector of plugin['ai.elanous'].connectors) entries.push({ id: connector.id, kind: 'connector', source: 'market', provenance: `${index.name}:${plugin.name}`, auth: marketAuth(plugin), state: sources.plugins === 'unknown' ? 'unknown' : 'candidate', capabilities: [connector.id] });
215
+ }
216
+ for (const pack of index.knowledgePacks ?? []) {
217
+ if (pack.visibility !== 'public') continue;
218
+ entries.push({ id: pack.name, kind: 'knowledge', source: 'market', provenance: index.name, auth: 'unknown', state: 'candidate', capabilities: [pack.name] });
219
+ }
220
+ });
221
+ // Matrix is an additional service observation, not proof of plugin installation.
222
+ let matrix: readonly CapabilityEntry[] = [];
223
+ try { matrix = (readers.matrix ?? (() => buildCapabilityMatrix(createCapabilityReaders())))(); }
224
+ catch { /* Matrix is supplementary; plugin inventories keep their own observation status. */ }
225
+ for (const service of matrix) {
226
+ // Only backends that are index sources are attributed; grok has no source row here, so it is not relabelled.
227
+ if (!service.service || service.service === '*' || (service.backend !== 'codex' && service.backend !== 'claude')) continue;
228
+ entries.push({ id: service.service, kind: 'connector', source: service.backend, provenance: `${service.backend}:mcp`, auth: 'unknown', state: service.state, capabilities: [service.service] });
229
+ }
230
+ return { sources, entries };
231
+ }
@@ -0,0 +1,74 @@
1
+ // The condition extraction (including any LLM judgment) happens before this deterministic selector.
2
+ export type WizardRung = 'a' | 'b' | 'c' | 'd' | 'e';
3
+ export type GraphValueSignal = 'verification' | 'rework' | 'approval' | 'branching' | 'resume' | 'parallel' | 'resolution';
4
+
5
+ export type RungConditions = {
6
+ capabilityGaps: number;
7
+ graphSignals: readonly GraphValueSignal[];
8
+ recurring: boolean;
9
+ needsMemory: boolean;
10
+ unattended: boolean;
11
+ roles: number;
12
+ differentCadences: boolean;
13
+ differentPermissions: boolean;
14
+ handoffs: number;
15
+ };
16
+
17
+ export type RungDecision = {
18
+ rung: WizardRung;
19
+ reasons: string[];
20
+ rejectedHigher: string[];
21
+ };
22
+
23
+ const graphSignalNames: readonly GraphValueSignal[] = [
24
+ 'verification', 'rework', 'approval', 'branching', 'resume', 'parallel', 'resolution',
25
+ ];
26
+ const rungOrder: readonly WizardRung[] = ['a', 'b', 'c', 'd', 'e'];
27
+
28
+ /** Select the lowest rung sufficient for the supplied, already-established conditions. */
29
+ export function classifyRung(conditions: RungConditions): RungDecision {
30
+ const { capabilityGaps, graphSignals, recurring, needsMemory, unattended, roles,
31
+ differentCadences, differentPermissions, handoffs } = conditions;
32
+ for (const [name, value] of Object.entries({ capabilityGaps, roles, handoffs })) {
33
+ if (!Number.isSafeInteger(value) || value < 0) throw new RangeError(`${name} must be a non-negative safe integer`);
34
+ }
35
+ if (graphSignals.some(signal => !graphSignalNames.includes(signal))) {
36
+ throw new TypeError('graphSignals contains an unknown signal');
37
+ }
38
+
39
+ const distinctSignals = graphSignalNames.filter(signal => graphSignals.includes(signal));
40
+ const graphWorthwhile = distinctSignals.length >= 2;
41
+ const loopNeeded = recurring && (needsMemory || unattended);
42
+ const collectiveNeeded = roles >= 2 && (differentCadences || differentPermissions) && handoffs >= 1;
43
+ let rung: WizardRung = 'a';
44
+ const reasons: string[] = [];
45
+ if (capabilityGaps > 0) {
46
+ rung = 'b';
47
+ reasons.push(`b: capability gaps ${capabilityGaps} > 0`);
48
+ }
49
+ if (graphWorthwhile) {
50
+ rung = 'c';
51
+ reasons.push(`c: ${distinctSignals.length} graph value signals >= 2 (${distinctSignals.join(', ')})`);
52
+ }
53
+ if (loopNeeded) {
54
+ rung = 'd';
55
+ reasons.push(`d: recurring and ${[needsMemory && 'needs memory', unattended && 'unattended'].filter(Boolean).join(' / ')}`);
56
+ }
57
+ if (collectiveNeeded) {
58
+ rung = 'e';
59
+ reasons.push(`e: ${roles} roles >= 2, ${[differentCadences && 'different cadences', differentPermissions && 'different permissions'].filter(Boolean).join(' / ')}, handoffs ${handoffs} >= 1`);
60
+ }
61
+ if (reasons.length === 0) reasons.push('a: no higher-rung condition met; one skill call or short chain suffices');
62
+
63
+ const rejected = {
64
+ b: `b: capability gaps ${capabilityGaps} = 0`,
65
+ c: `c: ${distinctSignals.length} distinct graph value signals < 2`,
66
+ d: `d: ${!recurring ? 'not recurring' : 'neither memory nor unattended execution'}`,
67
+ e: `e: ${[
68
+ roles < 2 && `roles ${roles} < 2`,
69
+ !differentCadences && !differentPermissions && 'neither different cadences nor different permissions',
70
+ handoffs < 1 && `handoffs ${handoffs} < 1`,
71
+ ].filter(Boolean).join('; ')}`,
72
+ };
73
+ return { rung, reasons, rejectedHigher: rungOrder.slice(rungOrder.indexOf(rung) + 1).map(higher => rejected[higher as keyof typeof rejected]) };
74
+ }
@@ -1,6 +1,8 @@
1
1
  import { randomUUID } from 'node:crypto';
2
2
  import { closeSync, mkdirSync, openSync, readFileSync, renameSync, writeFileSync } from 'node:fs';
3
3
  import { join, resolve } from 'node:path';
4
+ import { getElanousConfigDir } from '../elanous-config-dir.js';
5
+ import { resolveHqLaunchSeat } from '../hq/seats.js';
4
6
  import { debug } from '../debug/log.js';
5
7
  import { publishInsideEvent } from '../nexus/api/inside-events.js';
6
8
  import { redactSecrets } from '../task-cards/card-store.js';
@@ -42,9 +44,11 @@ export interface LaunchDeps {
42
44
  settings: StewardSettings;
43
45
  ledger: LaunchLedger;
44
46
  /** Injected command boundary; the production adapter runs only argv, never a shell. */
45
- command?: (args: string[]) => { exitCode: number; stdout: string; stderr?: string };
46
- spawn?: (args: string[], log: string) => { pid: number };
47
+ command?: (args: string[], seat?: string) => { exitCode: number; stdout: string; stderr?: string };
48
+ spawn?: (args: string[], log: string, seat?: string) => { pid: number };
47
49
  gate?: (goalId: string, budget: BudgetDecision | 'unknown') => PreLaunchGateDecision;
50
+ /** Production commands run from the registered OP view; tests can supply an isolated view. */
51
+ launchSeat?: () => string;
48
52
  }
49
53
 
50
54
  const RUN_ID = /\brun-[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}\b/i;
@@ -52,7 +56,7 @@ const DEFAULT_POOL = 'pool-node-b@node-b:8';
52
56
  // `harness budget --json` outcomes: proceed | next-provider | wait-reset | stop. next-provider still runs (the harness switches provider itself).
53
57
  const BUDGET_PROCEED: readonly string[] = ['proceed', 'next-provider'];
54
58
  const launchMode = (settings: StewardSettings): 'off' | 'shadow' | 'live' => launchModeOf(settings.mode ?? settings.launch ?? 'shadow');
55
- const cli = (args: string[]) => ['bun', 'bin/elanous.mjs', ...(process.env.NODE_ENV === 'test' ? ['--test'] : []), ...args];
59
+ const cli = (args: string[]) => [process.execPath, resolve(import.meta.dir, '../../bin/elanous.mjs'), ...(process.env.NODE_ENV === 'test' ? ['--test'] : []), ...args];
56
60
  const sourceOf = (issue: TriageIssue): string => /^출처: (telegram|pwa|tui|cli)$/m.exec(issue.body)?.[1] ?? `linear:${issue.identifier}`;
57
61
  const promptOf = (issue: TriageIssue): string => `${issue.title}\n${issue.body.slice(0, 1500)}`;
58
62
  const argvFor = (issue: TriageIssue, settings: StewardSettings): string[] =>
@@ -100,15 +104,19 @@ export function planLaunches(rows: ScheduledDecision[], issues: TriageIssue[], l
100
104
  return { launches, hitl };
101
105
  }
102
106
 
103
- function runCommand(args: string[]): { exitCode: number; stdout: string; stderr: string } {
104
- const result = Bun.spawnSync(args, { cwd: resolve(import.meta.dir, '../..'), stdout: 'pipe', stderr: 'pipe' });
107
+ function stewardLaunchSeat(): string {
108
+ return resolveHqLaunchSeat('OP', getElanousConfigDir());
109
+ }
110
+
111
+ function runCommand(args: string[], cwd = resolve(import.meta.dir, '../..')): { exitCode: number; stdout: string; stderr: string } {
112
+ const result = Bun.spawnSync(args, { cwd, stdout: 'pipe', stderr: 'pipe' });
105
113
  return { exitCode: result.exitCode, stdout: result.stdout.toString(), stderr: result.stderr.toString() };
106
114
  }
107
115
 
108
- function spawnDetached(args: string[], log: string): { pid: number } {
116
+ function spawnDetached(args: string[], log: string, seat = stewardLaunchSeat()): { pid: number } {
109
117
  const fd = openSync(log, 'a');
110
118
  try {
111
- const child = Bun.spawn(args, { cwd: resolve(import.meta.dir, '../..'), stdout: fd, stderr: fd, stdin: 'ignore', detached: true });
119
+ const child = Bun.spawn(args, { cwd: seat, stdout: fd, stderr: fd, stdin: 'ignore', detached: true });
112
120
  child.unref();
113
121
  return { pid: child.pid };
114
122
  } finally { closeSync(fd); }
@@ -149,9 +157,12 @@ export function launch(item: LaunchItem, deps: LaunchDeps): LaunchEntry {
149
157
  // L6: a launch must remain on the isolated Pod pool, never fall back to the host or another substrate.
150
158
  if (!/^[a-zA-Z0-9_-]+(?:@[a-zA-Z0-9._-]+(?::[1-9][0-9]*)?)?$/.test(settings.podPool ?? DEFAULT_POOL))
151
159
  return blocked('blocked-location', 'invalid steward pod pool');
160
+ let seat: string;
161
+ try { seat = (deps.launchSeat ?? stewardLaunchSeat)(); }
162
+ catch (error) { return blocked('blocked-location', `steward OP seat unavailable: ${String(error)}`); }
152
163
  let budget: BudgetDecision | 'unknown' = 'unknown';
153
164
  try {
154
- const result = command(cli(['harness', 'budget', '--json']));
165
+ const result = command(cli(['harness', 'budget', '--json']), seat);
155
166
  const decision = result.exitCode === 0 ? lastJson(result.stdout) : {};
156
167
  if (!BUDGET_PROCEED.includes(String(decision.outcome)))
157
168
  return blocked('skipped-budget', result.exitCode === 0 ? JSON.stringify(decision.reasons ?? ['budget unavailable']) : result.stderr ?? 'budget unavailable');
@@ -171,7 +182,7 @@ export function launch(item: LaunchItem, deps: LaunchDeps): LaunchEntry {
171
182
  ledger.launches[key] = entry;
172
183
  saveLaunchLedger(root, ledger);
173
184
  try {
174
- entry.pid = (deps.spawn ?? spawnDetached)(argvFor(item.issue, settings), entry.log).pid;
185
+ entry.pid = (deps.spawn ?? spawnDetached)(argvFor(item.issue, settings), entry.log, seat).pid;
175
186
  } catch (error) {
176
187
  entry.status = 'failed';
177
188
  entry.reason = redactSecrets(String(error));
@@ -62,6 +62,8 @@ export interface StewardDeps {
62
62
  launchSettings?: Pick<StewardSettings, 'mode' | 'launch' | 'maxParallel' | 'podPool'>;
63
63
  launchCommand?: LaunchDeps['command'];
64
64
  spawnLaunch?: LaunchDeps['spawn'];
65
+ /** Isolated OP view for tests; production resolves the registered HQ seat (launch.ts stewardLaunchSeat). */
66
+ launchSeat?: LaunchDeps['launchSeat'];
65
67
  launchGate?: LaunchDeps['gate'];
66
68
  outcomeNotify?: Pick<OutcomeNotifyDeps, 'document' | 'message' | 'worktreeCommand' | 'loadOrigin' | 'loadOrigins'>;
67
69
  /** Internal command boundary: the current sync has already claimed this pid. */
@@ -450,7 +452,7 @@ export async function runStewardStage(stage: 'sync' | 'triage' | 'schedule' | 'r
450
452
  }); } catch { /* logging must not change the schedule */ }
451
453
  writeFileSync(schedule, JSON.stringify(rows));
452
454
  const ledger = readLaunchLedger(root);
453
- const launchDeps: LaunchDeps = { root, settings, ledger, command: deps.launchCommand, spawn: deps.spawnLaunch, gate: deps.launchGate };
455
+ const launchDeps: LaunchDeps = { root, settings, ledger, command: deps.launchCommand, spawn: deps.spawnLaunch, gate: deps.launchGate, launchSeat: deps.launchSeat };
454
456
  const cardDeps = { root, store: deps.cardStore, now: deps.now };
455
457
  collectOutcomes(ledger, launchDeps);
456
458
  const plan = planLaunches(rows, issues, ledger, settings);
@@ -510,7 +512,7 @@ export async function runStewardStage(stage: 'sync' | 'triage' | 'schedule' | 'r
510
512
  writeFileSync(path, JSON.stringify(state));
511
513
  }
512
514
  const ledger = readLaunchLedger(root);
513
- const outcomes = collectOutcomes(ledger, { root, settings, ledger, command: deps.launchCommand, spawn: deps.spawnLaunch });
515
+ const outcomes = collectOutcomes(ledger, { root, settings, ledger, command: deps.launchCommand, spawn: deps.spawnLaunch, launchSeat: deps.launchSeat });
514
516
  for (const outcome of outcomes) {
515
517
  const issue = issues.find(item => item.identifier === outcome.issue) ??
516
518
  { identifier: outcome.issue, title: outcome.title, ref: '', body: '' };
@@ -46,7 +46,7 @@ export interface LockOpts {
46
46
  * (a holder killed with -9 must not wedge waiters for `staleMs`).
47
47
  */
48
48
  breakDeadHolder?: boolean;
49
- /** Sync lock only: called once, the first time the lock is found held by someone else. */
49
+ /** Called once, the first time the lock is found held by someone else. */
50
50
  onWait?: (holder: string) => void;
51
51
  }
52
52
 
@@ -137,6 +137,7 @@ export async function acquireLockAsync(lockPath: string, opts: LockOpts = {}): P
137
137
  const heartbeatMs = Math.max(50, Math.floor(staleMs / 3));
138
138
  // ⭐ **소유 토큰** — inode 보다 강하다(inode 는 재사용된다). 파일 내용이 곧 소유 증명이다.
139
139
  const token = `${process.pid}:${randomUUID()}`;
140
+ let waited = false;
140
141
 
141
142
  for (let attempt = 0; attempt < maxTries; attempt += 1) {
142
143
  try {
@@ -187,6 +188,12 @@ export async function acquireLockAsync(lockPath: string, opts: LockOpts = {}): P
187
188
  } catch {
188
189
  continue;
189
190
  }
191
+ if (!waited && opts.onWait) {
192
+ waited = true;
193
+ let holder = '';
194
+ try { holder = readFileSync(lockPath, 'utf8').trim(); } catch { /* gone */ }
195
+ try { opts.onWait(holder); } catch { /* observer only */ }
196
+ }
190
197
  await new Promise((resolve) => { setTimeout(resolve, retryBusyMs); });
191
198
  }
192
199
  }
@@ -164,6 +164,10 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
164
164
  parsed = item as typeof parsed;
165
165
  } catch { return record('failed', 'invalid review JSON'); }
166
166
  if (parsed.reviewed !== true) return record('failed', 'review was not performed');
167
+ // TA-LAND-MUSTFIX-ZERO — «pass» 라도 must-fix 가 남았거나 수를 못 읽으면 land 로 가지 않는다(#25941 `canAuto` 와 같은 축).
168
+ // `self review --json` 은 mustFix 배열을 «항상» 싣는다 — 배열이 아니면 «0» 이 아니라 «모름»으로 읽는다(fail-closed).
169
+ if (parsed.verdict === 'pass' && (!Array.isArray(parsed.mustFix) || !parsed.mustFix.every(fix => typeof fix === 'string'))) return card('review-must-fix-unknown: pass verdict without a readable must-fix list');
170
+ if (parsed.verdict === 'pass' && parsed.mustFix!.length > 0) return card(`review-warn-with-must-fix: pass verdict carries ${parsed.mustFix!.length} must-fix`);
167
171
  if (parsed.verdict === 'pass') { record('done', 'review pass'); return executeNextAction({ ...action, kind: 'land', history: [...(action.history ?? []), 'review pass'] }, deps); }
168
172
  if (parsed.verdict === 'fail' && Array.isArray(parsed.mustFix) && parsed.mustFix.length > 0 && parsed.mustFix.every(fix => typeof fix === 'string' && fix.trim())) { record('done', 'review fail'); return executeNextAction({ ...action, kind: 'retry', mustFix: parsed.mustFix, history: [...(action.history ?? []), 'review fail'] }, deps); }
169
173
  return card('review verdict or must-fix unavailable');