elanous 0.2.24 → 0.2.27

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 (601) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +36 -0
  9. package/apps/pwa/out/_next/static/chunks/1146.80d15ea7c6e6ee95.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1157.f08bf2b70915e176.js +148 -0
  11. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1454-a9c338f5bb556f42.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{8532.a86e99acf9b761cb.js → 1516.83dd2c1b86b4e507.js} +2 -2
  17. package/apps/pwa/out/_next/static/chunks/{89849432.9eaa2f4c9c010965.js → 16e57f67.3ea19e893461e611.js} +3 -3
  18. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{1505.5826671109111e75.js → 1743.563d3168e95825ef.js} +2 -2
  20. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +27 -0
  21. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2528.3868070ef1be69f9.js +24 -0
  26. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2697.76ca2ac3efef6f3b.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +32 -0
  29. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2846.d6a433b8663819a5.js +309 -0
  31. package/apps/pwa/out/_next/static/chunks/3143.257997a5f1ed79df.js +34 -0
  32. package/apps/pwa/out/_next/static/chunks/{5967-c0a80f8ffe5d4050.js → 3259-86f3be56e43eaf6a.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3309.364573ceedbdfd5f.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +287 -0
  37. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/{5578.ac963634373b28c6.js → 4084.15ecaf4240bd9e77.js} +2 -2
  42. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{8438.ee7f0df3b3f6fcb4.js → 4204.a409ab6250c0f6a8.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +8 -0
  48. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{7905.b230b9d06cb4ad5d.js → 4593.10f5b9bd702d4a6c.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +104 -0
  52. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +149 -0
  54. package/apps/pwa/out/_next/static/chunks/{8569.b853a8daa8f31d12.js → 5081.a240b63fad28663a.js} +1 -1
  55. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/{2528.0af5c0e1fad88df6.js → 5408.377c8c543635b81f.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9502-32c5dc22e8f120f5.js → 5492-e05e26a033ba80d2.js} +3 -3
  62. package/apps/pwa/out/_next/static/chunks/5785-ea8d2c633b6688e3.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/599-a914cc0468f56143.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +23 -0
  68. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{5974.360f8441eb0ac1ec.js → 6196.34d6b229079e9e28.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +77 -0
  73. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +64 -0
  75. package/apps/pwa/out/_next/static/chunks/{ce383d63.d2ede338788ed18e.js → 65ebff95.081daeff622d238e.js} +1 -1
  76. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +2 -0
  78. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{83cfc5c8.349535543c1548b6.js → 6def8a8e.c81f9ca41028eccf.js} +1 -1
  80. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/{2721.bc9a8f36bd85c07a.js → 7483.ba01c6c209b81bba.js} +1 -1
  85. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{6702.ebbd165d5e4a4a14.js → 7752.5cbdd0b433c54af9.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8925-2abfb48af477fb7f.js → 8085-1e5fce59500a2cc2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +226 -0
  97. package/apps/pwa/out/_next/static/chunks/{b4e12462-5fab4a813a63dadd.js → 83a80514-b897b64df43ce108.js} +1 -1
  98. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +93 -0
  99. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/{8264.00e434fbd02e9311.js → 8578.dff22d988cc2b106.js} +3 -3
  101. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +115 -0
  104. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +41 -0
  106. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +74 -0
  107. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +94 -0
  108. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{7518.49161e8f5814abdb.js → 9311.24c8f5ea793253dd.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/{9976.8f28864317639fe6.js → 94.4cfed21c0b781a06.js} +3 -3
  112. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/949.1e7d45ccb71580aa.js +90 -0
  114. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{0e3acd34.d42b2ef87fdf4234.js → 973cbf1b.3bbcf2b41548eca7.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{6571-926ddf024a6ad5df.js → 9917-9e26abc5f7772735.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9938.b23e4d4dfa0114cd.js +79 -0
  120. package/apps/pwa/out/_next/static/chunks/{740.90b31555290236a9.js → 9974.e77b4ff4884557b3.js} +2 -2
  121. package/apps/pwa/out/_next/static/chunks/{4c5e95ce.83e9b16add6fcd8c.js → ab4d57c2.e90bc2cb31949045.js} +7 -7
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-a1ce306364f08da9.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-07110da72c45e68f.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-d2d76d4a7eae91bd.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-30007380f2e2a3c1.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-e5a9302c105725a3.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-b93c04b5311c97ec.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-718a49e86bf25f9c.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-20662900d6b4b455.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-f707a509515ac50c.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-6a16a48d1aa6e91f.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/{page-26345242e4049f55.js → page-fcb06e305f515527.js} +1 -1
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-6acf5ec4e6c6d1af.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-39f82acf619cca23.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-7c2c8f81b185f9c0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ae7aff07e32676bb.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-482c60c1bc540d0a.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-7cb996c1aa08b6f5.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-623e08fe4477d606.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-db460cd8aecb8490.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-ff27902d0b11ef4f.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-8397a5c6ca569bf4.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1917ea87ea71ab6b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-25a302273b054fd7.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-670510eda8b9443f.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d73c3f1e00d93986.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-65caacf54389081e.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-4bb7556e2e97a750.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-77e04b4f8762c666.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-b92caddb5c715f30.js → page-15c0a4095baddfba.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-4eb96fc7241c2456.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-63e272a4cd3b6634.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-0d64ff212dc55d03.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-7f096248993fc2d4.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-e47fc72049149a38.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-f7d808e31e005895.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-5c2b24b5496dad73.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-76cdb531668b5191.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-e2b63345bba1a11f.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-d376e0c83edc041a.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d6db55fe2c04d128.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-87b88f551f421d8b.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-dab163b338e3b966.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-08019efef111ed2e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-0260ffc7eda50db1.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-980ce6fe36ad95eb.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-99c4e6c7345a9156.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-0ab42e0f05823013.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-ad9220422d20ba33.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{53746282.1be36038d1abd949.js → e117f801.e92bf10242653497.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/e87d89b9.2e71c0ae475d28a1.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{0673cc54.8e2ef1c23e49e190.js → f4dfbfc0.a69fb12f854882aa.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +1 -0
  183. package/apps/pwa/out/approvals/index.html +1 -1
  184. package/apps/pwa/out/approvals/index.txt +22 -22
  185. package/apps/pwa/out/autopilot/index.html +1 -1
  186. package/apps/pwa/out/autopilot/index.txt +22 -22
  187. package/apps/pwa/out/board/index.html +1 -1
  188. package/apps/pwa/out/board/index.txt +22 -22
  189. package/apps/pwa/out/botlab/index.html +1 -1
  190. package/apps/pwa/out/botlab/index.txt +21 -21
  191. package/apps/pwa/out/bots/index.html +1 -1
  192. package/apps/pwa/out/bots/index.txt +21 -21
  193. package/apps/pwa/out/ceo/index.html +1 -1
  194. package/apps/pwa/out/ceo/index.txt +22 -22
  195. package/apps/pwa/out/chat/index.html +1 -1
  196. package/apps/pwa/out/chat/index.txt +21 -21
  197. package/apps/pwa/out/consult/index.html +1 -1
  198. package/apps/pwa/out/consult/index.txt +22 -22
  199. package/apps/pwa/out/control/index.html +1 -1
  200. package/apps/pwa/out/control/index.txt +22 -22
  201. package/apps/pwa/out/decisions/index.html +1 -1
  202. package/apps/pwa/out/decisions/index.txt +21 -21
  203. package/apps/pwa/out/design-check/index.html +1 -1
  204. package/apps/pwa/out/design-check/index.txt +22 -22
  205. package/apps/pwa/out/editor/index.html +1 -1
  206. package/apps/pwa/out/editor/index.txt +22 -22
  207. package/apps/pwa/out/exec/index.html +1 -1
  208. package/apps/pwa/out/exec/index.txt +22 -22
  209. package/apps/pwa/out/field/index.html +1 -1
  210. package/apps/pwa/out/field/index.txt +22 -22
  211. package/apps/pwa/out/healthz +1 -1
  212. package/apps/pwa/out/index.html +1 -1
  213. package/apps/pwa/out/index.txt +21 -21
  214. package/apps/pwa/out/inside/index.html +1 -1
  215. package/apps/pwa/out/inside/index.txt +21 -21
  216. package/apps/pwa/out/intake/index.html +1 -1
  217. package/apps/pwa/out/intake/index.txt +22 -22
  218. package/apps/pwa/out/live/index.html +1 -1
  219. package/apps/pwa/out/live/index.txt +22 -22
  220. package/apps/pwa/out/live-run/index.html +1 -1
  221. package/apps/pwa/out/live-run/index.txt +22 -22
  222. package/apps/pwa/out/loops/index.html +1 -1
  223. package/apps/pwa/out/loops/index.txt +21 -21
  224. package/apps/pwa/out/market/index.html +1 -1
  225. package/apps/pwa/out/market/index.txt +21 -21
  226. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  227. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  228. package/apps/pwa/out/morning/index.html +1 -1
  229. package/apps/pwa/out/morning/index.txt +22 -22
  230. package/apps/pwa/out/observatory/index.html +1 -1
  231. package/apps/pwa/out/observatory/index.txt +22 -22
  232. package/apps/pwa/out/ops/checklist/index.html +1 -1
  233. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  234. package/apps/pwa/out/ops/release/index.html +1 -1
  235. package/apps/pwa/out/ops/release/index.txt +21 -21
  236. package/apps/pwa/out/ops/seats/index.html +1 -1
  237. package/apps/pwa/out/ops/seats/index.txt +21 -21
  238. package/apps/pwa/out/outputs/index.html +1 -1
  239. package/apps/pwa/out/outputs/index.txt +21 -21
  240. package/apps/pwa/out/reflection/index.html +1 -1
  241. package/apps/pwa/out/reflection/index.txt +22 -22
  242. package/apps/pwa/out/scheduler/index.html +1 -1
  243. package/apps/pwa/out/scheduler/index.txt +22 -22
  244. package/apps/pwa/out/sessions/index.html +1 -1
  245. package/apps/pwa/out/sessions/index.txt +21 -21
  246. package/apps/pwa/out/settings/devices/index.html +1 -1
  247. package/apps/pwa/out/settings/devices/index.txt +22 -22
  248. package/apps/pwa/out/settings/index.html +1 -1
  249. package/apps/pwa/out/settings/index.txt +22 -22
  250. package/apps/pwa/out/setup/done/index.html +1 -1
  251. package/apps/pwa/out/setup/done/index.txt +22 -22
  252. package/apps/pwa/out/setup/index.html +1 -1
  253. package/apps/pwa/out/setup/index.txt +22 -22
  254. package/apps/pwa/out/share/index.html +1 -1
  255. package/apps/pwa/out/share/index.txt +22 -22
  256. package/apps/pwa/out/showroom/index.html +1 -1
  257. package/apps/pwa/out/showroom/index.txt +21 -21
  258. package/apps/pwa/out/tasks/index.html +1 -1
  259. package/apps/pwa/out/tasks/index.txt +22 -22
  260. package/apps/pwa/out/term/index.html +1 -1
  261. package/apps/pwa/out/term/index.txt +22 -22
  262. package/apps/pwa/out/today/index.html +1 -1
  263. package/apps/pwa/out/today/index.txt +22 -22
  264. package/apps/pwa/out/trace/index.html +1 -1
  265. package/apps/pwa/out/trace/index.txt +22 -22
  266. package/apps/pwa/out/vault/index.html +1 -1
  267. package/apps/pwa/out/vault/index.txt +22 -22
  268. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  269. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  270. package/apps/pwa/out/workflows/index.html +1 -1
  271. package/apps/pwa/out/workflows/index.txt +22 -22
  272. package/apps/pwa/out/workspace/index.html +1 -1
  273. package/apps/pwa/out/workspace/index.txt +22 -22
  274. package/apps/pwa/out/worktrees/index.html +1 -1
  275. package/apps/pwa/out/worktrees/index.txt +22 -22
  276. package/graphs/release/release-loop.yaml +5 -5
  277. package/graphs/steward/recipes.yaml +4 -0
  278. package/graphs/steward/steward.yaml +10 -1
  279. package/package.json +1 -1
  280. package/scripts/bench-report.ts +46 -1
  281. package/scripts/ci-typecheck-changed.ts +88 -7
  282. package/scripts/coord-msg-bridge.ts +209 -0
  283. package/scripts/coord-post.sh +40 -7
  284. package/scripts/coord-requests-bridge.ts +10 -5
  285. package/scripts/expose-rubric-suggest.ts +1 -1
  286. package/scripts/measure-tsc-affected-roots.ts +10 -1
  287. package/scripts/release-loop/auto-approve-node.ts +6 -0
  288. package/scripts/release-loop/export-check-node.ts +8 -5
  289. package/scripts/release-loop/gate-closure.ts +286 -0
  290. package/scripts/release-loop/gate-node.ts +73 -13
  291. package/scripts/release-loop/gate-partial.ts +34 -6
  292. package/scripts/release-loop/node-verdict.ts +7 -2
  293. package/scripts/release-loop/ops-upgrade-node.ts +63 -42
  294. package/scripts/release-loop/publish-node.ts +6 -0
  295. package/scripts/release-loop/resume-release.ts +37 -10
  296. package/scripts/release-loop/resume.ts +69 -4
  297. package/scripts/tsc-baseline-cache.ts +28 -3
  298. package/scripts/usage-rollup.ts +27 -13
  299. package/scripts/ux-sim.ts +30 -1
  300. package/skills/youtube-master/scripts/main.ts +4 -1
  301. package/skills/youtube-master/src/obsidian.ts +9 -0
  302. package/src/agent/task-notification.ts +30 -1
  303. package/src/agent-substrate/acp-implementer.ts +14 -7
  304. package/src/agent-substrate/pr-reviewer.ts +30 -10
  305. package/src/agent-substrate/review-observation.ts +9 -2
  306. package/src/agent-substrate/self-review-cli.ts +154 -16
  307. package/src/boot/daemon-tools/self-implement.ts +72 -4
  308. package/src/budget/cost-tier-advisor.ts +91 -0
  309. package/src/budget/llm-cost.ts +5 -1
  310. package/src/budget/shadow-arms.ts +77 -0
  311. package/src/budget/types.ts +5 -3
  312. package/src/budget/unified-usage.ts +172 -8
  313. package/src/cli/control-cli.ts +29 -0
  314. package/src/cli/doctor-cli.ts +106 -3
  315. package/src/cli/friendly-errors.ts +113 -0
  316. package/src/cli/intake-cli.ts +3 -1
  317. package/src/cli/memory-cli.ts +182 -0
  318. package/src/cli/model-watch-cli.ts +4 -1
  319. package/src/cli/msg-cli.ts +15 -5
  320. package/src/cli/pr-cli.ts +53 -0
  321. package/src/cli/pr-land-overlap-evidence.ts +18 -10
  322. package/src/cli/pr-land-pod-shadow.ts +54 -0
  323. package/src/cli/release-cli.ts +41 -12
  324. package/src/cli/release-run-if-ready.ts +11 -0
  325. package/src/cli/resource-cli.ts +48 -0
  326. package/src/cli/retro-cli.ts +12 -3
  327. package/src/cli/seat-cli.ts +121 -0
  328. package/src/cli/seat-requests-cli.ts +25 -0
  329. package/src/cli/self-utterances-cli.ts +140 -0
  330. package/src/cli/tasks-cli.ts +168 -14
  331. package/src/cli/usage-cli.ts +3 -1
  332. package/src/compact/verify-probe.ts +23 -3
  333. package/src/context-card/cell.ts +40 -0
  334. package/src/context-card/index.ts +50 -0
  335. package/src/control/control-status.ts +30 -1
  336. package/src/dashboard/boot-timing.ts +35 -0
  337. package/src/dashboard/index.ts +86 -24
  338. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +26 -0
  339. package/src/dashboard/slash-runtime/dashboard-handlers.ts +10 -138
  340. package/src/dashboard/slash-runtime/shell-slash.ts +145 -0
  341. package/src/debug/log-diet.ts +16 -4
  342. package/src/debug/log.ts +1 -1
  343. package/src/domains/morning-essential.ts +18 -3
  344. package/src/domains/release-tool.ts +29 -8
  345. package/src/domains/surface-events.ts +16 -0
  346. package/src/elanous-config-dir.ts +2 -2
  347. package/src/execution-loop/launch-gate.ts +158 -2
  348. package/src/fleet/host-doctor.ts +446 -0
  349. package/src/goals/judge.ts +20 -6
  350. package/src/graph-runner/runner.ts +12 -6
  351. package/src/graph-wizard/archetypes.ts +14 -8
  352. package/src/graph-wizard/generate.ts +77 -1
  353. package/src/grok.ts +13 -7
  354. package/src/harness/harness-cli-command.ts +102 -51
  355. package/src/harness/harness-stop.ts +93 -19
  356. package/src/index.ts +52 -179
  357. package/src/instance/current.ts +2 -6
  358. package/src/instance/resolve.ts +5 -6
  359. package/src/intake-plane/collect-github.ts +7 -2
  360. package/src/intake-plane/lens.ts +46 -4
  361. package/src/intake-plane/requirement-funnel.ts +53 -1
  362. package/src/intelligence-map/catalog-feed.ts +119 -0
  363. package/src/intelligence-map/model-watch-intake.ts +40 -0
  364. package/src/intelligence-map/model-watch-mission.ts +14 -1
  365. package/src/llm/open-weight-discipline.ts +21 -0
  366. package/src/llm/openai-sampling-fields.ts +89 -0
  367. package/src/llm/runtime-model-family.ts +61 -0
  368. package/src/llm/zai-coding-plan.ts +27 -1
  369. package/src/llm.ts +17 -97
  370. package/src/machines/machine-ledger.ts +31 -3
  371. package/src/maturity/cli-maturity.ts +13 -3
  372. package/src/maturity/feature-maturity.ts +1 -1
  373. package/src/msg/msg-store.ts +69 -7
  374. package/src/nexus/api/http-server.ts +22 -0
  375. package/src/oauth/codex-account-rotation.ts +4 -1
  376. package/src/oauth/codex-account-store.ts +20 -7
  377. package/src/oauth/codex-quota-policy.ts +33 -4
  378. package/src/ops/overview-collect.ts +3 -2
  379. package/src/ops/overview-owner.ts +29 -0
  380. package/src/plugin-hooks/shell-hook.ts +17 -2
  381. package/src/plugin-missions/evaluator-runner.ts +18 -2
  382. package/src/plugins/install/plugin-install.ts +11 -1
  383. package/src/preview/terminal.ts +15 -5
  384. package/src/project/project-store.ts +20 -0
  385. package/src/prompt-enhance/enhance.ts +11 -0
  386. package/src/release-loop/auto-start.ts +7 -5
  387. package/src/release-loop/checklist.ts +52 -5
  388. package/src/release-loop/feature-store.ts +10 -9
  389. package/src/release-loop/gate-shards.ts +4 -0
  390. package/src/release-loop/light-rc.ts +84 -13
  391. package/src/release-loop/merged-pr-checklist.ts +35 -5
  392. package/src/release-loop/rehearsal.ts +1 -1
  393. package/src/seat-loop/duty-ledger.ts +64 -0
  394. package/src/seat-loop/seat-loop.ts +5 -1
  395. package/src/self-dev/decompose.ts +37 -3
  396. package/src/self-dev/dev-pipeline.ts +32 -7
  397. package/src/self-dev/draft-residue.ts +16 -6
  398. package/src/self-dev/draft-sweep.ts +75 -18
  399. package/src/self-dev/fabric-decompose-adapter.ts +9 -2
  400. package/src/self-dev/orchestrate.ts +6 -2
  401. package/src/self-dev/run-supervisor.ts +72 -8
  402. package/src/self-implement/gate-cli.ts +29 -10
  403. package/src/self-implement/gate-remote.ts +4 -1
  404. package/src/self-implement/goal-author.ts +15 -29
  405. package/src/self-implement/goal-command-execution.ts +26 -0
  406. package/src/self-implement/goal-new-paths.ts +42 -0
  407. package/src/self-implement/host-regate.ts +124 -30
  408. package/src/self-implement/importer-test-index.ts +3 -1
  409. package/src/self-implement/l8-merge-queue.ts +80 -2
  410. package/src/self-implement/merge-train.ts +19 -0
  411. package/src/self-implement/off-diff-evidence.ts +40 -1
  412. package/src/self-implement/orchestrator.ts +90 -20
  413. package/src/self-implement/premise-review.ts +159 -0
  414. package/src/self-implement/pwa-import-graph.ts +194 -7
  415. package/src/self-implement/regate-detail.ts +79 -0
  416. package/src/self-implement/review-deferred-to-host.ts +21 -0
  417. package/src/self-implement/rework-budget-judgment.ts +23 -3
  418. package/src/self-implement/running-runs.ts +2 -2
  419. package/src/self-implement/scope-adjacency.ts +23 -0
  420. package/src/self-implement/seams.ts +42 -7
  421. package/src/self-implement/self-implement-runtime.ts +126 -21
  422. package/src/session/index.ts +14 -4
  423. package/src/session-runtime/index.ts +55 -11
  424. package/src/skills/tools/agent.ts +16 -1
  425. package/src/skills/tools/persistent-grounding.ts +11 -1
  426. package/src/skills/tools/shell.ts +33 -1
  427. package/src/steward/rejudge-tick.ts +142 -0
  428. package/src/task-agent/board.ts +92 -3
  429. package/src/task-agent/card-evidence.ts +88 -1
  430. package/src/task-agent/cover.ts +85 -1
  431. package/src/task-agent/live-moves.ts +14 -6
  432. package/src/task-agent/parent-host.ts +27 -3
  433. package/src/task-agent/rejudge-on-head.ts +370 -29
  434. package/src/task-agent/review-result-capture.ts +67 -2
  435. package/src/task-agent/shadow.ts +148 -21
  436. package/src/task-agent/task-hand.ts +22 -3
  437. package/src/task-orchestrator/surfaces/pod-command-job.ts +14 -0
  438. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +122 -0
  439. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +23 -0
  440. package/src/task-orchestrator/surfaces/pod-pool.ts +53 -0
  441. package/src/task-orchestrator/surfaces/self-implement-pod.ts +236 -28
  442. package/src/tool-runtime/tool-search-runtime.ts +25 -0
  443. package/src/tui.ts +20 -1
  444. package/src/user-config.ts +21 -63
  445. package/src/ux-sim/fault-cred-expiry.ts +100 -0
  446. package/src/ux-sim/fault-pod-death.ts +74 -0
  447. package/src/ux-sim/fault-pool-cap.ts +81 -0
  448. package/src/version/packed-revision.json +1 -1
  449. package/src/webclone/qa-table.ts +22 -0
  450. package/apps/pwa/out/_next/static/chunks/0a09e062-34f747a17d8d8c2e.js +0 -1
  451. package/apps/pwa/out/_next/static/chunks/1168.a0fb3d9db76c00bd.js +0 -77
  452. package/apps/pwa/out/_next/static/chunks/1325-dc3f3c21eb181cb4.js +0 -1
  453. package/apps/pwa/out/_next/static/chunks/1357.a843c41d2cd7ec31.js +0 -34
  454. package/apps/pwa/out/_next/static/chunks/1430.53f49882b17607c2.js +0 -24
  455. package/apps/pwa/out/_next/static/chunks/1459-be6509b3419d8a9f.js +0 -1
  456. package/apps/pwa/out/_next/static/chunks/153.0a4e3cd516930491.js +0 -1
  457. package/apps/pwa/out/_next/static/chunks/1572.7bc291352e241a45.js +0 -1
  458. package/apps/pwa/out/_next/static/chunks/1593-d07ad068c120dfb0.js +0 -1
  459. package/apps/pwa/out/_next/static/chunks/1608.b7c900baa56cab32.js +0 -1
  460. package/apps/pwa/out/_next/static/chunks/1615-4d8156febaac4b35.js +0 -1
  461. package/apps/pwa/out/_next/static/chunks/1646.e03f0fbc26bc72f6.js +0 -1
  462. package/apps/pwa/out/_next/static/chunks/1669-da843ed73aa301f5.js +0 -1
  463. package/apps/pwa/out/_next/static/chunks/176.13ba0659e3e96fd4.js +0 -1
  464. package/apps/pwa/out/_next/static/chunks/1990.9c60f495ef33c070.js +0 -36
  465. package/apps/pwa/out/_next/static/chunks/2042e469.f86158dd5c1e51a1.js +0 -122
  466. package/apps/pwa/out/_next/static/chunks/2543-28ec6aeb80a5e1e1.js +0 -1
  467. package/apps/pwa/out/_next/static/chunks/2561.43c99d6ee914ee6a.js +0 -62
  468. package/apps/pwa/out/_next/static/chunks/2638.b39ab2f674caa1a5.js +0 -1
  469. package/apps/pwa/out/_next/static/chunks/272-0eed0fb0aab716b6.js +0 -1
  470. package/apps/pwa/out/_next/static/chunks/2778.67e0c1d484189ccf.js +0 -1
  471. package/apps/pwa/out/_next/static/chunks/2841.10ff309f6a3168af.js +0 -1
  472. package/apps/pwa/out/_next/static/chunks/2886-9639f97d523d752a.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/2978.57fb87ce21cc5a85.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/3664.15f968c39d15bd28.js +0 -149
  475. package/apps/pwa/out/_next/static/chunks/3786-935eb3fcde90e496.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/3813.df4a01ae89c6f63f.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/3961-aaae04ed1d32622f.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/3992.f79c70480e8c4077.js +0 -309
  479. package/apps/pwa/out/_next/static/chunks/40-413e8641de9ed1e5.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/4054-521f11a503daed64.js +0 -1
  481. package/apps/pwa/out/_next/static/chunks/4315.e7356f34c7d8ec79.js +0 -1
  482. package/apps/pwa/out/_next/static/chunks/4489-bf629de6f04f7681.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/4540.557733cc88c6a82b.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/462.0275b4338c5b6337.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/4658-7ed9266098a787e4.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/4945-0f4046cfc3228ea3.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/5105-18b4165c5d3a86b0.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/5205-6992210fe31f45f4.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/5287-72898b126d722457.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/5313.1697309c532b9856.js +0 -2
  491. package/apps/pwa/out/_next/static/chunks/5474.991b90688c3cb321.js +0 -1
  492. package/apps/pwa/out/_next/static/chunks/5544-871146192d095594.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/5935.d5e8ca3e096772e8.js +0 -1
  494. package/apps/pwa/out/_next/static/chunks/6006.84e8b418a7a0db97.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/6013-1267ba7454d6764b.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/6038-1e0f7ee1086da4cf.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/617.709dd0019fe99796.js +0 -1
  498. package/apps/pwa/out/_next/static/chunks/6261.fb9bf94947094636.js +0 -74
  499. package/apps/pwa/out/_next/static/chunks/6411.1966866fae31ffa9.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/6481-b829d99aa8d158f5.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/6541.2b7daa043100d0fa.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/6597.2d7a6d77ab485b27.js +0 -64
  503. package/apps/pwa/out/_next/static/chunks/67.5dd2dc543c2fa3de.js +0 -1
  504. package/apps/pwa/out/_next/static/chunks/6777-312496b0d774719b.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/681.0116f7036cfb4e8d.js +0 -32
  506. package/apps/pwa/out/_next/static/chunks/6871.30b2bf23b3126e36.js +0 -24
  507. package/apps/pwa/out/_next/static/chunks/6882.737d366d54e29d83.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/7035.54c2c535164b1c9b.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/7086-8bfa7e8f796a03d9.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/7126.5e5599f251726b67.js +0 -93
  511. package/apps/pwa/out/_next/static/chunks/7203-47ff0740a293e284.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/7268.017f49dafb5f0ff3.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/7355.5d65a87e9567ae08.js +0 -1
  514. package/apps/pwa/out/_next/static/chunks/7392.4018c2a62177f296.js +0 -1
  515. package/apps/pwa/out/_next/static/chunks/7471.3a3d1be50559cfb8.js +0 -148
  516. package/apps/pwa/out/_next/static/chunks/7500.73489a345cef2201.js +0 -226
  517. package/apps/pwa/out/_next/static/chunks/7565.c2f72a15c1ed0396.js +0 -27
  518. package/apps/pwa/out/_next/static/chunks/7651.6d1c984d3d8587a4.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/7713.7ab863ed59b2d661.js +0 -1
  520. package/apps/pwa/out/_next/static/chunks/7793.d7cd2026767ddd54.js +0 -115
  521. package/apps/pwa/out/_next/static/chunks/7837.c7c267e5dceadb11.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/7891.09266382daf70d1c.js +0 -1
  523. package/apps/pwa/out/_next/static/chunks/7990-cbf6a01bcbdcb7e6.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/8119-819c549e0c197786.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/8186-74ea19a3700d04a8.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/8267-e7b3262b735ae106.js +0 -1
  527. package/apps/pwa/out/_next/static/chunks/8386.86518e55b75f7cf5.js +0 -8
  528. package/apps/pwa/out/_next/static/chunks/8437.ba6eeeb29590042f.js +0 -23
  529. package/apps/pwa/out/_next/static/chunks/8469-1500be57e582296f.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/8483-7164cecdaf178ca6.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/8722-4c940f02c496ad36.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/887-41d0dcf5af48c628.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/9039.da86361496797522.js +0 -90
  534. package/apps/pwa/out/_next/static/chunks/905.d5745a25884754d4.js +0 -94
  535. package/apps/pwa/out/_next/static/chunks/9089-d909f3d4478b0628.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/9096.dc5c7a267f83790c.js +0 -41
  537. package/apps/pwa/out/_next/static/chunks/93.a567257b6bdb7fe4.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/9320.419acb9665b46597.js +0 -287
  539. package/apps/pwa/out/_next/static/chunks/9356.b8ceda6634612ff8.js +0 -79
  540. package/apps/pwa/out/_next/static/chunks/94.e9e1043b35cd3eed.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/9400-7498ea90b2e6ee8f.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/9930-58644af9c813d6e1.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/9932.367cf4725fedd6e2.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/9935.1628b904cdc8ce0e.js +0 -104
  545. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-a2aa8709d193ee0d.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/app/approvals/page-3b9fc39362473ae7.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-f2b62c19ca68fef8.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/app/board/page-d7602d489edf5f37.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/app/botlab/page-24282bf9f90031a5.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/app/bots/page-8b7c5ab6b5bc8d64.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/app/ceo/page-4eb84d454f8c3415.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/app/chat/page-b2e494bdad57fcb5.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/app/consult/page-c0ab229673a8b0eb.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/app/control/page-3e2b45f3c36dbac4.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c22aa511b28743ad.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/app/editor/page-bf88c0f558d8ef54.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/app/exec/page-52fec523e5b5d3ad.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/app/field/page-67723dfdcde92b31.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/app/healthz/route-a2aa8709d193ee0d.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/app/inside/page-22725e2570f1126b.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/intake/page-1891335950d68b70.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/layout-3267af1ebdc73cf5.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/live/page-c314b75c11234998.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/live-run/page-9f9c85415f61782b.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/loops/page-c1d4276059085587.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/market/page-833aab587f26ad4c.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-8526c17ae38e6a50.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/morning/page-f998637a8402115c.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/not-found-b7bb53828b17b335.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/observatory/page-1b1850de0257e46d.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6f23159fedb41f67.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1d809a87139dd024.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-da9e570234d481fd.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/page-8ce3a38e210b810a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/reflection/page-57ffeeb6019440fd.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-abbb417bf514630b.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2c2b3f29cec1efa4.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-9369279f72fc7b51.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/settings/page-64861f14039499c3.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ddc4c93efd8ab94b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/setup/layout-a2aa8709d193ee0d.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/setup/page-901a1391b81053bc.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/share/page-68d9bbaac9841a58.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/showroom/page-b5c0c996f329371e.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/tasks/page-89881ccbcf728978.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/term/page-0e87a803b3d7165e.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/today/page-58d4e5cb30ef4871.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/trace/page-02ce4c3b5f39e4d2.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/vault/page-e620d1bb8eadcec2.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-acf868c64d77f950.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/workflows/page-54fa605fa6dba457.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/workspace/page-bc79f0833533fa84.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-d5c4398eea03d8f3.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/cd39fa05.fac4545f42a3ef70.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/framework-b2763b10dc6b3836.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/main-app-27893e93b0ec193d.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/main-f280047194e1daf8.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/pages/_app-e90eff2d0b70564c.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/pages/_error-70f2d654b3435d34.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/webpack-4794f053bd5e4230.js +0 -1
  601. /package/apps/pwa/out/_next/static/{Q-7iofoxOEv1WX18S35of → Ev2jivDMTSoEc-5rIXdcy}/_ssgManifest.js +0 -0
@@ -0,0 +1,119 @@
1
+ // ── MK · 0.2.26 칸 CATALOG-FEED — signed catalog feed ──────────────────
2
+ //
3
+ // Folds a ModelCatalog into a verifiable feed document and verifies it on
4
+ // the receiving side:
5
+ // buildCatalogFeed — canonicalize (models sorted by id, stable-key JSON)
6
+ // + sha256 content digest.
7
+ // signCatalogFeed — ed25519 signature over the feed document (base64).
8
+ // verifyCatalogFeed — reject tampered / forged feeds with a reason.
9
+ //
10
+ // Design = 내부 문서 `RFC-smart-model-routing-and-catalog-2026-10-10` §판올림=카탈로그 동봉.
11
+ // This piece is the judgment only — key generation/holding, the daily
12
+ // publish cron, and fetching are the next slice.
13
+ //
14
+ // 🔎 세 얼굴 — 관측: verify 거부는 debug.log('intelligence-map.catalog-feed',
15
+ // 'verify-rejected', { reason }) 로 남는다. 판단 근거: digest 는 «정렬·키 고정
16
+ // JSON» 의 sha256 hex 라 서명과 무관하게 내용 변조를 가른다. 수복·인계: 거부
17
+ // 사유가 'digest-mismatch' 면 서명 키는 맞고 «내용»이 바뀌었다 — 발행 측 카탈로그를
18
+ // 다시 잰다; 'bad-signature' 면 키가 다르다.
19
+
20
+ import { createHash, sign as cryptoSign, verify as cryptoVerify } from 'node:crypto';
21
+ import { debug } from '../debug/log.js';
22
+ import type { ModelCatalog, ModelEntry } from './types.js';
23
+
24
+ export interface CatalogFeed {
25
+ schema: 'elanous.catalog-feed/1';
26
+ issuedAt: string;
27
+ models: ModelEntry[];
28
+ digest: string;
29
+ }
30
+
31
+ export interface SignedCatalogFeed {
32
+ feed: CatalogFeed;
33
+ signature: string;
34
+ }
35
+
36
+ export type CatalogFeedVerifyResult =
37
+ | { ok: true; feed: CatalogFeed }
38
+ | { ok: false; reason: 'bad-signature' | 'digest-mismatch' | 'schema' };
39
+
40
+ /** Canonical JSON — sorted object keys, deterministic spacing. Arrays keep
41
+ * order; `models` is sorted by `id` before this is applied. */
42
+ function canonicalJson(value: unknown): string {
43
+ // undefined follows JSON.stringify: dropped as an object key, null in an
44
+ // array — so a feed survives a JSON round trip with the same digest.
45
+ if (value === undefined) return 'null';
46
+ if (value === null || typeof value !== 'object') return JSON.stringify(value);
47
+ if (Array.isArray(value)) return `[${value.map(canonicalJson).join(',')}]`;
48
+ const obj = value as Record<string, unknown>;
49
+ const keys = Object.keys(obj).filter((k) => obj[k] !== undefined).sort();
50
+ return `{${keys.map((k) => `${JSON.stringify(k)}:${canonicalJson(obj[k])}`).join(',')}}`;
51
+ }
52
+
53
+ /** sha256 hex of the canonical (sorted, key-stable) JSON of the feed. */
54
+ function feedDigest(feed: Omit<CatalogFeed, 'digest'>): string {
55
+ return createHash('sha256').update(canonicalJson(feed)).digest('hex');
56
+ }
57
+
58
+ /** Fold a catalog into a signed-feed-ready document. `models` is sorted by
59
+ * id so byte-identical catalogs always produce the same digest. */
60
+ export function buildCatalogFeed(catalog: ModelCatalog, issuedAt: Date): CatalogFeed {
61
+ const models = [...catalog.models].sort((a, b) => (a.id < b.id ? -1 : a.id > b.id ? 1 : 0));
62
+ const base = {
63
+ schema: 'elanous.catalog-feed/1' as const,
64
+ issuedAt: issuedAt.toISOString(),
65
+ models,
66
+ };
67
+ return { ...base, digest: feedDigest(base) };
68
+ }
69
+
70
+ /** Sign the feed document (whole feed, digest included) with an ed25519
71
+ * private key (PEM). Signature is base64 over the canonical JSON of the
72
+ * feed. */
73
+ export function signCatalogFeed(
74
+ feed: CatalogFeed,
75
+ privateKeyPem: string,
76
+ ): { feed: CatalogFeed; signature: string } {
77
+ const signature = cryptoSign(null, Buffer.from(canonicalJson(feed)), privateKeyPem).toString('base64');
78
+ return { feed, signature };
79
+ }
80
+
81
+ /** Verify a signed feed: schema → content digest (recomputed, catches
82
+ * tampering that keeps the original digest) → signature. Rejected feeds
83
+ * are logged (제1원칙 관측) so the receiver's self-cognition can see why a
84
+ * feed was refused. */
85
+ export function verifyCatalogFeed(signed: SignedCatalogFeed, publicKeyPem: string): CatalogFeedVerifyResult {
86
+ if (signed === null || typeof signed !== 'object') return reject('schema');
87
+ const { feed, signature } = signed;
88
+ if (feed === null || typeof feed !== 'object' || feed.schema !== 'elanous.catalog-feed/1' || typeof feed.issuedAt !== 'string' || !Array.isArray(feed.models)
89
+ || typeof feed.digest !== 'string' || typeof signature !== 'string' || !feed.models.every(isModelEntryShape)) {
90
+ return reject('schema');
91
+ }
92
+ const { digest: _digest, ...body } = feed;
93
+ if (feedDigest(body) !== feed.digest) return reject('digest-mismatch');
94
+ let sigOk = false;
95
+ try {
96
+ sigOk = cryptoVerify(null, Buffer.from(canonicalJson(feed)), publicKeyPem, Buffer.from(signature, 'base64'));
97
+ } catch {
98
+ sigOk = false;
99
+ }
100
+ if (!sigOk) return reject('bad-signature');
101
+ return { ok: true, feed };
102
+ }
103
+
104
+ /** Required ModelEntry fields at the receiving boundary — a signed feed with
105
+ * a model missing any of these is a schema failure, not a usable catalog. */
106
+ function isModelEntryShape(m: unknown): boolean {
107
+ if (m === null || typeof m !== 'object') return false;
108
+ const e = m as Record<string, unknown>;
109
+ const finite = (v: unknown) => typeof v === 'number' && Number.isFinite(v);
110
+ const strings = (v: unknown) => Array.isArray(v) && v.every((x) => typeof x === 'string');
111
+ return typeof e.id === 'string' && e.id.length > 0 && typeof e.provider === 'string' && typeof e.family === 'string'
112
+ && finite(e.contextWindow) && finite(e.inputPerMtok) && finite(e.outputPerMtok)
113
+ && typeof e.local === 'boolean' && strings(e.tags) && strings(e.bestFor);
114
+ }
115
+
116
+ function reject(reason: 'bad-signature' | 'digest-mismatch' | 'schema'): { ok: false; reason: typeof reason } {
117
+ debug.log('intelligence-map.catalog-feed', 'verify-rejected', { reason });
118
+ return { ok: false, reason };
119
+ }
@@ -103,6 +103,46 @@ export async function runModelWatchIntake(
103
103
  return { candidates, proposal, perSource };
104
104
  }
105
105
 
106
+ export type PriceField = 'inputPerMtok' | 'outputPerMtok';
107
+
108
+ export interface PriceChange {
109
+ id: string;
110
+ field: PriceField;
111
+ /** Price currently in the catalog (USD per 1M tokens). */
112
+ before: number;
113
+ /** Price the watched page reports. */
114
+ after: number;
115
+ }
116
+
117
+ const PRICE_FIELDS: readonly PriceField[] = ['inputPerMtok', 'outputPerMtok'];
118
+
119
+ /** Price differences between the catalog and the watched pages. The merge
120
+ * only fills undefined fields, so a repriced model shows up in
121
+ * `proposal.updated` with no trace of the new price — this reports it.
122
+ * A catalog price of 0 means "not priced yet" and is not a change. */
123
+ export function detectPriceChanges(result: Pick<WatchIntakeResult, 'candidates' | 'proposal'>): PriceChange[] {
124
+ const current = new Map(result.proposal.catalog.models.map((model) => [model.id, model]));
125
+ const updated = new Set(result.proposal.updated);
126
+ const changes: PriceChange[] = [];
127
+ for (const candidate of result.candidates) {
128
+ const entry = current.get(candidate.id);
129
+ if (!entry || !updated.has(candidate.id)) continue;
130
+ for (const field of PRICE_FIELDS) {
131
+ const before = entry[field];
132
+ const after = candidate[field];
133
+ if (typeof after !== 'number' || !Number.isFinite(after) || after < 0) continue;
134
+ if (typeof before !== 'number' || before <= 0 || before === after) continue;
135
+ changes.push({ id: candidate.id, field, before, after });
136
+ }
137
+ }
138
+ return changes;
139
+ }
140
+
141
+ export function formatPriceChange(change: PriceChange): string {
142
+ const label = change.field === 'inputPerMtok' ? 'input' : 'output';
143
+ return `${change.id} ${label} $${change.before}→$${change.after} /Mtok`;
144
+ }
145
+
106
146
  function errorMessage(error: unknown): string {
107
147
  try {
108
148
  const message = error instanceof Error ? error.message : String(error);
@@ -21,7 +21,13 @@ import { lookupLlmTierSpec } from '../model-tier/index.js';
21
21
  import type { LlmRunner } from '../model-tier/preset-suggest-llm.js';
22
22
  import type { LLMProviderName } from '../user-config.js';
23
23
  import { getUserConfig } from '../user-config.js';
24
- import { runModelWatchIntake, type WatchIntakeResult, type WatchPage } from './model-watch-intake.js';
24
+ import {
25
+ detectPriceChanges,
26
+ formatPriceChange,
27
+ runModelWatchIntake,
28
+ type WatchIntakeResult,
29
+ type WatchPage,
30
+ } from './model-watch-intake.js';
25
31
 
26
32
  export function getModelWatchProposalPath(home: string = homedir()): string {
27
33
  return join(home, '.elanous', 'model-watch-proposals.jsonl');
@@ -93,6 +99,13 @@ export async function runModelIntelligenceWatch(
93
99
  line: `Classification incomplete for zero-candidate sources: ${abnormalEmptySources.join(', ')}`,
94
100
  });
95
101
  }
102
+ const priceChanges = detectPriceChanges(result);
103
+ if (priceChanges.length > 0) {
104
+ await safeLog(log, 'intelligence-map.model-watch', 'price-changes', {
105
+ changes: priceChanges,
106
+ line: `Price changes vs catalog: ${priceChanges.map(formatPriceChange).join('; ')}`,
107
+ });
108
+ }
96
109
  await safeLog(log, 'intelligence-map.model-watch', 'pass', {
97
110
  pages: pages.length,
98
111
  candidates: result.candidates.length,
@@ -0,0 +1,21 @@
1
+ /** OpenRouter(`openrouter/…`) GLM·Kimi·Qwen 전용 도구 호출 규율 — 다른 군 상수와 합성하지 않는 독립 상수.
2
+ *
3
+ * 2026-10-11 GLM-PROMPT-TUNE 첫 조각: `llm.ts` 동결(RFC #25983)을 위해 상수를 이 파일로 옮겼다.
4
+ * 줄 둘을 추가했다 — 실측 약점 둘을 겨냥한다:
5
+ * ⑴ 그라운딩 비교 8회 중 GLM 3회 전부 «Grep 으로만 확인하고 Read 는 안 했다»고 스스로 적고
6
+ * 그 경로를 증거로 써 grounding-evidence 기각
7
+ * ⑵ 상 칸에서 PR 없이 라운드만 도는 no-progress(부검반 ×26)
8
+ * 다른 군(codex·grok·local·claude·gemini·gpt·other)의 요청 바이트는 불변 — 이 상수는
9
+ * open-weight 계열에만 주입된다(`TOOL_DISCIPLINE_BY_FAMILY`).
10
+ *
11
+ * ⛔ `llm.ts` 의 `selectIntentClassificationMessages` 가 이 상수와 «정확 일치»로 분류기를
12
+ * 걸러 내므로, 주입부는 상수를 그대로 싣는다(합성 금지). */
13
+ export const OPEN_WEIGHT_TOOL_DISCIPLINE = [
14
+ '[open-weight tool-use discipline]',
15
+ '- 도구로 할 수 있는 일은 이번 응답에서 바로 도구를 호출하라. "먼저 읽겠다" 또는 "확인하겠다" 같은 계획만 말하고 응답을 끝내지 마라.',
16
+ '- 작업을 시작하는 첫 응답에는 도구 호출이 하나 이상 있어야 한다.',
17
+ '- 도구 호출 인자는 해당 도구의 스키마에 맞는 JSON 으로 내라.',
18
+ '- 충분한 근거가 모이면 도구 호출 없이 최종 답을 평문으로 써서 끝내라.',
19
+ '- 증거·근거로 적는 파일은 이번 작업에서 Read 로 연 파일만 — Grep·Glob 결과만으로 내용을 단정하지 마라.',
20
+ '- 구현을 끝냈다고 말하기 전에 바꾼 파일과 돌린 시험 명령·결과를 적어라.',
21
+ ].join('\n');
@@ -0,0 +1,89 @@
1
+ /**
2
+ * ⛔⭐ OpenAI Chat Completions 의 «출력 상한» 칸 이름은 모델 세대로 갈린다.
3
+ *
4
+ * `gpt-5` 이후 계열은 `max_tokens` 를 ***거부한다*** — 400 `unsupported_parameter` 를 내고
5
+ * *"Use 'max_completion_tokens' instead"* 라고 말한다. `gpt-4o` 계열은 반대로 옛 이름만 받는다.
6
+ *
7
+ * 📏 2026-08-22 실측: `provider auto` 의 티어 사다리가 `gpt-5.6-*` 로 바뀐 뒤(`#11161`)
8
+ * 3시간 만에 이 400 이 **93건** 났고 «가속»했다(20h:2 → 21h:16 → 22h:30 → 23h:45).
9
+ * 7일 창에서 그 이전 발생은 ***0***이다. ⇒ 칸 이름을 모델로 갈라야 한다.
10
+ *
11
+ * ⚠️ 값을 «안 보내는» 선택은 하지 않는다 — 상한이 사라지면 비용이 조용히 는다.
12
+ */
13
+ /**
14
+ * ⛔⭐⭐ **브랜드마다 «칸 이름」이 다르다**(2026-09-12). `makeOpenAICompatProvider` 는 `grok` 과
15
+ * `openai` 를 «한 경로»로 태우는데, 종전엔 둘 다 옛 칸(`max_tokens`·`temperature`)을 «생으로» 박았다.
16
+ * ⇒ `openai` 브랜드의 새 세대(`gpt-5`+)는 그 둘을 «거부»한다 — 400 `unsupported_parameter`.
17
+ *
18
+ * 📏 실측 2026-09-12: `gpt-6-astra · maxTokens=2048 · api.openai.com/v1/chat/completions` 가 400 을 받았고,
19
+ * 그 400 이 `review.done` 미실행 57건 중 ***30건***의 사유였다(무인 리뷰가 그만큼 «안 돌았다»).
20
+ *
21
+ * ⭐ 자는 «이미» 있었다 — `openAiOutputTokenField`·`openAiTemperatureField`. ***이 호출부가 안 물었을 뿐이다.***
22
+ * 🪞 같은 파일의 `stripLocalLlmSpec` 이 「두 builder 중 하나만 정규화했다」로 난 사고의 처방이었다.
23
+ * ***같은 모양이 다시 났다*** — 그래서 이번에도 «순수 함수로 뽑아» 양쪽이 같은 자를 쓰게 한다.
24
+ *
25
+ * ⛔ grok 은 옛 칸을 그대로 받는다 — 바꾸지 않는다.
26
+ */
27
+ export function openAiCompatSamplingFields(
28
+ brand: string,
29
+ model: string,
30
+ temperature: number,
31
+ maxTokens: number,
32
+ ): Record<string, number> {
33
+ return brand === 'openai'
34
+ ? { ...openAiTemperatureField(model, temperature), ...openAiOutputTokenField(model, maxTokens) }
35
+ : { temperature, max_tokens: maxTokens };
36
+ }
37
+
38
+ export function openAiOutputTokenField(model: string, maxTokens: number): Record<string, number> {
39
+ return isNewGenerationOpenAiModel(model)
40
+ ? { max_completion_tokens: maxTokens }
41
+ : { max_tokens: maxTokens };
42
+ }
43
+
44
+ /** `gpt-5` 이후 계열 판정 — 옛 Chat Completions 파라미터를 거부하는 세대.
45
+ *
46
+ * 🩸⭐⭐ **2026-09-12 — 이 자가 «늙어서» 400 이 돌아왔다.** 종전 문면은 `/^(?:gpt-5|o[1-9])/` 라
47
+ * ***`gpt-6` 계열을 «못 봤다»***. 그래서 `gpt-6-astra` 가 `max_tokens` 로 나갔고 400 을 받았다:
48
+ * `Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens'`
49
+ * 📏 실측(2026-09-12 · 12시간 창): `review.done` 200행 중 `reviewed=false` 57, 그중 ***30***이 이 400 이다.
50
+ * ⊕ 요청 로그가 그것을 한 줄로 말한다 — `gpt-6-astra · maxTokens=2048 · api.openai.com/v1/chat/completions`.
51
+ *
52
+ * ⇒ ⭐ **세대를 「이름 목록」으로 세지 않는다.** 번호를 «범위»로 읽어 다음 세대가 와도 안 늙게 한다.
53
+ * `gpt-5` 이상(두 자리 포함) ⊕ `o1`~`o9`. ⛔ `gpt-4` 이하와 로컬 모델은 종전대로 옛 칸을 쓴다.
54
+ *
55
+ * 🌐 **외부 그라운딩**(2026-09-12 · omni-crawl `fc-dev`) — 같은 사고가 «업스트림에도» 있었다:
56
+ * · `quantumnous/new-api#7211` — *"GPT-6 Astra 未命中原来的 GPT-5 前缀判断"* (똑같은 접두 판정 누락)
57
+ * · `genkit-ai/genkit#6320` — *"max_tokens is sent verbatim and rejected by reasoning models"*
58
+ * · Azure AI docs — `gpt-6-astra`(2026-09-03) Chat Completions ⊕ Reasoning
59
+ * · overchat.ai — *"Astra does not support `temperature`, `top_p`, `top_logprobs`"*
60
+ * ⇒ ✅ 우리가 `temperature` 를 «생략»하는 것이 외부 사실과 «맞는다».
61
+ * ⚠️ `top_p`·`logprobs` 는 이 경로가 «안 보낸다»(local 프리셋 경로만 보낸다) — 그래서 조치 없음.
62
+ *
63
+ * ⚖️ ⛔ **알려진 트레이드오프 — new-api 는 «반대» 결론을 냈다.** 그들은
64
+ * *"모든 미래 GPT 메이저를 GPT-5 로 묶으면 서로 다른 모델의 파라미터 규칙이 엮인다"* 며
65
+ * ***미지의 미래 메이저는 추론하지 않는다***로 갔다(명시 목록 + 날짜 스냅샷).
66
+ * ⇒ 우리는 «반대»를 택했다. 이유: ***목록이 늙어서 이 사고가 났기 때문***이다
67
+ * (이 저장소에서 실제로 리뷰 미실행 30건을 냈다). 새 규칙은 «새 관례 쪽으로» 실패한다.
68
+ * 📌 그러므로 ***`gpt-N` 중 옛 칸을 «되찾는» 모델이 나오면 이 자가 틀린다.*** 그때는
69
+ * 여기서 갈지 말고 «모델별 능력 선언»으로 옮긴다(new-api 가 간 길). 지금은 그 표본이 0이다. */
70
+ export function isNewGenerationOpenAiModel(model: string): boolean {
71
+ const match = /^gpt-(\d+)/i.exec(model);
72
+ if (match) return Number.parseInt(match[1]!, 10) >= 5;
73
+ return /^o[1-9]/i.test(model);
74
+ }
75
+
76
+ /**
77
+ * ⛔⭐ 같은 세대가 `temperature` 도 거부한다 — 400 `unsupported_value`,
78
+ * *"Only the default (1) value is supported"*.
79
+ *
80
+ * 📏 2026-08-22 실측: `max_tokens` 를 고친 «2분 뒤»(00:13:03Z)부터 이 400 이 났고
81
+ * 90분에 **41건**이었다. ⇒ ***한 파라미터만 고치면 다음 파라미터에서 막힌다.***
82
+ * ⚠️ 그때 나는 「수리 뒤 400 이 0건」이라 보고했는데, 그 자가 `grep max_completion_tokens`
83
+ * 라서 «새 400»을 못 봤다 — ***좁은 자로 「나았다」를 읽었다.***
84
+ *
85
+ * ⇒ 값을 «1로 보내지» 않고 ***칸을 생략***한다. 서버 기본이 1이고, 보내면 또 다른 거부를 부른다.
86
+ */
87
+ export function openAiTemperatureField(model: string, temperature: number): Record<string, number> {
88
+ return isNewGenerationOpenAiModel(model) ? {} : { temperature };
89
+ }
@@ -0,0 +1,61 @@
1
+ import type { LLMProviderName } from '../user-config.js';
2
+
3
+ /** Lightweight model-id family — prefix/substring only. No catalog, no
4
+ * `src/llm/model-defaults.ts` (that module imports this file). */
5
+ export type RuntimeLlmModelFamily =
6
+ | 'grok' | 'anthropic' | 'openai' | 'openai-codex' | 'gemini' | 'local'
7
+ | 'kimi' | 'qwen' | 'glm' | 'openrouter' | 'bedrock' | 'unknown';
8
+
9
+ export function inferRuntimeLlmModelFamily(model: string | undefined): RuntimeLlmModelFamily {
10
+ if (!model) return 'unknown';
11
+ const m = model.trim().toLowerCase();
12
+ if (!m) return 'unknown';
13
+ // ⛔ 2026-09-23 — 게이트웨이 접두가 «먼저»다. 안 그러면 `openrouter/anthropic/claude-…` 가 `anthropic` 으로
14
+ // 읽혀 openrouter 와 «비호환»이 되고, `openrouter/z-ai/…` 는 `unknown` 이라 아무 provider 와도 «호환»이 됐다.
15
+ if (m.startsWith('openrouter/')) return 'openrouter';
16
+ // ⭐ BEDROCK-PROVIDER — Bedrock 전용 꼴(`anthropic.claude-…`·지역 접두·`bedrock/…`)이 `includes('claude')` 보다 «먼저».
17
+ // 1st-party id(`claude-…`)는 그대로 anthropic 이다(불변).
18
+ if (m.startsWith('bedrock/') || /^(?:[a-z]{2,6}\.)?anthropic\.claude-/.test(m)) return 'bedrock';
19
+ if (m.includes('grok')) return 'grok';
20
+ if (m.includes('claude')) return 'anthropic';
21
+ if (m.startsWith('gemini-') || m.includes('gemini')) return 'gemini';
22
+ if (m.startsWith('local:')) return 'local';
23
+ if (m.startsWith('kimi')) return 'kimi';
24
+ if (m.startsWith('qwen')) return 'qwen';
25
+ if (m.startsWith('glm')) return 'glm';
26
+ // openai-codex 구독 모델만 여기 — gpt-5.5 등 Chat Completions 모델은 openai.
27
+ // ⛔ openai 와 openai-codex 를 한 계열로 접지 마라. 서로 다른 엔드포인트다.
28
+ // ✅ 2026-09-23 (대표 ⒜ 결정) — ***`gpt-6` 를 여기 «더했다».***
29
+ // 종전엔 `gpt-6-*` 가 아래 `startsWith('gpt-')` 로 떨어져 `openai` 가 됐고, 그래서
30
+ // ***사다리가 «자기 가드가 거부하는 모델»을 가리켰다*** (`CODEX.loaded = gpt-6-astra`).
31
+ // 📏 구독 경로 실호출로 확인(codex-cli 0.155.1): gpt-6-sol · luna · astra 전부 응답.
32
+ // ⚠️ 이 셋은 API 로도 불린다(`/v1/models` 에 있다). 「계열」이 재는 것은 «가용성»이 아니라
33
+ // ***「우리가 어느 문으로 보내나」***다 — 5.6 계열도 API 에 있지만 여기로 온다.
34
+ if (m.includes('codex') || m.startsWith('gpt-5.6') || m.startsWith('gpt-6')) return 'openai-codex';
35
+ // Exact o1/o3/o4 ids are standard OpenAI models; prefix-only (`o1-`) misses them.
36
+ if (
37
+ m.startsWith('gpt-')
38
+ || m === 'o1' || m.startsWith('o1-')
39
+ || m === 'o3' || m.startsWith('o3-')
40
+ || m === 'o4' || m.startsWith('o4-')
41
+ ) return 'openai';
42
+ return 'unknown';
43
+ }
44
+
45
+ /** Cycle-safe compatibility: same-provider model overrides pass;
46
+ * cross-family ids fail. Unknown prefixes and `auto` stay silent.
47
+ * ⛔ `openai` 와 `openai-codex` 는 별개 provider — 양방향 호환으로 접지 않는다. */
48
+ export function isRuntimeLlmModelCompatibleWithProvider(
49
+ provider: LLMProviderName,
50
+ model: string | undefined,
51
+ ): boolean {
52
+ if (!model) return true;
53
+ if (provider === 'auto') return true;
54
+ const family = inferRuntimeLlmModelFamily(model);
55
+ if (family === 'unknown') return true;
56
+ if (provider === 'local') return family === 'local';
57
+ // bedrock 은 1st-party claude id 도 받는다(공급자가 `anthropic.` 접두로 바꿔 보낸다).
58
+ if (provider === 'bedrock') return family === 'bedrock' || family === 'anthropic';
59
+ return provider === family;
60
+ }
61
+
@@ -122,6 +122,26 @@ export interface ZaiErrorClass {
122
122
  resetRaw: string | null;
123
123
  }
124
124
 
125
+ /** Provider-neutral signal shape for supervisors coordinating plan-limit recovery. */
126
+ export interface ProviderPlanLimitSignal {
127
+ provider: string;
128
+ kind: 'plan-limit';
129
+ resetAt: number | null;
130
+ overage: string;
131
+ }
132
+
133
+ /** Extract the structured recovery signal from a Z.ai 1308 response; unrelated errors return null. */
134
+ export function extractZaiPlanLimitSignal(
135
+ status: number,
136
+ bodyText: string,
137
+ overage: string,
138
+ ): ProviderPlanLimitSignal | null {
139
+ const classified = classifyZaiError(status, bodyText);
140
+ if (!classified || classified.code !== 1308 || classified.kind !== 'plan-limit') return null;
141
+ return { provider: 'glm', kind: 'plan-limit', resetAt: classified.resetAt, overage };
142
+ }
143
+
144
+
125
145
  const PLAN_LIMIT = new Set([1308, 1310]);
126
146
  const BALANCE_LIMIT = new Set([1113, 1316, 1317, 1318, 1319, 1320, 1321]);
127
147
  const PLAN_UNAVAILABLE = new Set([1309, 1311, 1313, 1314, 1315]);
@@ -433,13 +453,15 @@ export class ZaiCodingPlanLimitError extends Error {
433
453
  readonly code: number;
434
454
  readonly limitKind: ZaiLimitKind;
435
455
  readonly resetAt: number | null;
436
- constructor(opts: { code: number; limitKind: ZaiLimitKind; resetAt: number | null; policy: ZaiOveragePolicy; reason: string }) {
456
+ readonly planLimitSignal?: ProviderPlanLimitSignal;
457
+ constructor(opts: { code: number; limitKind: ZaiLimitKind; resetAt: number | null; policy: ZaiOveragePolicy; reason: string; planLimitSignal?: ProviderPlanLimitSignal }) {
437
458
  const when = opts.resetAt ? ` · 리셋 ${new Date(opts.resetAt).toISOString()}` : '';
438
459
  super(`GLM Coding Plan 한도(code ${opts.code} · ${opts.limitKind}${when}) — 정책 llm.zaiCodingPlan.overage=${opts.policy}: ${opts.reason}`);
439
460
  this.name = 'ZaiCodingPlanLimitError';
440
461
  this.code = opts.code;
441
462
  this.limitKind = opts.limitKind;
442
463
  this.resetAt = opts.resetAt;
464
+ if (opts.planLimitSignal) this.planLimitSignal = opts.planLimitSignal;
443
465
  }
444
466
  }
445
467
 
@@ -575,6 +597,9 @@ export function makeZaiCodingPlanProvider(cfg: UCLLMConfig, deps: ZaiProviderDep
575
597
  const status = (error as { status?: unknown })?.status;
576
598
  const bodyText = (error as { bodyText?: unknown })?.bodyText;
577
599
  const cls = typeof status === 'number' && typeof bodyText === 'string' ? classifyZaiError(status, bodyText) : null;
600
+ const planLimitSignal = typeof status === 'number' && typeof bodyText === 'string'
601
+ ? extractZaiPlanLimitSignal(status, bodyText, settings.overage)
602
+ : null;
578
603
  if (!cls || cls.kind === 'rate' || cls.kind === 'other') {
579
604
  if (cls) debug.log('zai.coding-plan', 'error', { code: cls.code, kind: cls.kind, model: wireModel }, { level: 'warn' });
580
605
  throw error;
@@ -588,6 +613,7 @@ export function makeZaiCodingPlanProvider(cfg: UCLLMConfig, deps: ZaiProviderDep
588
613
  if (action === 'stop' || emitted) {
589
614
  throw new ZaiCodingPlanLimitError({
590
615
  code: cls.code, limitKind: cls.kind, resetAt: cls.resetAt, policy: settings.overage,
616
+ ...(planLimitSignal ? { planLimitSignal } : {}),
591
617
  reason: emitted ? '출력이 이미 나간 뒤라 폴백하지 않는다' : '리셋까지 멈춘다',
592
618
  });
593
619
  }
package/src/llm.ts CHANGED
@@ -42,6 +42,7 @@ import {
42
42
  } from './session-runtime/retry-policy.js';
43
43
  import { fetchApiWithRetry, OverloadFailoverError, type FetchApiWithRetryOpts } from './session-runtime/retry-api.js';
44
44
  import { BedrockProvider, isBedrockCompatibleModel, makeBedrockProvider } from './llm/bedrock-provider.js';
45
+ import { OPEN_WEIGHT_TOOL_DISCIPLINE } from './llm/open-weight-discipline.js';
45
46
  import { makeZaiCodingPlanProvider, zaiCodingPlanAvailable } from './llm/zai-coding-plan.js';
46
47
  import { isOpenRouterDeepSeekWireModel, nonEmptyReasoningDetails, openRouterDeepSeekCatalogEffort, openRouterDeepSeekEffort, openRouterDeepSeekRequestExtras, openRouterNeedsKimiToolSchema } from './llm/openrouter-deepseek.js';
47
48
  import { resolveModelAlias } from './intelligence-map/model-alias.js';
@@ -5165,14 +5166,9 @@ const LOCAL_TOOL_DISCIPLINE = [
5165
5166
  '- 범위 읽기만으로 판단할 수 없을 때에만 전체 읽기를 선택하고, 읽은 뒤에는 다음 행동을 계속 결정하라.',
5166
5167
  ].join('\n');
5167
5168
 
5168
- /** OpenRouter(`openrouter/…`) GLM·Kimi·Qwen 전용 도구 호출 규율 — 다른 군 상수와 합성하지 않는 독립 상수. */
5169
- export const OPEN_WEIGHT_TOOL_DISCIPLINE = [
5170
- '[open-weight tool-use discipline]',
5171
- '- 도구로 할 수 있는 일은 이번 응답에서 바로 도구를 호출하라. "먼저 읽겠다" 또는 "확인하겠다" 같은 계획만 말하고 응답을 끝내지 마라.',
5172
- '- 작업을 시작하는 첫 응답에는 도구 호출이 하나 이상 있어야 한다.',
5173
- '- 도구 호출 인자는 해당 도구의 스키마에 맞는 JSON 으로 내라.',
5174
- '- 충분한 근거가 모이면 도구 호출 없이 최종 답을 평문으로 써서 끝내라.',
5175
- ].join('\n');
5169
+ // ⭐ 2026-10-11 GLM-PROMPT-TUNE: 상수 정의는 `src/llm/open-weight-discipline.ts` 로 옮겼다(llm.ts 동결 RFC #25983).
5170
+ // llm.ts 는 이 재수출만 남긴다 — 기존 임포트 경로(`./llm.js`)를 그대로 지킨다.
5171
+ export { OPEN_WEIGHT_TOOL_DISCIPLINE };
5176
5172
 
5177
5173
  /** 모델군 → 그 군에 주입할 툴 규율(없으면 `null`). **능력 술어 판** — 2026-08-14.
5178
5174
  *
@@ -11703,92 +11699,16 @@ export function getProviderForConfig(
11703
11699
  import { getModelFamily } from './models/prompts.js';
11704
11700
  import type { ModelFamily } from './models/prompts.js';
11705
11701
 
11706
- /**
11707
- * ⛔⭐ OpenAI Chat Completions 의 «출력 상한» 칸 이름은 모델 세대로 갈린다.
11708
- *
11709
- * `gpt-5` 이후 계열은 `max_tokens` 를 ***거부한다*** — 400 `unsupported_parameter` 를 내고
11710
- * *"Use 'max_completion_tokens' instead"* 라고 말한다. `gpt-4o` 계열은 반대로 옛 이름만 받는다.
11711
- *
11712
- * 📏 2026-08-22 실측: `provider auto` 의 티어 사다리가 `gpt-5.6-*` 로 바뀐 뒤(`#11161`)
11713
- * 3시간 만에 이 400 이 **93건** 났고 «가속»했다(20h:2 → 21h:16 → 22h:30 → 23h:45).
11714
- * 7일 창에서 그 이전 발생은 ***0***이다. ⇒ 칸 이름을 모델로 갈라야 한다.
11715
- *
11716
- * ⚠️ 값을 «안 보내는» 선택은 하지 않는다 — 상한이 사라지면 비용이 조용히 는다.
11717
- */
11718
- /**
11719
- * ⛔⭐⭐ **브랜드마다 «칸 이름」이 다르다**(2026-09-12). `makeOpenAICompatProvider` 는 `grok` 과
11720
- * `openai` 를 «한 경로»로 태우는데, 종전엔 둘 다 옛 칸(`max_tokens`·`temperature`)을 «생으로» 박았다.
11721
- * ⇒ `openai` 브랜드의 새 세대(`gpt-5`+)는 그 둘을 «거부»한다 — 400 `unsupported_parameter`.
11722
- *
11723
- * 📏 실측 2026-09-12: `gpt-6-astra · maxTokens=2048 · api.openai.com/v1/chat/completions` 가 400 을 받았고,
11724
- * 그 400 이 `review.done` 미실행 57건 중 ***30건***의 사유였다(무인 리뷰가 그만큼 «안 돌았다»).
11725
- *
11726
- * ⭐ 자는 «이미» 있었다 — `openAiOutputTokenField`·`openAiTemperatureField`. ***이 호출부가 안 물었을 뿐이다.***
11727
- * 🪞 같은 파일의 `stripLocalLlmSpec` 이 「두 builder 중 하나만 정규화했다」로 난 사고의 처방이었다.
11728
- * ***같은 모양이 다시 났다*** — 그래서 이번에도 «순수 함수로 뽑아» 양쪽이 같은 자를 쓰게 한다.
11729
- *
11730
- * ⛔ grok 은 옛 칸을 그대로 받는다 — 바꾸지 않는다.
11731
- */
11732
- export function openAiCompatSamplingFields(
11733
- brand: string,
11734
- model: string,
11735
- temperature: number,
11736
- maxTokens: number,
11737
- ): Record<string, number> {
11738
- return brand === 'openai'
11739
- ? { ...openAiTemperatureField(model, temperature), ...openAiOutputTokenField(model, maxTokens) }
11740
- : { temperature, max_tokens: maxTokens };
11741
- }
11742
-
11743
- export function openAiOutputTokenField(model: string, maxTokens: number): Record<string, number> {
11744
- return isNewGenerationOpenAiModel(model)
11745
- ? { max_completion_tokens: maxTokens }
11746
- : { max_tokens: maxTokens };
11747
- }
11748
-
11749
- /** `gpt-5` 이후 계열 판정 — 옛 Chat Completions 파라미터를 거부하는 세대.
11750
- *
11751
- * 🩸⭐⭐ **2026-09-12 — 이 자가 «늙어서» 400 이 돌아왔다.** 종전 문면은 `/^(?:gpt-5|o[1-9])/` 라
11752
- * ***`gpt-6` 계열을 «못 봤다»***. 그래서 `gpt-6-astra` 가 `max_tokens` 로 나갔고 400 을 받았다:
11753
- * `Unsupported parameter: 'max_tokens' is not supported with this model. Use 'max_completion_tokens'`
11754
- * 📏 실측(2026-09-12 · 12시간 창): `review.done` 200행 중 `reviewed=false` 57, 그중 ***30***이 이 400 이다.
11755
- * ⊕ 요청 로그가 그것을 한 줄로 말한다 — `gpt-6-astra · maxTokens=2048 · api.openai.com/v1/chat/completions`.
11756
- *
11757
- * ⇒ ⭐ **세대를 「이름 목록」으로 세지 않는다.** 번호를 «범위»로 읽어 다음 세대가 와도 안 늙게 한다.
11758
- * `gpt-5` 이상(두 자리 포함) ⊕ `o1`~`o9`. ⛔ `gpt-4` 이하와 로컬 모델은 종전대로 옛 칸을 쓴다.
11759
- *
11760
- * 🌐 **외부 그라운딩**(2026-09-12 · omni-crawl `fc-dev`) — 같은 사고가 «업스트림에도» 있었다:
11761
- * · `quantumnous/new-api#7211` — *"GPT-6 Astra 未命中原来的 GPT-5 前缀判断"* (똑같은 접두 판정 누락)
11762
- * · `genkit-ai/genkit#6320` — *"max_tokens is sent verbatim and rejected by reasoning models"*
11763
- * · Azure AI docs — `gpt-6-astra`(2026-09-03) Chat Completions ⊕ Reasoning
11764
- * · overchat.ai — *"Astra does not support `temperature`, `top_p`, `top_logprobs`"*
11765
- * ⇒ ✅ 우리가 `temperature` 를 «생략»하는 것이 외부 사실과 «맞는다».
11766
- * ⚠️ `top_p`·`logprobs` 는 이 경로가 «안 보낸다»(local 프리셋 경로만 보낸다) — 그래서 조치 없음.
11767
- *
11768
- * ⚖️ ⛔ **알려진 트레이드오프 — new-api 는 «반대» 결론을 냈다.** 그들은
11769
- * *"모든 미래 GPT 메이저를 GPT-5 로 묶으면 서로 다른 모델의 파라미터 규칙이 엮인다"* 며
11770
- * ***미지의 미래 메이저는 추론하지 않는다***로 갔다(명시 목록 + 날짜 스냅샷).
11771
- * ⇒ 우리는 «반대»를 택했다. 이유: ***목록이 늙어서 이 사고가 났기 때문***이다
11772
- * (이 저장소에서 실제로 리뷰 미실행 30건을 냈다). 새 규칙은 «새 관례 쪽으로» 실패한다.
11773
- * 📌 그러므로 ***`gpt-N` 중 옛 칸을 «되찾는» 모델이 나오면 이 자가 틀린다.*** 그때는
11774
- * 여기서 갈지 말고 «모델별 능력 선언»으로 옮긴다(new-api 가 간 길). 지금은 그 표본이 0이다. */
11775
- export function isNewGenerationOpenAiModel(model: string): boolean {
11776
- const match = /^gpt-(\d+)/i.exec(model);
11777
- if (match) return Number.parseInt(match[1]!, 10) >= 5;
11778
- return /^o[1-9]/i.test(model);
11779
- }
11780
-
11781
- /**
11782
- * ⛔⭐ 같은 세대가 `temperature` 도 거부한다 — 400 `unsupported_value`,
11783
- * *"Only the default (1) value is supported"*.
11784
- *
11785
- * 📏 2026-08-22 실측: `max_tokens` 를 고친 «2분 뒤»(00:13:03Z)부터 이 400 이 났고
11786
- * 90분에 **41건**이었다. ⇒ ***한 파라미터만 고치면 다음 파라미터에서 막힌다.***
11787
- * ⚠️ 그때 나는 「수리 뒤 400 이 0건」이라 보고했는데, 그 자가 `grep max_completion_tokens`
11788
- * 라서 «새 400»을 못 봤다 — ***좁은 자로 「나았다」를 읽었다.***
11789
- *
11790
- * ⇒ 값을 «1로 보내지» 않고 ***칸을 생략***한다. 서버 기본이 1이고, 보내면 또 다른 거부를 부른다.
11791
- */
11792
- export function openAiTemperatureField(model: string, temperature: number): Record<string, number> {
11793
- return isNewGenerationOpenAiModel(model) ? {} : { temperature };
11794
- }
11702
+ // COMPAT(llm-facade-openai-sampling-fields) · 기존 llm.ts 공개 API 유지.
11703
+ import {
11704
+ openAiCompatSamplingFields,
11705
+ openAiOutputTokenField,
11706
+ isNewGenerationOpenAiModel,
11707
+ openAiTemperatureField,
11708
+ } from './llm/openai-sampling-fields.js';
11709
+ export {
11710
+ openAiCompatSamplingFields,
11711
+ openAiOutputTokenField,
11712
+ isNewGenerationOpenAiModel,
11713
+ openAiTemperatureField,
11714
+ };
@@ -10,6 +10,16 @@ export interface MachineRow {
10
10
  locationStatus: string;
11
11
  role: string;
12
12
  duties: string;
13
+ /** Fleet intent only. Live membership comes from Nexus machine resources. */
14
+ fleet?: MachineFleetIntent;
15
+ }
16
+
17
+ export interface MachineFleetIntent {
18
+ sshName: string;
19
+ role: 'worker' | 'hq';
20
+ platform: 'darwin' | 'linux' | 'wsl';
21
+ podPool: string;
22
+ cap: number;
13
23
  }
14
24
 
15
25
  export interface DeviceRow {
@@ -59,18 +69,36 @@ export function validateMachineLedger(value: unknown): MachineLedger {
59
69
  keys(data, ['title', 'policy', 'machines', 'devices', 'rules', 'changes'], 'ledger');
60
70
  if (!Array.isArray(data.machines) || !Array.isArray(data.devices)) throw new Error('invalid machines or devices');
61
71
  const ids = new Set<string>();
62
- const rows = <T extends { id: string }>(entries: unknown[], fields: string[], label: string): T[] => entries.map((entry, index) => {
72
+ const rows = <T extends { id: string }>(entries: unknown[], fields: string[], label: string, extraFields: string[] = []): T[] => entries.map((entry, index) => {
63
73
  const row = record(entry, `${label}[${index}]`);
64
- keys(row, fields, label);
74
+ keys(row, [...fields, ...extraFields], label);
65
75
  const result = Object.fromEntries(fields.map((field) => [field, text(row[field], `${label}.${field}`)])) as T;
66
76
  if (!idPattern.test(result.id) || ids.has(result.id)) throw new Error(`empty, duplicate or invalid id: ${result.id}`);
67
77
  ids.add(result.id);
68
78
  return result;
69
79
  });
80
+ const machines = rows<MachineRow>(data.machines, ['id', 'name', 'specs', 'locationStatus', 'role', 'duties'], 'machines', ['fleet']);
81
+ const sshNames = new Set<string>();
82
+ for (let index = 0; index < machines.length; index++) {
83
+ const raw = record(data.machines[index], `machines[${index}]`);
84
+ if (raw.fleet === undefined) continue;
85
+ const fleet = record(raw.fleet, `machines[${index}].fleet`);
86
+ keys(fleet, ['sshName', 'role', 'platform', 'podPool', 'cap'], 'fleet');
87
+ const sshName = text(fleet.sshName, 'fleet.sshName');
88
+ const role = text(fleet.role, 'fleet.role');
89
+ const platform = text(fleet.platform, 'fleet.platform');
90
+ const podPool = text(fleet.podPool, 'fleet.podPool');
91
+ if (!idPattern.test(sshName) || sshNames.has(sshName)) throw new Error(`duplicate or invalid fleet.sshName: ${sshName}`);
92
+ if (role !== 'worker' && role !== 'hq') throw new Error(`invalid fleet.role: ${role}`);
93
+ if (platform !== 'darwin' && platform !== 'linux' && platform !== 'wsl') throw new Error(`invalid fleet.platform: ${platform}`);
94
+ if (!Number.isSafeInteger(fleet.cap) || (fleet.cap as number) < 0) throw new Error('invalid fleet.cap');
95
+ sshNames.add(sshName);
96
+ machines[index]!.fleet = { sshName, role, platform, podPool, cap: fleet.cap as number };
97
+ }
70
98
  return {
71
99
  title: text(data.title, 'title'),
72
100
  policy: list(data.policy, 'policy'),
73
- machines: rows<MachineRow>(data.machines, ['id', 'name', 'specs', 'locationStatus', 'role', 'duties'], 'machines'),
101
+ machines,
74
102
  devices: rows<DeviceRow>(data.devices, ['id', 'name', 'status', 'purpose'], 'devices'),
75
103
  rules: list(data.rules, 'rules'),
76
104
  changes: list(data.changes, 'changes'),