elanous 0.2.32 → 0.2.35

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 (753) 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/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 0368f25d-ad84af92fefee68f.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
  7. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 1530.0e612369b6fd7ea0.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
  9. package/apps/pwa/out/_next/static/chunks/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
  11. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
  12. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 2018.a741297bce759490.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
  23. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
  26. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
  31. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 3408.21d1570602f4b6c0.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 3677-4215f826f6aa68e5.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
  40. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
  42. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
  46. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
  49. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 4718-17d2af636796a330.js} +3 -3
  51. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
  61. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 5483-dd5d7697f6bdb106.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
  63. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
  67. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
  74. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
  75. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
  78. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
  80. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
  87. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
  88. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 7644.17e37ba6f1d4226e.js} +4 -4
  90. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
  100. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
  101. package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
  104. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 8637.47f5b35afcae5e6b.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9214.63a510d39178e997.js} +2 -2
  111. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
  112. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 9512.5a76207a730e0491.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 9952.5daf5f94063a2b3e.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/{page-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-dc0a532f5b9196ec.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
  178. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/bin/elanous.mjs +10 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/README.md +5 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +76 -5
  285. package/graphs/document-loop.yaml +71 -4
  286. package/graphs/implement-loop.yaml +59 -4
  287. package/graphs/journey/SCENARIOS.md +33 -0
  288. package/graphs/journey/recipes.yaml +1 -0
  289. package/graphs/journey/ta-journey.yaml +94 -0
  290. package/graphs/journey/units/author/author.yaml +20 -0
  291. package/graphs/journey/units/author/recipes.yaml +2 -0
  292. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  293. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  294. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  295. package/graphs/journey/units/green/green.yaml +20 -0
  296. package/graphs/journey/units/green/recipes.yaml +2 -0
  297. package/graphs/journey/units/pr/pr.yaml +20 -0
  298. package/graphs/journey/units/pr/recipes.yaml +2 -0
  299. package/graphs/journey/units/remember/recipes.yaml +2 -0
  300. package/graphs/journey/units/remember/remember.yaml +20 -0
  301. package/graphs/operate-loop.yaml +71 -4
  302. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  303. package/graphs/release-rehearsal/recipes.yaml +1 -1
  304. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  305. package/graphs/research-loop.yaml +159 -4
  306. package/graphs/test-diet/test-diet.yaml +3 -0
  307. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  308. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  309. package/graphs/units/entry/entry.yaml +50 -0
  310. package/graphs/units/entry/recipes.yaml +14 -0
  311. package/graphs/units/harvest/harvest.yaml +25 -0
  312. package/graphs/units/harvest/recipes.yaml +4 -0
  313. package/graphs/units/land/land.yaml +45 -0
  314. package/graphs/units/land/recipes.yaml +3 -0
  315. package/graphs/units/recipes.yaml +7 -0
  316. package/graphs/units/recover.yaml +39 -0
  317. package/graphs/units/reflect/recipes.yaml +3 -0
  318. package/graphs/units/reflect/reflect.yaml +15 -0
  319. package/graphs/units/task-agent-recover-review.yaml +17 -0
  320. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  321. package/graphs/units/verbs/make-doc.yaml +34 -0
  322. package/graphs/units/verbs/recipes.yaml +33 -0
  323. package/graphs/units/verbs/verify.yaml +55 -0
  324. package/graphs/work/recipes.yaml +2 -0
  325. package/graphs/work/research-report.yaml +28 -0
  326. package/package.json +1 -1
  327. package/scripts/ci-typecheck-changed.ts +69 -16
  328. package/scripts/coord-role-pack.ts +19 -6
  329. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  330. package/scripts/graph-harvest-unit.ts +22 -0
  331. package/scripts/graph-units/journey-stub.ts +6 -0
  332. package/scripts/graph-units/land-enqueue.ts +78 -0
  333. package/scripts/graph-units/recover-plan.ts +15 -0
  334. package/scripts/graph-units/reflect-node.ts +88 -0
  335. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  336. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  337. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  338. package/scripts/graph-units/verbs-envelope.ts +139 -0
  339. package/scripts/hq/standby-snapshot.ts +30 -0
  340. package/scripts/public-export.ts +43 -1
  341. package/scripts/ratchets/train-side-invariants.sh +45 -0
  342. package/scripts/release-loop/auto-approve-node.ts +30 -16
  343. package/scripts/release-loop/docs-land-node.ts +21 -5
  344. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  345. package/scripts/release-loop/gate-closure.ts +5 -1
  346. package/scripts/release-loop/gate-diff.ts +1 -1
  347. package/scripts/release-loop/gate-node.ts +675 -49
  348. package/scripts/release-loop/gate-partial.ts +68 -14
  349. package/scripts/release-loop/gate-radius-live.ts +177 -0
  350. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  351. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  352. package/scripts/release-loop/gate-triage-node.ts +5 -2
  353. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  354. package/scripts/release-loop/known-issues-node.ts +77 -8
  355. package/scripts/release-loop/node-verdict.ts +12 -1
  356. package/scripts/release-loop/npm-publish-node.ts +66 -12
  357. package/scripts/release-loop/preflight.ts +93 -7
  358. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  359. package/scripts/release-loop/publish-node.ts +60 -9
  360. package/scripts/release-loop/pwa-remote.ts +166 -0
  361. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  362. package/scripts/release-loop/resume-cap.ts +56 -0
  363. package/scripts/release-loop/resume-release.ts +155 -19
  364. package/scripts/release-loop/resume.ts +24 -1
  365. package/scripts/release-loop/tui-sim-node.ts +8 -2
  366. package/scripts/release-loop/unattended-release.ts +10 -2
  367. package/scripts/test-diet/lib.ts +6 -1
  368. package/scripts/test-diet/node.ts +194 -13
  369. package/scripts/ux-sim.ts +39 -0
  370. package/src/acp/core-turn-bridge.ts +20 -5
  371. package/src/acp/reasoning-thought-buffer.ts +45 -0
  372. package/src/agent/self-ambient-cache.ts +8 -0
  373. package/src/agent-substrate/acp-reviewer.ts +90 -15
  374. package/src/agent-substrate/pr-reviewer.ts +17 -0
  375. package/src/agent-substrate/review-finding-key.ts +53 -0
  376. package/src/agent-substrate/self-review-cli.ts +188 -18
  377. package/src/ask-user-question/pending-questions.ts +1 -1
  378. package/src/autopilot/pr-manager.ts +393 -65
  379. package/src/budget/run-usage-rollup.ts +1 -0
  380. package/src/chat/index.ts +0 -2
  381. package/src/chat/pickers/modal-runtime.ts +10 -27
  382. package/src/chat/tool-render/dispatch.ts +62 -10
  383. package/src/cli/agent-cli.ts +13 -2
  384. package/src/cli/control-cli.ts +24 -7
  385. package/src/cli/doctor-cli.ts +4 -1
  386. package/src/cli/guardian-cli.ts +10 -0
  387. package/src/cli/light-entry-route.ts +75 -0
  388. package/src/cli/llm-detect-cli.ts +23 -1
  389. package/src/cli/pod-cli.ts +77 -3
  390. package/src/cli/pr-cli.ts +81 -14
  391. package/src/cli/pr-land-base-read.ts +2 -0
  392. package/src/cli/pr-land-overlap-evidence.ts +154 -16
  393. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  394. package/src/cli/pr-land-recovery.ts +64 -0
  395. package/src/cli/pty-takeover-cli.ts +6 -5
  396. package/src/cli/release-checklist-read-cli.ts +79 -0
  397. package/src/cli/release-cli.ts +189 -132
  398. package/src/cli/release-run-if-ready.ts +29 -28
  399. package/src/cli/release-single-flight.ts +178 -0
  400. package/src/cli/remote-resolve.ts +1 -1
  401. package/src/cli/root-tui-entry.ts +48 -0
  402. package/src/cli/seat-cli.ts +37 -0
  403. package/src/cli/setup-cli.ts +40 -1
  404. package/src/cli/sim-cli.ts +22 -0
  405. package/src/cli/tasks-cli.ts +667 -14
  406. package/src/cli/usage-cli.ts +13 -11
  407. package/src/clipboard/history.ts +179 -13
  408. package/src/config.ts +8 -1
  409. package/src/control/control-status.ts +8 -3
  410. package/src/control-plane/ledger.ts +5 -3
  411. package/src/control-plane/server.ts +5 -3
  412. package/src/core-turn/short-question.ts +5 -1
  413. package/src/dashboard/chat/acp-chat.ts +8 -0
  414. package/src/dashboard/index.ts +114 -77
  415. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  416. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  417. package/src/dashboard/input/seat-autowake.ts +56 -3
  418. package/src/dashboard/render/theme-resolver.ts +33 -4
  419. package/src/dashboard/seat-boot-preamble.ts +1 -1
  420. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  421. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  422. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  423. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  424. package/src/dashboard/turn-preamble.ts +47 -1
  425. package/src/dashboard/turn-stream-formatter.ts +34 -1
  426. package/src/dashboard/turn-stream-runtime.ts +2 -0
  427. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  428. package/src/domains/guardian-tick.ts +54 -2
  429. package/src/domains/outbound-alert.ts +3 -2
  430. package/src/domains/schedule-registry.ts +16 -2
  431. package/src/extractors.ts +3 -1
  432. package/src/git-fs/idle-refresh.ts +76 -0
  433. package/src/git-fs/index.ts +18 -7
  434. package/src/git-fs/retry.ts +4 -0
  435. package/src/git-fs/runner.ts +2 -0
  436. package/src/git-fs/worktree.ts +42 -4
  437. package/src/graph-kinds/registry.ts +2 -2
  438. package/src/graph-runner/runner.ts +267 -54
  439. package/src/grok/credential.ts +15 -3
  440. package/src/harness/harness-cli-command.ts +151 -38
  441. package/src/harness/harness-incidents.ts +37 -0
  442. package/src/harness/harness-pod-dispatch.ts +38 -1
  443. package/src/harness/harness-salvage-cli.ts +14 -2
  444. package/src/harness/launch-utterance-ledger.ts +208 -0
  445. package/src/impl-discipline/detector.ts +16 -4
  446. package/src/impl-discipline/system-prompt.ts +11 -0
  447. package/src/impl-discipline/types.ts +2 -2
  448. package/src/index.ts +683 -146
  449. package/src/intake-plane/already-built-hint.ts +91 -0
  450. package/src/intake-plane/requirement-funnel.ts +29 -1
  451. package/src/knowhow/pack.ts +199 -0
  452. package/src/light-cli.ts +111 -0
  453. package/src/llm/opengateway-models.ts +11 -0
  454. package/src/llm/provider-credentials.ts +14 -0
  455. package/src/llm/provider-detect.ts +8 -1
  456. package/src/llm/runtime-model-family.ts +2 -1
  457. package/src/llm.ts +268 -65
  458. package/src/loops/budget.ts +95 -0
  459. package/src/loops/msg-wake.ts +8 -2
  460. package/src/loops/orchestrator/traffic.ts +132 -1
  461. package/src/model-tier/llm-tier-map.ts +15 -1
  462. package/src/mss/logging/log-store.ts +4 -5
  463. package/src/native-tool-catalog.ts +15 -1
  464. package/src/nexus/api/graphs-api.ts +22 -3
  465. package/src/nexus/api/http-server.ts +1 -1
  466. package/src/nexus/api/loop-resources.ts +13 -1
  467. package/src/nexus/api/ops-api.ts +12 -0
  468. package/src/oauth/claude-pty-maturity.ts +66 -0
  469. package/src/oauth/codex-access-mirror.ts +55 -0
  470. package/src/oauth/codex.ts +7 -0
  471. package/src/oauth/fallback-chain.ts +1 -1
  472. package/src/onboarding/first-run.ts +5 -3
  473. package/src/onboarding/non-interactive.ts +64 -13
  474. package/src/onboarding.ts +10 -2
  475. package/src/ops/overview-collect.ts +54 -4
  476. package/src/ops/overview.ts +31 -7
  477. package/src/pr-tool/census.ts +282 -30
  478. package/src/pr-tool/inflight-registry.ts +160 -7
  479. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  480. package/src/pty-shell/herdr-agent-report.ts +442 -0
  481. package/src/pty-shell/pty-control-ipc.ts +5 -5
  482. package/src/pty-shell/pty-manifest.ts +7 -0
  483. package/src/pty-shell/pty-write-outcome.ts +24 -6
  484. package/src/pty-shell/tui-run-state.ts +117 -3
  485. package/src/release-loop/checklist.ts +103 -5
  486. package/src/release-loop/feature-store.ts +19 -2
  487. package/src/release-loop/landed-but-yellow.ts +129 -5
  488. package/src/release-loop/light-rc.ts +1 -0
  489. package/src/release-loop/placement.ts +10 -3
  490. package/src/release-loop/rehearsal.ts +205 -25
  491. package/src/release-loop/rubric.ts +16 -2
  492. package/src/repl/index.ts +174 -17
  493. package/src/repl/ops-msg-bridge.ts +32 -0
  494. package/src/self-dev/ask-launch-flow.ts +44 -5
  495. package/src/self-dev/cli-help-text.ts +17 -0
  496. package/src/self-dev/dev-cli.ts +11 -9
  497. package/src/self-dev/draft-residue.ts +37 -1
  498. package/src/self-dev/draft-sweep.ts +188 -13
  499. package/src/self-dev/draft-triage-rules.ts +107 -0
  500. package/src/self-dev/fleet-reduce.ts +3 -2
  501. package/src/self-dev/graph-front-nodes.ts +112 -0
  502. package/src/self-dev/graph-journey-nodes.ts +11 -6
  503. package/src/self-dev/graph-journey-route.ts +60 -6
  504. package/src/self-dev/harness-run-cli.ts +3 -15
  505. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  506. package/src/self-dev/orchestrate.ts +79 -3
  507. package/src/self-dev/review-provider-fallback.ts +35 -1
  508. package/src/self-dev/run-supervisor.ts +107 -12
  509. package/src/self-dev/run-types.ts +5 -1
  510. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  511. package/src/self-dev/shard-aggregate.ts +42 -5
  512. package/src/self-dev/shard-run.ts +8 -1
  513. package/src/self-implement/blocked-draft-policy.ts +20 -0
  514. package/src/self-implement/classify-shadow.ts +3 -7
  515. package/src/self-implement/doctor-visit.ts +18 -1
  516. package/src/self-implement/gate-baseline.ts +95 -12
  517. package/src/self-implement/gate-cli.ts +1 -0
  518. package/src/self-implement/gate-remote.ts +40 -25
  519. package/src/self-implement/goal-author-decompose.ts +275 -47
  520. package/src/self-implement/goal-author-identity.ts +66 -0
  521. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  522. package/src/self-implement/goal-author.ts +254 -120
  523. package/src/self-implement/goal-elaborate.ts +295 -0
  524. package/src/self-implement/goal-refine.ts +270 -0
  525. package/src/self-implement/graph-overlay-yaml.ts +28 -2
  526. package/src/self-implement/graph-unit-flatten.ts +103 -0
  527. package/src/self-implement/graph-unit-resolver.ts +107 -0
  528. package/src/self-implement/graph-yaml.ts +151 -1
  529. package/src/self-implement/headless-elanous-driver.ts +1 -0
  530. package/src/self-implement/knowhow-pack.ts +103 -0
  531. package/src/self-implement/orchestrator.ts +160 -45
  532. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  533. package/src/self-implement/review-mustfix-class.ts +203 -0
  534. package/src/self-implement/rework-budget-judgment.ts +5 -8
  535. package/src/self-implement/run-stop.ts +17 -2
  536. package/src/self-implement/running-runs.ts +29 -1
  537. package/src/self-implement/scope-adjacency.ts +113 -0
  538. package/src/self-implement/seams.ts +138 -4
  539. package/src/self-implement/stop-autoheal.ts +112 -2
  540. package/src/session/chat.ts +27 -0
  541. package/src/session-runtime/index.ts +1 -1
  542. package/src/session-runtime/retry-policy.ts +2 -1
  543. package/src/setup/llm-env-detect.ts +5 -0
  544. package/src/skills/tools/agent.ts +140 -14
  545. package/src/skills/tools/msg-ask.ts +100 -0
  546. package/src/skills/tools/ops-ledger.ts +2 -1
  547. package/src/skills/tools/schedule-wakeup.ts +66 -17
  548. package/src/steward/hold-hygiene.ts +24 -6
  549. package/src/steward/release-day.ts +7 -3
  550. package/src/steward/triage-budget.ts +194 -0
  551. package/src/steward/triage.ts +57 -7
  552. package/src/task-agent/actions.ts +69 -1
  553. package/src/task-agent/green-sweep.ts +4 -0
  554. package/src/task-agent/harvest-unit.ts +141 -0
  555. package/src/task-agent/live-moves.ts +257 -15
  556. package/src/task-agent/parent-host.ts +216 -6
  557. package/src/task-agent/postland-card.ts +80 -1
  558. package/src/task-agent/rejudge-on-head.ts +112 -26
  559. package/src/task-agent/repair-branch-cas.ts +4 -1
  560. package/src/task-agent/repair-cycle.ts +16 -3
  561. package/src/task-agent/run-identity.ts +4 -3
  562. package/src/task-agent/shadow.ts +19 -3
  563. package/src/task-agent/task-hand.ts +96 -36
  564. package/src/task-agent/tier-split.ts +127 -0
  565. package/src/task-agent/work-order-build.ts +24 -0
  566. package/src/task-agent/work-order.ts +3 -2
  567. package/src/task-orchestrator/generator-prompt.ts +60 -11
  568. package/src/task-orchestrator/surfaces/pod-account-broker.ts +72 -3
  569. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  570. package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
  571. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  572. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  573. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  574. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  575. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
  576. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  577. package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
  578. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  579. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
  580. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  581. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
  582. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
  583. package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
  584. package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
  585. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  586. package/src/tool-runtime/truncation-store.ts +4 -0
  587. package/src/tui/README.md +2 -0
  588. package/src/tui/chat/background-job-status.ts +54 -0
  589. package/src/tui/chat/log-view.ts +80 -0
  590. package/src/tui/entry.ts +406 -0
  591. package/src/tui/input/composer.ts +144 -0
  592. package/src/tui/seat-mail-boot.ts +59 -0
  593. package/src/tui/slash/compact.ts +100 -0
  594. package/src/tui/slash/new-session.ts +35 -0
  595. package/src/tui-client/dashboard-session.ts +10 -1
  596. package/src/tui-client/local-chat-turn.ts +239 -0
  597. package/src/tui-client/local-harness-command.ts +63 -0
  598. package/src/tui-client/local-provider-command.ts +184 -0
  599. package/src/user-config/coercion.ts +36 -0
  600. package/src/user-config.ts +22 -43
  601. package/src/ux-sim/event-monkey.ts +378 -0
  602. package/src/ux-sim/fake-bin.ts +42 -7
  603. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  604. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  605. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  606. package/src/ux-sim/scenario.ts +72 -13
  607. package/src/version/packed-revision.json +1 -1
  608. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  611. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  612. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  613. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  619. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  636. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  640. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +0 -226
  642. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  644. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/5543.a438b8ab5a13ea47.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  653. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  655. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  661. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  662. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  663. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  668. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  669. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  674. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +0 -24
  685. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9989.3694300e5f000b14.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  744. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  752. package/src/cli/g6a-registration-probe.ts +0 -16
  753. /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -5,11 +5,11 @@
5
5
  // elanous release tag --version <x.y.z> --source <commit> [--yes]
6
6
  // elanous release verify [--version <x.y.z>]
7
7
  // elanous release notes --from <ref> [--to <ref>]
8
- // elanous release run --version <x.y.z> [--prerelease rc] [--main-cut | --cut-commit <sha>] [--publish-at <iso>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--dry-run] [--json] [--if-ready]
9
- // elanous release resume --run <runId> --from <node> [--waive <node> --reason <text>] [--accepted-regressions <json>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--json]
8
+ // elanous release run --version <x.y.z> [--prerelease rc] [--main-cut | --cut-commit <sha>] [--publish-at <iso>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--dry-run] [--json] [--if-ready] [--force-new]
9
+ // elanous release resume --run <runId> --from <node> [--waive <node> --reason <text>] [--accepted-regressions <json>] [--gate-executor <pod|host> [--gate-host <ssh-host>]] [--gate-pod-pool <pool>] [--json]
10
10
  // elanous release auto-start [--window-minutes <n>] [--apply] [--json]
11
- // elanous release rehearsal tick [--apply] [--checkout <dir>] [--shards <n>] [--remote <host>] [--json]
12
- // elanous release preflight --version <x.y.z> [--publish-at <iso>] [--json] (컷 30분 전 사전 점검 · 읽기 전용 · ⛔ 있으면 exit 1)
11
+ // elanous release rehearsal tick [--apply] [--checkout <dir>] [--shards <n>] [--remote <host>] [--recovery-run <id>] [--json]
12
+ // elanous release preflight --version <x.y.z> [--publish-at <iso>] [--json] (컷 − 60분 main export 포함 사전 점검 · 읽기 전용 · ⛔ 있으면 exit 1)
13
13
  // elanous release cut-branch --version <x.y.z> --base <sha> --pick <sha>... [--dry-run]
14
14
  //
15
15
  // 🩸 계기(2026-09-25 v0.1.0 첫 공개): 손으로 밟은 절차에서 둘을 빠뜨릴 뻔했다 — 공개본 git 커밋(판 커밋이 공개본 커밋이 된다) ·
@@ -17,7 +17,7 @@
17
17
  // ⛔ prepare 는 «네트워크에 아무것도 쓰지 않는다»(공개 저장소를 «읽기»로 clone 만 한다) — 쓰는 것은 publish 뿐이고 `--yes` 가 있어야 한다.
18
18
  // 공개는 되돌릴 수 없다(그 판은 영구히 공개 라이선스).
19
19
  // ⛔ 공개본은 «원본 매니페스트»(`release/public-export.yaml`)대로만 만든다 — 매매 실행 코드는 그 매니페스트가 이미 뺀다(🅢 #20529).
20
- import { spawnSync } from 'node:child_process';
20
+ import { spawn, spawnSync } from 'node:child_process';
21
21
  import { createHash } from 'node:crypto';
22
22
  import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, readdirSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, writeFileSync } from 'node:fs';
