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
@@ -30,6 +30,7 @@ import { isAbandonedClassification, type AbandonedClassificationResult } from '.
30
30
  import { createExecution, type Task, type TaskExecution } from '../types.js';
31
31
  import type { DispatchContext, DispatchResult } from '../surface-registry.js';
32
32
  import { nestedPodResult } from './pod-failure-reason.js';
33
+ import { SCOPE_EXPANSION_CAP, SCOPE_STOP_REASONS, isProtectedScopePath, type ScopeStopReason } from '../../self-implement/scope-adjacency.js';
33
34
 
34
35
  /** Result of one self-implement subprocess. */
35
36
  export interface SelfImplementJobDone {
@@ -103,10 +104,19 @@ export interface PodChildEvidence {
103
104
  error?: string;
104
105
  detail?: string;
105
106
  stderr?: string;
107
+ /** Bounded, redacted complete Pod log tail. Separate from child stderr to avoid replacing stronger child facts. */
108
+ podLogTail?: string[];
109
+ podLogTailLines?: number;
110
+ podLogUnavailable?: string;
106
111
  exitCode?: number;
107
112
  classification?: string;
108
113
  scopeEscape?: true;
109
114
  outOfScopeEdits?: unknown;
115
+ /** SCOPE-ESCAPE-AS-REFINE — why held out-of-scope edits stop the run (deletion · protected path · cap). Present only with scopeEscape. */
116
+ scopeStopReasons?: ScopeStopReason[];
117
+ /** SCOPE-ESCAPE-AS-REFINE — «구현이 알려준 새 범위», not a failure: held names with no stop reason, or (no held names)
118
+ * the accepted `scopeExpansion` paths of a child that failed later (e.g. gate). Evidence is built only for failed results. */
119
+ newScope?: string[];
110
120
  abandonedClassification?: Record<string, unknown>;
111
121
  supervisorVerdict?: unknown;
112
122
  goalCauseObserved?: true;
@@ -122,6 +132,34 @@ export interface PodChildEvidence {
122
132
  };
123
133
  }
124
134
 
135
+ const SCOPE_STOP_REASON_ORDER: readonly ScopeStopReason[] = SCOPE_STOP_REASONS;
136
+
137
+ /** Stop reasons for held out-of-scope edits: the child's own `scopeStopReasons` (orchestrator decideScopeExpansion) plus
138
+ * what the names alone prove (protected path · count over SCOPE_EXPANSION_CAP · incomplete name list). A deletion is
139
+ * only known from the child. Deterministic, fixed order. */
140
+ export function scopeStopReasonsFromResult(o: Record<string, unknown>, outOfScopeEdits: unknown = o.outOfScopeEdits): ScopeStopReason[] {
141
+ const reasons = new Set<ScopeStopReason>();
142
+ if (Array.isArray(o.scopeStopReasons)) {
143
+ for (const reason of o.scopeStopReasons) if ((SCOPE_STOP_REASON_ORDER as readonly unknown[]).includes(reason)) reasons.add(reason as ScopeStopReason);
144
+ }
145
+ const names = Array.isArray(outOfScopeEdits) ? outOfScopeEdits.filter((name): name is string => typeof name === 'string') : [];
146
+ if (names.some(isProtectedScopePath)) reasons.add('protected-path');
147
+ const count = typeof o.outsideCount === 'number' ? Math.max(o.outsideCount, names.length) : names.length;
148
+ if (count > SCOPE_EXPANSION_CAP) reasons.add('over-cap');
149
+ if (o.nameCapReached === true) reasons.add('name-cap');
150
+ return SCOPE_STOP_REASON_ORDER.filter((reason) => reasons.has(reason));
151
+ }
152
+
153
+ /** «구현이 알려준 새 범위» — held names with no stop reason, else the accepted expansion's paths. */
154
+ function newScopeFromResult(outOfScopeEdits: unknown, scopeExpansion: unknown): string[] | undefined {
155
+ const names = Array.isArray(outOfScopeEdits) ? outOfScopeEdits.filter((name): name is string => typeof name === 'string' && name.length > 0) : [];
156
+ if (names.length) return names.slice(0, 40);
157
+ const files = scopeExpansion && typeof scopeExpansion === 'object' ? (scopeExpansion as { files?: unknown }).files : undefined;
158
+ const paths = Array.isArray(files) ? files.map((file) => (file && typeof file === 'object' ? (file as { path?: unknown }).path : undefined))
159
+ .filter((path): path is string => typeof path === 'string' && path.length > 0) : [];
160
+ return paths.length ? paths.slice(0, 40).map((path) => redactSecretText(path)) : undefined;
161
+ }
162
+
125
163
  /** Preserve only named terminal facts; the full child detail may contain logs or credentials. */
126
164
  export function podChildEvidenceFromResult(o: Record<string, unknown>): PodChildEvidence | undefined {
127
165
  const object = (value: unknown): Record<string, unknown> | undefined =>
@@ -146,8 +184,13 @@ export function podChildEvidenceFromResult(o: Record<string, unknown>): PodChild
146
184
  const failureExitCode = o.ok === false && typeof o.exitCode === 'number'
147
185
  && Number.isInteger(o.exitCode) && o.exitCode >= 0 && o.exitCode <= 255 ? o.exitCode : undefined;
148
186
  const outOfScopeEdits = scrubValue(o.outOfScopeEdits);
149
- const scopeEscape = (Array.isArray(outOfScopeEdits) && outOfScopeEdits.length > 0)
187
+ const held = (Array.isArray(outOfScopeEdits) && outOfScopeEdits.length > 0)
150
188
  || (typeof o.detail === 'string' && /^Out-of-scope edits held in the worktree(?:[.;]|$)/i.test(o.detail.trim()));
189
+ // SCOPE-ESCAPE-AS-REFINE (대표 10-22 «범위 밖 허용도 로직으로») — held edits stop the run only for a deletion, a protected
190
+ // path, or a cap; otherwise they are the new scope the implementation found and the exit is classified as if unheld.
191
+ const scopeStopReasons = held ? scopeStopReasonsFromResult(o, outOfScopeEdits) : [];
192
+ const scopeEscape = held && scopeStopReasons.length > 0;
193
+ const newScope = scopeEscape ? undefined : newScopeFromResult(outOfScopeEdits, o.scopeExpansion);
151
194
  const classification = scopeEscape ? 'scope-escape'
152
195
  : typeof abandoned?.classification === 'string' ? redactSecretText(abandoned.classification)
153
196
  : typeof o.failureClassification === 'string' ? redactSecretText(o.failureClassification) : undefined;
@@ -157,8 +200,9 @@ export function podChildEvidenceFromResult(o: Record<string, unknown>): PodChild
157
200
  ...(failedText(o.stderr) ? { stderr: failedText(o.stderr) } : {}),
158
201
  ...(failureExitCode !== undefined ? { exitCode: failureExitCode } : {}),
159
202
  ...(classification ? { classification } : {}),
160
- ...(scopeEscape ? { scopeEscape: true } : {}),
203
+ ...(scopeEscape ? { scopeEscape: true, scopeStopReasons } : {}),
161
204
  ...(outOfScopeEdits !== undefined ? { outOfScopeEdits } : {}),
205
+ ...(newScope ? { newScope } : {}),
162
206
  ...(abandoned ? { abandonedClassification: abandoned } : {}),
163
207
  ...(o.supervisorVerdict !== undefined ? { supervisorVerdict: scrubValue(o.supervisorVerdict) } : {}),
164
208
  ...(o.goalCauseObserved === true ? { goalCauseObserved: true } : {}),
@@ -0,0 +1,177 @@
1
+ /**
2
+ * 🐧 LINUX-STAGE — 개발 머신 환경에 기대지 않는 «격리 무대».
3
+ *
4
+ * Situation: 같은 시험이 macOS(개발 머신)에서는 통과하고 Linux 에서는 실패하는 잔여 실패가 있다.
5
+ * 원인은 코드가 아니라 «환경»이다 — 개발 머신 HOME 의 글로벌 git user.* · PATH 에 있는 grok CLI ·
6
+ * LANG/LC_ALL 이 정하는 콜레이션 · 로케일마다 달라지는 이모지 비교.
7
+ * Answer: 그 네 축을 «무대»로 고정한다 — 임시 HOME(글로벌 설정 없음), grok 이 없는 PATH,
8
+ * 저장소 로컬 identity 만 가진 git 작업 트리, C.UTF-8, 코드포인트 비교.
9
+ * ⛔ 이 무대는 «생산 진입점을 그대로 지나게» 하는 시험을 위한 것이다 — 소스 문자열 검사용이 아니다.
10
+ * ⛔ `withLinuxEnv` 는 끝나면 env 와 임시 디렉터리를 원상복구한다(같은 파일의 뒤 시험을 오염시키지 않는다).
11
+ */
12
+ import { spawnSync, type SpawnSyncReturns } from 'node:child_process';
13
+ import { accessSync, constants, existsSync, mkdirSync, mkdtempSync, rmSync, writeFileSync } from 'node:fs';
14
+ import { tmpdir } from 'node:os';
15
+ import { delimiter, join } from 'node:path';
16
+
17
+ /** 무대 로케일 — Linux CI 의 기본값(LANG 미설정 · POSIX)을 넘긴다. */
18
+ export const STAGE_LOCALE = 'C.UTF-8';
19
+
20
+ /** 무대 git 신원 — 글로벌 설정이 아니라 저장소 로컬에만 박는다. */
21
+ export const STAGE_GIT_IDENTITY = { name: 'Elanous Stage', email: 'stage@elanous.test', branch: 'main' } as const;
22
+
23
+ export interface LinuxEnvStage {
24
+ /** 무대 루트(시험 끝에 통째로 지운다). */
25
+ readonly root: string;
26
+ /** 임시 HOME — `.gitconfig` 가 없다(글로벌 git 신원 없음). */
27
+ readonly home: string;
28
+ /** ELANOUS_STATE_DIR — config-dir 이 이 경로를 따라가므로 둘 다 격리된다. */
29
+ readonly state: string;
30
+ /** 무대 git 작업 트리(저장소 로컬 identity 만). */
31
+ readonly repo: string;
32
+ /** PATH 앞머리 — grok 이 없는 빈 디렉터리. */
33
+ readonly bin: string;
34
+ readonly env: Record<string, string>;
35
+ }
36
+
37
+ const ENV_KEYS = [
38
+ 'HOME',
39
+ 'ELANOUS_STATE_DIR',
40
+ 'ELANOUS_STATE_DIR_SOURCE',
41
+ 'ELANOUS_CONFIG_DIR',
42
+ 'LANG',
43
+ 'LC_ALL',
44
+ 'TZ',
45
+ 'PATH',
46
+ 'GIT_CONFIG_GLOBAL',
47
+ 'GIT_CONFIG_SYSTEM',
48
+ 'GIT_AUTHOR_NAME',
49
+ 'GIT_AUTHOR_EMAIL',
50
+ 'GIT_COMMITTER_NAME',
51
+ 'GIT_COMMITTER_EMAIL',
52
+ ] as const;
53
+
54
+ /** 무대 PATH 의 시스템 꼬리 — grok 이 깔린 디렉터리는 «걸러낸다»(머신마다 설치 위치가 다르다). */
55
+ const SYSTEM_PATH = ['/usr/local/bin', '/usr/bin', '/bin'];
56
+
57
+ /** 무대를 만들기만 한다(env 적용은 `withLinuxEnv`). */
58
+ export function createLinuxEnvStage(): LinuxEnvStage {
59
+ const root = mkdtempSync(join(tmpdir(), 'elanous-linux-env-'));
60
+ const home = join(root, 'home');
61
+ const repo = join(root, 'repo');
62
+ const bin = join(root, 'bin');
63
+ const state = join(repo, '.elanous');
64
+ for (const dir of [home, repo, bin, state]) mkdirSync(dir, { recursive: true });
65
+ const env: Record<string, string> = {
66
+ HOME: home,
67
+ // ELANOUS_CONFIG_DIR 는 state 를 따라가는 것이 정본이므로 따로 두지 않는다(무시 경고 방지).
68
+ ELANOUS_STATE_DIR: state,
69
+ ELANOUS_STATE_DIR_SOURCE: 'explicit',
70
+ LANG: STAGE_LOCALE,
71
+ LC_ALL: STAGE_LOCALE,
72
+ TZ: 'UTC',
73
+ PATH: [bin, ...SYSTEM_PATH.filter((dir) => !existsSync(join(dir, 'grok')))].join(delimiter),
74
+ // 글로벌·시스템 git 설정을 read 자체에서 끊는다 — 개발 머신 설정이 새어 들어올 길을 없앤다.
75
+ GIT_CONFIG_GLOBAL: '/dev/null',
76
+ GIT_CONFIG_SYSTEM: '/dev/null',
77
+ };
78
+ return { root, home, state, repo, bin, env };
79
+ }
80
+
81
+ /**
82
+ * 무대 env 로 `fn` 을 돌리고 원상복구한다.
83
+ * `ELANOUS_STATE_DIR` 가 정해지면 config-dir 도 그 아래로 오므로(config 정본 = state) 저장소·HOME 오염이 없다.
84
+ */
85
+ export async function withLinuxEnv<T>(fn: (stage: LinuxEnvStage) => T | Promise<T>): Promise<T> {
86
+ const stage = createLinuxEnvStage();
87
+ const saved = ENV_KEYS.map((key) => [key, process.env[key]] as const);
88
+ delete process.env.ELANOUS_CONFIG_DIR;
89
+ for (const [key, value] of Object.entries(stage.env)) process.env[key] = value;
90
+ // 개발 머신이 물려준 author/committer env 가 저장소 로컬 identity 증명을 가리지 않게 걷어낸다.
91
+ for (const key of ['GIT_AUTHOR_NAME', 'GIT_AUTHOR_EMAIL', 'GIT_COMMITTER_NAME', 'GIT_COMMITTER_EMAIL']) delete process.env[key];
92
+ try {
93
+ return await fn(stage);
94
+ } finally {
95
+ for (const [key, value] of saved) {
96
+ if (value === undefined) delete process.env[key];
97
+ else process.env[key] = value;
98
+ }
99
+ rmSync(stage.root, { recursive: true, force: true });
100
+ }
101
+ }
102
+
103
+ /**
104
+ * 무대 env 를 «명시» 해서 자식 프로세스를 띄운다.
105
+ * ⛔ bun 1.4.2 는 `process.env.PATH` 를 바꾸는 순간 이후 spawn 한 자식의 environ 을 기동 시 스냅샷으로
106
+ * 재구성한다 — HOME 등 다른 키의 JS 측 변이가 자식에 새지 않는다(실측: PATH assign 뒤 `env` 자식의
107
+ * HOME 이 원래 값으로 되돌아감). ambient 상속에 기대지 말고 무대 안의 자식은 반드시 이 함수로 띄운다.
108
+ * in-process(process.env 를 직접 읽는 코드)는 `withLinuxEnv` 의 변이가 그대로 보인다.
109
+ */
110
+ export function stageSpawnSync(
111
+ stage: LinuxEnvStage,
112
+ file: string,
113
+ args: string[],
114
+ opts: { cwd?: string } = {},
115
+ ): SpawnSyncReturns<string> {
116
+ return spawnSync(file, args, {
117
+ cwd: opts.cwd ?? stage.repo,
118
+ env: { ...process.env, ...stage.env },
119
+ encoding: 'utf8',
120
+ });
121
+ }
122
+
123
+ /** 무대 PATH 에서 그 명령이 실행 가능한가 — Linux CI 에 grok 이 없다는 사실을 «재는» 데 쓴다. */
124
+ export function stageHasCommand(stage: LinuxEnvStage, name: string): boolean {
125
+ return (stage.env.PATH ?? '').split(delimiter).some((dir) => {
126
+ if (!dir) return false;
127
+ try {
128
+ accessSync(join(dir, name), constants.X_OK);
129
+ return true;
130
+ } catch {
131
+ return false;
132
+ }
133
+ });
134
+ }
135
+
136
+ /** 무대 HOME 에 글로벌 git 신원이 있는가 — 무대에서는 false 여야 한다. */
137
+ export function hasGlobalGitIdentity(stage: LinuxEnvStage): boolean {
138
+ return existsSync(join(stage.home, '.gitconfig')) || existsSync(join(stage.home, '.config', 'git', 'config'));
139
+ }
140
+
141
+ function gitInStage(stage: LinuxEnvStage, args: string[]): string {
142
+ const result = stageSpawnSync(stage, 'git', args);
143
+ if (result.error) throw result.error;
144
+ if (result.status !== 0) throw new Error(`git ${args.join(' ')} 실패(rc=${result.status}): ${result.stderr.trim()}`);
145
+ return result.stdout.trim();
146
+ }
147
+
148
+ /**
149
+ * 무대 작업 트리를 «저장소 로컬 identity 만» 으로 초기화하고 첫 커밋까지 만든다.
150
+ * 커밋이 성공했다는 것 자체가 user.name/user.email 이 로컬 설정으로 먹었다는 실물 증거다.
151
+ */
152
+ export function initGitWithExplicitIdentity(stage: LinuxEnvStage): void {
153
+ gitInStage(stage, ['-c', `init.defaultBranch=${STAGE_GIT_IDENTITY.branch}`, 'init', '--quiet']);
154
+ gitInStage(stage, ['config', 'user.name', STAGE_GIT_IDENTITY.name]);
155
+ gitInStage(stage, ['config', 'user.email', STAGE_GIT_IDENTITY.email]);
156
+ gitInStage(stage, ['config', 'init.defaultBranch', STAGE_GIT_IDENTITY.branch]);
157
+ writeFileSync(join(stage.repo, 'README.md'), '# linux stage\n');
158
+ gitInStage(stage, ['add', 'README.md']);
159
+ gitInStage(stage, ['commit', '--quiet', '-m', 'stage: 초기 커밋']);
160
+ }
161
+
162
+ /** 무대 작업 트리의 실제 git 정체 — 로컬 설정과 현재 브랜치를 읽어 온다. */
163
+ export function gitStageIdentity(stage: LinuxEnvStage): { name: string; email: string; branch: string } {
164
+ return {
165
+ name: gitInStage(stage, ['config', '--get', 'user.name']),
166
+ email: gitInStage(stage, ['config', '--get', 'user.email']),
167
+ branch: gitInStage(stage, ['symbolic-ref', '--short', 'HEAD']),
168
+ };
169
+ }
170
+
171
+ /**
172
+ * 문자열을 «코드포인트» 단위로 쪼갠다 — `'🎉party'.length` 는 7(UTF-16)이지만 코드포인트는 6이다.
173
+ * 로케일·인코딩에 따라 이모지 비교가 흔들리는 자리를 코드포인트로 고정한다.
174
+ */
175
+ export function codePoints(value: string): string[] {
176
+ return [...value];
177
+ }
@@ -73,11 +73,18 @@ import { bootstrapMcpProxyRuntimes } from './mcp-proxy-bootstrap.js';
73
73
  import { SELF_COGNITION_RUNTIMES } from './self-cognition-runtimes.js';
74
74
  import { ELANOUS_CONTROL_RUNTIMES } from './elanous-control-runtimes.js';
75
75
 
76
+ export interface RegisterAllDefaultToolRuntimesOpts {
77
+ /** CLASSIC-IDLE-MCP-LAZY — classic TUI 만 켠다. 외부 MCP 프록시를 «첫 도구
78
+ * 호출» 때 띄우고, 그 전엔 지난 부팅의 툴 인덱스로 목록만 알린다.
79
+ * 데몬·`mcp serve` 는 기본값(즉시 기동) 그대로다. */
80
+ mcpLazyBoot?: boolean;
81
+ }
82
+
76
83
  /** Register every built-in runtime. Idempotent — safe to call more
77
84
  * than once (registry dedupe). Call from the dashboard boot path;
78
85
  * skills pick up registrations via side-effect when this module
79
86
  * gets imported. */
80
- export function registerAllDefaultToolRuntimes(): void {
87
+ export function registerAllDefaultToolRuntimes(opts: RegisterAllDefaultToolRuntimesOpts = {}): void {
81
88
  for (const rt of PTY_RUNTIMES) registerToolRuntime(rt);
82
89
  registerToolRuntime(terminalInjectRuntime);
83
90
  registerToolRuntime(bashRuntime);
@@ -170,7 +177,13 @@ export function registerAllDefaultToolRuntimes(): void {
170
177
  // External MCP proxies already declare surfaces `['mcp','tui']`, but the
171
178
  // TUI process never registered them. Fire-and-forget: handshake must not
172
179
  // block TUI startup; failures stay queryable via diagnostics.
173
- bootstrapMcpProxyRuntimes();
180
+ // CLASSIC-IDLE-MCP-LAZY: classic TUI 는 지연 기동 — 자식 둘(약 267MB)을
181
+ // 기동 때 상주시키지 않고, 첫 도구 호출 때 한 번 띄운다.
182
+ if (opts.mcpLazyBoot === true) {
183
+ bootstrapMcpProxyRuntimes({ lazy: true });
184
+ } else {
185
+ bootstrapMcpProxyRuntimes();
186
+ }
174
187
  }
175
188
 
176
189
  export { setTerminalInjectApprover } from './terminal-inject-runtime.js';
@@ -51,6 +51,10 @@ export interface BootstrapMcpProxyRuntimesOpts {
51
51
  registerRuntime?: typeof registerToolRuntime;
52
52
  logger?: McpBootLogger;
53
53
  handshakeTimeoutMs?: number;
54
+ /** CLASSIC-IDLE-MCP-LAZY — classic TUI 만 켠다. MCP 자식을 «첫 도구 호출»
55
+ * 때 띄우고, 그 전엔 지난 부팅의 툴 인덱스로 목록만 알린다. */
56
+ lazy?: boolean;
57
+ toolIndexStore?: RegisterMcpClientsOpts['toolIndexStore'];
54
58
  }
55
59
 
56
60
  const IDLE: McpProxyBootstrapSnapshot = {
@@ -62,6 +66,8 @@ const IDLE: McpProxyBootstrapSnapshot = {
62
66
 
63
67
  let testOpts: BootstrapMcpProxyRuntimesOpts | null = null;
64
68
  let activeHandle: McpProxyBootstrapHandle | undefined;
69
+ let activeClients: McpClientsHandle | undefined;
70
+ let exitHookInstalled = false;
65
71
  let lastSnapshot: McpProxyBootstrapSnapshot = IDLE;
66
72
  let bootGeneration = 0;
67
73
 
@@ -75,6 +81,7 @@ export function setMcpProxyBootstrapOptsForTest(opts: BootstrapMcpProxyRuntimesO
75
81
  export function _resetMcpProxyBootstrapForTest(): void {
76
82
  bootGeneration += 1;
77
83
  activeHandle = undefined;
84
+ activeClients = undefined;
78
85
  lastSnapshot = IDLE;
79
86
  }
80
87
 
@@ -86,6 +93,24 @@ export function getMcpProxyBootstrapHandle(): McpProxyBootstrapHandle | undefine
86
93
  return activeHandle;
87
94
  }
88
95
 
96
+ /** 프로세스가 «그냥» 죽는 경로(exit 훅)에서도 MCP 자식이 고아로 남지 않게 마지막
97
+ * SIGTERM 을 건다. `process.on('exit')` 은 await 할 수 없으므로 동기 kill 만 쓴다. */
98
+ function installMcpExitHook(): void {
99
+ if (exitHookInstalled) return;
100
+ exitHookInstalled = true;
101
+ process.once('exit', () => {
102
+ const clients = activeClients;
103
+ activeClients = undefined;
104
+ if (!clients) return;
105
+ try {
106
+ const terminated = clients.terminateChildrenSync?.() ?? 0;
107
+ if (terminated > 0) log('exit-terminate', { terminated });
108
+ } catch {
109
+ /* dying process — never throw from an exit hook */
110
+ }
111
+ });
112
+ }
113
+
89
114
  function observabilityBootLogger(): McpBootLogger {
90
115
  return {
91
116
  info: (line) => {
@@ -183,11 +208,15 @@ export function bootstrapMcpProxyRuntimes(
183
208
  ...(resolved.handshakeTimeoutMs !== undefined
184
209
  ? { handshakeTimeoutMs: resolved.handshakeTimeoutMs }
185
210
  : {}),
211
+ ...(resolved.lazy === true ? { lazy: true } : {}),
212
+ ...(resolved.toolIndexStore ? { toolIndexStore: resolved.toolIndexStore } : {}),
186
213
  });
187
214
  if (generation !== bootGeneration) {
188
215
  try { await result.shutdown(); } catch { /* abandoned boot */ }
189
216
  return current;
190
217
  }
218
+ activeClients = result;
219
+ installMcpExitHook();
191
220
  const snap = freezeSnapshot({
192
221
  status: 'ready',
193
222
  registered: result.registered,
@@ -0,0 +1,155 @@
1
+ // TUI-SIGTTIN-SUSPEND (0.2.36 · 10-23 n8n) — the TUI must not be stopped because a child stole its terminal.
2
+ //
3
+ // Observed: the TUI's process group was no longer the foreground group of its own tty, its next stdin
4
+ // read raised SIGTTIN and zsh printed «suspended (tty input)» (state T). The trigger was an interactive
5
+ // login shell (`$SHELL -l -i -c printenv`, shell-env-bootstrap.ts) that opened /dev/tty for job control,
6
+ // moved the terminal to its own group and never gave it back. The root fix runs that capture with no
7
+ // controlling tty (`detached`). This module is the defence for any other child that does the same:
8
+ //
9
+ // ① every tick, compare tcgetpgrp(stdin) with our own group;
10
+ // ② if the foreground group is gone, or it is led by one of our own descendants (or its leader is
11
+ // dead), it was taken by a child of ours → take it back (SIGTTOU ignored for that one call);
12
+ // ③ if a live process that is NOT ours holds it (the user's shell after a real job-control action),
13
+ // do not fight it — log `tui.lifecycle background-tty` once.
14
+ //
15
+ // Shared by both TUIs: `initTui()` (src/tui.ts) starts it for the classic dashboard and `--tui next`.
16
+
17
+ import { spawnSync } from 'node:child_process';
18
+ import { debug } from './debug/log.js';
19
+
20
+ export interface ForegroundFacts {
21
+ /** Our process group id (getpgrp()). */
22
+ ownPgid: number;
23
+ /** tcgetpgrp(stdin) — -1 when it could not be read (stdin is not our controlling tty). */
24
+ ttyPgid: number;
25
+ /** Some process still exists in ttyPgid (kill(-ttyPgid, 0)). */
26
+ groupAlive: boolean;
27
+ /** The group leader (pid === ttyPgid) still exists. */
28
+ leaderAlive: boolean;
29
+ /** The group leader is one of our descendants. */
30
+ leaderIsDescendant: boolean;
31
+ }
32
+
33
+ export type ForegroundVerdict =
34
+ | { action: 'ok' }
35
+ | { action: 'unknown' }
36
+ | { action: 'reclaim'; reason: 'fg-group-gone' | 'fg-leader-gone' | 'fg-held-by-our-child'; ttyPgid: number }
37
+ | { action: 'yield'; ttyPgid: number };
38
+
39
+ /** Pure decision — see the header for the rule. */
40
+ export function decideForeground(f: ForegroundFacts): ForegroundVerdict {
41
+ if (f.ttyPgid < 0 || f.ownPgid < 0) return { action: 'unknown' };
42
+ if (f.ttyPgid === f.ownPgid) return { action: 'ok' };
43
+ if (!f.groupAlive) return { action: 'reclaim', reason: 'fg-group-gone', ttyPgid: f.ttyPgid };
44
+ if (!f.leaderAlive) return { action: 'reclaim', reason: 'fg-leader-gone', ttyPgid: f.ttyPgid };
45
+ if (f.leaderIsDescendant) return { action: 'reclaim', reason: 'fg-held-by-our-child', ttyPgid: f.ttyPgid };
46
+ return { action: 'yield', ttyPgid: f.ttyPgid };
47
+ }
48
+
49
+ export interface ForegroundDeps {
50
+ tcgetpgrp(): number;
51
+ getpgrp(): number;
52
+ /** tcsetpgrp(stdin, pgid) with SIGTTOU ignored for the call. Returns true on success. */
53
+ reclaim(pgid: number): boolean;
54
+ alive(pid: number): boolean;
55
+ isDescendant(pid: number): boolean;
56
+ log(event: string, data: Record<string, unknown>): void;
57
+ }
58
+
59
+ function exists(pid: number): boolean {
60
+ try { process.kill(pid, 0); return true; } catch (e) { return (e as { code?: string }).code === 'EPERM'; }
61
+ }
62
+
63
+ /** Walks ppid from `pid` up to 1 and reports whether it passes through us. Only runs on an anomaly. */
64
+ function isOurDescendant(pid: number): boolean {
65
+ let cur = pid;
66
+ for (let i = 0; i < 64 && cur > 1; i++) {
67
+ const r = spawnSync('ps', ['-o', 'ppid=', '-p', String(cur)], { encoding: 'utf8', stdio: ['ignore', 'pipe', 'ignore'], timeout: 1000 });
68
+ const ppid = Number.parseInt(String(r.stdout ?? '').trim(), 10);
69
+ if (!Number.isFinite(ppid) || ppid <= 0) return false;
70
+ if (ppid === process.pid) return true;
71
+ cur = ppid;
72
+ }
73
+ return false;
74
+ }
75
+
76
+ type Libc = { tcgetpgrp(fd: number): number; tcsetpgrp(fd: number, pgid: number): number; getpgrp(): number; signal(sig: number, handler: number | bigint): number | bigint };
77
+
78
+ let libcCache: Libc | null | undefined;
79
+ function libc(): Libc | null {
80
+ if (libcCache !== undefined) return libcCache;
81
+ libcCache = null;
82
+ const path = process.platform === 'darwin' ? '/usr/lib/libSystem.B.dylib' : process.platform === 'linux' ? 'libc.so.6' : null;
83
+ if (!path || typeof (globalThis as { Bun?: unknown }).Bun === 'undefined') return null;
84
+ try {
85
+ // eslint-disable-next-line @typescript-eslint/no-require-imports
86
+ const { dlopen, FFIType } = require('bun:ffi') as typeof import('bun:ffi');
87
+ const lib = dlopen(path, {
88
+ tcgetpgrp: { args: [FFIType.i32], returns: FFIType.i32 },
89
+ tcsetpgrp: { args: [FFIType.i32, FFIType.i32], returns: FFIType.i32 },
90
+ getpgrp: { args: [], returns: FFIType.i32 },
91
+ // sig_t signal(int, sig_t) — the handler is a pointer; i64 carries it in the same register.
92
+ signal: { args: [FFIType.i32, FFIType.i64], returns: FFIType.i64 },
93
+ });
94
+ libcCache = lib.symbols as unknown as Libc;
95
+ } catch {
96
+ libcCache = null;
97
+ }
98
+ return libcCache;
99
+ }
100
+
101
+ const SIGTTOU = 22; // darwin and linux
102
+ const SIG_IGN = 1;
103
+
104
+ export function defaultForegroundDeps(): ForegroundDeps | null {
105
+ const c = libc();
106
+ if (!c) return null;
107
+ return {
108
+ tcgetpgrp: () => c.tcgetpgrp(0),
109
+ getpgrp: () => c.getpgrp(),
110
+ reclaim: (pgid) => {
111
+ // A background tcsetpgrp raises SIGTTOU unless it is ignored — ignore it for this one call only.
112
+ const prev = c.signal(SIGTTOU, SIG_IGN);
113
+ try { return c.tcsetpgrp(0, pgid) === 0; } finally { c.signal(SIGTTOU, prev); }
114
+ },
115
+ alive: exists,
116
+ isDescendant: isOurDescendant,
117
+ log: (event, data) => debug.log('tui.lifecycle', event, data),
118
+ };
119
+ }
120
+
121
+ /** One check. Exported for tests; the guard calls it on a timer. `state.yieldedTo` keeps the yield log to once per holder. */
122
+ export function checkForeground(deps: ForegroundDeps, state: { yieldedTo: number | null } = { yieldedTo: null }): ForegroundVerdict {
123
+ const ownPgid = deps.getpgrp();
124
+ const ttyPgid = deps.tcgetpgrp();
125
+ if (ttyPgid < 0 || ttyPgid === ownPgid) {
126
+ state.yieldedTo = null;
127
+ return decideForeground({ ownPgid, ttyPgid, groupAlive: true, leaderAlive: true, leaderIsDescendant: false });
128
+ }
129
+ if (state.yieldedTo === ttyPgid) return { action: 'yield', ttyPgid };
130
+ const groupAlive = deps.alive(-ttyPgid);
131
+ const leaderAlive = groupAlive && deps.alive(ttyPgid);
132
+ const leaderIsDescendant = leaderAlive && deps.isDescendant(ttyPgid);
133
+ const verdict = decideForeground({ ownPgid, ttyPgid, groupAlive, leaderAlive, leaderIsDescendant });
134
+ if (verdict.action === 'reclaim') {
135
+ const ok = deps.reclaim(ownPgid);
136
+ deps.log(ok ? 'foreground-reclaimed' : 'foreground-reclaim-failed', { reason: verdict.reason, ttyPgid, ownPgid });
137
+ } else if (verdict.action === 'yield') {
138
+ state.yieldedTo = ttyPgid;
139
+ deps.log('background-tty', { ttyPgid, ownPgid, groupAlive, leaderAlive });
140
+ }
141
+ return verdict;
142
+ }
143
+
144
+ /** Starts the guard; returns stop(). No-op (returns a no-op) when libc/FFI is unavailable. */
145
+ export function startForegroundGuard(opts: { intervalMs?: number; deps?: ForegroundDeps | null } = {}): () => void {
146
+ if (process.env.ELANOUS_TTY_FOREGROUND_GUARD === '0') return () => {};
147
+ const deps = opts.deps === undefined ? defaultForegroundDeps() : opts.deps;
148
+ if (!deps) return () => {};
149
+ const state = { yieldedTo: null as number | null };
150
+ const tick = (): void => { try { checkForeground(deps, state); } catch { /* fail-soft */ } };
151
+ tick();
152
+ const timer = setInterval(tick, opts.intervalMs ?? 250);
153
+ (timer as { unref?: () => void }).unref?.();
154
+ return () => clearInterval(timer);
155
+ }