elanous 0.2.32 → 0.2.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (753) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 0368f25d-ad84af92fefee68f.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
  7. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 1530.0e612369b6fd7ea0.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
  9. package/apps/pwa/out/_next/static/chunks/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
  11. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
  12. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 2018.a741297bce759490.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
  23. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
  26. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
  31. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 3408.21d1570602f4b6c0.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 3677-4215f826f6aa68e5.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
  40. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
  42. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
  46. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
  49. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 4718-17d2af636796a330.js} +3 -3
  51. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
  61. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 5483-dd5d7697f6bdb106.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
  63. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
  67. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
  74. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
  75. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
  78. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
  80. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
  87. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
  88. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 7644.17e37ba6f1d4226e.js} +4 -4
  90. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
  100. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
  101. package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
  104. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 8637.47f5b35afcae5e6b.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9214.63a510d39178e997.js} +2 -2
  111. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
  112. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 9512.5a76207a730e0491.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 9952.5daf5f94063a2b3e.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/{page-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-dc0a532f5b9196ec.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
  178. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/bin/elanous.mjs +10 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/README.md +5 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +76 -5
  285. package/graphs/document-loop.yaml +71 -4
  286. package/graphs/implement-loop.yaml +59 -4
  287. package/graphs/journey/SCENARIOS.md +33 -0
  288. package/graphs/journey/recipes.yaml +1 -0
  289. package/graphs/journey/ta-journey.yaml +94 -0
  290. package/graphs/journey/units/author/author.yaml +20 -0
  291. package/graphs/journey/units/author/recipes.yaml +2 -0
  292. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  293. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  294. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  295. package/graphs/journey/units/green/green.yaml +20 -0
  296. package/graphs/journey/units/green/recipes.yaml +2 -0
  297. package/graphs/journey/units/pr/pr.yaml +20 -0
  298. package/graphs/journey/units/pr/recipes.yaml +2 -0
  299. package/graphs/journey/units/remember/recipes.yaml +2 -0
  300. package/graphs/journey/units/remember/remember.yaml +20 -0
  301. package/graphs/operate-loop.yaml +71 -4
  302. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  303. package/graphs/release-rehearsal/recipes.yaml +1 -1
  304. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  305. package/graphs/research-loop.yaml +159 -4
  306. package/graphs/test-diet/test-diet.yaml +3 -0
  307. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  308. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  309. package/graphs/units/entry/entry.yaml +50 -0
  310. package/graphs/units/entry/recipes.yaml +14 -0
  311. package/graphs/units/harvest/harvest.yaml +25 -0
  312. package/graphs/units/harvest/recipes.yaml +4 -0
  313. package/graphs/units/land/land.yaml +45 -0
  314. package/graphs/units/land/recipes.yaml +3 -0
  315. package/graphs/units/recipes.yaml +7 -0
  316. package/graphs/units/recover.yaml +39 -0
  317. package/graphs/units/reflect/recipes.yaml +3 -0
  318. package/graphs/units/reflect/reflect.yaml +15 -0
  319. package/graphs/units/task-agent-recover-review.yaml +17 -0
  320. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  321. package/graphs/units/verbs/make-doc.yaml +34 -0
  322. package/graphs/units/verbs/recipes.yaml +33 -0
  323. package/graphs/units/verbs/verify.yaml +55 -0
  324. package/graphs/work/recipes.yaml +2 -0
  325. package/graphs/work/research-report.yaml +28 -0
  326. package/package.json +1 -1
  327. package/scripts/ci-typecheck-changed.ts +69 -16
  328. package/scripts/coord-role-pack.ts +19 -6
  329. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  330. package/scripts/graph-harvest-unit.ts +22 -0
  331. package/scripts/graph-units/journey-stub.ts +6 -0
  332. package/scripts/graph-units/land-enqueue.ts +78 -0
  333. package/scripts/graph-units/recover-plan.ts +15 -0
  334. package/scripts/graph-units/reflect-node.ts +88 -0
  335. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  336. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  337. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  338. package/scripts/graph-units/verbs-envelope.ts +139 -0
  339. package/scripts/hq/standby-snapshot.ts +30 -0
  340. package/scripts/public-export.ts +43 -1
  341. package/scripts/ratchets/train-side-invariants.sh +45 -0
  342. package/scripts/release-loop/auto-approve-node.ts +30 -16
  343. package/scripts/release-loop/docs-land-node.ts +21 -5
  344. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  345. package/scripts/release-loop/gate-closure.ts +5 -1
  346. package/scripts/release-loop/gate-diff.ts +1 -1
  347. package/scripts/release-loop/gate-node.ts +675 -49
  348. package/scripts/release-loop/gate-partial.ts +68 -14
  349. package/scripts/release-loop/gate-radius-live.ts +177 -0
  350. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  351. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  352. package/scripts/release-loop/gate-triage-node.ts +5 -2
  353. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  354. package/scripts/release-loop/known-issues-node.ts +77 -8
  355. package/scripts/release-loop/node-verdict.ts +12 -1
  356. package/scripts/release-loop/npm-publish-node.ts +66 -12
  357. package/scripts/release-loop/preflight.ts +93 -7
  358. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  359. package/scripts/release-loop/publish-node.ts +60 -9
  360. package/scripts/release-loop/pwa-remote.ts +166 -0
  361. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  362. package/scripts/release-loop/resume-cap.ts +56 -0
  363. package/scripts/release-loop/resume-release.ts +155 -19
  364. package/scripts/release-loop/resume.ts +24 -1
  365. package/scripts/release-loop/tui-sim-node.ts +8 -2
  366. package/scripts/release-loop/unattended-release.ts +10 -2
  367. package/scripts/test-diet/lib.ts +6 -1
  368. package/scripts/test-diet/node.ts +194 -13
  369. package/scripts/ux-sim.ts +39 -0
  370. package/src/acp/core-turn-bridge.ts +20 -5
  371. package/src/acp/reasoning-thought-buffer.ts +45 -0
  372. package/src/agent/self-ambient-cache.ts +8 -0
  373. package/src/agent-substrate/acp-reviewer.ts +90 -15
  374. package/src/agent-substrate/pr-reviewer.ts +17 -0
  375. package/src/agent-substrate/review-finding-key.ts +53 -0
  376. package/src/agent-substrate/self-review-cli.ts +188 -18
  377. package/src/ask-user-question/pending-questions.ts +1 -1
  378. package/src/autopilot/pr-manager.ts +393 -65
  379. package/src/budget/run-usage-rollup.ts +1 -0
  380. package/src/chat/index.ts +0 -2
  381. package/src/chat/pickers/modal-runtime.ts +10 -27
  382. package/src/chat/tool-render/dispatch.ts +62 -10
  383. package/src/cli/agent-cli.ts +13 -2
  384. package/src/cli/control-cli.ts +24 -7
  385. package/src/cli/doctor-cli.ts +4 -1
  386. package/src/cli/guardian-cli.ts +10 -0
  387. package/src/cli/light-entry-route.ts +75 -0
  388. package/src/cli/llm-detect-cli.ts +23 -1
  389. package/src/cli/pod-cli.ts +77 -3
  390. package/src/cli/pr-cli.ts +81 -14
  391. package/src/cli/pr-land-base-read.ts +2 -0
  392. package/src/cli/pr-land-overlap-evidence.ts +154 -16
  393. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  394. package/src/cli/pr-land-recovery.ts +64 -0
  395. package/src/cli/pty-takeover-cli.ts +6 -5
  396. package/src/cli/release-checklist-read-cli.ts +79 -0
  397. package/src/cli/release-cli.ts +189 -132
  398. package/src/cli/release-run-if-ready.ts +29 -28
  399. package/src/cli/release-single-flight.ts +178 -0
  400. package/src/cli/remote-resolve.ts +1 -1
  401. package/src/cli/root-tui-entry.ts +48 -0
  402. package/src/cli/seat-cli.ts +37 -0
  403. package/src/cli/setup-cli.ts +40 -1
  404. package/src/cli/sim-cli.ts +22 -0
  405. package/src/cli/tasks-cli.ts +667 -14
  406. package/src/cli/usage-cli.ts +13 -11
  407. package/src/clipboard/history.ts +179 -13
  408. package/src/config.ts +8 -1
  409. package/src/control/control-status.ts +8 -3
  410. package/src/control-plane/ledger.ts +5 -3
  411. package/src/control-plane/server.ts +5 -3
  412. package/src/core-turn/short-question.ts +5 -1
  413. package/src/dashboard/chat/acp-chat.ts +8 -0
  414. package/src/dashboard/index.ts +114 -77
  415. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  416. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  417. package/src/dashboard/input/seat-autowake.ts +56 -3
  418. package/src/dashboard/render/theme-resolver.ts +33 -4
  419. package/src/dashboard/seat-boot-preamble.ts +1 -1
  420. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  421. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  422. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  423. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  424. package/src/dashboard/turn-preamble.ts +47 -1
  425. package/src/dashboard/turn-stream-formatter.ts +34 -1
  426. package/src/dashboard/turn-stream-runtime.ts +2 -0
  427. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  428. package/src/domains/guardian-tick.ts +54 -2
  429. package/src/domains/outbound-alert.ts +3 -2
  430. package/src/domains/schedule-registry.ts +16 -2
  431. package/src/extractors.ts +3 -1
  432. package/src/git-fs/idle-refresh.ts +76 -0
  433. package/src/git-fs/index.ts +18 -7
  434. package/src/git-fs/retry.ts +4 -0
  435. package/src/git-fs/runner.ts +2 -0
  436. package/src/git-fs/worktree.ts +42 -4
  437. package/src/graph-kinds/registry.ts +2 -2
  438. package/src/graph-runner/runner.ts +267 -54
  439. package/src/grok/credential.ts +15 -3
  440. package/src/harness/harness-cli-command.ts +151 -38
  441. package/src/harness/harness-incidents.ts +37 -0
  442. package/src/harness/harness-pod-dispatch.ts +38 -1
  443. package/src/harness/harness-salvage-cli.ts +14 -2
  444. package/src/harness/launch-utterance-ledger.ts +208 -0
  445. package/src/impl-discipline/detector.ts +16 -4
  446. package/src/impl-discipline/system-prompt.ts +11 -0
  447. package/src/impl-discipline/types.ts +2 -2
  448. package/src/index.ts +683 -146
  449. package/src/intake-plane/already-built-hint.ts +91 -0
  450. package/src/intake-plane/requirement-funnel.ts +29 -1
  451. package/src/knowhow/pack.ts +199 -0
  452. package/src/light-cli.ts +111 -0
  453. package/src/llm/opengateway-models.ts +11 -0
  454. package/src/llm/provider-credentials.ts +14 -0
  455. package/src/llm/provider-detect.ts +8 -1
  456. package/src/llm/runtime-model-family.ts +2 -1
  457. package/src/llm.ts +268 -65
  458. package/src/loops/budget.ts +95 -0
  459. package/src/loops/msg-wake.ts +8 -2
  460. package/src/loops/orchestrator/traffic.ts +132 -1
  461. package/src/model-tier/llm-tier-map.ts +15 -1
  462. package/src/mss/logging/log-store.ts +4 -5
  463. package/src/native-tool-catalog.ts +15 -1
  464. package/src/nexus/api/graphs-api.ts +22 -3
  465. package/src/nexus/api/http-server.ts +1 -1
  466. package/src/nexus/api/loop-resources.ts +13 -1
  467. package/src/nexus/api/ops-api.ts +12 -0
  468. package/src/oauth/claude-pty-maturity.ts +66 -0
  469. package/src/oauth/codex-access-mirror.ts +55 -0
  470. package/src/oauth/codex.ts +7 -0
  471. package/src/oauth/fallback-chain.ts +1 -1
  472. package/src/onboarding/first-run.ts +5 -3
  473. package/src/onboarding/non-interactive.ts +64 -13
  474. package/src/onboarding.ts +10 -2
  475. package/src/ops/overview-collect.ts +54 -4
  476. package/src/ops/overview.ts +31 -7
  477. package/src/pr-tool/census.ts +282 -30
  478. package/src/pr-tool/inflight-registry.ts +160 -7
  479. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  480. package/src/pty-shell/herdr-agent-report.ts +442 -0
  481. package/src/pty-shell/pty-control-ipc.ts +5 -5
  482. package/src/pty-shell/pty-manifest.ts +7 -0
  483. package/src/pty-shell/pty-write-outcome.ts +24 -6
  484. package/src/pty-shell/tui-run-state.ts +117 -3
  485. package/src/release-loop/checklist.ts +103 -5
  486. package/src/release-loop/feature-store.ts +19 -2
  487. package/src/release-loop/landed-but-yellow.ts +129 -5
  488. package/src/release-loop/light-rc.ts +1 -0
  489. package/src/release-loop/placement.ts +10 -3
  490. package/src/release-loop/rehearsal.ts +205 -25
  491. package/src/release-loop/rubric.ts +16 -2
  492. package/src/repl/index.ts +174 -17
  493. package/src/repl/ops-msg-bridge.ts +32 -0
  494. package/src/self-dev/ask-launch-flow.ts +44 -5
  495. package/src/self-dev/cli-help-text.ts +17 -0
  496. package/src/self-dev/dev-cli.ts +11 -9
  497. package/src/self-dev/draft-residue.ts +37 -1
  498. package/src/self-dev/draft-sweep.ts +188 -13
  499. package/src/self-dev/draft-triage-rules.ts +107 -0
  500. package/src/self-dev/fleet-reduce.ts +3 -2
  501. package/src/self-dev/graph-front-nodes.ts +112 -0
  502. package/src/self-dev/graph-journey-nodes.ts +11 -6
  503. package/src/self-dev/graph-journey-route.ts +60 -6
  504. package/src/self-dev/harness-run-cli.ts +3 -15
  505. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  506. package/src/self-dev/orchestrate.ts +79 -3
  507. package/src/self-dev/review-provider-fallback.ts +35 -1
  508. package/src/self-dev/run-supervisor.ts +107 -12
  509. package/src/self-dev/run-types.ts +5 -1
  510. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  511. package/src/self-dev/shard-aggregate.ts +42 -5
  512. package/src/self-dev/shard-run.ts +8 -1
  513. package/src/self-implement/blocked-draft-policy.ts +20 -0
  514. package/src/self-implement/classify-shadow.ts +3 -7
  515. package/src/self-implement/doctor-visit.ts +18 -1
  516. package/src/self-implement/gate-baseline.ts +95 -12
  517. package/src/self-implement/gate-cli.ts +1 -0
  518. package/src/self-implement/gate-remote.ts +40 -25
  519. package/src/self-implement/goal-author-decompose.ts +275 -47
  520. package/src/self-implement/goal-author-identity.ts +66 -0
  521. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  522. package/src/self-implement/goal-author.ts +254 -120
  523. package/src/self-implement/goal-elaborate.ts +295 -0
  524. package/src/self-implement/goal-refine.ts +270 -0
  525. package/src/self-implement/graph-overlay-yaml.ts +28 -2
  526. package/src/self-implement/graph-unit-flatten.ts +103 -0
  527. package/src/self-implement/graph-unit-resolver.ts +107 -0
  528. package/src/self-implement/graph-yaml.ts +151 -1
  529. package/src/self-implement/headless-elanous-driver.ts +1 -0
  530. package/src/self-implement/knowhow-pack.ts +103 -0
  531. package/src/self-implement/orchestrator.ts +160 -45
  532. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  533. package/src/self-implement/review-mustfix-class.ts +203 -0
  534. package/src/self-implement/rework-budget-judgment.ts +5 -8
  535. package/src/self-implement/run-stop.ts +17 -2
  536. package/src/self-implement/running-runs.ts +29 -1
  537. package/src/self-implement/scope-adjacency.ts +113 -0
  538. package/src/self-implement/seams.ts +138 -4
  539. package/src/self-implement/stop-autoheal.ts +112 -2
  540. package/src/session/chat.ts +27 -0
  541. package/src/session-runtime/index.ts +1 -1
  542. package/src/session-runtime/retry-policy.ts +2 -1
  543. package/src/setup/llm-env-detect.ts +5 -0
  544. package/src/skills/tools/agent.ts +140 -14
  545. package/src/skills/tools/msg-ask.ts +100 -0
  546. package/src/skills/tools/ops-ledger.ts +2 -1
  547. package/src/skills/tools/schedule-wakeup.ts +66 -17
  548. package/src/steward/hold-hygiene.ts +24 -6
  549. package/src/steward/release-day.ts +7 -3
  550. package/src/steward/triage-budget.ts +194 -0
  551. package/src/steward/triage.ts +57 -7
  552. package/src/task-agent/actions.ts +69 -1
  553. package/src/task-agent/green-sweep.ts +4 -0
  554. package/src/task-agent/harvest-unit.ts +141 -0
  555. package/src/task-agent/live-moves.ts +257 -15
  556. package/src/task-agent/parent-host.ts +216 -6
  557. package/src/task-agent/postland-card.ts +80 -1
  558. package/src/task-agent/rejudge-on-head.ts +112 -26
  559. package/src/task-agent/repair-branch-cas.ts +4 -1
  560. package/src/task-agent/repair-cycle.ts +16 -3
  561. package/src/task-agent/run-identity.ts +4 -3
  562. package/src/task-agent/shadow.ts +19 -3
  563. package/src/task-agent/task-hand.ts +96 -36
  564. package/src/task-agent/tier-split.ts +127 -0
  565. package/src/task-agent/work-order-build.ts +24 -0
  566. package/src/task-agent/work-order.ts +3 -2
  567. package/src/task-orchestrator/generator-prompt.ts +60 -11
  568. package/src/task-orchestrator/surfaces/pod-account-broker.ts +72 -3
  569. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  570. package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
  571. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  572. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  573. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  574. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  575. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
  576. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  577. package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
  578. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  579. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
  580. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  581. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
  582. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
  583. package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
  584. package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
  585. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  586. package/src/tool-runtime/truncation-store.ts +4 -0
  587. package/src/tui/README.md +2 -0
  588. package/src/tui/chat/background-job-status.ts +54 -0
  589. package/src/tui/chat/log-view.ts +80 -0
  590. package/src/tui/entry.ts +406 -0
  591. package/src/tui/input/composer.ts +144 -0
  592. package/src/tui/seat-mail-boot.ts +59 -0
  593. package/src/tui/slash/compact.ts +100 -0
  594. package/src/tui/slash/new-session.ts +35 -0
  595. package/src/tui-client/dashboard-session.ts +10 -1
  596. package/src/tui-client/local-chat-turn.ts +239 -0
  597. package/src/tui-client/local-harness-command.ts +63 -0
  598. package/src/tui-client/local-provider-command.ts +184 -0
  599. package/src/user-config/coercion.ts +36 -0
  600. package/src/user-config.ts +22 -43
  601. package/src/ux-sim/event-monkey.ts +378 -0
  602. package/src/ux-sim/fake-bin.ts +42 -7
  603. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  604. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  605. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  606. package/src/ux-sim/scenario.ts +72 -13
  607. package/src/version/packed-revision.json +1 -1
  608. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  611. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  612. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  613. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  619. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  636. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  640. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +0 -226
  642. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  644. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/5543.a438b8ab5a13ea47.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  653. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  655. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  661. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  662. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  663. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  668. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  669. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  674. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +0 -24
  685. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9989.3694300e5f000b14.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  744. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  752. package/src/cli/g6a-registration-probe.ts +0 -16
  753. /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -1,4 +1,6 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import { appendFileSync, mkdirSync, readFileSync } from 'node:fs';
3
+ import { join } from 'node:path';
2
4
  import { debug } from '../debug/log.js';
3
5
  import type { TriageDecision, TriageIssue } from './triage.js';
4
6
  import { InvalidWorkingBackwardsDraft } from './working-backwards.js';
@@ -187,3 +189,195 @@ export async function draftWithinBudget<T>({ wishes, draft, concurrency = 4, per
187
189
  debug.log('steward.triage', 'draft-budget', stats);
188
190
  return { ...result, stats };
189
191
  }
192
+
193
+ /** Consecutive healthy shadow ticks before a live move is safe to record. */
194
+ export const LIVE_AFTER_TICKS = 3;
195
+
196
+ /** Reasons a decision is a placeholder, not a judgment — they must never be reused as if they were fresh. */
197
+ const TEMPORARY_WHYS = ['triage deferred — deadline', 'triage judgment timed out — human review',
198
+ 'triage judgment unavailable — human review'];
199
+
200
+ export function isTemporaryDecision(decision: TriageDecision): boolean {
201
+ return decision.rung === 'hitl' && decision.hitlReason === 'other' && TEMPORARY_WHYS.includes(decision.why);
202
+ }
203
+
204
+ export interface TriageTickCycle {
205
+ /** sha256 of this tick's sorted issue identifiers — the batch fingerprint. */
206
+ key: string;
207
+ /** Consecutive ticks (this one included) that carried the same fingerprint. */
208
+ ticks: number;
209
+ }
210
+
211
+ export interface TriageTickBudget {
212
+ cycle: TriageTickCycle;
213
+ deadlineMs: number;
214
+ perIssueMs: number;
215
+ concurrency: number;
216
+ /** `repeat-tick` when the same batch already arrived in the previous tick. */
217
+ basis: 'first-tick' | 'repeat-tick';
218
+ }
219
+
220
+ export type TriageItemOutcome = 'reused' | 'judged' | 'timed-out' | 'unavailable' | 'deferred';
221
+
222
+ export interface TriageItemEvent {
223
+ /** 1-based position of the issue in this tick's batch. */
224
+ index: number;
225
+ /** Which tick cycle the item was judged in. */
226
+ cycle: number;
227
+ issue: string;
228
+ outcome: TriageItemOutcome;
229
+ /** No fresh judgment backs this item — the next tick (or a human) must pick it up. */
230
+ degraded: boolean;
231
+ why: string;
232
+ }
233
+
234
+ export interface TriageItemMetrics {
235
+ items: number;
236
+ fresh: number;
237
+ reused: number;
238
+ degraded: number;
239
+ byOutcome: Record<TriageItemOutcome, number>;
240
+ }
241
+
242
+ export interface TriageTickHealth {
243
+ degraded: string[];
244
+ /** Degraded last tick, freshly judged this tick. */
245
+ healed: string[];
246
+ health: 'healthy' | 'healing' | 'degraded';
247
+ /** Consecutive non-degraded shadow ticks. */
248
+ liveStreak: number;
249
+ /** Shadow has stayed healthy long enough that a live move is safe; the mode itself is not flipped here. */
250
+ liveEligible: boolean;
251
+ transition?: 'shadow→live' | 'live→shadow';
252
+ }
253
+
254
+ export interface TriageTickRecord extends TriageTickHealth {
255
+ at: string;
256
+ mode: string;
257
+ key: string;
258
+ ticks: number;
259
+ issues: number;
260
+ deadlineMs: number;
261
+ perIssueMs: number;
262
+ concurrency: number;
263
+ reused: number;
264
+ judged: number;
265
+ timedOut: number;
266
+ deferred: number;
267
+ events: TriageItemEvent[];
268
+ }
269
+
270
+ export function triageTickKey(issues: TriageIssue[]): string {
271
+ return createHash('sha256').update(JSON.stringify(issues.map(issue => issue.identifier).sort())).digest('hex').slice(0, 16);
272
+ }
273
+
274
+ /** The tick cycle: a batch that keeps re-arriving is the same cycle, counted up; a changed batch starts at 1. */
275
+ export function triageTickCycle(previous: Pick<TriageTickRecord, 'key' | 'ticks'> | undefined, key: string): TriageTickCycle {
276
+ const ticks = previous && previous.key === key && Number.isFinite(previous.ticks) ? Math.max(1, previous.ticks) + 1 : 1;
277
+ return { key, ticks };
278
+ }
279
+
280
+ /**
281
+ * Budget derived from the tick cycle: the stage deadline is fixed per tick, but a repeat cycle widens each issue's
282
+ * slice (up to 3×) instead of re-running the same timeout on the batch that already ran out of window last tick.
283
+ */
284
+ export function triageTickBudget({ cycle, issueCount, deadlineMs = 240_000, basePerIssueMs = 90_000, maxConcurrency = 8 }: {
285
+ cycle: TriageTickCycle;
286
+ issueCount: number;
287
+ deadlineMs?: number;
288
+ basePerIssueMs?: number;
289
+ maxConcurrency?: number;
290
+ }): TriageTickBudget {
291
+ const count = Math.max(1, Math.floor(issueCount));
292
+ const concurrency = Math.max(1, Math.min(Math.max(1, Math.floor(maxConcurrency)), count));
293
+ const stretch = Math.min(Math.max(1, Math.floor(cycle.ticks)), 3);
294
+ return { cycle, deadlineMs, perIssueMs: Math.min(deadlineMs, basePerIssueMs * stretch), concurrency,
295
+ basis: cycle.ticks > 1 ? 'repeat-tick' : 'first-tick' };
296
+ }
297
+
298
+ /** One event per item: what actually happened to it this tick and whether that leaves it degraded. */
299
+ export function triageItemEvents({ cycle, issues, decisions, previous = [] }: {
300
+ cycle: TriageTickCycle;
301
+ issues: TriageIssue[];
302
+ decisions: Array<TriageDecision & { inputHash?: string; deferred?: true }>;
303
+ previous?: Array<TriageDecision & { inputHash?: string }>;
304
+ }): TriageItemEvent[] {
305
+ const judged = new Map(decisions.map(decision => [decision.issue, decision]));
306
+ const earlier = new Map(previous.map(decision => [decision.issue, decision]));
307
+ const events: TriageItemEvent[] = [];
308
+ for (const [index, issue] of issues.entries()) {
309
+ const decision = judged.get(issue.identifier);
310
+ const before = earlier.get(issue.identifier);
311
+ let outcome: TriageItemOutcome;
312
+ if (!decision) outcome = 'unavailable';
313
+ else if (decision.deferred === true) outcome = 'deferred';
314
+ else if (decision.why === 'triage judgment timed out — human review') outcome = 'timed-out';
315
+ else if (decision.why === 'triage judgment unavailable — human review') outcome = 'unavailable';
316
+ else if (before && before.inputHash !== undefined && before.inputHash === decision.inputHash &&
317
+ !before.deferred && !isTemporaryDecision(before)) outcome = 'reused';
318
+ else outcome = 'judged';
319
+ events.push({ index: index + 1, cycle: cycle.ticks, issue: issue.identifier, outcome,
320
+ degraded: outcome !== 'judged' && outcome !== 'reused',
321
+ why: decision?.why ?? 'triage decision missing' });
322
+ }
323
+ return events;
324
+ }
325
+
326
+ export function triageItemMetrics(events: TriageItemEvent[]): TriageItemMetrics {
327
+ const byOutcome: Record<TriageItemOutcome, number> = { reused: 0, judged: 0, 'timed-out': 0, unavailable: 0, deferred: 0 };
328
+ for (const event of events) byOutcome[event.outcome]++;
329
+ const reused = byOutcome.reused;
330
+ return { items: events.length, fresh: byOutcome.judged, reused,
331
+ degraded: events.filter(event => event.degraded).length, byOutcome };
332
+ }
333
+
334
+ /** Healing and the shadow→live transition, read off the previous real tick — never off an assumed one. */
335
+ export function triageTickHealth({ previous, mode, events }: {
336
+ previous?: Pick<TriageTickRecord, 'mode' | 'degraded' | 'liveStreak'>;
337
+ mode: string;
338
+ events: TriageItemEvent[];
339
+ }): TriageTickHealth {
340
+ const degraded = events.filter(event => event.degraded).map(event => event.issue);
341
+ const healed = (previous?.degraded ?? []).filter(issue => !degraded.includes(issue)).sort();
342
+ const health = healed.length ? 'healing' : degraded.length ? 'degraded' : 'healthy';
343
+ // Any degradation still present this tick resets the streak — a healed item next to a degraded one is not a healthy tick.
344
+ const liveStreak = mode === 'shadow' ? (degraded.length ? 0 : (previous?.mode === 'shadow' ? previous.liveStreak + 1 : 1)) : 0;
345
+ const transition = previous && previous.mode !== mode
346
+ ? (mode === 'live' && previous.mode === 'shadow' ? 'shadow→live'
347
+ : mode === 'shadow' && previous.mode === 'live' ? 'live→shadow' : undefined)
348
+ : undefined;
349
+ return { degraded, healed, health, liveStreak, liveEligible: mode === 'shadow' && liveStreak >= LIVE_AFTER_TICKS,
350
+ ...(transition ? { transition } : {}) };
351
+ }
352
+
353
+ export function triageTickLedgerPath(root: string): string {
354
+ return join(root, 'steward', 'triage-ticks.jsonl');
355
+ }
356
+
357
+ /** The real ticks that already ran, oldest first. A torn line is not a tick. */
358
+ export function readTriageTicks(root: string, limit = 24): TriageTickRecord[] {
359
+ let text: string;
360
+ try { text = readFileSync(triageTickLedgerPath(root), 'utf8'); } catch { return []; }
361
+ const records: TriageTickRecord[] = [];
362
+ for (const line of text.split('\n')) {
363
+ if (!line.trim()) continue;
364
+ try {
365
+ const parsed: unknown = JSON.parse(line);
366
+ if (parsed && typeof parsed === 'object' && typeof (parsed as { mode?: unknown }).mode === 'string' &&
367
+ typeof (parsed as { key?: unknown }).key === 'string' && typeof (parsed as { ticks?: unknown }).ticks === 'number' &&
368
+ Array.isArray((parsed as { degraded?: unknown }).degraded) && Array.isArray((parsed as { events?: unknown }).events)) {
369
+ records.push(parsed as TriageTickRecord);
370
+ }
371
+ } catch { /* torn line */ }
372
+ }
373
+ return records.slice(-Math.max(1, limit));
374
+ }
375
+
376
+ export function appendTriageTick(root: string, record: TriageTickRecord): void {
377
+ try {
378
+ mkdirSync(join(root, 'steward'), { recursive: true });
379
+ appendFileSync(triageTickLedgerPath(root), `${JSON.stringify(record)}\n`);
380
+ } catch (error) {
381
+ debug.log('steward.triage', 'tick-ledger-failed', { reason: String(error) }, { level: 'warn' });
382
+ }
383
+ }
@@ -1,5 +1,5 @@
1
1
  import { randomUUID } from 'node:crypto';
2
- import { closeSync, existsSync, openSync, readFileSync, writeFileSync, mkdirSync, rmSync } from 'node:fs';
2
+ import { closeSync, existsSync, openSync, readFileSync, writeFileSync, mkdirSync, renameSync, rmSync } from 'node:fs';
3
3
  import { launchModeOf, rescueAllows } from './rescue.js';
4
4
  import { join } from 'node:path';
5
5
  import { fetchLinearIssues } from '../connectors/linear.js';
@@ -130,7 +130,7 @@ export function trackTablePrompt(tracks?: Record<string, string>): string {
130
130
  return `\n담당 트랙(owner) — 아래 중 하나(${keys.map(k => JSON.stringify(k)).join('|')}) · 이슈가 어느 트랙 일인지:\n${keys.map(k => `- ${k}: ${tracks[k]}`).join('\n')}`;
131
131
  }
132
132
 
133
- export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<StewardDeps['judge']>, decide: typeof emitDecision = emitDecision, tracks?: Record<string, string>, previous: Array<TriageDecision & { inputHash?: string }> = [], ask: StewardAsk = askSteward): Promise<TriageDecision[]> {
133
+ export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<StewardDeps['judge']>, decide: typeof emitDecision = emitDecision, tracks?: Record<string, string>, previous: Array<TriageDecision & { inputHash?: string }> = [], ask: StewardAsk = askSteward, budget?: { deadlineMs: number; perIssueMs: number; concurrency: number }): Promise<TriageDecision[]> {
134
134
  const started = judge ? 0 : Date.now();
135
135
  const classified: ClassifiedIssue[] = [];
136
136
  const classifiedIds = new Set<string>();
@@ -144,7 +144,7 @@ export async function triageIssues(issues: TriageIssue[], judge?: NonNullable<St
144
144
  decide({ kind: result.rung === 'hitl' ? 'ESCALATE' : 'ROUTE', what: result.issue, reason: result.why,
145
145
  purpose: 'steward triage', target: result.owner ? `${result.rung} · ${result.owner}` : String(result.rung), refs: { issue: result.issue } });
146
146
  };
147
- const { decisions } = await triageWithinBudget({ issues, previous, tracks, judge: async (issue, observedIssues) => {
147
+ const { decisions } = await triageWithinBudget({ issues, previous, tracks, ...(budget ?? {}), judge: async (issue, observedIssues) => {
148
148
  try {
149
149
  if (judge) return parseJudgment(issue, await judge(issue, observedIssues ?? issues, tracks), tracks);
150
150
  const byRule = ruleJudgment(issue, observedIssues ?? issues);
@@ -328,13 +328,46 @@ function logStageFailure(root: string, stage: StewardStage, reason: string): voi
328
328
  }
329
329
  const SCHEDULE_CHECK_MS = 15 * 60_000;
330
330
 
331
+ /** Atomic marker write: stage the payload at `<marker>.tmp-<pid>`, then renameSync it into place so a
332
+ * crash mid-write never leaves a half-written marker for the next sync to trip over. */
333
+ export function writeScheduleCheckMarker(
334
+ marker: string,
335
+ at: Date,
336
+ write: (path: string, data: string) => void = writeFileSync,
337
+ ): void {
338
+ const tmp = `${marker}.tmp-${process.pid}`;
339
+ try {
340
+ write(tmp, JSON.stringify({ at: at.toISOString() }));
341
+ renameSync(tmp, marker);
342
+ } catch (error) {
343
+ try { rmSync(tmp, { force: true }); } catch { /* Preserve the write or rename error. */ }
344
+ throw error;
345
+ }
346
+ }
347
+
331
348
  /** Called by runStewardStage(sync) under its stage slot, never from the checker CLI. */
332
349
  async function checkStewardSchedules(root: string, settings: StewardSettings, deps: StewardDeps): Promise<void> {
333
350
  const now = (deps.now ?? (() => new Date()))();
334
351
  const marker = join(root, 'steward', 'schedule-check.json');
335
352
  let previous: { at?: string } = {};
336
- try { previous = JSON.parse(readFileSync(marker, 'utf8')) as typeof previous; }
337
- catch (error) { if ((error as NodeJS.ErrnoException).code !== 'ENOENT') throw error; }
353
+ try {
354
+ const parsed: unknown = JSON.parse(readFileSync(marker, 'utf8'));
355
+ if (parsed !== null && typeof parsed === 'object' && !Array.isArray(parsed)
356
+ && (!('at' in parsed) || typeof parsed.at === 'string')) {
357
+ previous = parsed as typeof previous;
358
+ } else {
359
+ debug.log('steward.schedule-check', 'marker-recovered', { reason: 'invalid-marker-shape' });
360
+ }
361
+ }
362
+ catch (error) {
363
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') { /* first run in this window — previous stays {} */ }
364
+ else if (error instanceof SyntaxError) {
365
+ // Corrupt marker bytes self-heal: previous stays {} so this check runs now and the fresh
366
+ // writeScheduleCheckMarker below replaces the broken file. The recovery is observed.
367
+ debug.log('steward.schedule-check', 'marker-recovered', { reason: redactSecretText(String(error)) });
368
+ }
369
+ else throw error;
370
+ }
338
371
  const elapsed = now.getTime() - Date.parse(previous.at ?? '');
339
372
  if (Number.isFinite(elapsed) && elapsed >= 0 && elapsed < SCHEDULE_CHECK_MS) return;
340
373
  const inventory = deps.scheduleInventory ?? (() => {
@@ -378,7 +411,7 @@ async function checkStewardSchedules(root: string, settings: StewardSettings, de
378
411
  debug.log('steward.schedule-check', 'routing', { ownerRequests, opEscalations, recovered });
379
412
  }
380
413
  debug.log('steward.schedule-check', 'checked', { count: checked.length, findings: findings.length, mode: settings.mode });
381
- writeFileSync(marker, JSON.stringify({ at: now.toISOString() }));
414
+ writeScheduleCheckMarker(marker, now);
382
415
  }
383
416
 
384
417
  function readState(path: string): { issues: Record<string, string>; digestDay?: string } {
@@ -454,7 +487,24 @@ export async function runStewardStage(stage: 'sync' | 'triage' | 'schedule' | 'r
454
487
  Array.isArray(item.dependsOn) && item.dependsOn.every((dep: unknown) => typeof dep === 'string') &&
455
488
  typeof item.priority === 'number' && Number.isFinite(item.priority) && typeof item.why === 'string')) previous = parsed;
456
489
  } catch { /* Missing or corrupt previous judgments are an empty cache. */ }
457
- writeFileSync(judgments, JSON.stringify(await triageIssues(issues, judge, deps.decide, settings.tracks, previous, deps.ask)));
490
+ const { appendTriageTick, readTriageTicks, triageItemEvents, triageItemMetrics, triageTickBudget, triageTickCycle,
491
+ triageTickHealth, triageTickKey } = await import('./triage-budget.js');
492
+ const ticks = readTriageTicks(root);
493
+ const cycle = triageTickCycle(ticks.at(-1), triageTickKey(issues));
494
+ const budget = triageTickBudget({ cycle, issueCount: issues.length });
495
+ const decisions = await triageIssues(issues, judge, deps.decide, settings.tracks, previous, deps.ask, budget);
496
+ writeFileSync(judgments, JSON.stringify(decisions));
497
+ const events = triageItemEvents({ cycle, issues, decisions, previous });
498
+ const metrics = triageItemMetrics(events);
499
+ const mode = settings.mode ?? 'shadow';
500
+ const health = triageTickHealth({ previous: ticks.at(-1), mode, events });
501
+ for (const event of events) debug.log('steward.triage', 'item-event', { ...event, health: health.health });
502
+ debug.log('steward.triage', 'tick', { cycle, basis: budget.basis, perIssueMs: budget.perIssueMs,
503
+ concurrency: budget.concurrency, ...metrics, ...health });
504
+ appendTriageTick(root, { at: new Date().toISOString(), mode, key: cycle.key, ticks: cycle.ticks, issues: issues.length,
505
+ deadlineMs: budget.deadlineMs, perIssueMs: budget.perIssueMs, concurrency: budget.concurrency,
506
+ reused: metrics.byOutcome.reused, judged: metrics.byOutcome.judged, timedOut: metrics.byOutcome['timed-out'],
507
+ deferred: metrics.byOutcome.deferred, ...health, events });
458
508
  } else if (stage === 'schedule') {
459
509
  const decisions = JSON.parse(readFileSync(judgments, 'utf8')) as TriageDecision[];
460
510
  const pending = new Set(decisions.flatMap(decision => decision.dependsOn));
@@ -64,7 +64,7 @@ export interface ActionDeps {
64
64
  releaseLanding?(day: string): void;
65
65
  /** 실패 한 번을 잠금 안에서 디스크에 더한다(다른 프로세스의 실패를 덮지 않게) · 더한 뒤의 값을 돌려준다. */
66
66
  incrementFailure?(key: string): number;
67
- observe(event: 'task-agent.action', data: { taskId: string; kind: NextActionKind; result: string; reason: string }): void;
67
+ observe(event: 'task-agent.action' | 'task-agent.entrance-denominator', data: ActionObservation): void;
68
68
  /** 사다리 R4 — 실제로 할 재발사 수의 허용 목록(`taskAgent.liveMoves` 어휘). 없으면 종전 그대로(재발사에 목록 검사 없음) · 목록에 없는 수는 shadow. */
69
69
  liveMoves?: ReadonlySet<string>;
70
70
  /** 한 판단 회차의 발사 칸 — 호출부가 회차마다 새로 준다. 없으면 회당 상한 없음(종전). 발사를 시도할 때마다 `count` 가 오른다. */
@@ -76,6 +76,49 @@ export interface ActionDeps {
76
76
  /** 재발사는 한 판단 회차에 한 건만 발사한다. */
77
77
  export const RETRY_LAUNCHES_PER_CYCLE = 1;
78
78
 
79
+ export interface ActionObservation {
80
+ taskId: string;
81
+ kind: NextActionKind | 'entrance-tick';
82
+ result: string;
83
+ reason: string;
84
+ reviewed?: number;
85
+ allowed?: number;
86
+ refused?: number;
87
+ reasons?: Record<string, number>;
88
+ }
89
+
90
+ export interface EntranceCandidateReview {
91
+ taskId: string;
92
+ kind: NextActionKind;
93
+ refusal?: string;
94
+ }
95
+
96
+ export interface EntranceTickCandidate {
97
+ action: NextAction;
98
+ refusal?: string;
99
+ }
100
+
101
+ export interface EntranceRefusalDenominator {
102
+ reviewed: number;
103
+ allowed: number;
104
+ refused: number;
105
+ reasons: Record<string, number>;
106
+ }
107
+
108
+ /** Count a tick's candidate refusals without confusing special object keys with prototypes. */
109
+ export function buildEntranceRefusalDenominator(reviews: readonly EntranceCandidateReview[]): EntranceRefusalDenominator {
110
+ const reasonCounts = new Map<string, number>();
111
+ let refused = 0;
112
+ for (const review of reviews) {
113
+ const reason = typeof review.refusal === 'string' ? review.refusal.trim() : '';
114
+ if (!reason) continue;
115
+ refused += 1;
116
+ reasonCounts.set(reason, (reasonCounts.get(reason) ?? 0) + 1);
117
+ }
118
+ const reasons = Object.fromEntries(reasonCounts) as Record<string, number>;
119
+ return { reviewed: reviews.length, allowed: reviews.length - refused, refused, reasons };
120
+ }
121
+
79
122
  /** live 인데도 shadow 로 내릴 사유 — 없으면 발사해도 된다(재발사 아닌 수는 늘 없다). 기다림(wait)은 발사가 아니라 부하·회당 상한을 보지 않는다. */
80
123
  function retryShadowReason(action: NextAction, deps: ActionDeps): string | undefined {
81
124
  if (action.kind !== 'retry') return undefined;
@@ -264,6 +307,31 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
264
307
  return record('done', action.rationale);
265
308
  }
266
309
 
310
+ /** Execute the allowed candidates in a caller-supplied tick and emit one isolated denominator event. */
311
+ export async function executeEntranceTick(candidates: readonly EntranceTickCandidate[], deps: ActionDeps): Promise<string[]> {
312
+ const denominator = buildEntranceRefusalDenominator(candidates.map(({ action, refusal }) => ({
313
+ taskId: action.taskId,
314
+ kind: action.kind,
315
+ ...(typeof refusal === 'string' ? { refusal } : {}),
316
+ })));
317
+ const observeDenominator = (result: string) => {
318
+ try {
319
+ deps.observe('task-agent.entrance-denominator', {
320
+ taskId: candidates[0]?.action.taskId ?? 'entrance-tick',
321
+ kind: 'entrance-tick', result, reason: 'entrance refusal denominator', ...denominator,
322
+ });
323
+ } catch { /* Logging must not change the actions selected for this tick. */ }
324
+ };
325
+ const results: string[] = [];
326
+ for (const { action, refusal } of candidates) {
327
+ if (typeof refusal === 'string' && refusal.trim()) continue;
328
+ try { results.push(await executeNextAction(action, deps)); }
329
+ catch (error) { observeDenominator('failed'); throw error; }
330
+ }
331
+ observeDenominator(results.at(-1) ?? 'refused-all');
332
+ return results;
333
+ }
334
+
267
335
  /** 재발사 문면 — 원문은 고치지 않고 앞에 둔다 · 갈래 문면 · must-fix · 직전 런 순서. */
268
336
  export function retryText(action: NextAction): string {
269
337
  const sections = [action.original];
@@ -28,6 +28,8 @@ export interface GreenSweepDecision {
28
28
  source: GreenSweepCandidate['source'];
29
29
  verdict: GreenSweepVerdict;
30
30
  reason: string;
31
+ /** Present when traffic hold state could not be read; preserves the decision reason while exposing its cause. */
32
+ holdDiagnostic?: string;
31
33
  evidence: string;
32
34
  existingEvidence: string;
33
35
  /** Preview only; a later live operation may persist this complete value. */
@@ -107,6 +109,7 @@ export function decideGreenSweep(input: {
107
109
  pr: GreenSweepPr | null;
108
110
  ancestor: boolean | null;
109
111
  hold: boolean | null;
112
+ holdDiagnostic?: string;
110
113
  repositoryMatches?: boolean | null;
111
114
  ambiguousAcrossCells?: boolean;
112
115
  }): GreenSweepDecision {
@@ -116,6 +119,7 @@ export function decideGreenSweep(input: {
116
119
  const landing = pr?.viaTrain ? ` via train #${pr.viaTrain.integrationPr}` : '';
117
120
  const evidence = `GREEN-FROM-LEDGER: PR #${candidate.pr}${landing}${mergeSha ? ` merged ${mergeSha}` : ''} · ${verdict} · ${reason}`;
118
121
  return { cell: item.id, pr: candidate.pr, mergeSha, source: candidate.source, verdict, reason,
122
+ ...(reason === 'hold-state-unreadable' && input.holdDiagnostic ? { holdDiagnostic: input.holdDiagnostic } : {}),
119
123
  evidence, existingEvidence: item.evidence ?? '', plannedEvidence: appendGreenSweepEvidence(item.evidence, evidence) };
120
124
  };
121
125
  if (item.status !== 'yellow' && item.status !== 'red') return result('skip', 'cell-not-yellow');
@@ -0,0 +1,141 @@
1
+ export type HarvestInput = {
2
+ ask?: unknown;
3
+ context?: unknown;
4
+ prior?: unknown;
5
+ };
6
+
7
+ export type ReviewInvocation = {
8
+ stdout: string;
9
+ stderr?: string;
10
+ exitCode: number | null;
11
+ };
12
+
13
+ export type HarvestResult = {
14
+ outcome: 'done' | 'rework' | 'needs-human' | 'failed';
15
+ result: Record<string, unknown>;
16
+ evidence: Record<string, unknown>;
17
+ };
18
+
19
+ type ReviewRecord = Record<string, unknown> & {
20
+ pr?: string | number;
21
+ reviewed?: boolean;
22
+ verdict?: string | null;
23
+ mustFix?: unknown;
24
+ model?: string;
25
+ headCommit?: string;
26
+ currentHeadCommit?: string;
27
+ };
28
+
29
+ function object(value: unknown): value is Record<string, unknown> {
30
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
31
+ }
32
+
33
+ function expectedHead(input: HarvestInput): string | undefined {
34
+ if (object(input.context) && typeof input.context.expectedHead === 'string' && input.context.expectedHead.trim()) return input.context.expectedHead.trim();
35
+ return undefined;
36
+ }
37
+
38
+ function normalizedPr(value: unknown): string | undefined {
39
+ const raw = typeof value === 'number' && Number.isSafeInteger(value) ? String(value) : typeof value === 'string' ? value.trim() : '';
40
+ const normalized = raw.replace(/^#/, '');
41
+ return /^\d+$/.test(normalized) ? normalized : undefined;
42
+ }
43
+
44
+ function previousAttempts(input: HarvestInput): number {
45
+ if (!object(input.prior)) return 0;
46
+ const result = object(input.prior.result) ? input.prior.result : input.prior;
47
+ const attempts = result.attempts;
48
+ return Number.isSafeInteger(attempts) && (attempts as number) >= 0 ? attempts as number : 0;
49
+ }
50
+
51
+ function parseReview(stdout: string): ReviewRecord | undefined {
52
+ try {
53
+ const parsed: unknown = JSON.parse(stdout.trim());
54
+ if (Array.isArray(parsed)) {
55
+ if (parsed.length !== 1) return undefined;
56
+ return object(parsed[0]) ? parsed[0] as ReviewRecord : undefined;
57
+ }
58
+ return object(parsed) ? parsed as ReviewRecord : undefined;
59
+ } catch {
60
+ return undefined;
61
+ }
62
+ }
63
+
64
+ export async function runHarvestUnit(
65
+ input: HarvestInput,
66
+ invokeReview: (args: { pr: string; intent: string }) => Promise<ReviewInvocation>,
67
+ ): Promise<HarvestResult> {
68
+ const attempts = previousAttempts(input) + 1;
69
+ const prValue = object(input.context) ? input.context.pr : undefined;
70
+ const pr = normalizedPr(prValue);
71
+ if (!pr) {
72
+ return { outcome: 'failed', result: { attempts, error: 'context.pr must identify one pull request' }, evidence: { pr: pr || null, attempts } };
73
+ }
74
+
75
+ const context = object(input.context) ? input.context : {};
76
+ const hasContextIntent = Object.prototype.hasOwnProperty.call(context, 'reviewIntent');
77
+ const intentValue = context.reviewIntent;
78
+ const intent = hasContextIntent
79
+ ? typeof intentValue === 'string' ? intentValue.trim() : ''
80
+ : typeof input.ask === 'string' ? input.ask.trim() : '';
81
+ if (!intent) {
82
+ return { outcome: 'failed', result: { attempts, error: hasContextIntent ? 'context.reviewIntent must be a non-empty string' : 'context.reviewIntent or ask is required' }, evidence: { pr, attempts } };
83
+ }
84
+ const expected = expectedHead(input);
85
+ if (!expected || !/^[0-9a-f]{40}$/i.test(expected)) {
86
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'expected PR head is required' }, evidence: { pr, attempts, expectedHead: expected ?? null } };
87
+ }
88
+
89
+ let invocation: ReviewInvocation;
90
+ try {
91
+ invocation = await invokeReview({ pr: pr.replace(/^#/, ''), intent });
92
+ } catch (error) {
93
+ const reason = error instanceof Error ? error.message : String(error);
94
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review could not be executed' }, evidence: { pr, attempts, error: reason } };
95
+ }
96
+
97
+ const review = parseReview(invocation.stdout);
98
+ if (!review || review.reviewed !== true || typeof review.headCommit !== 'string' || typeof review.currentHeadCommit !== 'string') {
99
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review result is missing or incomplete' }, evidence: {
100
+ pr, attempts, exitCode: invocation.exitCode, stderr: invocation.stderr ?? '', stdout: invocation.stdout.slice(0, 4000),
101
+ } };
102
+ }
103
+ if (normalizedPr(review.pr) !== pr) {
104
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review result belongs to a different pull request' }, evidence: {
105
+ pr, attempts, reviewedPr: review.pr ?? null, expectedHead: expected,
106
+ } };
107
+ }
108
+ if (invocation.exitCode !== 0) {
109
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review command exited unsuccessfully' }, evidence: {
110
+ pr, attempts, exitCode: invocation.exitCode, stderr: invocation.stderr ?? '',
111
+ } };
112
+ }
113
+ if (review.headCommit !== review.currentHeadCommit || (expected !== undefined && review.headCommit !== expected)) {
114
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review head is stale or differs from expected head' }, evidence: {
115
+ pr, attempts, expectedHead: expected ?? null, reviewedHead: review.headCommit, currentHead: review.currentHeadCommit,
116
+ } };
117
+ }
118
+ if (!['pass', 'warn', 'fail'].includes(review.verdict ?? '')) {
119
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review verdict is missing or invalid' }, evidence: {
120
+ pr, attempts, verdict: review.verdict ?? null, headCommit: review.headCommit,
121
+ } };
122
+ }
123
+ if (!Array.isArray(review.mustFix) || !review.mustFix.every(item => typeof item === 'string' && item.trim().length > 0)) {
124
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review mustFix field is invalid' }, evidence: { pr, attempts, headCommit: review.headCommit } };
125
+ }
126
+
127
+ const mustFix = review.mustFix as string[];
128
+ if ((review.verdict === 'fail' && mustFix.length === 0)
129
+ || ((review.verdict === 'pass' || review.verdict === 'warn') && mustFix.length > 0)) {
130
+ return { outcome: 'needs-human', result: { pr, attempts, reason: 'review verdict conflicts with mustFix findings' }, evidence: {
131
+ pr, attempts, verdict: review.verdict, mustFix, headCommit: review.headCommit,
132
+ } };
133
+ }
134
+ const evidence = {
135
+ pr, headCommit: review.headCommit, attempts, model: review.model ?? null, verdict: review.verdict ?? null,
136
+ reviewResultsJson: true, exitCode: invocation.exitCode,
137
+ };
138
+ return mustFix.length > 0
139
+ ? { outcome: 'rework', result: { pr, headCommit: review.headCommit, attempts, mustFix }, evidence }
140
+ : { outcome: 'done', result: { pr, headCommit: review.headCommit, attempts, mustFix: [] }, evidence };
141
+ }