23
23
  import { tmpdir } from 'node:os';
@@ -27,14 +27,14 @@ import { debug } from '../debug/log.js';
27
27
  import { effectiveInstanceRoot, releaseLedgerRoot } from '../instance/resolve.js';
28
28
  import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
29
29
  import { envLiteral } from '../platform/env-literal.js';
30
- import { getUserConfig, userConfigPath } from '../user-config.js';
31
- import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, devVersion, inspectChecklistTargetPaths, lintDocRefs, listChecklist, normalizeRefs, ownerMatches, parseOwner, parityGap, refRoots, removeItem, renderRefsStatus, seedFromRoadmap, setItem, summarizeChecklist, type ChecklistStatus, type ChecklistDisposition, type ChecklistKind, type ChecklistDispatchKind } from '../release-loop/checklist.js';
30
+ import { getUserConfig } from '../user-config.js';
31
+ import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, inspectChecklistTargetPaths, lintDocRefs, listChecklist, normalizeRefs, noteDispatchSkip, ownerMatches, parseOwner, parityGap, refRoots, removeItem, renderRefsStatus, seedFromRoadmap, setItem, type ChecklistStatus, type ChecklistDisposition, type ChecklistKind, type ChecklistDispatchKind } from '../release-loop/checklist.js';
32
32
  import * as features from '../release-loop/feature-store.js';
