elanous 0.2.35 → 0.2.37

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 (827) 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/{T1mBQqmkwKDLGtyisDCOd → 8kITumG9GAZ1LwT9POrAR}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/1041-5841aae848fb6403.js +1 -0
  5. package/apps/pwa/out/_next/static/chunks/1087.3177e54f672dc526.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1105.efe1e13503ac7a33.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1224.2ceca6c180d5130b.js +62 -0
  8. package/apps/pwa/out/_next/static/chunks/{9952.5daf5f94063a2b3e.js → 1262.a89bb27a5b2f844e.js} +1 -1
  9. package/apps/pwa/out/_next/static/chunks/1417-1768233ac92f8a5d.js +1 -0
  10. package/apps/pwa/out/_next/static/chunks/1612.81bbc19af06af16c.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1746.3563617ea64023a3.js +115 -0
  12. package/apps/pwa/out/_next/static/chunks/1766.728d42053070bb2d.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1773.d38e945481e04125.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/1974-c12f9600da3d3c26.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/{1dc5a567.9b092bfae3d7099b.js → 1ed5e8af.cf424815c7c0efad.js} +1 -1
  16. package/apps/pwa/out/_next/static/chunks/{4705-194e64e47ca0fbdb.js → 2002-a43a3f380df873ec.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2061.7232dc9dc058417f.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{13.02a07436dec15f89.js → 210.90b2cbd64926cf34.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/{9512.5a76207a730e0491.js → 2283.edd9627b7bdfb546.js} +2 -2
  20. package/apps/pwa/out/_next/static/chunks/{6866-79aa5b4e47cac6aa.js → 2318-450e75d07605b8fe.js} +1 -1
  21. package/apps/pwa/out/_next/static/chunks/{938.66ad1ef0e5abae1c.js → 2375.bf364c85dbb6f085.js} +1 -1
  22. package/apps/pwa/out/_next/static/chunks/244-a810d282a20f1783.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/2479-fe7e188bd9402d14.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2514.03b60f266531a015.js +148 -0
  25. package/apps/pwa/out/_next/static/chunks/2526-a657538869888604.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2533-6f0341ff075809e9.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2676.e7994c695ef0f30d.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2734.3ffdf54254fb6f99.js +27 -0
  29. package/apps/pwa/out/_next/static/chunks/2770-23252bf3a37880b9.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/2969.66b8b545139d1544.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/3128.a9210d08800ea6a8.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/3199.6a1a9b0e6cd01dc6.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/3212.12179fd3eee8cef1.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/{9214.63a510d39178e997.js → 3578.4e9f9948a9a6f2f4.js} +2 -2
  35. package/apps/pwa/out/_next/static/chunks/3760-2909ddb9279281cd.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3825.1921b5901bf33dce.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3994-63eb884ed0547011.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/4036.d54e55e1ebf5acdc.js +90 -0
  39. package/apps/pwa/out/_next/static/chunks/4115.5b438b99f0ae729f.js +226 -0
  40. package/apps/pwa/out/_next/static/chunks/4269.d8f9f34bb0fc6c43.js +287 -0
  41. package/apps/pwa/out/_next/static/chunks/431-4eed5bd2c5fe1719.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{2018.a741297bce759490.js → 4313.76f232c304a15bde.js} +1 -1
  43. package/apps/pwa/out/_next/static/chunks/{1165.bad13fc9151a7288.js → 4324.c99ba3e83eb1b691.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/{3f7c4ee5.3dde54f01a816613.js → 4337e36d.f42c3b391b3d8f20.js} +1 -1
  45. package/apps/pwa/out/_next/static/chunks/{7385.50a308a477bdfc21.js → 4383.18e5c54db3a22c88.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4599-96eff3f2a9c242c1.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/{8557-e7898769499cd56f.js → 4725-34bed25720cc326b.js} +1 -1
  48. package/apps/pwa/out/_next/static/chunks/4825-a9d9d4e9f5892309.js +1 -0
  49. package/apps/pwa/out/_next/static/chunks/{5483-dd5d7697f6bdb106.js → 4833-7934c592c5569f00.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4879-68518f547a207aff.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4896.f9b70285363b27b2.js +24 -0
  52. package/apps/pwa/out/_next/static/chunks/{8444.4c26b379ca2b9596.js → 4931.95cc6dbd230774ca.js} +17 -17
  53. package/apps/pwa/out/_next/static/chunks/4937-28d437999b77c9dd.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/49aa54ab.80f39398e0ed0f30.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{3408.21d1570602f4b6c0.js → 5046.7fd5cbd859299448.js} +1 -1
  56. package/apps/pwa/out/_next/static/chunks/5056.482687319b82638e.js +104 -0
  57. package/apps/pwa/out/_next/static/chunks/506.16b83d56a437a9ee.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5260-20593b0a25d0afbc.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5404.cc4e9fec26fd5925.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/576.485e83e3f3dec19a.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5832-a6be14e663f65726.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5854-56648a9fe646b9a0.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/58edce7d.f1b0c72acf13b123.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5925.3b1f8b135710249b.js +93 -0
  65. package/apps/pwa/out/_next/static/chunks/5952.294fc574a8625184.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/{b6705a4f-b9a9047de9eecfd0.js → 5f6af561-f90b7a67f4f75d13.js} +1 -1
  67. package/apps/pwa/out/_next/static/chunks/6168.17749aa3905fa073.js +74 -0
  68. package/apps/pwa/out/_next/static/chunks/6252.240578f10952e091.js +34 -0
  69. package/apps/pwa/out/_next/static/chunks/6416.5d50b8ec9986ca98.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/{5101.e32282718f99ed6f.js → 6680.6a693c28aae4cd19.js} +1 -1
  71. package/apps/pwa/out/_next/static/chunks/{4718-17d2af636796a330.js → 6745-5a63492933959dd9.js} +3 -3
  72. package/apps/pwa/out/_next/static/chunks/6758.e7fbf532953c0783.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6795.0cb8a59730d99703.js +149 -0
  74. package/apps/pwa/out/_next/static/chunks/{6236.e18cced2d5ba6afb.js → 6819.be5c9c4d67f22922.js} +16 -16
  75. package/apps/pwa/out/_next/static/chunks/6877-84d47b7e85d0c41e.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{2833-0fe47af99ed13c29.js → 6971-fb5f9dc0a2cb5d2d.js} +1 -1
  77. package/apps/pwa/out/_next/static/chunks/{da5176c6.6773b6c5994e1d99.js → 709a918c.4fd3b4e2a32cb4e3.js} +1 -1
  78. package/apps/pwa/out/_next/static/chunks/717.522b08685979b814.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/7191.e41eb8f455c7f089.js +41 -0
  80. package/apps/pwa/out/_next/static/chunks/7233.8e744b7513119409.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7238-97c2226f80504bd8.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/7285.307963afcf7e7660.js +24 -0
  83. package/apps/pwa/out/_next/static/chunks/7299-fbe4b8c47a87614a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7314.df0d95930b0c3f50.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7406.c0589fdf2ee66629.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7424.c0fe2a595d4232b5.js +23 -0
  87. package/apps/pwa/out/_next/static/chunks/752-90e3e7daad3d8e39.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7524-bcd3d9928c6842d9.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7549.9a4de3bf231cfc52.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/757-4fbaf50942b8c424.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/765.76ae970ceb597b5b.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{7644.17e37ba6f1d4226e.js → 7867.e8725745ddd1d940.js} +4 -4
  93. package/apps/pwa/out/_next/static/chunks/7893-e444a1b0809cd1e4.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7956-33748cabb3a05562.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{0368f25d-ad84af92fefee68f.js → 7c5ed21f-f286708e57cf88f7.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8030-aa66b478b53dbfca.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8051.c88c07dacbbc5f21.js +8 -0
  98. package/apps/pwa/out/_next/static/chunks/{359-2250789a2d3499e7.js → 8080-40d781e7704d3671.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8149.80e402d4345e8dae.js +77 -0
  100. package/apps/pwa/out/_next/static/chunks/8205.50a5268f4e12ba0b.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8231.a128feaa6f8b6079.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/85.4ddb1dda2ea3ffa2.js +286 -0
  103. package/apps/pwa/out/_next/static/chunks/8537.26517a09e8247beb.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8595-e9b7081ab773a61f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8821-30cc65a61a60951f.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8905.b3385aadb7b133e6.js +79 -0
  107. package/apps/pwa/out/_next/static/chunks/8983.246bb3a1ac38f50f.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{b2f6ba4d.fb56fdbbf798df33.js → 8c58d09b.e8724a299658d86f.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/9072.18342f5941a1f3ec.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9123.9df04866b2d6e00f.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{1530.0e612369b6fd7ea0.js → 9151.a2c51e93f9156dae.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{4441-875b97f5821ed58a.js → 9175-7d383df15a82e2be.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9181-bf89c07ce5b8f599.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/920-429bbc4504b45f71.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9207.625edf45d656151c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9378.d2575c6ffd6dd756.js +94 -0
  117. package/apps/pwa/out/_next/static/chunks/957.db5b5c4d32a35240.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/958.53a8dcf4729e6997.js +64 -0
  119. package/apps/pwa/out/_next/static/chunks/9647.8f0cd0898c592a29.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9665-26abb02665704c2c.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9703.e7d81b6faef1050a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9882-7a9164b3c2dacbe5.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/9998.b74e033efadecd10.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-c604fb980a634d88.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ec2d8a4979ca9075.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-cb6add08ad3c7660.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/board/page-e2eaa321ec223fe6.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/botlab/page-5b8a09c475b5f844.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/bots/page-91a77daedfbac191.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/ceo/page-f37fc5e974bda39b.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/chat/page-91429a0b78415a94.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/consult/page-b95798b58263b910.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/control/page-763d53e175e17aa1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/decisions/page-d55023204055b12f.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/design-check/page-89d2140d78abc810.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/editor/page-82dc069abfe27f55.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/exec/page-25d9eee7beb552c0.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/field/page-770b4594c713ee97.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/healthz/route-c604fb980a634d88.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/inside/page-ba8e0dcae4f83985.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/intake/page-5c112c6d7c33656e.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/layout-09788e1aa9a87db6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live/page-3337c6a1328c2674.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/live-run/page-89acd5d68c0bc560.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/loops/page-5c13e2c76371d797.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/market/page-653a9f18642825c6.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-fe986fe79b107546.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/morning/{page-47c5d4db587266bd.js → page-1e5da297557d2354.js} +1 -1
  149. package/apps/pwa/out/_next/static/chunks/app/not-found-91ea9f5869a40943.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/observatory/page-7824e21b999962e2.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-53d00a60cc75a922.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/release/{page-1f5a60f70cb4dd0c.js → page-88a1edbff62eaf1d.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4e931248b3f9574b.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-bac7dee94e5eae4a.js → page-443364c9e4a23b31.js} +1 -1
  155. package/apps/pwa/out/_next/static/chunks/app/page-b9af2ac1c4737ce8.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/reflection/page-25ab9c614c14129b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-dbcdcfac0a395a8a.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bf1de6645089ec58.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-c4201761a5e839c9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/settings/page-c304f469ea5d70e4.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8e5a238cf5e50c9c.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/layout-c604fb980a634d88.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/page-32b526069ee50b3c.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/share/page-fb9e639c107f5f72.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/showroom/page-84220c776608cedc.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/tasks/page-e475618cbfd5ca2b.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/term/{page-dc0a532f5b9196ec.js → page-ac2c1e6169cfce57.js} +1 -1
  168. package/apps/pwa/out/_next/static/chunks/app/today/page-fccd3020af2f8806.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/trace/page-9c0d7198ff7b5a91.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/vault/page-d54b1ec9b9c6430d.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8c4bef1791d732ca.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workflows/page-46fcc0b0bbc6fbfe.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workspace/page-c1c80e345fa9d6f5.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-7dfda00afd172f5b.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{d06f9160.a3d9062f95de8ad7.js → d9815f84.4918f682a45a8502.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{cbe38a15.5a032598e39970c6.js → de8446d3.31b73eb239fecd7b.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/f21fd540.63ac75328926ed30.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-77fdcc873519a6cd.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-d0d620d2ce235713.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-e0ef79c79337ba90.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-84b1bc71e3f9ce6a.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-2acb61f1363128cb.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-462ff5727ceb7824.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  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 +23 -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/docs/goal-context/05-authoring-lessons.jsonl +47 -0
  279. package/docs/goal-context/README.md +3 -0
  280. package/graphs/default-loop.yaml +6 -1
  281. package/graphs/drafts/recipes.yaml +27 -7
  282. package/graphs/implement-loop.yaml +24 -0
  283. package/graphs/release/recipes.yaml +6 -0
  284. package/graphs/release/release-loop.yaml +17 -4
  285. package/graphs/wizard/recipes.yaml +44 -0
  286. package/graphs/wizard/wizard-loop.yaml +44 -0
  287. package/graphs/work/draft-close.yaml +54 -0
  288. package/graphs/work/green-close.yaml +37 -0
  289. package/graphs/work/recipes.yaml +46 -1
  290. package/graphs/work/research-report.yaml +2 -0
  291. package/graphs/work/run-research.yaml +35 -0
  292. package/package.json +1 -1
  293. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  294. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  295. package/scripts/ci-typecheck-changed.ts +139 -5
  296. package/scripts/codex-fallback-live-probe.ts +17 -15
  297. package/scripts/coord-role-pack.ts +1 -1
  298. package/scripts/first10-gate.ts +416 -0
  299. package/scripts/fleet/node-setup.sh +32 -2
  300. package/scripts/fleet/run-light-worker.sh +9 -0
  301. package/scripts/fleet/wsl-node-setup.sh +432 -0
  302. package/scripts/gate-0226-failure-census.ts +507 -0
  303. package/scripts/goals/authoring-metrics.ts +258 -0
  304. package/scripts/graph-units/draft-close-node.ts +222 -0
  305. package/scripts/hook-order-sweep.ts +7 -4
  306. package/scripts/land-global-checks.ts +69 -1
  307. package/scripts/measure-nl-routing-corpus.ts +207 -2
  308. package/scripts/release-loop/docs-node.ts +344 -8
  309. package/scripts/release-loop/gate-closure.ts +48 -0
  310. package/scripts/release-loop/gate-diff.ts +2 -1
  311. package/scripts/release-loop/gate-node.ts +249 -53
  312. package/scripts/release-loop/known-issues-node.ts +6 -4
  313. package/scripts/release-loop/node-verdict.ts +2 -0
  314. package/scripts/release-loop/notes-repair.ts +216 -0
  315. package/scripts/release-loop/prepare-node.ts +61 -5
  316. package/scripts/release-loop/resume-cap.ts +14 -34
  317. package/scripts/release-loop/resume-release.ts +151 -15
  318. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  319. package/scripts/release-loop/traffic-node.ts +59 -0
  320. package/scripts/release-loop/traffic-transition.ts +159 -0
  321. package/scripts/release-loop/version-node.ts +81 -12
  322. package/scripts/rhythm/daily.ts +137 -3
  323. package/scripts/train/green-leg.ts +176 -0
  324. package/scripts/tui-continue-real-evidence.ts +47 -0
  325. package/scripts/ux-sim.ts +53 -0
  326. package/skills/README.md +1 -0
  327. package/src/acp/client.ts +31 -5
  328. package/src/acp/core-turn-bridge.ts +54 -6
  329. package/src/acp/stderr-summary.ts +49 -0
  330. package/src/agent/delegate-hint.ts +16 -0
  331. package/src/agent/monad-agent-turn.ts +1 -0
  332. package/src/agent/runner.ts +82 -2
  333. package/src/agent/task-notification.ts +56 -10
  334. package/src/agent/terminal-surface.ts +217 -0
  335. package/src/agent/types.ts +4 -0
  336. package/src/agent-substrate/pr-reviewer.ts +64 -4
  337. package/src/agent-substrate/review-intent.ts +29 -2
  338. package/src/agent-substrate/review-observation.ts +3 -0
  339. package/src/agent-substrate/self-review-cli.ts +490 -26
  340. package/src/autopilot/lineage/sources.ts +1 -1
  341. package/src/autopilot/mission-codebase-gate.ts +141 -12
  342. package/src/autopilot/pr-manager.ts +89 -18
  343. package/src/boot/daemon-runtime.ts +35 -3
  344. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  345. package/src/boot/daemon-tools/self-implement.ts +1 -0
  346. package/src/budget/run-usage-rollup.ts +12 -7
  347. package/src/budget/unified-usage.ts +20 -0
  348. package/src/budget/usage-outcomes.ts +8 -4
  349. package/src/capture/tui-self-report.ts +132 -1
  350. package/src/chat/goal-continue-verdict.ts +41 -0
  351. package/src/chat/index.ts +30 -4
  352. package/src/chat/internal-turn-origin.ts +1 -0
  353. package/src/chat/paste-fold.ts +86 -0
  354. package/src/chat/tool-render/block.ts +32 -0
  355. package/src/chat/tool-render/dispatch.ts +2 -20
  356. package/src/chat/tool-render/result-text.ts +98 -0
  357. package/src/chat/turn-typeahead.ts +70 -7
  358. package/src/cli/autopilot-cli.ts +24 -9
  359. package/src/cli/config-audit.ts +119 -0
  360. package/src/cli/decisions-cli.ts +7 -4
  361. package/src/cli/doctor-cli.ts +137 -6
  362. package/src/cli/guardian-cli.ts +10 -0
  363. package/src/cli/herdr-cli.ts +34 -0
  364. package/src/cli/light-entry-route.ts +6 -3
  365. package/src/cli/log-event-names.ts +2 -0
  366. package/src/cli/logs-cli.ts +357 -2
  367. package/src/cli/make-cli.ts +247 -11
  368. package/src/cli/memory-cli.ts +30 -1
  369. package/src/cli/msg-cli.ts +132 -14
  370. package/src/cli/pr-cli.ts +29 -16
  371. package/src/cli/pr-granularity.ts +5 -3
  372. package/src/cli/pr-land-base-read.ts +11 -2
  373. package/src/cli/pr-land-heavy-remote.ts +6 -3
  374. package/src/cli/pr-land-overlap-evidence.ts +23 -4
  375. package/src/cli/pr-land-recovery.ts +117 -1
  376. package/src/cli/pty-takeover-cli.ts +8 -7
  377. package/src/cli/release-checklist-read-cli.ts +109 -4
  378. package/src/cli/release-cli.ts +64 -15
  379. package/src/cli/release-single-flight.ts +1 -1
  380. package/src/cli/self-update.ts +23 -5
  381. package/src/cli/self-utterances-cli.ts +13 -16
  382. package/src/cli/tasks-card-show.ts +162 -0
  383. package/src/cli/tasks-cli.ts +868 -352
  384. package/src/cli/tasks-read-cli.ts +197 -0
  385. package/src/cli/usage-cli.ts +12 -10
  386. package/src/context-bus/claude-memory-import.ts +99 -0
  387. package/src/context-bus/long-term-memory.ts +125 -0
  388. package/src/core-turn/run-core-turn.ts +4 -2
  389. package/src/core-turn/run-goal-loop.ts +76 -16
  390. package/src/core-turn/types.ts +8 -1
  391. package/src/dashboard/chat/acp-chat.ts +9 -0
  392. package/src/dashboard/context/keys.ts +8 -31
  393. package/src/dashboard/index.ts +299 -62
  394. package/src/dashboard/input/agent-wake.ts +50 -1
  395. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  396. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +146 -3
  397. package/src/dashboard/input/chat-main-slash-command.ts +4 -2
  398. package/src/dashboard/input/goal-continue.ts +210 -0
  399. package/src/dashboard/input/goal-interim.ts +2 -0
  400. package/src/dashboard/input/internal-turn.ts +2 -8
  401. package/src/dashboard/input/seat-autowake.ts +9 -7
  402. package/src/dashboard/input/turn-autoheal.ts +52 -0
  403. package/src/dashboard/replay-preview.ts +25 -0
  404. package/src/dashboard/seat-boot-preamble.ts +132 -5
  405. package/src/dashboard/slash-runtime/chat-persona.ts +65 -8
  406. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -10
  407. package/src/dashboard/slash-runtime/model-choices.ts +15 -0
  408. package/src/dashboard/stale-install-check.ts +3 -99
  409. package/src/dashboard/synchronized-frame-output.ts +74 -0
  410. package/src/debug/batch-queue.ts +119 -0
  411. package/src/debug/tui-log-tag.ts +67 -0
  412. package/src/display/agent-surface.ts +7 -0
  413. package/src/display/coordinator.ts +45 -12
  414. package/src/display/resize-listener.ts +41 -20
  415. package/src/display/synchronized-output-region.ts +60 -0
  416. package/src/domains/standalone-log-sink.ts +15 -2
  417. package/src/domains/surface-events.ts +80 -1
  418. package/src/esc-abort-gate.ts +69 -0
  419. package/src/exec-requests/planner.ts +37 -2
  420. package/src/execution-loop/launch-gate.ts +4 -3
  421. package/src/git-fs/cli-stderr.ts +45 -0
  422. package/src/git-fs/gh-cli.ts +6 -3
  423. package/src/git-fs/git-cli.ts +11 -5
  424. package/src/git-fs/worktree.ts +95 -1
  425. package/src/graph-runner/graph-cli.ts +44 -2
  426. package/src/graph-runner/graph-run-api.ts +3 -2
  427. package/src/graph-runner/runner.ts +37 -16
  428. package/src/graph-wizard/generate.ts +131 -4
  429. package/src/graph-wizard/steps.ts +15 -0
  430. package/src/grounding/proactive-ground.ts +86 -0
  431. package/src/harness/control-inbox.ts +49 -1
  432. package/src/harness/harness-cli-command.ts +230 -40
  433. package/src/harness/harness-incidents.ts +52 -1
  434. package/src/harness/pod-control-send.ts +33 -5
  435. package/src/harness/review-adapter.ts +26 -6
  436. package/src/harness/self-send-remote.ts +69 -0
  437. package/src/harness/self-send-routing-guard.ts +6 -0
  438. package/src/harness/self-send-target.ts +4 -3
  439. package/src/index.ts +443 -25
  440. package/src/input-core/context-key-runtime.ts +21 -0
  441. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  442. package/src/light-cli.ts +6 -1
  443. package/src/llm/route-decision.ts +13 -0
  444. package/src/llm-tool-name.ts +37 -0
  445. package/src/llm-tool-schema.ts +35 -0
  446. package/src/llm-wellformed.ts +70 -0
  447. package/src/llm.ts +158 -15
  448. package/src/loops/checker.ts +100 -0
  449. package/src/loops/consensus.ts +26 -2
  450. package/src/loops/loop-cli.ts +9 -4
  451. package/src/loops/msg-wake.ts +35 -39
  452. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  453. package/src/loops/orchestrator/inbox.ts +59 -11
  454. package/src/loops/orchestrator/knowhow-pack.ts +364 -0
  455. package/src/loops/orchestrator/tick.ts +54 -5
  456. package/src/maturity/feature-maturity.ts +1 -1
  457. package/src/model-tier/llm-tier-map.ts +12 -17
  458. package/src/models/prompts.ts +17 -2
  459. package/src/msg/msg-post-office.ts +116 -0
  460. package/src/msg/msg-store.ts +17 -0
  461. package/src/mss/logging/log-store.ts +79 -22
  462. package/src/native-tool-catalog.ts +1 -1
  463. package/src/nexus/api/decisions-route.ts +38 -18
  464. package/src/nexus/api/graph-wizard-api.ts +46 -3
  465. package/src/nexus/api/grid.ts +24 -4
  466. package/src/nexus/api/http-server.ts +1 -1
  467. package/src/nexus/api/ops-api.ts +14 -6
  468. package/src/nexus/boot/register-mcp-clients.ts +263 -38
  469. package/src/nexus/onboarding/first-boot-wizard.ts +56 -8
  470. package/src/nexus/state/state.ts +7 -1
  471. package/src/oauth/codex-account-store.ts +34 -1
  472. package/src/onboarding/first-run.ts +37 -6
  473. package/src/onboarding/web-first.ts +43 -11
  474. package/src/ops/loops-map.ts +46 -0
  475. package/src/ops/overview-cache.ts +22 -4
  476. package/src/ops/overview-collect.ts +12 -6
  477. package/src/ops/overview.ts +44 -8
  478. package/src/persona/loader.ts +11 -0
  479. package/src/persona/types.ts +8 -0
  480. package/src/policy/llm-policy.ts +3 -1
  481. package/src/prompt-enhance/enhance.ts +4 -4
  482. package/src/prompt-library/session-guidance.ts +14 -0
  483. package/src/provider-summary.ts +8 -0
  484. package/src/pty-shell/availability.ts +7 -0
  485. package/src/pty-shell/herdr-agent-report.ts +155 -37
  486. package/src/pty-shell/herdr-prompt.ts +266 -0
  487. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  488. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  489. package/src/pty-shell/pty-control-ipc.ts +327 -15
  490. package/src/pty-shell/pty-special-keys.ts +42 -2
  491. package/src/pty-shell/registry.ts +25 -15
  492. package/src/pty-shell/stale-install-check.ts +99 -0
  493. package/src/pty-shell/tui-run-state.ts +249 -3
  494. package/src/release-loop/auto-start.ts +20 -2
  495. package/src/release-loop/checklist.ts +126 -9
  496. package/src/release-loop/feature-store.ts +9 -9
  497. package/src/release-loop/landed-but-yellow.ts +93 -12
  498. package/src/release-loop/rehearsal.ts +36 -20
  499. package/src/repl/index.ts +27 -1
  500. package/src/seat-loop/knowhow-lint.ts +1 -1
  501. package/src/seat-loop/seat-report.ts +1 -0
  502. package/src/self-dev/ask-launch-flow.ts +86 -10
  503. package/src/self-dev/decompose-proposal.ts +183 -20
  504. package/src/self-dev/decompose.ts +61 -0
  505. package/src/self-dev/dev-cli.ts +37 -3
  506. package/src/self-dev/dev-pipeline.ts +37 -9
  507. package/src/self-dev/draft-sweep.ts +241 -16
  508. package/src/self-dev/draft-triage-rules.ts +50 -5
  509. package/src/self-dev/glm-credential-guard.ts +77 -0
  510. package/src/self-dev/graph-journey-nodes.ts +1 -0
  511. package/src/self-dev/graph-journey-route.ts +12 -2
  512. package/src/self-dev/orchestrate-cli.ts +68 -3
  513. package/src/self-dev/orchestrate.ts +116 -17
  514. package/src/self-dev/review-provider-fallback.ts +45 -7
  515. package/src/self-dev/run-supervisor.ts +55 -2
  516. package/src/self-dev/run-types.ts +1 -1
  517. package/src/self-dev/shard-plan.ts +48 -0
  518. package/src/self-dev/shard-run.ts +50 -3
  519. package/src/self-health/autoheal.ts +153 -0
  520. package/src/self-health/signatures.ts +6 -0
  521. package/src/self-implement/device-first.ts +116 -0
  522. package/src/self-implement/doctor-visit.ts +322 -1
  523. package/src/self-implement/evidence-command-budget.ts +80 -0
  524. package/src/self-implement/gate-artifacts.ts +6 -2
  525. package/src/self-implement/gate-baseline.ts +64 -1
  526. package/src/self-implement/gate-cli.ts +93 -9
  527. package/src/self-implement/gate-remote.ts +28 -4
  528. package/src/self-implement/gate-scope.ts +13 -1
  529. package/src/self-implement/goal-author-cli.ts +1 -0
  530. package/src/self-implement/goal-author-decompose.ts +265 -4
  531. package/src/self-implement/goal-author.ts +366 -26
  532. package/src/self-implement/goal-elaborate.ts +176 -22
  533. package/src/self-implement/goal-refine.ts +3 -0
  534. package/src/self-implement/goal-supervisor-fill.ts +75 -26
  535. package/src/self-implement/graph-variant.ts +40 -6
  536. package/src/self-implement/headless-elanous-driver.ts +19 -3
  537. package/src/self-implement/importer-test-index.ts +215 -2
  538. package/src/self-implement/knowhow-pack.ts +5 -5
  539. package/src/self-implement/off-diff-evidence.ts +58 -6
  540. package/src/self-implement/orchestrator.ts +536 -42
  541. package/src/self-implement/pod-warm-pool-profile.ts +1 -0
  542. package/src/self-implement/pwa-import-graph.ts +1 -1
  543. package/src/self-implement/review-round-brief.ts +300 -0
  544. package/src/self-implement/rework-policy.ts +44 -0
  545. package/src/self-implement/run-ledger.ts +278 -6
  546. package/src/self-implement/run-stop.ts +1 -1
  547. package/src/self-implement/run-ttl.ts +38 -24
  548. package/src/self-implement/running-runs.ts +17 -3
  549. package/src/self-implement/scope-adjacency.ts +3 -1
  550. package/src/self-implement/seams.ts +72 -10
  551. package/src/self-implement/stop-autoheal.ts +1 -0
  552. package/src/self-implement/test-seams.ts +13 -1
  553. package/src/self-implement/train-reach-grouping.ts +8 -2
  554. package/src/self-implement/wiring-check.ts +358 -0
  555. package/src/session/chat.ts +7 -1
  556. package/src/session/id-prefix.ts +60 -0
  557. package/src/session/index.ts +4 -0
  558. package/src/session-runtime/index.ts +9 -1
  559. package/src/shell-env-bootstrap.ts +11 -4
  560. package/src/skills/runner.ts +4 -2
  561. package/src/skills/tools/agent.ts +290 -48
  562. package/src/skills/tools/pty.ts +5 -0
  563. package/src/skills/tools/schedule-wakeup.ts +23 -4
  564. package/src/skills/tools/shell.ts +61 -6
  565. package/src/skills/tools/terminal-modal-inject.ts +1 -2
  566. package/src/skills/tools/terminal-modal.ts +10 -8
  567. package/src/skills/url-router.ts +41 -1
  568. package/src/smart-wizard/run.ts +66 -0
  569. package/src/status/bar.ts +34 -6
  570. package/src/status/metrics.ts +12 -1
  571. package/src/status/status-provider-info.ts +37 -6
  572. package/src/steward/rejudge-tick.ts +22 -7
  573. package/src/steward/resync-tick.ts +31 -4
  574. package/src/steward/ta-repair-event-collect.ts +17 -6
  575. package/src/task-agent/actions.ts +202 -5
  576. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  577. package/src/task-agent/boundary-proof-producer.ts +147 -0
  578. package/src/task-agent/completion-evidence.ts +2 -1
  579. package/src/task-agent/green-close-recipe.ts +239 -0
  580. package/src/task-agent/green-sweep.ts +64 -10
  581. package/src/task-agent/land-queue.ts +21 -8
  582. package/src/task-agent/live-moves.ts +70 -9
  583. package/src/task-agent/map-host-adapter.ts +134 -0
  584. package/src/task-agent/map-reduce.ts +158 -0
  585. package/src/task-agent/map-run-ledger.ts +226 -0
  586. package/src/task-agent/mission.ts +30 -0
  587. package/src/task-agent/parent-host.ts +21 -11
  588. package/src/task-agent/rejudge-on-head.ts +87 -5
  589. package/src/task-agent/repair-cycle.ts +179 -32
  590. package/src/task-agent/repair-next-move.ts +42 -4
  591. package/src/task-agent/repair-outcomes.ts +29 -0
  592. package/src/task-agent/repair-worker.ts +14 -4
  593. package/src/task-agent/review-prior-fix.ts +12 -2
  594. package/src/task-agent/shadow.ts +229 -8
  595. package/src/task-agent/task-card-prefix.ts +2 -0
  596. package/src/task-agent/task-hand.ts +630 -30
  597. package/src/task-agent/task-parent-role-llm.ts +45 -0
  598. package/src/task-agent/tier-split.ts +80 -10
  599. package/src/task-agent/work-order.ts +53 -2
  600. package/src/task-orchestrator/dispatcher.ts +46 -1
  601. package/src/task-orchestrator/generator-prompt.ts +6 -0
  602. package/src/task-orchestrator/surfaces/pod-account-broker.ts +9 -0
  603. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  604. package/src/task-orchestrator/surfaces/pod-child-reuse.ts +146 -0
  605. package/src/task-orchestrator/surfaces/pod-command-job.ts +86 -5
  606. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +215 -3
  607. package/src/task-orchestrator/surfaces/pod-launch-history.ts +133 -0
  608. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  609. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  610. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +11 -0
  611. package/src/task-orchestrator/surfaces/pod-pool.ts +126 -8
  612. package/src/task-orchestrator/surfaces/pod-provenance.ts +8 -2
  613. package/src/task-orchestrator/surfaces/pod-repair-commit.ts +18 -3
  614. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +16 -0
  615. package/src/task-orchestrator/surfaces/pod-si-warm-host.ts +224 -0
  616. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +201 -0
  617. package/src/task-orchestrator/surfaces/pod-si-warm-provider.ts +444 -0
  618. package/src/task-orchestrator/surfaces/pod-si-warm-runner.ts +387 -0
  619. package/src/task-orchestrator/surfaces/pod-si-warm-transport.ts +157 -0
  620. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +4 -0
  621. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +491 -36
  622. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +3 -0
  623. package/src/task-orchestrator/surfaces/self-implement-pod.ts +612 -54
  624. package/src/task-orchestrator/surfaces/self-implement.ts +46 -2
  625. package/src/testing/linux-env.ts +177 -0
  626. package/src/tool-runtime/index.ts +15 -2
  627. package/src/tool-runtime/mcp-proxy-bootstrap.ts +29 -0
  628. package/src/tty-foreground.ts +155 -0
  629. package/src/tui/chat/goal-interim.ts +177 -0
  630. package/src/tui/chat/log-view.ts +205 -18
  631. package/src/tui/chat/self-health-status.ts +232 -0
  632. package/src/tui/entry.ts +623 -80
  633. package/src/tui/input/at-picker.ts +55 -0
  634. package/src/tui/input/composer.ts +8 -1
  635. package/src/tui/slash/compact-command.ts +7 -0
  636. package/src/tui/slash/compact.ts +1 -7
  637. package/src/tui/slash/resume.ts +98 -0
  638. package/src/tui/slash/signals.ts +114 -0
  639. package/src/tui/slash/term-next.ts +71 -0
  640. package/src/tui-client/local-chat-turn.ts +49 -5
  641. package/src/tui-client/next-dashboard-runtime.ts +8 -0
  642. package/src/tui-client/next-loop-command.ts +70 -0
  643. package/src/tui-client/next-wakeup.ts +191 -0
  644. package/src/tui.ts +37 -0
  645. package/src/ui/modal-adapter.ts +2 -2
  646. package/src/user-config.ts +19 -1
  647. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  648. package/src/ux-sim/classic-tui-seat-scenarios.ts +670 -0
  649. package/src/ux-sim/cli-config-audit-device.ts +121 -0
  650. package/src/ux-sim/dashboard-event-loop-stall-monitor-device.ts +238 -0
  651. package/src/ux-sim/event-monkey.ts +3 -2
  652. package/src/ux-sim/fake-bin.ts +45 -0
  653. package/src/ux-sim/fake-gh.ts +174 -0
  654. package/src/ux-sim/fake-herdr.ts +238 -0
  655. package/src/ux-sim/fake-kubectl.ts +142 -0
  656. package/src/ux-sim/fake-llm.ts +116 -6
  657. package/src/ux-sim/fault-glm-no-credential.ts +116 -0
  658. package/src/ux-sim/fault-nextmove-dispatch.ts +102 -1
  659. package/src/ux-sim/fault-scope-escape-lift.ts +33 -6
  660. package/src/ux-sim/fault-tui-400-autoheal.ts +297 -0
  661. package/src/ux-sim/goal-device.ts +619 -0
  662. package/src/ux-sim/in-process-cli.ts +22 -5
  663. package/src/ux-sim/mock-authoring-first-run-child.ts +35 -0
  664. package/src/ux-sim/mock-authoring-first-run.ts +97 -0
  665. package/src/ux-sim/mock-seat-pty-frame-child.ts +29 -0
  666. package/src/ux-sim/mock-seat-pty-frame.ts +297 -0
  667. package/src/ux-sim/mock-seat-pty-sequence-child.ts +21 -0
  668. package/src/ux-sim/mock-seat-pty-sequence.ts +206 -0
  669. package/src/ux-sim/next-tui-seat-scenarios.ts +749 -0
  670. package/src/ux-sim/onboarding-first-run-device.ts +269 -0
  671. package/src/ux-sim/pty-key-modifiers-device.ts +85 -0
  672. package/src/ux-sim/resume-picker-device.ts +173 -0
  673. package/src/ux-sim/session-id-seed.ts +60 -0
  674. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  675. package/src/ux-sim/subagent-tools-device.ts +81 -0
  676. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  677. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  678. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +250 -0
  679. package/src/ux-sim/tty-foreground-steal-child.ts +21 -0
  680. package/src/version/packed-revision.json +1 -1
  681. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +0 -41
  682. package/apps/pwa/out/_next/static/chunks/1674.2a65fd5668e1cc5f.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +0 -24
  684. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +0 -74
  685. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/1993-c0007b7ad0c0ef41.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/1c735de4.f993a30bbd3c57c4.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +0 -148
  694. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/2625.5d870aa999f33db1.js +0 -34
  696. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +0 -77
  697. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +0 -62
  699. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +0 -90
  701. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +0 -36
  705. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/3677-4215f826f6aa68e5.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +0 -79
  708. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/4346.8601952e73bf5803.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +0 -286
  712. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +0 -24
  715. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/5154.a118f3957ed14e36.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +0 -23
  724. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +0 -94
  725. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/56d372f2.681ab4ec4c998fae.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +0 -287
  729. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +0 -8
  736. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +0 -27
  739. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +0 -93
  741. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/6b89c8bd.24df687a820500b3.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +0 -149
  747. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +0 -104
  748. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/8219.baa715d1deee80e2.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/8256.e3ac8421a71f82f4.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +0 -226
  758. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +0 -64
  760. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/8637.47f5b35afcae5e6b.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +0 -115
  767. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/967-2aa39b2d04b4c690.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/control/page-406b47745b53f269.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +0 -1
  802. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +0 -1
  803. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +0 -1
  804. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +0 -1
  805. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +0 -1
  806. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +0 -1
  807. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +0 -1
  808. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +0 -1
  809. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +0 -1
  810. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +0 -1
  811. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +0 -1
  812. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +0 -1
  813. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +0 -1
  814. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +0 -1
  815. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +0 -1
  816. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +0 -1
  817. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +0 -1
  818. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +0 -1
  819. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +0 -1
  820. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +0 -1
  821. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +0 -1
  822. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +0 -1
  823. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +0 -1
  824. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +0 -1
  825. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +0 -1
  826. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +0 -1
  827. /package/apps/pwa/out/_next/static/{T1mBQqmkwKDLGtyisDCOd → 8kITumG9GAZ1LwT9POrAR}/_ssgManifest.js +0 -0
@@ -2,6 +2,7 @@ import { CLAIM_IDLE_HOURS, PR_LABELS, STALLED_DRAFT_HOURS } from '../github/pr-l
2
2
  import { debug } from '../debug/log.js';
3
3
  import { assessDraftTriage, decideDraft, draftClaimComment, draftClaimState, draftReleaseComment, laterMergedTwins, sameGoalPr, PROTECTED_LABELS, type DraftTriageAssessment, type DraftTriagePr, type DraftTriageReviewState } from './draft-triage-rules.js';
4
4
  import { cellIdFromBody } from '../pr-tool/census.js';
5
+ import { RELEASE_PATH_LABEL } from './release-path-guard.js';
5
6
  import { cardPrNumber, draftTaskOwner, type TaskCard } from '../task-agent/task-hand.js';
6
7
  import type { PrTerminalRecord } from './draft-residue.js';
7
8
  import { branchLineageSlug } from '../cli/pr-lineage.js';
@@ -13,6 +14,7 @@ export interface SweepDraft extends DraftTriagePr {
13
14
  readonly createdAt: string;
14
15
  /** Last PR update (push, label, comment). Missing ⇒ no idle-based close; merged twins can still close. */
15
16
  readonly updatedAt?: string;
17
+ readonly headSha?: string;
16
18
  readonly runId?: string | null;
17
19
  }
18
20
 
@@ -26,17 +28,22 @@ export interface SweepMergedPr extends DraftTriagePr {
26
28
  export interface DraftSweepAdapters {
27
29
  /** Each call returns one complete page; a rejection must not be mistaken for an empty page. */
28
30
  listDrafts(page: number, perPage: number, repository: string): Promise<readonly SweepDraft[]>;
31
+ /** Optional completeness of a bounded inventory; a partial inventory can inform dry-run only. */
32
+ inventoryStatus?(): Promise<{ complete: boolean; reason?: string }>;
29
33
  /** Head commit time is fetched only for explicit triage, where it gates idle/close recommendations. */
30
34
  getHeadCommitTime?(repository: string, number: number): Promise<string | undefined>;
31
35
  listMerged(page: number, perPage: number, repository: string): Promise<readonly SweepMergedPr[]>;
32
36
  /** Complete closed PR inventory for the creation cohort (including closed without merge). */
33
37
  listRecentClosed?(repository: string, createdSince: Date): Promise<readonly SweepMergedPr[]>;
34
38
  /** Undefined means no run assessment; a merged twin or 24h idle draft can still authorize a close. */
35
- getRunStatus(draft: SweepDraft, repository: string): Promise<string | undefined>;
39
+ /** Intentionally needs identity only: adapters must not couple sweep status lookup to presentation fields. */
40
+ getRunStatus(draft: Pick<SweepDraft, 'number' | 'branch' | 'runId'>, repository: string): Promise<string | undefined>;
36
41
  /** Undefined means liveness could not be established. */
37
42
  listLiveBranches(repository: string): Promise<ReadonlySet<string> | undefined>;
38
43
  setLabels(repository: string, number: number, change: { add: string; remove: readonly string[] }): Promise<void>;
39
44
  closeDraft(repository: string, number: number): Promise<void>;
45
+ /** Minimal live identity check used by snapshot apply; no repository-wide inventory is read. */
46
+ getDraftSnapshot?(repository: string, number: number): Promise<DraftSweepSnapshot | undefined>;
40
47
  /** Resolve the latest claim comment owner; a failed lookup must not authorize a close. */
41
48
  getClaimOwner?(repository: string, number: number): Promise<string | undefined>;
42
49
  /** Current owner, accounting for a later claim release; only draft metrics need this distinction. */
@@ -71,7 +78,28 @@ export interface DraftSweepAdapters {
71
78
  * Must reject when the run could not be stopped — the draft is then neither labelled nor closed.
72
79
  * Absent ⇒ a live duplicate is kept, never closed.
73
80
  */
74
- supersedeRun?(draft: SweepDraft, repository: string, newer: SweepDraft): Promise<void>;
81
+ /** Same minimal identity contract as getRunStatus; stopping authority is scoped to the selected run pair. */
82
+ supersedeRun?(draft: Pick<SweepDraft, 'number' | 'branch' | 'runId'>, repository: string,
83
+ newer: Pick<SweepDraft, 'number' | 'branch' | 'runId'>): Promise<void>;
84
+ }
85
+
86
+ export interface DraftSweepSnapshot {
87
+ readonly number: number;
88
+ readonly state: 'open' | 'closed';
89
+ readonly draft: boolean;
90
+ readonly headSha: string;
91
+ readonly branch: string;
92
+ readonly updatedAt: string;
93
+ readonly labels: readonly string[];
94
+ }
95
+
96
+ export interface DraftSweepApplyPlan {
97
+ readonly version: 1;
98
+ readonly closeCap: number;
99
+ readonly closeCapSource: DraftSweepCloseCapSource;
100
+ readonly entries: readonly (DraftSweepEntry & { readonly headSha: string; readonly branch: string; readonly runId?: string;
101
+ readonly stopRunRequired?: boolean; readonly supersedeNewer?: { readonly number: number; readonly branch: string; readonly runId?: string };
102
+ readonly updatedAt: string; readonly labels: readonly string[] })[];
75
103
  }
76
104
 
77
105
  /** Review PASS and gate posture used only by the daily old-draft count. */
@@ -95,6 +123,10 @@ export interface DraftSweepOptions {
95
123
  alreadyClosed?: number;
96
124
  /** Include evidence-backed next-action recommendations in JSON output; never authorizes writes. */
97
125
  includeTriage?: boolean;
126
+ /** Build a frozen apply plan from a complete dry-run classification. */
127
+ includeApplyPlan?: boolean;
128
+ /** Apply exactly this plan after live identity preflight. */
129
+ applyPlan?: DraftSweepApplyPlan;
98
130
  }
99
131
 
100
132
  export interface DraftSweepEntry {
@@ -113,6 +145,7 @@ export interface DraftSweepResult {
113
145
  apply: boolean;
114
146
  complete: boolean;
115
147
  entries: DraftSweepEntry[];
148
+ applyPlan?: DraftSweepApplyPlan;
116
149
  triage?: { entries: Array<{ number: number; assessment: DraftTriageAssessment }>; counts: Record<string, number> };
117
150
  counts: Record<string, number>;
118
151
  /** Drafts whose run could not be observed from here (kept, or closed by the idle rule). */
@@ -260,9 +293,26 @@ export async function collectDraftMetrics(repository: string, adapters: Pick<Dra
260
293
  || (pr.mergedAt !== undefined && !Number.isFinite(Date.parse(pr.mergedAt)))
261
294
  || !Array.isArray(pr.labels) || pr.labels.some((name) => typeof name !== 'string')))
262
295
  throw new Error('Incomplete draft metric inventory');
263
- if (new Set(drafts.map((pr) => pr.number)).size !== drafts.length
264
- || new Set(closed.map((pr) => pr.number)).size !== closed.length) throw new Error('Duplicate draft metric PR');
265
- const open = drafts.filter(harnessDraft);
296
+ // Fold each source independently; a merged closed row outranks an unmerged snapshot.
297
+ // The serialized row is a stable tie-breaker when timestamps match, regardless of page order.
298
+ const fold = <T extends { number: number }>(rows: readonly T[], rank: (pr: T) => readonly number[]): T[] => {
299
+ const byNumber = new Map<number, T>();
300
+ for (const row of rows) {
301
+ const prior = byNumber.get(row.number);
302
+ if (prior) {
303
+ const a = rank(row), b = rank(prior);
304
+ const order = a.reduce((result, value, index) => result || value - b[index]!, 0);
305
+ if (order < 0 || (order === 0 && JSON.stringify(row) <= JSON.stringify(prior))) continue;
306
+ }
307
+ byNumber.set(row.number, row);
308
+ }
309
+ return [...byNumber.values()];
310
+ };
311
+ const uniqueDrafts = fold(drafts, (pr) => [Number.isFinite(Date.parse(pr.updatedAt ?? ''))
312
+ ? Date.parse(pr.updatedAt!) : Date.parse(pr.createdAt), Date.parse(pr.createdAt)]);
313
+ const uniqueClosed = fold(closed, (pr) => [pr.mergedAt ? 1 : 0,
314
+ pr.mergedAt ? Date.parse(pr.mergedAt) : Date.parse(pr.createdAt!), Date.parse(pr.createdAt!)]);
315
+ const open = uniqueDrafts.filter(harnessDraft);
266
316
  const owners = await Promise.all(open.map(async (draft) => {
267
317
  if (!adapters.getActiveClaimOwner) throw new Error('Draft owner lookup unavailable');
268
318
  const owner = await adapters.getActiveClaimOwner(repository, draft.number);
@@ -270,9 +320,12 @@ export async function collectDraftMetrics(repository: string, adapters: Pick<Dra
270
320
  return owner;
271
321
  }));
272
322
  const cohort = [...open.filter((pr) => Date.parse(pr.createdAt) >= cutoff && Date.parse(pr.createdAt) <= matured),
273
- ...closed.filter((pr) => (pr.branch.startsWith('self-impl/') || pr.labels!.some((name) => name.startsWith('elanous:')))
323
+ ...uniqueClosed.filter((pr) => (pr.branch.startsWith('self-impl/') || pr.labels!.some((name) => name.startsWith('elanous:')))
274
324
  && pr.createdAt && Date.parse(pr.createdAt) >= cutoff && Date.parse(pr.createdAt) <= matured)];
275
325
  if (new Set(cohort.map((pr) => pr.number)).size !== cohort.length) throw new Error('Overlapping draft metric inventory');
326
+ const folded = drafts.length - uniqueDrafts.length + closed.length - uniqueClosed.length;
327
+ if (folded) try { debug.log('drafts.metrics', 'duplicate-pr-folded', { repository, drafts: drafts.length - uniqueDrafts.length,
328
+ closed: closed.length - uniqueClosed.length, folded }); } catch { /* fail-soft */ }
276
329
  const converted48h = cohort.filter((pr) => 'mergedAt' in pr && typeof pr.mergedAt === 'string'
277
330
  && Date.parse(pr.mergedAt) >= Date.parse(pr.createdAt!) && Date.parse(pr.mergedAt) <= clock
278
331
  && Date.parse(pr.mergedAt) - Date.parse(pr.createdAt!) <= 48 * 3_600_000).length;
@@ -770,6 +823,17 @@ function harnessDraft(draft: SweepDraft): boolean {
770
823
  return draft.branch.startsWith('self-impl/') || draft.labels.some((name) => name.startsWith('elanous:'));
771
824
  }
772
825
 
826
+ /** A prior final event is authoritative only when the branch is not observably live. */
827
+ function isLiveDraftRun(status: string | undefined, branch: string, liveBranches: ReadonlySet<string>): boolean {
828
+ return status === 'running' || status === 'probable-running'
829
+ || (status !== 'self-implement.result final' && liveBranches.has(branch));
830
+ }
831
+
832
+ function isKnownSweepCloseReason(reason: string): boolean {
833
+ return ['superseded-by #', 'duplicate-of-open #', 'claim-expired', 'stale-unobserved', 'harvest-expired', 'stale-ended-run']
834
+ .some((prefix) => reason === prefix || reason.startsWith(prefix));
835
+ }
836
+
773
837
  /**
774
838
  * The newest open draft of the same goal lineage that was created strictly after `draft` — a rerun
775
839
  * (e.g. a forced requeue) of the same goal. Reads only the branch, so a draft with no task card still has a lineage.
@@ -835,8 +899,130 @@ export function draftSweepDaily(
835
899
  return { date: now.toISOString().slice(0, 10), over24h, closable, harvestable, blocked };
836
900
  }
837
901
 
902
+ /** Validate serialized plans at the CLI boundary; malformed or ambiguous plans must never reach a writer. */
903
+ export function validateDraftSweepApplyPlan(value: unknown): DraftSweepApplyPlan {
904
+ if (!value || typeof value !== 'object') throw new Error('invalid draft sweep apply plan');
905
+ const plan = value as Partial<DraftSweepApplyPlan>;
906
+ if (plan.version !== 1 || !validCloseCap(plan.closeCap)
907
+ || !['flag', 'config', 'default'].includes(String(plan.closeCapSource)) || !Array.isArray(plan.entries)) {
908
+ throw new Error('invalid draft sweep apply plan header');
909
+ }
910
+ const seen = new Set<number>();
911
+ for (const entry of plan.entries) {
912
+ if (!entry || !Number.isSafeInteger(entry.number) || entry.number! < 1 || seen.has(entry.number!)
913
+ || !['keep', 'close', 'report'].includes(entry.action) || typeof entry.reason !== 'string'
914
+ || (entry.action === 'close' && !isKnownSweepCloseReason(entry.reason))
915
+ || typeof entry.headSha !== 'string' || !/^[a-f0-9]{40}$/i.test(entry.headSha)
916
+ || typeof entry.branch !== 'string' || !entry.branch
917
+ || (entry.statusLabel !== undefined && !stateLabels.some((state) => state.name === entry.statusLabel))
918
+ || (entry.supersedeNewer !== undefined && (!Number.isSafeInteger(entry.supersedeNewer.number)
919
+ || entry.supersedeNewer.number < 1 || entry.supersedeNewer.number === entry.number
920
+ || typeof entry.supersedeNewer.branch !== 'string' || !entry.supersedeNewer.branch
921
+ || (entry.supersedeNewer.runId !== undefined && typeof entry.supersedeNewer.runId !== 'string')))
922
+ || typeof entry.updatedAt !== 'string' || !Number.isFinite(Date.parse(entry.updatedAt))
923
+ || !Array.isArray(entry.labels) || entry.labels.some((name: unknown) => typeof name !== 'string')
924
+ || (entry.stopRunRequired === true && (!entry.runId || !entry.supersedeNewer?.runId))
925
+ || (entry.supersedeNewer !== undefined && entry.stopRunRequired !== true)) {
926
+ throw new Error('invalid draft sweep apply plan entry');
927
+ }
928
+ seen.add(entry.number!);
929
+ }
930
+ const closes = plan.entries.filter((entry) => entry.action === 'close').length;
931
+ if (closes > plan.closeCap!) throw new Error('draft sweep apply plan exceeds close cap');
932
+ return value as DraftSweepApplyPlan;
933
+ }
934
+
935
+ async function applyDraftSweepPlan(repository: string, adapters: DraftSweepAdapters, planInput: DraftSweepApplyPlan): Promise<DraftSweepResult> {
936
+ const plan = validateDraftSweepApplyPlan(planInput);
937
+ const result: DraftSweepResult = { repository, apply: true, complete: false, entries: plan.entries.map(({ number, action, reason, statusLabel }) => ({
938
+ number, action, reason, ...(statusLabel ? { statusLabel } : {}), applied: false,
939
+ })), counts: {}, closeCap: plan.closeCap, closeCapSource: plan.closeCapSource };
940
+ const writable = plan.entries.filter((entry) => entry.action !== 'report' && (entry.action === 'close' || Boolean(entry.statusLabel)));
941
+ const preflightEntries = new Map(writable.map((entry) => [entry.number, entry]));
942
+ for (const entry of writable) if (entry.supersedeNewer) {
943
+ const newer = plan.entries.find((candidate) => candidate.number === entry.supersedeNewer!.number);
944
+ if (!newer) { result.error = `snapshot apply plan missing newer PR #${entry.supersedeNewer.number}`; return result; }
945
+ preflightEntries.set(newer.number, newer);
946
+ }
947
+ if (!adapters.getDraftSnapshot) { result.error = 'draft snapshot preflight unavailable'; return result; }
948
+ // Read and validate every target before the first mutation: one stale item blocks the whole write batch.
949
+ const snapshots = await mapBounded([...preflightEntries.values()], DRAFT_SWEEP_CONCURRENCY, async (entry) => ({ entry,
950
+ current: await adapters.getDraftSnapshot!(repository, entry.number) }));
951
+ const drift = snapshots.find(({ entry, current }) => !current || current.number !== entry.number || current.state !== 'open'
952
+ || current.draft !== true || current.headSha !== entry.headSha || current.branch !== entry.branch || current.updatedAt !== entry.updatedAt
953
+ || current.labels.length !== entry.labels.length || [...current.labels].sort().join('\0') !== [...entry.labels].sort().join('\0'));
954
+ if (drift) {
955
+ const number = drift.entry.number;
956
+ result.error = `draft snapshot drift at #${number}; no writes performed`;
957
+ for (const entry of result.entries) if (writable.some((item) => item.number === entry.number)) entry.error = result.error;
958
+ return result;
959
+ }
960
+ const stopPlans = writable.filter((entry) => entry.stopRunRequired === true);
961
+ const stoppedRuns = new Set<number>();
962
+ if (stopPlans.length) {
963
+ if (!adapters.supersedeRun || !adapters.getRunStatus || !adapters.listLiveBranches
964
+ || stopPlans.some((entry) => !entry.runId || !entry.supersedeNewer?.runId)) {
965
+ result.error = 'snapshot apply cannot verify live duplicate run ownership';
966
+ return result;
967
+ }
968
+ const branches = await adapters.listLiveBranches(repository);
969
+ if (!branches) { result.error = 'snapshot apply cannot verify branch liveness'; return result; }
970
+ const liveChecks = await Promise.all(stopPlans.map(async (entry) => {
971
+ const newer = entry.supersedeNewer!;
972
+ const [oldStatus, newerStatus] = await Promise.all([
973
+ adapters.getRunStatus!({ number: entry.number, branch: entry.branch, runId: entry.runId }, repository),
974
+ adapters.getRunStatus!({ number: newer.number, branch: newer.branch, runId: newer.runId }, repository),
975
+ ]);
976
+ return { entry, newer, oldStatus, newerStatus, ok: isLiveDraftRun(oldStatus, entry.branch, branches)
977
+ && isLiveDraftRun(newerStatus, newer.branch, branches) };
978
+ }));
979
+ const invalid = liveChecks.find((check) => !check.ok);
980
+ if (invalid) { result.error = `live duplicate run state drift at #${invalid.entry.number}; no PR writes performed`; return result; }
981
+ for (const check of liveChecks) {
982
+ try {
983
+ await adapters.supersedeRun!({ number: check.entry.number, branch: check.entry.branch, runId: check.entry.runId }, repository,
984
+ { number: check.newer.number, branch: check.newer.branch, runId: check.newer.runId });
985
+ stoppedRuns.add(check.entry.number);
986
+ } catch (error) { result.error = `could not stop planned run at #${check.entry.number}: ${sweepFailureReason(error)}`; return result; }
987
+ }
988
+ }
989
+ for (const { entry } of snapshots) {
990
+ const output = result.entries.find((item) => item.number === entry.number)!;
991
+ let mutated = false;
992
+ try {
993
+ if (entry.action === 'close' && entry.reason.startsWith('claim-expired')) {
994
+ // A complete comment inventory with no owner marker is valid; incomplete/unreadable inventories throw.
995
+ // The owner value itself is not a close criterion; classification and updatedAt preflight own that decision.
996
+ if (!adapters.getClaimOwner) throw new Error('claim owner lookup unavailable');
997
+ await adapters.getClaimOwner(repository, entry.number);
998
+ }
999
+ if (entry.statusLabel) {
1000
+ const remove = stateLabels.filter((item) => entry.labels.includes(item.name) && item.name !== entry.statusLabel).map((item) => item.name);
1001
+ if (!entry.labels.includes(entry.statusLabel) || remove.length) {
1002
+ await adapters.setLabels(repository, entry.number, { add: entry.statusLabel, remove });
1003
+ mutated = true;
1004
+ }
1005
+ }
1006
+ if (entry.action === 'close') {
1007
+ await closeSweptDraft(adapters, repository, entry.number, entry.reason, () => { mutated = true; });
1008
+ }
1009
+ output.applied = mutated;
1010
+ } catch (error) {
1011
+ if ((mutated && entry.action === 'close') || stoppedRuns.has(entry.number)) output.partialApplied = true;
1012
+ output.error = sweepFailureReason(error);
1013
+ result.error = `snapshot apply failed at #${entry.number}: ${output.error}`;
1014
+ return result;
1015
+ }
1016
+ }
1017
+ result.complete = true;
1018
+ result.closed = plan.entries.filter((entry) => entry.action === 'close').length;
1019
+ for (const entry of result.entries) result.counts[entry.reason] = (result.counts[entry.reason] ?? 0) + 1;
1020
+ return result;
1021
+ }
1022
+
838
1023
  /** A failed inventory or liveness lookup is never treated as proof that a draft can be closed. */
839
- export async function runDraftSweep({ repository, adapters, apply = false, now = new Date(), closeCap: requestedCap, closeCapSource: requestedSource, alreadyClosed = 0, includeTriage = false }: DraftSweepOptions): Promise<DraftSweepResult> {
1024
+ export async function runDraftSweep({ repository, adapters, apply = false, now = new Date(), closeCap: requestedCap, closeCapSource: requestedSource, alreadyClosed = 0, includeTriage = false, includeApplyPlan = false, applyPlan }: DraftSweepOptions): Promise<DraftSweepResult> {
1025
+ if (applyPlan) return applyDraftSweepPlan(repository, adapters, applyPlan);
840
1026
  const validCap = validCloseCap(requestedCap);
841
1027
  const closeCap = validCap ?? DRAFT_SWEEP_CLOSE_CAP;
842
1028
  const closeCapSource: DraftSweepCloseCapSource = validCap === undefined ? 'default' : requestedSource ?? 'flag';
@@ -871,6 +1057,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
871
1057
  let drafts: SweepDraft[] = [];
872
1058
  let merged: SweepMergedPr[] = [];
873
1059
  let liveBranches: ReadonlySet<string> | undefined;
1060
+ let inventoryStatus: { complete: boolean; reason?: string } = { complete: true };
874
1061
  try {
875
1062
  [drafts, merged, liveBranches] = await Promise.all([
876
1063
  collectPages((page, size) => adapters.listDrafts(page, size, repository)),
@@ -880,6 +1067,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
880
1067
  if (!liveBranches) throw new Error('Branch liveness unavailable');
881
1068
  if (drafts.some((pr) => !Number.isInteger(pr.number) || !pr.branch || !Array.isArray(pr.labels) || !Number.isFinite(Date.parse(pr.createdAt)))
882
1069
  || merged.some((pr) => !Number.isInteger(pr.number) || !pr.branch)) throw new Error('Invalid PR inventory');
1070
+ inventoryStatus = await adapters.inventoryStatus?.() ?? inventoryStatus;
883
1071
  } catch (error) {
884
1072
  timing('inventory', drafts.length + merged.length, 'failed');
885
1073
  result.error = sweepFailureReason(error);
@@ -887,6 +1075,10 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
887
1075
  return finish();
888
1076
  }
889
1077
  timing('inventory', drafts.length + merged.length);
1078
+ if (!inventoryStatus.complete && apply) {
1079
+ result.error = inventoryStatus.reason ?? 'PR inventory incomplete';
1080
+ return finish();
1081
+ }
890
1082
  for (const pr of drafts) if (pr.runId) runIdByNumber.set(pr.number, pr.runId);
891
1083
  const statuses = new Map<number, string | undefined>();
892
1084
  const finality = new Map<number, boolean | undefined>();
@@ -926,7 +1118,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
926
1118
  }
927
1119
  timing('review-gate', censused.length);
928
1120
  }
929
- result.daily = draftSweepDaily(drafts, merged, now, reviewGate);
1121
+ if (inventoryStatus.complete) result.daily = draftSweepDaily(drafts, merged, now, reviewGate);
930
1122
  // Card and terminal inventories are observations, not closing authority. An unreadable source cannot mint a claim.
931
1123
  let cards: readonly TaskCard[] | undefined;
932
1124
  let terminals: readonly PrTerminalRecord[] | undefined;
@@ -999,7 +1191,17 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
999
1191
  const cellTerminals = terminals?.filter((terminal) => terminal.repository === repository && terminal.prNumber === draft.number);
1000
1192
  const activeOwnerObservation = ownerCard ? undefined : activeOwnerObservations.get(draft.number);
1001
1193
  const posture = reviewGate.get(draft.number);
1194
+ const replacement = identity.cellId && identity.checks.provenance.state === 'yes'
1195
+ ? merged.find((pr) => pr.number !== draft.number && cellIdFromBody(pr.body ?? '') === identity.cellId
1196
+ && Number.isFinite(Date.parse(pr.mergedAt ?? '')) && Date.parse(pr.mergedAt!) > Date.parse(draft.createdAt)
1197
+ && (pr.body ?? '').split(/\r?\n/).some((line) => line.trim() === `Supersedes: #${draft.number}`)) : undefined;
1198
+ const lastFailure = cellTerminals?.filter((terminal) => terminal.terminalClass.startsWith('failed-')
1199
+ && Number.isFinite(Date.parse(terminal.at)))
1200
+ .sort((a, b) => Date.parse(b.at) - Date.parse(a.at))[0];
1201
+ const lastFailureTail = lastFailure?.hostRegateFailure?.detail ?? lastFailure?.stage ?? null;
1002
1202
  const assessment = assessDraftTriage({ draft, now, runStatus: statuses.get(draft.number),
1203
+ ...(replacement ? { replacement: { number: replacement.number, evidence: `Supersedes: #${draft.number}` } } : {}),
1204
+ lastFailureTail,
1003
1205
  ...(posture?.gate ? { gate: posture.gate } : {}),
1004
1206
  ...(posture?.triageReview ? { review: posture.triageReview } : {}),
1005
1207
  newerSameCellSameCard,
@@ -1013,12 +1215,14 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1013
1215
  for (const row of triageRows) triageCounts[row.assessment.nextAction] = (triageCounts[row.assessment.nextAction] ?? 0) + 1;
1014
1216
  result.triage = { entries: triageRows, counts: triageCounts };
1015
1217
  }
1016
- result.complete = true;
1218
+ result.complete = inventoryStatus.complete;
1219
+ if (!inventoryStatus.complete) result.error = inventoryStatus.reason ?? 'PR inventory incomplete';
1017
1220
  let closes = Number.isSafeInteger(alreadyClosed) && alreadyClosed > 0 ? alreadyClosed : 0;
1018
1221
  let unobserved = 0;
1019
1222
  let claimed = 0;
1020
1223
  let claimExpired = 0;
1021
1224
  const lineageCounts: DraftSweepLineageCounts = { closed: 0, harvestableClosed: 0, fallThrough: {} };
1225
+ const stopRunPlans = new Map<number, { runId?: string; newer: { number: number; branch: string; runId?: string } }>();
1022
1226
  result.lineage = lineageCounts;
1023
1227
  // 칸-keyed closes this tick; published on `lineageCounts` only when the 칸 rule fires (existing shapes stay byte-identical).
1024
1228
  let cellClosed = 0;
@@ -1035,7 +1239,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1035
1239
  let claimPartialApplied = false;
1036
1240
  let partialClaimUnowned = false;
1037
1241
  let releasePending = false;
1038
- if (apply && harnessDraft(draft) && !draft.labels.some((name) => name === approvalLabel || name === keepLabel || name === releaseHoldLabel)
1242
+ if (apply && harnessDraft(draft) && !draft.labels.some((name) => name === approvalLabel || name === keepLabel || name === releaseHoldLabel || name === RELEASE_PATH_LABEL)
1039
1243
  && stateLabels.filter((state) => draft.labels.includes(state.name)).length <= 1
1040
1244
  && !draft.labels.includes(supersededLabel)) {
1041
1245
  const logClaim = (event: 'claim-marked' | 'claim-released' | 'claim-skipped', owner: string | null, runId: string | null, reason: string) =>
@@ -1128,8 +1332,10 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1128
1332
  ...(claimWriteFailed ? { error: claimWriteError, ...(claimPartialApplied ? { partialApplied: true } : {}) } : {}) });
1129
1333
  continue;
1130
1334
  }
1131
- if (draft.labels.includes(releaseHoldLabel ?? '') || (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
1132
- const held = draft.labels.includes(keepLabel ?? '') ? keepLabel : releaseHoldLabel;
1335
+ if (draft.labels.includes(releaseHoldLabel ?? '') || draft.labels.includes(RELEASE_PATH_LABEL)
1336
+ || (!contradiction && draft.labels.includes(keepLabel ?? ''))) {
1337
+ const held = draft.labels.includes(keepLabel ?? '') ? keepLabel
1338
+ : draft.labels.includes(RELEASE_PATH_LABEL) ? RELEASE_PATH_LABEL : releaseHoldLabel;
1133
1339
  record({ number: draft.number, action: 'keep', reason: `label:${held}`, applied: false });
1134
1340
  continue;
1135
1341
  }
@@ -1152,9 +1358,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1152
1358
  const base = decideDraft({ draft, runStatus, mergedTwins: merged, openDrafts: drafts, liveBranches,
1153
1359
  finalRunResult, ageHours: runStatus ? ageHours : idleHours });
1154
1360
  if (!base.reason.startsWith('label:') && !base.reason.startsWith('superseded-by #') && !base.reason.startsWith('duplicate-of-open #')) {
1155
- const live = (status: string | undefined, branch: string) => status === 'running' || status === 'probable-running'
1156
- || (status !== 'self-implement.result final' && liveBranches.has(branch));
1157
- const runLive = live(runStatus, draft.branch);
1361
+ const runLive = isLiveDraftRun(runStatus, draft.branch, liveBranches);
1158
1362
  const lineageKey = branchLineageKey(draft.branch);
1159
1363
  const cellId = cellNewer ? cellIdFromBody(draft.body ?? '') : null;
1160
1364
  const duplicateOf = cellNewer ? `cell ${cellId}` : `lineage ${lineageKey}`;
@@ -1184,7 +1388,7 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1184
1388
  else if (runLive && !adapters.supersedeRun) fallThrough('lineage-duplicate-run-live');
1185
1389
  // Safety (OP 10-11): a live run is stopped only when the newer run of the same lineage is itself live —
1186
1390
  // never trade a running attempt for one that already ended or was never observed running.
1187
- else if (runLive && !live(statuses.get(duplicateNewer.number), duplicateNewer.branch)) fallThrough('lineage-newer-run-not-live');
1391
+ else if (runLive && !isLiveDraftRun(statuses.get(duplicateNewer.number), duplicateNewer.branch, liveBranches)) fallThrough('lineage-newer-run-not-live');
1188
1392
  else if (closes >= closeCap) {
1189
1393
  record({ number: draft.number, action: 'keep', reason: 'close-cap', applied: false });
1190
1394
  continue;
@@ -1208,6 +1412,8 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1208
1412
  lineageCounts.closed += 1;
1209
1413
  if (harvestable) lineageCounts.harvestableClosed += 1;
1210
1414
  if (cellNewer) cellClosed += 1;
1415
+ if (runLive) stopRunPlans.set(draft.number, { runId: draft.runId ?? undefined, newer: { number: duplicateNewer.number,
1416
+ branch: duplicateNewer.branch, runId: duplicateNewer.runId ?? undefined } });
1211
1417
  const entry: DraftSweepEntry = { number: draft.number, action: 'close', reason, statusLabel: supersededLabel, applied: false };
1212
1418
  record(entry);
1213
1419
  if (!apply) continue;
@@ -1345,5 +1551,24 @@ export async function runDraftSweep({ repository, adapters, apply = false, now =
1345
1551
  result.closed = closes - (Number.isSafeInteger(alreadyClosed) && alreadyClosed > 0 ? alreadyClosed : 0);
1346
1552
  result.claimed = claimed;
1347
1553
  result.claimExpired = claimExpired;
1554
+ if (includeApplyPlan && !apply && result.complete) {
1555
+ const byNumber = new Map(drafts.map((draft) => [draft.number, draft]));
1556
+ const planEntries = result.entries.map((entry) => {
1557
+ const draft = byNumber.get(entry.number);
1558
+ if (!draft?.headSha || !draft.updatedAt || !Number.isFinite(Date.parse(draft.updatedAt))) {
1559
+ throw new Error(`cannot freeze apply plan: missing head SHA or updatedAt for #${entry.number}`);
1560
+ }
1561
+ const stopRun = stopRunPlans.get(entry.number);
1562
+ const newer = stopRun ? byNumber.get(stopRun.newer.number) : undefined;
1563
+ if (stopRun && (!draft.runId || !newer?.runId || stopRun.runId !== draft.runId
1564
+ || stopRun.newer.branch !== newer.branch || stopRun.newer.runId !== newer.runId)) {
1565
+ throw new Error(`cannot freeze apply plan: live duplicate run identity incomplete for #${entry.number}`);
1566
+ }
1567
+ return { ...entry, headSha: draft.headSha, branch: draft.branch, ...(draft.runId ? { runId: draft.runId } : {}),
1568
+ ...(stopRun ? { stopRunRequired: true, supersedeNewer: stopRun.newer } : {}),
1569
+ updatedAt: draft.updatedAt, labels: [...draft.labels].sort() };
1570
+ });
1571
+ result.applyPlan = validateDraftSweepApplyPlan({ version: 1, closeCap, closeCapSource, entries: planEntries });
1572
+ }
1348
1573
  return finish();
1349
1574
  }
@@ -17,6 +17,12 @@ export function draftClaimState(draft: { labels: readonly string[]; updatedAt?:
17
17
  return (now.getTime() - updated) / 3_600_000 < CLAIM_IDLE_HOURS ? 'claimed' : 'expired';
18
18
  }
19
19
 
20
+ /** DRAFT-CLAIM-AUTO-2-FU — 카드에 남은 claim 기록(`draftClaim.at`)이 아직 살아 있나 — `draftClaimState` 와 «같은 창»(CLAIM_IDLE_HOURS)을 쓴다. */
21
+ export function draftClaimRecordLive(at: string, now: Date): boolean {
22
+ const updated = Date.parse(at);
23
+ return Number.isFinite(updated) && (now.getTime() - updated) / 3_600_000 < CLAIM_IDLE_HOURS;
24
+ }
25
+
20
26
  export interface DraftTriagePr {
21
27
  number: number;
22
28
  title?: string;
@@ -34,7 +40,7 @@ export interface DraftTriagePr {
34
40
  latestCommitAt?: string;
35
41
  }
36
42
 
37
- export type DraftTriageNextAction = 'close-a' | 'close-c' | 'human';
43
+ export type DraftTriageNextAction = 'close-a' | 'close-b' | 'close-c' | 'harvest' | 'human';
38
44
  export type DraftTriageReviewState = 'approved' | 'changes-requested' | 'commented' | 'dismissed' | 'pending' | 'unknown';
39
45
  export type DraftTriageCheck = { state: 'yes' | 'no' | 'unknown'; evidence: string };
40
46
  export interface DraftTriageAssessment {
@@ -45,6 +51,8 @@ export interface DraftTriageAssessment {
45
51
  review: DraftTriageReviewState;
46
52
  cellStatus: 'green' | 'yellow' | 'red' | 'done' | 'unknown';
47
53
  nextAction: DraftTriageNextAction;
54
+ lastFailureTail: string | null;
55
+ missingEvidence: readonly string[];
48
56
  checks: Readonly<Record<'provenance' | 'gate' | 'review' | 'cell-complete' | 'cell-status-repository-bound' | 'replacement-landed' | 'newer-same-card' | 'idle-48h' | 'protected' | 'recent-commit' | 'running' | 'owner-confirmed', DraftTriageCheck>>;
49
57
  evidence: readonly string[];
50
58
  }
@@ -62,11 +70,15 @@ export interface DraftTriageAssessmentInput {
62
70
  targetRepository?: string;
63
71
  newerSameCellSameCard?: boolean;
64
72
  ownerConfirmed?: boolean;
73
+ /** Explicit merged PR naming this draft as its same-cell predecessor. */
74
+ replacement?: { number: number; evidence: string };
75
+ /** Exact-PR terminal failure, not a failure inferred from another draft in the cell. */
76
+ lastFailureTail?: string | null;
65
77
  }
66
78
 
67
79
  const CLOSE_PROTECTED_LABELS = new Set([
68
80
  'elanous:running', 'elanous:keep', 'elanous:release-hold', 'elanous:idea-approval',
69
- 'elanous:harvest-claimed', 'triage:land', 'triage:active',
81
+ 'elanous:harvest-claimed', RELEASE_PATH_LABEL, 'triage:land', 'triage:active',
70
82
  ]);
71
83
  const TRIAGE_TERMINAL_RUN_STATUSES = new Set(['completed', 'failed', 'cancelled', 'abandoned', 'self-implement.result final']);
72
84
 
@@ -118,7 +130,10 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
118
130
  const idle48h = Number.isFinite(ageHours) && ageHours >= 48;
119
131
  let nextAction: DraftTriageNextAction = 'human';
120
132
  if (closeEligible && cellComplete && cellStatusRepositoryBound) nextAction = 'close-a';
133
+ else if (closeEligible && input.replacement) nextAction = 'close-b';
121
134
  else if (closeEligible && idle48h && input.ownerConfirmed === true) nextAction = 'close-c';
135
+ else if (provenance && (draft.labels ?? []).includes('elanous:harvestable') && !protectedState && runNotRunning
136
+ && input.gate === 'pass' && input.review === 'approved') nextAction = 'harvest';
122
137
 
123
138
  const checks = {
124
139
  provenance: { state: provenance ? 'yes' : 'unknown', evidence: provenance ? `origin=${origin}; cell=${cellId}; card=${cardId}` : '출처·유효 칸·카드 표지가 모두 확인되지 않음' },
@@ -126,7 +141,9 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
126
141
  review: { state: input.review === undefined || input.review === 'unknown' ? 'unknown' : input.review === 'approved' ? 'yes' : 'no', evidence: `latest exact-head review=${input.review ?? 'unknown'}` },
127
142
  'cell-complete': { state: input.cellStatus && cellStatusRepositoryBound ? (cellComplete ? 'yes' : 'no') : 'unknown', evidence: input.cellStatus ? `cell=${cellId ?? 'unknown'} status=${input.cellStatus}${cellStatusRepositoryBound ? '' : ' (저장소 귀속 미확인)'}` : `칸 상태 미관측${cellId ? ` (${cellId})` : ''}` },
128
143
  'cell-status-repository-bound': { state: cellStatusRepositoryBound ? 'yes' : hasCellStatusRepositoryIdentity ? 'no' : 'unknown', evidence: cellStatusRepositoryBound ? `칸 상태 저장소=${input.cellStatusRepository}; 대상 저장소=${input.targetRepository}` : hasCellStatusRepositoryIdentity ? `칸 상태 저장소=${input.cellStatusRepository}; 대상 저장소=${input.targetRepository} (불일치)` : '칸 상태의 대상 저장소 귀속 미확인' },
129
- 'replacement-landed': { state: 'unknown', evidence: '현재 adapter는 같은 칸 병합 PR과 이 초안의 대체 관계를 증명하지 않음; follow-up 필요' },
144
+ 'replacement-landed': input.replacement
145
+ ? { state: 'yes', evidence: `merged #${input.replacement.number}: ${input.replacement.evidence}` }
146
+ : { state: 'unknown', evidence: '현재 adapter는 같은 칸 병합 PR과 이 초안의 대체 관계를 증명하지 않음; follow-up 필요' },
130
147
  'newer-same-card': { state: input.newerSameCellSameCard === undefined ? 'unknown' : input.newerSameCellSameCard ? 'yes' : 'no', evidence: `${input.newerSameCellSameCard === undefined ? '같은 칸·카드 새 draft 관계 미관측' : `same-cell-same-card-newer=${input.newerSameCellSameCard}`}; 관측 표지이며 대체 증거가 아님` },
131
148
  'idle-48h': { state: Number.isFinite(ageHours) ? (idle48h ? 'yes' : 'no') : 'unknown', evidence: Number.isFinite(ageHours) ? `head age=${ageHours.toFixed(1)}h` : 'head commit 시각 미관측' },
132
149
  protected: { state: protectedState ? 'yes' : 'no', evidence: protectedLabel ? `보호 표지=${protectedLabel}` : '보호 표지 없음' },
@@ -134,9 +151,12 @@ export function assessDraftTriage(input: DraftTriageAssessmentInput): DraftTriag
134
151
  running: { state: running ? 'yes' : runNotRunning ? 'no' : 'unknown', evidence: running ? `run=${input.runStatus ?? 'elanous:running'}` : runNotRunning ? `종결 run=${input.runStatus}` : `run 상태 미관측${input.runStatus ? ` (${input.runStatus})` : ''}` },
135
152
  'owner-confirmed': { state: input.ownerConfirmed === undefined ? 'unknown' : input.ownerConfirmed ? 'yes' : 'no', evidence: input.ownerConfirmed === undefined ? '소유자 출처 미관측' : input.ownerConfirmed ? '고유 카드 또는 활성 claim owner 확인' : '고유 소유자 없음' },
136
153
  } satisfies DraftTriageAssessment['checks'];
137
- const evidence = Object.values(checks).map((check) => check.evidence);
154
+ const missingEvidence = Object.entries(checks).filter(([, check]) => check.state === 'unknown').map(([name]) => name);
155
+ const evidence = [...Object.values(checks).map((check) => check.evidence),
156
+ ...(input.lastFailureTail ? [`last failure: ${input.lastFailureTail}`] : [])];
138
157
  return { origin, cellId, cardId, gate: input.gate ?? 'unknown', review: input.review ?? 'unknown',
139
- cellStatus: input.cellStatus ?? 'unknown', nextAction, checks, evidence };
158
+ cellStatus: input.cellStatus ?? 'unknown', nextAction, lastFailureTail: input.lastFailureTail ?? null,
159
+ missingEvidence, checks, evidence };
140
160
  }
141
161
 
142
162
  export interface DraftTriageInput {
@@ -209,7 +229,32 @@ export function laterMergedTwins(draft: DraftTriagePr, mergedTwins: readonly Dra
209
229
  || (draftSlot && slot(pr.body) === draftSlot) || (stem && branchStem(pr.branch) === stem)));
210
230
  }
211
231
 
232
+ /**
233
+ * DRAFT-ZERO — explicit harvest-deferred marker: the exact PR-metadata key·value a failed run's termination
234
+ * path records when the draft's changes must survive the sweep for harvest. The marker line is
235
+ * `수확보류: harvest-deferred` (body key·value, never a label-registry entry); the value byte-matches the keep reason.
236
+ */
237
+ export const HARVEST_DEFERRED_MARKER_KEY = '수확보류';
238
+ export const HARVEST_DEFERRED_MARKER_VALUE = 'harvest-deferred';
239
+
240
+ const HARVEST_DEFERRED_ROW_RE = new RegExp(`^${HARVEST_DEFERRED_MARKER_KEY}:\\s*([^\\r\\n]*)$`);
241
+ const HARVEST_DEFERRED_CONFLICT_RE = new RegExp(`^\\s*${HARVEST_DEFERRED_MARKER_KEY}\\s*:`);
242
+
243
+ /** Verified only when at least one unindented `수확보류:` body line exists and every such line carries exactly the marker value — missing, indented or conflicting lines never verify. */
244
+ export function harvestDeferredMarker(body: string | undefined): boolean {
245
+ const lines = (body ?? '').split(/\r?\n/);
246
+ const rows = lines.flatMap((line) => {
247
+ const match = HARVEST_DEFERRED_ROW_RE.exec(line);
248
+ return match ? [match[1]!.trim()] : [];
249
+ });
250
+ return lines.filter((line) => HARVEST_DEFERRED_CONFLICT_RE.test(line)).length === rows.length
251
+ && rows.length > 0 && rows.every((value) => value === HARVEST_DEFERRED_MARKER_VALUE);
252
+ }
253
+
212
254
  export function decideDraft({ draft, runStatus, mergedTwins, openDrafts, ageHours, liveBranches, finalRunResult }: DraftTriageInput): DraftDecision {
255
+ // DRAFT-ZERO — a verified harvest-deferred marker is the strongest hold: it outranks protected labels
256
+ // and every close rule, so a failed run's harvestable draft survives the sweep for harvest.
257
+ if (runStatus === 'failed' && harvestDeferredMarker(draft.body)) return { action: 'keep', reason: 'harvest-deferred' };
213
258
  const held = draft.labels?.find((label) => PROTECTED_LABELS.has(label));
214
259
  if (held) return { action: 'keep', reason: `label:${held}` };
215
260
  if (runStatus !== 'self-implement.result final' && draft.branch && liveBranches.has(draft.branch)
@@ -0,0 +1,77 @@
1
+ /**
2
+ * GLM-NO-CREDENTIAL-FALLBACK (OP #28375 · 10-22) — 하니스 자식 공급자가 `glm`(Z.ai GLM Coding Plan 직결)인데
3
+ * 이 프로세스에 Z.ai 자격이 없으면, 구현 라운드를 «열기 전»에 정한다:
4
+ * · OpenRouter 키가 있으면 → `openrouter` / `openrouter/z-ai/glm-5.3` 로 바꿔 발사한다(같은 GLM 계열 · 관측 한 줄).
5
+ * · 둘 다 없으면 → 이유 한 줄로 발사 전에 거부한다(조용한 no-progress 라운드를 만들지 않는다).
6
+ *
7
+ * ⭐ 자격 판정은 생산 해석기 그대로다 — `zaiCodingPlanAvailable()`(키 캐시 `~/.cache/zai_api_key` → env `ZAI_API_KEY`)이
8
+ * `getProviderForConfig` 가 glm 직결을 세우는 조건과 «같은» 함수이고, OpenRouter 는 `getOpenRouterApiKey()` 다.
9
+ * ⛔ Pod 경로는 이 판정 «전»에 이미 fail-closed 다(`pod-zai-child.ts` · 클러스터 Secret 판정). Pod 안에선 Secret 이
10
+ * `ZAI_API_KEY` 를 env 로 주므로 여기는 그대로 통과한다(keep). 이 모듈은 호스트 로컬 자식·Secret 밖 경로의 받침이다.
11
+ * ⛔ 이 모듈은 가볍게 둔다(무거운 import 0) — dev-pipeline 이 발사 직전에 부른다.
12
+ */
13
+
14
+ import type { ChildLlmSelection } from '../agent/run-context.js';
15
+ import { getOpenRouterApiKey } from '../config.js';
16
+ import { debug } from '../debug/log.js';
17
+ import { ZAI_OPENROUTER_FALLBACK_MODEL, zaiCodingPlanAvailable } from '../llm/zai-coding-plan.js';
18
+
19
+ export interface GlmCredentialProbe {
20
+ /** Z.ai 직결이 서나 — 기본 = 생산 `zaiCodingPlanAvailable()`. */
21
+ readonly zai: () => boolean;
22
+ /** OpenRouter 키가 있나 — 기본 = 생산 `getOpenRouterApiKey()`. */
23
+ readonly openrouter: () => boolean;
24
+ }
25
+
26
+ export const defaultGlmCredentialProbe: GlmCredentialProbe = {
27
+ zai: () => zaiCodingPlanAvailable(),
28
+ openrouter: () => Boolean(getOpenRouterApiKey()?.trim()),
29
+ };
30
+
31
+ export type GlmCredentialDecision =
32
+ | { kind: 'keep' }
33
+ | { kind: 'fallback'; from: string; to: string; reason: string }
34
+ | { kind: 'refuse'; reason: string };
35
+
36
+ /** 발사 전 거부 — 호출부가 자기 오류 종류로 감싼다(dev-pipeline 은 DevPipelineError). */
37
+ export class GlmChildCredentialError extends Error {
38
+ constructor(message: string) {
39
+ super(message);
40
+ this.name = 'GlmChildCredentialError';
41
+ }
42
+ }
43
+
44
+ const ZAI_MISSING = 'Z.ai 자격 없음(~/.cache/zai_api_key · env ZAI_API_KEY)';
45
+
46
+ /** 순수 판정 — glm 이 아니면 언제나 keep. */
47
+ export function decideGlmChildCredential(
48
+ selection: Pick<ChildLlmSelection, 'provider' | 'model'> | undefined,
49
+ probe: GlmCredentialProbe = defaultGlmCredentialProbe,
50
+ ): GlmCredentialDecision {
51
+ if (!selection || selection.provider.trim().toLowerCase() !== 'glm') return { kind: 'keep' };
52
+ if (probe.zai()) return { kind: 'keep' };
53
+ const from = `glm/${selection.model}`;
54
+ if (probe.openrouter()) {
55
+ return { kind: 'fallback', from, to: `openrouter/${ZAI_OPENROUTER_FALLBACK_MODEL}`, reason: `${ZAI_MISSING} · OpenRouter 키 있음 → OpenRouter GLM 으로 발사` };
56
+ }
57
+ return {
58
+ kind: 'refuse',
59
+ reason: `child provider glm(${selection.model}) 발사 전 거부 — ${ZAI_MISSING} ⊕ OpenRouter 키 없음(~/.cache/openrouter_api_key · env OPENROUTER_API_KEY) · 자격 하나를 세우거나 --child-llm-provider 를 바꿔라`,
60
+ };
61
+ }
62
+
63
+ /** 발사 직전 적용 — keep 이면 같은 객체, fallback 이면 바꾼 선택, refuse 면 던진다. 결정마다 관측 한 줄. */
64
+ export function applyGlmCredentialFallback(
65
+ selection: ChildLlmSelection | undefined,
66
+ probe: GlmCredentialProbe = defaultGlmCredentialProbe,
67
+ ): ChildLlmSelection | undefined {
68
+ const decision = decideGlmChildCredential(selection, probe);
69
+ if (decision.kind === 'keep') return selection;
70
+ if (decision.kind === 'fallback') {
71
+ debug.log('self-dev.child-llm', 'glm-no-credential-fallback', { from: decision.from, to: decision.to, reason: decision.reason }, { level: 'warn' });
72
+ // effort·source·codexQuotaPolicy 는 그대로 — 바뀌는 것은 «길»(provider·model)뿐이다.
73
+ return { ...selection!, provider: 'openrouter', model: ZAI_OPENROUTER_FALLBACK_MODEL };
74
+ }
75
+ debug.log('self-dev.child-llm', 'glm-no-credential-refused', { from: `glm/${selection!.model}`, reason: decision.reason }, { level: 'warn' });
76
+ throw new GlmChildCredentialError(decision.reason);
77
+ }
@@ -42,6 +42,7 @@ export const JOURNEY_NODE_IDS = [
42
42
  'decision-card',
43
43
  'ready',
44
44
  'pr-head-checkout',
45
+ 'recover', // LAND-REFUSAL-EDGES — 착지 거부 결속 간선의 목적지(recover@1 subgraph)
45
46
  'stopped',
46
47
  ] as const;
47
48
  export type JourneyNodeId = typeof JOURNEY_NODE_IDS[number];