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
@@ -10,9 +10,11 @@ export interface Project {
10
10
  name: string;
11
11
  primaryFolder?: string;
12
12
  createdAt: string;
13
+ relations?: Array<{ type: 'dependsOn' | 'derivedFrom' | 'partOf' | 'deploysTo'; target: string }>;
13
14
  }
14
15
 
15
16
  const PROJECT_ID = /^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i;
17
+ const RELATION_TYPES = new Set(['dependsOn', 'derivedFrom', 'partOf', 'deploysTo']);
16
18
 
17
19
  function validId(id: unknown): id is string {
18
20
  return typeof id === 'string' && PROJECT_ID.test(id);
@@ -26,9 +28,27 @@ function validateProject(value: unknown): Project {
26
28
  || (item.primaryFolder !== undefined && (typeof item.primaryFolder !== 'string' || !isAbsolute(item.primaryFolder)))) {
27
29
  throw new Error('invalid project record');
28
30
  }
31
+ if (item.relations !== undefined) {
32
+ if (!Array.isArray(item.relations)) throw new Error('invalid project record');
33
+ const seen = new Set<string>();
34
+ for (const rel of item.relations) {
35
+ if (!rel || typeof rel !== 'object' || Array.isArray(rel)) throw new Error('invalid project record');
36
+ const edge = rel as Record<string, unknown>;
37
+ if (!RELATION_TYPES.has(edge.type as string) || !validId(edge.target) || edge.target === item.id) {
38
+ throw new Error('invalid project record');
39
+ }
40
+ const key = `${edge.type}\0${edge.target}`;
41
+ if (seen.has(key)) throw new Error('invalid project record');
42
+ seen.add(key);
43
+ }
44
+ }
29
45
  return value as Project;
30
46
  }
31
47
 
48
+ export function relationsOf(project: Project): Array<{ type: 'dependsOn' | 'derivedFrom' | 'partOf' | 'deploysTo'; target: string }> {
49
+ return project.relations ?? [];
50
+ }
51
+
32
52
  export class ProjectStore {
33
53
  readonly dir: string;
34
54
 
@@ -393,6 +393,8 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
393
393
  let complication: string | undefined;
394
394
  let decisionSignal: EnhanceResult['decisionSignal'];
395
395
  let enhancedBy: 'llm' | 'fallback' = 'llm';
396
+ let fallbackReason: 'llm-error' | 'empty-reply' | 'unparsed' | 'none' = 'none';
397
+ let replyChars = 0;
396
398
  const groundedFacts = opts.groundedFacts ?? [];
397
399
  const wantsScqa = groundedFacts.length > 0;
398
400
 
@@ -439,6 +441,10 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
439
441
  try { opts.onUsage?.(usage); } catch { /* usage observation must not change enhancement */ }
440
442
  },
441
443
  });
444
+ replyChars = rawOut.length;
445
+ if (rawOut.trim().length === 0) {
446
+ fallbackReason = 'empty-reply';
447
+ }
442
448
  const parsed = parseEnhanceJson(rawOut);
443
449
  if (parsed) {
444
450
  goal = parsed.goal;
@@ -449,9 +455,11 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
449
455
  complication = parsed.complication;
450
456
  decisionSignal = parsed.decisionSignal;
451
457
  } else {
458
+ fallbackReason = fallbackReason === 'empty-reply' ? 'empty-reply' : 'unparsed';
452
459
  enhancedBy = 'fallback';
453
460
  }
454
461
  } catch (e) {
462
+ fallbackReason = 'llm-error';
455
463
  debug.log('prompt-enhance', 'llm-error', { error: String((e as { message?: string })?.message ?? e).slice(0, 160) }, { level: 'error' });
456
464
  enhancedBy = 'fallback';
457
465
  }
@@ -461,6 +469,7 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
461
469
  checklist = extractChecklistFallback(original);
462
470
  checklistProvenance = checklist.map(() => 'unknown');
463
471
  enhancedBy = 'fallback';
472
+ if (fallbackReason === 'none') fallbackReason = 'unparsed';
464
473
  }