33
- import { evidencePlan, landedButYellow, type MergedChecklistPr } from '../release-loop/landed-but-yellow.js';
33
+ import { evidencePlan, fetchMergedChecklistPrs, landedButYellow, type MergedPrRunner } from '../release-loop/landed-but-yellow.js';
34
34
  import { formatSchedule, getSchedule, listSchedules, setSchedule } from '../release-loop/release-schedule.js';
35
35
  import { mergedPrsLast24h, placeCell, planPullForward, pullForwardPlacementConfig, rebalance, seatMove, type PlacementPriority } from '../release-loop/placement.js';
36
36
  import { readTrafficSignal } from '../seat-loop/traffic-signal.js';
37
- import { parseRubric, readRubricItems, rubricGrade, rubricScore } from '../release-loop/rubric.js';
37
+ import { parseRubric, parseRubricS, readRubricItems, rubricGrade, rubricScore } from '../release-loop/rubric.js';
38
38
  import { writeStdoutJson } from './stdout-json.js';
39
39
  import { CliUserError } from './cli-user-error.js';
40
40
  import { hqCliWriteAllowed, type HqDeps } from '../hq/hq.js';
@@ -43,11 +43,12 @@ import { isIsolatedLedgerWriteRoot } from '../hq/ledger-write-target.js';
43
43
  import { runUnattendedRelease, type UnattendedReleaseDeps } from '../../scripts/release-loop/unattended-release.js';
44
44
  import { publishAtError } from '../../scripts/release-loop/publish-at.js';
45
45
  import { cutReleaseBranch } from '../../scripts/release-loop/cut-branch.js';
46
- import { resumeReleaseRun } from '../../scripts/release-loop/resume-release.js';
46
+ import { planResumeReleaseRun, resumeReleaseRun, type ResumeReleaseDeps } from '../../scripts/release-loop/resume-release.js';
47
47
  import type { AcceptedRegression } from '../../scripts/release-loop/resume.js';
48
48
  import type { PrereleaseKind } from '../../scripts/release-loop/release-version.js';
49
49
  import { releaseReadiness } from '../../scripts/release-loop/release-readiness.js';
50
50
  import { runReleaseIfReady } from './release-run-if-ready.js';
51
+ import { ReleaseRunClaimConflict, findActiveReleaseRun, readActiveForceReleaseRun, readReleaseRunLock, withDirectReleaseRunLock, withForceReleaseRunMarker } from './release-single-flight.js';
51
52
  import { formatPreflight, releasePreflight } from '../../scripts/release-loop/preflight.js';
52
53
  import { defaultReleaseGraphRunsRoot, formatPublishProposal, measurePublishWindow, proposePublishAt, publishWindowWarning } from '../../scripts/release-loop/publish-window.js';
53
54
  import { autoStartScheduledRelease, type AutoStartDeferral } from '../release-loop/auto-start.js';
@@ -56,9 +57,11 @@ import { landingFreezeMessage, LandingFrozenError, readLandingFreeze } from '../
56
57
  import { formatLightRc, runLightRc, type LightRcDeps } from '../release-loop/light-rc.js';
57
58
  import { applyWatchList, formatGateHistory, gateHistory, ghMergedPrs } from '../../scripts/release-loop/gate-history.js';
58
59
  import { registerRfcCommands } from './rfc-cli.js';
60
+ import { checklistCodenames, checklistVersion, isReleaseVersion, readChecklistContext, registerChecklistReadCommands } from './release-checklist-read-cli.js';
61
+
62
+ export { isReleaseVersion } from './release-checklist-read-cli.js';
59
63
 
60
64
  export const DEFAULT_PUBLIC_REPO = 'ElanvitalAI/elanous';
61
- const SEMVER = /^\d+\.\d+\.\d+(?:-(?:rc|alpha|beta)\.\d+)?$/;
62
65
 
63
66
  export interface RunResult { status: number | null; stdout: string; stderr: string }
64
67
  export type Runner = (command: string, args: readonly string[], cwd: string, opts?: { env?: NodeJS.ProcessEnv; input?: string }) => RunResult;
@@ -68,7 +71,6 @@ export const defaultRunner: Runner = (command, args, cwd, opts = {}) => {
68
71
  return { status: r.status, stdout: r.stdout ?? '', stderr: r.error ? String(r.error) : (r.stderr ?? '') };
69
72
  };
