elanous 0.2.31 → 0.2.34

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 (715) 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/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1162.c69abda138c7ce43.js +79 -0
  5. package/apps/pwa/out/_next/static/chunks/1449-1fede62af84c3e43.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1598-13fc845935e816df.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1639.62c5e16fa20d242f.js +94 -0
  8. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 1644.35dd25240ae24e4b.js} +2 -2
  9. package/apps/pwa/out/_next/static/chunks/1661-adb8b2babc9aaf8c.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 1895-60ed0e341c658bd4.js} +1 -1
  11. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 2124.ed5bf480cea7f85b.js} +1 -1
  12. package/apps/pwa/out/_next/static/chunks/2147.107c0fc6146fb15a.js +23 -0
  13. package/apps/pwa/out/_next/static/chunks/2202-ef1c9b000c3074fc.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/2247.1e326638ee43e672.js +115 -0
  15. package/apps/pwa/out/_next/static/chunks/2268.56e1e3d58180abae.js +8 -0
  16. package/apps/pwa/out/_next/static/chunks/2469-606819c812414021.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 2547.dd27303624cb4da8.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 2554.3b5e200f5f5cfcd6.js} +16 -16
  19. package/apps/pwa/out/_next/static/chunks/2593.e53c1620c0bb3599.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2690.e96671114222676a.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2898-79ee1a5cc0cd9d13.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/298.26099a9f65e5c8ff.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 2987-30cf9c2eb7b8bdd5.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/2992.51fc2a7295bd8139.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/{3541-ce3a5424ed5ad7f1.js → 3001-5a52788c813b6113.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/3014-291245fba9df7b5b.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/3068.ee78201f0251a18d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/3083.cd399a17e9365f78.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.84470c8445962f04.js +34 -0
  30. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 3110.0a7065f25c841818.js} +17 -17
  31. package/apps/pwa/out/_next/static/chunks/3117-e1c474683fd1f824.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3121.779fafe3e44612c5.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3251-2c17bd5a91f8de2e.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/326.3fb32322bb2ddf6d.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3411-f87314c6c66ebc73.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 3414.172ad4ca2d9b08e8.js} +2 -2
  37. package/apps/pwa/out/_next/static/chunks/3421-7ff7fbaa156985a7.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{4745.67d6f99c245af3f7.js → 3498.cf2a15a8a9e5b926.js} +3 -3
  39. package/apps/pwa/out/_next/static/chunks/381.f55dc63ea87735e6.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3819.163d4777f0a597f6.js +32 -0
  41. package/apps/pwa/out/_next/static/chunks/{5543.a438b8ab5a13ea47.js → 3837.722e053fb9f321ad.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/4129-ab0a6189f1778633.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/4361.93d14ba594b3a035.js +104 -0
  44. package/apps/pwa/out/_next/static/chunks/4364.7a7eb19cceb67d2f.js +286 -0
  45. package/apps/pwa/out/_next/static/chunks/4406.d71f506f7c3ee9d3.js +149 -0
  46. package/apps/pwa/out/_next/static/chunks/4461.2ad1514180ae7e29.js +148 -0
  47. package/apps/pwa/out/_next/static/chunks/4479.bd309cbe0e3842ee.js +64 -0
  48. package/apps/pwa/out/_next/static/chunks/4522-05966f777d66d13b.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/4543-9a3e9812e845de65.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4557.f8f1d84a0d90d590.js +74 -0
  51. package/apps/pwa/out/_next/static/chunks/4589-79b11542179ef58c.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4633-9f8f9f88ffbb8f5c.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4831.23af4d10c0697b5e.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4983.5951b85724f61f2a.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → 4fa33ebd.21c1bd5b294496e6.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 5014f970-22bef0b5210f7d60.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/{2112-e4efc21a6505d5bc.js → 5028-f0722e6114c313e7.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{2898.fd781bc7cf01a7b7.js → 5249.96a848656b582a93.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/5311.16e0ffbfa5468b80.js +62 -0
  60. package/apps/pwa/out/_next/static/chunks/{9407.e49124dedf0f5e72.js → 5446.edf141cff9ef647d.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9002.e5658224e3dc1b6f.js → 5489.ec2dd1b5272a19dc.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 5576-82d3703636d5c4b9.js} +3 -3
  63. package/apps/pwa/out/_next/static/chunks/559.df87695df637920c.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5618-5c88f2f70178c4ad.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5764.05487bf0b73ddb6b.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5930.e678826c3f831aab.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5dfb57f7.f2e3305326202474.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/6053-d893974de92e6198.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 6086.913a69e6fa3e4a8b.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/6200-cefd6f33f59d765e.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6314-edeba650ae686ac9.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6316-bc9a9b74d7842d79.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6476-13b9779b73528008.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/666-04db3ac4c8e3c66f.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/670.682e55106ef915a6.js +77 -0
  76. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 6740.43de73fc427c9fe2.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/6816.b7ba9d0a1a4a46a7.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/690-fbbcc777f189af37.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6989.0d3d4020e5cb3df6.js +90 -0
  80. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7005.1623d2aea78eb85f.js} +1 -1
  81. package/apps/pwa/out/_next/static/chunks/7193-cf355cca5ba6c5d5.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7217-d17393fe7af78fa6.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/7232.24edbd938a69c8d0.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7295cd1e.b4b557908888eeee.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7323.adb02de21991883c.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7386.5d8e7e42e818dfb6.js +287 -0
  87. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 7431.3051e9b8a4372d2d.js} +2 -2
  88. package/apps/pwa/out/_next/static/chunks/{3583.a05e88cc8d594628.js → 7448.478958ffbbba0ac0.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/7537.ba2208c5c656b8a3.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7562.948255cbc3e79d33.js +41 -0
  91. package/apps/pwa/out/_next/static/chunks/7596-962ae6db6cfc9c83.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7671.cff51beac212a2ba.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/7883.3916734ee16d3e58.js +27 -0
  94. package/apps/pwa/out/_next/static/chunks/{9989.3694300e5f000b14.js → 7952.b192c31b6a0e00cc.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/801.5b24e81eded22d1b.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/8176.8c9a8613f5a01ac1.js +36 -0
  97. package/apps/pwa/out/_next/static/chunks/819e78a6.fa3dd7f7da19bf61.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8220-78978450c3183d8d.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8221-eb60b5bc692a3361.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/826.e9a26064f474949e.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 8368.014caa8de2f5af34.js} +1 -1
  102. package/apps/pwa/out/_next/static/chunks/8459-a351487a4480f584.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8482-75823d513a4ce151.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8488.8da515248cda3f3a.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 8548.036c344973968847.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8584.388a1779d9b203af.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8637.a55e098e61ffefb8.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8817.61bb7ffbba502ecb.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 9131-fce7256c4180c4a5.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/9207-8e6a12db30373f32.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9263-00ae932c62696a86.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/9318.caafc3a130e8769c.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/932.da3fb55951882562.js +93 -0
  114. package/apps/pwa/out/_next/static/chunks/9433.002f8426ac75b6b7.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9464.dd631a5a14b1d660.js +24 -0
  116. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9550.d5f76828f972058c.js} +2 -2
  117. package/apps/pwa/out/_next/static/chunks/{2534.e85ae21ad0dac829.js → 9739.8d5f36ac67a3b236.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9743.beeabb9d5f86abe4.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9843-a23d3f32dc43f715.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/994-28211077c7c587d5.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → 9a8cb466.cc9fc9e6e46038aa.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → 9b48c871.204d5d13e7809bd0.js} +7 -7
  123. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → abb4b98b.163e0f56e84ae35d.js} +1 -1
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-3b4c947f174e33d8.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-369d5ce99483f859.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-63c0ed0eb26e5fce.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-62802c6003bc85cc.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ecb41560d4e77be9.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-7b65ad8130c93e95.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8755477c15a9060c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-5725447dd972c471.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b979de0591a69375.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-6d0796bf4633751a.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-59c31dc0394e67b4.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-12dfc95f6cc5c718.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-25788244e66aa4dd.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-a2555dc705466322.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-4fb31eb476dcbad3.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-3b4c947f174e33d8.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-578729adbeaa40cb.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-a1d20fffbec35205.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-4a558f94516b8004.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-9e3834705b86145e.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d7bff0f0905a662c.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-cb1c5fe746ea4014.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-9ee320507356582a.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-66fd183b74835886.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/page-3272a064a01a9927.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-f281b7a7f6ef2529.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-d45a65f8b7124fcd.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-e9c1fe684dd19a66.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-b8322932fc6e34de.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-82c66d9af2290575.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/page-63c6752009c97b05.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/page-bb33d42ebc358aec.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-7e4c9379197d7214.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-38bf1e9a7001732b.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-2e5b752012389d56.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/{page-0a07363b130182a1.js → page-398c0faa173203f7.js} +1 -1
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-002f53a965b6445c.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-7f75997f61a26269.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-3b4c947f174e33d8.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-05631753294f23fb.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-edd700fd2cc3d7f8.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-105f83ecb4594365.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-5823e87d2017f19c.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/page-df3445b207ceceab.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-b51ca09566c03de7.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-8aacd5ded5dbac60.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-bae3365a0b3c6a8e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9ed52b48ff1aa7fd.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b6f8cad35fe00946.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6d25ceda500d2457.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-b6401a5f2c962fe8.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/ebf6cf5e.0d2f887b040e80fb.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/f09ec7d7-d29abe23edcbb193.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{ebc7d829.264a0bcb6c750b50.js → ffdc3a04.b9c23c1b28dd4a96.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-9322cb8a56ac081c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-2fbab294e49a1561.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f36729f56621a8f3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-2a62e450b47c6114.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-5e17f7b445f34d43.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-b4263e2190ea7adf.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +9 -2
  279. package/docs/goal-context/README.md +1 -0
  280. package/graphs/default-loop.yaml +20 -3
  281. package/graphs/document-loop.yaml +21 -2
  282. package/graphs/implement-loop.yaml +11 -0
  283. package/graphs/journey/SCENARIOS.md +33 -0
  284. package/graphs/journey/recipes.yaml +1 -0
  285. package/graphs/journey/ta-journey.yaml +84 -0
  286. package/graphs/journey/units/author/author.yaml +20 -0
  287. package/graphs/journey/units/author/recipes.yaml +2 -0
  288. package/graphs/journey/units/green/green.yaml +20 -0
  289. package/graphs/journey/units/green/recipes.yaml +2 -0
  290. package/graphs/journey/units/pr/pr.yaml +20 -0
  291. package/graphs/journey/units/pr/recipes.yaml +2 -0
  292. package/graphs/journey/units/remember/recipes.yaml +2 -0
  293. package/graphs/journey/units/remember/remember.yaml +20 -0
  294. package/graphs/operate-loop.yaml +21 -2
  295. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  296. package/graphs/release-rehearsal/recipes.yaml +1 -1
  297. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  298. package/graphs/research-loop.yaml +23 -2
  299. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  300. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  301. package/graphs/units/entry/entry.yaml +50 -0
  302. package/graphs/units/entry/recipes.yaml +14 -0
  303. package/graphs/units/harvest/harvest.yaml +25 -0
  304. package/graphs/units/harvest/recipes.yaml +4 -0
  305. package/graphs/units/land/land.yaml +45 -0
  306. package/graphs/units/land/recipes.yaml +3 -0
  307. package/graphs/units/recipes.yaml +7 -0
  308. package/graphs/units/recover.yaml +39 -0
  309. package/graphs/units/reflect/recipes.yaml +3 -0
  310. package/graphs/units/reflect/reflect.yaml +15 -0
  311. package/graphs/units/task-agent-recover-review.yaml +17 -0
  312. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  313. package/graphs/units/verbs/make-doc.yaml +34 -0
  314. package/graphs/units/verbs/recipes.yaml +33 -0
  315. package/graphs/units/verbs/verify.yaml +55 -0
  316. package/graphs/work/recipes.yaml +2 -0
  317. package/graphs/work/research-report.yaml +28 -0
  318. package/package.json +1 -1
  319. package/scripts/ci-typecheck-changed.ts +95 -17
  320. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  321. package/scripts/graph-harvest-unit.ts +22 -0
  322. package/scripts/graph-units/journey-stub.ts +6 -0
  323. package/scripts/graph-units/land-enqueue.ts +78 -0
  324. package/scripts/graph-units/recover-plan.ts +15 -0
  325. package/scripts/graph-units/reflect-node.ts +88 -0
  326. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  327. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  328. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  329. package/scripts/graph-units/verbs-envelope.ts +139 -0
  330. package/scripts/hq/standby-snapshot.ts +25 -0
  331. package/scripts/measure-si-task-cpu.ts +143 -0
  332. package/scripts/public-export.ts +43 -1
  333. package/scripts/ratchets/test-interference-patterns.allowlist.txt +0 -2
  334. package/scripts/ratchets/train-side-invariants.sh +45 -0
  335. package/scripts/release-loop/auto-approve-node.ts +30 -16
  336. package/scripts/release-loop/gate-closure.ts +5 -1
  337. package/scripts/release-loop/gate-diff.ts +1 -1
  338. package/scripts/release-loop/gate-node.ts +498 -31
  339. package/scripts/release-loop/gate-partial.ts +3 -3
  340. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  341. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  342. package/scripts/release-loop/gate-triage-node.ts +5 -2
  343. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  344. package/scripts/release-loop/known-issues-node.ts +77 -8
  345. package/scripts/release-loop/preflight.ts +93 -7
  346. package/scripts/release-loop/prepare-node.ts +102 -4
  347. package/scripts/release-loop/publish-node.ts +60 -9
  348. package/scripts/release-loop/resume-cap.ts +56 -0
  349. package/scripts/release-loop/resume-release.ts +114 -15
  350. package/scripts/release-loop/resume.ts +24 -1
  351. package/scripts/release-loop/tui-sim-node.ts +8 -2
  352. package/scripts/release-loop/unattended-release.ts +8 -2
  353. package/src/acp/core-turn-bridge.ts +36 -9
  354. package/src/acp/elanous-extensions.ts +3 -0
  355. package/src/acp/reasoning-thought-buffer.ts +45 -0
  356. package/src/acp/server.ts +3 -0
  357. package/src/acp/tool-trace.ts +186 -11
  358. package/src/agent/self-ambient-cache.ts +156 -0
  359. package/src/agent/self-ambient.ts +8 -1
  360. package/src/agent/task-notification.ts +5 -0
  361. package/src/agent-substrate/acp-reviewer.ts +52 -12
  362. package/src/agent-substrate/pr-reviewer.ts +3 -1
  363. package/src/agent-substrate/review-finding-key.ts +53 -0
  364. package/src/agent-substrate/self-review-cli.ts +126 -5
  365. package/src/ask-user-question/pending-questions.ts +1 -1
  366. package/src/ask-user-question/tool.ts +22 -0
  367. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  368. package/src/autopilot/pr-manager.ts +213 -46
  369. package/src/capture/frame-state-detect.ts +39 -0
  370. package/src/capture/tui-self-report.ts +134 -6
  371. package/src/chat/index.ts +61 -15
  372. package/src/chat/pickers/modal-runtime.ts +6 -0
  373. package/src/chat/pickers/modals.ts +8 -2
  374. package/src/chat/tool-render/dispatch.ts +62 -10
  375. package/src/cli/ask-bare.ts +1 -0
  376. package/src/cli/control-cli.ts +24 -7
  377. package/src/cli/guardian-cli.ts +10 -0
  378. package/src/cli/import-cli.ts +12 -0
  379. package/src/cli/light-entry-route.ts +35 -0
  380. package/src/cli/llm-detect-cli.ts +23 -1
  381. package/src/cli/log-event-names.ts +10 -0
  382. package/src/cli/msg-cli.ts +1 -0
  383. package/src/cli/pod-cli.ts +14 -3
  384. package/src/cli/pr-cli.ts +140 -41
  385. package/src/cli/pr-land-base-read.ts +36 -0
  386. package/src/cli/pr-land-heavy-remote.ts +81 -25
  387. package/src/cli/pr-land-overlap-evidence.ts +200 -18
  388. package/src/cli/pr-land-pod-shadow-job.ts +26 -3
  389. package/src/cli/pr-land-recovery.ts +64 -0
  390. package/src/cli/pr-land-refusal.ts +20 -5
  391. package/src/cli/pty-takeover-cli.ts +94 -19
  392. package/src/cli/release-cli.ts +120 -33
  393. package/src/cli/release-run-if-ready.ts +29 -28
  394. package/src/cli/release-single-flight.ts +178 -0
  395. package/src/cli/seat-cli.ts +37 -0
  396. package/src/cli/setup-cli.ts +40 -1
  397. package/src/cli/sim-cli.ts +18 -0
  398. package/src/cli/tasks-cli.ts +149 -5
  399. package/src/context-bus/ops-events.ts +6 -2
  400. package/src/control/control-status.ts +8 -3
  401. package/src/control-plane/ledger.ts +5 -3
  402. package/src/control-plane/server.ts +5 -3
  403. package/src/core-turn/run-core-turn.ts +1 -0
  404. package/src/core-turn/run-goal-loop.ts +21 -0
  405. package/src/core-turn/short-question.ts +5 -1
  406. package/src/core-turn/types.ts +3 -0
  407. package/src/dashboard/acp-active-model.ts +42 -1
  408. package/src/dashboard/background-jobs-status.ts +66 -0
  409. package/src/dashboard/index.ts +153 -111
  410. package/src/dashboard/input/agent-wake.ts +242 -0
  411. package/src/dashboard/input/chat-main-entry-runtime.ts +5 -0
  412. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  413. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  414. package/src/dashboard/input/external-input-host.ts +23 -9
  415. package/src/dashboard/input/mouse-wiring.ts +108 -11
  416. package/src/dashboard/input/seat-autowake.ts +56 -3
  417. package/src/dashboard/log-click-runtime.ts +118 -2
  418. package/src/dashboard/seat-boot-preamble.ts +1 -1
  419. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  420. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  421. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  422. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  423. package/src/dashboard/turn-preamble.ts +163 -41
  424. package/src/dashboard/turn-session-layers.ts +4 -2
  425. package/src/dashboard/turn-start-segments.ts +222 -0
  426. package/src/dashboard/turn-stream-formatter.ts +34 -1
  427. package/src/dashboard/turn-stream-runtime.ts +2 -0
  428. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  429. package/src/display/prompt-row-owner.ts +146 -0
  430. package/src/display/resize-listener.ts +33 -2
  431. package/src/domains/guardian-tick.ts +54 -2
  432. package/src/domains/outbound-alert.ts +3 -2
  433. package/src/extractors.ts +3 -1
  434. package/src/fold-stack.ts +4 -2
  435. package/src/git-fs/index.ts +263 -36
  436. package/src/git-fs/retry.ts +4 -0
  437. package/src/git-fs/runner.ts +2 -0
  438. package/src/graph-runner/runner.ts +114 -44
  439. package/src/grok/credential.ts +5 -0
  440. package/src/harness/gate-reserve.ts +87 -0
  441. package/src/harness/harness-cli-command.ts +39 -10
  442. package/src/harness/harness-incidents.ts +17 -0
  443. package/src/harness/harness-pod-dispatch.ts +38 -1
  444. package/src/harness/harness-queue.ts +15 -0
  445. package/src/harness/harness-salvage-cli.ts +14 -2
  446. package/src/index.ts +198 -12
  447. package/src/input/external-input-queue.ts +34 -9
  448. package/src/intake-plane/already-built-hint.ts +89 -0
  449. package/src/knowhow/pack.ts +199 -0
  450. package/src/light-cli.ts +95 -0
  451. package/src/llm/route-decision.ts +36 -0
  452. package/src/llm/tool-loop-steered-rejection.ts +8 -0
  453. package/src/llm-request-shape.ts +209 -0
  454. package/src/llm.ts +221 -276
  455. package/src/loops/budget.ts +95 -0
  456. package/src/loops/msg-wake.ts +8 -2
  457. package/src/loops/orchestrator/tick.ts +24 -2
  458. package/src/loops/orchestrator/traffic.ts +132 -1
  459. package/src/maturity/feature-maturity.ts +1 -1
  460. package/src/mss/logging/log-store.ts +4 -5
  461. package/src/mss/logging/render-categories.ts +5 -0
  462. package/src/nexus/api/graphs-api.ts +22 -3
  463. package/src/nexus/api/http-server.ts +1 -1
  464. package/src/nexus/api/ops-api.ts +12 -0
  465. package/src/oauth/claude-pty-maturity.ts +66 -0
  466. package/src/oauth/codex-access-mirror.ts +55 -0
  467. package/src/oauth/fallback-chain.ts +1 -1
  468. package/src/onboarding/first-run.ts +5 -3
  469. package/src/onboarding/non-interactive.ts +64 -13
  470. package/src/onboarding.ts +10 -2
  471. package/src/ops/overview-collect.ts +36 -1
  472. package/src/ops/overview.ts +70 -2
  473. package/src/pr-tool/census.ts +41 -8
  474. package/src/pr-tool/inflight-registry.ts +296 -0
  475. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  476. package/src/pty-shell/herdr-agent-report.ts +442 -0
  477. package/src/pty-shell/pty-control-ipc.ts +5 -5
  478. package/src/pty-shell/pty-manifest.ts +12 -3
  479. package/src/pty-shell/pty-write-outcome.ts +24 -6
  480. package/src/pty-shell/tui-run-state.ts +151 -6
  481. package/src/release-loop/checklist.ts +79 -5
  482. package/src/release-loop/feature-store.ts +19 -2
  483. package/src/release-loop/placement.ts +10 -3
  484. package/src/release-loop/rehearsal.ts +205 -25
  485. package/src/release-loop/rubric.ts +16 -2
  486. package/src/seat-loop/traffic-signal.ts +2 -1
  487. package/src/self-dev/ask-launch-flow.ts +13 -0
  488. package/src/self-dev/draft-residue.ts +243 -24
  489. package/src/self-dev/draft-sweep.ts +52 -3
  490. package/src/self-dev/graph-journey-nodes.ts +10 -6
  491. package/src/self-dev/graph-journey-route.ts +60 -6
  492. package/src/self-dev/orchestrate.ts +79 -3
  493. package/src/self-dev/run-supervisor.ts +107 -12
  494. package/src/self-dev/run-types.ts +5 -1
  495. package/src/self-dev/shard-plan.ts +11 -3
  496. package/src/self-dev/shard-run.ts +103 -10
  497. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  498. package/src/self-implement/follow-up-placement.ts +79 -0
  499. package/src/self-implement/gate-artifacts.ts +15 -4
  500. package/src/self-implement/gate-baseline.ts +145 -10
  501. package/src/self-implement/gate-cli.ts +7 -2
  502. package/src/self-implement/gate-remote.ts +35 -6
  503. package/src/self-implement/goal-author-identity.ts +66 -0
  504. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  505. package/src/self-implement/goal-author.ts +4 -120
  506. package/src/self-implement/graph-overlay-yaml.ts +17 -2
  507. package/src/self-implement/graph-unit-flatten.ts +103 -0
  508. package/src/self-implement/graph-unit-resolver.ts +107 -0
  509. package/src/self-implement/graph-yaml.ts +151 -1
  510. package/src/self-implement/headless-elanous-driver.ts +1 -0
  511. package/src/self-implement/host-regate.ts +36 -4
  512. package/src/self-implement/knowhow-pack.ts +103 -0
  513. package/src/self-implement/orchestrator.ts +109 -11
  514. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  515. package/src/self-implement/review-mustfix-class.ts +203 -0
  516. package/src/self-implement/run-ledger.ts +16 -14
  517. package/src/self-implement/run-stop.ts +8 -2
  518. package/src/self-implement/seams.ts +32 -1
  519. package/src/self-implement/stop-autoheal.ts +25 -1
  520. package/src/session/chat.ts +27 -0
  521. package/src/session-runtime/index.ts +22 -267
  522. package/src/session-runtime/retry-policy.ts +2 -1
  523. package/src/shell-runner/background-surface.ts +15 -5
  524. package/src/skills/tools/agent.ts +39 -6
  525. package/src/skills/tools/list-dir.ts +11 -0
  526. package/src/skills/tools/schedule-wakeup.ts +457 -0
  527. package/src/skills/tools/shell.ts +245 -3
  528. package/src/status/bar.ts +26 -0
  529. package/src/steward/digest-delivery.ts +118 -0
  530. package/src/steward/hold-hygiene.ts +120 -0
  531. package/src/steward/release-day.ts +7 -3
  532. package/src/steward/triage.ts +47 -4
  533. package/src/surface/shell-runner-boot.ts +5 -2
  534. package/src/task-agent/harvest-unit.ts +141 -0
  535. package/src/task-agent/live-moves.ts +98 -12
  536. package/src/task-agent/parent-host.ts +93 -3
  537. package/src/task-agent/postland-card.ts +80 -1
  538. package/src/task-agent/rejudge-on-head.ts +112 -26
  539. package/src/task-agent/repair-branch-cas.ts +4 -1
  540. package/src/task-agent/repair-cycle.ts +16 -3
  541. package/src/task-agent/run-identity.ts +4 -3
  542. package/src/task-agent/shadow.ts +12 -2
  543. package/src/task-agent/task-hand.ts +76 -5
  544. package/src/task-agent/work-order-build.ts +22 -0
  545. package/src/task-orchestrator/surfaces/pod-account-broker.ts +39 -3
  546. package/src/task-orchestrator/surfaces/pod-command-job.ts +67 -12
  547. package/src/task-orchestrator/surfaces/pod-lease.ts +98 -0
  548. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  549. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  550. package/src/task-orchestrator/surfaces/pod-pool.ts +76 -18
  551. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +10 -6
  552. package/src/task-orchestrator/surfaces/pod-source-receive.ts +54 -4
  553. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +548 -0
  554. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +389 -0
  555. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  556. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +158 -3
  557. package/src/task-orchestrator/surfaces/self-implement-pod.ts +230 -43
  558. package/src/task-orchestrator/surfaces/self-implement.ts +83 -2
  559. package/src/tool-runtime/truncation-store.ts +4 -0
  560. package/src/tui/chat/execution-badge.ts +5 -1
  561. package/src/tui/input-lag-probe.ts +230 -0
  562. package/src/tui-client/dashboard-session.ts +10 -1
  563. package/src/tui.ts +4 -0
  564. package/src/user-config/coercion.ts +36 -0
  565. package/src/user-config.ts +18 -41
  566. package/src/ux-sim/scenario.ts +314 -0
  567. package/src/version/packed-revision.json +1 -1
  568. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  571. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  572. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  573. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  577. package/apps/pwa/out/_next/static/chunks/1834-50625904996a8fa8.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  579. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  580. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  587. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  588. package/apps/pwa/out/_next/static/chunks/3267c0e6.d34854e7b3984a6e.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +0 -34
  591. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  595. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  599. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  600. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  602. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  605. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  610. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  612. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  619. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  620. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  622. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  627. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  628. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  635. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/botlab/page-2ebb8fd59b9461f9.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/setup/page-521ee23ac8c0abfa.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-149dc1caba411bb9.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  706. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  713. package/apps/pwa/out/_next/static/css/3f5fc6f96e2cf7b2.css +0 -1
  714. package/src/cli/g6a-registration-probe.ts +0 -16
  715. /package/apps/pwa/out/_next/static/{LSXfY0u9QtfDbejY0Ukf_ → L04y73dlwKeTW-GetaTF3}/_ssgManifest.js +0 -0
@@ -5,7 +5,7 @@ import { dirname, join, resolve } from 'node:path';
5
5
  import { runGitCommand } from '../git-fs/runner.js';
6
6
  import { debug } from '../debug/log.js';
7
7
  import { getPty, listPty, renamePty, requestPtyTakeover } from '../pty-shell/registry.js';
8
- import { describePtyRunState, readCheckoutHead, readCurrentInstallRecord, shortSha, type InstalledRecord, type PtyRunStateView } from '../pty-shell/tui-run-state.js';
8
+ import { describePtyRunState, describeTurnCell, formatTurnCell, ptyTurnViewOfRow, readCheckoutHead, readCurrentInstallRecord, shortSha, UNKNOWN_TURN_CELL, type InstalledRecord, type PtyRunStateView, type PtyTurnCell } from '../pty-shell/tui-run-state.js';
9
9
  import { getPtyManifest, isProcessAlive, listPtyManifest, listPtyManifestRows, listPtyManifestRowsAt, ptyManifestDbPath, readPtyManifestFrame, reapDeadPtyManifest, reapDeadPtyManifestAt, reapStalePtyManifest, removePtyManifest, PTY_MANIFEST_CLOSED_TTL_MS, PTY_MANIFEST_STALE_MS, type PtyManifestExternalReapResult, type PtyManifestRow } from '../pty-shell/pty-manifest.js';
10
10
  import { readPtyEventsAfter, readPtyEventsAfterAt, type PtyEventLogReadResult, type PtyEventRow } from '../pty-shell/pty-event-log.js';
11
11
  import { resolvePtyRef, type PtyRefItem } from '../pty-shell/pty-ref.js';
@@ -18,7 +18,7 @@ import { inspectControlInbox, type ControlInboxSnapshot } from '../harness/contr
18
18
  import { requestRemotePtyControl, type PtyControlAction, type PtyControlPayload, type PtyControlRequestOptions, type PtyControlResult } from '../pty-shell/pty-control-ipc.js';
19
19
  import { resolvePtySpecialKey } from '../pty-shell/pty-special-keys.js';
20
20
  import { encodeSgrMouse, mouseModeOffReason, type PtyMouseInput } from '../pty-shell/pty-mouse.js';
21
- import { resizePtyWithOutcome, writePtyWithOutcome } from '../pty-shell/pty-write-outcome.js';
21
+ import { resizePtyWithOutcome, writePtyWithOutcome, writePtyWithOutcomeDetail } from '../pty-shell/pty-write-outcome.js';
22
22
  import type { PtyControlTarget, PtyHandle } from '../pty-shell/registry.js';
23
23
  import { ptyEventLogTargets, ptyManifestTargets } from '../domains/fleet.js';
24
24
  import { loadRunLedger, resolveFederatedRunLedgerDirectories, type RunLedgerEntry } from '../self-implement/run-ledger.js';
@@ -27,7 +27,7 @@ import { isRunStatus } from '../self-implement/run-status-mapping.js';
27
27
  import { terminalTreeLabel } from '../pty-shell/terminal-tree.js';
28
28
  import { RemotesStore } from './remotes.js';
29
29
  import { bookmarkAttachDefaults } from './remote-resolve.js';
30
- import { classifyFrameState, type FrameState } from '../capture/frame-state-detect.js';
30
+ import { classifyFrameState, reconcileFrameStateWithTurn, type FrameState } from '../capture/frame-state-detect.js';
31
31
  import { installMissingTool, waitForPtyCompletion, type ToolInstallDeps, type ToolInstallResult } from '../agent-mission/tool-install.js';
32
32
 
33
33
  interface PtyTakeoverCommandResult { readonly exitCode: 0 | 1 | 2; readonly message: string; readonly notice?: string; }
@@ -1441,6 +1441,10 @@ interface PtyListJsonRow extends PtyWebAddress {
1441
1441
  * 그 값은 거의 항상 몇 초이고 「얼마나 오래 있었나」를 못 답한다.
1442
1442
  * ⚠️ `startedAt` 이 0(미상)이면 이 칸을 «비운다» — 「0분」과 「못 잼」은 다른 값이다. */
1443
1443
  readonly ageMs?: number;
1444
+ /** ⭐ H10 — TUI 가 스스로 적은 턴(화면 추정 아님) ⊕ 그 상태 경과 초. 턴 기록 없는 행·원격 행은 `state:'unknown'`. */
1445
+ readonly turn: PtyTurnCell;
1446
+ /** ⭐ H10 — 기동 판(실행판 sha) ⊕ 낡음. 판 기록 없는 행·판독 실패는 null. */
1447
+ readonly build: { readonly version: string; readonly sha: string; readonly source: string; readonly stale: boolean | null; readonly staleReason: string } | null;
1444
1448
  }
1445
1449
 
1446
1450
  function defaultRunTermination(runId: string, opts: { includeTest: boolean }, log: (event: string, data: Record<string, unknown>) => void): RunTermination {
@@ -1457,7 +1461,7 @@ function ptyAgeField(startedAt: number, now: number): { ageMs?: number } {
1457
1461
  return ageMs >= 0 ? { ageMs } : {};
1458
1462
  }
1459
1463
 
1460
- function ptyListJsonRow(row: PtyManifestRow, instance: string, sourceRoot: PtyManifestSourceRoot, deps: PtyTakeoverCommandDeps, opts: { includeTest: boolean }, pwa?: NexusPwaResolution): PtyListJsonRow {
1464
+ function ptyListJsonRow(row: PtyManifestRow, instance: string, sourceRoot: PtyManifestSourceRoot, deps: PtyTakeoverCommandDeps, opts: { includeTest: boolean }, pwa?: NexusPwaResolution, installed: () => InstalledRecord = () => deps.readInstalledBuild?.() ?? {}): PtyListJsonRow {
1461
1465
  // ⛔⭐ 리뷰 should-fix (2026-08-19): 기준 시각을 «한 번만» 읽는다.
1462
1466
  // 종전엔 proof(updatedAgeMs)와 ageMs 가 각각 `deps.now?.()` 를 불러, 한 행의 두 값이
1463
1467
  // ***«다른 순간»을 가리킬 수 있었다***. 두 값을 나란히 놓고 판정하는 것이 이 축의 용도인데
@@ -1498,9 +1502,56 @@ function ptyListJsonRow(row: PtyManifestRow, instance: string, sourceRoot: PtyMa
1498
1502
  runTerminationSource: resolution?.source ?? 'unknown',
1499
1503
  runStoreIo: resolution?.runStoreIo ?? 'not-checked',
1500
1504
  ownerRunUsage,
1505
+ ...ptyListRunFields(row, deps, observedAt, installed),
1501
1506
  };
1502
1507
  }
1503
1508
 
1509
+ /** `pty list --json` 의 턴·판 칸 — ⛔ 키는 «언제나» 싣는다(값으로만 갈린다 · 모르면 unknown/null).
1510
+ * ⭐ 턴은 행의 자기보고 값만 읽는다 — 판 판독(설치본·git)이 실패해도 기록된 턴은 버리지 않는다. */
1511
+ function ptyListRunFields(row: PtyManifestRow, deps: PtyTakeoverCommandDeps, observedAt: number, installed: () => InstalledRecord): Pick<PtyListJsonRow, 'turn' | 'build'> {
1512
+ const turn = describeTurnCell(ptyTurnViewOfRow(row), observedAt);
1513
+ try {
1514
+ if (!row.build) return { turn, build: null };
1515
+ // 판독 예외 계약: 판 sha 는 기록값이라 그대로 두고 낡음만 «모른다»(stale=null · unknown) ⊕ `list-build-read-failed` 관측.
1516
+ // 그 밖의 뜻밖 예외는 판을 null 로(아래 catch) — 어느 쪽이든 기록된 턴은 버리지 않는다.
1517
+ const run = describePtyRunState(row, {
1518
+ readInstalled: installed,
1519
+ readCheckoutHead: (codeRoot) => {
1520
+ try { return deps.readCheckoutHead?.(codeRoot); } catch (error) {
1521
+ deps.log('list-build-read-failed', { ptyId: row.id, source: 'checkout-head', error: error instanceof Error ? error.message : String(error) });
1522
+ return undefined;
1523
+ }
1524
+ },
1525
+ });
1526
+ return { turn, build: run.build ? { version: run.build.version, sha: run.build.sha, source: run.build.source, stale: run.stale, staleReason: run.staleReason } : null };
1527
+ } catch (error) {
1528
+ deps.log('list-build-read-failed', { ptyId: row.id, source: 'describe', error: error instanceof Error ? error.message : String(error) });
1529
+ return { turn, build: null };
1530
+ }
1531
+ }
1532
+
1533
+ /** 목록 한 번에 설치본 기록을 «한 번만» 읽는다. 예외는 «모른다»({}) ⊕ `list-build-read-failed`(목록당 한 줄) — 목록·턴 칸을 깨지 않는다. */
1534
+ function listInstalledReader(deps: PtyTakeoverCommandDeps): () => InstalledRecord {
1535
+ let once: InstalledRecord | undefined;
1536
+ return () => {
1537
+ if (once === undefined) {
1538
+ try { once = deps.readInstalledBuild?.() ?? {}; } catch (error) {
1539
+ once = {};
1540
+ deps.log('list-build-read-failed', { source: 'installed', error: error instanceof Error ? error.message : String(error) });
1541
+ }
1542
+ }
1543
+ return once;
1544
+ };
1545
+ }
1546
+
1547
+ /** 글 표의 판 칸 — 판독이 어떻게 실패해도 그 행(과 뒤따르는 턴 칸)을 깨지 않는다: 판 칸만 비우고 관측 한 줄. */
1548
+ function safeListRunColumn(row: PtyManifestRow | undefined, deps: PtyTakeoverCommandDeps, installed: () => InstalledRecord): string {
1549
+ try { return formatListRunColumn(row, deps, installed); } catch (error) {
1550
+ deps.log('list-build-read-failed', { ptyId: row?.id ?? '', source: 'run-column', error: error instanceof Error ? error.message : String(error) });
1551
+ return '';
1552
+ }
1553
+ }
1554
+
1504
1555
  function federatedManifestTargets(
1505
1556
  targets: readonly { name: string; dbPath: string }[],
1506
1557
  currentDbPath: string,
@@ -1771,6 +1822,9 @@ function remotePtyListJsonRow(row: RemoteTerminalListItem): PtyListJsonRow {
1771
1822
  runTerminationSource: 'unknown',
1772
1823
  runStoreIo: 'not-checked',
1773
1824
  ownerRunUsage: 'unknown',
1825
+ // 원격 응답은 턴·판을 안 싣는다 — «모른다»로(로컬과 같은 키).
1826
+ turn: UNKNOWN_TURN_CELL,
1827
+ build: null,
1774
1828
  };
1775
1829
  }
1776
1830
 
@@ -1893,9 +1947,11 @@ function runPtyListJson(deps: PtyTakeoverCommandDeps, opts: { all?: boolean; inc
1893
1947
  }
1894
1948
  // Keep the existing list contract: rows whose selected PTY/owner process is dead are not listable.
1895
1949
  const pwa = deps.resolveNexusPwa?.();
1950
+ // 설치본 기록은 목록 한 번에 한 번만 읽는다(행마다 다시 읽으면 I/O 와 행 사이 불일치). 실패는 «모른다» ⊕ 관측 한 줄.
1951
+ const installed = listInstalledReader(deps);
1896
1952
  const payload = rows
1897
1953
  .filter(({ row }) => row.alive && (row.ptyPid > 0 ? deps.isProcessAlive!(row.ptyPid) : deps.isProcessAlive!(row.ownerPid)))
1898
- .map(({ row, instance, sourceRoot }) => ptyListJsonRow(row, instance, sourceRoot, deps, { includeTest: opts.includeTest === true }, pwa));
1954
+ .map(({ row, instance, sourceRoot }) => ptyListJsonRow(row, instance, sourceRoot, deps, { includeTest: opts.includeTest === true }, pwa, installed));
1899
1955
  deps.log('list', { count: payload.length, federated: opts.all === true, includeTest: opts.includeTest === true, json: true });
1900
1956
  return { exitCode: 0, message: JSON.stringify(payload, null, 2), ...(payload.length === 0 ? { notice: ptyListEmptyNotice(opts) } : {}) };
1901
1957
  }
@@ -1966,12 +2022,15 @@ export function runPtyList(
1966
2022
  const pwa = deps.resolveNexusPwa?.();
1967
2023
  // 판 칸(맨 끝) — 설치본 기록은 목록 한 번에 한 번만 읽는다.
1968
2024
  // 설치본 판독기가 없는 구성(시험 deps)은 이 칸을 안 낸다 — 기계마다 다른 값이 목록에 새지 않게.
1969
- const manifestRowById = new Map((deps.readInstalledBuild ? deps.listManifestRows?.() ?? [] : []).map((row) => [row.id, row] as const));
1970
- let installedOnce: InstalledRecord | undefined;
1971
- const installed = (): InstalledRecord => (installedOnce ??= deps.readInstalledBuild?.() ?? {});
2025
+ // ⭐ H10 턴 칸은 판독기와 «무관하게» TUI ref 마다 낸다(기계마다 다른 값이 아니다) — 행을 못 얻으면 `turn=?`.
2026
+ let manifestRows: readonly PtyManifestRow[] = [];
2027
+ try { manifestRows = deps.listManifestRows?.() ?? []; } catch { manifestRows = []; }
2028
+ const manifestRowById = new Map(manifestRows.map((row) => [row.id, row] as const));
2029
+ const listedAt = deps.now?.() ?? Date.now();
2030
+ const installed = listInstalledReader(deps);
1972
2031
  const rendered = refs.map((ref) => {
1973
2032
  const provenance = (deps.resolveWorktreeProvenance ?? resolvePtyWorktreeProvenance)(ref.workdir);
1974
- return { known: ptyPurposeKnown(provenance, ref.purpose), line: `${ref.id}\t${ref.kind}\t${ref.nickname ?? '-'}\t${ref.source}\t${ref.alive ? 'alive' : 'dead'}\t${ref.mode ?? '?'}\t${ref.workdir ?? '-'}\t${ref.runId ?? '-'}${ownerRunUsageById.has(ref.id) ? `\t${ownerRunUsageById.get(ref.id)}` : ''}\t${formatTerminalOrigin(ref)}\t${formatPtyPurpose(provenance, ref.purpose)}${pwa ? `\t${formatPtyWebAddress(ptyWebAddress(ref.id, pwa))}` : ''}${formatListRunColumn(manifestRowById.get(ref.id), deps, installed)}` };
2033
+ return { known: ptyPurposeKnown(provenance, ref.purpose), line: `${ref.id}\t${ref.kind}\t${ref.nickname ?? '-'}\t${ref.source}\t${ref.alive ? 'alive' : 'dead'}\t${ref.mode ?? '?'}\t${ref.workdir ?? '-'}\t${ref.runId ?? '-'}${ownerRunUsageById.has(ref.id) ? `\t${ownerRunUsageById.get(ref.id)}` : ''}\t${formatTerminalOrigin(ref)}\t${formatPtyPurpose(provenance, ref.purpose)}${pwa ? `\t${formatPtyWebAddress(ptyWebAddress(ref.id, pwa))}` : ''}${safeListRunColumn(manifestRowById.get(ref.id), deps, installed)}${formatListTurnColumn(ref.kind, manifestRowById.get(ref.id), listedAt)}` };
1975
2034
  });
1976
2035
  return {
1977
2036
  exitCode: 0,
@@ -2015,12 +2074,13 @@ async function inject(ref: string, action: 'input-text' | 'input-key', chars: st
2015
2074
  if (!handle) return mapResult(action, id, await deps.requestRemote(id, action, { chars }, { actor }), deps, observed);
2016
2075
  const resolved = localActor(id, actor, deps);
2017
2076
  if (typeof resolved !== 'string') return mapResult(action, id, { status: 'denied', reason: resolved.reason }, deps, observed);
2018
- const outcome = writePtyWithOutcome(handle, chars, resolved);
2019
- return mapResult(action, id, outcome === 'success'
2077
+ const outcome = writePtyWithOutcomeDetail(handle, chars, resolved);
2078
+ const control: PtyControlResult = outcome.status === 'success'
2020
2079
  ? { status: 'success' }
2021
- : outcome === 'denied'
2080
+ : outcome.status === 'denied'
2022
2081
  ? { status: 'denied', reason: 'write-arbiter' }
2023
- : { status: 'write-failed', reason: 'adapter-write' }, deps, observed);
2082
+ : { status: 'write-failed', reason: outcome.reason ?? 'adapter-write' };
2083
+ return mapResult(action, id, control, deps, observed);
2024
2084
  }
2025
2085
  interface PtyScreenAcquisition {
2026
2086
  readonly id: string;
@@ -2067,24 +2127,30 @@ export async function runPtyState(ref: string, deps: PtyTakeoverCommandDeps = li
2067
2127
  if (run.turn === 'unknown' && run.build === null) return { exitCode: 1, message: formatSnapshotResult(acquired.id, acquired.control) };
2068
2128
  const screenUnavailable = acquired.control.reason ?? acquired.control.status;
2069
2129
  deps.log('state-screen-unavailable', { ptyId: acquired.id, reason: screenUnavailable, turn: run.turn });
2070
- return formatPtyStateResult(acquired.id, { state: 'unknown', label: null }, run, deps.now?.() ?? Date.now(), json, screenUnavailable);
2130
+ return formatPtyStateResult(acquired.id, { state: 'unknown', label: null }, run, deps.now?.() ?? Date.now(), json, deps, screenUnavailable);
2071
2131
  }
2072
2132
  const verdict = classifyFrameState(acquired.control.screen ?? '');
2073
2133
  const at = deps.now?.() ?? Date.now();
2074
2134
  if (run.turn === 'unknown' || run.stale === null) deps.log('state-run-unknown', { ptyId: acquired.id, turn: run.turn, staleReason: run.staleReason, hasBuild: run.build !== null });
2075
- return formatPtyStateResult(acquired.id, { state: verdict.state, label: verdict.matchedLabel }, run, at, json);
2135
+ return formatPtyStateResult(acquired.id, { state: verdict.state, label: verdict.matchedLabel }, run, at, json, deps);
2076
2136
  }
2077
2137
 
2078
- function formatPtyStateResult(id: string, screen: { state: string; label?: string | null }, run: PtyRunStateView, at: number, json: boolean, screenUnavailable?: string): PtyTakeoverCommandResult {
2138
+ // ⭐ H10 조각 1 — `state` 는 «하나»다: TUI 가 스스로 적은 턴이 있으면 그것이 바쁜가/한가한가를 정하고(`stateSource=turn`),
2139
+ // 화면 추정은 턴을 모를 때·턴과 모순 없는 더 구체적인 상태(blocked·waiting·done)일 때만 쓴다(`stateSource=screen`).
2140
+ // 화면 원값은 `screenState`(JSON) · `guess=`(글, 갈렸을 때만)로 남긴다 — 둘이 갈린 순간은 `state-reconciled` 관측.
2141
+ function formatPtyStateResult(id: string, screen: { state: FrameState; label?: string | null }, run: PtyRunStateView, at: number, json: boolean, deps: PtyTakeoverCommandDeps, screenUnavailable?: string): PtyTakeoverCommandResult {
2142
+ const reconciled = reconcileFrameStateWithTurn(screen.state, run.turn);
2143
+ if (reconciled.overridden) deps.log('state-reconciled', { ptyId: id, turn: run.turn, screenState: reconciled.screenState, label: screen.label ?? null, state: reconciled.state });
2144
+ const guess = reconciled.screenState !== reconciled.state && !screenUnavailable ? ` guess=${reconciled.screenState}` : '';
2079
2145
  return { exitCode: 0, message: json
2080
2146
  ? JSON.stringify({
2081
- id, state: screen.state, label: screen.label, at,
2147
+ id, state: reconciled.state, stateSource: reconciled.source, screenState: reconciled.screenState, label: screen.label, at,
2082
2148
  ...(screenUnavailable ? { screenUnavailable } : {}),
2083
2149
  turn: run.turn, ...(run.turnAt !== undefined ? { turnAt: run.turnAt } : {}),
2084
2150
  build: run.build ? { version: run.build.version, sha: run.build.sha, source: run.build.source } : null,
2085
2151
  installed: run.installed, stale: run.stale, staleReason: run.staleReason,
2086
2152
  })
2087
- : `pty state: ${id} state=${screen.state} label=${screen.label ?? '-'}${screenUnavailable ? ` screen=unavailable(${screenUnavailable})` : ''} turn=${run.turn} build=${formatRunBuild(run)} installed=${shortSha(run.installed)} stale=${run.stale ?? 'unknown'}${run.stale === null ? '' : ` (${run.staleReason})`}` };
2153
+ : `pty state: ${id} state=${reconciled.state} source=${reconciled.source}${guess} label=${screen.label ?? '-'}${screenUnavailable ? ` screen=unavailable(${screenUnavailable})` : ''} turn=${run.turn} build=${formatRunBuild(run)} installed=${shortSha(run.installed)} stale=${run.stale ?? 'unknown'}${run.stale === null ? '' : ` (${run.staleReason})`}` };
2088
2154
  }
2089
2155
 
2090
2156
  function ptyRunStateFor(id: string, deps: PtyTakeoverCommandDeps): PtyRunStateView {
@@ -2103,7 +2169,8 @@ function formatRunBuild(run: PtyRunStateView): string {
2103
2169
 
2104
2170
  /** `pty list` 한 칸 — 판을 적는 행(TUI)만. `run=<sha>` · 낡았으면 `,stale` · 옛 행 추정은 `run=?,stale`. */
2105
2171
  function formatListRunColumn(row: PtyManifestRow | undefined, deps: PtyTakeoverCommandDeps, installed: () => InstalledRecord): string {
2106
- if (!row || (!row.build && row.kind !== 'tui')) return '';
2172
+ // 설치본 판독기가 없는 구성(시험 deps)은 이 칸을 안 낸다 — 기계마다 다른 값이 목록에 새지 않게.
2173
+ if (!deps.readInstalledBuild || !row || (!row.build && row.kind !== 'tui')) return '';
2107
2174
  const run = describePtyRunState(row, {
2108
2175
  readInstalled: installed,
2109
2176
  ...(deps.readCheckoutHead ? { readCheckoutHead: deps.readCheckoutHead } : {}),
@@ -2112,6 +2179,14 @@ function formatListRunColumn(row: PtyManifestRow | undefined, deps: PtyTakeoverC
2112
2179
  return `\trun=${run.build?.sha ? shortSha(run.build.sha) : '?'}${run.stale === true ? ',stale' : ''}`;
2113
2180
  }
2114
2181
 
2182
+ /** ⭐ H10 «턴 칸» — ref 가 TUI 면 «언제나» 낸다: `turn=busy,42s` · `turn=idle,300s` · 행 없음·종류 불일치·기록 없음 `turn=?`.
2183
+ * OP·TF 가 화면(«Streaming…/완료»)을 긁지 않고 «지금 턴 중인가·얼마나 됐나»를 읽는다. 턴은 자기보고 값만 쓴다(설치본·git 무관). */
2184
+ function formatListTurnColumn(refKind: string, row: PtyManifestRow | undefined, now: number): string {
2185
+ if (refKind !== 'tui') return '';
2186
+ if (!row || row.kind !== 'tui') return '\tturn=?';
2187
+ return `\tturn=${formatTurnCell(describeTurnCell(ptyTurnViewOfRow(row), now))}`;
2188
+ }
2189
+
2115
2190
  export async function runPtyWait(ref: string, until: string, options: { readonly timeoutMs?: number; readonly pollMs?: number } = {}, deps: PtyTakeoverCommandDeps = liveDeps): Promise<PtyTakeoverCommandResult> {
2116
2191
  if (!WAITABLE_FRAME_STATES.includes(until as Exclude<FrameState, 'unknown'>)) return { exitCode: 2, message: `pty wait: --until must be one of ${WAITABLE_FRAME_STATES.join(', ')} (got ${until})` };
2117
2192
  const target = until as Exclude<FrameState, 'unknown'>;
@@ -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
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)
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 커밋(판 커밋이 공개본 커밋이 된다) ·
@@ -28,13 +28,13 @@ 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
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';
31
+ import { addItem, cellsReferencingDoc, claimItem, decodeClaimHistoryEntry, devVersion, inspectChecklistTargetPaths, lintDocRefs, listChecklist, normalizeRefs, noteDispatchSkip, ownerMatches, parseOwner, parityGap, refRoots, removeItem, renderRefsStatus, seedFromRoadmap, setItem, summarizeChecklist, 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
33
  import { evidencePlan, landedButYellow, type MergedChecklistPr } 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 } 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';
@@ -491,13 +492,33 @@ async function jsonAction<T>(json: boolean | undefined, body: (log: (l: string)
491
492
  }
492
493
  }
493
494
 
494
- function warnChecklistTargetPaths(input: { title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind }): void {
495
+ function warnChecklistTargetPaths(input: { title: string; evidence?: string; refs?: readonly string[]; dispatchKind?: ChecklistDispatchKind }, strict = false): void {
495
496
  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;
497
+ const objectTypeAtMain = (path: string): 'blob' | 'tree' | 'commit' | 'blocked-blob' | 'blocked-gitlink' | 'unavailable' | null => {
498
+ if (path.startsWith('/') || path.split('/').includes('..')) return null;
499
+ const segments = path.split('/');
500
+ for (let length = 1; length < segments.length; length++) {
501
+ const ancestor = segments.slice(0, length).join('/');
502
+ const lookup = spawnSync('git', ['cat-file', '-t', `origin/main:${ancestor}`], { cwd, timeout: 5_000, encoding: 'utf8' });
503
+ if (lookup.status === 0) {
504
+ if (lookup.stdout.trim() === 'blob') return 'blocked-blob';
505
+ if (lookup.stdout.trim() === 'commit') return 'blocked-gitlink';
506
+ if (lookup.stdout.trim() !== 'tree') return 'unavailable';
507
+ continue;
508
+ }
509
+ const missing = spawnSync('git', ['ls-tree', 'origin/main', '--', ancestor], { cwd, timeout: 5_000, encoding: 'utf8' });
510
+ return missing.status === 0 && missing.stdout.trim() === '' ? null : 'unavailable';
511
+ }
512
+ const result = spawnSync('git', ['cat-file', '-t', `origin/main:${path}`], { cwd, timeout: 5_000, encoding: 'utf8' });
513
+ const type = result.status === 0 ? result.stdout.trim() : '';
514
+ if (type === 'blob' || type === 'tree' || type === 'commit') return type;
515
+ if (result.status === 0) return 'unavailable';
516
+ // cat-file also fails for a genuinely new path. ls-tree distinguishes that
517
+ // from a missing ref or another Git read failure before --strict accepts 신설:.
518
+ const probe = spawnSync('git', ['ls-tree', 'origin/main', '--', path], { cwd, timeout: 5_000, encoding: 'utf8' });
519
+ return probe.status === 0 && probe.stdout.trim() === '' ? null : 'unavailable';
500
520
  };
521
+ const existsAtMain = (path: string): boolean => objectTypeAtMain(path) === 'blob';
501
522
  const mergedPrFiles = (number: number): string[] => {
502
523
  const result = spawnSync('gh', ['pr', 'view', String(number), '--json', 'state,files'], { cwd, encoding: 'utf8', timeout: 10_000 });
503
524
  if (result.status !== 0) return [];
@@ -506,7 +527,8 @@ function warnChecklistTargetPaths(input: { title: string; evidence?: string; ref
506
527
  return pr.state === 'MERGED' ? (pr.files ?? []).map((file) => file.path).filter((path): path is string => typeof path === 'string') : [];
507
528
  } catch { return []; }
508
529
  };
509
- const report = inspectChecklistTargetPaths(input, { existsAtMain, mergedPrFiles });
530
+ const report = inspectChecklistTargetPaths(input, { existsAtMain, objectTypeAtMain, mergedPrFiles });
531
+ if (strict && report.warnings.length) throw new CliUserError(`칸 대상 경로/완료 경계 검사: ${report.warnings.join(' · ')}`, '문면을 고치거나 --strict 없이 경고로 저장한다');
510
532
  for (const warning of report.warnings) {
511
533
  console.error(`⚠ 대상 경로: ${warning}${report.candidates.length ? ` · 후보: ${report.candidates.join(' · ')}` : ''}`);
512
534
  debug.log('release.checklist', 'target-path-warning', { warning, candidates: report.candidates });
@@ -713,9 +735,9 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
713
735
  for (const item of readRubricItems(version, releaseLedgerRoot())) {
714
736
  if (item.priority !== 'P0' && item.priority !== 'P1') continue;
715
737
  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; }
738
+ const s = parseRubricS(item.evidence ?? '') ?? parseRubric(item.title)?.S ?? parseRubricS(item.title);
739
+ if (s === null) group.missing++;
740
+ else { group.s[s as 0 | 1 | 2 | 3]++; group.total += s; }
719
741
  }
720
742
  const result = { version, byPriority, total: byPriority.P0.total + byPriority.P1.total, missing: byPriority.P0.missing + byPriority.P1.missing };
721
743
  if (opts.json) await writeStdoutJson(`${JSON.stringify(result)}\n`);
@@ -858,7 +880,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
858
880
  if (opts.applyEvidence && !opts.dryRun && !mayWrite(cmd)) return;
859
881
  const snapshots = opts.open ? openSnapshots : [(landedDeps.checklist ?? listChecklist)(context(cmd).version)];
860
882
  const now = (landedDeps.now ?? (() => new Date()))();
861
- // --version 도 --open 과 같은 판 전체 최좌 수정일로 병합 PR 을 찾는다 — 선택 판 칸의 updatedAt 에 묶이면 그보다 오래 전에 병합된 PR 을 놓친다(LBY-VERSION-OPEN-MISMATCH · OPT #4059).
883
+ // --version 도 --open 과 같은 판 전체 최초 수정일로 병합 PR 을 찾는다 — 선택 판 칸의 updatedAt 에 묶이면 그보다 오래 전에 병합된 PR 을 놓친다(LBY-VERSION-OPEN-MISMATCH · OPT #4059).
862
884
  const sinceSnapshots = opts.open ? snapshots : [...openSnapshots, ...snapshots];
863
885
  const updated = sinceSnapshots.flatMap(({ items }) => items
864
886
  .filter((item) => (item.status === 'yellow' || item.status === 'red') && (opts.owner === undefined || ownerMatches(item.owner, opts.owner)))
@@ -908,13 +930,14 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
908
930
  .option('--ceo-minutes <minutes>', '대표 손 분량(분)').option('--ceo-date <date>', '대표 손 날짜 YYYY-MM-DD (없으면 판 착지일 KST)')
909
931
  .option('--accelerator', '가속 등급 — 다른 칸의 처리량을 올리는 칸(자율성·효율성·동시성). 생략하면 등급 없음')
910
932
  .option('--allow-duplicate-id', '다른 판에 같은 id 가 있어도 경고 후 추가')
933
+ .option('--strict', '대상 경로·완료 경계 경고가 있으면 저장 전 거부')
911
934
  .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) => {
935
+ .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
936
  const { version, json } = context(cmd);
914
937
  if (!mayWrite(cmd)) return;
915
938
  const dispatchKind = opts.kind && !['screen', 'postpub'].includes(opts.kind) ? opts.kind as ChecklistDispatchKind : undefined;
939
+ warnChecklistTargetPaths({ title, refs: opts.ref, dispatchKind }, opts.strict);
916
940
  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
941
  if (json) console.log(JSON.stringify(data)); else console.log(`✅ ${id} 추가`);
919
942
  });
920
943
  withContext(checklist.command('set <id>').description('칸 상태·근거·담당·처분 갱신'))
@@ -977,15 +1000,26 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
977
1000
  else features.move(id, from, to, actor(), undefined, undefined, opts.reason);
978
1001
  if (json) console.log(JSON.stringify(listChecklist(to))); else console.log(`✅ ${id} ${from} → ${to}`);
979
1002
  });
980
- withContext(checklist.command('retitle <id> <title>').description('칸 제목 수정')).action((id: string, title: string, _opts: unknown, cmd: Command) => {
1003
+ withContext(checklist.command('retitle <id> <title>').description('칸 제목 수정')).option('--strict', '대상 경로·완료 경계 경고가 있으면 저장 전 거부').action((id: string, title: string, opts: { strict?: boolean }, cmd: Command) => {
981
1004
  const { version, json } = context(cmd);
982
1005
  if (!mayWrite(cmd)) return;
983
1006
  const snapshot = listChecklist(version);
984
- features.retitle(id, title, actor(), snapshot.released, snapshot.dev);
985
1007
  const item = snapshot.items.find((entry) => entry.id === id);
986
- warnChecklistTargetPaths({ title, evidence: item?.evidence, refs: item?.refs, dispatchKind: item?.dispatchKind });
1008
+ if (!opts.strict) warnChecklistTargetPaths({ title, evidence: item?.evidence, refs: item?.refs, dispatchKind: item?.dispatchKind });
1009
+ features.retitle(id, title, actor(), snapshot.released, snapshot.dev, opts.strict
1010
+ ? (affected) => warnChecklistTargetPaths({ title, evidence: affected.evidence, refs: affected.refs, dispatchKind: affected.dispatchKind }, true)
1011
+ : undefined);
987
1012
  if (json) console.log(JSON.stringify(listChecklist(version))); else console.log(`✅ ${id} 제목 수정`);
988
1013
  });
1014
+ withContext(checklist.command('skip-note <id> <reason>').description('디스패처 건너뜀 사유를 칸 근거에 중복 없이 기록'))
1015
+ .requiredOption('--expected-title <title>', '검사한 칸 제목; 바뀐 제목이면 기록하지 않는다')
1016
+ .requiredOption('--by <actor>', '실제 기록 주체(디스패처 자리)')
1017
+ .action((id: string, reason: string, opts: { expectedTitle: string; by: string }, cmd: Command) => {
1018
+ const { version, json } = context(cmd);
1019
+ if (!mayWrite(cmd)) return;
1020
+ const data = noteDispatchSkip(version, id, reason, opts.expectedTitle, opts.by);
1021
+ if (json) console.log(JSON.stringify(data)); else console.log(`✅ ${id} 건너뜀 근거 확인`);
1022
+ });
989
1023
  const evidence = checklist.command('evidence').description('칸의 PR·커밋 근거');
990
1024
  withContext(evidence.command('add <id> <ref>').description('근거 참조 추가')).action((id: string, ref: string, _opts: unknown, cmd: Command) => {
991
1025
  const { version, json } = context(cmd);
@@ -1082,7 +1116,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1082
1116
  .action(async (o: { version: string; base: string; pick: string[]; append?: boolean; dryRun?: boolean; json?: boolean }) => {
1083
1117
  await jsonAction(o.json, async (log) => cutReleaseBranch({ ...o, log }), () => true);
1084
1118
  });
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> => {
1119
+ 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
1120
  // Only the rc rehearsal channel is operated for now (alpha/beta stay valid version shapes, not run options).
1087
1121
  if (o.prerelease !== undefined && o.prerelease !== 'rc') {
1088
1122
  const message = `--prerelease supports rc only: ${o.prerelease}`;
@@ -1099,6 +1133,18 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1099
1133
  process.exitCode = 1;
1100
1134
  return false;
1101
1135
  }
1136
+ const ledgerRoot = releaseRunDeps.ledgerRoot ?? releaseLedgerRoot();
1137
+ if (!o.dryRun && !o.forceNew) {
1138
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1139
+ if (active) {
1140
+ const error = `release run already running: ${o.version} runId=${active.runId} pid=${active.pid} startedAt=${active.startedAt} (--force-new to bypass)`;
1141
+ debug.log('release.run', 'already-running', { version: o.version, ...active });
1142
+ if (o.json) await writeStdoutJson(`${JSON.stringify({ ok: false, reason: 'already-running', error, ...active })}\n`);
1143
+ else console.error(`⛔ ${error}`);
1144
+ process.exitCode = 1;
1145
+ return false;
1146
+ }
1147
+ }
1102
1148
  const prerelease = o.prerelease as PrereleaseKind | undefined;
1103
1149
  if (!o.dryRun) {
1104
1150
  try {
@@ -1130,10 +1176,20 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1130
1176
  try {
1131
1177
  const outcome = await runReleaseIfReady(o.version, {
1132
1178
  ledgerRoot: releaseRunDeps.ledgerRoot,
1179
+ forceNew: o.forceNew,
1133
1180
  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),
1181
+ 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
1182
  });
1136
1183
  if (outcome.skipped) {
1184
+ if (outcome.reason === 'already-running') {
1185
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1186
+ const lock = readReleaseRunLock(o.version, ledgerRoot);
1187
+ 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)`;
1188
+ if (o.json) await writeStdoutJson(`${JSON.stringify({ ok: false, reason: 'already-running', error, ...(active ?? {}) })}\n`);
1189
+ else console.error(`⛔ ${error}`);
1190
+ process.exitCode = 1;
1191
+ return false;
1192
+ }
1137
1193
  if (o.json) await writeStdoutJson(`${JSON.stringify(outcome)}\n`);
1138
1194
  else logRun(`· 준비 안 됨 ${o.version} · ${outcome.reason} · ${outcome.detail}`);
1139
1195
  return { deferred: true, reason: outcome.reason };
@@ -1159,7 +1215,20 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1159
1215
  }
1160
1216
  }
1161
1217
  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);
1218
+ 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);
1219
+ const forceRun = () => {
1220
+ const atStart = releaseReadiness(o.version, { ledgerRoot, checklist: releaseRunDeps.checklist, isPidAlive: () => false });
1221
+ if (!atStart.ready) throw new Error(`release run --force-new not ready after claim: ${atStart.reason}`);
1222
+ return run();
1223
+ };
1224
+ let result: Awaited<ReturnType<typeof runUnattendedRelease>>;
1225
+ try { result = o.dryRun ? await run() : o.forceNew ? await withForceReleaseRunMarker(o.version, ledgerRoot, forceRun) : await withDirectReleaseRunLock(o.version, ledgerRoot, run); }
1226
+ catch (error) {
1227
+ if (!(error instanceof ReleaseRunClaimConflict)) throw error;
1228
+ const active = findActiveReleaseRun(o.version, ledgerRoot) ?? readActiveForceReleaseRun(o.version, ledgerRoot);
1229
+ const lock = readReleaseRunLock(o.version, ledgerRoot);
1230
+ 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)`);
1231
+ }
1163
1232
  log(`${result.dryRun ? '· 드라이런' : '▶ 릴리스 루프'} ${result.input.version} · 입력 ${JSON.stringify(result.input)}`);
1164
1233
  return result;
1165
1234
  }, (r) => r.dryRun || r.state?.status === 'done' || r.state?.status === 'awaiting-approval');
@@ -1174,12 +1243,13 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1174
1243
  .option('--if-ready', '준비되지 않았으면 사유를 출력하고 성공으로 건너뛴다')
1175
1244
  .option('--publish-at <iso>', '승인·선행 노드 통과 뒤 지정 시각까지 발행 대기(오프셋 포함 ISO 시각)')
1176
1245
  .option('--force-freeze', '동결 중 게이트·발행 강행(관측 기록) — 가지 컷은 동결이 필요 없다 · 동결은 비상 스위치로 남는다')
1246
+ .option('--force-new', '같은 판의 살아 있는 릴리스 런을 확인한 뒤에도 새 런을 명시적으로 시작')
1177
1247
  .option('--gate-executor <pod|host>', 'gate 노드 실행기(기본 pod) — host 는 Pod 대신 SSH 호스트의 깨끗한 클론에서 같은 판정(면제 아님)')
1178
1248
  .option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 release.loop.gateRemote)')
1179
1249
  .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); });
1250
+ .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
1251
  release.command('preflight')
1182
- .description('컷 30분 전 사전 점검(읽기 전용) — 체크리스트 게이트 모의 · 발행 뒤 칸 · run --dry-run 입력 · 동결 · 일정/게이트 실측. ⛔ 있으면 exit 1')
1252
+ .description('컷 전 사전 점검(읽기 전용) — 체크리스트·런 입력·동결·일정 + 컷 − 60분 origin/main export(자동 예약 없음). ⛔ 있으면 exit 1')
1183
1253
  .requiredOption('--version <v>', '점검할 판(x.y.z)')
1184
1254
  .option('--publish-at <iso>', '계획 발행 시각(기본: 컷 뒤 첫 07·18시 KST)')
1185
1255
  .option('--json', '결과 한 줄 JSON(stdout)')
@@ -1229,8 +1299,11 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1229
1299
  .option('--accepted-regressions <json>', '알려진 문제 추가 입력 JSON 배열 [{"id":"…","note":"…"}]')
1230
1300
  .option('--gate-executor <pod|host>', '다시 도는 gate 의 실행기 전환(--from gate 이전만) — 런 입력에 기록 · 면제 아님')
1231
1301
  .option('--gate-host <ssh-host>', '--gate-executor host 의 SSH 호스트(기본 저장된 런 입력 gateRemote)')
1302
+ .option('--gate-pod-pool <pool>', '다시 도는 gate 의 Pod 풀을 전환(--from gate 이전만) — 런 입력에 기록')
1303
+ .option('--command-root <path>', '노드 명령을 실행할 컷 tip checkout(생략 시 현재 폴더)')
1304
+ .option('--dry-run', '재개 preflight만 수행하고 런·상태 원장·시도 횟수는 변경하지 않는다')
1232
1305
  .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 }) => {
1306
+ .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
1307
  await jsonAction(o.json, async (log) => {
1235
1308
  let acceptedRegressions: AcceptedRegression[] | undefined;
1236
1309
  if (o.acceptedRegressions !== undefined) {
@@ -1241,21 +1314,34 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1241
1314
  throw new Error('acceptedRegressions must be an array of {id, note}');
1242
1315
  }
1243
1316
  }
1244
- const result = await resumeReleaseRun({ runId: o.run, from: o.from, partial: o.partial,
1317
+ const resumeOptions = { runId: o.run, from: o.from, partial: o.partial, commandRoot: o.commandRoot,
1245
1318
  ...(o.waive === undefined ? {} : { waive: o.waive }),
1246
1319
  ...(o.reason === undefined ? {} : { reason: o.reason }),
1247
1320
  ...(o.acceptedRegressions === undefined ? {} : { acceptedRegressions }),
1248
1321
  ...(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}` : ''} (런 입력에 기록 · 면제 아님)`);
1322
+ ...(o.gateHost === undefined ? {} : { gateHost: o.gateHost }),
1323
+ ...(o.gatePodPool === undefined ? {} : { gatePodPool: o.gatePodPool }) };
1324
+ if (o.dryRun) {
1325
+ const plan = await planResumeReleaseRun(resumeOptions, { onSource: log });
1326
+ const gate = plan.gatePlan.mode === 'not-run' ? 'gate 실행 없음'
1327
+ : plan.gatePlan.mode === 'partial' ? `부분 gate 계획 ${plan.partial.requested && plan.partial.applied ? `${plan.partial.files}파일` : '미상'}`
1328
+ : `전체 gate${plan.gatePlan.reason ? ` (${plan.gatePlan.reason})` : ''}`;
1329
+ 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} · 실행·원장 변경 없음`);
1330
+ return plan;
1331
+ }
1332
+ const result = await resumeReleaseRun(resumeOptions, { onSource: log });
1333
+ const executorOverride = [...(result.state.inputOverrides ?? [])].reverse().find((item) => item.kind === 'gate-executor');
1334
+ const poolOverride = [...(result.state.inputOverrides ?? [])].reverse().find((item) => item.kind === 'gate-pod-pool');
1335
+ if (o.gateExecutor !== undefined && executorOverride?.kind === 'gate-executor') log(`⇄ gate 실행기 ${executorOverride.set.gateExecutor}${executorOverride.set.gateRemote ? ` @ ${executorOverride.set.gateRemote}` : ''} (런 입력에 기록 · 면제 아님)`);
1336
+ if (o.gatePodPool !== undefined && poolOverride?.kind === 'gate-pod-pool') log(`⇄ gate Pod 풀 ${poolOverride.set.gatePodPool} (런 입력에 기록)`);
1252
1337
  if (result.partial.requested) log(result.partial.applied
1253
1338
  ? `◐ 부분 재검${result.partial.auto ? '(기본)' : ''}: ${result.partial.files}파일${result.partial.closure ? ` (코드 닿음 ${result.partial.closure.reached} · 닫힘 불투명 ${result.partial.closure.opaque})` : ''} · 나머지는 앞 게이트(${result.partial.priorCommit.slice(0, 12)}) 결과를 잇는다`
1254
1339
  : `● 전체 게이트로: ${result.partial.reason}`);
1255
1340
  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
1341
  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');
1342
+ ...(o.gateExecutor !== undefined && executorOverride?.kind === 'gate-executor' ? { gateExecutor: executorOverride } : {}),
1343
+ ...(o.gatePodPool !== undefined && poolOverride?.kind === 'gate-pod-pool' ? { gatePodPool: poolOverride } : {}) };
1344
+ }, (r) => 'preflight' in r || r.status === 'done' || r.status === 'awaiting-approval');
1259
1345
  });
1260
1346
  release.command('gate-history')
1261
1347
  .description('GATE-FAIL-HISTORY (0.2.29) — 판을 넘는 게이트 실패 표 — 모든 release-loop·light-rc 런 원장 ⊕ gate-verdict 에서 시험 파일별 introduced·preexisting·env·flaky 횟수 · 마지막 실패 판 · 원인 PR(수리 PR 본문 «원인 #N»)')
@@ -1308,6 +1394,7 @@ export function registerReleaseCommands(program: Command, releaseRunDeps: Unatte
1308
1394
  await jsonAction(o.json, async (log) => {
1309
1395
  const ledgerRoot = scheduleLedgerRoot();
1310
1396
  if (o.apply && !mayWriteLedger('release rehearsal tick', false, ledgerRoot)) throw new Error('release rehearsal tick: ledger write denied');
1397
+ // The tick reports a preflight shard shortage as an unmeasured attempt; its released stage can be claimed on the next CLI tick.
1311
1398
  const result = await runRehearsalTick({ apply: o.apply, checkout: o.checkout, shards: o.shards === undefined ? undefined : Number(o.shards), remote: o.remote, ledgerRoot }, rehearsalDeps);
1312
1399
  log(`· 리허설 ${result.status}${'version' in result ? ` ${result.version}` : ''}${result.status === 'due' ? ` · 실행 ${result.run ?? '-'} · 건너뜀 ${result.supersede.join(', ') || '-'}` : ''}`);
1313
1400
  return result;