elanous 0.2.29 → 0.2.32

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 (775) 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/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{058a98ba.7eb28d5e6dc03565.js → 0bb0ff36.b8d418980951e5ba.js} +7 -7
  5. package/apps/pwa/out/_next/static/chunks/1034-8b639cee57b8e4a8.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/1085-6c2d35526f11f840.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1220.1ff7d5cdc34b1ae5.js +27 -0
  8. package/apps/pwa/out/_next/static/chunks/1247.5884ec81b39fe2e7.js +287 -0
  9. package/apps/pwa/out/_next/static/chunks/1302.87681521a7a4661e.js +62 -0
  10. package/apps/pwa/out/_next/static/chunks/1324-59dae3002413623b.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/{6013-2f769370d8b4c2c6.js → 1335-6731f392c35216eb.js} +3 -3
  12. package/apps/pwa/out/_next/static/chunks/1343-f40b5870ac1eda5a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/146-b6cd56be11dda017.js +1 -0
  14. package/apps/pwa/out/_next/static/chunks/{8332.6f0f49df772e163b.js → 1654.32de4b324981a188.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/1834-98b64172bc1efe77.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/1849.1ce38efa6c527d9a.js +149 -0
  17. package/apps/pwa/out/_next/static/chunks/{8795.32573a185af18c7b.js → 1913.7cc6fb6055b1ed3f.js} +2 -2
  18. package/apps/pwa/out/_next/static/chunks/{419.736c0d6f426249a7.js → 2001.6c7e0fd02190886c.js} +1 -1
  19. package/apps/pwa/out/_next/static/chunks/2030.41fae98c7e907304.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2099-08b2f2dfba742c9b.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2112-e4efc21a6505d5bc.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2134.ecee03a550ee7250.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6767.1fcfc9b8be83975f.js → 2213.2ccbada92c33ea0f.js} +16 -16
  24. package/apps/pwa/out/_next/static/chunks/2236.66061832181cb745.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2422.b0bd272e7020d7e6.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/2534.e85ae21ad0dac829.js +1 -0
  27. package/apps/pwa/out/_next/static/chunks/{4759.1f76713aefb87db5.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/{6776.06ff1e3b464cc607.js → 2898.fd781bc7cf01a7b7.js} +1 -1
  29. package/apps/pwa/out/_next/static/chunks/{1782-59db1b5aa06df38a.js → 2940-619bfd8ef337c611.js} +1 -1
  30. package/apps/pwa/out/_next/static/chunks/{8471.8d2a8c74f09c36ff.js → 2985.39ccdecd36848b12.js} +4 -4
  31. package/apps/pwa/out/_next/static/chunks/3040.92ff9ffc9f971cb9.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/3144.6861096c7b4edef7.js +64 -0
  33. package/apps/pwa/out/_next/static/chunks/{bc324b7c.02a09dd93f6a399b.js → 3267c0e6.d34854e7b3984a6e.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3278.2e5d15b53a4091c8.js +2 -0
  35. package/apps/pwa/out/_next/static/chunks/{7725-4f83d5541fbdb81b.js → 3541-ce3a5424ed5ad7f1.js} +1 -1
  36. package/apps/pwa/out/_next/static/chunks/3583.a05e88cc8d594628.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3771.e928edf2867d28c0.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3902.e1e71aaac850a045.js +34 -0
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{46bd8bea.2f4b4099172fcdb7.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/4111.2bfedbb233ad206b.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/{1142.65d002789ab3af7d.js → 4174.92ed04922709ac9e.js} +2 -2
  43. package/apps/pwa/out/_next/static/chunks/4300-c7ec4eeabbb5f3f7.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/4483.646d5065199e1b55.js +36 -0
  45. package/apps/pwa/out/_next/static/chunks/4519.28199ff26b2fd80d.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/4581.ef2443578054544f.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4608-8d894e9cbe4f08bf.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/4639.ae48a01d1bb50a93.js +286 -0
  49. package/apps/pwa/out/_next/static/chunks/4739.08742ac668aada67.js +77 -0
  50. package/apps/pwa/out/_next/static/chunks/4745.67d6f99c245af3f7.js +226 -0
  51. package/apps/pwa/out/_next/static/chunks/4882-16cef71d6a1a32be.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4999.c064a4000c2a9e94.js +79 -0
  53. package/apps/pwa/out/_next/static/chunks/5173-233188df2f42c626.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/5260-69f35419bca263e7.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/5272.b92d1b72a15c25fe.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/5304.04d24756f242a094.js +148 -0
  57. package/apps/pwa/out/_next/static/chunks/5307.60f2209e809bd627.js +1 -0
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{3396-97b97928c49190c9.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{3403.7199205e65124486.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{9143.ff14585db1d275ff.js → 5543.a438b8ab5a13ea47.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5572-42c9084f27ca761e.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5661-80470aac963d9f36.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5723.421338408b5c30c4.js +74 -0
  65. package/apps/pwa/out/_next/static/chunks/5809.64c3664267c50bce.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/6000.64bc21ac8627f2f5.js +94 -0
  67. package/apps/pwa/out/_next/static/chunks/6013.39459b9c68eabf5f.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/607-06466dff012b03ef.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{8398.73a19b39715eda04.js → 6092.a7f99e68b188ca66.js} +1 -1
  70. package/apps/pwa/out/_next/static/chunks/60fb96c9.360b01d8d4927b7b.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/{5591.a35e7a217734a8b9.js → 6157.0c9af021de4fb31b.js} +2 -2
  72. package/apps/pwa/out/_next/static/chunks/6192.a190b989b81e9743.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/6323.8672b4817a306928.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{7375.050ea0d72968e49f.js → 6433.fc573af22bbc9ab7.js} +17 -17
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6517.4147878ac06d584d.js +90 -0
  77. package/apps/pwa/out/_next/static/chunks/6532.e34302010b2f0b68.js +32 -0
  78. package/apps/pwa/out/_next/static/chunks/6544cb48.a87fe20ddf137be2.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6546.74bc4ed82f19016d.js +104 -0
  80. package/apps/pwa/out/_next/static/chunks/6684-e7523ce7c2fad075.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6726.ebdc82feb161431e.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6739.00fb6f892e5e392b.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6745.934c4921bf15513a.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6767.ea607cf0c20a25af.js +24 -0
  85. package/apps/pwa/out/_next/static/chunks/6843.67bfd020da0926c5.js +93 -0
  86. package/apps/pwa/out/_next/static/chunks/69-0a2c8209c6d4a158.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/6948.1062d4594652b5bf.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  94. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  95. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8097-9530c03bcc550f02.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  110. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  116. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  118. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-504204b58c82c253.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-a9717a67c2eecbaf.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-5c9ec30aee62dfbf.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/page-584191533721fa16.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-73c4b4bb3ac7ab5f.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-c0f1ca371f710b06.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-46430d45a9e04eac.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-3b2ebf1dc64ff0be.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-a27b1e5a0d1b308f.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-25654b82094f7d22.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-8ea49a4c6dd2c6e7.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-ce5113aefea0a8d1.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-0e5a41fac1c75396.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-31aaf1ed37c6df9a.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-3dcc1fa411e1f4e0.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-c69247e7134d329d.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-66dc5cd3a0999abe.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/page-26ff7ff651a7217d.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-617b3976981efa96.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-d256f5d5d9552823.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-ce8f1907b8a6101c.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-33e182a316263116.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/page-32866485913d6a04.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-7607cca9b84950c6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eeab86176b03dc3b.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-5b93dbae3432b996.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-77a6cb90a9cf2b10.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-f47e768b5b242b5a.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-eb41aa3367fc2505.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-4d13ab0b8a267e3f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-84dad32ff0fc0831.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-95306f892aa2d0ee.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-940fb6c217f6b470.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-8c66a3b24a745630.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-7b675dfd35c36fc9.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-8bd0d3cf7665bcfc.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-c219f2ed171131be.js} +1 -1
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-40f8fa21bdae955b.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-468f8313e4f1fbd9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-7bbb8fa353a246c4.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/page-04d00ae9b0890349.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-4214b855d9233ea8.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-936752c7aa58762e.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-ec052ad359df1797.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-8305570551091338.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-fad650e4793adb65.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/page-d90e64743826e1d8.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-a16bcfd49af86a32.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  184. package/apps/pwa/out/_next/static/css/b5d88eba78a3d7bf.css +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +26 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/bin/elanous.mjs +7 -3
  279. package/graphs/context/nightly-condense.yaml +1 -0
  280. package/graphs/implement-loop.yaml +5 -0
  281. package/graphs/intake/intake-daily.yaml +8 -1
  282. package/graphs/intake/recipes.yaml +5 -0
  283. package/graphs/lecture/lecture-note.yaml +2 -2
  284. package/graphs/ops/harness-gc.yaml +1 -0
  285. package/graphs/release/recipes.yaml +3 -0
  286. package/graphs/release/release-loop.yaml +9 -5
  287. package/graphs/units/recipes.yaml +3 -0
  288. package/graphs/units/release-gate-recheck.yaml +15 -0
  289. package/package.json +2 -1
  290. package/scripts/check-native-tool-wiring.ts +3 -2
  291. package/scripts/ci-android-unit-tests.ts +16 -0
  292. package/scripts/ci-typecheck-changed.ts +63 -10
  293. package/scripts/coord-channel-watch.sh +22 -16
  294. package/scripts/coord-role-pack.ts +81 -2
  295. package/scripts/cron-run.ts +96 -3
  296. package/scripts/detect-test-interference.ts +38 -5
  297. package/scripts/gate-pr-cache.ts +65 -0
  298. package/scripts/gh-surface/capture.ts +126 -0
  299. package/scripts/gh-surface/gh +40 -0
  300. package/scripts/import-graph-scc.ts +38 -0
  301. package/scripts/install.ps1 +19 -0
  302. package/scripts/intake-social.ts +181 -0
  303. package/scripts/lecture-note/node.ts +71 -4
  304. package/scripts/lib/android-toolchain.ts +32 -0
  305. package/scripts/lib/deterministic-env.ts +62 -0
  306. package/scripts/lib/gate-test-env.ts +19 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/measure-si-task-cpu.ts +143 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +255 -0
  310. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  311. package/scripts/release-loop/cut-branch.ts +4 -3
  312. package/scripts/release-loop/export-check-node.ts +0 -1
  313. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  314. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  315. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  316. package/scripts/release-loop/gate-closure.ts +12 -8
  317. package/scripts/release-loop/gate-diff.ts +1 -1
  318. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  319. package/scripts/release-loop/gate-node.ts +523 -75
  320. package/scripts/release-loop/gate-partial.ts +106 -9
  321. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  322. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  323. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  324. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  325. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  326. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  327. package/scripts/release-loop/import-graph-scc.ts +215 -0
  328. package/scripts/release-loop/node-verdict.ts +2 -0
  329. package/scripts/release-loop/prepare-node.ts +102 -4
  330. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  331. package/scripts/release-loop/resume-release.ts +33 -4
  332. package/scripts/release-loop/resume.ts +13 -5
  333. package/scripts/release-loop/spawn-lane.ts +2 -19
  334. package/scripts/release-loop/tui-sim-node.ts +3 -2
  335. package/scripts/release-loop/unattended-release.ts +16 -0
  336. package/scripts/test-deterministic.ts +5 -61
  337. package/scripts/train-reach-grouping.ts +48 -0
  338. package/scripts/tsc-incremental-cache.ts +86 -0
  339. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  340. package/scripts/tsc-main-safety-net.ts +2 -2
  341. package/src/acp/client.ts +4 -1
  342. package/src/acp/core-turn-bridge.ts +65 -8
  343. package/src/acp/elanous-extensions.ts +3 -0
  344. package/src/acp/server.ts +3 -0
  345. package/src/acp/tool-trace.ts +186 -11
  346. package/src/ad-pipeline/run.ts +4 -2
  347. package/src/agent/runner.ts +169 -3
  348. package/src/agent/self-ambient-cache.ts +156 -0
  349. package/src/agent/self-ambient.ts +8 -1
  350. package/src/agent/subagent-callable.ts +3 -2
  351. package/src/agent/task-notification.ts +5 -0
  352. package/src/agent-mission/review-loop.ts +6 -3
  353. package/src/agent-substrate/acp-implementer.ts +14 -2
  354. package/src/agent-substrate/pr-reviewer.ts +14 -0
  355. package/src/agent-substrate/self-review-cli.ts +30 -4
  356. package/src/ask-user-question/tool.ts +22 -0
  357. package/src/autopilot/build/llm-conflict-merge.ts +56 -10
  358. package/src/autopilot/pr-manager.ts +80 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/capture/frame-state-detect.ts +39 -0
  361. package/src/capture/tui-self-report.ts +149 -6
  362. package/src/chat/chat-cli.ts +10 -2
  363. package/src/chat/index.ts +138 -26
  364. package/src/chat/input-control-key.ts +5 -3
  365. package/src/chat/pickers/modal-runtime.ts +6 -0
  366. package/src/chat/pickers/modals.ts +8 -2
  367. package/src/chat/tool-interrupt-behavior.ts +38 -0
  368. package/src/chat/tool-render/dispatch.ts +5 -1
  369. package/src/chat/turn-typeahead.ts +75 -20
  370. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  371. package/src/cli/agent-cli.ts +41 -13
  372. package/src/cli/ask-bare.ts +1 -0
  373. package/src/cli/config-audit.ts +123 -0
  374. package/src/cli/decisions-cli.ts +80 -6
  375. package/src/cli/import-cli.ts +12 -0
  376. package/src/cli/log-event-names.ts +17 -0
  377. package/src/cli/mcp-login.ts +21 -5
  378. package/src/cli/msg-cli.ts +89 -0
  379. package/src/cli/pod-cli.ts +14 -3
  380. package/src/cli/pr-cli.ts +273 -81
  381. package/src/cli/pr-land-base-read.ts +34 -0
  382. package/src/cli/pr-land-heavy-remote.ts +82 -26
  383. package/src/cli/pr-land-overlap-evidence.ts +109 -11
  384. package/src/cli/pr-land-pod-shadow-job.ts +106 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-refusal.ts +20 -5
  387. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  388. package/src/cli/pty-takeover-cli.ts +88 -14
  389. package/src/cli/release-cli.ts +80 -14
  390. package/src/cli/seat-cli.ts +138 -3
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/sim-cli.ts +18 -0
  393. package/src/cli/tasks-cli.ts +97 -19
  394. package/src/context-bus/context-first.ts +13 -0
  395. package/src/context-bus/context-now.ts +13 -2
  396. package/src/context-bus/ops-events.ts +79 -0
  397. package/src/control-plane/lease-holder.ts +12 -8
  398. package/src/control-plane/ledger.ts +163 -4
  399. package/src/control-plane/server.ts +91 -11
  400. package/src/core-turn/run-core-turn.ts +2 -0
  401. package/src/core-turn/run-goal-loop.ts +243 -3
  402. package/src/core-turn/seat-turn-cap.ts +79 -0
  403. package/src/core-turn/short-question.ts +38 -6
  404. package/src/core-turn/types.ts +6 -0
  405. package/src/dashboard/acp-active-model.ts +42 -1
  406. package/src/dashboard/acp-boot.ts +3 -0
  407. package/src/dashboard/background-jobs-status.ts +66 -0
  408. package/src/dashboard/index.ts +339 -657
  409. package/src/dashboard/input/agent-wake.ts +242 -0
  410. package/src/dashboard/input/chat-main-entry-runtime.ts +6 -1
  411. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  412. package/src/dashboard/input/chat-main-session.ts +8 -1
  413. package/src/dashboard/input/chat-main-turn.ts +12 -3
  414. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  415. package/src/dashboard/input/external-input-host.ts +49 -9
  416. package/src/dashboard/input/internal-turn.ts +261 -0
  417. package/src/dashboard/input/mouse-wiring.ts +108 -11
  418. package/src/dashboard/input/seat-autowake.ts +318 -0
  419. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  420. package/src/dashboard/log-click-runtime.ts +118 -2
  421. package/src/dashboard/loop-scheduler.ts +72 -0
  422. package/src/dashboard/seat-boot-preamble.ts +18 -0
  423. package/src/dashboard/skill-runtime.ts +2 -0
  424. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  425. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  426. package/src/dashboard/slash-runtime/index.ts +13 -0
  427. package/src/dashboard/turn-busy-teardown.ts +50 -0
  428. package/src/dashboard/turn-preamble.ts +116 -40
  429. package/src/dashboard/turn-session-layers.ts +4 -2
  430. package/src/dashboard/turn-start-segments.ts +222 -0
  431. package/src/decisions/decision-ledger.ts +45 -4
  432. package/src/discord-self-message.ts +4 -4
  433. package/src/display/prompt-row-owner.ts +146 -0
  434. package/src/display/resize-listener.ts +33 -2
  435. package/src/domains/release-tool.ts +18 -1
  436. package/src/field-note/transcribe.ts +17 -0
  437. package/src/fold-stack.ts +4 -2
  438. package/src/git-fs/index.ts +263 -36
  439. package/src/github/remote-call.ts +81 -0
  440. package/src/goals/registry.ts +46 -6
  441. package/src/goals/types.ts +7 -1
  442. package/src/graph-runner/runner.ts +1 -0
  443. package/src/grok/credential.ts +26 -0
  444. package/src/harness/gate-reserve.ts +87 -0
  445. package/src/harness/harness-clean.ts +2 -1
  446. package/src/harness/harness-cli-command.ts +52 -5
  447. package/src/harness/harness-gc.ts +2 -1
  448. package/src/harness/harness-incidents.ts +70 -20
  449. package/src/harness/harness-pod-dispatch.ts +87 -10
  450. package/src/harness/harness-queue.ts +68 -4
  451. package/src/harness/harness-stop.ts +4 -3
  452. package/src/harness/harness-substrate-default.ts +78 -7
  453. package/src/harness/harness-worktree-auto.ts +2 -1
  454. package/src/harness/harness-worktrees.ts +3 -2
  455. package/src/hooks/dispatch.ts +2 -1
  456. package/src/index.ts +156 -27
  457. package/src/input/external-input-queue.ts +64 -7
  458. package/src/intake-plane/slash.ts +14 -3
  459. package/src/keybindings.ts +4 -1
  460. package/src/llm/route-decision.ts +36 -0
  461. package/src/llm/tool-loop-steered-rejection.ts +41 -0
  462. package/src/llm-request-shape.ts +209 -0
  463. package/src/llm.ts +301 -283
  464. package/src/loops/consensus.ts +348 -0
  465. package/src/loops/msg-wake.ts +206 -4
  466. package/src/loops/observe.ts +19 -3
  467. package/src/loops/orchestrator/tick.ts +88 -12
  468. package/src/loops/orchestrator/traffic.ts +64 -1
  469. package/src/loops/registry.ts +30 -0
  470. package/src/market/signed-index.ts +14 -0
  471. package/src/maturity/feature-maturity.ts +1 -1
  472. package/src/mcp/mcp-oauth.ts +54 -5
  473. package/src/models/prompts.ts +28 -0
  474. package/src/msg/msg-sse-client.ts +223 -0
  475. package/src/msg/msg-store.ts +86 -2
  476. package/src/mss/logging/log-store.ts +225 -1
  477. package/src/mss/logging/render-categories.ts +5 -0
  478. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  479. package/src/nexus/api/http-server.ts +54 -15
  480. package/src/nexus/api/loop-resources.ts +19 -3
  481. package/src/nexus/api/ops-api.ts +11 -0
  482. package/src/nexus/daemon-thin-inventory.md +37 -0
  483. package/src/nexus/index.ts +70 -0
  484. package/src/nexus/state/state.ts +1 -0
  485. package/src/oauth/store.ts +32 -7
  486. package/src/onboarding/first-run.ts +28 -3
  487. package/src/ops/overview-cache.ts +16 -4
  488. package/src/ops/overview.ts +59 -2
  489. package/src/ops/resources.ts +82 -0
  490. package/src/plugins/maker/connector-maker.ts +41 -0
  491. package/src/plugins/maker/skill-maker.ts +42 -0
  492. package/src/pr-tool/census.ts +303 -0
  493. package/src/pr-tool/inflight-registry.ts +143 -0
  494. package/src/prompt-library/chat-conciseness.ts +13 -0
  495. package/src/prompt-library/universal-preamble.ts +10 -5
  496. package/src/pty-shell/pty-manifest.ts +12 -3
  497. package/src/pty-shell/tui-run-state.ts +34 -3
  498. package/src/release-loop/gate-host-reservation.ts +97 -0
  499. package/src/release-loop/landing-freeze.ts +5 -0
  500. package/src/release-loop/light-rc.ts +5 -2
  501. package/src/release-loop/placement.ts +92 -1
  502. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  503. package/src/release-loop/rehearsal.ts +73 -17
  504. package/src/repl/index.ts +20 -2
  505. package/src/seat-loop/seat-knowhow.ts +282 -0
  506. package/src/seat-loop/seat-loop.ts +41 -2
  507. package/src/seat-loop/traffic-signal.ts +5 -1
  508. package/src/self-dev/ask-launch-flow.ts +37 -3
  509. package/src/self-dev/decompose-compose-graph.ts +28 -27
  510. package/src/self-dev/decompose-proposal.ts +53 -38
  511. package/src/self-dev/decompose.ts +17 -0
  512. package/src/self-dev/dev-pipeline.ts +31 -2
  513. package/src/self-dev/draft-residue.ts +267 -33
  514. package/src/self-dev/draft-sweep.ts +59 -4
  515. package/src/self-dev/external-call-zero.ts +77 -0
  516. package/src/self-dev/launch-preflight-text.ts +6 -0
  517. package/src/self-dev/launch-preflight.ts +25 -3
  518. package/src/self-dev/local-supervisor-judge.ts +185 -0
  519. package/src/self-dev/run-supervisor.ts +229 -19
  520. package/src/self-dev/run-types.ts +20 -0
  521. package/src/self-dev/shard-aggregate.ts +13 -2
  522. package/src/self-dev/shard-plan.ts +56 -1
  523. package/src/self-dev/shard-run.ts +207 -12
  524. package/src/self-dev/spawn-lane-files.ts +19 -0
  525. package/src/self-implement/app-api-budget.ts +51 -11
  526. package/src/self-implement/config-gate.ts +2 -1
  527. package/src/self-implement/elanous-tui-spawn.ts +14 -0
  528. package/src/self-implement/expose-gate.ts +2 -1
  529. package/src/self-implement/follow-up-placement.ts +79 -0
  530. package/src/self-implement/gate-artifacts.ts +416 -0
  531. package/src/self-implement/gate-baseline.ts +96 -5
  532. package/src/self-implement/gate-cli.ts +207 -17
  533. package/src/self-implement/gate-remote.ts +136 -26
  534. package/src/self-implement/gate-scenario.ts +85 -0
  535. package/src/self-implement/goal-author.ts +160 -8
  536. package/src/self-implement/graph-authority.ts +38 -6
  537. package/src/self-implement/graph-overlay-condition.ts +92 -1
  538. package/src/self-implement/heal-triage.ts +79 -0
  539. package/src/self-implement/host-regate.ts +97 -7
  540. package/src/self-implement/orchestrator.ts +115 -134
  541. package/src/self-implement/pr-title.ts +123 -0
  542. package/src/self-implement/run-checkpoint.ts +235 -0
  543. package/src/self-implement/run-ledger.ts +162 -15
  544. package/src/self-implement/run-stop.ts +4 -3
  545. package/src/self-implement/run-ttl.ts +28 -4
  546. package/src/self-implement/seams.ts +2 -0
  547. package/src/self-implement/shadow-stage.ts +7 -6
  548. package/src/self-implement/stop-autoheal.ts +2 -1
  549. package/src/self-implement/train-gate-remote.ts +37 -8
  550. package/src/self-implement/train-reach-grouping.ts +157 -0
  551. package/src/self-implement/train-scenario-layers.ts +133 -0
  552. package/src/self-implement/uncommitted-work.ts +2 -0
  553. package/src/session/pending-input.ts +19 -0
  554. package/src/session/session-start.ts +224 -0
  555. package/src/session-runtime/index.ts +22 -267
  556. package/src/session-runtime/parallel-dispatch.ts +22 -5
  557. package/src/shell-runner/background-surface.ts +15 -5
  558. package/src/skills/tools/agent.ts +39 -6
  559. package/src/skills/tools/dev-harness.ts +6 -4
  560. package/src/skills/tools/list-dir.ts +11 -0
  561. package/src/skills/tools/schedule-wakeup.ts +408 -0
  562. package/src/skills/tools/shell.ts +246 -4
  563. package/src/status/bar.ts +26 -0
  564. package/src/steward/digest-delivery.ts +118 -0
  565. package/src/steward/hold-hygiene.ts +120 -0
  566. package/src/steward/resync-tick.ts +114 -23
  567. package/src/steward/ta-repair-event-collect.ts +158 -0
  568. package/src/steward/triage.ts +10 -0
  569. package/src/surface/shell-runner-boot.ts +5 -2
  570. package/src/task-agent/card-evidence.ts +25 -1
  571. package/src/task-agent/green-sweep.ts +8 -3
  572. package/src/task-agent/judge.ts +76 -0
  573. package/src/task-agent/land-queue.ts +79 -0
  574. package/src/task-agent/live-moves.ts +30 -9
  575. package/src/task-agent/postland-card.ts +5 -0
  576. package/src/task-agent/prelaunch-already-done.ts +98 -0
  577. package/src/task-agent/real-launch-guard.ts +37 -0
  578. package/src/task-agent/rejudge-on-head.ts +89 -12
  579. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  580. package/src/task-agent/repair-cycle.ts +45 -7
  581. package/src/task-agent/repair-worker.ts +7 -0
  582. package/src/task-agent/run-identity.ts +200 -0
  583. package/src/task-agent/shadow.ts +50 -3
  584. package/src/task-agent/task-hand.ts +182 -5
  585. package/src/task-agent/train-landing.ts +77 -0
  586. package/src/task-agent/work-order.ts +104 -0
  587. package/src/task-orchestrator/surfaces/pod-command-job.ts +151 -37
  588. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  589. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  590. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  591. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  592. package/src/task-orchestrator/surfaces/pod-lease.ts +118 -6
  593. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +1 -1
  594. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  595. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  596. package/src/task-orchestrator/surfaces/pod-pool.ts +3 -1
  597. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  598. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +67 -0
  599. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  600. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  601. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  602. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +525 -0
  603. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  604. package/src/task-orchestrator/surfaces/pod-warm-worker-runner.ts +90 -0
  605. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +362 -0
  606. package/src/task-orchestrator/surfaces/self-implement-pod.ts +138 -19
  607. package/src/telegram.ts +2 -4
  608. package/src/tui/chat/execution-badge.ts +5 -1
  609. package/src/tui/input/pickers.ts +732 -0
  610. package/src/tui/input-lag-probe.ts +230 -0
  611. package/src/tui/slash/mission.ts +492 -0
  612. package/src/tui/slash/term.ts +877 -0
  613. package/src/tui-client/dashboard-session.ts +9 -0
  614. package/src/tui.ts +52 -0
  615. package/src/user-config/gemini-server-tools.ts +9 -0
  616. package/src/user-config.ts +53 -16
  617. package/src/util/spawn-sync-output.ts +7 -0
  618. package/src/ux-sim/fake-bin.ts +154 -0
  619. package/src/ux-sim/fake-clock.ts +36 -0
  620. package/src/ux-sim/headless-tui.ts +72 -0
  621. package/src/ux-sim/in-process-cli.ts +2 -1
  622. package/src/ux-sim/scenario.ts +255 -0
  623. package/src/ux-sim/temp-git-remote.ts +82 -0
  624. package/src/version/packed-revision.json +1 -1
  625. package/src/video-pipeline/recipes/vlog.ts +25 -7
  626. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  630. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  632. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  635. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  636. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  639. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  641. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  647. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  651. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  662. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  668. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  671. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  672. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  673. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  676. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  678. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  679. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  680. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  682. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  688. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  695. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  698. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  703. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  705. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/botlab/page-a5635eba0d73b84e.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  742. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  744. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  745. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  748. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  750. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  751. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  752. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-9f92737b8766009a.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  768. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  774. package/apps/pwa/out/_next/static/css/72becfd42807b50d.css +0 -1
  775. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → IVKr3AlRUVLKsw2fh7eXF}/_ssgManifest.js +0 -0
@@ -223,6 +223,8 @@ export interface AdProductionDeps {
223
223
  readonly render?: CommandRunner;
224
224
  /** Optional calibrated thresholds; omitted thresholds intentionally preserve unmeasured QC findings. */
225
225
  readonly qcThresholds?: QcThresholds;
226
+ /** Platform that decides whether on-screen text OCR (macOS Vision via swiftc) is planned; defaults to `process.platform`. */
227
+ readonly qcPlatform?: NodeJS.Platform;
226
228
  }
227
229
 
228
230
  export interface AdOutputIdentity {
@@ -828,7 +830,7 @@ async function runQc(
828
830
  captionedMasterPath?: string,
829
831
  ): Promise<QcResult | undefined> {
830
832
  if (!production?.render || !scene || !masterPath) return undefined;
831
- const { measurements, unavailableTextRegions } = await measureQc(production, buildQcMeasurementPlan(scene, masterPath));
833
+ const { measurements, unavailableTextRegions } = await measureQc(production, buildQcMeasurementPlan(scene, masterPath, production.qcPlatform ?? process.platform));
832
834
  if (unavailableTextRegions !== undefined) {
833
835
  debug.log('ad-pipeline.qc', 'text-regions-unavailable', { reason: unavailableTextRegions });
834
836
  }
@@ -851,7 +853,7 @@ async function runQc(
851
853
  debug.log('ad-pipeline.qc', 'captioned-master-absent', { reason: !captionedMasterPath ? 'captioned-master-unavailable' : 'no-caption-lines' });
852
854
  return baseResult;
853
855
  }
854
- const captionedPlan = buildQcMeasurementPlan(scene, captionedMasterPath, process.platform, {
856
+ const captionedPlan = buildQcMeasurementPlan(scene, captionedMasterPath, production.qcPlatform ?? process.platform, {
855
857
  textFrameAtSeconds: (line.startMs + line.endMs) / 2000,
856
858
  });
857
859
  const captionedMeasurement = await measureQc(production, captionedPlan, (step) => step === 'probe' || step.startsWith('text-'));
@@ -13,6 +13,9 @@
13
13
  // generator terminates instead of hanging.
14
14
 
15
15
  import {
16
+ inferProviderFromModel,
17
+ isModelCompatible,
18
+ resolveDefaultProvider,
16
19
  streamLLMWithTools,
17
20
  type LLMMessage,
18
21
  type LLMToolSpec,
@@ -20,6 +23,7 @@ import {
20
23
  import { debug } from '../debug/log.js';
21
24
  import { buildUniversalPreamble } from '../prompt-library/universal-preamble.js';
22
25
  import { getModelFamily } from '../models/prompts.js';
26
+ import { resolveModelAlias } from '../intelligence-map/model-alias.js';
23
27
  import type {
24
28
  AgentDefinition, AgentEvent, AgentSpawnOpts, AgentTask,
25
29
  } from './types.js';
@@ -57,6 +61,151 @@ class AsyncEventQueue<T> {
57
61
  }
58
62
  }
59
63
 
64
+ // ── Model resolution (TUI-AGENT-MODEL-FALLBACK · 결함 #34) ──
65
+ //
66
+ // A definition's frontmatter `model:` is a REQUEST, not a guarantee. The
67
+ // runner must check it against the provider the child will actually run
68
+ // on BEFORE handing it to streamLLMWithTools — a codex parent used to
69
+ // request `haiku` verbatim and die (the provider chain re-routed the
70
+ // Claude-family id to Anthropic, 결함 #34, 2026-10-14).
71
+ //
72
+ // `model: undefined` in the result means "inherit the parent": the child
73
+ // then rides streamLLMWithTools's own provider decision
74
+ // (`opts.provider ?? resolveDefaultProvider(opts.model)`), exactly like a
75
+ // spawn with no model hint at all.
76
+
77
+ /** Why resolveAgentModel returned the model it did. Six distinct exits —
78
+ * never collapse them into one value: "fell back to parent" and "sent an
79
+ * unrecognized id verbatim" must stay separable in the logs. */
80
+ export type AgentModelResolutionReason =
81
+ | 'no-definition-model'
82
+ | 'declared-inherit'
83
+ | 'definition'
84
+ | 'incompatible-provider'
85
+ | 'unknown-model'
86
+ | 'provider-unknown';
87
+
88
+ export interface AgentModelResolution {
89
+ /** Canonical model id; undefined = inherit the parent's model. */
90
+ model: string | undefined;
91
+ reason: AgentModelResolutionReason;
92
+ }
93
+
94
+ /** Injection seams so tests can pin the provider / inference without
95
+ * touching user config. Defaults are the production functions. */
96
+ export interface ResolveAgentModelDeps {
97
+ currentProviderName: () => string;
98
+ isCompatible: (providerName: string, model: string) => boolean;
99
+ inferProvider: (model: string) => string | null;
100
+ }
101
+
102
+ /** Production `currentProviderName` — the provider a model-less spawn
103
+ * would run on right now (the parent-configured default). A lookup
104
+ * failure is NOT hidden behind a made-up name: it throws, and
105
+ * resolveAgentModel turns it into the separate `provider-unknown` exit
106
+ * (judging compatibility against a fake name like 'auto' would drop a
107
+ * usable definition model to inherit). */
108
+ function productionCurrentProviderName(): string {
109
+ return resolveDefaultProvider().name;
110
+ }
111
+
112
+ const defaultResolveAgentModelDeps: ResolveAgentModelDeps = {
113
+ currentProviderName: productionCurrentProviderName,
114
+ isCompatible: isModelCompatible,
115
+ inferProvider: inferProviderFromModel,
116
+ };
117
+
118
+ /** Resolve a definition model against the provider the child would run
119
+ * on RIGHT NOW. Decision order — each step guards the next:
120
+ * 1. no model → { undefined, 'no-definition-model' }
121
+ * 2. `inherit` (trimmed, case-insensitive; an inheritance MARKER, not
122
+ * a model name) → { undefined, 'declared-inherit' }
123
+ * 3. resolveModelAlias → canonical id
124
+ * 4. inferProvider(canonical) === null → { canonical, 'unknown-model' }
125
+ * — do NOT fall back: free-form names ride the provider as-is
126
+ * (isModelCompatible's "unknown prefix is the provider's problem"
127
+ * stance; dropping a local free-form name to inherit is a regression)
128
+ * 5. isCompatible(currentProviderName, canonical)
129
+ * true → { canonical, 'definition' }
130
+ * false → { undefined, 'incompatible-provider' } (parent fallback)
131
+ * currentProviderName throws → { undefined, 'provider-unknown' } —
132
+ * compatibility cannot be judged, so the definition model is NOT
133
+ * sent (sending it could re-route the provider by model name); the
134
+ * child inherits the parent model — the goal's «can't call it →
135
+ * parent model» intent, kept as its own reason so a lookup failure
136
+ * is never confused with a real incompatibility
137
+ *
138
+ * Inference (4) runs BEFORE compatibility (5) because isModelCompatible
139
+ * returns true on null inference — checking compatibility first would
140
+ * mislabel every unknown model as compatible and the unknown-model exit
141
+ * would be unreachable. */
142
+ export function resolveAgentModel(
143
+ defModel: string | undefined,
144
+ deps: Partial<ResolveAgentModelDeps> = {},
145
+ ): AgentModelResolution {
146
+ const d: ResolveAgentModelDeps = { ...defaultResolveAgentModelDeps, ...deps };
147
+ if (defModel === undefined || defModel.trim() === '') {
148
+ return { model: undefined, reason: 'no-definition-model' };
149
+ }
150
+ const trimmed = defModel.trim();
151
+ if (trimmed.toLowerCase() === 'inherit') {
152
+ return { model: undefined, reason: 'declared-inherit' };
153
+ }
154
+ const canonical = resolveModelAlias(trimmed) ?? trimmed;
155
+ if (d.inferProvider(canonical) === null) {
156
+ return { model: canonical, reason: 'unknown-model' };
157
+ }
158
+ let providerName: string;
159
+ try {
160
+ providerName = d.currentProviderName();
161
+ } catch {
162
+ return { model: undefined, reason: 'provider-unknown' };
163
+ }
164
+ if (d.isCompatible(providerName, canonical)) {
165
+ return { model: canonical, reason: 'definition' };
166
+ }
167
+ return { model: undefined, reason: 'incompatible-provider' };
168
+ }
169
+
170
+ /** Resolve + record exactly one `agent.model` observation. Every runtime
171
+ * resolution goes through here (runAgent ⊕ a direct buildAgentMessages call
172
+ * without a pre-resolved `model`) so «one observation per resolution» holds
173
+ * on both paths. incompatible-provider (parent fallback), unknown-model
174
+ * (verbatim pass-through of an unrecognizable id) and provider-unknown
175
+ * (provider lookup failed, inherited the parent unjudged) are the exits an
176
+ * operator must tell apart from a log line alone — they get warn level. */
177
+ function resolveAgentModelObserved(
178
+ def: Pick<AgentDefinition, 'name' | 'model'>,
179
+ pinnedProviderName?: string,
180
+ ): AgentModelResolution {
181
+ let providerError: string | undefined;
182
+ let currentProviderName: string | undefined = pinnedProviderName;
183
+ const resolution = resolveAgentModel(def.model, {
184
+ currentProviderName: () => {
185
+ if (currentProviderName !== undefined) return currentProviderName;
186
+ try {
187
+ currentProviderName = productionCurrentProviderName();
188
+ return currentProviderName;
189
+ } catch (error) {
190
+ providerError = error instanceof Error ? error.message : String(error);
191
+ throw error;
192
+ }
193
+ },
194
+ });
195
+ debug.log('agent.model', 'resolved', {
196
+ agent: def.name,
197
+ declared: def.model,
198
+ model: resolution.model,
199
+ reason: resolution.reason,
200
+ provider: currentProviderName ?? null,
201
+ ...(providerError !== undefined ? { providerError } : {}),
202
+ }, resolution.reason === 'incompatible-provider' || resolution.reason === 'unknown-model'
203
+ || resolution.reason === 'provider-unknown'
204
+ ? { level: 'warn' as const }
205
+ : undefined);
206
+ return resolution;
207
+ }
208
+
60
209
  // ── Helpers ──
61
210
 
62
211
  /** Assemble the initial message history. The parent's rendered system
@@ -74,7 +223,7 @@ export function buildAgentMessages(
74
223
  def: AgentDefinition,
75
224
  prompt: string,
76
225
  systemPromptPrefix?: string,
77
- ctx: { cwd?: string; enabledTools?: readonly string[] } = {},
226
+ ctx: { cwd?: string; enabledTools?: readonly string[]; model?: string } = {},
78
227
  ): LLMMessage[] {
79
228
  let effectivePrefix: string | undefined = systemPromptPrefix;
80
229
  if (def.omitInheritedContext) {
@@ -108,7 +257,15 @@ export function buildAgentMessages(
108
257
  // omitInheritedContext contract stable we honor it strictly.
109
258
  let universalPreamble: LLMMessage[] = [];
110
259
  if (!def.omitInheritedContext && ctx.cwd) {
111
- const agentModelFamily = def.model ? getModelFamily(def.model) : undefined;
260
+ // TUI-AGENT-MODEL-FALLBACK: the preamble's modelFamily must track the
261
+ // model the run will actually use. runAgent passes the already-resolved
262
+ // model (one resolution + one `agent.model` observation per spawn);
263
+ // direct callers that omit `model` resolve here so a definition model
264
+ // the current provider can't run never reaches the preamble either.
265
+ const effectiveModel = 'model' in ctx
266
+ ? ctx.model
267
+ : resolveAgentModelObserved(def).model;
268
+ const agentModelFamily = effectiveModel ? getModelFamily(effectiveModel) : undefined;
112
269
  universalPreamble = buildUniversalPreamble({
113
270
  cwd: ctx.cwd,
114
271
  ...(agentModelFamily !== undefined ? { modelFamily: agentModelFamily } : {}),
@@ -206,6 +363,14 @@ export async function* runAgent(
206
363
  // `Agent` → search-vs-spawn split, `TaskCreate` → don't batch).
207
364
  const tools = filterAgentTools(opts.tools, task.definition.tools);
208
365
 
366
+ // TUI-AGENT-MODEL-FALLBACK (결함 #34): resolve the definition model
367
+ // against the provider the child will ACTUALLY run on — the pinned
368
+ // `opts.provider` when the dispatcher chose one, otherwise the
369
+ // parent-configured default (what streamLLMWithTools picks for a
370
+ // model-less spawn). `model: undefined` = inherit: the child then takes
371
+ // the same provider/model decision path as the parent.
372
+ const modelResolution = resolveAgentModelObserved(task.definition, opts.provider?.name);
373
+
209
374
  // Build history on the task so callers can inspect it after the run.
210
375
  // PFC-S1 P5: pass task.cwd so the slim-context notice (when
211
376
  // omitInheritedContext) can name the child's working directory.
@@ -214,6 +379,7 @@ export async function* runAgent(
214
379
  task.prompt,
215
380
  opts.systemPromptPrefix,
216
381
  {
382
+ model: modelResolution.model,
217
383
  ...(task.cwd ? { cwd: task.cwd } : {}),
218
384
  ...(tools ? { enabledTools: tools.map(t => t.name) } : {}),
219
385
  },
@@ -252,7 +418,7 @@ export async function* runAgent(
252
418
  dispatchTool,
253
419
  },
254
420
  {
255
- model: task.definition.model,
421
+ model: modelResolution.model,
256
422
  tools,
257
423
  signal: task.controller.signal,
258
424
  provider: opts.provider,
@@ -0,0 +1,156 @@
1
+ // ── TUI 자기인지 ambient 캐시 — 턴 시작이 이벤트 루프를 막지 않게 (TUI-TYPING-LAG · 2026-10-14) ──
2
+ //
3
+ // 실측(격리 TUI · bun --cpu-prof): 턴마다 `elanousSelfAmbientBaseParts()`(ops 스캔·crontab·`ps`)가
4
+ // 메인 스레드에서 동기로 돌았고, 한 턴에 «두 번»(대시보드 preamble ⊕ ACP buildTurnMessages) 돌아
5
+ // 그 동안 키 입력이 0.4~9s 멈췄다. 이 캐시는 «요청과 무관한» 부분만 담는다:
6
+ // · 신선(< FRESH_MS) → 그대로 쓴다.
7
+ // · 오래됨(< STALE_MAX_MS) → 그대로 쓰고 워커에서 다시 잰다(다음 턴용).
8
+ // · 없음/너무 오래됨 → 종전대로 동기 계산(첫 턴 내용 보존). TUI 는 부팅 때 데우고 5s 주기
9
+ // 틱(`refreshSelfAmbientCache({}, { ifOlderThanMs })` · src/dashboard/index.ts)으로 계속 데워
10
+ // 두므로, 워커가 실패(백오프)하지 않는 한 오래 쉰 뒤 첫 턴도 이 길로 안 온다.
11
+ // 관측 = `self-ambient.cache` (hit · stale-hit · sync · worker-refreshed · worker-failed).
12
+
13
+ import { isMainThread, parentPort, workerData, Worker } from 'node:worker_threads';
14
+ import { debug } from '../debug/log.js';
15
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
16
+ import { setElanousConfigDir } from '../elanous-config-dir.js';
17
+ import { elanousSelfAmbientBaseParts } from './self-ambient.js';
18
+
19
+ export const SELF_AMBIENT_FRESH_MS = 30_000;
20
+ export const SELF_AMBIENT_STALE_MAX_MS = 10 * 60_000;
21
+ const WORKER_TIMEOUT_MS = 60_000;
22
+
23
+ interface CacheEntry { at: number; version: number; parts: string[] }
24
+
25
+ export interface SelfAmbientCacheDeps {
26
+ now?: () => number;
27
+ computeSync?: () => string[];
28
+ computeInWorker?: (stateRoot: string | undefined, selectedRoot: string) => Promise<string[]>;
29
+ universeKey?: () => { stateRoot: string | undefined; selectedRoot: string };
30
+ log?: (category: string, event: string, data: Record<string, unknown>) => void;
31
+ }
32
+
33
+ const entries = new Map<string, CacheEntry>();
34
+ /** Monotonic store sequence — orders async worker stores against synchronous ones.
35
+ * A millisecond `at` clock ties within the same millisecond and let a worker's older
36
+ * result overwrite a newer synchronous computation; the version never ties. */
37
+ let storeSeq = 0;
38
+ const inFlight = new Map<string, Promise<void>>();
39
+ /** A failed worker is not retried (by ticks or stale turn reads) for this long; the turn path keeps
40
+ * serving the stale entry, or falls back to sync once it is too old. */
41
+ const WORKER_FAILURE_BACKOFF_MS = 60_000;
42
+ const lastFailureAt = new Map<string, number>();
43
+
44
+ function resolveDeps(deps: SelfAmbientCacheDeps): Required<SelfAmbientCacheDeps> {
45
+ return {
46
+ now: deps.now ?? Date.now,
47
+ computeSync: deps.computeSync ?? elanousSelfAmbientBaseParts,
48
+ computeInWorker: deps.computeInWorker ?? computeBasePartsInWorker,
49
+ universeKey: deps.universeKey ?? (() => ({ stateRoot: process.env.ELANOUS_STATE_DIR, selectedRoot: effectiveInstanceRoot() })),
50
+ log: deps.log ?? ((category, event, data) => debug.log(category, event, data)),
51
+ };
52
+ }
53
+
54
+ /** Start (or join) a background refresh. Resolves when the cache has been updated or the refresh failed.
55
+ * `ifOlderThanMs` turns it into a keep-warm tick: a younger entry is left alone. */
56
+ export function refreshSelfAmbientCache(deps: SelfAmbientCacheDeps = {}, opts: { ifOlderThanMs?: number } = {}): Promise<void> {
57
+ const d = resolveDeps(deps);
58
+ const { stateRoot, selectedRoot } = d.universeKey();
59
+ const key = JSON.stringify([selectedRoot, stateRoot ?? null]);
60
+ const cached = entries.get(key);
61
+ if (cached && opts.ifOlderThanMs !== undefined && d.now() - cached.at < opts.ifOlderThanMs) return Promise.resolve();
62
+ if (d.now() - (lastFailureAt.get(key) ?? -Infinity) < WORKER_FAILURE_BACKOFF_MS) return Promise.resolve();
63
+ const running = inFlight.get(key);
64
+ if (running) return running;
65
+ const startedAt = d.now();
66
+ const startedVersion = storeSeq;
67
+ // A worker that fails to even start (sync throw) is the same fail-soft failure as one that rejects.
68
+ let started: Promise<string[]>;
69
+ try { started = d.computeInWorker(stateRoot, selectedRoot); }
70
+ catch (error) { started = Promise.reject(error); }
71
+ const refresh = started
72
+ .then((parts) => {
73
+ // A newer entry (e.g. a synchronous first-turn computation that overlapped this worker) is kept.
74
+ // Judged by the monotonic store version, not the millisecond clock: a store that landed in the
75
+ // same millisecond as this worker's start is still newer.
76
+ const current = entries.get(key);
77
+ if (current && current.version > startedVersion) return;
78
+ entries.set(key, { at: startedAt, version: ++storeSeq, parts });
79
+ d.log('self-ambient.cache', 'worker-refreshed', { ms: d.now() - startedAt, parts: parts.length });
80
+ }, (error: unknown) => {
81
+ lastFailureAt.set(key, d.now());
82
+ d.log('self-ambient.cache', 'worker-failed', { ms: d.now() - startedAt, reason: error instanceof Error ? error.message : String(error) });
83
+ })
84
+ .finally(() => { inFlight.delete(key); });
85
+ inFlight.set(key, refresh);
86
+ return refresh;
87
+ }
88
+
89
+ /** Request-independent ambient parts for the TUI turn preamble, served from the cache when possible. */
90
+ export function cachedSelfAmbientBaseParts(deps: SelfAmbientCacheDeps = {}): string[] {
91
+ const d = resolveDeps(deps);
92
+ const { stateRoot, selectedRoot } = d.universeKey();
93
+ const key = JSON.stringify([selectedRoot, stateRoot ?? null]);
94
+ const at = d.now();
95
+ const cached = entries.get(key);
96
+ const ageMs = cached ? at - cached.at : null;
97
+ if (cached && ageMs! < SELF_AMBIENT_FRESH_MS) {
98
+ d.log('self-ambient.cache', 'hit', { ageMs });
99
+ return [...cached.parts];
100
+ }
101
+ if (cached && ageMs! < SELF_AMBIENT_STALE_MAX_MS) {
102
+ d.log('self-ambient.cache', 'stale-hit', { ageMs });
103
+ void refreshSelfAmbientCache(deps);
104
+ return [...cached.parts];
105
+ }
106
+ const parts = d.computeSync();
107
+ entries.set(key, { at, version: ++storeSeq, parts });
108
+ d.log('self-ambient.cache', 'sync', { ms: d.now() - at, ageMs, parts: parts.length });
109
+ return [...parts];
110
+ }
111
+
112
+ export function _resetSelfAmbientCacheForTest(): void {
113
+ storeSeq = 0;
114
+ entries.clear();
115
+ inFlight.clear();
116
+ lastFailureAt.clear();
117
+ }
118
+
119
+ function computeBasePartsInWorker(stateRoot: string | undefined, selectedRoot: string): Promise<string[]> {
120
+ const worker = new Worker(new URL(import.meta.url), { workerData: { kind: 'self-ambient' } });
121
+ return new Promise((resolve, reject) => {
122
+ let settled = false;
123
+ const timeout = setTimeout(() => finish(new Error(`self-ambient worker timed out after ${WORKER_TIMEOUT_MS}ms`)), WORKER_TIMEOUT_MS);
124
+ // A background warm-up must never keep a finished CLI or test process alive.
125
+ timeout.unref?.();
126
+ worker.unref?.();
127
+ const finish = (error?: Error, parts?: string[]): void => {
128
+ if (settled) return;
129
+ settled = true;
130
+ clearTimeout(timeout);
131
+ void worker.terminate();
132
+ if (error) reject(error);
133
+ else resolve(parts!);
134
+ };
135
+ worker.on('message', (message: { parts?: string[]; error?: string }) => {
136
+ if (message.error) finish(new Error(message.error));
137
+ else if (message.parts) finish(undefined, message.parts);
138
+ });
139
+ worker.on('error', error => finish(error instanceof Error ? error : new Error(String(error))));
140
+ worker.on('exit', code => { if (!settled) finish(new Error(`self-ambient worker exited before answering: ${code}`)); });
141
+ // Pin the caller's universe: a programmatic config override is not inherited by workers.
142
+ worker.postMessage({ stateRoot, selectedRoot });
143
+ });
144
+ }
145
+
146
+ const selfAmbientWorkerPort = parentPort;
147
+ if (!isMainThread && selfAmbientWorkerPort && workerData?.kind === 'self-ambient') {
148
+ selfAmbientWorkerPort.on('message', ({ stateRoot, selectedRoot }: { stateRoot?: string; selectedRoot: string }) => {
149
+ try {
150
+ if (stateRoot === undefined) delete process.env.ELANOUS_STATE_DIR;
151
+ else process.env.ELANOUS_STATE_DIR = stateRoot;
152
+ setElanousConfigDir(selectedRoot);
153
+ selfAmbientWorkerPort.postMessage({ parts: elanousSelfAmbientBaseParts() });
154
+ } catch (error) { selfAmbientWorkerPort.postMessage({ error: error instanceof Error ? error.message : String(error) }); }
155
+ });
156
+ }
@@ -184,11 +184,18 @@ export function investigationRecallAmbient(taskText: string): string {
184
184
  /** 자기인지 ambient — 최근 자기 구현/변경 + 최근 자율행동 + 자율 시스템 이상 + 미션 사건 사실
185
185
  * (+ taskText 주면 조사문맥 관련 회상·축B). 매 턴 fresh · 각각 fail-soft(없음이면 빈 문자열). */
186
186
  export function elanousSelfAmbientParts(taskText?: string): string[] {
187
+ const parts = elanousSelfAmbientBaseParts();
188
+ if (taskText) { try { parts.push(investigationRecallAmbient(taskText)); } catch { /* fail-soft */ } }
189
+ return parts.filter(Boolean);
190
+ }
191
+
192
+ /** The request-independent ambient parts (store scans · `ps` · crontab). Split out so the
193
+ * TUI can compute them off its event loop (`self-ambient-cache.ts`). */
194
+ export function elanousSelfAmbientBaseParts(): string[] {
187
195
  const parts: string[] = [];
188
196
  try { parts.push(recentSelfChangesContext()); } catch { /* fail-soft */ }
189
197
  try { parts.push(recentAutonomyContext()); } catch { /* fail-soft */ }
190
198
  try { parts.push(opsHealthContext()); } catch { /* fail-soft */ }
191
199
  try { parts.push(missionIncidentAmbient()); } catch { /* fail-soft */ }
192
- if (taskText) { try { parts.push(investigationRecallAmbient(taskText)); } catch { /* fail-soft */ } }
193
200
  return parts.filter(Boolean);
194
201
  }
@@ -132,7 +132,7 @@ export function createGlobalSubagentCallable(
132
132
  const done = drainToResult(handle.events, () => ({
133
133
  durationMs: Date.now() - startedAt,
134
134
  modelId: effectiveDefinition.model,
135
- }));
135
+ }), () => handle.task.controller?.signal.aborted ?? (signal?.aborted === true));
136
136
 
137
137
  return { address, done };
138
138
  };
@@ -154,6 +154,7 @@ async function drainToResult(
154
154
  unknown
155
155
  >,
156
156
  closing: () => { durationMs: number; modelId?: string },
157
+ signalAborted: () => boolean,
157
158
  ): Promise<{
158
159
  status: 'completed' | 'failed' | 'cancelled';
159
160
  output: string;
@@ -190,7 +191,7 @@ async function drainToResult(
190
191
 
191
192
  const close = closing();
192
193
  const baseModel = close.modelId ? { modelId: close.modelId } : {};
193
- if (aborted) {
194
+ if (aborted || signalAborted()) {
194
195
  return { status: 'cancelled', output: accumulated, durationMs: close.durationMs, ...baseModel };
195
196
  }
196
197
  if (errorMsg !== null) {
@@ -113,6 +113,11 @@ export class TaskNotificationQueue {
113
113
  return this.queue.length;
114
114
  }
115
115
 
116
+ /** Is this task's notification still queued (not yet drained into a turn)? */
117
+ has(taskId: string): boolean {
118
+ return this.queue.some((n) => n.taskId === taskId);
119
+ }
120
+
116
121
  /** Forget everything — tests use this for isolation. Listeners are
117
122
  * preserved: clear() empties queue + seen, not the wake wiring. */
118
123
  clear(): void {
@@ -361,9 +361,12 @@ export function extractAppliedReviewItems(comments: readonly NonNullable<LatestR
361
361
  /** 브랜치의 열린 PR 코멘트에서 이전 self-dev 반영분을 fail-soft로 읽는다. */
362
362
  export function fetchAppliedReviewItemsForBranch(branch: string, runGh: (args: string[]) => string = gh): AppliedReviewItems {
363
363
  try {
364
- const raw = runGh(['pr', 'view', branch, '--json', 'comments']);
365
- const source = JSON.parse(raw) as LatestReviewSource;
366
- const signals = filterReviewSignals(source);
364
+ // A Pod repair uses the synthetic worktree base `pr-N`; GitHub knows that
365
+ // source by PR number, not by the synthetic branch name.
366
+ const source = /^pr[:-]([1-9]\d*)$/.exec(branch)?.[1] ?? branch;
367
+ const raw = runGh(['pr', 'view', source, '--json', 'comments']);
368
+ const reviewSource = JSON.parse(raw) as LatestReviewSource;
369
+ const signals = filterReviewSignals(reviewSource);
367
370
  return { basePrLocated: true, ...analyzeAppliedReviewItems(signals.selfAuthoredComments) };
368
371
  } catch {
369
372
  return { basePrLocated: false, items: [], headlineComments: 0 };
@@ -85,6 +85,18 @@ export interface AcpImplementerResult {
85
85
 
86
86
  const OBS = 'agent-substrate.acp-implementer';
87
87
 
88
+ /** Claude ACP's default preset imports user/project plugins and MCP servers into every
89
+ * prompt snapshot. The implementation child only needs the built-in coding tools. */
90
+ export const CLAUDE_IMPLEMENTER_META = {
91
+ claudeCode: { options: {
92
+ tools: ['Read', 'Write', 'Edit', 'Bash', 'Glob', 'Grep'],
93
+ settingSources: [],
94
+ plugins: [],
95
+ mcpServers: {},
96
+ strictMcpConfig: true,
97
+ } },
98
+ } as const;
99
+
88
100
  export function makeAcpImplementer(opts: AcpImplementerOpts): (prompt: string) => Promise<AcpImplementerResult> {
89
101
  return async (prompt) => {
90
102
  const spawn = subscriptionReviewerSpawn(opts.spec ?? { provider: 'claude-acp' }, opts.env ?? process.env, opts.proxyBaseUrl);
@@ -119,10 +131,10 @@ export function makeAcpImplementer(opts: AcpImplementerOpts): (prompt: string) =
119
131
  await withinHandshake(agent.start());
120
132
  let sid: string;
121
133
  if (opts.resumeSessionId) {
122
- await withinHandshake(agent.loadSession({ sessionId: opts.resumeSessionId, cwd: opts.worktree }));
134
+ await withinHandshake(agent.loadSession({ sessionId: opts.resumeSessionId, cwd: opts.worktree, _meta: CLAUDE_IMPLEMENTER_META }));
123
135
  sid = opts.resumeSessionId;
124
136
  } else {
125
- sid = await withinHandshake(agent.newSession());
137
+ sid = await withinHandshake(agent.newSession(CLAUDE_IMPLEMENTER_META));
126
138
  }
127
139
  if (opts.model) await withinHandshake(agent.selectSessionModel(sid, opts.model));
128
140
  debug.log(OBS, 'start', { cwd: opts.worktree, model: opts.model ?? '(default)', resumed: Boolean(opts.resumeSessionId) });
@@ -652,6 +652,17 @@ export function buildReviewPrompt(
652
652
  * `none of the tests …`. 표지 낱말로 시작하는 실제 블로커를 지우면 PASS/WARN 리뷰에서 블로커가 사라진다. */
653
653
  const NONE_WORD = String.raw`(?:없음|해당\s*없음|n\/a|none|nothing)`;
654
654
  const BARE_SENTINEL = new RegExp(String.raw`^${NONE_WORD}\s*[.。]?$`, 'i');
655
+ // GLM 은 비어 있는 mustFix 항목이나 괄호 안의 한 문장으로 무소견을 적는다.
656
+ // 괄호 전체만 검사한다. 중간에 "no blockers" 가 있어도 뒤에 지적이 이어지면 버리지 않는다.
657
+ const BRACKETED_PLACEHOLDER = /^[((]\s*([\s\S]*?)\s*[))]$/;
658
+ const PLACEHOLDER_ONLY = /^(?:없음|해당\s*없음|none|n\/a|no\s+blockers?)$/i;
659
+ const PLACEHOLDER_END = /(?:블로커|차단)(?:\s*(?:수준의?\s*)?(?:결함|문제|이슈|지적))?\s*없음$|no\s+blockers?$/i;
660
+ function isBracketedPlaceholder(text: string): boolean {
661
+ const bracketed = BRACKETED_PLACEHOLDER.exec(text);
662
+ if (!bracketed) return false;
663
+ const inside = bracketed[1]!.trim().replace(/(?:\s*(?:…|\.{2,}|[.。]))+\s*$/, '').trim();
664
+ return PLACEHOLDER_ONLY.test(inside) || PLACEHOLDER_END.test(inside);
665
+ }
655
666
  const DASH_ONLY_SENTINEL = /^[([(【]\s*[-—–]\s*[)\])】]$/;
656
667
  // 목록 항목의 바깥 `- `와 별개로, 리뷰어가 괄호 안에도 장식 대시를 둘 수 있다: `- (- 없음 -)`.
657
668
  const DASH_WRAPPED_BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*(?:[-—–]+\s*)?${NONE_WORD}\s*(?:[-—–]+\s*)?[)\])】]$`, 'i');
@@ -659,6 +670,8 @@ const BRACKETED_SENTINEL = new RegExp(String.raw`^[([(【]\s*${NONE_WORD}(?:\s
659
670
  // ⭐ 설명 «전체»가 「지적 없음」 한 문장일 때만 — 일부만 맞아도 접으면 `(none: no blockers are checked because …)` 같은 지적이 사라진다.
660
671
  const NO_FINDING_REMARK = new RegExp([
661
672
  String.raw`^(?:(?:블로커|차단)\s*)?(?:수준의?\s*)?(?:결함|문제|이슈|지적|블로커)(?:은|는|이|가)?\s*(?:발견되지\s*않(?:음|았(?:다|습니다)?)|없(?:음|다|습니다))[.。]?$`,
673
+ // REVIEW-MUSTFIX-NONE-PARSE — `(없음 — 이 조각 범위에서는 차단 결함 없음)` 꼬리.
674
+ String.raw`^(?:이\s*)?(?:조각\s*)?범위(?:에서는|에서|엔)?\s*(?:블로커|차단)(?:\s*(?:수준의?\s*)?(?:결함|문제|이슈|지적))?\s*없(?:음|다|습니다)[.。]?$`,
662
675
  String.raw`^(?:no|zero)\s+(?:blocking\s+)?(?:blockers?|issues?|problems?|findings?|must-?fix(?:es)?)(?:\s+found)?\.?$`,
663
676
  String.raw`^nothing\s+(?:blocking|to\s+fix)\.?$`,
664
677
  // REVIEW-MUSTFIX-NONE-SENTINEL — `(없음 — 수용기준 충족)` · `(none — acceptance criteria met)` (GLM 실측 6건). «미충족» 은 ^ 앵커로 안 맞는다.
@@ -685,6 +698,7 @@ function isLongNoFindingBracket(text: string): boolean {
685
698
  * ⭐ export — `parseReviewResultOutput` 가 «같은» 판정으로 저장된 결과의 표지 줄을 다시 접는다(PR-LAND-MUSTFIX-NONE · 복제 금지). */
686
699
  export function isNoneSentinelFinding(finding: string): boolean {
687
700
  const text = finding.trim();
701
+ if (!text || isBracketedPlaceholder(text)) return true;
688
702
  if (/^[-—–]+$/.test(text)) return true;
689
703
  const markerText = text.replace(/^[—–-]+\s*|\s*[—–-]+$/g, '').trim();
690
704
  if (markerText && (BARE_SENTINEL.test(markerText) || DASH_ONLY_SENTINEL.test(markerText) || DASH_WRAPPED_BRACKETED_SENTINEL.test(markerText))) return true;
@@ -1125,6 +1125,24 @@ function roleAcpErrorReason(error: unknown): 'acp-handshake-timeout' | 'acp-erro
1125
1125
 
1126
1126
  type AcpFallbackSkip = { backend: string; reason: string };
1127
1127
 
1128
+ function validateReviewDenyBackends(value: unknown, now: number): string[] | null {
1129
+ if (value === undefined) return [];
1130
+ if (!Array.isArray(value)) return null;
1131
+ const denied: string[] = [];
1132
+ for (const entry of value) {
1133
+ if (typeof entry === 'string' && entry.trim()) { denied.push(entry); continue; }
1134
+ if (!entry || typeof entry !== 'object' || Array.isArray(entry)) return null;
1135
+ const item = entry as Record<string, unknown>;
1136
+ if (Object.keys(item).some((key) => key !== 'backend' && key !== 'expiresAt')
1137
+ || typeof item.backend !== 'string' || !item.backend.trim()
1138
+ || typeof item.expiresAt !== 'string' || !/^\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d(?:\.\d+)?Z$/.test(item.expiresAt)
1139
+ || !Number.isFinite(Date.parse(item.expiresAt)) || new Date(item.expiresAt).toISOString().slice(0, 19) !== item.expiresAt.slice(0, 19)
1140
+ || Date.parse(item.expiresAt) <= now) return null;
1141
+ denied.push(item.backend);
1142
+ }
1143
+ return denied;
1144
+ }
1145
+
1128
1146
  function orderedAcpReviewFallbackBackends(configuredBackend: string | undefined, denyBackends: readonly string[] = []): {
1129
1147
  backends: string[];
1130
1148
  skipped: AcpFallbackSkip[];
@@ -1294,10 +1312,17 @@ async function runSelfReviewCliCommandPinned(
1294
1312
  const acpBackend = acpBackendResolution.backend;
1295
1313
  const requestedModel = opts.model?.trim() || undefined;
1296
1314
  const rawReviewDenyBackends = (getUserConfig().raw?.acp as { reviewDenyBackends?: unknown } | undefined)?.reviewDenyBackends;
1297
- const configuredReviewDenyBackends = Array.isArray(rawReviewDenyBackends)
1298
- ? rawReviewDenyBackends.filter((backend): backend is string => typeof backend === 'string')
1299
- : [];
1300
- const automaticFallbacks = orderedAcpReviewFallbackBackends(opts.configuredAcpBackend, opts.reviewDenyBackends ?? configuredReviewDenyBackends);
1315
+ const denyCheckedAt = Date.now();
1316
+ const configuredReviewDenyBackends = validateReviewDenyBackends(rawReviewDenyBackends, denyCheckedAt);
1317
+ const reviewDenyBackends = validateReviewDenyBackends(opts.reviewDenyBackends, denyCheckedAt);
1318
+ if (configuredReviewDenyBackends === null || reviewDenyBackends === null) {
1319
+ const message = 'acp.reviewDenyBackends 설정이 유효하지 않거나 만료됐습니다 — 리뷰를 실행하지 않습니다.';
1320
+ deps.log('review-deny-invalid', { reason: 'invalid-or-expired-review-deny-backends' }, { level: 'warn' });
1321
+ deps.error(message);
1322
+ return { results: opts.json ? [{ error: message }] : [], failed: 1 };
1323
+ }
1324
+ const automaticFallbacks = orderedAcpReviewFallbackBackends(opts.configuredAcpBackend,
1325
+ opts.reviewDenyBackends === undefined ? configuredReviewDenyBackends : reviewDenyBackends);
1301
1326
  const fallbackAcpBackends = opts.acpBackend
1302
1327
  ? [canonicalizeBackendId(opts.acpBackend)]
1303
1328
  : automaticFallbacks.backends;
@@ -1632,6 +1657,7 @@ async function runSelfReviewCliCommandPinned(
1632
1657
  const reviewProvenance = {
1633
1658
  reviewRoute,
1634
1659
  fallbackAttempted,
1660
+ ...(requestedModel ? { requestedModel } : {}),
1635
1661
  ...(fallbackBackend ? { fallbackBackend } : {}),
1636
1662
  ...(fallbackBackend ? { requestedModel: primaryModel, actualBackend: `acp:${fallbackBackend}` } : {}),
1637
1663
  ...(fallbackNotAttemptedReason ? { fallbackNotAttemptedReason } : {}),