elanous 0.2.32 → 0.2.35

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (753) hide show
  1. package/apps/pwa/out/404/index.html +1 -1
  2. package/apps/pwa/out/404.html +1 -1
  3. package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{997ce8a5-2ad501927003b41b.js → 0368f25d-ad84af92fefee68f.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1165.bad13fc9151a7288.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/13.02a07436dec15f89.js +32 -0
  7. package/apps/pwa/out/_next/static/chunks/{5525.86debf231e181813.js → 1530.0e612369b6fd7ea0.js} +1 -1
  8. package/apps/pwa/out/_next/static/chunks/1540.af38731fa7c4a3e0.js +41 -0
  9. package/apps/pwa/out/_next/static/chunks/{7391.ebae168025c91b6a.js → 1674.2a65fd5668e1cc5f.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1850.f2b470ba5a471da0.js +24 -0
  11. package/apps/pwa/out/_next/static/chunks/193.62da94cd0b88323b.js +74 -0
  12. package/apps/pwa/out/_next/static/chunks/1975.260f6d249fac5f7c.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1982-67cd8dfe8682325f.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{7947-d0759430f8042240.js → 1993-c0007b7ad0c0ef41.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1999-bb415351c8a2846c.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{60fb96c9.360b01d8d4927b7b.js → 1c735de4.f993a30bbd3c57c4.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/1dc5a567.9b092bfae3d7099b.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/{5307.60f2209e809bd627.js → 2018.a741297bce759490.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2085.8f950b4bda1cbbc7.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2159-6179a961376956b9.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/216.b5c2a421aa1d28a5.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2251.49fbe369f74c372c.js +148 -0
  23. package/apps/pwa/out/_next/static/chunks/2286-2939577360d3dcc0.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/{3902.e1e71aaac850a045.js → 2625.5d870aa999f33db1.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/2668.34d21539e62bf111.js +77 -0
  26. package/apps/pwa/out/_next/static/chunks/2833-0fe47af99ed13c29.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/2930.d0edb4f108787ef7.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2973.77318e7d85f59477.js +62 -0
  29. package/apps/pwa/out/_next/static/chunks/3103.0df8da390948bb84.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3123.2bee9ba15d320bd2.js +90 -0
  31. package/apps/pwa/out/_next/static/chunks/3162-6cf652bf7124d8cf.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{4174.92ed04922709ac9e.js → 3408.21d1570602f4b6c0.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/3577-7340009f7007a795.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/3589.5444a06bcf6e775c.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/359-2250789a2d3499e7.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3618.f514792d6c59d7fd.js +36 -0
  37. package/apps/pwa/out/_next/static/chunks/3669.343f9119aa276001.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/{9398-6aed28f0a96d0d6f.js → 3677-4215f826f6aa68e5.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/3736.c2efad489604cc3b.js +79 -0
  40. package/apps/pwa/out/_next/static/chunks/3817.f9aeab2bb6675d73.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3f7c4ee5.3dde54f01a816613.js +122 -0
  42. package/apps/pwa/out/_next/static/chunks/4182-0b9b1251c29cc0cf.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{7371.80c05c653b08e907.js → 4346.8601952e73bf5803.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/4441-875b97f5821ed58a.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/4582.bd68683c076649e3.js +286 -0
  46. package/apps/pwa/out/_next/static/chunks/4605-6e623f55aec77422.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4607.5cc27468628eb4bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4627.f07508b3936fd6c0.js +24 -0
  49. package/apps/pwa/out/_next/static/chunks/{2940-619bfd8ef337c611.js → 4705-194e64e47ca0fbdb.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/{1335-6731f392c35216eb.js → 4718-17d2af636796a330.js} +3 -3
  51. package/apps/pwa/out/_next/static/chunks/4747-c22262c093e46807.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4775-178215aed0daba61.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4815-6ffb8c3c991cc45d.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4834-beca8b47ad29a898.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5023-fb4802b6d2492b02.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/{7502.ccd5b8065545edd0.js → 5101.e32282718f99ed6f.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{2001.6c7e0fd02190886c.js → 5154.a118f3957ed14e36.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5210-a2e0015e3d4d5d9c.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5356.84ac712cc15928bf.js +1 -0
  60. package/apps/pwa/out/_next/static/chunks/5401.22352141b6fd336e.js +23 -0
  61. package/apps/pwa/out/_next/static/chunks/{5173-233188df2f42c626.js → 5483-dd5d7697f6bdb106.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5637.281e5dec4ea6ecf1.js +94 -0
  63. package/apps/pwa/out/_next/static/chunks/5662.02eaa029af05ad46.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{3267c0e6.d34854e7b3984a6e.js → 56d372f2.681ab4ec4c998fae.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5760.22456f433c6f42c0.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5852.db1f7449f4f74612.js +287 -0
  67. package/apps/pwa/out/_next/static/chunks/5891-0f11a7d7362a9072.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5943.264d14a44ca32513.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/604-1b3c39df083c02aa.js +1 -0
  70. package/apps/pwa/out/_next/static/chunks/6121-5f97072330738caf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/6193.07d8ca5af4b09086.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/6203-b3fea3a60d69ff14.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/{6433.fc573af22bbc9ab7.js → 6236.e18cced2d5ba6afb.js} +17 -17
  74. package/apps/pwa/out/_next/static/chunks/6286.d638fb5953e2e757.js +8 -0
  75. package/apps/pwa/out/_next/static/chunks/630.fe5a46428d63b013.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6301.ae0245f507e4395e.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/6673.fbbe5699f6ea5991.js +27 -0
  78. package/apps/pwa/out/_next/static/chunks/6777-f6d301efb5de828d.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6786.423f24c88de034c7.js +93 -0
  80. package/apps/pwa/out/_next/static/chunks/6854-cef64a948c5e122d.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6866-79aa5b4e47cac6aa.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/{6544cb48.a87fe20ddf137be2.js → 6b89c8bd.24df687a820500b3.js} +1 -1
  83. package/apps/pwa/out/_next/static/chunks/7037-fe27f001db30d323.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7080.2d826860534fd88e.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7118.8731be28c3ebb14b.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/7196.44241bc1df3e26fe.js +149 -0
  87. package/apps/pwa/out/_next/static/chunks/7235.c7c4e6cb5c693c2d.js +104 -0
  88. package/apps/pwa/out/_next/static/chunks/{2871.0bca6137343b3f76.js → 7385.50a308a477bdfc21.js} +1 -1
  89. package/apps/pwa/out/_next/static/chunks/{2985.39ccdecd36848b12.js → 7644.17e37ba6f1d4226e.js} +4 -4
  90. package/apps/pwa/out/_next/static/chunks/7706-58bfb1546637f217.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7839.5b91455338c9fd3f.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7857-31f13ee96f4011aa.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/81.f74cb60312fe4001.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/{8018.a32663f04a6fc5f9.js → 8219.baa715d1deee80e2.js} +1 -1
  95. package/apps/pwa/out/_next/static/chunks/{4111.2bfedbb233ad206b.js → 8256.e3ac8421a71f82f4.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/8310-444a6a895c402f12.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/8423.f7dda8aca4fcaae5.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/8437-8d5492094b166cfa.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{2213.2ccbada92c33ea0f.js → 8444.4c26b379ca2b9596.js} +17 -17
  100. package/apps/pwa/out/_next/static/chunks/8496.75649af8652c74f4.js +226 -0
  101. package/apps/pwa/out/_next/static/chunks/8557-e7898769499cd56f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8576.65bb654b524f3614.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8609.558ce2f8f9aea2be.js +64 -0
  104. package/apps/pwa/out/_next/static/chunks/8614.caec96cfb91f4ae7.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/{6092.a7f99e68b188ca66.js → 8637.47f5b35afcae5e6b.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/8714.ff0b7ce3ec3e3ae2.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8732.367f44a916202353.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9141-7fd1f73a5400bdc2.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/921.c4267d0d69a65404.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{3278.2e5d15b53a4091c8.js → 9214.63a510d39178e997.js} +2 -2
  111. package/apps/pwa/out/_next/static/chunks/9261.3962c3321b047691.js +115 -0
  112. package/apps/pwa/out/_next/static/chunks/936-26efd1a0efdd44d3.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9221.7d22eaf353a2d4e7.js → 938.66ad1ef0e5abae1c.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{6157.0c9af021de4fb31b.js → 9512.5a76207a730e0491.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9627-4b9efe616b27e2e2.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{69-0a2c8209c6d4a158.js → 967-2aa39b2d04b4c690.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9734.40eb1e558c29ccea.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9908.3aa54f7a586a73dc.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/{7862.30a8d6482bb238eb.js → 9952.5daf5f94063a2b3e.js} +1 -1
  120. package/apps/pwa/out/_next/static/chunks/9954-ca8d29752bdbb45a.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9974-507fa67cb94066dd.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-ce9e00f7fb45506a.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-fa59d6d17daa3389.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-53f68bbe7bd4b774.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-1c500fbb9f4a7a04.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-99d72673aa5c307c.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d2d5adc1e9484c88.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c607c5aae637f1cc.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-fa8c23596d555c0f.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-bdab8c5e855c8416.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/{page-a27b1e5a0d1b308f.js → page-406b47745b53f269.js} +1 -1
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-a4276386b7051f50.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8a26bab9ad375f25.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-775f48aa1dc7a2d5.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-1c4dd5f959d0c558.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-c48938a8377c9f70.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-ce9e00f7fb45506a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-c6e7905859425aa9.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c280f4252452e830.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-cf8c57498f20970a.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-ca3a17caf409fc83.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-26e6c18a1a750cf6.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-3abc872cc6aeee39.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-f7481b7b2174fe3d.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-1ae7ef8077680337.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/{page-32866485913d6a04.js → page-47c5d4db587266bd.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-415f1e243c7ccb13.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-73f380f17b76f95c.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-2991073ad66ee2d9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-1f5a60f70cb4dd0c.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fbad60d1e358fb2c.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-bac7dee94e5eae4a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-398047d6949e8ca5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2d33a2231540ca89.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5bf1e6bf70bcb96c.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-ba59c19376a0917d.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-111f187139add30f.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-acaae197d5be5779.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0df20b0f546a0d7d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-ce9e00f7fb45506a.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-27e1202d24b8fe35.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-bda78c50a78363e5.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-da592691293d9c9f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f832994317a2e9f0.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-04d00ae9b0890349.js → page-dc0a532f5b9196ec.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-cfccbbeae0473404.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-527e2073af84c81b.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-bac86e9112671357.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-6d59dff410e9d76a.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-53a61f8be09f02d2.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-db8f559e763c17f9.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-c02aa4cc66455093.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{7a1887c4.f36b88fba31da8fd.js → b2f6ba4d.fb56fdbbf798df33.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/b6705a4f-b9a9047de9eecfd0.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/{b313b242.cb1265eea908db61.js → cbe38a15.5a032598e39970c6.js} +1 -1
  176. package/apps/pwa/out/_next/static/chunks/{409f1e57.d0649fc47691ebfe.js → d06f9160.a3d9062f95de8ad7.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{0bb0ff36.b8d418980951e5ba.js → da5176c6.6773b6c5994e1d99.js} +7 -7
  178. package/apps/pwa/out/_next/static/chunks/framework-50e6acebc630849b.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-7a1ae342d5ed75e6.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7ad7d505ba1f92b4.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-02edba75232cb235.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-97d6ebae3e8eee4a.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-e986adaa429163e8.js +1 -0
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +22 -22
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +22 -22
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +22 -22
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +21 -21
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +21 -21
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +22 -22
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +21 -21
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +22 -22
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +22 -22
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +21 -21
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +22 -22
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +22 -22
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +22 -22
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +22 -22
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +21 -21
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +21 -21
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +22 -22
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +22 -22
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +22 -22
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +21 -21
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +21 -21
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +22 -22
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +22 -22
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +21 -21
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +21 -21
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +21 -21
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +22 -22
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +22 -22
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +21 -21
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +22 -22
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +22 -22
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +22 -22
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +22 -22
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +22 -22
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +21 -21
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +22 -22
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +22 -22
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +22 -22
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +22 -22
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +22 -22
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +22 -22
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +22 -22
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +22 -22
  277. package/bin/elanous.mjs +10 -2
  278. package/catalog/providers/opengateway.yaml +25 -0
  279. package/docs/goal-context/01-goal-authoring-checks.md +8 -0
  280. package/docs/goal-context/03-verification-menu.md +24 -0
  281. package/docs/goal-context/04-mock-scenarios.md +100 -0
  282. package/docs/goal-context/README.md +5 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/default-loop.yaml +76 -5
  285. package/graphs/document-loop.yaml +71 -4
  286. package/graphs/implement-loop.yaml +59 -4
  287. package/graphs/journey/SCENARIOS.md +33 -0
  288. package/graphs/journey/recipes.yaml +1 -0
  289. package/graphs/journey/ta-journey.yaml +94 -0
  290. package/graphs/journey/units/author/author.yaml +20 -0
  291. package/graphs/journey/units/author/recipes.yaml +2 -0
  292. package/graphs/journey/units/author-dialogue/author-dialogue.yaml +42 -0
  293. package/graphs/journey/units/author-dialogue/observe.ts +96 -0
  294. package/graphs/journey/units/author-dialogue/recipes.yaml +10 -0
  295. package/graphs/journey/units/green/green.yaml +20 -0
  296. package/graphs/journey/units/green/recipes.yaml +2 -0
  297. package/graphs/journey/units/pr/pr.yaml +20 -0
  298. package/graphs/journey/units/pr/recipes.yaml +2 -0
  299. package/graphs/journey/units/remember/recipes.yaml +2 -0
  300. package/graphs/journey/units/remember/remember.yaml +20 -0
  301. package/graphs/operate-loop.yaml +71 -4
  302. package/graphs/overlays/stop-heal-ladder.yaml +1 -1
  303. package/graphs/release-rehearsal/recipes.yaml +1 -1
  304. package/graphs/release-rehearsal/release-rehearsal.yaml +2 -2
  305. package/graphs/research-loop.yaml +159 -4
  306. package/graphs/test-diet/test-diet.yaml +3 -0
  307. package/graphs/units/dispatch-pod/dispatch-pod.yaml +50 -0
  308. package/graphs/units/dispatch-pod/recipes.yaml +14 -0
  309. package/graphs/units/entry/entry.yaml +50 -0
  310. package/graphs/units/entry/recipes.yaml +14 -0
  311. package/graphs/units/harvest/harvest.yaml +25 -0
  312. package/graphs/units/harvest/recipes.yaml +4 -0
  313. package/graphs/units/land/land.yaml +45 -0
  314. package/graphs/units/land/recipes.yaml +3 -0
  315. package/graphs/units/recipes.yaml +7 -0
  316. package/graphs/units/recover.yaml +39 -0
  317. package/graphs/units/reflect/recipes.yaml +3 -0
  318. package/graphs/units/reflect/reflect.yaml +15 -0
  319. package/graphs/units/task-agent-recover-review.yaml +17 -0
  320. package/graphs/units/task-agent-recover-wait.yaml +17 -0
  321. package/graphs/units/verbs/make-doc.yaml +34 -0
  322. package/graphs/units/verbs/recipes.yaml +33 -0
  323. package/graphs/units/verbs/verify.yaml +55 -0
  324. package/graphs/work/recipes.yaml +2 -0
  325. package/graphs/work/research-report.yaml +28 -0
  326. package/package.json +1 -1
  327. package/scripts/ci-typecheck-changed.ts +69 -16
  328. package/scripts/coord-role-pack.ts +19 -6
  329. package/scripts/docs/generate-graph-anatomy.ts +19 -2
  330. package/scripts/graph-harvest-unit.ts +22 -0
  331. package/scripts/graph-units/journey-stub.ts +6 -0
  332. package/scripts/graph-units/land-enqueue.ts +78 -0
  333. package/scripts/graph-units/recover-plan.ts +15 -0
  334. package/scripts/graph-units/reflect-node.ts +88 -0
  335. package/scripts/graph-units/ta-journey-observe.ts +109 -0
  336. package/scripts/graph-units/verbs/headless-goal-loop.ts +152 -0
  337. package/scripts/graph-units/verbs/verify-stage.ts +75 -0
  338. package/scripts/graph-units/verbs-envelope.ts +139 -0
  339. package/scripts/hq/standby-snapshot.ts +30 -0
  340. package/scripts/public-export.ts +43 -1
  341. package/scripts/ratchets/train-side-invariants.sh +45 -0
  342. package/scripts/release-loop/auto-approve-node.ts +30 -16
  343. package/scripts/release-loop/docs-land-node.ts +21 -5
  344. package/scripts/release-loop/gate-baseline-receipt.ts +155 -0
  345. package/scripts/release-loop/gate-closure.ts +5 -1
  346. package/scripts/release-loop/gate-diff.ts +1 -1
  347. package/scripts/release-loop/gate-node.ts +675 -49
  348. package/scripts/release-loop/gate-partial.ts +68 -14
  349. package/scripts/release-loop/gate-radius-live.ts +177 -0
  350. package/scripts/release-loop/gate-radius-shadow.ts +138 -0
  351. package/scripts/release-loop/gate-traffic-mode.ts +128 -0
  352. package/scripts/release-loop/gate-triage-node.ts +5 -2
  353. package/scripts/release-loop/known-issues-0.2.33-approved.json +194 -0
  354. package/scripts/release-loop/known-issues-node.ts +77 -8
  355. package/scripts/release-loop/node-verdict.ts +12 -1
  356. package/scripts/release-loop/npm-publish-node.ts +66 -12
  357. package/scripts/release-loop/preflight.ts +93 -7
  358. package/scripts/release-loop/probe-pod-host-dirs-live.ts +5 -0
  359. package/scripts/release-loop/publish-node.ts +60 -9
  360. package/scripts/release-loop/pwa-remote.ts +166 -0
  361. package/scripts/release-loop/pwa-scenarios-node.ts +19 -3
  362. package/scripts/release-loop/resume-cap.ts +56 -0
  363. package/scripts/release-loop/resume-release.ts +155 -19
  364. package/scripts/release-loop/resume.ts +24 -1
  365. package/scripts/release-loop/tui-sim-node.ts +8 -2
  366. package/scripts/release-loop/unattended-release.ts +10 -2
  367. package/scripts/test-diet/lib.ts +6 -1
  368. package/scripts/test-diet/node.ts +194 -13
  369. package/scripts/ux-sim.ts +39 -0
  370. package/src/acp/core-turn-bridge.ts +20 -5
  371. package/src/acp/reasoning-thought-buffer.ts +45 -0
  372. package/src/agent/self-ambient-cache.ts +8 -0
  373. package/src/agent-substrate/acp-reviewer.ts +90 -15
  374. package/src/agent-substrate/pr-reviewer.ts +17 -0
  375. package/src/agent-substrate/review-finding-key.ts +53 -0
  376. package/src/agent-substrate/self-review-cli.ts +188 -18
  377. package/src/ask-user-question/pending-questions.ts +1 -1
  378. package/src/autopilot/pr-manager.ts +393 -65
  379. package/src/budget/run-usage-rollup.ts +1 -0
  380. package/src/chat/index.ts +0 -2
  381. package/src/chat/pickers/modal-runtime.ts +10 -27
  382. package/src/chat/tool-render/dispatch.ts +62 -10
  383. package/src/cli/agent-cli.ts +13 -2
  384. package/src/cli/control-cli.ts +24 -7
  385. package/src/cli/doctor-cli.ts +4 -1
  386. package/src/cli/guardian-cli.ts +10 -0
  387. package/src/cli/light-entry-route.ts +75 -0
  388. package/src/cli/llm-detect-cli.ts +23 -1
  389. package/src/cli/pod-cli.ts +77 -3
  390. package/src/cli/pr-cli.ts +81 -14
  391. package/src/cli/pr-land-base-read.ts +2 -0
  392. package/src/cli/pr-land-overlap-evidence.ts +154 -16
  393. package/src/cli/pr-land-pod-shadow-job.ts +3 -0
  394. package/src/cli/pr-land-recovery.ts +64 -0
  395. package/src/cli/pty-takeover-cli.ts +6 -5
  396. package/src/cli/release-checklist-read-cli.ts +79 -0
  397. package/src/cli/release-cli.ts +189 -132
  398. package/src/cli/release-run-if-ready.ts +29 -28
  399. package/src/cli/release-single-flight.ts +178 -0
  400. package/src/cli/remote-resolve.ts +1 -1
  401. package/src/cli/root-tui-entry.ts +48 -0
  402. package/src/cli/seat-cli.ts +37 -0
  403. package/src/cli/setup-cli.ts +40 -1
  404. package/src/cli/sim-cli.ts +22 -0
  405. package/src/cli/tasks-cli.ts +667 -14
  406. package/src/cli/usage-cli.ts +13 -11
  407. package/src/clipboard/history.ts +179 -13
  408. package/src/config.ts +8 -1
  409. package/src/control/control-status.ts +8 -3
  410. package/src/control-plane/ledger.ts +5 -3
  411. package/src/control-plane/server.ts +5 -3
  412. package/src/core-turn/short-question.ts +5 -1
  413. package/src/dashboard/chat/acp-chat.ts +8 -0
  414. package/src/dashboard/index.ts +114 -77
  415. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +3 -0
  416. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  417. package/src/dashboard/input/seat-autowake.ts +56 -3
  418. package/src/dashboard/render/theme-resolver.ts +33 -4
  419. package/src/dashboard/seat-boot-preamble.ts +1 -1
  420. package/src/dashboard/slash-runtime/ask-clarification.ts +48 -0
  421. package/src/dashboard/slash-runtime/dashboard-delegated-slashes.ts +68 -0
  422. package/src/dashboard/slash-runtime/dashboard-handlers.ts +62 -322
  423. package/src/dashboard/slash-runtime/dashboard-log-slash.ts +208 -0
  424. package/src/dashboard/turn-preamble.ts +47 -1
  425. package/src/dashboard/turn-stream-formatter.ts +34 -1
  426. package/src/dashboard/turn-stream-runtime.ts +2 -0
  427. package/src/dashboard/turn-typeahead-prompt-zone.ts +67 -0
  428. package/src/domains/guardian-tick.ts +54 -2
  429. package/src/domains/outbound-alert.ts +3 -2
  430. package/src/domains/schedule-registry.ts +16 -2
  431. package/src/extractors.ts +3 -1
  432. package/src/git-fs/idle-refresh.ts +76 -0
  433. package/src/git-fs/index.ts +18 -7
  434. package/src/git-fs/retry.ts +4 -0
  435. package/src/git-fs/runner.ts +2 -0
  436. package/src/git-fs/worktree.ts +42 -4
  437. package/src/graph-kinds/registry.ts +2 -2
  438. package/src/graph-runner/runner.ts +267 -54
  439. package/src/grok/credential.ts +15 -3
  440. package/src/harness/harness-cli-command.ts +151 -38
  441. package/src/harness/harness-incidents.ts +37 -0
  442. package/src/harness/harness-pod-dispatch.ts +38 -1
  443. package/src/harness/harness-salvage-cli.ts +14 -2
  444. package/src/harness/launch-utterance-ledger.ts +208 -0
  445. package/src/impl-discipline/detector.ts +16 -4
  446. package/src/impl-discipline/system-prompt.ts +11 -0
  447. package/src/impl-discipline/types.ts +2 -2
  448. package/src/index.ts +683 -146
  449. package/src/intake-plane/already-built-hint.ts +91 -0
  450. package/src/intake-plane/requirement-funnel.ts +29 -1
  451. package/src/knowhow/pack.ts +199 -0
  452. package/src/light-cli.ts +111 -0
  453. package/src/llm/opengateway-models.ts +11 -0
  454. package/src/llm/provider-credentials.ts +14 -0
  455. package/src/llm/provider-detect.ts +8 -1
  456. package/src/llm/runtime-model-family.ts +2 -1
  457. package/src/llm.ts +268 -65
  458. package/src/loops/budget.ts +95 -0
  459. package/src/loops/msg-wake.ts +8 -2
  460. package/src/loops/orchestrator/traffic.ts +132 -1
  461. package/src/model-tier/llm-tier-map.ts +15 -1
  462. package/src/mss/logging/log-store.ts +4 -5
  463. package/src/native-tool-catalog.ts +15 -1
  464. package/src/nexus/api/graphs-api.ts +22 -3
  465. package/src/nexus/api/http-server.ts +1 -1
  466. package/src/nexus/api/loop-resources.ts +13 -1
  467. package/src/nexus/api/ops-api.ts +12 -0
  468. package/src/oauth/claude-pty-maturity.ts +66 -0
  469. package/src/oauth/codex-access-mirror.ts +55 -0
  470. package/src/oauth/codex.ts +7 -0
  471. package/src/oauth/fallback-chain.ts +1 -1
  472. package/src/onboarding/first-run.ts +5 -3
  473. package/src/onboarding/non-interactive.ts +64 -13
  474. package/src/onboarding.ts +10 -2
  475. package/src/ops/overview-collect.ts +54 -4
  476. package/src/ops/overview.ts +31 -7
  477. package/src/pr-tool/census.ts +282 -30
  478. package/src/pr-tool/inflight-registry.ts +160 -7
  479. package/src/prompt-library/gpt6-family-addendum.ts +14 -1
  480. package/src/pty-shell/herdr-agent-report.ts +442 -0
  481. package/src/pty-shell/pty-control-ipc.ts +5 -5
  482. package/src/pty-shell/pty-manifest.ts +7 -0
  483. package/src/pty-shell/pty-write-outcome.ts +24 -6
  484. package/src/pty-shell/tui-run-state.ts +117 -3
  485. package/src/release-loop/checklist.ts +103 -5
  486. package/src/release-loop/feature-store.ts +19 -2
  487. package/src/release-loop/landed-but-yellow.ts +129 -5
  488. package/src/release-loop/light-rc.ts +1 -0
  489. package/src/release-loop/placement.ts +10 -3
  490. package/src/release-loop/rehearsal.ts +205 -25
  491. package/src/release-loop/rubric.ts +16 -2
  492. package/src/repl/index.ts +174 -17
  493. package/src/repl/ops-msg-bridge.ts +32 -0
  494. package/src/self-dev/ask-launch-flow.ts +44 -5
  495. package/src/self-dev/cli-help-text.ts +17 -0
  496. package/src/self-dev/dev-cli.ts +11 -9
  497. package/src/self-dev/draft-residue.ts +37 -1
  498. package/src/self-dev/draft-sweep.ts +188 -13
  499. package/src/self-dev/draft-triage-rules.ts +107 -0
  500. package/src/self-dev/fleet-reduce.ts +3 -2
  501. package/src/self-dev/graph-front-nodes.ts +112 -0
  502. package/src/self-dev/graph-journey-nodes.ts +11 -6
  503. package/src/self-dev/graph-journey-route.ts +60 -6
  504. package/src/self-dev/harness-run-cli.ts +3 -15
  505. package/src/self-dev/orchestrate-cli-text.ts +10 -0
  506. package/src/self-dev/orchestrate.ts +79 -3
  507. package/src/self-dev/review-provider-fallback.ts +35 -1
  508. package/src/self-dev/run-supervisor.ts +107 -12
  509. package/src/self-dev/run-types.ts +5 -1
  510. package/src/self-dev/self-orchestrate-runtime.ts +1 -11
  511. package/src/self-dev/shard-aggregate.ts +42 -5
  512. package/src/self-dev/shard-run.ts +8 -1
  513. package/src/self-implement/blocked-draft-policy.ts +20 -0
  514. package/src/self-implement/classify-shadow.ts +3 -7
  515. package/src/self-implement/doctor-visit.ts +18 -1
  516. package/src/self-implement/gate-baseline.ts +95 -12
  517. package/src/self-implement/gate-cli.ts +1 -0
  518. package/src/self-implement/gate-remote.ts +40 -25
  519. package/src/self-implement/goal-author-decompose.ts +275 -47
  520. package/src/self-implement/goal-author-identity.ts +66 -0
  521. package/src/self-implement/goal-author-preservation-obligation.ts +35 -0
  522. package/src/self-implement/goal-author.ts +254 -120
  523. package/src/self-implement/goal-elaborate.ts +295 -0
  524. package/src/self-implement/goal-refine.ts +270 -0
  525. package/src/self-implement/graph-overlay-yaml.ts +28 -2
  526. package/src/self-implement/graph-unit-flatten.ts +103 -0
  527. package/src/self-implement/graph-unit-resolver.ts +107 -0
  528. package/src/self-implement/graph-yaml.ts +151 -1
  529. package/src/self-implement/headless-elanous-driver.ts +1 -0
  530. package/src/self-implement/knowhow-pack.ts +103 -0
  531. package/src/self-implement/orchestrator.ts +160 -45
  532. package/src/self-implement/pod-warm-pool-profile.ts +45 -0
  533. package/src/self-implement/review-mustfix-class.ts +203 -0
  534. package/src/self-implement/rework-budget-judgment.ts +5 -8
  535. package/src/self-implement/run-stop.ts +17 -2
  536. package/src/self-implement/running-runs.ts +29 -1
  537. package/src/self-implement/scope-adjacency.ts +113 -0
  538. package/src/self-implement/seams.ts +138 -4
  539. package/src/self-implement/stop-autoheal.ts +112 -2
  540. package/src/session/chat.ts +27 -0
  541. package/src/session-runtime/index.ts +1 -1
  542. package/src/session-runtime/retry-policy.ts +2 -1
  543. package/src/setup/llm-env-detect.ts +5 -0
  544. package/src/skills/tools/agent.ts +140 -14
  545. package/src/skills/tools/msg-ask.ts +100 -0
  546. package/src/skills/tools/ops-ledger.ts +2 -1
  547. package/src/skills/tools/schedule-wakeup.ts +66 -17
  548. package/src/steward/hold-hygiene.ts +24 -6
  549. package/src/steward/release-day.ts +7 -3
  550. package/src/steward/triage-budget.ts +194 -0
  551. package/src/steward/triage.ts +57 -7
  552. package/src/task-agent/actions.ts +69 -1
  553. package/src/task-agent/green-sweep.ts +4 -0
  554. package/src/task-agent/harvest-unit.ts +141 -0
  555. package/src/task-agent/live-moves.ts +257 -15
  556. package/src/task-agent/parent-host.ts +216 -6
  557. package/src/task-agent/postland-card.ts +80 -1
  558. package/src/task-agent/rejudge-on-head.ts +112 -26
  559. package/src/task-agent/repair-branch-cas.ts +4 -1
  560. package/src/task-agent/repair-cycle.ts +16 -3
  561. package/src/task-agent/run-identity.ts +4 -3
  562. package/src/task-agent/shadow.ts +19 -3
  563. package/src/task-agent/task-hand.ts +96 -36
  564. package/src/task-agent/tier-split.ts +127 -0
  565. package/src/task-agent/work-order-build.ts +24 -0
  566. package/src/task-agent/work-order.ts +3 -2
  567. package/src/task-orchestrator/generator-prompt.ts +60 -11
  568. package/src/task-orchestrator/surfaces/pod-account-broker.ts +72 -3
  569. package/src/task-orchestrator/surfaces/pod-child-providers.ts +1 -1
  570. package/src/task-orchestrator/surfaces/pod-command-job.ts +47 -8
  571. package/src/task-orchestrator/surfaces/pod-image-source.ts +89 -1
  572. package/src/task-orchestrator/surfaces/pod-lease.ts +17 -8
  573. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +86 -8
  574. package/src/task-orchestrator/surfaces/pod-manifest-test-normalize.ts +8 -2
  575. package/src/task-orchestrator/surfaces/pod-pool.ts +73 -17
  576. package/src/task-orchestrator/surfaces/pod-provenance.ts +76 -0
  577. package/src/task-orchestrator/surfaces/pod-source-receive.ts +72 -4
  578. package/src/task-orchestrator/surfaces/pod-warm-provenance.ts +81 -0
  579. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +32 -5
  580. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +3 -0
  581. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +421 -0
  582. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +2 -1
  583. package/src/task-orchestrator/surfaces/self-implement-pod.ts +588 -71
  584. package/src/task-orchestrator/surfaces/self-implement.ts +106 -2
  585. package/src/tool-runtime/ops-ledger-runtimes.ts +10 -2
  586. package/src/tool-runtime/truncation-store.ts +4 -0
  587. package/src/tui/README.md +2 -0
  588. package/src/tui/chat/background-job-status.ts +54 -0
  589. package/src/tui/chat/log-view.ts +80 -0
  590. package/src/tui/entry.ts +406 -0
  591. package/src/tui/input/composer.ts +144 -0
  592. package/src/tui/seat-mail-boot.ts +59 -0
  593. package/src/tui/slash/compact.ts +100 -0
  594. package/src/tui/slash/new-session.ts +35 -0
  595. package/src/tui-client/dashboard-session.ts +10 -1
  596. package/src/tui-client/local-chat-turn.ts +239 -0
  597. package/src/tui-client/local-harness-command.ts +63 -0
  598. package/src/tui-client/local-provider-command.ts +184 -0
  599. package/src/user-config/coercion.ts +36 -0
  600. package/src/user-config.ts +22 -43
  601. package/src/ux-sim/event-monkey.ts +378 -0
  602. package/src/ux-sim/fake-bin.ts +42 -7
  603. package/src/ux-sim/fault-nextmove-dispatch.ts +266 -0
  604. package/src/ux-sim/fault-pod-codex-503.ts +211 -0
  605. package/src/ux-sim/fault-scope-escape-lift.ts +189 -0
  606. package/src/ux-sim/scenario.ts +72 -13
  607. package/src/version/packed-revision.json +1 -1
  608. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +0 -27
  611. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +0 -287
  612. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +0 -62
  613. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/1654.32de4b324981a188.js +0 -23
  617. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +0 -149
  619. package/apps/pwa/out/_next/static/chunks/1913.7cc6fb6055b1ed3f.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +0 -1
  625. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +0 -115
  629. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +0 -64
  630. package/apps/pwa/out/_next/static/chunks/3541-ce3a5424ed5ad7f1.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +0 -36
  636. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +0 -286
  640. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +0 -77
  641. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +0 -226
  642. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +0 -79
  644. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +0 -148
  647. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/5458-16cd7a2b51b74c8c.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/5543.a438b8ab5a13ea47.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +0 -74
  653. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +0 -94
  655. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +0 -90
  661. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +0 -32
  662. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +0 -104
  663. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +0 -24
  668. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +0 -93
  669. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +0 -8
  674. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +0 -24
  685. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/9138.b6e80031afb1d973.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/9279-d28c5b7754d010ae.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/9989.3694300e5f000b14.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/setup/page-c219f2ed171131be.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +0 -122
  744. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +0 -1
  752. package/src/cli/g6a-registration-probe.ts +0 -16
  753. /package/apps/pwa/out/_next/static/{IVKr3AlRUVLKsw2fh7eXF → T1mBQqmkwKDLGtyisDCOd}/_ssgManifest.js +0 -0
@@ -0,0 +1,36 @@
1
+ export function clampNum(v: unknown, fallback: number, min: number, max: number): number {
2
+ if (typeof v !== 'number' || !Number.isFinite(v)) return fallback;
3
+ if (v < min) return min;
4
+ if (v > max) return max;
5
+ return v;
6
+ }
7
+
8
+ export function positiveIntOr(v: unknown, fallback: number): number {
9
+ return typeof v === 'number' && Number.isSafeInteger(v) && v > 0 ? v : fallback;
10
+ }
11
+
12
+ export function str(v: unknown): string | undefined {
13
+ return typeof v === 'string' && v.length > 0 ? v : undefined;
14
+ }
15
+
16
+ export function strArray(v: unknown, fallback: string[]): string[] {
17
+ if (!Array.isArray(v)) return fallback;
18
+ const out = v.filter((x): x is string => typeof x === 'string' && x.length > 0);
19
+ return out.length > 0 ? out : fallback;
20
+ }
21
+
22
+ export function stringRecord(v: unknown): Record<string, string> {
23
+ if (!v || typeof v !== 'object' || Array.isArray(v)) return {};
24
+ const out: Record<string, string> = {};
25
+ for (const [k, val] of Object.entries(v as Record<string, unknown>)) {
26
+ if (typeof k === 'string' && k.length > 0 && typeof val === 'string' && val.length > 0) {
27
+ out[k] = val;
28
+ }
29
+ }
30
+ return out;
31
+ }
32
+
33
+ export function numArray(v: unknown, fallback: number[]): number[] {
34
+ if (!Array.isArray(v)) return fallback;
35
+ return v.filter((x): x is number => typeof x === 'number' && Number.isFinite(x));
36
+ }
@@ -64,6 +64,8 @@ import {
64
64
  import { lookupLlmTierSpec } from './model-tier/llm-tier-map.js';
65
65
  import { BEDROCK_DEFAULT_MODEL } from './llm/bedrock.js';
66
66
  import { userConfigPath as nexusUserConfigPath } from './nexus/config/paths.js';
67
+ import { getElanousConfigDirOverride } from './elanous-config-dir.js';
68
+ import { getTestStateRoot } from './nexus/paths.js';
67
69
  import { type StreamingMode, isStreamingMode } from './session/streaming/stream-compositor.js';
68
70
  import type { DevRequestRoutingConfig } from './skills/dev-request-router.js';
69
71
  import type { UrlRoutingConfig } from './skills/url-router.js';
@@ -72,6 +74,7 @@ import { withFileLockSync } from './storage/file-lock.js';
72
74
  import { debug } from './debug/log.js';
73
75
  import { setConfigTimeZoneSource } from './time/format.js';
74
76
  import { parseGeminiServerTools } from './user-config/gemini-server-tools.js';
77
+ import { clampNum, numArray, positiveIntOr, str, strArray, stringRecord } from './user-config/coercion.js';
75
78
  import type { FoldMode } from './log-entry.js';
76
79
  import {
77
80
  CLAUDE_PACKAGE_MISSING,
@@ -147,6 +150,7 @@ export type LLMProviderName =
147
150
  | 'kimi' | 'qwen' | 'glm'
148
151
  // 대표 2026-09-23 — OpenAI 호환 게이트웨이. kimi·qwen·glm 의 «첫 실제 경로»(모델 id `openrouter/<vendor>/<model>`).
149
152
  | 'openrouter'
153
+ | 'opengateway'
150
154
  // 대표 2026-10-10 (BEDROCK-PROVIDER) — AWS Bedrock 의 Claude. 자격 = AWS 기본 자격 체인 · 명시 선택 전용(auto·폴백 후보 아님).
151
155
  | 'bedrock';
152
156
 
@@ -154,12 +158,12 @@ export type LLMProviderName =
154
158
  // ⛔ 2026-09-23 — 손으로 적은 목록이라 새 provider 를 «조용히» 거른다: `openrouter` 를 배선(#19900)했는데
155
159
  // 여기 없어서 config 로 고르면 정규화가 `auto` 로 떨궜다(「직렬화 드롭」). 자 = `test/llm-provider-name-lists.test.ts`.
156
160
  export const CONFIG_LLM_PROVIDER_NAMES: readonly LLMProviderName[] = [
157
- 'auto', 'grok', 'openai', 'anthropic', 'local', 'openai-codex', 'gemini', 'openrouter', 'bedrock',
161
+ 'auto', 'grok', 'openai', 'anthropic', 'local', 'openai-codex', 'gemini', 'openrouter', 'opengateway', 'bedrock',
158
162
  ];
159
163
 
160
164
  /** `ELANOUS_LLM_PROVIDER` additionally permits every declared runtime provider. */
161
165
  export const RUNTIME_LLM_PROVIDER_NAMES: readonly LLMProviderName[] = [
162
- 'auto', 'grok', 'openai', 'anthropic', 'local', 'openai-codex', 'gemini', 'kimi', 'qwen', 'glm', 'openrouter', 'bedrock',
166
+ 'auto', 'grok', 'openai', 'anthropic', 'local', 'openai-codex', 'gemini', 'kimi', 'qwen', 'glm', 'openrouter', 'opengateway', 'bedrock',
163
167
  ];
164
168
 
165
169
  /** Provider-agnostic reasoning intensity. The HUD click cycle and the
@@ -3892,7 +3896,7 @@ export interface UserConfig {
3892
3896
  guardian?: { mode?: 'shadow' | 'live'; /** Orphan CLI GC on the guardian tick: off = no ps collection, shadow (default) = evidence only, on = evidence then SIGTERM. */ orphanGc?: 'off' | 'shadow' | 'on' };
3893
3897
  /** Task-agent live move allow-list (`src/task-agent/live-moves.ts` validates its vocabulary).
3894
3898
  * Absent = env ELANOUS_TASK_AGENT_LIVE_MOVES, else none (pure shadow). */
3895
- taskAgent?: { liveMoves?: string[]; /** TA-REJUDGE-PERIODIC — steward tick runs `tasks rejudge --all` every N minutes (absent/0 = off). */ rejudgeEveryMinutes?: number; /** 1-minute load average above which that tick is skipped (default 60). */ rejudgeMaxLoad?: number; /** TA-REPAIR-TICK-CAP — new repair launches per `tasks rejudge --all` (default 3, 0 = none). */ repairMaxPerTick?: number; /** TA-LAND-AFTER-REVIEW — opt-in external queue adapter, never a direct merge command. */ landQueue?: { command: string; remote: string }; parentHost?: { host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number } | Array<{ host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number }> };
3899
+ taskAgent?: { liveMoves?: string[]; /** TA-REJUDGE-PERIODIC — steward tick runs `tasks rejudge --all` every N minutes (absent/0 = off). */ rejudgeEveryMinutes?: number; /** 1-minute load average above which that tick is skipped (default 60). */ rejudgeMaxLoad?: number; /** TA-REPAIR-TICK-CAP — new repair launches per `tasks rejudge --all` (default 3, 0 = none). */ repairMaxPerTick?: number; /** Old cards are skipped by periodic rejudge after this many hours (default 72). */ rejudgeMaxAgeHours?: number; /** TA-LAND-AFTER-REVIEW — opt-in external queue adapter, never a direct merge command. */ landQueue?: { command: string; remote: string }; parentHost?: { host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number } | Array<{ host?: string; cwd?: string; elanous?: string; configDir?: string; podPool?: string; approvalCapacity?: number }> };
3896
3900
  events?: EventsConfig;
3897
3901
  /** GATE-REMOTE — see GateRemoteConfig. Absent = defaults (auto on · node-b · load 20 · cap 2). */
3898
3902
  gateRemote?: GateRemoteConfig;
@@ -4204,7 +4208,7 @@ function parseTaskAgentConfig(raw: unknown): UserConfig['taskAgent'] {
4204
4208
  }
4205
4209
  const parentHost = parseTaskAgentParentHost((raw as Record<string, unknown>).parentHost);
4206
4210
  // TA-REJUDGE-PERIODIC — 음이 아닌 유한수만 산다(0 = 끔). 그 밖은 경고하고 버린다(= 끔 · 기본 부하 상한).
4207
- const rejudge: { rejudgeEveryMinutes?: number; rejudgeMaxLoad?: number; repairMaxPerTick?: number } = {};
4211
+ const rejudge: { rejudgeEveryMinutes?: number; rejudgeMaxLoad?: number; repairMaxPerTick?: number; rejudgeMaxAgeHours?: number } = {};
4208
4212
  for (const key of ['rejudgeEveryMinutes', 'rejudgeMaxLoad'] as const) {
4209
4213
  const value = (raw as Record<string, unknown>)[key];
4210
4214
  if (value === undefined) continue;
@@ -4216,6 +4220,12 @@ function parseTaskAgentConfig(raw: unknown): UserConfig['taskAgent'] {
4216
4220
  if (Number.isSafeInteger(repairMaxPerTick) && (repairMaxPerTick as number) >= 0) rejudge.repairMaxPerTick = repairMaxPerTick as number;
4217
4221
  else warnUserConfigDrop('taskAgent.repairMaxPerTick', `음이 아닌 정수가 아니다(${JSON.stringify(repairMaxPerTick)}) — 기본 3`);
4218
4222
  }
4223
+ const rejudgeMaxAgeHours = (raw as Record<string, unknown>).rejudgeMaxAgeHours;
4224
+ if (rejudgeMaxAgeHours !== undefined) {
4225
+ if (typeof rejudgeMaxAgeHours === 'number' && Number.isFinite(rejudgeMaxAgeHours) && rejudgeMaxAgeHours > 0)
4226
+ rejudge.rejudgeMaxAgeHours = rejudgeMaxAgeHours;
4227
+ else warnUserConfigDrop('taskAgent.rejudgeMaxAgeHours', `양의 유한수가 아니다(${JSON.stringify(rejudgeMaxAgeHours)}) — 기본 72`);
4228
+ }
4219
4229
  const queueRaw = (raw as Record<string, unknown>).landQueue;
4220
4230
  let landQueue: { command: string; remote: string } | undefined;
4221
4231
  if (queueRaw !== undefined) {
@@ -4541,6 +4551,13 @@ function emitXdgDeprecationWarningOnce(xdgPath: string): void {
4541
4551
  }
4542
4552
 
4543
4553
  export function userConfigPath(): string {
4554
+ // An explicit CLI override or an isolated root selected by --test or a
4555
+ // parent stamp must not be shadowed by legacy XDG from a parent shell.
4556
+ // All state roots, including bun test's isolation root, outrank legacy XDG.
4557
+ // XDG-only callers have no selected state root (covered by a spawned CLI).
4558
+ if (getElanousConfigDirOverride() !== undefined || process.env.ELANOUS_STATE_DIR?.trim() || getTestStateRoot() !== undefined) {
4559
+ return nexusUserConfigPath();
4560
+ }
4544
4561
  const xdg = process.env.XDG_CONFIG_HOME?.trim();
4545
4562
  if (xdg) {
4546
4563
  const xdgPath = join(xdg, 'elanous', 'config.json');
@@ -6285,6 +6302,7 @@ export const PROVIDER_DEFAULT_MODEL: Record<LLMProviderName, string> = {
6285
6302
  grok: 'grok-4.7',
6286
6303
  // 대표 2026-09-23 — 사다리 balanced 와 같다(`llm.ts` OPENROUTER_MODEL). 자가 둘을 묶는다.
6287
6304
  openrouter: 'openrouter/z-ai/glm-5.3',
6305
+ opengateway: 'opengateway/deepseek/deepseek-v4.1-flash-ultrafast',
6288
6306
  // ⛔ 2026-08-18: 'gemini-2.0-flash' 는 카탈로그의 «가장 낡은» 항목이었다. 같은 날 grok 을
6289
6307
  // 고치면서 이 줄이 빠졌다. 카탈로그가 recommended 로 표시한 실물 flash 로 맞춘다.
6290
6308
  gemini: 'gemini-3.8-flash',
@@ -6994,45 +7012,6 @@ export function markOnboardingComplete(cfg: UserConfig): UserConfig {
6994
7012
 
6995
7013
  export function currentOnboardingVersion(): number { return ONBOARDING_VERSION; }
6996
7014
 
6997
- // ── Coercion helpers ─────────────────────────────────────────────────
6998
-
6999
- function clampNum(v: unknown, fallback: number, min: number, max: number): number {
7000
- if (typeof v !== 'number' || !Number.isFinite(v)) return fallback;
7001
- if (v < min) return min;
7002
- if (v > max) return max;
7003
- return v;
7004
- }
7005
-
7006
- function positiveIntOr(v: unknown, fallback: number): number {
7007
- return typeof v === 'number' && Number.isSafeInteger(v) && v > 0 ? v : fallback;
7008
- }
7009
-
7010
- function str(v: unknown): string | undefined {
7011
- return typeof v === 'string' && v.length > 0 ? v : undefined;
7012
- }
7013
-
7014
- function strArray(v: unknown, fallback: string[]): string[] {
7015
- if (!Array.isArray(v)) return fallback;
7016
- const out = v.filter((x): x is string => typeof x === 'string' && x.length > 0);
7017
- return out.length > 0 ? out : fallback;
7018
- }
7019
-
7020
- function stringRecord(v: unknown): Record<string, string> {
7021
- if (!v || typeof v !== 'object' || Array.isArray(v)) return {};
7022
- const out: Record<string, string> = {};
7023
- for (const [k, val] of Object.entries(v as Record<string, unknown>)) {
7024
- if (typeof k === 'string' && k.length > 0 && typeof val === 'string' && val.length > 0) {
7025
- out[k] = val;
7026
- }
7027
- }
7028
- return out;
7029
- }
7030
-
7031
- function numArray(v: unknown, fallback: number[]): number[] {
7032
- if (!Array.isArray(v)) return fallback;
7033
- return v.filter((x): x is number => typeof x === 'number' && Number.isFinite(x));
7034
- }
7035
-
7036
7015
  function normalizeProvider(v: unknown): LLMProviderName {
7037
7016
  const allowed = CONFIG_LLM_PROVIDER_NAMES;
7038
7017
  if (typeof v === 'string' && (allowed as readonly string[]).includes(v)) {
@@ -0,0 +1,378 @@
1
+ // ── 사건 주입 «이벤트 몽키» (SIM-EVENT-MONKEY · 사다리 L0 · 0.2.35) ─────────────────
2
+ //
3
+ // 🚨 왜 이것이 있나
4
+ // green 판정·run doctor 는 «진짜 사건»이 일어나야 돈다. 그런데 긴 자식 오류 · 같은 칸 재사용 push ·
5
+ // 범위 밖 편집 보류 · 결과 줄 없음 · PR 번호 잃은 종료 · 착지 슬롯 대기는 운영에서 «기다려야» 났다.
6
+ // 이 장치는 그 사건 줄을 «격리 시험 우주»에 언제든 쓴다 — 소비자(run doctor · tasks outcomes · green 근거)를
7
+ // 사건을 기다리지 않고 돌려 볼 수 있게.
8
+ //
9
+ // ⛔ 흉내 내지 않는다(MANUAL-ux-simulation-devices §2):
10
+ // - 원장 줄은 운영과 «같은» 쓰기 함수 appendRunLedgerEntry 로 쓴다(JSONL 을 손으로 짓지 않는다).
11
+ // - 자식 증거는 호스트가 부르는 «같은» 정형기 podChildEvidenceFromResult 로, PR 종료 기록은
12
+ // «같은» 분류기 classifyPodTerminal 로 만든다. 관측 줄은 debug.log 와 같은 꼴(category·event·data)로,
13
+ // 격리 우주 logs.db 를 «같은» LogStore 로 직접 열어 쓴다.
14
+ // ⛔ 전역 debug.log 로 보내지 않는다 — 그 프로세스에 운영 LogStore 싱크가 붙어 있으면 원장 검사를 통과해도
15
+ // 운영 logs.db 에 주입 줄이 들어간다(리뷰 r3 must-fix). 그래서 관측 줄의 출구는 격리 DB «하나»뿐이다.
16
+ // ⛔ 운영 우주(~/.elanous · 계정의 ops 뿌리)에는 «한 줄도» 쓰지 않는다 — 쓰기 전에 거부한다.
17
+ // 🏷️ 모든 줄에 injected:true · injectionId · level:'L0' 를 싣는다 — 소비자가 진짜 사건과 가를 수 있게.
18
+
19
+ import { randomUUID } from 'node:crypto';
20
+ import { isAbsolute, join, relative, resolve, sep } from 'node:path';
21
+ import { appendRunLedgerEntry, runLedgerDir, runLedgerPath, type RunLedgerEntry } from '../self-implement/run-ledger.js';
22
+ import { podChildEvidenceFromResult } from '../task-orchestrator/surfaces/self-implement.js';
23
+ import { classifyPodTerminal } from '../self-dev/draft-residue.js';
24
+ import { effectiveInstanceRoot, normRoot, prodInstanceRoot } from '../instance/resolve.js';
25
+ import { isInsideOpsRoot, physicalPath } from '../instance/test-write-guard.js';
26
+ import { LogStore } from '../mss/logging/log-store.js';
27
+ import { resolveTestRoot } from '../cli/test-flag.js';
28
+ import { getElanousConfigDirOverride } from '../elanous-config-dir.js';
29
+
30
+ export const EVENT_MONKEY_LEVEL = 'L0' as const;
31
+
32
+ export const EVENT_MONKEY_KINDS = [
33
+ 'child-error-long', 'same-cell-reuse-push', 'scope-escape-held', 'no-result-line', 'pr-terminal-null', 'land-slot-wait',
34
+ ] as const;
35
+ export type EventMonkeyKind = (typeof EVENT_MONKEY_KINDS)[number];
36
+
37
+ export interface EventMonkeyCatalogEntry {
38
+ readonly summary: string;
39
+ /** 원장(run-ledger)에 쓰는 사건 이름 — 운영의 같은 이름. */
40
+ readonly ledgerEvents: readonly string[];
41
+ /** 격리 logs.db 에 쓰는 «범주 사건» — 운영 debug.log 의 같은 이름. */
42
+ readonly debugEvents: readonly string[];
43
+ /** 이 줄을 읽어야 하는 소비자(정적 목록). */
44
+ readonly consumers: readonly string[];
45
+ }
46
+
47
+ export const EVENT_MONKEY_CATALOG: Readonly<Record<EventMonkeyKind, EventMonkeyCatalogEntry>> = {
48
+ 'child-error-long': {
49
+ summary: 'Pod 자식이 ≈4KB 오류 문면으로 실패 — 호스트가 pod-child-evidence 로 옮긴 꼴',
50
+ ledgerEvents: ['pod-child-run', 'pod-child-evidence'],
51
+ debugEvents: ['self-implement.pod child-error', 'self-implement.pod job-finished'],
52
+ consumers: ['run doctor (elanous doctor · child-dead-no-result)', 'harness 종료 분류 latestPodChildEvidence → recordRunExit', 'elanous tasks outcomes', 'harness incidents'],
53
+ },
54
+ 'same-cell-reuse-push': {
55
+ summary: '같은 칸 OPEN PR 재사용 push — allowed(fast-forward) · refused(신원 불일치) 두 변형',
56
+ ledgerEvents: ['same-cell-push-decision', 'pod-child-run', 'pod-child-evidence'],
57
+ debugEvents: ['autopilot.pr-manager same-cell-push-decision', 'autopilot.pr-manager same-cell-reused'],
58
+ consumers: ['elanous tasks outcomes (prFailure)', 'green 근거 (card-evidence)', 'elanous logs --category autopilot.pr-manager'],
59
+ },
60
+ 'scope-escape-held': {
61
+ summary: '범위 밖 편집을 worktree 에 보류 — outOfScopeEdits 이름 목록',
62
+ ledgerEvents: ['execution-scope-held', 'pod-child-run', 'pod-child-evidence'],
63
+ debugEvents: ['self-implement.pod child-error'],
64
+ consumers: ['run doctor (scope-drift)', 'harness 종료 분류 scope-escape', 'elanous tasks outcomes', 'harness incidents'],
65
+ },
66
+ 'no-result-line': {
67
+ summary: 'Pod 가 결과 줄 없이 실패 — childEvidence null · PR 종료 미관측',
68
+ ledgerEvents: ['pod-child-run', 'pod-child-evidence', 'pod-ledger-incomplete', 'pr-terminal'],
69
+ debugEvents: ['self-implement.pod job-finished'],
70
+ consumers: ['run doctor (child-dead-no-result)', 'elanous tasks outcomes', 'draft residue sweeper (pr-terminal)', 'green 근거 (card-evidence)'],
71
+ },
72
+ 'pr-terminal-null': {
73
+ summary: 'draft 를 연 뒤 자식 실패 — 같은 가지인데 pr-terminal.prNumber 가 null',
74
+ ledgerEvents: ['pod-child-run', 'pr-opened', 'pod-child-evidence', 'pr-terminal'],
75
+ debugEvents: ['self-implement.pod pr-terminal-branch-lookup'],
76
+ consumers: ['draft residue sweeper (pr-terminal)', 'green 근거 (card-evidence)', 'elanous tasks outcomes', 'harness 하니스 draft 소유 판정 (pr-opened)'],
77
+ },
78
+ 'land-slot-wait': {
79
+ summary: '착지 무거운 단계 호스트 슬롯이 모두 차서 대기',
80
+ ledgerEvents: ['land-slot-wait'],
81
+ debugEvents: ['pr.land host-busy'],
82
+ consumers: ['run doctor (host-overload)', 'elanous logs --category pr.land', 'OP 착지 줄(land-queue) 관측'],
83
+ },
84
+ };
85
+
86
+ export type EventMonkeyVariant = 'allowed' | 'refused';
87
+
88
+ export interface EventMonkeyDebugRow {
89
+ readonly category: string;
90
+ readonly event: string;
91
+ readonly data: Record<string, unknown>;
92
+ }
93
+
94
+ export interface EmitInjectedEventOptions {
95
+ kind: EventMonkeyKind;
96
+ /** 기존 런에 덧붙일 때. 없으면 정규 run-<uuid> 를 새로 민다. */
97
+ runId?: string;
98
+ /** same-cell-reuse-push 전용 — 없으면 두 변형 모두. */
99
+ variant?: EventMonkeyVariant;
100
+ /** 쓸 우주 뿌리. 없으면 effectiveInstanceRoot(). */
101
+ stateRoot?: string;
102
+ injectionId?: string;
103
+ now?: () => Date;
104
+ }
105
+
106
+ export interface EmitInjectedEventResult {
107
+ readonly kind: EventMonkeyKind;
108
+ readonly level: typeof EVENT_MONKEY_LEVEL;
109
+ readonly injectionId: string;
110
+ readonly runId: string;
111
+ readonly stateRoot: string;
112
+ readonly ledgerPath: string;
113
+ readonly ledgerRows: readonly RunLedgerEntry[];
114
+ readonly debugRows: readonly EventMonkeyDebugRow[];
115
+ readonly consumers: readonly string[];
116
+ }
117
+
118
+ export class EventMonkeyRefusedError extends Error {
119
+ constructor(readonly stateRoot: string, readonly reason: 'production-root' | 'ops-root') {
120
+ super(`event monkey refuses to write into a production root (${reason}): ${stateRoot} — set ELANOUS_STATE_DIR (or --state-dir) to an isolated test dir`);
121
+ this.name = 'EventMonkeyRefusedError';
122
+ }
123
+ }
124
+
125
+ /** 이 장치가 실제로 쓰는 자리 — 뿌리 ⊕ 원장 디렉터리·파일 ⊕ logs 디렉터리·logs.db(⊕ WAL·SHM). */
126
+ export function eventMonkeyWriteTargets(root: string, runId?: string): string[] {
127
+ const logs = join(root, 'logs');
128
+ const db = join(logs, 'logs.db');
129
+ return [root, runLedgerDir(root), ...(runId ? [runLedgerPath(runId, runLedgerDir(root))] : []), logs, db, `${db}-wal`, `${db}-shm`];
130
+ }
131
+
132
+ function insideOrEqual(parent: string, target: string): boolean {
133
+ const rel = relative(parent, target);
134
+ return rel === '' || (rel !== '..' && !rel.startsWith(`..${sep}`) && !isAbsolute(rel));
135
+ }
136
+
137
+ /**
138
+ * 운영 뿌리면 던진다 — 쓰기 «전»에 부른다.
139
+ * ⛔ 뿌리 «이름»만 보지 않는다: 격리 뿌리 안의 `run-ledger`·`logs` 가 운영으로 가는 symlink 면
140
+ * 이름 검사를 통과한 뒤 운영에 쓴다. 그래서 실제 쓰기 대상마다 «물리 경로»를 운영 뿌리·ops 뿌리와 대조한다.
141
+ */
142
+ export function assertIsolatedEventRoot(root: string, runId?: string): string {
143
+ const normalized = normRoot(root);
144
+ const prod = prodInstanceRoot();
145
+ const prodPhysical = physicalPath(prod);
146
+ // ⛔ 디렉터리에서 멈추지 않는다 — 원장 «파일»·logs.db «파일» 자체가 symlink 여도 물리 경로로 잡는다.
147
+ for (const target of eventMonkeyWriteTargets(normalized, runId)) {
148
+ const physical = physicalPath(target);
149
+ if (insideOrEqual(prod, target) || insideOrEqual(prodPhysical, physical)) throw new EventMonkeyRefusedError(normalized, 'production-root');
150
+ if (isInsideOpsRoot(target) || isInsideOpsRoot(physical)) throw new EventMonkeyRefusedError(normalized, 'ops-root');
151
+ }
152
+ return normalized;
153
+ }
154
+
155
+ /** 짧은 별칭 — 사람이 치기 쉽게. 정식 이름도 그대로 받는다. */
156
+ export const EVENT_MONKEY_ALIASES: Readonly<Record<string, EventMonkeyKind>> = {
157
+ 'child-error': 'child-error-long',
158
+ 'same-cell': 'same-cell-reuse-push',
159
+ 'scope-escape': 'scope-escape-held',
160
+ 'no-result': 'no-result-line',
161
+ 'pr-null': 'pr-terminal-null',
162
+ 'slot-wait': 'land-slot-wait',
163
+ };
164
+
165
+ export function resolveEventMonkeyKind(name: string): EventMonkeyKind | undefined {
166
+ return isEventMonkeyKind(name) ? name : EVENT_MONKEY_ALIASES[name];
167
+ }
168
+
169
+ /**
170
+ * 기본 우주 = test. 명시(--test/--config-dir/ELANOUS_STATE_DIR)가 있으면 그것을 쓰고(운영이면 거부된다),
171
+ * 없으면 `--test` 와 같은 `<트리>/.elanous-test`. 트리도 없으면 운영 뿌리를 돌려 거부되게 둔다(조용히 다른 곳에 쓰지 않는다).
172
+ */
173
+ export function resolveEventMonkeyRoot(cwd: string = process.cwd()): string {
174
+ const effective = effectiveInstanceRoot();
175
+ const explicit = Boolean(getElanousConfigDirOverride() || process.env.ELANOUS_STATE_DIR?.trim());
176
+ if (explicit || effective !== prodInstanceRoot()) return effective;
177
+ return resolveTestRoot(cwd) ?? effective;
178
+ }
179
+
180
+ function isEventMonkeyKind(value: string): value is EventMonkeyKind {
181
+ return (EVENT_MONKEY_KINDS as readonly string[]).includes(value);
182
+ }
183
+ export { isEventMonkeyKind };
184
+
185
+ const LONG_ERROR_LINE = 'error: bun test src/self-implement/orchestrator.test.ts exited 1 — expect(received).toEqual(expected) at orchestrator.test.ts:4210:7 (injected L0 long child error)';
186
+
187
+ /** 실제 자식 실패처럼 «한 줄 요약 + 긴 스택» 꼴의 ≈4KB 문면. 정형기가 4,000자로 자른다. */
188
+ function longChildError(): string {
189
+ const lines: string[] = [LONG_ERROR_LINE];
190
+ for (let i = 0; lines.join('\n').length < 4_400; i++) {
191
+ lines.push(` at runGate (src/self-implement/gate.ts:${100 + i}:${(i * 7) % 80}) — frame ${i}`);
192
+ }
193
+ return lines.join('\n');
194
+ }
195
+
196
+ /** 원장 쓰기만 담당하는 묶음 — 줄마다 주입 꼬리표를 붙여 «같은» 쓰기 함수로 쓴다. */
197
+ function makeWriter(runId: string, dir: string, tag: Record<string, unknown>, now: () => Date) {
198
+ const rows: RunLedgerEntry[] = [];
199
+ return {
200
+ rows,
201
+ write(event: string, data: Record<string, unknown>): void {
202
+ const entry: RunLedgerEntry = { timestamp: now().toISOString(), runId, event, data: { ...data, ...tag } };
203
+ appendRunLedgerEntry(entry, dir);
204
+ rows.push(entry);
205
+ },
206
+ };
207
+ }
208
+
209
+ export function emitInjectedEvent(options: EmitInjectedEventOptions): EmitInjectedEventResult {
210
+ const { kind } = options;
211
+ if (!isEventMonkeyKind(kind)) throw new Error(`unknown event monkey kind: ${String(kind)}`);
212
+ // ⛔ 거부·검증은 «쓰기 전» — 운영 뿌리면 0줄.
213
+ const runId = options.runId ?? `run-${randomUUID()}`;
214
+ const requestedRoot = resolve(options.stateRoot ?? resolveEventMonkeyRoot());
215
+ const ledgerPath = runLedgerPath(runId, runLedgerDir(requestedRoot)); // 정규화 계약 밖 runId 는 여기서 던진다(쓰기 전).
216
+ const stateRoot = assertIsolatedEventRoot(requestedRoot, runId);
217
+ const dir = runLedgerDir(stateRoot);
218
+ const injectionId = options.injectionId ?? `inj-${randomUUID()}`;
219
+ const tag = { injected: true, injectionId, level: EVENT_MONKEY_LEVEL } as const;
220
+ const now = options.now ?? (() => new Date());
221
+ const debugRows: EventMonkeyDebugRow[] = [];
222
+ const emit = (category: string, event: string, data: Record<string, unknown>): void => {
223
+ debugRows.push({ category, event, data: { ...data, ...tag, runId } });
224
+ };
225
+ const ledger = makeWriter(runId, dir, tag, now);
226
+
227
+ const short = injectionId.slice(4, 12);
228
+ const job = `si-sim-${short}`;
229
+ const childRunId = `run-${randomUUID()}`;
230
+ const branch = `elanous/self-dev/sim-event-monkey-goalid-${short}`;
231
+ const podChildRun = (): void => ledger.write('pod-child-run', { childRunId, job, attempt: 1 });
232
+ const childEvidence = (result: Record<string, unknown> | null): void => {
233
+ ledger.write('pod-child-evidence', { childEvidence: result ? podChildEvidenceFromResult(result) ?? null : null, childRunId, job });
234
+ };
235
+
236
+ switch (kind) {
237
+ case 'child-error-long': {
238
+ const error = longChildError();
239
+ podChildRun();
240
+ childEvidence({ ok: false, error, exitCode: 1, failureClassification: 'child-error' });
241
+ emit('self-implement.pod', 'child-error', { job, stage: 'implement', error: error.slice(0, 500) });
242
+ emit('self-implement.pod', 'job-finished', { job, state: 'failed', containerReason: 'Error', stage: null, prUrl: null, childRunId, childStage: 'implement', childError: error.slice(0, 500) });
243
+ break;
244
+ }
245
+ case 'same-cell-reuse-push': {
246
+ const variants: EventMonkeyVariant[] = options.variant ? [options.variant] : ['allowed', 'refused'];
247
+ const headSha = 'a'.repeat(40);
248
+ const cardId = `card-sim-${short}`;
249
+ const pushEvidence = { ref: `refs/heads/${branch}`, remoteHead: headSha, cardId };
250
+ for (const variant of variants) {
251
+ if (variant === 'allowed') {
252
+ ledger.write('same-cell-push-decision', { ...pushEvidence, outcome: 'allowed', reason: 'bound-card-pr-head-fast-forward' });
253
+ emit('autopilot.pr-manager', 'same-cell-push-decision', { ...pushEvidence, outcome: 'allowed', reason: 'bound-card-pr-head-fast-forward' });
254
+ emit('autopilot.pr-manager', 'same-cell-reused', { pr: 99_999_999, cellId: 'SIM-EVENT-MONKEY', cardId, branch });
255
+ } else {
256
+ const reason = 'candidate identity mismatch';
257
+ ledger.write('same-cell-push-decision', { ...pushEvidence, outcome: 'refused', reason });
258
+ emit('autopilot.pr-manager', 'same-cell-push-decision', { ...pushEvidence, outcome: 'refused', reason });
259
+ podChildRun();
260
+ childEvidence({ ok: false, exitCode: 1, error: `PR guard 실패: same-cell reuse: ${reason} blockingPr=#99999999:${cardId} candidateCardId=card-sim-other` });
261
+ }
262
+ }
263
+ break;
264
+ }
265
+ case 'scope-escape-held': {
266
+ const outOfScopeEdits = ['src/index.ts', 'src/cli/tasks-cli.ts', 'docs/_index.md'];
267
+ ledger.write('execution-scope-held', { outOfScopeEdits, nameCapReached: false, outsideCount: outOfScopeEdits.length,
268
+ worktreePath: `/tmp/elanous-sim/${job}`, branch, disposition: 'in-scope-only' });
269
+ podChildRun();
270
+ childEvidence({ ok: false, exitCode: 1, outOfScopeEdits, detail: 'Out-of-scope edits held in the worktree; gate and publication skipped.' });
271
+ emit('self-implement.pod', 'child-error', { job, stage: 'soft-stopped', error: 'Out-of-scope edits held in the worktree' });
272
+ break;
273
+ }
274
+ case 'no-result-line': {
275
+ podChildRun();
276
+ childEvidence(null);
277
+ ledger.write('pod-ledger-incomplete', { job, reason: 'child-ledger-missing' });
278
+ ledger.write('pr-terminal', { ...classifyPodTerminal({ childRunId, state: 'failed', disposition: undefined, at: now().toISOString() }) });
279
+ emit('self-implement.pod', 'job-finished', { job, state: 'failed', containerReason: 'Error', stage: null, prUrl: null, childRunId, childError: 'no-result-line' });
280
+ break;
281
+ }
282
+ case 'pr-terminal-null': {
283
+ podChildRun();
284
+ ledger.write('pr-opened', { number: 99_999_999, url: 'https://github.com/elanous-sim/event-monkey/pull/99999999', branch, draft: true });
285
+ childEvidence({ ok: false, exitCode: 1, error: 'review loop exhausted after draft open (injected L0)' });
286
+ ledger.write('pr-terminal', { ...classifyPodTerminal({ childRunId, state: 'failed',
287
+ disposition: { prNumber: null, prUrl: null, stage: 'review-failed', ok: false, branch }, at: now().toISOString() }) });
288
+ emit('self-implement.pod', 'pr-terminal-branch-lookup', { branch, status: 'not-found', reason: 'injected-no-lookup', job });
289
+ break;
290
+ }
291
+ case 'land-slot-wait': {
292
+ const data = { host: 'node-b', occupied: 2, slotWaitSeconds: 600 };
293
+ ledger.write('land-slot-wait', { ...data, waitedSeconds: 600, pr: 99_999_999 });
294
+ emit('pr.land', 'host-busy', data);
295
+ break;
296
+ }
297
+ }
298
+
299
+ // 관측 줄 — 격리 우주 logs.db 하나로만(전역 싱크 0). 경로는 위 assertIsolatedEventRoot 가 이미 물리 대조했다.
300
+ const store = new LogStore(join(stateRoot, 'logs', 'logs.db'));
301
+ try {
302
+ store.insertBatch(debugRows.map((row) => ({ rec: { ts: now().toISOString(), category: row.category, event: row.event, data: row.data, level: 'info' as const }, surface: 'ux-sim' })));
303
+ } finally { store.close(); }
304
+
305
+ return {
306
+ kind, level: EVENT_MONKEY_LEVEL, injectionId, runId, stateRoot, ledgerPath,
307
+ ledgerRows: ledger.rows, debugRows, consumers: EVENT_MONKEY_CATALOG[kind].consumers,
308
+ };
309
+ }
310
+
311
+ /** 사람용 한 줄 — 주입 id · 쓴 원장 경로 · 읽어야 할 소비자. */
312
+ export function renderInjectedEventLine(result: EmitInjectedEventResult): string {
313
+ return `주입 ${result.injectionId} · ${result.kind} · 원장 ${result.ledgerPath} · 소비자: ${result.consumers.join(' · ')}`;
314
+ }
315
+
316
+ /** JSON 출력 꼴(CLI 공용). */
317
+ export function injectedEventJson(result: EmitInjectedEventResult): Record<string, unknown> {
318
+ return {
319
+ ok: true, level: result.level, kind: result.kind, injectionId: result.injectionId, runId: result.runId,
320
+ stateRoot: result.stateRoot, ledgerPath: result.ledgerPath,
321
+ ledgerEvents: result.ledgerRows.map((row) => row.event),
322
+ debugEvents: result.debugRows.map((row) => `${row.category} ${row.event}`),
323
+ consumers: result.consumers,
324
+ };
325
+ }
326
+
327
+ export interface EventMonkeyCliInput {
328
+ kindName: string | undefined;
329
+ runId?: string;
330
+ variant?: string;
331
+ /** 명시 우주(없으면 resolveEventMonkeyRoot). */
332
+ stateDir?: string;
333
+ json?: boolean;
334
+ }
335
+
336
+ export interface EventMonkeyCliOutcome {
337
+ /** 0 성공 · 1 기타 오류 · 2 사용법 · 3 운영 뿌리 거부. */
338
+ code: 0 | 1 | 2 | 3;
339
+ stdout: string[];
340
+ stderr: string[];
341
+ }
342
+
343
+ /** `eln sim emit` · `scripts/ux-sim.ts emit` 공용 — 인자 해석 뒤 «같은» 함수 하나. 출력은 돌려주기만 한다. */
344
+ export function runEventMonkeyCli(input: EventMonkeyCliInput): EventMonkeyCliOutcome {
345
+ const kind = input.kindName ? resolveEventMonkeyKind(input.kindName) : undefined;
346
+ if (!kind) {
347
+ const known = [...EVENT_MONKEY_KINDS, ...Object.keys(EVENT_MONKEY_ALIASES)].join(' · ');
348
+ return { code: 2, stdout: [], stderr: [`⛔ 모르는 사건이다: ${input.kindName ?? '(없음)'} — 아는 것: ${known}`] };
349
+ }
350
+ if (input.variant !== undefined && (kind !== 'same-cell-reuse-push' || (input.variant !== 'allowed' && input.variant !== 'refused'))) {
351
+ return { code: 2, stdout: [], stderr: ['⛔ --variant 는 same-cell-reuse-push 에만 · allowed|refused'] };
352
+ }
353
+ try {
354
+ const result = emitInjectedEvent({
355
+ kind, stateRoot: input.stateDir ? resolve(input.stateDir) : resolveEventMonkeyRoot(),
356
+ ...(input.runId ? { runId: input.runId } : {}),
357
+ ...(input.variant ? { variant: input.variant as EventMonkeyVariant } : {}),
358
+ });
359
+ return { code: 0, stdout: [input.json ? JSON.stringify(injectedEventJson(result)) : renderInjectedEventLine(result)], stderr: [] };
360
+ } catch (error) {
361
+ if (error instanceof EventMonkeyRefusedError) {
362
+ return input.json
363
+ ? { code: 3, stdout: [JSON.stringify({ ok: false, error: error.reason === 'ops-root' ? 'refused-ops-root' : 'refused-production-root', reason: error.reason, stateRoot: error.stateRoot })], stderr: [] }
364
+ : { code: 3, stdout: [], stderr: [`⛔ ${error.message}`] };
365
+ }
366
+ return { code: 1, stdout: [], stderr: [`⛔ ${error instanceof Error ? error.message : String(error)}`] };
367
+ }
368
+ }
369
+
370
+ /** `eln sim kinds` · `emit --list` 공용 출력. */
371
+ export function renderEventMonkeyKinds(json = false): string[] {
372
+ if (json) return [JSON.stringify(EVENT_MONKEY_CATALOG, null, 2)];
373
+ const alias = (kind: EventMonkeyKind): string => Object.entries(EVENT_MONKEY_ALIASES).find(([, k]) => k === kind)?.[0] ?? '-';
374
+ return EVENT_MONKEY_KINDS.map((kind) => {
375
+ const entry = EVENT_MONKEY_CATALOG[kind];
376
+ return `${kind} (${alias(kind)})\t${entry.summary}\n 원장: ${entry.ledgerEvents.join(' · ')}\n 소비자: ${entry.consumers.join(' · ')}`;
377
+ });
378
+ }
@@ -15,15 +15,28 @@
15
15
  // tests that run where the tool exists.
16
16
  import { chmodSync, existsSync, mkdirSync, mkdtempSync, readFileSync, rmSync, writeFileSync } from 'node:fs';
17
17
  import { tmpdir } from 'node:os';
18
- import { delimiter, join } from 'node:path';
18
+ import { delimiter, isAbsolute, join } from 'node:path';
19
19
 
20
20
  export interface FakeBinSpec {
21
21
  readonly stdout?: string;
22
22
  readonly stderr?: string;
23
23
  /** Exit code (default 0). */
24
24
  readonly exitCode?: number;
25
- /** Stay alive this long before exiting — for long-running daemons a test kills. */
25
+ /** Stay alive this long before exiting — for long-running daemons a test kills, or a fractional
26
+ * per-call latency (e.g. 0.2) for a test that measures fan-out. */
26
27
  readonly sleepSeconds?: number;
28
+ /**
29
+ * Fake only the calls whose argv starts with these words (e.g. `['worktree', 'add']`);
30
+ * every other call `exec`s `otherwise` with the same argv. Needs `otherwise`.
31
+ */
32
+ readonly whenArgsStartWith?: readonly string[];
33
+ /** Absolute path of the real executable that serves the calls `whenArgsStartWith` does not match. */
34
+ readonly otherwise?: string;
35
+ /**
36
+ * After stdout/stderr (and any sleep), the fake kills itself with this signal instead of exiting —
37
+ * a «died without a word» failure (`status` null · `signal` set). `exitCode` is then never reached.
38
+ */
39
+ readonly killSignal?: 'KILL' | 'TERM' | 'INT' | 'HUP' | 'ABRT' | 'SEGV';
27
40
  }
28
41
 
29
42
  export interface FakeBinCall {
@@ -48,6 +61,7 @@ export interface FakeBins {
48
61
  }
49
62
 
50
63
  const NAME = /^[A-Za-z0-9._+-]+$/;
64
+ const KILL_SIGNALS: ReadonlySet<string> = new Set(['KILL', 'TERM', 'INT', 'HUP', 'ABRT', 'SEGV']);
51
65
 
52
66
  function shellQuote(value: string): string {
53
67
  return `'${value.replace(/'/g, `'\\''`)}'`;
@@ -57,25 +71,37 @@ function script(name: string, spec: FakeBinSpec, dataDir: string, logPath: strin
57
71
  const lines = ['#!/bin/sh'];
58
72
  // One record per call: name and each argv entry NUL-terminated (one printf), then an ASCII record
59
73
  // separator \x1e (a second printf). `calls()` drops the unterminated tail, so a reader never sees half a record.
60
- lines.push(`{ printf '%s\\0' ${shellQuote(name)} "$@"; printf '\\036'; } >> ${shellQuote(logPath)}`);
74
+ // The record is staged in its own file and appended by one `cat` (one write), so concurrent calls never interleave.
75
+ // The fake PATH may itself contain mktemp, cat, or rm. Use the shell's default utility path
76
+ // for recorder and payload reads so a fake of one of those names cannot recursively call itself.
77
+ lines.push(`rec=$(command -p mktemp ${shellQuote(join(dataDir, 'rec.XXXXXX'))})`);
78
+ lines.push(`{ printf '%s\\0' ${shellQuote(name)} "$@"; printf '\\036'; } > "$rec"; command -p cat "$rec" >> ${shellQuote(logPath)}; command -p rm -f "$rec"`);
79
+ if (spec.whenArgsStartWith !== undefined && spec.otherwise !== undefined) {
80
+ const words = spec.whenArgsStartWith;
81
+ const tests = [`[ "$#" -ge ${words.length} ]`, ...words.map((word, index) => `[ "$${index + 1}" = ${shellQuote(word)} ]`)];
82
+ lines.push(`if ${tests.join(' && ')}; then :; else exec ${shellQuote(spec.otherwise)} "$@"; fi`);
83
+ }
61
84
  if (spec.stdout !== undefined) {
62
85
  const file = join(dataDir, `${name}.stdout`);
63
86
  writeFileSync(file, spec.stdout);
64
- lines.push(`cat ${shellQuote(file)}`);
87
+ lines.push(`command -p cat ${shellQuote(file)}`);
65
88
  }
66
89
  if (spec.stderr !== undefined) {
67
90
  const file = join(dataDir, `${name}.stderr`);
68
91
  writeFileSync(file, spec.stderr);
69
- lines.push(`cat ${shellQuote(file)} >&2`);
92
+ lines.push(`command -p cat ${shellQuote(file)} >&2`);
70
93
  }
71
94
  const exitCode = spec.exitCode ?? 0;
72
95
  if (spec.sleepSeconds !== undefined && spec.sleepSeconds > 0) {
73
- const seconds = Math.ceil(spec.sleepSeconds);
96
+ // Whole seconds stay as they were; a fraction keeps millisecond precision (`sleep 0.2` — BSD · GNU · busybox).
97
+ const seconds = Number.isInteger(spec.sleepSeconds) ? spec.sleepSeconds : Math.ceil(spec.sleepSeconds * 1000) / 1000;
74
98
  // exit 0: `exec` so killing the fake kills the sleep itself. Any other code needs the shell to
75
99
  // outlive the sleep; a fake killed mid-sleep then leaves `sleep` until `sleepSeconds` ends.
76
- if (exitCode === 0) lines.push(`exec sleep ${seconds}`);
100
+ // killSignal must outlive the sleep too, or `exec` would replace the shell before the kill line.
101
+ if (exitCode === 0 && spec.killSignal === undefined) lines.push(`exec sleep ${seconds}`);
77
102
  else lines.push(`sleep ${seconds}`);
78
103
  }
104
+ if (spec.killSignal !== undefined) lines.push(`kill -s ${spec.killSignal} $$`);
79
105
  lines.push(`exit ${exitCode}`);
80
106
  return `${lines.join('\n')}\n`;
81
107
  }
@@ -83,6 +109,15 @@ function script(name: string, spec: FakeBinSpec, dataDir: string, logPath: strin
83
109
  export function createFakeBins(specs: Readonly<Record<string, FakeBinSpec>>): FakeBins {
84
110
  for (const name of Object.keys(specs)) {
85
111
  if (!NAME.test(name) || name === '.' || name === '..') throw new Error(`fake-bin: invalid executable name ${JSON.stringify(name)}`);
112
+ const spec = specs[name]!;
113
+ if (spec.killSignal !== undefined && !KILL_SIGNALS.has(spec.killSignal)) throw new Error(`fake-bin: ${name}: killSignal must be one of ${[...KILL_SIGNALS].join(', ')}`);
114
+ if (spec.whenArgsStartWith !== undefined) {
115
+ if (spec.whenArgsStartWith.length === 0) throw new Error(`fake-bin: ${name}: whenArgsStartWith needs at least one word`);
116
+ if (spec.otherwise === undefined) throw new Error(`fake-bin: ${name}: whenArgsStartWith needs otherwise (the real executable)`);
117
+ if (!isAbsolute(spec.otherwise)) throw new Error(`fake-bin: ${name}: otherwise must be an absolute path, got ${JSON.stringify(spec.otherwise)}`);
118
+ } else if (spec.otherwise !== undefined) {
119
+ throw new Error(`fake-bin: ${name}: otherwise is only used with whenArgsStartWith`);
120
+ }
86
121
  }
87
122
  const root = mkdtempSync(join(tmpdir(), 'ux-sim-fake-bin-'));
88
123
  const dir = join(root, 'bin');