465
474
  if (!constraints.length) {
466
475
  constraints = [
@@ -515,6 +524,8 @@ export async function enhancePrompt(raw: string, opts: EnhanceOpts = {}): Promis
515
524
  enhancedChars: enhanced.length,
516
525
  checklist: checklist.length,
517
526
  enhancedBy,
527
+ fallbackReason,
528
+ replyChars,
518
529
  model,
519
530
  verbatimPreserved,
520
531
  // ⭐ 관측 — 「요약을 요구했나 / 받았나 / 옮겨 적어 버렸나」를 «다른 값»으로 남긴다.
@@ -1,3 +1,4 @@
1
+ import { debug } from '../debug/log.js';
1
2
  import { releaseLedgerRoot } from '../instance/resolve.js';
2
3
  import { releaseReadiness, type ReleaseReadiness } from '../../scripts/release-loop/release-readiness.js';
3
4
  import { listSchedules, type ReleaseSchedule } from './release-schedule.js';
@@ -21,7 +22,7 @@ export type AutoStartResult =
21
22
  | { status: 'no-cut' }
22
23
  | { status: 'planned'; version: string; cutAt: string }
23
24
  | { status: 'skipped'; version: string; reason: AutoStartDeferral['reason'] }
24
- | { status: 'started'; version: string; cutAt: string };
25
+ | { status: 'started'; version: string; cutAt: string; publishAt?: string };
25
26
 
26
27
  export interface AutoStartOptions {
27
28
  windowMinutes: number;
@@ -30,7 +31,7 @@ export interface AutoStartOptions {
30
31
  ledgerRoot?: string;
31
32
  schedules?: (root: string) => ReleaseSchedule[];
32
33
  readiness?: (version: string, ledgerRoot: string, now: Date) => ReleaseReadiness;
33
- launch?: (version: string) => void | AutoStartDeferral | Promise<void | AutoStartDeferral>;
34
+ launch?: (version: string, launchOptions?: { publishAt?: string }) => void | AutoStartDeferral | Promise<void | AutoStartDeferral>;
34
35
  }
35
36
 
36
37
  /** Select from the release schedule; the existing `release run --if-ready` owns the launch-time lock and guards. */
@@ -40,12 +41,13 @@ export async function autoStartScheduledRelease(options: AutoStartOptions): Prom
40
41
  // Validate the window even when the ledger has no rows.
41
42
  const schedule = selectScheduledCut((options.schedules ?? listSchedules)(root), now, options.windowMinutes);
42
43
  if (!schedule) return { status: 'no-cut' };
43
- const { version, cutAt } = schedule;
44
+ const { version, cutAt, publishAt } = schedule;
44
45
  if (!options.apply) return { status: 'planned', version, cutAt };
45
46
  const readiness = (options.readiness ?? ((v, ledgerRoot, at) => releaseReadiness(v, { ledgerRoot, now: () => at })))(version, root, now);
46
47
  if (!readiness.ready) return { status: 'skipped', version, reason: readiness.reason };
47
48
  if (!options.launch) throw new Error('auto-start apply requires a launch callback');
48
- const launched = await options.launch(version);
49
+ const launched = await options.launch(version, publishAt != null ? { publishAt: publishAt } : {});
49
50
  if (launched?.deferred) return { status: 'skipped', version, reason: launched.reason };
50
- return { status: 'started', version, cutAt };
51
+ debug.log('release.schedule', 'auto-start', { version, cutAt, publishAt: publishAt ?? null });
52
+ return { status: 'started', version, cutAt, ...(publishAt != null ? { publishAt: publishAt } : {}) };
51
53
  }
@@ -10,6 +10,8 @@ export type ChecklistDisposition = 'move' | 'known-issue' | 'block';
10
10
  /** `screen` = a five-surface feature cell — its evidence carries a `짝:` line (MANUAL-five-surface-parity §A). `postpub` = measured after publication, outside the pre-publication gate. */
11
11
  export type ChecklistKind = 'screen' | 'postpub';
12
12
  const CHECKLIST_KINDS: readonly ChecklistKind[] = ['screen', 'postpub'];
13
+ export type ChecklistDispatchKind = 'code' | 'ops' | 'measure' | 'decision' | 'umbrella';
14
+ const CHECKLIST_DISPATCH_KINDS: readonly ChecklistDispatchKind[] = ['code', 'ops', 'measure', 'decision', 'umbrella'];
13
15
  export interface ChecklistItem {
14
16
  id: string;
15
17
  title: string;
@@ -27,6 +29,8 @@ export interface ChecklistItem {
27
29
  evidence?: string;
28
30
  disposition?: ChecklistDisposition;
29
31
  kind?: ChecklistKind;
32
+ /** Whether the seat dispatcher should launch a coding task. Missing in old rows means code. */
33
+ dispatchKind?: ChecklistDispatchKind;
30
34
  updatedAt: string;
31
35
  updatedBy: string;
32
36
  }
@@ -102,6 +106,14 @@ export function statusChangesSince(history: readonly ChecklistHistory[], sinceIs
102
106
  return history.filter((entry) => entry.field === 'status' && Date.parse(entry.at) >= since);
103
107
  }
104
108
 
109
+ /** CELL-DEPENDS-ID: a predecessor must name a cell that exists in SOME version — this one (data.items) or any other (otherItems). */
110
+ function assertPredecessorsExist(predecessors: readonly string[] | undefined, data: Checklist, otherItems: (id: string) => store.ChecklistCollision[]): void {
111
+ for (const id of predecessors ?? []) {
112
+ if (data.items.some((item) => item.id === id) || otherItems(id).length) continue;
113
+ throw new CliUserError(`없는 선행 칸: ${JSON.stringify(id).slice(1, -1)}`, '어느 판에도 없는 id 다 — release checklist status --json 으로 칸 id 를 확인한다');
114
+ }
115
+ }
116
+
105
117
  function mutate(v: string, apply: (data: Checklist, otherItems: (id: string) => store.ChecklistCollision[]) => boolean): Checklist {
106
118
  // addItem/setItem/claimItem/removeItem/seedFromRoadmap reach the generation-fenced ledger write here.
107
119
  return decodeClaimHistory(store.mutate(v, store.releasedVersion(), devVersion(), apply));
@@ -114,6 +126,37 @@ function change(data: Checklist, id: string, field: string, from: unknown, to: u
114
126
 
115
127
  const REPO_ROOT = join(import.meta.dir, '..', '..');
116
128
 
129
+ const PATH_TOKEN = /(?:^|[^A-Za-z0-9_.\/-])((?:(?:[A-Za-z0-9_.-]+\/)+)?[A-Za-z0-9_.-]+\.(?:ts|tsx|js|jsx|mjs|cjs|json|md|yaml|yml|sh|py|css|html|toml|sql|rs|swift))(?![A-Za-z0-9_.\/-])/g;
130
+ function mentionedPaths(text: string): string[] {
131
+ return [...text.matchAll(PATH_TOKEN)].map((match) => match[1]!).filter((path) => !path.split('/').includes('..'));
132
+ }
133
+
134
+ /** Shadow check at checklist authorship. Callers supply the origin/main file probe and merged-PR file reader. */
135
+ export function inspectChecklistTargetPaths(input: {
136
+ title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind;
137
+ }, deps: { existsAtMain: (path: string) => boolean; mergedPrFiles?: (number: number) => readonly string[] }): {
138
+ targets: string[]; warnings: string[]; candidates: string[];
139
+ } {
140
+ const lines = input.title.split(/\r?\n/);
141
+ const first = /^대상 경로:\s*(.*)$/.exec(lines[0] ?? '');
142
+ const targets = first ? [...new Set(mentionedPaths(first[1]!))] : [];
143
+ const newFileDeclared = /^신설:\s*/.test(lines[1] ?? '');
144
+ const warnings: string[] = [];
145
+ if ((input.dispatchKind ?? 'code') === 'code') {
146
+ if (!first || !first[1]!.trim() || targets.length === 0) warnings.push('첫 줄 대상 경로가 없다');
147
+ for (const path of targets) if (!deps.existsAtMain(path) && !newFileDeclared) warnings.push(`${path}: origin/main에 없는 파일 · 신설: 둘째 줄 선언 필요`);
148
+ }
149
+ if (!warnings.length) return { targets, warnings, candidates: [] };
150
+ const sources = [input.title, input.evidence ?? '', ...(input.refs ?? [])].join('\n');
151
+ const candidates = [...new Set(mentionedPaths(sources).filter(deps.existsAtMain))];
152
+ for (const match of sources.matchAll(/(?:^|[^\d])#(\d{2,8})\b/g)) {
153
+ for (const path of deps.mergedPrFiles?.(Number(match[1])) ?? []) {
154
+ if (deps.existsAtMain(path) && !candidates.includes(path)) candidates.push(path);
155
+ }
156
+ }
157
+ return { targets, warnings, candidates };
158
+ }
159
+
117
160
  /** `--ref` 문서를 찾는 뿌리들 — 이 코드의 트리 ⊕ 지금 작업 디렉토리의 git 뿌리.
118
161
  * ⭐ 설치본(`~/.local/share/elanous/current`)에는 `docs/` 가 없다 — 저장소 안에서 부른 설치본도 저장소 문서를 인용할 수 있게. */
119
162
  export function refRoots(cwd = process.cwd()): string[] {
@@ -225,10 +268,11 @@ export function validateCeoLoad(input: { ceoMinutes?: number; ceoDate?: string }
225
268
  if (input.ceoDate !== undefined && (!/^\d{4}-\d{2}-\d{2}$/.test(input.ceoDate) || !Number.isFinite(Date.parse(`${input.ceoDate}T00:00:00Z`)) || new Date(`${input.ceoDate}T00:00:00Z`).toISOString().slice(0, 10) !== input.ceoDate)) throw new CliUserError('대표 손 날짜는 YYYY-MM-DD 이어야 한다');
226
269
  }
227
270
 
228
- export function addItem(v: string, input: { id: string; title: string; refs?: string[]; owner?: string; kind?: ChecklistKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean }, options: { allowDuplicateId?: boolean } = {}): Checklist {
271
+ export function addItem(v: string, input: { id: string; title: string; refs?: string[]; owner?: string; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean }, options: { allowDuplicateId?: boolean } = {}): Checklist {
229
272
  if (!input.id.trim()) throw new CliUserError('칸 id 가 비었다');
230
273
  if (!input.title.trim()) throw new CliUserError('칸 제목이 비었다');
231
274
  if (input.kind !== undefined && !CHECKLIST_KINDS.includes(input.kind)) throw new CliUserError(`잘못된 종류: ${input.kind}`, 'screen|postpub');
275
+ if (input.dispatchKind !== undefined && !CHECKLIST_DISPATCH_KINDS.includes(input.dispatchKind)) throw new CliUserError(`잘못된 발사 종류: ${input.dispatchKind}`, 'code|ops|measure|decision|umbrella');
232
276
  if (input.owner !== undefined) parseOwner(input.owner);
233
277
  if (input.priority !== undefined && !['P0', 'P1', 'P2'].includes(input.priority)) throw new CliUserError(`잘못된 우선순위: ${input.priority}`);
234
278
  if (input.predecessors !== undefined && (!Array.isArray(input.predecessors) || input.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === input.id))) throw new CliUserError('잘못된 선행 칸');
@@ -244,24 +288,27 @@ export function addItem(v: string, input: { id: string; title: string; refs?: st
244
288
  console.error(`⚠ 중복 id: ${displayedId} — ${collisions.map((item) => `${item.version} · 담당 ${JSON.stringify(item.owner ?? '-').slice(1, -1)} · ${item.title.replace(/\s+/g, ' ').slice(0, 40)}`).join(' / ')}`);
245
289
  if (!options.allowDuplicateId) throw new CliUserError(`다른 판에 이미 있는 칸: ${displayedId}`, '--allow-duplicate-id 로 허용');
246
290
  }
291
+ assertPredecessorsExist(input.predecessors, data, otherItems);
247
292
  const by = process.env.ELANOUS_TRACK || 'cli';
248
293
  const at = new Date().toISOString();
249
- const item: ChecklistItem = { id: input.id, title: input.title, status: 'yellow', ...(input.owner !== undefined ? { owner: input.owner } : {}), ...(input.kind !== undefined ? { kind: input.kind } : {}), ...(input.priority !== undefined ? { priority: input.priority } : {}), ...(input.predecessors !== undefined ? { predecessors: input.predecessors } : {}), ...(input.deadlineVersion !== undefined ? { deadlineVersion: input.deadlineVersion } : {}), ...(input.ceoMinutes !== undefined ? { ceoMinutes: input.ceoMinutes } : {}), ...(input.ceoDate !== undefined ? { ceoDate: input.ceoDate } : {}), ...(input.accelerator === true ? { accelerator: true as const } : {}), ...(refs ? { refs } : {}), updatedAt: at, updatedBy: by };
294
+ const item: ChecklistItem = { id: input.id, title: input.title, status: 'yellow', ...(input.owner !== undefined ? { owner: input.owner } : {}), ...(input.kind !== undefined ? { kind: input.kind } : {}), ...(input.dispatchKind !== undefined ? { dispatchKind: input.dispatchKind } : {}), ...(input.priority !== undefined ? { priority: input.priority } : {}), ...(input.predecessors !== undefined ? { predecessors: input.predecessors } : {}), ...(input.deadlineVersion !== undefined ? { deadlineVersion: input.deadlineVersion } : {}), ...(input.ceoMinutes !== undefined ? { ceoMinutes: input.ceoMinutes } : {}), ...(input.ceoDate !== undefined ? { ceoDate: input.ceoDate } : {}), ...(input.accelerator === true ? { accelerator: true as const } : {}), ...(refs ? { refs } : {}), updatedAt: at, updatedBy: by };
250
295
  data.items.push(item);
251
296
  change(data, item.id, 'add', null, item, by, at);
252
297
  return true;
253
298
  });
254
299
  }
255
300
 
256
- export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
257
- return mutate(v, (data) => {
301
+ export function setItem(v: string, id: string, patch: { status?: ChecklistStatus; evidence?: string; refs?: string[]; owner?: string; disposition?: ChecklistDisposition; kind?: ChecklistKind; dispatchKind?: ChecklistDispatchKind; priority?: ChecklistItem['priority']; predecessors?: string[]; deadlineVersion?: string; ceoMinutes?: number; ceoDate?: string; accelerator?: boolean | null }, by: string): Checklist {
302
+ return mutate(v, (data, otherItems) => {
258
303
  const item = data.items.find((i) => i.id === id);
259
304
  if (!item) throw new CliUserError(`없는 칸: ${id}`, 'list 로 칸 목록을 본다');
260
305
  if (patch.status !== undefined && !['green', 'yellow', 'red', 'done'].includes(patch.status)) throw new CliUserError(`잘못된 상태: ${patch.status}`);
261
306
  if (patch.disposition !== undefined && !['move', 'known-issue', 'block'].includes(patch.disposition)) throw new CliUserError(`잘못된 처분: ${patch.disposition}`);
262
307
  if (patch.kind !== undefined && !CHECKLIST_KINDS.includes(patch.kind)) throw new CliUserError(`잘못된 종류: ${patch.kind}`, 'screen|postpub');
308
+ if (patch.dispatchKind !== undefined && !CHECKLIST_DISPATCH_KINDS.includes(patch.dispatchKind)) throw new CliUserError(`잘못된 발사 종류: ${patch.dispatchKind}`, 'code|ops|measure|decision|umbrella');
263
309
  if (patch.priority !== undefined && !['P0', 'P1', 'P2'].includes(patch.priority)) throw new CliUserError(`잘못된 우선순위: ${patch.priority}`);
264
310
  if (patch.predecessors !== undefined && (!Array.isArray(patch.predecessors) || patch.predecessors.some((p) => typeof p !== 'string' || !p.trim() || p === id))) throw new CliUserError('잘못된 선행 칸');
311
+ assertPredecessorsExist(patch.predecessors, data, otherItems);
265
312
  if (patch.deadlineVersion !== undefined) store.validateVersion(patch.deadlineVersion);
266
313
  if (patch.accelerator !== undefined && patch.accelerator !== true && patch.accelerator !== null) throw new CliUserError('가속 등급은 true(부여) 또는 null(해제)이다');
267
314
  validateCeoLoad(patch);
@@ -273,7 +320,7 @@ export function setItem(v: string, id: string, patch: { status?: ChecklistStatus
273
320
  throw new CliUserError(`지금 주인: ${item.owner} — --force 로만 바꾼다`, 'release checklist claim <id> --by <자리> --force');
274
321
  }
275
322
  }
276
- const fields = (['evidence', 'owner', 'status', 'disposition', 'kind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
323
+ const fields = (['evidence', 'owner', 'status', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const).filter((field) => patch[field] !== undefined && JSON.stringify(patch[field]) !== JSON.stringify(item[field] ?? null));
277
324
  if (fields.length === 0) return false;
278
325
  const at = new Date().toISOString();
279
326
  for (const field of fields) {
@@ -36,7 +36,7 @@ const walWait = new Int32Array(new SharedArrayBuffer(4));
36
36
  const SCHEMA_COLUMNS: Record<string, readonly string[]> = {
37
37
  imported_versions: ['json_hash', 'imported_at'],
38
38
  events: ['reason', 'generation'],
39
- assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs'],
39
+ assignments: ['priority', 'predecessors', 'deadline_version', 'ceo_minutes', 'ceo_date', 'accelerator', 'refs', 'dispatch_kind'],
40
40
  release_schedules: ['freeze_from', 'freeze_until', 'publish_at'],
41
41
  };
42
42
  function schemaCurrent(db: Database): boolean {
@@ -81,7 +81,7 @@ function open(root = releaseLedgerRoot()): Database {
81
81
  if (!eventColumns.some((column) => column.name === 'generation')) db.exec('ALTER TABLE events ADD COLUMN generation INTEGER');
82
82
  db.exec('CREATE TABLE IF NOT EXISTS release_schedules (version TEXT PRIMARY KEY, cut_at TEXT NOT NULL, land_by TEXT, updated_at TEXT NOT NULL, updated_by TEXT NOT NULL)');
83
83
  const assignmentColumns = db.query('PRAGMA table_info(assignments)').all() as Array<{ name: string }>;
84
- for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT']] as const) {
84
+ for (const [name, sql] of [['priority', 'TEXT'], ['predecessors', 'TEXT'], ['deadline_version', 'TEXT'], ['ceo_minutes', 'INTEGER'], ['ceo_date', 'TEXT'], ['accelerator', 'INTEGER'], ['refs', 'TEXT'], ['dispatch_kind', 'TEXT']] as const) {
85
85
  if (!assignmentColumns.some((column) => column.name === name)) db.exec(`ALTER TABLE assignments ADD COLUMN ${name} ${sql}`);
86
86
  }
87
87
  const scheduleColumns = db.query('PRAGMA table_info(release_schedules)').all() as Array<{ name: string }>;
@@ -178,12 +178,13 @@ function evidenceRefs(db: Database, version: string, id: string): string[] {
178
178
  return (db.query('SELECT ref FROM evidence WHERE feature_id = ? AND version = ? ORDER BY rowid').all(id, version) as Array<{ ref: string }>).map((row) => row.ref);
179
179
  }
180
180
  function items(db: Database, version: string): ChecklistItem[] {
181
- const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.updated_at, a.updated_by
181
+ const rows = db.query(`SELECT f.id, COALESCE(a.title_override, f.title) AS title, a.owner, a.kind, a.dispatch_kind, a.priority, a.predecessors, a.deadline_version, a.ceo_minutes, a.ceo_date, a.accelerator, a.refs, a.status, a.disposition, a.evidence, a.updated_at, a.updated_by
182
182
  FROM assignments a JOIN features f ON f.id = a.feature_id WHERE a.version = ? ORDER BY a.rowid`).all(version) as Array<Record<string, string | number | null>>;
183
183
  return rows.map((r) => {
184
184
  const evidence = [r.evidence, ...evidenceRefs(db, version, r.id as string)].filter((value) => value !== null).join('\n');
185
185
  return { id: r.id as string, title: r.title as string, status: r.status as ChecklistItem['status'],
186
186
  ...(r.owner !== null ? { owner: r.owner as string } : {}), ...(r.kind !== null ? { kind: r.kind as ChecklistItem['kind'] } : {}),
187
+ ...(r.dispatch_kind !== null ? { dispatchKind: r.dispatch_kind as ChecklistItem['dispatchKind'] } : {}),
187
188
  ...(r.priority !== null ? { priority: r.priority as ChecklistItem['priority'] } : {}), ...(r.predecessors !== null ? { predecessors: JSON.parse(r.predecessors as string) as string[] } : {}),
188
189
  ...(r.deadline_version !== null ? { deadlineVersion: r.deadline_version as string } : {}),
189
190
  ...(r.ceo_minutes !== null ? { ceoMinutes: r.ceo_minutes as number } : {}), ...(r.ceo_date !== null ? { ceoDate: r.ceo_date as string } : {}),
@@ -202,9 +203,9 @@ function putItem(db: Database, version: string, item: ChecklistItem): void {
202
203
  if (!feature) db.query('INSERT INTO features (id, title, owner, kind, created_at) VALUES (?, ?, ?, ?, ?)').run(item.id, item.title, item.owner ?? null, item.kind ?? null, item.updatedAt);
203
204
  // features.owner/kind follow the latest assignment so details() and the checklist never disagree after a set.
204
205
  else if (item.owner !== undefined || item.kind !== undefined) db.query('UPDATE features SET owner = COALESCE(?, owner), kind = COALESCE(?, kind) WHERE id = ?').run(item.owner ?? null, item.kind ?? null, item.id);
205
- db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
206
- ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
207
- .run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
206
+ db.query(`INSERT INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
207
+ ON CONFLICT(feature_id, version) DO UPDATE SET status=excluded.status, disposition=excluded.disposition, evidence=excluded.evidence, owner=excluded.owner, kind=excluded.kind, dispatch_kind=excluded.dispatch_kind, priority=excluded.priority, predecessors=excluded.predecessors, deadline_version=excluded.deadline_version, ceo_minutes=excluded.ceo_minutes, ceo_date=excluded.ceo_date, accelerator=excluded.accelerator, refs=excluded.refs, updated_at=excluded.updated_at, updated_by=excluded.updated_by`)
208
+ .run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, feature && feature.title !== item.title ? item.title : null, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
208
209
  }
209
210
  function jsonHash(contents: string | Buffer): string { return createHash('sha256').update(contents).digest('hex'); }
210
211
 
@@ -245,8 +246,8 @@ function importOnDb(db: Database, version: string): boolean {
245
246
  // Keep a legacy per-version title until an explicit retitle unifies the feature identity.
246
247
  if (!existing) putItem(db, version, item);
247
248
  else {
248
- db.query('INSERT OR IGNORE INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
249
- .run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, item.title === existing.title ? null : item.title, item.owner ?? null, item.kind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
249
+ db.query('INSERT OR IGNORE INTO assignments (feature_id, version, status, disposition, evidence, title_override, owner, kind, dispatch_kind, priority, predecessors, deadline_version, ceo_minutes, ceo_date, accelerator, refs, updated_at, updated_by) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)')
250
+ .run(item.id, version, item.status, item.disposition ?? null, item.evidence ?? null, item.title === existing.title ? null : item.title, item.owner ?? null, item.kind ?? null, item.dispatchKind ?? null, item.priority ?? null, item.predecessors ? JSON.stringify(item.predecessors) : null, item.deadlineVersion ?? null, item.ceoMinutes ?? null, item.ceoDate ?? null, item.accelerator === true ? 1 : null, item.refs?.length ? JSON.stringify(item.refs) : null, item.updatedAt, item.updatedBy);
250
251
  }
251
252
  }
252
253
  for (const entry of data.history) record(db, version, entry);
@@ -273,7 +274,7 @@ function importOnDb(db: Database, version: string): boolean {
273
274
  record(db, version, { at: new Date().toISOString(), by: item.updatedBy, id: item.id, field: 'reimport', from: null, to: item, released: data.released, dev: data.dev });
274
275
  continue;
275
276
  }
276
- const fields = ['title', 'status', 'evidence', 'owner', 'disposition', 'kind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
277
+ const fields = ['title', 'status', 'evidence', 'owner', 'disposition', 'kind', 'dispatchKind', 'priority', 'predecessors', 'deadlineVersion', 'ceoMinutes', 'ceoDate', 'accelerator', 'refs'] as const;
277
278
  const baseEvidence = (db.query('SELECT evidence FROM assignments WHERE feature_id = ? AND version = ?').get(item.id, version) as { evidence: string | null }).evidence ?? undefined;
278
279
  const preserveRefs = item.evidence === baseEvidence || item.evidence === current.evidence;
279
280
  const differs = fields.some((field) => field === 'evidence'
@@ -21,6 +21,8 @@ export interface GateShard {
21
21
  waitReason?: string;
22
22
  /** 계획 분 — 남은 시간 추정의 재료. */
23
23
  plannedMin?: number;
24
+ /** GATE-MULTI-HOST — 이 조각(가장 최근 시도)이 놓인 풀 멤버(kubectl 컨텍스트). 놓이기 전엔 없다. */
25
+ host?: string;
24
26
  }
25
27
 
26
28
  /** 게이트 노드의 판정 결과 — 끝난 조각의 rc≠0 을 «새로 생긴 실패»와 «기존 실패»로 가른 수. */
@@ -58,11 +60,13 @@ function shardOf(value: unknown): GateShard | null {
58
60
  const rc = num(raw.rc);
59
61
  const waitReason = str(raw.waitReason);
60
62
  const plannedMin = num(raw.plannedMin);
63
+ const host = str(raw.host, 120);
61
64
  return {
62
65
  id, state,
63
66
  ...(startedAt ? { startedAt } : {}), ...(endedAt ? { endedAt } : {}),
64
67
  ...(installSec !== undefined ? { installSec } : {}), ...(rc !== undefined ? { rc } : {}),
65
68
  ...(waitReason ? { waitReason } : {}), ...(plannedMin !== undefined ? { plannedMin } : {}),
69
+ ...(host ? { host } : {}),
66
70
  };
67
71
  }
68
72
 
@@ -3,7 +3,8 @@
3
3
  * gate host (GATE-REMOTE). Read-only for the release ledger: it reads the previous published version and never writes.
4
4
  * It does not touch the landing freeze or launch Pods. */
5
5
  import { spawnSync } from 'node:child_process';
6
- import { existsSync, readFileSync } from 'node:fs';
6
+ import { existsSync, mkdtempSync, readFileSync, rmSync } from 'node:fs';
7
+ import { tmpdir } from 'node:os';
7
8
  import { join } from 'node:path';
8
9
  import { debug } from '../debug/log.js';
9
10
  import { runSelfGateCli, type SelfGateCliOptions, type SelfGateCliResult } from '../self-implement/gate-cli.js';
@@ -14,9 +15,14 @@ import { baseVersion, isReleaseVersion } from '../../scripts/release-loop/releas
14
15
  export const LIGHT_RC_ALWAYS_FILE = 'release/light-rc-always.txt';
15
16
  export const LIGHT_RC_DEFAULT_SHARDS = 4;
16
17
  export const LIGHT_RC_NO_PREVIOUS_CUT = '직전 판 컷을 못 찾았다 — --base 로 준다';
18
+ /** RELEASE-DAILY-LIGHT-RC ① — what light-rc measures by default: main as it is on origin, not the tree it started in
19
+ * (10-12: the seat tree measured changed=2, a main worktree 52). */
20
+ export const LIGHT_RC_DEFAULT_HEAD = 'origin/main';
17
21
 
18
22
  export interface LightRcOptions {
19
23
  base?: string;
24
+ /** Commit to measure (RELEASE-DAILY-LIGHT-RC ①). Absent = `origin/main` after `git fetch origin main`. */
25
+ head?: string;
20
26
  /** Gate host; absent = config gateRemote.host (the dispatch's own default). */
21
27
  remote?: string;
22
28
  /** Run on this machine (the remote child is re-invoked with it). */
@@ -30,6 +36,12 @@ export interface LightRcOptions {
30
36
  export interface LightRcResult {
31
37
  version: string;
32
38
  base: string;
39
+ /** The commit the gate measured (RELEASE-DAILY-LIGHT-RC ①) — origin/main unless --head was given. */
40
+ measuredCommit: string;
41
+ /** HEAD of the tree light-rc was started from; differs from measuredCommit when it ran from a seat/work tree. */
42
+ worktreeHead: string | null;
43
+ /** RELEASE-DAILY-LIGHT-RC ② — tests added because they import a changed source; null = not reported. */
44
+ importerTests: number | null;
33
45
  /** New failures vs. the base; null = the gate produced no measurement (never read as green). */
34
46
  introduced: number | null;
35
47
  preexisting: number | null;
@@ -56,6 +68,9 @@ export interface LightRcDeps {
56
68
  dispatch?: (opts: DispatchOptions, deps?: DispatchDeps) => Promise<number>;
57
69
  /** Extra dispatch deps (runner · settings) — tests drive the real dispatch with a fake host. */
58
70
  dispatchDeps?: Omit<DispatchDeps, 'write'>;
71
+ /** Detached checkout of `sha` for a local run whose tree is not at the measured commit (default: git worktree add
72
+ * --detach in a temp dir ⊕ bun install); `cleanup` removes it. */
73
+ checkout?: (sha: string, repo: string, log: (line: string) => void) => { dir: string; cleanup: () => void };
59
74
  }
60
75
 
61
76
  /** Shown when the gate ran remotely but the host name did not come back. */
@@ -87,6 +102,51 @@ export function previousCutBase(version: string, deps: LightRcDeps & { cwd: stri
87
102
  return sha;
88
103
  }
89
104
 
105
+ const SHA_RE = /^[0-9a-f]{40}$/;
106
+
107
+ /** RELEASE-DAILY-LIGHT-RC ① — the commit to measure. Default: fetch origin main, then origin/main (a failed fetch is
108
+ * said, and the local origin/main is measured — never silently the tree's HEAD). */
109
+ export function resolveMeasuredCommit(cwd: string, head: string | undefined, deps: LightRcDeps, log: (line: string) => void): { measuredCommit: string; worktreeHead: string | null } {
110
+ const git = deps.git ?? defaultGit;
111
+ const ref = head ?? LIGHT_RC_DEFAULT_HEAD;
112
+ if (head === undefined) {
113
+ const fetch = git(['fetch', '--quiet', 'origin', 'main'], cwd);
114
+ if (fetch.rc !== 0) {
115
+ log(`⚠️ light-rc: git fetch origin main rc=${fetch.rc} — measuring the local ${LIGHT_RC_DEFAULT_HEAD} (may be stale)`);
116
+ debug.log('release.light-rc', 'fetch-failed', { rc: fetch.rc });
117
+ }
118
+ }
119
+ const parsed = git(['rev-parse', '--verify', '--quiet', `${ref}^{commit}`], cwd);
120
+ const measuredCommit = parsed.stdout.trim();
121
+ if (parsed.rc !== 0 || !SHA_RE.test(measuredCommit)) throw new Error(`release light-rc: cannot resolve ${ref} to a commit (rc=${parsed.rc})`);
122
+ const top = git(['rev-parse', 'HEAD'], cwd);
123
+ const worktreeHead = top.rc === 0 && SHA_RE.test(top.stdout.trim()) ? top.stdout.trim() : null;
124
+ if (worktreeHead !== measuredCommit) {
125
+ log(`ⓘ light-rc measures ${measuredCommit.slice(0, 12)} (${ref}) — this tree's HEAD ${worktreeHead?.slice(0, 12) ?? '(unresolved)'} is not what is measured`);
126
+ debug.log('release.light-rc', 'measured-commit-differs', { ref, measuredCommit, worktreeHead, cwd });
127
+ }
128
+ return { measuredCommit, worktreeHead };
129
+ }
130
+
131
+ function defaultCheckout(sha: string, repo: string, log: (line: string) => void): { dir: string; cleanup: () => void } {
132
+ const dir = mkdtempSync(join(tmpdir(), 'elanous-light-rc-'));
133
+ const run = (cmd: string, args: string[], cwd: string) => spawnSync(cmd, args, { cwd, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'] });
134
+ const cleanup = () => {
135
+ run('git', ['worktree', 'remove', '--force', dir], repo);
136
+ rmSync(dir, { recursive: true, force: true });
137
+ run('git', ['worktree', 'prune'], repo);
138
+ };
139
+ const add = run('git', ['worktree', 'add', '--detach', dir, sha], repo);
140
+ if (add.status !== 0) { cleanup(); throw new Error(`release light-rc: git worktree add ${sha.slice(0, 12)} failed: ${(add.stderr ?? '').trim()}`); }
141
+ log(`light-rc: detached checkout of ${sha.slice(0, 12)} at ${dir} — installing dependencies`);
142
+ for (const sub of ['.', 'apps/pwa']) {
143
+ if (!existsSync(join(dir, sub, 'package.json'))) continue;
144
+ const install = run('bun', ['install', '--frozen-lockfile'], join(dir, sub));
145
+ if (install.status !== 0) { cleanup(); throw new Error(`release light-rc: bun install (${sub}) failed in the checkout: ${(install.stderr ?? '').trim().slice(-400)}`); }
146
+ }
147
+ return { dir, cleanup };
148
+ }
149
+
90
150
  function repoRoot(deps: LightRcDeps): string {
91
151
  if (deps.cwd) return deps.cwd;
92
152
  const top = defaultGit(['rev-parse', '--show-toplevel'], process.cwd());
@@ -110,23 +170,32 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
110
170
  if (opts.remote !== undefined && !isValidGateHost(opts.remote)) throw new Error(`invalid --remote host: ${opts.remote}`);
111
171
  const log = opts.log ?? ((line: string) => process.stderr.write(`${line}\n`));
112
172
  const cwd = repoRoot(deps);
173
+ const { measuredCommit, worktreeHead } = resolveMeasuredCommit(cwd, opts.head, deps, log);
113
174
  const base = opts.base ?? previousCutBase(version, { ...deps, cwd, ledgerRoot: opts.ledgerRoot });
114
- const listPath = join(cwd, LIGHT_RC_ALWAYS_FILE);
115
- const listText = (deps.readFile ?? ((path: string) => existsSync(path) ? readFileSync(path, 'utf8') : undefined))(listPath);
116
- if (listText === undefined) throw new Error(`release light-rc: ${LIGHT_RC_ALWAYS_FILE} not found`);
117
- const alwaysInclude = parseAlwaysIncludeList(listText);
175
+ const readList = (dir: string) => {
176
+ const text = (deps.readFile ?? ((path: string) => existsSync(path) ? readFileSync(path, 'utf8') : undefined))(join(dir, LIGHT_RC_ALWAYS_FILE));
177
+ if (text === undefined) throw new Error(`release light-rc: ${LIGHT_RC_ALWAYS_FILE} not found`);
178
+ return parseAlwaysIncludeList(text);
179
+ };
180
+ let alwaysInclude = readList(cwd);
118
181
 
119
182
  let local: SelfGateCliResult | undefined;
120
183
  const runLocal = () => {
121
- local = (deps.runGate ?? runSelfGateCli)(cwd, { base, shards, alwaysInclude });
184
+ // ① The gate scopes by its tree's HEAD — so a tree that is not at the measured commit runs in a detached checkout of it.
185
+ const checkout = worktreeHead === measuredCommit ? undefined : (deps.checkout ?? defaultCheckout)(measuredCommit, cwd, log);
186
+ try {
187
+ const dir = checkout?.dir ?? cwd;
188
+ if (checkout) alwaysInclude = readList(dir);
189
+ local = (deps.runGate ?? runSelfGateCli)(dir, { base, shards, alwaysInclude, includeImporterTests: true });
190
+ } finally { checkout?.cleanup(); }
122
191
  for (const line of local.lines) log(line);
123
192
  return local.exitCode;
124
193
  };
125
194
  const captured: Buffer[] = [];
126
195
  const rc = await (deps.dispatch ?? dispatchHeavyCheck)({
127
- tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true,
196
+ tool: 'self-gate', repo: cwd, installPwa: true, refs: [base], json: true, commit: measuredCommit,
128
197
  // The host re-runs this command with --local (and ELANOUS_GATE_REMOTE_CHILD=1), so it never recurses.
129
- remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--shards', String(shards), '--local', '--json'],
198
+ remoteArgv: (sha) => ['bun', 'bin/elanous.mjs', 'release', 'light-rc', '--version', version, '--base', sha(base), '--head', measuredCommit, '--shards', String(shards), '--local', '--json'],
130
199
  flags: { remote: opts.local ? undefined : opts.remote ?? true, local: !!opts.local },
131
200
  runLocal,
132
201
  }, {
@@ -140,7 +209,8 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
140
209
  let result: LightRcResult;
141
210
  if (local) {
142
211
  result = {
143
- version, base,
212
+ version, base, measuredCommit, worktreeHead,
213
+ importerTests: local.importerTestsAdded ? local.importerTestsAdded.length : null,
144
214
  introduced: local.baseline?.introduced ?? null,
145
215
  preexisting: local.baseline?.preexisting ?? null,
146
216
  unclassified: local.baseline ? local.baseline.unknown + local.baseline.preconditionUnmet : null,
@@ -154,7 +224,8 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
154
224
  if (!remote) throw new Error(`release light-rc: remote gate returned no result (rc=${rc})`);
155
225
  const host = (remote as { host?: unknown }).host;
156
226
  result = {
157
- version, base,
227
+ version, base, measuredCommit, worktreeHead,
228
+ importerTests: typeof remote.importerTests === 'number' ? remote.importerTests : null,
158
229
  introduced: typeof remote.introduced === 'number' ? remote.introduced : null,
159
230
  preexisting: typeof remote.preexisting === 'number' ? remote.preexisting : null,
160
231
  unclassified: typeof remote.unclassified === 'number' ? remote.unclassified : null,
@@ -170,14 +241,14 @@ export async function runLightRc(version: string, opts: LightRcOptions = {}, dep
170
241
  // Unmeasured (null) or unclassified failures are never green; policy-gate findings in the gate output are reported
171
242
  // (gate rc), not a regression.
172
243
  result.ok = result.introduced === 0 && result.unclassified === 0;
173
- debug.log('release.light-rc', 'done', { version, base, introduced: result.introduced, preexisting: result.preexisting, unclassified: result.unclassified, shards, remote: result.remote, unmeasured: result.unmeasured });
244
+ debug.log('release.light-rc', 'done', { version, base, measuredCommit, worktreeHead, importerTests: result.importerTests, introduced: result.introduced, preexisting: result.preexisting, unclassified: result.unclassified, shards, remote: result.remote, unmeasured: result.unmeasured });
174
245
  return result;
175
246
  }
176
247
 
177
248
  export function formatLightRc(result: LightRcResult): string[] {
178
249
  return [
179
- `${result.ok ? '✅' : '⛔'} light-rc ${result.version} · base ${result.base.slice(0, 12)} · ${result.remote ? `host ${result.remote}` : 'local'} · shards ${result.shards}`,
180
- ` introduced ${result.introduced ?? '못 쟀다'} · preexisting ${result.preexisting ?? '못 쟀다'} · unclassified ${result.unclassified ?? '못 쟀다'} · always-include ${result.alwaysInclude}${result.alwaysIncludeMissing.length ? ` (missing: ${result.alwaysIncludeMissing.join(', ')})` : ''} · gate rc ${result.gateExitCode}`,
250
+ `${result.ok ? '✅' : '⛔'} light-rc ${result.version} · base ${result.base.slice(0, 12)} · measured ${result.measuredCommit.slice(0, 12)} · ${result.remote ? `host ${result.remote}` : 'local'} · shards ${result.shards}`,
251
+ ` introduced ${result.introduced ?? '못 쟀다'} · preexisting ${result.preexisting ?? '못 쟀다'} · unclassified ${result.unclassified ?? '못 쟀다'} · importer tests ${result.importerTests ?? '못 쟀다'} · always-include ${result.alwaysInclude}${result.alwaysIncludeMissing.length ? ` (missing: ${result.alwaysIncludeMissing.join(', ')})` : ''} · gate rc ${result.gateExitCode}`,
181
252
  ...(result.unmeasured !== null ? [` shards: unmeasured (${result.unmeasured})`] : []),
182
253
  ];
183
254
  }
@@ -38,7 +38,18 @@ export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: st
38
38
  // The audit matcher owns explicit-label and evidence decisions on both PR surfaces.
39
39
  // The shared matcher only accepts a whole `칸: X` line. A designated label in the body (`칸: X — …` at a line head)
40
40
  // or in the title is restated as such a line; prose mentions are not (the audit command's contract is unchanged).
41
- const designated = [...goalCells(pr.body ?? ''), ...titleCells(pr.title)];
41
+ // Goal-file ids join that set: `칸: X` lines plus `- 칸 id: A · B` declarations (not-declared excluded).
42
+ const fromBody = goalCells(pr.body ?? '');
43
+ const fromTitle = titleCells(pr.title);
44
+ const fromGoal = goal ? goalFileCells(goal) : new Set<string>();
45
+ const designated = [...new Set([...fromBody, ...fromTitle, ...fromGoal])];
46
+ for (const id of designated) {
47
+ log('release.checklist', 'merged-pr-cell-source', {
48
+ pr: number,
49
+ id,
50
+ source: fromBody.has(id) ? 'body' : fromTitle.has(id) ? 'title' : 'goal',
51
+ });
52
+ }
42
53
  // Only the restated labels go to the matcher — raw body text (quotes, fences, indented code) never does.
43
54
  const prForMatch = { ...merged, title: '', body: designated.map((id) => `칸: ${id}`).join('\n') };
44
55
  const matches = [...new Set(versions)].flatMap((version) => {
@@ -86,10 +97,14 @@ export function syncMergedPrChecklist(number: number, cwd: string, goalFile?: st
86
97
  for (const id of missing) log('release.checklist', 'merged-pr-cell-not-found', { pr: number, id });
87
98
  }
88
99
 
89
- const LABEL_IDS = '([A-Za-z0-9_-]+(?:[ \\t]*,[ \\t]*[A-Za-z0-9_-]+)*)';
100
+ const LABEL_IDS = '([A-Za-z0-9_-]+(?:[ \\t]*(?:,|·)[ \\t]*[A-Za-z0-9_-]+)*)';
90
101
  const LABEL_END = '(?=[ \\t]*$|[ \\t]+[—–·(-])';
91
102
  const DESIGNATION = new RegExp(`^ {0,3}(?:#{1,6}[ \\t]+|[-*][ \\t]+)?칸[ \\t]*:[ \\t]*${LABEL_IDS}${LABEL_END}`);
92
103
 
104
+ function idsInLabel(captured: string): string[] {
105
+ return captured.split(/[,·]/).map((id) => id.trim()).filter(Boolean);
106
+ }
107
+
93
108
  /** Lines of a Markdown document outside fenced code (closed only by the same marker, at least as long), 4-space
94
109
  * indented code and `>` quotes — the only lines that may designate a cell or declare completion. */
95
110
  function proseLines(text: string): string[] {
@@ -109,13 +124,28 @@ function proseLines(text: string): string[] {
109
124
  return lines;
110
125
  }
111
126
 
112
- /** Cell ids a document designates on a line head: `칸: X[, Y]`, optionally after a heading or list marker. */
127
+ /** Cell ids a document designates on a line head: `칸: X[, Y]` or `칸: X · Y`, optionally after a heading or list marker. */
113
128
  export function goalCells(goal: string): Set<string> {
114
129
  const ids = new Set<string>();
115
130
  for (const line of proseLines(goal)) {
116
131
  const label = DESIGNATION.exec(line);
117
132
  if (!label) continue;
118
- for (const id of label[1]!.split(',')) ids.add(id.trim());
133
+ for (const id of idsInLabel(label[1]!)) ids.add(id);
134
+ }
135
+ return ids;
136
+ }
137
+
138
+ /** Goal-file designations: `칸:` lines plus `- 칸 id: A · B` declarations (same shape as goalChecklistIds). */
139
+ function goalFileCells(goal: string): Set<string> {
140
+ const ids = goalCells(goal);
141
+ for (const line of proseLines(goal)) {
142
+ if (!line.startsWith('- 칸 id: ')) continue;
143
+ const declared = line.slice('- 칸 id: '.length).trim();
144
+ if (!declared || declared === 'not declared') continue;
145
+ for (const id of declared.split(' · ')) {
146
+ const trimmed = id.trim();
147
+ if (trimmed) ids.add(trimmed);
148
+ }
119
149
  }
120
150
  return ids;
121
151
  }
@@ -129,7 +159,7 @@ export function declaresCompletion(goal: string): boolean {
129
159
  export function titleCells(title: string): Set<string> {
130
160
  const ids = new Set<string>();
131
161
  for (const label of title.matchAll(new RegExp(`(?<![A-Za-z0-9가-힣])칸[ \\t]*:[ \\t]*${LABEL_IDS}${LABEL_END}`, 'g'))) {
132
- for (const id of label[1]!.split(',')) ids.add(id.trim());
162
+ for (const id of idsInLabel(label[1]!)) ids.add(id);
133
163
  }
134
164
  return ids;
135
165
  }
@@ -290,7 +290,7 @@ export async function runRehearsalTick(opts: RehearsalOptions = {}, deps: Rehear
290
290
  stamp.sha = gitResult(git, ['rev-parse', 'HEAD'], checkout);
291
291
  if (!stamp.sha) throw new Error('git rev-parse HEAD returned no sha');
292
292
  const regressionFiles: string[] = [];
293
- const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, log: (line) => {
293
+ const result = await (deps.lightRc ?? ((version, cwd) => runLightRc(version, { ledgerRoot: root, head: stamp.sha, log: (line) => {
294
294
  for (const entry of line.split(/\r?\n/)) {
295
295
  const file = /^- introduced: (.+?)(?: > |$)/.exec(entry)?.[1];
296
296
  if (file && regressionFiles.length < 3) regressionFiles.push(file);