70
73
 
71
- export function isReleaseVersion(version: string): boolean { return SEMVER.test(version); }
72
74
  export function isPrerelease(version: string): boolean { return version.includes('-'); }
73
75
 
74
76
  export interface ReleaseManifest {
@@ -491,13 +493,33 @@ async function jsonAction<T>(json: boolean | undefined, body: (log: (l: string)
491
493
  }
492
494
  }
493
495
 
494
- function warnChecklistTargetPaths(input: { title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind }): void {
496
+ function warnChecklistTargetPaths(input: { title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind }, strict = false): void {
495
497
  const cwd = process.cwd();
496
- const existsAtMain = (path: string): boolean => {
497
- if (path.startsWith('/') || path.split('/').includes('..')) return false;
498
- const result = spawnSync('git', ['cat-file', '-e', `origin/main:${path}`], { cwd, timeout: 5_000, stdio: 'ignore' });
499
- return result.status === 0;
498
+ const objectTypeAtMain = (path: string): 'blob' | 'tree' | 'commit' | 'blocked-blob' | 'blocked-gitlink' | 'unavailable' | null => {
499
+ if (path.startsWith('/') || path.split('/').includes('..')) return null;
500
+ const segments = path.split('/');
501
+ for (let length = 1; length < segments.length; length++) {
502
+ const ancestor = segments.slice(0, length).join('/');
503
+ const lookup = spawnSync('git', ['cat-file', '-t', `origin/main:${ancestor}`], { cwd, timeout: 5_000, encoding: 'utf8' });
504
+ if (lookup.status === 0) {
505
+ if (lookup.stdout.trim() === 'blob') return 'blocked-blob';
506
+ if (lookup.stdout.trim() === 'commit') return 'blocked-gitlink';
507
+ if (lookup.stdout.trim() !== 'tree') return 'unavailable';
508
+ continue;
509
+ }
510
+ const missing = spawnSync('git', ['ls-tree', 'origin/main', '--', ancestor], { cwd, timeout: 5_000, encoding: 'utf8' });
511
+ return missing.status === 0 && missing.stdout.trim() === '' ? null : 'unavailable';
512
+ }
513
+ const result = spawnSync('git', ['cat-file', '-t', `origin/main:${path}`], { cwd, timeout: 5_000, encoding: 'utf8' });
514
+ const type = result.status === 0 ? result.stdout.trim() : '';
515
+ if (type === 'blob' || type === 'tree' || type === 'commit') return type;
516
+ if (result.status === 0) return 'unavailable';
517
+ // cat-file also fails for a genuinely new path. ls-tree distinguishes that
518
+ // from a missing ref or another Git read failure before --strict accepts 신설:.
519
+ const probe = spawnSync('git', ['ls-tree', 'origin/main', '--', path], { cwd, timeout: 5_000, encoding: 'utf8' });
520
+ return probe.status === 0 && probe.stdout.trim() === '' ? null : 'unavailable';
500
521
  };
522
+ const existsAtMain = (path: string): boolean => objectTypeAtMain(path) === 'blob';
501
523
  const mergedPrFiles = (number: number): string[] => {
502
524
  const result = spawnSync('gh', ['pr', 'view', String(number), '--json', 'state,files'], { cwd, encoding: 'utf8', timeout: 10_000 });
503
525
  if (result.status !== 0) return [];
@@ -506,52 +528,20 @@ function warnChecklistTargetPaths(input: { title: string; evidence?: string; ref
506
528
  return pr.state === 'MERGED' ? (pr.files ?? []).map((file) => file.path).filter((path): path is string => typeof path === 'string') : [];
507
529
  } catch { return []; }
508
530
  };
509
- const report = inspectChecklistTargetPaths(input, { existsAtMain, mergedPrFiles });
531
+ const report = inspectChecklistTargetPaths(input, { existsAtMain, objectTypeAtMain, mergedPrFiles });
532
+ if (strict && report.warnings.length) throw new CliUserError(`칸 대상 경로/완료 경계 검사: ${report.warnings.join(' · ')}`, '문면을 고치거나 --strict 없이 경고로 저장한다');
510
533
  for (const warning of report.warnings) {
511
534
  console.error(`⚠ 대상 경로: ${warning}${report.candidates.length ? ` · 후보: ${report.candidates.join(' · ')}` : ''}`);
512
535
  debug.log('release.checklist', 'target-path-warning', { warning, candidates: report.candidates });
513
536
  }
514
537
  }
515
538
 
516
- function checklistCodenames(): Record<string, string> {
517
- const path = getElanousConfigDirOverride() ? join(effectiveInstanceRoot(), 'config.json') : userConfigPath();
518
- if (!existsSync(path)) return {};
519
- const raw = JSON.parse(readFileSync(path, 'utf8')) as { release?: { codenames?: Record<string, string> } };
520
- return raw.release?.codenames ?? {};
521
- }
522
-
523
- function checklistVersion(input: string | undefined, codenames: Record<string, string>): string {
524
- const v = input ?? devVersion().replace(/-dev\.\d+$/, '');
525
- const resolved = isReleaseVersion(v) ? v : Object.entries(codenames).find(([, name]) => name === v)?.[0] ?? v;
526
- if (!isReleaseVersion(resolved)) throw new CliUserError(`체크리스트 판 또는 별칭이 아니다: ${v}`);
527
- return resolved;
528
- }
529
-
530
- async function checklistOutput(v: string, codenames: Record<string, string>, mode: 'list' | 'status', json?: boolean, owner?: string): Promise<void> {
531
- if (owner !== undefined) parseOwner(owner);
532
- const snapshot = listChecklist(v);
533
- const data = owner === undefined ? snapshot : { ...snapshot, items: snapshot.items.filter((item) => ownerMatches(item.owner, owner)) };
534
- const summary = summarizeChecklist(data);
535
- const parity = data.items.flatMap((item) => {
536
- const why = item.kind === 'screen' ? parityGap(item.evidence) : null;
537
- return why ? [{ id: item.id, why }] : [];
538
- });
539
- const result = { ...data, codename: codenames[v] ?? '', ...summary, parity };
540
- for (const { id, why } of parity) debug.log('release.checklist', 'parity-warning', { version: v, id, why });
541
- if (json) { await writeStdoutJson(`${JSON.stringify(result)}\n`); return; }
542
- console.log(`⚠ 짝 경고 ${parity.length}: ${parity.map(({ id }) => id).join(', ') || '없음'}`);
543
- console.log(`${v}${result.codename ? ` (${result.codename})` : ''} · 공개 ${data.released || '없음'} · 개발 ${data.dev}`);
544
- if (mode === 'list') {
545
- for (const item of data.items) console.log(`${({ green: '🟢', yellow: '🟡', red: '🔴', done: '✅' } as const)[item.status]} ${item.id} ${item.title}${item.owner ? ` · ${item.owner}` : ''}${item.ceoMinutes !== undefined ? ` · 대표 손 ${item.ceoMinutes}분${item.ceoDate ? ` (${item.ceoDate})` : ''}` : ''}`);
546
- } else {
547
- console.log(`🟢 ${summary.green} · 🟡 ${summary.yellow} · 🔴 ${summary.red} · ✅ ${summary.done}`);
548
- console.log(`🔴 칸: ${summary.blocked.join(', ') || '없음'}`);
549
- console.log(`담당별: ${Object.entries(summary.byOwner).map(([owner, count]) => `${owner} ${count}`).join(' · ') || '없음'}`);
550
- }
551
- }
552
-
553
539
  export interface LandedButYellowDeps {
554
540
  run?: Runner;
541
+ /** Async gh for the merged-PR windows; wins over `run` (tests inject delay). */
542
+ runAsync?: MergedPrRunner;
543
+ /** logs.db sink for the stage timings; the default registers only on the real (uninjected) gh path. */
544
+ registerLogSink?: () => Promise<unknown>;
555
545
  checklist?: typeof listChecklist;
556
546
  now?: () => Date;
557
547
  evidenceAdd?: typeof features.evidenceAdd;
@@ -559,45 +549,18 @@ export interface LandedButYellowDeps {
559
549
  released?: typeof features.releasedVersion;
560
550
  }
561
551
 
562
- const MERGED_PR_LIMIT = 400;
563
-
564
- function mergedChecklistPrs(since: string, now: Date, run: Runner): { prs: MergedChecklistPr[]; truncated: boolean } {
565
- const cwd = process.cwd();
566
- const fetch = (lower: string, upper?: string, limit = MERGED_PR_LIMIT): MergedChecklistPr[] => {
567
- const search = `merged:>=${lower}${upper ? ` merged:<${upper}` : ''}`;
568
- const raw = must(run('gh', ['pr', 'list', '--state', 'merged', '--search', search, '--limit', String(limit), '--json', 'number,title,body,mergedAt'], cwd), '병합 PR 조회(gh)');
569
- const page = JSON.parse(raw) as MergedChecklistPr[];
570
- if (!Array.isArray(page)) throw new Error('병합 PR 조회(gh): 배열이 아니다');
571
- return page;
572
- };
573
- const unique = new Map<number, MergedChecklistPr>();
574
- let truncated = false;
575
- const collect = (page: MergedChecklistPr[]) => {
576
- for (const pr of page) if (!unique.has(pr.number)) unique.set(pr.number, pr);
577
- };
578
- const first = fetch(since);
579
- if (first.length < MERGED_PR_LIMIT) return { prs: first, truncated: false };
580
- const lower = Date.parse(`${since}T00:00:00Z`);
581
- const upper = Math.max(lower + 1000, Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate() + 1));
582
- const visit = (start: number, end: number): void => {
583
- const from = new Date(start).toISOString();
584
- const to = new Date(end).toISOString();
585
- const page = fetch(from, to);
586
- if (page.length < MERGED_PR_LIMIT) { collect(page); return; }
587
- if (end - start <= 1000) {
588
- // The second-precision search cannot be subdivided; probe one extra row to distinguish exactly 400 from a real truncation.
589
- const probe = fetch(from, to, MERGED_PR_LIMIT + 1);
590
- collect(probe.slice(0, MERGED_PR_LIMIT));
591
- if (probe.length > MERGED_PR_LIMIT) truncated = true;
592
- return;
593
- }
594
- const middle = start + Math.floor((end - start) / 2000) * 1000;
595
- visit(start, middle);
596
- visit(middle, end);
597
- };
598
- visit(lower, upper);
599
- return { prs: [...unique.values()], truncated };
600
- }
552
+ /** A spawn failure (gh missing from PATH) resolves `status: null` with the error text — the shape the sync runner gave. */
553
+ const defaultMergedPrRunner: MergedPrRunner = (command, args, cwd) => new Promise((resolve) => {
554
+ const out: Buffer[] = [], err: Buffer[] = [];
555
+ const failed = (error: unknown) => resolve({ status: null, stdout: Buffer.concat(out).toString('utf8'), stderr: String(error) });
556
+ let child: ReturnType<typeof spawn>;
557
+ try { child = spawn(command, [...args], { cwd, env: process.env, stdio: ['ignore', 'pipe', 'pipe'] }); }
558
+ catch (error) { failed(error); return; }
559
+ child.stdout?.on('data', (chunk: Buffer) => out.push(chunk));
560
+ child.stderr?.on('data', (chunk: Buffer) => err.push(chunk));
561
+ child.on('error', failed);
562
+ child.on('close', (code) => resolve({ status: code, stdout: Buffer.concat(out).toString('utf8'), stderr: Buffer.concat(err).toString('utf8') }));
563
+ });
601
564
 
602
565
  function printLandedRows(rows: ReturnType<typeof landedButYellow>, items: ReturnType<typeof listChecklist>['items']): void {
603
566
  const updatedAtById = new Map(items.map((item) => [item.id, item.updatedAt]));
@@ -625,7 +588,7 @@ function compareReleaseVersions(a: string, b: string): number {
625
588
  return 0;
626
589
  }
627
590
 
628
- export function registerReleaseCommands(program: Command, releaseRunDeps: UnattendedReleaseDeps = {}, landedDeps: LandedButYellowDeps = {}, hqDeps: HqDeps = {}, lightRcDeps: LightRcDeps = {}, rehearsalDeps: RehearsalDeps = {}): void {
591
+ export function registerReleaseCommands(program: Command, releaseRunDeps: UnattendedReleaseDeps = {}, landedDeps: LandedButYellowDeps = {}, hqDeps: HqDeps = {}, lightRcDeps: LightRcDeps = {}, rehearsalDeps: RehearsalDeps = {}, resumeDeps: ResumeReleaseDeps = {}): void {
629
592
  registerRfcCommands(program);
630
593
  const release = program.command('release').description('공개 배포 한 판 — prepare(로컬) → publish(--yes) → verify (docs/manual/MANUAL-versioning-and-release-2026-09-25.md)');
631
594
  const schedule = release.command('schedule').description('판별 컷·착지 마감 조회·갱신');
@@ -713,9 +676,9 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
713
676
  for (const item of readRubricItems(version, releaseLedgerRoot())) {
714
677
  if (item.priority !== 'P0' && item.priority !== 'P1') continue;
715
678
  const group = byPriority[item.priority];
716
- const rubric = parseRubric(`${item.title}\n${item.evidence ?? ''}`);
717
- if (rubric === null) group.missing++;
718
- else { group.s[rubric.S as 0 | 1 | 2 | 3]++; group.total += rubric.S; }
679
+ const s = parseRubricS(item.evidence ?? '') ?? parseRubric(item.title)?.S ?? parseRubricS(item.title);
680
+ if (s === null) group.missing++;
681
+ else { group.s[s as 0 | 1 | 2 | 3]++; group.total += s; }
719
682
  }
720
683
  const result = { version, byPriority, total: byPriority.P0.total + byPriority.P1.total, missing: byPriority.P0.missing + byPriority.P1.missing };
721
684
  if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
@@ -767,11 +730,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
767
730
  .option('--json', '결과 JSON')
768
731
  .option('--hq-override', '본부 임대 거부를 관측하며 수동 우회');
769
732
  const mayWrite = (cmd: Command) => mayWriteLedger(`release checklist ${cmd.name()}`, Boolean(cmd.optsWithGlobals().hqOverride), releaseLedgerRoot());
770
- const context = (cmd: Command) => {
771
- const opts = { ...(cmd.parent?.parent?.opts() as { version?: string; json?: boolean }), ...(cmd.parent?.opts() as { version?: string; json?: boolean }), ...(cmd.opts() as { version?: string; json?: boolean }) };
772
- const codenames = checklistCodenames();
773
- return { version: checklistVersion(opts.version, codenames), codenames, json: opts.json };
774
- };
733
+ const context = readChecklistContext;
775
734
  const withContext = (cmd: Command) => cmd.option('--version <v>', '판 또는 별칭').option('--json', '결과 JSON').option('--hq-override', '본부 임대 거부를 관측하며 수동 우회');
776
735
  const actor = () => process.env.ELANOUS_TRACK || 'cli';
777
736
  withContext(checklist.command('rubric').description('루브릭 채점(읽기 전용)'))
@@ -821,20 +780,30 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
821
780
  console.log(renderRefsStatus(rows));
822
781
  console.log(`칸 ${rows.length} · 🟢 ${byStatus.green} · 🟡 ${byStatus.yellow} · 🔴 ${byStatus.red} · ✅ ${byStatus.done}`);
823
782
  });
824
- withContext(checklist.command('list').description('모든 칸')).option('--owner <owner>', '자리 또는 하위 자리로 거르기').action(async (opts: { owner?: string }, cmd: Command) => {
825
- const { version, codenames, json } = context(cmd);
826
- await checklistOutput(version, codenames, 'list', json, opts.owner);
827
- });
828
- withContext(checklist.command('status').description('상태 요약')).option('--owner <owner>', '자리 또는 하위 자리로 거르기').action(async (opts: { owner?: string }, cmd: Command) => {
829
- const { version, codenames, json } = context(cmd);
830
- await checklistOutput(version, codenames, 'status', json, opts.owner);
831
- });
783
+ registerChecklistReadCommands(checklist);
832
784
  withContext(checklist.command('landed-but-yellow').description('병합 PR 이 있지만 노랑·빨강인 칸(기본 읽기 전용)'))
833
785
  .option('--owner <owner>', '자리 또는 하위 자리로 거르기')
834
786
  .option('--open', '미발행 일정 판 중 칸이 있는 판 전부')
835
787
  .option('--apply-evidence', '확실한 PR 짝의 근거를 붙인다(상태는 그대로)')
836
788
  .option('--dry-run', '근거 추가 없이 계획만 출력')
837
789
  .action(async (opts: { owner?: string; open?: boolean; applyEvidence?: boolean; dryRun?: boolean }, cmd: Command) => {
790
+ // Stage timings (LANDED-YELLOW-FAST): which step ate the time — `elanous logs --category release.landed-yellow`.
791
+ let stageAt = performance.now();
792
+ const stage = (name: string, data: Record<string, unknown>) => {
793
+ const at = performance.now();
794
+ debug.log('release.landed-yellow', 'stage', { stage: name, ms: Math.round(at - stageAt), ...data });
795
+ stageAt = at;
796
+ };
797
+ // A standalone CLI's debug.log reaches logs.db only through a registered sink (pr land #6701 lesson). Fail-open, 1s cap.
798
+ const registerLogSink = landedDeps.registerLogSink ?? (landedDeps.run || landedDeps.runAsync ? undefined
799
+ : async () => (await import('../domains/standalone-log-sink.js')).registerStandaloneLogSink('release-landed-yellow'));
800
+ if (registerLogSink) {
801
+ let sinkTimer: ReturnType<typeof setTimeout> | undefined;
802
+ try {
803
+ await Promise.race([registerLogSink(), new Promise<void>((resolve) => { sinkTimer = setTimeout(resolve, 1000); })]);
804
+ } catch { /* observability is fail-open */ } finally { clearTimeout(sinkTimer); }
805
+ }
806
+ stageAt = performance.now();
838
807
  try {
839
808
  const inherited = cmd.parent?.opts() as { version?: string; json?: boolean } | undefined;
840
809
  const local = cmd.opts() as { version?: string; json?: boolean };
@@ -851,6 +820,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
851
820
  .filter(({ version }) => isReleaseVersion(version) && (!released || compareReleaseVersions(version, released) > 0))
852
821
  .sort((a, b) => compareReleaseVersions(a.version, b.version))
853
822
  .map(({ version }) => (landedDeps.checklist ?? listChecklist)(version)).filter((snapshot) => snapshot.items.length > 0);
823
+ stage('snapshots', { n: openSnapshots.length, schedules: schedules.length });
854
824
  if (opts.open && !openSnapshots.length) {
855
825
  if (json) await writeStdoutJson('[]\n'); else console.log('열린 판 없음');
856
826
  return;
@@ -858,14 +828,17 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
858
828
  if (opts.applyEvidence && !opts.dryRun && !mayWrite(cmd)) return;
859
829
  const snapshots = opts.open ? openSnapshots : [(landedDeps.checklist ?? listChecklist)(context(cmd).version)];
860
830
  const now = (landedDeps.now ?? (() => new Date()))();
861
- // --version 도 --open 과 같은 판 전체 최좌 수정일로 병합 PR 을 찾는다 — 선택 판 칸의 updatedAt 에 묶이면 그보다 오래 전에 병합된 PR 을 놓친다(LBY-VERSION-OPEN-MISMATCH · OPT #4059).
831
+ // --version 도 --open 과 같은 판 전체 최초 수정일로 병합 PR 을 찾는다 — 선택 판 칸의 updatedAt 에 묶이면 그보다 오래 전에 병합된 PR 을 놓친다(LBY-VERSION-OPEN-MISMATCH · OPT #4059).
862
832
  const sinceSnapshots = opts.open ? snapshots : [...openSnapshots, ...snapshots];
863
833
  const updated = sinceSnapshots.flatMap(({ items }) => items
864
834
  .filter((item) => (item.status === 'yellow' || item.status === 'red') && (opts.owner === undefined || ownerMatches(item.owner, opts.owner)))
865
835
  .map((item) => Date.parse(item.updatedAt)).filter((at) => Number.isFinite(at)));
866
836
  const since = updated.length ? new Date(updated.reduce((earliest, at) => Math.min(earliest, at))).toISOString().slice(0, 10)
867
837
  : new Date(now.getTime() - 7 * 86_400_000).toISOString().slice(0, 10);
868
- const { prs, truncated } = mergedChecklistPrs(since, now, landedDeps.run ?? defaultRunner);
838
+ const syncRun = landedDeps.run;
839
+ const runAsync: MergedPrRunner = landedDeps.runAsync ?? (syncRun ? async (command, args, cwd) => syncRun(command, args, cwd) : defaultMergedPrRunner);
840
+ const { prs, truncated, calls } = await fetchMergedChecklistPrs(since, now, runAsync, process.cwd());
841
+ stage('merged-prs', { n: prs.length, calls, since, truncated });
869
842
  const results: Array<{ version: string; rows?: ReturnType<typeof landedButYellow>; plan?: ReturnType<typeof evidencePlan> }> = [];
870
843
  let totalAdded = 0, totalSkipped = 0;
871
844
  for (const snapshot of snapshots) {
@@ -892,6 +865,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
892
865
  results.push({ version, rows });
893
866
  }
894
867
  }
868
+ stage('match', { n: results.reduce((sum, result) => sum + (result.rows?.length ?? result.plan?.length ?? 0), 0), versions: snapshots.length, prs: prs.length });
895
869
  if (opts.open) {
896
870
  if (opts.applyEvidence && !opts.dryRun) debug.log('release.checklist', 'evidence-synced', { versions: snapshots.map(({ version }) => version), added: totalAdded, skippedMention: totalSkipped });
897
871
  if (!json) console.log(`판 ${snapshots.length} · 붙임 합 ${totalAdded} · 건너뜀(언급만) 합 ${totalSkipped}`);
@@ -908,13 +882,14 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
908
882
  .option('--ceo-minutes <minutes>', '대표 손 분량(분)').option('--ceo-date <date>', '대표 손 날짜 YYYY-MM-DD (없으면 판 착지일 KST)')
909
883
  .option('--accelerator', '가속 등급 — 다른 칸의 처리량을 올리는 칸(자율성·효율성·동시성). 생략하면 등급 없음')
910
884
  .option('--allow-duplicate-id', '다른 판에 같은 id 가 있어도 경고 후 추가')
885
+ .option('--strict', '대상 경로·완료 경계 경고가 있으면 저장 전 거부')
911
886
  .option('--ref <path...>', '근거 문서 — 저장소 상대 경로[#절] (반복 가능)')
912
- .action((id: string, title: string, opts: { ref?: string[]; owner?: string; kind?: string; priority?: string; deadlineVersion?: string; predecessor?: string[]; ceoMinutes?: string; ceoDate?: string; accelerator?: boolean; allowDuplicateId?: boolean }, cmd: Command) => {
887
+ .action((id: string, title: string, opts: { ref?: string[]; owner?: string; kind?: string; priority?: string; deadlineVersion?: string; predecessor?: string[]; ceoMinutes?: string; ceoDate?: string; accelerator?: boolean; allowDuplicateId?: boolean; strict?: boolean }, cmd: Command) => {
913
888
  const { version, json } = context(cmd);
914
889
  if (!mayWrite(cmd)) return;
915
890
  const dispatchKind = opts.kind && !['screen', 'postpub'].includes(opts.kind) ? opts.kind as ChecklistDispatchKind : undefined;
891
+ warnChecklistTargetPaths({ title, refs: opts.ref, dispatchKind }, opts.strict);
916
892
  const data = addItem(version, { id, title, ...(opts.ref !== undefined ? { refs: opts.ref } : {}), ...(opts.owner !== undefined ? { owner: opts.owner } : {}), ...(opts.kind !== undefined && !dispatchKind ? { kind: opts.kind as ChecklistKind } : {}), ...(dispatchKind ? { dispatchKind } : {}), ...(opts.priority !== undefined ? { priority: opts.priority as PlacementPriority } : {}), ...(opts.deadlineVersion !== undefined ? { deadlineVersion: opts.deadlineVersion } : {}), ...(opts.predecessor !== undefined ? { predecessors: opts.predecessor } : {}), ...(opts.ceoMinutes !== undefined ? { ceoMinutes: ceoMinutes(opts.ceoMinutes) } : {}), ...(opts.ceoDate !== undefined ? { ceoDate: opts.ceoDate } : {}), ...(opts.accelerator ? { accelerator: true } : {}) }, { allowDuplicateId: opts.allowDuplicateId });
917
- warnChecklistTargetPaths({ title, refs: opts.ref, dispatchKind });
918
893
  if (json) console.log(JSON.stringify(data)); else console.log(`✅ ${id} 추가`);
919
894
  });
920
895
  withContext(checklist.command('set <id>').description('칸 상태·근거·담당·처분 갱신'))
@@ -977,15 +952,26 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
977
952
  else features.move(id, from, to, actor(), undefined, undefined, opts.reason);
978
953
  if (json) console.log(JSON.stringify(listChecklist(to))); else console.log(`✅ ${id} ${from} → ${to}`);
979
954
  });
980
- withContext(checklist.command('retitle <id> <title>').description('칸 제목 수정')).action((id: string, title: string, _opts: unknown, cmd: Command) => {
955
+ withContext(checklist.command('retitle <id> <title>').description('칸 제목 수정')).option('--strict', '대상 경로·완료 경계 경고가 있으면 저장 전 거부').action((id: string, title: string, opts: { strict?: boolean }, cmd: Command) => {
981
956
  const { version, json } = context(cmd);
982
957
  if (!mayWrite(cmd)) return;
983
958
  const snapshot = listChecklist(version);
984
- features.retitle(id, title, actor(), snapshot.released, snapshot.dev);
985
959
  const item = snapshot.items.find((entry) => entry.id === id);
986
- warnChecklistTargetPaths({ title, evidence: item?.evidence, refs: item?.refs, dispatchKind: item?.dispatchKind });
960
+ if (!opts.strict) warnChecklistTargetPaths({ title, evidence: item?.evidence, refs: item?.refs, dispatchKind: item?.dispatchKind });
961
+ features.retitle(id, title, actor(), snapshot.released, snapshot.dev, opts.strict
962
+ ? (affected) => warnChecklistTargetPaths({ title, evidence: affected.evidence, refs: affected.refs, dispatchKind: affected.dispatchKind }, true)
963
+ : undefined);
987
964
  if (json) console.log(JSON.stringify(listChecklist(version))); else console.log(`✅ ${id} 제목 수정`);
988
965
  });
966
+ withContext(checklist.command('skip-note <id> <reason>').description('디스패처 건너뜀 사유를 칸 근거에 중복 없이 기록'))
967
+ .requiredOption('--expected-title <title>', '검사한 칸 제목; 바뀐 제목이면 기록하지 않는다')
968
+ .requiredOption('--by <actor>', '실제 기록 주체(디스패처 자리)')
969
+ .action((id: string, reason: string, opts: { expectedTitle: string; by: string }, cmd: Command) => {
970
+ const { version, json } = context(cmd);
971
+ if (!mayWrite(cmd)) return;
972
+ const data = noteDispatchSkip(version, id, reason, opts.expectedTitle, opts.by);
973
+ if (json) console.log(JSON.stringify(data)); else console.log(`✅ ${id} 건너뜀 근거 확인`);
974
+ });
989
975
  const evidence = checklist.command('evidence').description('칸의 PR·커밋 근거');
990
976
  withContext(evidence.command('add <id> <ref>').description('근거 참조 추가')).action((id: string, ref: string, _opts: unknown, cmd: Command) => {
991
977
  const { version, json } = context(cmd);
@@ -1082,7 +1068,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1082
1068
  .action(async (o: { version: string; base: string; pick: string[]; append?: boolean; dryRun?: boolean; json?: boolean }) => {
1083
1069
  await jsonAction(o.json, async (log) => cutReleaseBranch({ ...o, log }), () => true);
1084
1070
  });
1085
- const runAction = async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }, logRun = console.log): Promise<boolean | AutoStartDeferral | undefined> => {
1071
+ const runAction = async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; forceNew?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }, logRun = console.log): Promise<boolean | AutoStartDeferral | undefined> => {
1086
1072
  // Only the rc rehearsal channel is operated for now (alpha/beta stay valid version shapes, not run options).
1087
1073
  if (o.prerelease !== undefined && o.prerelease !== 'rc') {
1088
1074
  const message = `--prerelease supports rc only: ${o.prerelease}`;
@@ -1099,6 +1085,18 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1099
1085
  process.exitCode = 1;
1100
1086
  return false;
1101
1087
  }
1088
+ const ledgerRoot = releaseRunDeps.ledgerRoot ?? releaseLedgerRoot();
1089
+ if (!o.dryRun && !o.forceNew) {
1090
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1091
+ if (active) {
1092
+ const error = `release run already running: ${o.version} runId=${active.runId} pid=${active.pid} startedAt=${active.startedAt} (--force-new to bypass)`;
1093
+ debug.log('release.run', 'already-running', { version: o.version, ...active });
1094
+ if (o.json) await writeStdoutJson(`${JSON.stringify({ ok: false, reason: 'already-running', error, ...active })}\n`);
1095
+ else console.error(`⛔ ${error}`);
1096
+ process.exitCode = 1;
1097
+ return false;
1098
+ }
1099
+ }
1102
1100
  const prerelease = o.prerelease as PrereleaseKind | undefined;
1103
1101
  if (!o.dryRun) {
1104
1102
  try {
@@ -1130,10 +1128,20 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1130
1128
  try {
1131
1129
  const outcome = await runReleaseIfReady(o.version, {
1132
1130
  ledgerRoot: releaseRunDeps.ledgerRoot,
1131
+ forceNew: o.forceNew,
1133
1132
  readiness: (version, options) => releaseReadiness(version, { ledgerRoot: releaseRunDeps.ledgerRoot, checklist: releaseRunDeps.checklist, ...options }),
1134
- run: () => runUnattendedRelease({ version: o.version, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps),
1133
+ run: () => runUnattendedRelease({ version: o.version, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, forceNew: o.forceNew, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps),
1135
1134
  });
1136
1135
  if (outcome.skipped) {
1136
+ if (outcome.reason === 'already-running') {
1137
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1138
+ const lock = readReleaseRunLock(o.version, ledgerRoot);
1139
+ const error = `release run already running: ${o.version} runId=${active?.runId ?? 'pending'} pid=${active?.pid ?? lock?.pid ?? 'unknown'} startedAt=${active?.startedAt ?? lock?.startedAt ?? 'unknown'} (--force-new to bypass)`;
1140
+ if (o.json) await writeStdoutJson(`${JSON.stringify({ ok: false, reason: 'already-running', error, ...(active ?? {}) })}\n`);
1141
+ else console.error(`⛔ ${error}`);
1142
+ process.exitCode = 1;
1143
+ return false;
1144
+ }
1137
1145
  if (o.json) await writeStdoutJson(`${JSON.stringify(outcome)}\n`);
1138
1146
  else logRun(`· 준비 안 됨 ${o.version} · ${outcome.reason} · ${outcome.detail}`);
1139
1147
  return { deferred: true, reason: outcome.reason };
@@ -1159,7 +1167,20 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1159
1167
  }
1160
1168
  }
1161
1169
  await jsonAction(o.json, async (log) => {
1162
- const result = await runUnattendedRelease({ version: o.version, dryRun: o.dryRun, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps);
1170
+ const run = () => runUnattendedRelease({ version: o.version, dryRun: o.dryRun, cutCommit: o.cutCommit, mainCut: o.mainCut, prerelease, forceFreeze: o.forceFreeze, forceNew: o.forceNew, publishAt: o.publishAt, gateExecutor: o.gateExecutor, gateHost: o.gateHost }, releaseRunDeps);
1171
+ const forceRun = () => {
1172
+ const atStart = releaseReadiness(o.version, { ledgerRoot, checklist: releaseRunDeps.checklist, isPidAlive: () => false });
1173
+ if (!atStart.ready) throw new Error(`release run --force-new not ready after claim: ${atStart.reason}`);
1174
+ return run();
1175
+ };
1176
+ let result: Awaited<ReturnType<typeof runUnattendedRelease>>;
1177
+ try { result = o.dryRun ? await run() : o.forceNew ? await withForceReleaseRunMarker(o.version, ledgerRoot, forceRun) : await withDirectReleaseRunLock(o.version, ledgerRoot, run); }
1178
+ catch (error) {
1179
+ if (!(error instanceof ReleaseRunClaimConflict)) throw error;
1180
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1181
+ const lock = readReleaseRunLock(o.version, ledgerRoot);
1182
+ throw new Error(`release run already running: ${o.version} runId=${active?.runId ?? 'pending'} pid=${active?.pid ?? lock?.pid ?? 'unknown'} startedAt=${active?.startedAt ?? lock?.startedAt ?? 'unknown'} (--force-new to bypass)`);
1183
+ }
1163
1184
  log(`${result.dryRun ? '· 드라이런' : '▶ 릴리스 루프'} ${result.input.version} · 입력 ${JSON.stringify(result.input)}`);
1164
1185
  return result;
1165
1186
  }, (r) => r.dryRun || r.state?.status === 'done' || r.state?.status === 'awaiting-approval');
@@ -1174,12 +1195,13 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1174
1195
  .option('--if-ready', '준비되지 않았으면 사유를 출력하고 성공으로 건너뛴다')
1175
1196
  .option('--publish-at <iso>', '승인·선행 노드 통과 뒤 지정 시각까지 발행 대기(오프셋 포함 ISO 시각)')
1176
1197
  .option('--force-freeze', '동결 중 게이트·발행 강행(관측 기록) — 가지 컷은 동결이 필요 없다 · 동결은 비상 스위치로 남는다')
1198
+ .option('--force-new', '같은 판의 살아 있는 릴리스 런을 확인한 뒤에도 새 런을 명시적으로 시작')
1177
1199
  .option('--gate-executor <pod|host>', 'gate 노드 실행기(기본 pod) — host 는 Pod 대신 SSH 호스트의 깨끗한 클론에서 같은 판정(면제 아님)')
1178
1200
  .option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 release.loop.gateRemote)')
1179
1201
  .option('--json', '결과 한 줄 JSON(stdout) · 사람 줄은 stderr')
1180
- .action(async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }) => { await runAction(o); });
1202
+ .action(async (o: { version: string; cutCommit?: string; mainCut?: boolean; prerelease?: string; dryRun?: boolean; ifReady?: boolean; publishAt?: string; forceFreeze?: boolean; forceNew?: boolean; gateExecutor?: string; gateHost?: string; json?: boolean }) => { await runAction(o); });
1181
1203
  release.command('preflight')
1182
- .description('컷 30분 전 사전 점검(읽기 전용) — 체크리스트 게이트 모의 · 발행 뒤 칸 · run --dry-run 입력 · 동결 · 일정/게이트 실측. ⛔ 있으면 exit 1')
1204
+ .description('컷 전 사전 점검(읽기 전용) — 체크리스트·런 입력·동결·일정 + 컷 − 60분 origin/main export(자동 예약 없음). ⛔ 있으면 exit 1')
1183
1205
  .requiredOption('--version <v>', '점검할 판(x.y.z)')
1184
1206
  .option('--publish-at <iso>', '계획 발행 시각(기본: 컷 뒤 첫 07·18시 KST)')
1185
1207
  .option('--json', '결과 한 줄 JSON(stdout)')
@@ -1229,8 +1251,11 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1229
1251
  .option('--accepted-regressions <json>', '알려진 문제 추가 입력 JSON 배열 [{"id":"…","note":"…"}]')
1230
1252
  .option('--gate-executor <pod|host>', '다시 도는 gate 의 실행기 전환(--from gate 이전만) — 런 입력에 기록 · 면제 아님')
1231
1253
  .option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 저장된 런 입력 gateRemote)')
1254
+ .option('--gate-pod-pool <pool>', '다시 도는 gate 의 Pod 풀을 전환(--from gate 이전만) — 런 입력에 기록')
1255
+ .option('--command-root <path>', '노드 명령을 실행할 컷 tip checkout(생략 시 현재 폴더)')
1256
+ .option('--dry-run', '재개 preflight만 수행하고 런·상태 원장·시도 횟수는 변경하지 않는다')
1232
1257
  .option('--json', '결과 한 줄 JSON(stdout)')
1233
- .action(async (o: { run: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: string; gateExecutor?: string; gateHost?: string; json?: boolean }) => {
1258
+ .action(async (o: { run: string; from: string; partial?: boolean; waive?: string; reason?: string; acceptedRegressions?: string; gateExecutor?: string; gateHost?: string; gatePodPool?: string; commandRoot?: string; dryRun?: boolean; json?: boolean }) => {
1234
1259
  await jsonAction(o.json, async (log) => {
1235
1260
  let acceptedRegressions: AcceptedRegression[] | undefined;
1236
1261
  if (o.acceptedRegressions !== undefined) {
@@ -1241,21 +1266,34 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1241
1266
  throw new Error('acceptedRegressions must be an array of {id, note}');
1242
1267
  }
1243
1268
  }
1244
- const result = await resumeReleaseRun({ runId: o.run, from: o.from, partial: o.partial,
1269
+ const resumeOptions = { runId: o.run, from: o.from, partial: o.partial, commandRoot: o.commandRoot,
1245
1270
  ...(o.waive === undefined ? {} : { waive: o.waive }),
1246
1271
  ...(o.reason === undefined ? {} : { reason: o.reason }),
1247
1272
  ...(o.acceptedRegressions === undefined ? {} : { acceptedRegressions }),
1248
1273
  ...(o.gateExecutor === undefined ? {} : { gateExecutor: o.gateExecutor }),
1249
- ...(o.gateHost === undefined ? {} : { gateHost: o.gateHost }) });
1250
- const override = result.state.inputOverrides?.at(-1);
1251
- if (o.gateExecutor !== undefined && override) log(`⇄ gate 실행기 ${override.set.gateExecutor}${override.set.gateRemote ? ` @ ${override.set.gateRemote}` : ''} (런 입력에 기록 · 면제 아님)`);
1274
+ ...(o.gateHost === undefined ? {} : { gateHost: o.gateHost }),
1275
+ ...(o.gatePodPool === undefined ? {} : { gatePodPool: o.gatePodPool }) };
1276
+ if (o.dryRun) {
1277
+ const plan = await planResumeReleaseRun(resumeOptions, { onSource: log });
1278
+ const gate = plan.gatePlan.mode === 'not-run' ? 'gate 실행 없음'
1279
+ : plan.gatePlan.mode === 'partial' ? `부분 gate 계획 ${plan.partial.requested && plan.partial.applied ? `${plan.partial.files}파일` : '미상'}`
1280
+ : `전체 gate${plan.gatePlan.reason ? ` (${plan.gatePlan.reason})` : ''}`;
1281
+ log(`· 재개 preflight 통과 · ${plan.version} · ${plan.fromNode}부터 · tip ${plan.tip.to.slice(0, 12)}${plan.tip.changed ? ` (기록 tip ${plan.tip.from.slice(0, 12)}에서 이동)` : ''} · ${gate} · 시도 ${plan.nextAttempt}/${plan.attemptLimit} · 실행·원장 변경 없음`);
1282
+ return plan;
1283
+ }
1284
+ const result = await resumeReleaseRun(resumeOptions, { onSource: log });
1285
+ const executorOverride = [...(result.state.inputOverrides ?? [])].reverse().find((item) => item.kind === 'gate-executor');
1286
+ const poolOverride = [...(result.state.inputOverrides ?? [])].reverse().find((item) => item.kind === 'gate-pod-pool');
1287
+ if (o.gateExecutor !== undefined && executorOverride?.kind === 'gate-executor') log(`⇄ gate 실행기 ${executorOverride.set.gateExecutor}${executorOverride.set.gateRemote ? ` @ ${executorOverride.set.gateRemote}` : ''} (런 입력에 기록 · 면제 아님)`);
1288
+ if (o.gatePodPool !== undefined && poolOverride?.kind === 'gate-pod-pool') log(`⇄ gate Pod 풀 ${poolOverride.set.gatePodPool} (런 입력에 기록)`);
1252
1289
  if (result.partial.requested) log(result.partial.applied
1253
1290
  ? `◐ 부분 재검${result.partial.auto ? '(기본)' : ''}: ${result.partial.files}파일${result.partial.closure ? ` (코드 닿음 ${result.partial.closure.reached} · 닫힘 불투명 ${result.partial.closure.opaque})` : ''} · 나머지는 앞 게이트(${result.partial.priorCommit.slice(0, 12)}) 결과를 잇는다`
1254
1291
  : `● 전체 게이트로: ${result.partial.reason}`);
1255
1292
  log(`${result.tip.changed ? `↻ ${result.tip.branch} ${result.tip.from.slice(0, 12)} → ${result.tip.to.slice(0, 12)} (백업 ${result.tip.backup})` : `· ${result.tip.branch} 끝 그대로 ${result.tip.to.slice(0, 12)}`} · ${o.from} 부터 → ${result.state.status}`);
1256
1293
  return { tip: result.tip, partial: result.partial, status: result.state.status, runId: result.state.runId,
1257
- ...(o.gateExecutor !== undefined && result.state.inputOverrides?.length ? { gateExecutor: result.state.inputOverrides.at(-1) } : {}) };
1258
- }, (r) => r.status === 'done' || r.status === 'awaiting-approval');
1294
+ ...(o.gateExecutor !== undefined && executorOverride?.kind === 'gate-executor' ? { gateExecutor: executorOverride } : {}),
1295
+ ...(o.gatePodPool !== undefined && poolOverride?.kind === 'gate-pod-pool' ? { gatePodPool: poolOverride } : {}) };
1296
+ }, (r) => 'preflight' in r || r.status === 'done' || r.status === 'awaiting-approval');
1259
1297
  });
1260
1298
  release.command('gate-history')
1261
1299
  .description('GATE-FAIL-HISTORY (0.2.29) — 판을 넘는 게이트 실패 표 — 모든 release-loop·light-rc 런 원장 ⊕ gate-verdict 에서 시험 파일별 introduced·preexisting·env·flaky 횟수 · 마지막 실패 판 · 원인 PR(수리 PR 본문 «원인 #N»)')
@@ -1303,15 +1341,34 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1303
1341
  .option('--checkout <dir>', '깨끗한 git 체크아웃(기본 ELANOUS_REHEARSAL_GIT_CWD)')
1304
1342
  .option('--shards <n>', '시험 분할 수')
1305
1343
  .option('--remote <host>', '게이트 호스트')
1344
+ .option('--recovery-run <id>', '기존 실패 release-loop 런을 gate에서 명시적으로 재개(기본 예약 틱과 분리)')
1306
1345
  .option('--json', '결과 한 줄 JSON(stdout)')
1307
- .action(async (o: { apply?: boolean; checkout?: string; shards?: string; remote?: string; json?: boolean }) => {
1346
+ .action(async (o: { apply?: boolean; checkout?: string; shards?: string; remote?: string; recoveryRun?: string; json?: boolean }) => {
1308
1347
  await jsonAction(o.json, async (log) => {
1309
1348
  const ledgerRoot = scheduleLedgerRoot();
1349
+ if (o.recoveryRun !== undefined) {
1350
+ if (!/^[a-zA-Z0-9][a-zA-Z0-9._-]{0,127}$/.test(o.recoveryRun)) throw new Error('release rehearsal recovery: invalid run id');
1351
+ if (o.shards !== undefined || o.remote !== undefined) throw new Error('release rehearsal recovery: --shards and --remote are unsupported; use the saved gate settings');
1352
+ const resumeOptions = { runId: o.recoveryRun, from: 'gate', commandRoot: o.checkout ?? process.cwd() };
1353
+ if (!o.apply) {
1354
+ const plan = await planResumeReleaseRun(resumeOptions, resumeDeps);
1355
+ log(`· 리허설 복구 사전점검 ${plan.preflight} · run ${plan.runId} · ${plan.version} · from ${plan.fromNode} · gate ${plan.gatePlan.mode}`);
1356
+ return { recovery: 'planned', ...plan };
1357
+ }
1358
+ if (!mayWriteLedger('release rehearsal recovery', false, ledgerRoot)) throw new Error('release rehearsal recovery: ledger write denied');
1359
+ const result = await resumeReleaseRun(resumeOptions, resumeDeps);
1360
+ log(`· 리허설 복구 완료 · run ${o.recoveryRun} · ${result.state.status} · gate에서 재개`);
1361
+ return { recovery: 'resumed', runId: o.recoveryRun, status: result.state.status, ...result };
1362
+ }
1310
1363
  if (o.apply && !mayWriteLedger('release rehearsal tick', false, ledgerRoot)) throw new Error('release rehearsal tick: ledger write denied');
1311
1364
  const result = await runRehearsalTick({ apply: o.apply, checkout: o.checkout, shards: o.shards === undefined ? undefined : Number(o.shards), remote: o.remote, ledgerRoot }, rehearsalDeps);
1312
1365
  log(`· 리허설 ${result.status}${'version' in result ? ` ${result.version}` : ''}${result.status === 'due' ? ` · 실행 ${result.run ?? '-'} · 건너뜀 ${result.supersede.join(', ') || '-'}` : ''}`);
1366
+ for (const stamp of result.stamps ?? []) {
1367
+ if (stamp.outcome === 'unmeasured' && !stamp.result && stamp.shardPlan && (stamp.shardPlan.testFiles === 0 || stamp.shardPlan.gatePlanShards === null))
1368
+ log(`· 리허설 ${stamp.version} ${stamp.step} · ${stamp.summary} · stage claim 해제 · 다음 tick 재시도`);
1369
+ }
1313
1370
  return result;
1314
- }, (result) => !result.notificationFailures && !result.stamps?.some((stamp) => !['ok', 'superseded'].includes(stamp.outcome)));
1371
+ }, (result) => result.status !== 'failed' && !result.notificationFailures && !result.stamps?.some((stamp) => !['ok', 'superseded'].includes(stamp.outcome)));
1315
1372
  });
1316
1373
  release.command('auto-start')
1317
1374
  .description('판 일정의 컷 창에서 릴리스 시작을 미리 본다 · --apply 로 release run --if-ready 실행')