elanous 0.2.29 → 0.2.31

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 (709) 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 → LSXfY0u9QtfDbejY0Ukf_}/_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-50625904996a8fa8.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/6948.1062d4594652b5bf.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7138-eaf841fc1dc03463.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/7174-cda29ee13d7790e7.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/7304-3c07583f4e405f4f.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7371.80c05c653b08e907.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7391.ebae168025c91b6a.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{1852.7f7b53991fcb99ef.js → 7502.ccd5b8065545edd0.js} +2 -2
  93. package/apps/pwa/out/_next/static/chunks/7557.e325503a090a4310.js +8 -0
  94. package/apps/pwa/out/_next/static/chunks/7569-9ce9432c7f10989f.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/{6534.1ab00f370db7b105.js → 7862.30a8d6482bb238eb.js} +1 -1
  96. package/apps/pwa/out/_next/static/chunks/7886-55854585fadeded1.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7947-d0759430f8042240.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/{285adb1a.5654e605dddf86d2.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/8018.a32663f04a6fc5f9.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/8097-92f87bd108322f66.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/8215-1661812b6e9ad71f.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8260-19c921a51ca8ec3e.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8440.3a5cf5c85aa76db8.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8519-4599be2249161e68.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8547.b028b90c5c01ace6.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8587-cbe02a953a7f4990.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/877-2b977259c4b15655.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/9002.e5658224e3dc1b6f.js +24 -0
  109. package/apps/pwa/out/_next/static/chunks/9019-0a4b40c50c7314fb.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/{1516.dfaceff3fd2d0e0d.js → 9138.b6e80031afb1d973.js} +1 -1
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{9907.49be0fcadaf214b5.js → 9221.7d22eaf353a2d4e7.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/9230.44f5039e796e4ab4.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/{8767-2f6a634f5abeaa01.js → 9279-d28c5b7754d010ae.js} +1 -1
  115. package/apps/pwa/out/_next/static/chunks/939.336acce73e98482c.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/{3160-95c96f4d2a21dd26.js → 9398-6aed28f0a96d0d6f.js} +1 -1
  117. package/apps/pwa/out/_next/static/chunks/9407.e49124dedf0f5e72.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/9610.c07cce4bfcc14ed7.js +1 -0
  119. package/apps/pwa/out/_next/static/chunks/9667-ce78c2ce91050ff9.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/{328bb3ab-6628a1114fe3fb3b.js → 997ce8a5-2ad501927003b41b.js} +1 -1
  121. package/apps/pwa/out/_next/static/chunks/{6853.cc5174a9dee59593.js → 9989.3694300e5f000b14.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-339fabb3499da0e1.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-bf3634a117322df7.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-3535a4a69f1fafaa.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-b9f51447f757fbf2.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-a5635eba0d73b84e.js → page-2ebb8fd59b9461f9.js} +1 -1
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-a2fc4e49a4fa4ba8.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-5a503541353e60a8.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-6025101384e361a5.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f4b630cc8b5273cd.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a645f00a06483e9a.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-61ac22cbab1ee4ec.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e9bab7413b028b28.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-c992eafe028b642e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-e547e6ce55f1fb33.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-d27e1b9850fd54bf.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-339fabb3499da0e1.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-805ac2e137b7a121.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-0fec29c7ba01894b.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-339a07410cd6f36b.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-349f2752d8cd37ad.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-d5c6dcf31c25cecc.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-2fd93ed8c9f16580.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-9b564dbff0fefc35.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-62f4475d3c38fb9b.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-814ba51385225776.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-397d479626e5a459.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-af1bba4e3251b728.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3ad3be5e7d3fdce9.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-f219ccdbc0bf27df.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4da93ad35d4a8d28.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/page-456666766e5ce6fc.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/page-7404e377e8adb8c5.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-14456240ed2a36ad.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-3a658d5fa6d16a25.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-0157de6e85f8bb6b.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-0a07363b130182a1.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-841d73d4ac44ed49.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-6f43a3d1146e6377.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-339fabb3499da0e1.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/{page-29900ed0011b2c83.js → page-521ee23ac8c0abfa.js} +1 -1
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9992ee285efaa83.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-3d48e85fa89ec04f.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-d2ced71132fac9b2.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/page-f08358bdf251adb9.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-233c71cd5f68f0d7.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-70151d78de2f375e.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-dcac33a3e2cb72c0.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/{page-9f92737b8766009a.js → page-149dc1caba411bb9.js} +1 -1
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0448145ccd5c45c1.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-9cb0c444903da65d.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-17e504c396e0e389.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{425cfc4d.fb91158e3971c39f.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/e5012ffe.f727e23c231f4342.js +122 -0
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/ebc7d829.264a0bcb6c750b50.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/framework-906af9bd029e166c.js +1 -0
  178. package/apps/pwa/out/_next/static/chunks/main-a24847f9f684d469.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-app-7bdcd8aa7c8397d3.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/pages/_app-6ba46a5066fc226d.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_error-a8dc6d07591f2a25.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/webpack-f13df28c15c55eee.js +1 -0
  183. package/apps/pwa/out/_next/static/css/{72becfd42807b50d.css → 3f5fc6f96e2cf7b2.css} +1 -1
  184. package/apps/pwa/out/approvals/index.html +1 -1
  185. package/apps/pwa/out/approvals/index.txt +23 -23
  186. package/apps/pwa/out/autopilot/index.html +1 -1
  187. package/apps/pwa/out/autopilot/index.txt +23 -23
  188. package/apps/pwa/out/board/index.html +1 -1
  189. package/apps/pwa/out/board/index.txt +23 -23
  190. package/apps/pwa/out/botlab/index.html +1 -1
  191. package/apps/pwa/out/botlab/index.txt +22 -22
  192. package/apps/pwa/out/bots/index.html +1 -1
  193. package/apps/pwa/out/bots/index.txt +22 -22
  194. package/apps/pwa/out/ceo/index.html +1 -1
  195. package/apps/pwa/out/ceo/index.txt +23 -23
  196. package/apps/pwa/out/chat/index.html +1 -1
  197. package/apps/pwa/out/chat/index.txt +22 -22
  198. package/apps/pwa/out/consult/index.html +1 -1
  199. package/apps/pwa/out/consult/index.txt +23 -23
  200. package/apps/pwa/out/control/index.html +1 -1
  201. package/apps/pwa/out/control/index.txt +23 -23
  202. package/apps/pwa/out/decisions/index.html +1 -1
  203. package/apps/pwa/out/decisions/index.txt +22 -22
  204. package/apps/pwa/out/design-check/index.html +1 -1
  205. package/apps/pwa/out/design-check/index.txt +23 -23
  206. package/apps/pwa/out/editor/index.html +1 -1
  207. package/apps/pwa/out/editor/index.txt +23 -23
  208. package/apps/pwa/out/exec/index.html +1 -1
  209. package/apps/pwa/out/exec/index.txt +23 -23
  210. package/apps/pwa/out/field/index.html +1 -1
  211. package/apps/pwa/out/field/index.txt +23 -23
  212. package/apps/pwa/out/healthz +1 -1
  213. package/apps/pwa/out/index.html +1 -1
  214. package/apps/pwa/out/index.txt +22 -22
  215. package/apps/pwa/out/inside/index.html +1 -1
  216. package/apps/pwa/out/inside/index.txt +22 -22
  217. package/apps/pwa/out/intake/index.html +1 -1
  218. package/apps/pwa/out/intake/index.txt +23 -23
  219. package/apps/pwa/out/live/index.html +1 -1
  220. package/apps/pwa/out/live/index.txt +23 -23
  221. package/apps/pwa/out/live-run/index.html +1 -1
  222. package/apps/pwa/out/live-run/index.txt +23 -23
  223. package/apps/pwa/out/loops/index.html +1 -1
  224. package/apps/pwa/out/loops/index.txt +22 -22
  225. package/apps/pwa/out/market/index.html +1 -1
  226. package/apps/pwa/out/market/index.txt +22 -22
  227. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  228. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  229. package/apps/pwa/out/morning/index.html +1 -1
  230. package/apps/pwa/out/morning/index.txt +23 -23
  231. package/apps/pwa/out/observatory/index.html +1 -1
  232. package/apps/pwa/out/observatory/index.txt +23 -23
  233. package/apps/pwa/out/ops/checklist/index.html +1 -1
  234. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  235. package/apps/pwa/out/ops/release/index.html +1 -1
  236. package/apps/pwa/out/ops/release/index.txt +22 -22
  237. package/apps/pwa/out/ops/seats/index.html +1 -1
  238. package/apps/pwa/out/ops/seats/index.txt +22 -22
  239. package/apps/pwa/out/outputs/index.html +1 -1
  240. package/apps/pwa/out/outputs/index.txt +22 -22
  241. package/apps/pwa/out/reflection/index.html +1 -1
  242. package/apps/pwa/out/reflection/index.txt +23 -23
  243. package/apps/pwa/out/scheduler/index.html +1 -1
  244. package/apps/pwa/out/scheduler/index.txt +23 -23
  245. package/apps/pwa/out/sessions/index.html +1 -1
  246. package/apps/pwa/out/sessions/index.txt +22 -22
  247. package/apps/pwa/out/settings/devices/index.html +1 -1
  248. package/apps/pwa/out/settings/devices/index.txt +23 -23
  249. package/apps/pwa/out/settings/index.html +1 -1
  250. package/apps/pwa/out/settings/index.txt +23 -23
  251. package/apps/pwa/out/setup/done/index.html +1 -1
  252. package/apps/pwa/out/setup/done/index.txt +23 -23
  253. package/apps/pwa/out/setup/index.html +1 -1
  254. package/apps/pwa/out/setup/index.txt +23 -23
  255. package/apps/pwa/out/share/index.html +1 -1
  256. package/apps/pwa/out/share/index.txt +23 -23
  257. package/apps/pwa/out/showroom/index.html +1 -1
  258. package/apps/pwa/out/showroom/index.txt +22 -22
  259. package/apps/pwa/out/tasks/index.html +1 -1
  260. package/apps/pwa/out/tasks/index.txt +23 -23
  261. package/apps/pwa/out/term/index.html +1 -1
  262. package/apps/pwa/out/term/index.txt +23 -23
  263. package/apps/pwa/out/today/index.html +1 -1
  264. package/apps/pwa/out/today/index.txt +23 -23
  265. package/apps/pwa/out/trace/index.html +1 -1
  266. package/apps/pwa/out/trace/index.txt +23 -23
  267. package/apps/pwa/out/vault/index.html +1 -1
  268. package/apps/pwa/out/vault/index.txt +23 -23
  269. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  270. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  271. package/apps/pwa/out/workflows/index.html +1 -1
  272. package/apps/pwa/out/workflows/index.txt +23 -23
  273. package/apps/pwa/out/workspace/index.html +1 -1
  274. package/apps/pwa/out/workspace/index.txt +23 -23
  275. package/apps/pwa/out/worktrees/index.html +1 -1
  276. package/apps/pwa/out/worktrees/index.txt +23 -23
  277. package/bin/elanous.mjs +7 -3
  278. package/graphs/context/nightly-condense.yaml +1 -0
  279. package/graphs/intake/intake-daily.yaml +8 -1
  280. package/graphs/intake/recipes.yaml +5 -0
  281. package/graphs/lecture/lecture-note.yaml +2 -2
  282. package/graphs/ops/harness-gc.yaml +1 -0
  283. package/graphs/release/recipes.yaml +3 -0
  284. package/graphs/release/release-loop.yaml +9 -5
  285. package/graphs/units/recipes.yaml +3 -0
  286. package/graphs/units/release-gate-recheck.yaml +15 -0
  287. package/package.json +2 -1
  288. package/scripts/check-native-tool-wiring.ts +3 -2
  289. package/scripts/ci-android-unit-tests.ts +16 -0
  290. package/scripts/ci-typecheck-changed.ts +37 -9
  291. package/scripts/coord-channel-watch.sh +22 -16
  292. package/scripts/coord-role-pack.ts +81 -2
  293. package/scripts/cron-run.ts +96 -3
  294. package/scripts/detect-test-interference.ts +38 -5
  295. package/scripts/gate-pr-cache.ts +65 -0
  296. package/scripts/gh-surface/capture.ts +126 -0
  297. package/scripts/gh-surface/gh +40 -0
  298. package/scripts/import-graph-scc.ts +38 -0
  299. package/scripts/install.ps1 +19 -0
  300. package/scripts/intake-social.ts +181 -0
  301. package/scripts/lecture-note/node.ts +71 -4
  302. package/scripts/lib/android-toolchain.ts +32 -0
  303. package/scripts/lib/deterministic-env.ts +62 -0
  304. package/scripts/lib/gate-test-env.ts +19 -0
  305. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  306. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -0
  307. package/scripts/ratchets/test-interference-patterns.ts +367 -0
  308. package/scripts/release-loop/cut-branch.ts +4 -3
  309. package/scripts/release-loop/export-check-node.ts +0 -1
  310. package/scripts/release-loop/fixtures/warm-failure-assertion/sample.junit.xml +8 -0
  311. package/scripts/release-loop/fixtures/warm-job-029/sample.json +1 -0
  312. package/scripts/release-loop/fixtures/warm-job-029/sample.junit.xml +10 -0
  313. package/scripts/release-loop/gate-closure.ts +12 -8
  314. package/scripts/release-loop/gate-diff.ts +1 -1
  315. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  316. package/scripts/release-loop/gate-node.ts +523 -75
  317. package/scripts/release-loop/gate-partial.ts +106 -9
  318. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  319. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  320. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  321. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  322. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  323. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  324. package/scripts/release-loop/import-graph-scc.ts +215 -0
  325. package/scripts/release-loop/node-verdict.ts +2 -0
  326. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  327. package/scripts/release-loop/resume-release.ts +33 -4
  328. package/scripts/release-loop/resume.ts +13 -5
  329. package/scripts/release-loop/spawn-lane.ts +2 -19
  330. package/scripts/release-loop/tui-sim-node.ts +3 -2
  331. package/scripts/release-loop/unattended-release.ts +16 -0
  332. package/scripts/test-deterministic.ts +5 -61
  333. package/scripts/train-reach-grouping.ts +48 -0
  334. package/scripts/tsc-incremental-cache.ts +86 -0
  335. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  336. package/scripts/tsc-main-safety-net.ts +2 -2
  337. package/src/acp/client.ts +4 -1
  338. package/src/acp/core-turn-bridge.ts +50 -5
  339. package/src/ad-pipeline/run.ts +4 -2
  340. package/src/agent/runner.ts +169 -3
  341. package/src/agent/subagent-callable.ts +3 -2
  342. package/src/agent-mission/review-loop.ts +6 -3
  343. package/src/agent-substrate/acp-implementer.ts +14 -2
  344. package/src/agent-substrate/pr-reviewer.ts +12 -0
  345. package/src/agent-substrate/self-review-cli.ts +30 -4
  346. package/src/autopilot/pr-manager.ts +62 -7
  347. package/src/briefing/brief-items.ts +24 -22
  348. package/src/capture/tui-self-report.ts +15 -0
  349. package/src/chat/chat-cli.ts +10 -2
  350. package/src/chat/index.ts +77 -11
  351. package/src/chat/input-control-key.ts +5 -3
  352. package/src/chat/tool-interrupt-behavior.ts +38 -0
  353. package/src/chat/tool-render/dispatch.ts +5 -1
  354. package/src/chat/turn-typeahead.ts +75 -20
  355. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  356. package/src/cli/agent-cli.ts +41 -13
  357. package/src/cli/config-audit.ts +123 -0
  358. package/src/cli/decisions-cli.ts +80 -6
  359. package/src/cli/log-event-names.ts +7 -0
  360. package/src/cli/mcp-login.ts +21 -5
  361. package/src/cli/msg-cli.ts +88 -0
  362. package/src/cli/pr-cli.ts +214 -57
  363. package/src/cli/pr-land-heavy-remote.ts +2 -2
  364. package/src/cli/pr-land-overlap-evidence.ts +63 -9
  365. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  366. package/src/cli/pr-land-pod-shadow.ts +16 -3
  367. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  368. package/src/cli/release-cli.ts +80 -14
  369. package/src/cli/seat-cli.ts +138 -3
  370. package/src/cli/self-update.ts +5 -2
  371. package/src/cli/tasks-cli.ts +97 -19
  372. package/src/context-bus/context-first.ts +13 -0
  373. package/src/context-bus/context-now.ts +13 -2
  374. package/src/context-bus/ops-events.ts +75 -0
  375. package/src/control-plane/lease-holder.ts +12 -8
  376. package/src/control-plane/ledger.ts +163 -4
  377. package/src/control-plane/server.ts +91 -11
  378. package/src/core-turn/run-core-turn.ts +1 -0
  379. package/src/core-turn/run-goal-loop.ts +222 -3
  380. package/src/core-turn/seat-turn-cap.ts +79 -0
  381. package/src/core-turn/short-question.ts +38 -6
  382. package/src/core-turn/types.ts +3 -0
  383. package/src/dashboard/acp-boot.ts +3 -0
  384. package/src/dashboard/index.ts +224 -615
  385. package/src/dashboard/input/chat-main-entry-runtime.ts +1 -1
  386. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +4 -1
  387. package/src/dashboard/input/chat-main-session.ts +8 -1
  388. package/src/dashboard/input/chat-main-turn.ts +12 -3
  389. package/src/dashboard/input/compact-prepass-recovery.ts +33 -0
  390. package/src/dashboard/input/external-input-host.ts +26 -0
  391. package/src/dashboard/input/internal-turn.ts +261 -0
  392. package/src/dashboard/input/seat-autowake.ts +318 -0
  393. package/src/dashboard/input/turn-steer-bridge.ts +70 -0
  394. package/src/dashboard/loop-scheduler.ts +72 -0
  395. package/src/dashboard/seat-boot-preamble.ts +18 -0
  396. package/src/dashboard/skill-runtime.ts +2 -0
  397. package/src/dashboard/slash-runtime/dashboard-handlers.ts +126 -1181
  398. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  399. package/src/dashboard/slash-runtime/index.ts +13 -0
  400. package/src/dashboard/turn-busy-teardown.ts +50 -0
  401. package/src/decisions/decision-ledger.ts +45 -4
  402. package/src/discord-self-message.ts +4 -4
  403. package/src/domains/release-tool.ts +18 -1
  404. package/src/field-note/transcribe.ts +17 -0
  405. package/src/github/remote-call.ts +81 -0
  406. package/src/goals/registry.ts +46 -6
  407. package/src/goals/types.ts +7 -1
  408. package/src/graph-runner/runner.ts +1 -0
  409. package/src/grok/credential.ts +26 -0
  410. package/src/harness/harness-clean.ts +2 -1
  411. package/src/harness/harness-cli-command.ts +52 -5
  412. package/src/harness/harness-gc.ts +2 -1
  413. package/src/harness/harness-incidents.ts +57 -20
  414. package/src/harness/harness-pod-dispatch.ts +87 -10
  415. package/src/harness/harness-queue.ts +53 -4
  416. package/src/harness/harness-stop.ts +4 -3
  417. package/src/harness/harness-substrate-default.ts +78 -7
  418. package/src/harness/harness-worktree-auto.ts +2 -1
  419. package/src/harness/harness-worktrees.ts +3 -2
  420. package/src/hooks/dispatch.ts +2 -1
  421. package/src/index.ts +152 -25
  422. package/src/input/external-input-queue.ts +33 -1
  423. package/src/intake-plane/slash.ts +14 -3
  424. package/src/keybindings.ts +4 -1
  425. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  426. package/src/llm.ts +138 -19
  427. package/src/loops/consensus.ts +348 -0
  428. package/src/loops/msg-wake.ts +206 -4
  429. package/src/loops/observe.ts +19 -3
  430. package/src/loops/orchestrator/tick.ts +64 -10
  431. package/src/loops/orchestrator/traffic.ts +64 -1
  432. package/src/loops/registry.ts +30 -0
  433. package/src/market/signed-index.ts +14 -0
  434. package/src/mcp/mcp-oauth.ts +54 -5
  435. package/src/models/prompts.ts +28 -0
  436. package/src/msg/msg-sse-client.ts +223 -0
  437. package/src/msg/msg-store.ts +86 -2
  438. package/src/mss/logging/log-store.ts +225 -1
  439. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  440. package/src/nexus/api/http-server.ts +54 -15
  441. package/src/nexus/api/loop-resources.ts +19 -3
  442. package/src/nexus/api/ops-api.ts +11 -0
  443. package/src/nexus/daemon-thin-inventory.md +37 -0
  444. package/src/nexus/index.ts +70 -0
  445. package/src/nexus/state/state.ts +1 -0
  446. package/src/oauth/store.ts +32 -7
  447. package/src/onboarding/first-run.ts +28 -3
  448. package/src/ops/overview-cache.ts +16 -4
  449. package/src/ops/resources.ts +82 -0
  450. package/src/plugins/maker/connector-maker.ts +41 -0
  451. package/src/plugins/maker/skill-maker.ts +42 -0
  452. package/src/pr-tool/census.ts +288 -0
  453. package/src/prompt-library/chat-conciseness.ts +13 -0
  454. package/src/prompt-library/universal-preamble.ts +10 -5
  455. package/src/release-loop/gate-host-reservation.ts +97 -0
  456. package/src/release-loop/landing-freeze.ts +5 -0
  457. package/src/release-loop/light-rc.ts +5 -2
  458. package/src/release-loop/placement.ts +92 -1
  459. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  460. package/src/release-loop/rehearsal.ts +73 -17
  461. package/src/repl/index.ts +20 -2
  462. package/src/seat-loop/seat-knowhow.ts +282 -0
  463. package/src/seat-loop/seat-loop.ts +41 -2
  464. package/src/seat-loop/traffic-signal.ts +3 -0
  465. package/src/self-dev/ask-launch-flow.ts +24 -3
  466. package/src/self-dev/decompose-compose-graph.ts +28 -27
  467. package/src/self-dev/decompose-proposal.ts +53 -38
  468. package/src/self-dev/decompose.ts +17 -0
  469. package/src/self-dev/dev-pipeline.ts +31 -2
  470. package/src/self-dev/draft-residue.ts +24 -9
  471. package/src/self-dev/draft-sweep.ts +59 -4
  472. package/src/self-dev/external-call-zero.ts +77 -0
  473. package/src/self-dev/launch-preflight-text.ts +6 -0
  474. package/src/self-dev/launch-preflight.ts +25 -3
  475. package/src/self-dev/local-supervisor-judge.ts +185 -0
  476. package/src/self-dev/run-supervisor.ts +229 -19
  477. package/src/self-dev/run-types.ts +20 -0
  478. package/src/self-dev/shard-aggregate.ts +13 -2
  479. package/src/self-dev/shard-plan.ts +47 -0
  480. package/src/self-dev/shard-run.ts +112 -10
  481. package/src/self-dev/spawn-lane-files.ts +19 -0
  482. package/src/self-implement/app-api-budget.ts +51 -11
  483. package/src/self-implement/config-gate.ts +2 -1
  484. package/src/self-implement/expose-gate.ts +2 -1
  485. package/src/self-implement/gate-artifacts.ts +405 -0
  486. package/src/self-implement/gate-cli.ts +201 -16
  487. package/src/self-implement/gate-remote.ts +110 -25
  488. package/src/self-implement/gate-scenario.ts +85 -0
  489. package/src/self-implement/goal-author.ts +160 -8
  490. package/src/self-implement/graph-authority.ts +38 -6
  491. package/src/self-implement/graph-overlay-condition.ts +92 -1
  492. package/src/self-implement/heal-triage.ts +79 -0
  493. package/src/self-implement/host-regate.ts +61 -3
  494. package/src/self-implement/orchestrator.ts +14 -123
  495. package/src/self-implement/pr-title.ts +123 -0
  496. package/src/self-implement/run-checkpoint.ts +235 -0
  497. package/src/self-implement/run-ledger.ts +155 -10
  498. package/src/self-implement/run-stop.ts +4 -3
  499. package/src/self-implement/run-ttl.ts +28 -4
  500. package/src/self-implement/seams.ts +2 -0
  501. package/src/self-implement/shadow-stage.ts +7 -6
  502. package/src/self-implement/stop-autoheal.ts +2 -1
  503. package/src/self-implement/train-gate-remote.ts +37 -8
  504. package/src/self-implement/train-reach-grouping.ts +157 -0
  505. package/src/self-implement/train-scenario-layers.ts +133 -0
  506. package/src/self-implement/uncommitted-work.ts +2 -0
  507. package/src/session/pending-input.ts +19 -0
  508. package/src/session/session-start.ts +224 -0
  509. package/src/session-runtime/parallel-dispatch.ts +22 -5
  510. package/src/skills/tools/dev-harness.ts +6 -4
  511. package/src/skills/tools/shell.ts +1 -1
  512. package/src/steward/resync-tick.ts +114 -23
  513. package/src/steward/ta-repair-event-collect.ts +158 -0
  514. package/src/task-agent/card-evidence.ts +25 -1
  515. package/src/task-agent/green-sweep.ts +8 -3
  516. package/src/task-agent/judge.ts +76 -0
  517. package/src/task-agent/land-queue.ts +79 -0
  518. package/src/task-agent/live-moves.ts +30 -9
  519. package/src/task-agent/postland-card.ts +5 -0
  520. package/src/task-agent/prelaunch-already-done.ts +98 -0
  521. package/src/task-agent/real-launch-guard.ts +37 -0
  522. package/src/task-agent/rejudge-on-head.ts +89 -12
  523. package/src/task-agent/remote-rejudge-bind.ts +28 -8
  524. package/src/task-agent/repair-cycle.ts +45 -7
  525. package/src/task-agent/repair-worker.ts +7 -0
  526. package/src/task-agent/run-identity.ts +200 -0
  527. package/src/task-agent/shadow.ts +50 -3
  528. package/src/task-agent/task-hand.ts +158 -5
  529. package/src/task-agent/train-landing.ts +77 -0
  530. package/src/task-agent/work-order.ts +104 -0
  531. package/src/task-orchestrator/surfaces/pod-command-job.ts +88 -28
  532. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  533. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  534. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  535. package/src/task-orchestrator/surfaces/pod-install-slots.ts +121 -9
  536. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  537. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  538. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +27 -0
  539. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  540. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  541. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  542. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  543. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  544. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  545. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  546. package/src/task-orchestrator/surfaces/self-implement-pod.ts +132 -15
  547. package/src/telegram.ts +2 -4
  548. package/src/tui/input/pickers.ts +732 -0
  549. package/src/tui/slash/mission.ts +492 -0
  550. package/src/tui/slash/term.ts +877 -0
  551. package/src/tui-client/dashboard-session.ts +9 -0
  552. package/src/tui.ts +48 -0
  553. package/src/user-config/gemini-server-tools.ts +9 -0
  554. package/src/user-config.ts +53 -16
  555. package/src/util/spawn-sync-output.ts +7 -0
  556. package/src/ux-sim/fake-bin.ts +154 -0
  557. package/src/ux-sim/fake-clock.ts +36 -0
  558. package/src/ux-sim/headless-tui.ts +72 -0
  559. package/src/ux-sim/in-process-cli.ts +2 -1
  560. package/src/ux-sim/temp-git-remote.ts +82 -0
  561. package/src/version/packed-revision.json +1 -1
  562. package/src/video-pipeline/recipes/vlog.ts +25 -7
  563. package/apps/pwa/out/_next/static/chunks/1015-9cba22a5a4554797.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/1084-4e66af7376a18db7.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/1106.3a6410b7b0c70ad4.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/1127.32fc642f70423506.js +0 -8
  567. package/apps/pwa/out/_next/static/chunks/1189-d9b8e1995a831fae.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/1224.6da98c7ad0eb7dd8.js +0 -34
  569. package/apps/pwa/out/_next/static/chunks/1370.4e3e2558f111fd5d.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/1514-b7da377fdc4eb17a.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/1577.3c24c32584e10d70.js +0 -286
  572. package/apps/pwa/out/_next/static/chunks/161.130a569855c4d68c.js +0 -24
  573. package/apps/pwa/out/_next/static/chunks/1864.16da9556e78a9236.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/1b6f6b2a.aff090122be3726e.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/2341.e8a9135e5b910dd5.js +0 -36
  576. package/apps/pwa/out/_next/static/chunks/257.10afdbe3520f2fc2.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/2658.87550e692dc493f6.js +0 -64
  578. package/apps/pwa/out/_next/static/chunks/2673.85e2f02efae7a85f.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/2766-bee623b37472ed63.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/2794.6d836872b0bf43e2.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/2806.eb57ced1a528ed39.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/283.7a121c4910e6dad7.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/2870.1dc29aa5fc01f09f.js +0 -115
  584. package/apps/pwa/out/_next/static/chunks/293.fd38e77ce5d48103.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/2993-5952a1cd3fd5d441.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/32-a523427c5bd5ed00.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/3280.af38002a6424a905.js +0 -90
  588. package/apps/pwa/out/_next/static/chunks/3292-5ddffdb2f517b44f.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/3523.d3231daaf7aba993.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/3763.577de3181e1e6ea0.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/4138-cc56b0938ef72783.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/4255-8350c43d307a8875.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/4352.a4954693499c2714.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/4421-f2dcbc6fd80ec013.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/4513-51b94aeee37c9905.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/4928-c3b72f99aa588699.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/4986-f9fc0283fb325219.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/5014.671a7b9f69c2b7b1.js +0 -94
  599. package/apps/pwa/out/_next/static/chunks/5137.d398e24710b3feb6.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/5298.0bea74885cabe754.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/5315.74c53a39739b11c4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/5317-8b1df8d02105cd07.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/5358-33051f41a2b239af.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/5388.a2ec02501f714ad5.js +0 -62
  605. package/apps/pwa/out/_next/static/chunks/5395.e6ac948a2d15058d.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/5409-f282bf533c151849.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/5466.d0f4aba9d52acfa8.js +0 -27
  608. package/apps/pwa/out/_next/static/chunks/5564.3d28b353470fe305.js +0 -104
  609. package/apps/pwa/out/_next/static/chunks/569.b0cbfb4dee4a167a.js +0 -93
  610. package/apps/pwa/out/_next/static/chunks/5835-72465b73a8bb8d74.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/5941.045d6093139e1f7a.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/6228.47cabb83564dfe54.js +0 -24
  613. package/apps/pwa/out/_next/static/chunks/6457-8d1993002a87d0fe.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/6513.ef54cfae52351982.js +0 -2
  615. package/apps/pwa/out/_next/static/chunks/6582.13d245bf87df69f1.js +0 -148
  616. package/apps/pwa/out/_next/static/chunks/6655.c33f6acc2c61bb89.js +0 -149
  617. package/apps/pwa/out/_next/static/chunks/6731-9d7195af289c8d4c.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/6733.0be05b1db9279fc5.js +0 -79
  619. package/apps/pwa/out/_next/static/chunks/6742-90937146253a8b9e.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/687-816858f77a396a4e.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/6888.72c7b8cfb02a7e61.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/6993.c17c828ac3ef3253.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/7076.9f27ef666b0cefdd.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/7113.1403c5d451804e8c.js +0 -287
  625. package/apps/pwa/out/_next/static/chunks/7169.9dd603c726c2cd7c.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/7247-e3ec21f761f86710.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/7261-a47b72f96f5199df.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/7335-5cda81ac90310077.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/7356-c2e4af090546e2d4.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/738-59518742078fda71.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/7385.a7375f10db73243a.js +0 -77
  632. package/apps/pwa/out/_next/static/chunks/7445.cf1cf2fe109bcd96.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/7505.a2057432ab6ef99a.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/7515.31f45fac1f9c70cb.js +0 -74
  635. package/apps/pwa/out/_next/static/chunks/7658-d4ce8c72a9548a91.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/8107-0b1ae46bc5bcb788.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/8132.bfea2f016ce8d992.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/8672.e299832bc7d18ee2.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/8735.f1ef798a5f260f6f.js +0 -226
  640. package/apps/pwa/out/_next/static/chunks/8774-88f67f7d8d53d299.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/8782.252e5a405d86e4ed.js +0 -32
  642. package/apps/pwa/out/_next/static/chunks/909-9ed7aa0dba804316.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/9100.22b0301256827007.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/9140-dde77575570bc71e.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/9292-a7ad9a01c7044b93.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/9517.00627dc51b02821c.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/9725.dcbb585652d8e9c5.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/9761.a3ebf5c389c24ddc.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/9972.834d2b2b7d48f1ed.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/9995-1a90486f5ae01546.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/a435ad95.577add051b4facb2.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-83372d8b5863ebf7.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/approvals/page-d69256d7613c140a.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-352c5e9ba3f9b858.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/board/page-69f1d725524201a8.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/bots/page-ad9181d84285e4ea.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/ceo/page-86feb08080261a2f.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/chat/page-ffa15987e4756d03.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/consult/page-11a3ab44ac327cc1.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/control/page-6309b11c4264d24d.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/decisions/page-8800472079612e87.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/design-check/page-d387bf3f2301882a.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/editor/page-048f88d8c8658da6.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/exec/page-6c14f9739b7f6880.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/field/page-2834f44f64e98d74.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/healthz/route-83372d8b5863ebf7.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/inside/page-a13df6f88e824887.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/intake/page-8a4397248754cf2b.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/layout-daf0bd329360a336.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/live/page-f7ef1c28764cb476.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/live-run/page-61e74f28b9353dac.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/loops/page-8aaa6dedc4c10dfb.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/market/page-294602ba649be829.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-5fa5f41ed3fce323.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/app/morning/page-33bf667a5fb297bf.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/app/not-found-5ae3cbd6e5dba515.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/app/observatory/page-eb867d16ad6fdede.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-1ab789fa68682f7e.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-6fd41b5b6ff13a71.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fb3d5f7642c99fba.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/app/outputs/page-70f705b2b5ed42ca.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/page-c9c93b358a7667b5.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1563c556b81c96ed.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-ce89c20c45b3a673.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/sessions/page-423ae63d786f4ee9.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-591a5378a4c4447c.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/settings/page-a250496b19a5824b.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-c36a9277febc5911.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/setup/layout-83372d8b5863ebf7.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/share/page-a5de57edc6d7f942.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/showroom/page-16bdd4c9f40498df.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/tasks/page-75e946e6e71cc6d8.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/term/page-9eb56166774eb256.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/today/page-1c5f9ef35dbb22c5.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/trace/page-657ff9985e508498.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/vault/page-22dc72499da68fb2.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/workflows/page-094ad334e40f8169.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/workspace/page-8bcd379852ff6287.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-6b04413f280cd344.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/de70ab42-d28d47437208d458.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/f800c5e3.46dbd7f2af8c3fce.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/f8bc19ad.47579f6d684b0760.js +0 -122
  703. package/apps/pwa/out/_next/static/chunks/framework-ca9ac4609fb9fed8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/main-app-0dd08d32d15a030f.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/main-f0399d33955c4e01.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/pages/_app-d42caca6f8ac2211.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/pages/_error-42e713c13aa41ca8.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/webpack-8fbf8f61a377aa16.js +0 -1
  709. /package/apps/pwa/out/_next/static/{cIpv5nU9AycwYWZI9H589 → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -11,6 +11,9 @@ gate:
11
11
  command: 'bun scripts/release-loop/gate-node.ts --json'
12
12
  # 4h — the Pod gate took 2h02m on 09-30 (G1f ②) and the 0.2.5 loop was cut at exactly 2h with no verdict; K9 (≤15 min) is the real fix.
13
13
  timeout_ms: 14400000
14
+ gate-triage:
15
+ command: 'bun scripts/release-loop/gate-triage-node.ts'
16
+ timeout_ms: 60000
14
17
  mac-smoke:
15
18
  command: 'bun scripts/release-loop/mac-smoke-node.ts'
16
19
  timeout_ms: 1800000
@@ -15,10 +15,13 @@ nodes:
15
15
  - { node_id: cutoff, kind: judge, recipe: 'cmd:cutoff', max_visits: 1 }
16
16
  - { node_id: checklist-gate, kind: gate, recipe: 'cmd:checklist-gate', max_visits: 1 }
17
17
  # cmd:docs dispatches by graph node ID: bounded prefetch before gate, TUI join after upgrade, docs write after both.
18
+ # Public export is checked before expensive prefetch/gate work; a leak stops the release immediately.
19
+ - { node_id: export-check, kind: gate, recipe: 'cmd:export-check', max_visits: 1 }
18
20
  - { node_id: prefetch, kind: agent, recipe: 'cmd:docs', max_visits: 1 }
19
21
  - { node_id: gate, kind: gate, recipe: 'cmd:gate', max_visits: 1, notify: { on: [fail] } }
22
+ # S1 shadow: classify and record only; all exits still terminate through the existing failed node.
23
+ - { node_id: gate-triage, kind: judge, recipe: 'cmd:gate-triage', max_visits: 1 }
20
24
  - { node_id: mac-smoke, kind: gate, recipe: 'cmd:mac-smoke', max_visits: 1 }
21
- - { node_id: export-check, kind: gate, recipe: 'cmd:export-check', max_visits: 1 }
22
25
  - { node_id: pwa, kind: gate, recipe: 'cmd:pwa', max_visits: 1, notify: { on: [fail] } }
23
26
  - { node_id: prepare, kind: agent, recipe: 'cmd:prepare', max_visits: 1, notify: { on: [fail] } }
24
27
  - { node_id: upgrade, kind: gate, recipe: 'cmd:upgrade', max_visits: 1 }
@@ -42,13 +45,14 @@ nodes:
42
45
  edges:
43
46
  - { from: version-release, on: outcome, map: { ok: cutoff, fail: failed, error: failed } }
44
47
  - { from: cutoff, on: outcome, map: { ok: checklist-gate, fail: failed, error: failed } }
45
- - { from: checklist-gate, on: outcome, map: { ok: prefetch, fail: failed, error: failed } }
48
+ - { from: checklist-gate, on: outcome, map: { ok: export-check, fail: failed, error: failed } }
49
+ - { from: export-check, on: outcome, map: { ok: prefetch, fail: failed, error: failed } }
46
50
  # Prefetch never gates: even a crashed prefetch node is a cache miss — the late nodes take their original paths.
47
51
  - { from: prefetch, on: outcome, map: { ok: gate, fail: gate, error: gate } }
48
- - { from: gate, on: outcome, map: { ok: mac-smoke, fail: failed, error: failed } }
52
+ - { from: gate, on: outcome, map: { ok: mac-smoke, fail: gate-triage, error: gate-triage } }
53
+ - { from: gate-triage, on: outcome, map: { ok: failed, fail: failed, error: failed } }
49
54
  # Warning-only: a macOS failure or unmeasured run never blocks publishing — auto-approve shows it as a warning row.
50
- - { from: mac-smoke, on: outcome, map: { ok: export-check, fail: export-check, error: export-check } }
51
- - { from: export-check, on: outcome, map: { ok: pwa, fail: failed, error: failed } }
55
+ - { from: mac-smoke, on: outcome, map: { ok: pwa, fail: pwa, error: pwa } }
52
56
  - { from: pwa, on: outcome, map: { ok: prepare, fail: failed, error: failed } }
53
57
  - { from: prepare, on: outcome, map: { ok: upgrade, fail: failed, error: failed } }
54
58
  - { from: upgrade, on: outcome, map: { ok: tui, fail: failed, error: failed } }
@@ -0,0 +1,3 @@
1
+ plan:
2
+ command: 'bun scripts/release-loop/gate-recheck-plan-node.ts'
3
+ timeout_ms: 60000
@@ -0,0 +1,15 @@
1
+ # Shadow G1 unit: plan only. TC connects gate-node's existing sweep to kind: recheck after #27800.
2
+ graph_id: release-gate-recheck
3
+ version: 1
4
+ unit:
5
+ inputs: [version, commit, measuredCommit, failures, errors, ledgerRoot]
6
+ outputs: [planPath, files]
7
+ exits: [done, failed]
8
+ entry_node: plan
9
+ terminal_nodes: [done, failed]
10
+ nodes:
11
+ - { node_id: plan, kind: agent, recipe: 'cmd:plan', max_visits: 1 }
12
+ - { node_id: done, kind: gate, recipe: none, max_visits: 1 }
13
+ - { node_id: failed, kind: gate, recipe: none, max_visits: 1 }
14
+ edges:
15
+ - { from: plan, on: outcome, map: { ok: done, fail: failed } }
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "elanous",
3
3
  "mcpName": "io.github.ElanvitalAI/elanous",
4
- "version": "0.2.29",
4
+ "version": "0.2.31",
5
5
  "description": "Self-healing coding harness where eyes, hands, and memory all turn on one sentence — it authors its own goals, implements them in isolated worktrees, and reviews its own work.",
6
6
  "license": "Apache-2.0",
7
7
  "author": "Elanvital AI",
@@ -129,6 +129,7 @@
129
129
  "telegram": "^2.26.22"
130
130
  },
131
131
  "devDependencies": {
132
+ "@copilotkit/aimock": "1.45.1",
132
133
  "@types/bun": "^1.2.0",
133
134
  "@types/diff": "^8.0.0",
134
135
  "@types/node-cron": "^3.0.11",
@@ -28,6 +28,7 @@
28
28
  import { readFileSync } from 'node:fs';
29
29
  import { resolve } from 'node:path';
30
30
  import { nativeToolCatalog } from '../src/native-tool-catalog.js';
31
+ import { TUI_SOURCE_DIRS, tuiSourceText } from '../test/helpers/dashboard-source.js';
31
32
 
32
33
  const verbose = process.argv.includes('--verbose');
33
34
  const strict = process.argv.includes('--strict');
@@ -68,7 +69,7 @@ const SKIP_TOOLS: ReadonlySet<string> = new Set([
68
69
  // ⇒ 그러므로 이 스크립트가 내는 issue 수는 «결함 수가 아니라 이 자로 잰 수»다. 분류는 후속.
69
70
  const root = resolve(import.meta.dir, '..');
70
71
  const skillDispatchSrc = readFileSync(resolve(root, 'src/tool-runtime/registry.ts'), 'utf8');
71
- const tuiSrc = readFileSync(resolve(root, 'src/dashboard/index.ts'), 'utf8');
72
+ const tuiSrc = tuiSourceText(root); // TUI 소스 묶음(src/dashboard/** ⊕ src/tui/**) — 경로 무관
72
73
 
73
74
  interface Issue { tool: string; surface: string; kind: 'missing' | 'extra'; detail: string; }
74
75
 
@@ -103,7 +104,7 @@ for (const entry of nativeToolCatalog) {
103
104
  tool: entry.id,
104
105
  surface: 'tui',
105
106
  kind: 'missing',
106
- detail: `dashboard/index.ts does not mention alias "${pascal}" (catalog lists host:'tui')`,
107
+ detail: `TUI source bundle (${TUI_SOURCE_DIRS.join(' + ')}) does not mention alias "${pascal}" (catalog lists host:'tui')`,
107
108
  });
108
109
  }
109
110
  }
@@ -26,6 +26,7 @@
26
26
  import { existsSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
27
27
  import { join, resolve } from 'node:path';
28
28
  import { spawnSync } from 'node:child_process';
29
+ import { androidToolchainMissing } from './lib/android-toolchain.js';
29
30
 
30
31
  const ROOT = join(import.meta.dir, '..');
31
32
 
@@ -225,6 +226,8 @@ export type AndroidGateIo = {
225
226
  readonly cwd?: string;
226
227
  readonly log?: (line: string) => void;
227
228
  readonly error?: (line: string) => void;
229
+ /** 툴체인 판정 심 — 기본은 bun 시험의 skip 관문과 «같은» `androidToolchainMissing()`. 다 있으면 null. */
230
+ readonly toolchainMissing?: () => string | null;
228
231
  /** 시험 실행 심 — 시험에서 주입한다. */
229
232
  readonly runGradle?: (androidDir: string) => { readonly status: number | null; readonly output: string };
230
233
  /** 결과 XML 읽기 심. */
@@ -382,6 +385,19 @@ export function runAndroidUnitTestGate(io: AndroidGateIo = {}): number {
382
385
  log(`[android-gate] 해당 없음 — 변경 ${changed.length}개 중 ${ANDROID_PREFIX} 아래 파일 0개.`);
383
386
  return 0;
384
387
  }
388
+ // ⭐ R5a(0.2.31 · OP #8961): 바뀐 안드로이드 파일이 «전부» bun 시험(.test.ts)이고 이 호스트에 툴체인이 없으면
389
+ // Gradle 축은 «측정 대상 아님»이다 — 그 파일들은 Kotlin 컴파일러가 안 읽어 Gradle 결과를 못 바꾸고,
390
+ // 그 자체는 bun 러너가 잰다(툴체인이 없으면 시험이 «전제 없음» 이유를 찍고 skip).
391
+ // ⛔ 「Gradle 통과」로 말하지 않는다. Kotlin·Gradle 설정이 하나라도 바뀌었으면 아래 기존 판정(0 = 실패) 그대로다.
392
+ // 면제는 «Kotlin 소스셋 안»의 bun 시험만이다(`androidKotlinSourcesetTestTsFiles` · r2 리뷰) — 그 밖의 .test.ts 는 기존 판정.
393
+ if (androidKotlinSourcesetTestTsFiles(hits).length === hits.length) {
394
+ const missing = (io.toolchainMissing ?? androidToolchainMissing)();
395
+ if (missing) {
396
+ log(`[android-gate] 측정 대상 아님 — 이 호스트에 안드로이드 툴체인이 없다: ${missing}`);
397
+ log(` 바뀐 안드로이드 파일 ${hits.length}개가 전부 bun 시험(.test.ts)이라 Gradle 결과를 바꾸지 못한다 — 그 시험은 bun 러너가 잰다. ⛔ 「Gradle 통과」가 아니라 「Gradle 안 잼」이다.`);
398
+ return 0;
399
+ }
400
+ }
385
401
  log(`[android-gate] 대상 ${hits.length}개 (변경 ${changed.length}개 중) — 시험을 돌린다.`);
386
402
  }
387
403
 
@@ -25,6 +25,7 @@ import {
25
25
  type BaselineCacheOptions,
26
26
  } from './tsc-baseline-cache.js';
27
27
  import { TSC_OOM_RETRY_HEAP_MB, TSC_HEAP_MB, tscEnv } from '../src/typecheck-ratchet.js';
28
+ import { runIncrementalCachedTsc } from './tsc-incremental-cache.js';
28
29
 
29
30
  /** Inherited GIT_DIR / GIT_WORK_TREE would make `--cwd <other tree>` still read the launcher's repo. */
30
31
  function gitEnv(base: NodeJS.ProcessEnv = process.env): NodeJS.ProcessEnv {
@@ -49,7 +50,7 @@ function sh(cmd: string, cwd = process.cwd()): string {
49
50
  return execSync(cmd, { encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'], cwd, env: gitEnv() });
50
51
  }
51
52
 
52
- export type TscRun = { out: string; ran: boolean; why?: string };
53
+ export type TscRun = { out: string; ran: boolean; why?: string; exitCode?: number };
53
54
 
54
55
  export { TSC_HEAP_MB, TSC_OOM_RETRY_HEAP_MB, tscEnv } from '../src/typecheck-ratchet.js';
55
56
  /** V8 힙 부족의 얼굴 — 「타입 에러」와 «다른 값»이다. */
@@ -70,7 +71,7 @@ export function runTsc(cmd: string, exec = execSync): TscRun {
70
71
  const result = (attempt: Attempt, env: NodeJS.ProcessEnv): TscRun => {
71
72
  const { out, error: e } = attempt;
72
73
  if (OOM.test(out)) return { out, ran: false, why: `tsc 가 V8 힙 부족(OOM)으로 죽었다 — 타입 에러가 아니다 (NODE_OPTIONS=${env.NODE_OPTIONS})` };
73
- if (!e) return { out, ran: true };
74
+ if (!e) return { out, ran: true, exitCode: 0 };
74
75
  if (e.signal || e.code === 'ENOENT' || e.status === null || e.status === undefined) {
75
76
  return { out, ran: false, why: `tsc 실행 실패 (signal=${String(e.signal)} code=${String(e.code)} status=${String(e.status)})` };
76
77
  }
@@ -81,7 +82,7 @@ export function runTsc(cmd: string, exec = execSync): TscRun {
81
82
  if (!/error TS\d+/.test(out)) {
82
83
  return { out, ran: false, why: `tsc 가 종료코드 ${e.status} 로 끝났는데 TS 진단이 한 건도 없다(래퍼 실패로 본다)` };
83
84
  }
84
- return { out, ran: true };
85
+ return { out, ran: true, exitCode: e.status };
85
86
  };
86
87
 
87
88
  const initialEnv = tscEnv();
@@ -140,6 +141,10 @@ export function changedTsFiles(run: (cmd: string) => string = sh, env: NodeJS.Pr
140
141
  const quietRevision = (command: string): string => { try { return run(command).trim(); } catch { return ''; } };
141
142
  const head = quietRevision('git rev-parse HEAD') || undefined;
142
143
  const warnings: string[] = [];
144
+ // base==HEAD ⊕ HEAD 가 origin/main 의 조상(merge-base 가 HEAD 자신) — 아래 수집이 git diff --name-only HEAD
145
+ // (커밋 안 된 변경) ⊕ git ls-files --others(untracked) 를 계속 모으므로 «변경을 셀 수 없다» 판정은
146
+ // 그 수집 결과에 따라 갈린다. 결정만 여기서 미뤄 수집 뒤에 넣는다.
147
+ let uncountableBase: { command: string; why: string } | undefined;
143
148
  if (head && quietRevision(`git rev-parse ${base}`) === head) {
144
149
  const main = quietRevision('git rev-parse origin/main');
145
150
  const merged = main && main !== head ? quietRevision('git merge-base HEAD origin/main') : '';
@@ -148,14 +153,18 @@ export function changedTsFiles(run: (cmd: string) => string = sh, env: NodeJS.Pr
148
153
  base = merged;
149
154
  baseSource = 'recomputed merge-base(origin/main)';
150
155
  } else if (main && main !== head) {
151
- failures.push({ command: `git rev-parse ${base}`, why: `base 가 HEAD(${head}) 와 같아 변경을 셀 수 없다 — TSC_BASE_REF 로 base 를 주라 (못 셌음 ≠ 0)` });
156
+ uncountableBase = { command: `git rev-parse ${base}`, why: `base 가 HEAD(${head}) 와 같아 변경을 셀 수 없다 — TSC_BASE_REF 로 base 를 주라 (못 셌음 ≠ 0)` };
152
157
  }
153
158
  }
154
159
 
155
160
  const files = new Set<string>();
156
161
  const diffFiles = new Set<string>();
162
+ // 커밋 안 된 변경 ⊕ untracked 를 내는 명령 — uncountableBase 판정의 분모다.
163
+ const dirtyCommands = new Set(['git diff --name-only HEAD', 'git ls-files --others --exclude-standard']);
164
+ let dirtyCount = 0;
157
165
  const commands = [`git diff --name-only ${base}...HEAD`, 'git diff --name-only HEAD', 'git ls-files --others --exclude-standard'];
158
166
  for (const command of commands) {
167
+ const countsDirty = uncountableBase !== undefined && dirtyCommands.has(command);
159
168
  try {
160
169
  for (const line of run(command).split('\n')) {
161
170
  const file = line.trim().replace(/^\.\//, '');
@@ -164,13 +173,22 @@ export function changedTsFiles(run: (cmd: string) => string = sh, env: NodeJS.Pr
164
173
  // A deleted .ts is not a compile candidate, so it must not count as «should have been collected».
165
174
  // existsSync is bound to the landing tree — process.cwd() would count the launcher's files.
166
175
  const present = existsSync(join(cwd, file));
167
- if (!ts || present) diffFiles.add(file);
176
+ if ((!ts || present) && !diffFiles.has(file)) {
177
+ diffFiles.add(file);
178
+ if (countsDirty) dirtyCount += 1;
179
+ }
168
180
  if (ts && present) files.add(file);
169
181
  }
170
182
  } catch (cause) {
171
183
  failures.push({ command, why: cause instanceof Error ? cause.message : String(cause) });
172
184
  }
173
185
  }
186
+ if (uncountableBase) {
187
+ // 커밋 안 된 변경·untracked 를 1개라도 셌으면 그 수(N)와 baseSource 를 경고에 실어 판정을 지속한다 —
188
+ // «못 셌음 ≠ 0» 실패는 둘 다 0일 때만 그대로 남긴다.
189
+ if (dirtyCount > 0) warnings.push(`base=HEAD — 커밋 안 된 변경 ${dirtyCount} 개만 센다 (baseSource=${baseSource})`);
190
+ else failures.push(uncountableBase);
191
+ }
174
192
  return { files, base, baseSource, head, diffFiles, warnings, failures };
175
193
  }
176
194
 
@@ -1144,13 +1162,22 @@ export function runGate(io: Partial<GateIo> = {}): void {
1144
1162
  const rootCommand = `${tscBin} --noEmit -p ${TYPECHECK_GATE_CONFIG}`;
1145
1163
  const pwaCommand = `${tscBin} --noEmit -p apps/pwa/tsconfig.json`;
1146
1164
  const pwaEnvCommand = `${tscBin} --noEmit -p tsconfig.pwa-env.json`;
1165
+ const cacheDir = (io.env ?? process.env).ELANOUS_TSC_CACHE_DIR;
1166
+ const cacheEnabled = !!cacheDir && !io.runTscCmd && base !== 'injected test seam';
1167
+ const checkedTsc = (command: string, config: string, scope: ReadonlySet<string>, excluded: readonly string[], included: readonly string[], promotionBaseline?: BaselineDiagnostics, excludeTests = false): TscRun => {
1168
+ if (!cacheEnabled) return runTscCmd(command);
1169
+ return runIncrementalCachedTsc({
1170
+ cwd, base, head, changed, config, command, cacheDir: cacheDir!, run: runTscCmd, log,
1171
+ decision: (result) => result.ran && inspectTscResult(result, scope, baseline, () => {}, () => {}, wholeRepository, excluded, included, promotionBaseline, excludeTests),
1172
+ });
1173
+ };
1147
1174
  const rootPromotionBaseline = wholeRepository ? readBaselineDiagnostics(base, rootCommand) : undefined;
1148
1175
  const pwaPromotionBaseline = wholeRepository && runsPwa ? readBaselineDiagnostics(base, pwaCommand) : undefined;
1149
1176
  const pwaEnvPromotionBaseline = wholeRepository && runsPwaEnv ? readBaselineDiagnostics(base, pwaEnvCommand) : undefined;
1150
1177
  let rootPlan = planRootCheck({ wholeRepository, rootChanged, env: io.env ?? process.env, cwd, affectedRoots: io.affectedRoots ?? reverseImportAffectedRoots });
1151
1178
  let rootsConfig: string | undefined;
1152
1179
  if (rootPlan.mode === 'affected') {
1153
- rootsConfig = `tsconfig.gate-roots.${process.pid}.${Date.now()}.json`;
1180
+ rootsConfig = cacheEnabled ? 'tsconfig.gate-roots.incremental.json' : `tsconfig.gate-roots.${process.pid}.${Date.now()}.json`;
1154
1181
  try {
1155
1182
  // `include` is replaced (not merged) so only the listed roots plus ambient declarations enter the program.
1156
1183
  writeFileSync(join(cwd, rootsConfig), JSON.stringify({ extends: `./${TYPECHECK_GATE_CONFIG}`, include: ['src/**/*.d.ts', 'scripts/**/*.d.ts', 'test/**/*.d.ts'], files: rootPlan.roots }, null, 2), { flag: 'wx' });
@@ -1173,19 +1200,20 @@ export function runGate(io: Partial<GateIo> = {}): void {
1173
1200
  debug.log('typecheck.gate', 'roots', { mode: 'full', roots: rootPlan.roots ?? null, fallbackReason: rootPlan.fallbackReason }, { level: 'info' });
1174
1201
  }
1175
1202
  let rootTsc: TscRun;
1176
- try { rootTsc = runTscCmd(rootsConfig ? `${tscBin} --noEmit -p ${rootsConfig}` : rootCommand); }
1203
+ try { rootTsc = checkedTsc(rootsConfig ? `${tscBin} --noEmit -p ${rootsConfig}` : rootCommand,
1204
+ rootsConfig ?? TYPECHECK_GATE_CONFIG, rootScope, ['apps/pwa/'], [], rootPromotionBaseline); }
1177
1205
  finally { if (rootsConfig) rmSync(join(cwd, rootsConfig), { force: true }); }
1178
1206
  let unmeasured = !rootTsc.ran;
1179
1207
  let passed = inspectTscResult(rootTsc, rootScope, baseline, error, warn, wholeRepository, ['apps/pwa/'], [], rootPromotionBaseline);
1180
1208
  if (runsPwa) {
1181
1209
  log(`[tsc-gate] PWA 변경 ${pwaChanged.size}개 관측 — apps/pwa/tsconfig.json 검사.`);
1182
- const pwaTsc = runTscCmd(pwaCommand);
1210
+ const pwaTsc = checkedTsc(pwaCommand, 'apps/pwa/tsconfig.json', pwaScope, [], ['apps/pwa/'], pwaPromotionBaseline);
1183
1211
  unmeasured = unmeasured || !pwaTsc.ran;
1184
1212
  passed = inspectTscResult(pwaTsc, pwaScope, baseline, error, warn, wholeRepository, [], ['apps/pwa/'], pwaPromotionBaseline) && passed;
1185
1213
  }
1186
1214
  if (runsPwaEnv) {
1187
1215
  log(`[tsc-gate] PWA env 패스 — 루트 비시험 ${nonTestRootChanged.size}개 (Next ProcessEnv 선언 포함).`);
1188
- const pwaEnvTsc = runTscCmd(pwaEnvCommand);
1216
+ const pwaEnvTsc = checkedTsc(pwaEnvCommand, 'tsconfig.pwa-env.json', pwaEnvScope, ['apps/pwa/'], [], pwaEnvPromotionBaseline, true);
1189
1217
  unmeasured = unmeasured || !pwaEnvTsc.ran;
1190
1218
  passed = inspectTscResult(pwaEnvTsc, pwaEnvScope, baseline, error, warn, wholeRepository, ['apps/pwa/'], [], pwaEnvPromotionBaseline, true) && passed;
1191
1219
  }
@@ -49,16 +49,35 @@
49
49
  set -u
50
50
  set -o pipefail
51
51
 
52
+ # WATCH1: help must still report a fixed token, even when the archived manual
53
+ # no longer has a current channel heading.
54
+ if [ -n "${GH_TOKEN:-}${GITHUB_TOKEN:-}" ]; then
55
+ if [ "${WATCH_KEEP_TOKEN:-}" = "1" ]; then
56
+ echo "⚠️ [watch] GH_TOKEN/GITHUB_TOKEN 고정 토큰으로 읽는다(WATCH_KEEP_TOKEN=1) — 만료되면 «⛔ 조회 실패» 줄이 뜬다"
57
+ else
58
+ echo "⚠️ [watch] GH_TOKEN/GITHUB_TOKEN 이 들어 있어 비웠다 — 읽기는 keyring gh 인증으로(고정 토큰은 만료돼 감시가 눈이 먼다 · WATCH1)"
59
+ unset GH_TOKEN GITHUB_TOKEN
60
+ fi
61
+ fi
62
+
63
+ for arg in "$@"; do
64
+ case "$arg" in -h|--help)
65
+ echo '⛔ PR 조율 채널은 퇴역했다. 자리 간 소통은 eln msg post/list 를 사용한다.'
66
+ sed -n '1,40p' "$0"
67
+ exit 0 ;;
68
+ esac
69
+ done
70
+
52
71
  SCRIPT_DIR=$(CDPATH= cd -- "$(dirname -- "$0")" && pwd) || { echo '⛔ 스크립트 위치를 못 읽었다' >&2; exit 3; }
53
72
  CANON="$SCRIPT_DIR/../docs/manual/MANUAL-multi-agent-coordination-channel-2026-07-28.md"
54
73
  resolve_pr() {
55
74
  [ -f "$CANON" ] || return 3
56
75
  # 머리말의 실제 인용 제목만 읽는다. 설명·과거 채널·손상된 제목에서 추측하지 않는다.
57
76
  head -40 "$CANON" | awk '
58
- /^> ## / && /현재 채널/ {
77
+ /^> ## / && /마지막 채널/ {
59
78
  count++
60
- if ($0 !~ /^> ## .*현재 채널 = \[PR #[0-9]+\]\(https:\/\/github\.com\/ElanvitalAI\/elanous-agent\/pull\/[0-9]+\)/) { bad=1; next }
61
- id=$0; sub(/^.*현재 채널 = \[PR #/, "", id); sub(/\].*$/, "", id)
79
+ if ($0 !~ /^> ## .*마지막 채널 = \[PR #[0-9]+\]\(https:\/\/github\.com\/ElanvitalAI\/elanous-agent\/pull\/[0-9]+\)/) { bad=1; next }
80
+ id=$0; sub(/^.*마지막 채널 = \[PR #/, "", id); sub(/\].*$/, "", id)
62
81
  url=$0; sub(/^.*\]\(https:\/\/github\.com\/ElanvitalAI\/elanous-agent\/pull\//, "", url); sub(/\).*$/, "", url)
63
82
  if (id != url) bad=1
64
83
  }
@@ -100,18 +119,6 @@ WATCH_EXIT_ANNOUNCED=0 # 종료 줄 중복 방지(INT→EXIT 로 trap 이 두
100
119
  # 「거의 비었다」로 «의심»할 자수 — 이 아래로 떨어지면 «변경»이 아니라 «의심»으로 말한다.
101
120
  BODY_MIN="${CH_BODY_MIN:-100}"
102
121
 
103
- # ⛔⭐ WATCH1(10-03 MK 6시간 실명): 감시자에 고정 토큰(GH_TOKEN·GITHUB_TOKEN — App 토큰은 1시간)을 넣어 띄우면
104
- # 만료 뒤 조회가 조용히 계속 실패한다. 읽기는 신원이 필요 없다 ⇒ 고정 토큰을 «비우고» keyring gh 인증으로 읽는다.
105
- # 그 토큰을 꼭 써야 하면 WATCH_KEEP_TOKEN=1 (그때도 경고 줄은 낸다).
106
- if [ -n "${GH_TOKEN:-}${GITHUB_TOKEN:-}" ]; then
107
- if [ "${WATCH_KEEP_TOKEN:-}" = "1" ]; then
108
- echo "⚠️ [watch] GH_TOKEN/GITHUB_TOKEN 고정 토큰으로 읽는다(WATCH_KEEP_TOKEN=1) — 만료되면 «⛔ 조회 실패» 줄이 뜬다"
109
- else
110
- echo "⚠️ [watch] GH_TOKEN/GITHUB_TOKEN 이 들어 있어 비웠다 — 읽기는 keyring gh 인증으로(고정 토큰은 만료돼 감시가 눈이 먼다 · WATCH1)"
111
- unset GH_TOKEN GITHUB_TOKEN
112
- fi
113
- fi
114
-
115
122
  CMD="ensure"
116
123
  TRACK=""
117
124
  ADOPT_PID=""
@@ -121,7 +128,6 @@ while [ $# -gt 0 ]; do
121
128
  ensure|status|stop|restart|adopt|discover|delivery) CMD="$1" ;;
122
129
  --track) shift; TRACK="${1:-}" ;;
123
130
  --pid) shift; ADOPT_PID="${1:-}" ;;
124
- -h|--help) sed -n '1,40p' "$0"; exit 0 ;;
125
131
  *) echo "⛔ 모르는 인자: $1" >&2; exit 2 ;;
126
132
  esac
127
133
  shift
@@ -2,6 +2,7 @@
2
2
  import { createHash } from 'node:crypto';
3
3
  import { existsSync, readFileSync } from 'node:fs';
4
4
  import { resolve } from 'node:path';
5
+ import { KnowhowLintError, lintKnowhow } from '../src/seat-loop/knowhow-lint.js';
5
6
 
6
7
  export type RolePackRole = 'coordinator' | 'guardian';
7
8
 
@@ -10,6 +11,7 @@ export interface RolePack {
10
11
  version: string;
11
12
  sha256: string;
12
13
  body: string;
14
+ /** Built-in C/G rule identifiers; verified KNOWHOW identifiers appear in the body. */
13
15
  includedCardIds: string[];
14
16
  excludedCardIds: string[];
15
17
  sources: Array<{ path: string; sha256: string }>;
@@ -17,6 +19,76 @@ export interface RolePack {
17
19
  missingSources: string[];
18
20
  }
19
21
 
22
+ const KNOWHOW_PATH = 'docs/roles/OP/KNOWHOW.md';
23
+
24
+ /**
25
+ * KNOWHOW.md 를 `##` 제목 단위 카드로 자른다(코드 울타리 안은 본문으로 본다).
26
+ * 유효한 `## K-<role>-<number>` 제목을 가진 카드만 반환한다.
27
+ */
28
+ export function splitKnowhowCards(body: string): Array<{ id: string; title: string; text: string }> {
29
+ const segments: Array<{ heading: string | null; lines: string[] }> = [{ heading: null, lines: [] }];
30
+ let fence: { marker: string; length: number } | null = null;
31
+ for (const line of body.split(/\r?\n/u)) {
32
+ const fenceLine = line.match(/^ {0,3}(`{3,}|~{3,})(.*)$/u);
33
+ if (fence) {
34
+ if (fenceLine && fenceLine[1]![0] === fence.marker && fenceLine[1]!.length >= fence.length && /^[ \t]*$/u.test(fenceLine[2]!)) fence = null;
35
+ segments.at(-1)!.lines.push(line);
36
+ continue;
37
+ }
38
+ if (fenceLine) {
39
+ fence = { marker: fenceLine[1]![0]!, length: fenceLine[1]!.length };
40
+ segments.at(-1)!.lines.push(line);
41
+ continue;
42
+ }
43
+ if (/^##\s/u.test(line)) {
44
+ segments.push({ heading: line, lines: [] });
45
+ continue;
46
+ }
47
+ segments.at(-1)!.lines.push(line);
48
+ }
49
+ const cards: Array<{ id: string; title: string; text: string }> = [];
50
+ for (const segment of segments) {
51
+ if (!segment.heading) continue;
52
+ const heading = segment.heading.match(/^##\s+(K-[A-Za-z]+-\d+)\s*(.*)$/u);
53
+ if (!heading) continue;
54
+ cards.push({ id: heading[1]!, title: heading[2]!.trim(), text: [segment.heading, ...segment.lines].join('\n') });
55
+ }
56
+ return cards;
57
+ }
58
+
59
+ /**
60
+ * KNOWHOW 카드 중 src/seat-loop/knowhow-lint.ts 의 린트를 통과한 항목만 검증된 출처로 싣는다.
61
+ * 실패 항목(비밀값 포함)은 제외하고 그 아이디만 남긴다. 파일이 없으면 아무것도 싣지 않는다.
62
+ */
63
+ export function collectVerifiedKnowhow(repo: string): {
64
+ included: Array<{ id: string; title: string; text: string }>;
65
+ excluded: string[];
66
+ fileBody: string | null;
67
+ } {
68
+ let body: string;
69
+ try {
70
+ body = readFileSync(resolve(repo, KNOWHOW_PATH), 'utf8');
71
+ } catch (error) {
72
+ if ((error as NodeJS.ErrnoException).code === 'ENOENT') return { included: [], excluded: [], fileBody: null };
73
+ throw error;
74
+ }
75
+ const included: Array<{ id: string; title: string; text: string }> = [];
76
+ const excluded: string[] = [];
77
+ for (const card of splitKnowhowCards(body)) {
78
+ try {
79
+ lintKnowhow(card.text, KNOWHOW_PATH);
80
+ included.push({ id: card.id, title: card.title, text: card.text });
81
+ } catch (error) {
82
+ if (error instanceof KnowhowLintError) {
83
+ excluded.push(card.id);
84
+ continue;
85
+ }
86
+ throw error;
87
+ }
88
+ }
89
+ return { included, excluded, fileBody: body };
90
+ }
91
+
20
92
  const SOURCE_PATHS = [
21
93
  'AGENTS.md',
22
94
  'docs/roles/OP.md',
@@ -70,6 +142,8 @@ export function buildCoordRolePackManifest(role: RolePackRole, root = resolve(im
70
142
  const present = SOURCE_PATHS.filter((path) => existsSync(resolve(repo, path)));
71
143
  const missingSources = SOURCE_PATHS.filter((path) => !present.includes(path));
72
144
  const sources = present.map((path) => ({ path, sha256: sha256(readFileSync(resolve(repo, path), 'utf8')) }));
145
+ const knowhow = collectVerifiedKnowhow(repo);
146
+ if (knowhow.fileBody !== null) sources.push({ path: KNOWHOW_PATH, sha256: sha256(knowhow.fileBody) });
73
147
  const packageJson = resolve(repo, 'package.json');
74
148
  const version = existsSync(packageJson)
75
149
  ? (JSON.parse(readFileSync(packageJson, 'utf8')) as { version: string }).version : 'unknown';
@@ -109,20 +183,25 @@ export function buildCoordRolePackManifest(role: RolePackRole, root = resolve(im
109
183
  '재는 명령: `eln release checklist status --version <판> --json`(칸·선행·판) · `eln config get harness.podPool`(Pod 풀) · `uptime`(부하 추세) · `eln self gate --help`(호스트·게이트 옵션). 명령이 못 재는 슬롯·런 상태는 담당 원장의 현행 명령을 확인한다.',
110
184
  ...cards.map(([id, rule]) => `- ${id} · ${rule} → 팩 ${role === 'coordinator' ? '조율자' : '수호자'} v1`),
111
185
  '',
186
+ '## KNOWHOW — 검증된 출처',
187
+ `docs/roles/OP/KNOWHOW.md 항목 중 src/seat-loop/knowhow-lint.ts 의 린트를 통과한 항목만 싣는다. 실패 항목·비밀값은 제외한다.`,
188
+ ...knowhow.included.map((card) => `- ${card.id} · ${card.title}`),
189
+ ...knowhow.included.flatMap((card) => ['', card.text]),
190
+ '',
112
191
  '## 판단 순서',
113
192
  '1. 원 요청과 지금의 우편 스레드·확인표 칸을 대조한다.',
114
193
  '2. 코드·설정·실행 결과를 읽고, 문서와 충돌하면 현재 실행 결과를 따른다.',
115
194
  '3. 관측·판단 근거·다음 행동을 분리해 답한다. 쓰기는 현재 확인 단계가 허용한 명령으로만 한다.',
116
195
  '4. 근거가 없거나 안전 난간과 충돌하면 보류하고 담당 자리 또는 사람에게 올린다.',
117
196
  '',
118
- '위에 명시한 검증된 C/G 카드 외의 노하우 카드는 포함하지 않는다. 현재 관측과 담당 자리의 검증된 원장을 직접 확인한다.',
197
+ '위에 명시한 검증된 C/G 카드와 KNOWHOW 린트 통과 항목 외의 노하우는 포함하지 않는다. 현재 관측과 담당 자리의 검증된 원장을 직접 확인한다.',
119
198
  '## 출처 해시',
120
199
  ...sources.map((source) => `- ${source.path}: ${source.sha256}`),
121
200
  ...missingSources.map((path) => `- ${path}: 없음(이 설치본에 미포함)`),
122
201
  '',
123
202
  ];
124
203
  const body = lines.join('\n');
125
- return { role, version, sha256: sha256(body), body, includedCardIds: cards.map(([id]) => id), excludedCardIds: [], sources, missingSources };
204
+ return { role, version, sha256: sha256(body), body, includedCardIds: cards.map(([id]) => id), excludedCardIds: knowhow.excluded, sources, missingSources };
126
205
  }
127
206
 
128
207
  /** Prompt body consumed by coordinator and guardian agents. */
@@ -16,7 +16,7 @@ import { ensureCronNodePath } from '../src/domains/cron-path.js';
16
16
  ensureCronNodePath();
17
17
 
18
18
  async function main(): Promise<void> {
19
- const argv = process.argv.slice(2);
19
+ const { argv, maxRuntimeMs } = extractMaxRuntimeArgs(process.argv.slice(2)); // 래퍼 옵션은 대상 앞에서만 소비한다.
20
20
  const hasScheduleId = argv[0] === '--schedule-id';
21
21
  const scheduleId = hasScheduleId ? argv.splice(0, 2)[1] : undefined;
22
22
  if (hasScheduleId && (!scheduleId?.trim() || scheduleId === '--shell')) {
@@ -90,6 +90,9 @@ async function main(): Promise<void> {
90
90
  const child = spawn(interpreter, [target, ...targetArgs], {
91
91
  stdio: ['ignore', 'inherit', 'pipe'],
92
92
  env: { ...process.env },
93
+ // ⓐ detached — 자식이 프로세스 그룹 리더가 된다. 상한 초과 kill 은 그룹 전체
94
+ // (자식의 자식까지)를 죽린다: process.kill(-pid).
95
+ detached: true,
93
96
  });
94
97
  let errTail = '';
95
98
  child.stderr?.on('data', (chunk: Buffer) => {
@@ -97,14 +100,53 @@ async function main(): Promise<void> {
97
100
  errTail = (errTail + chunk.toString()).slice(-2000); // 바운디드
98
101
  });
99
102
 
103
+ // ⓐ 상한 타이머 — 넘으면 자식 프로세스 그룹 전체를 SIGKILL 하고 관측 플래그를 올린다.
104
+ // 진단(stderr 한 줄)은 여기서, 관측 기록은 기존 finish() 경로가 그대로 맡는다(fail-open 불변).
105
+ // ⚠ 리더가 이미 종료했다고 조기 반환하지 않는다(리뷰 must-fix): 리더만 죽고 손자가 stderr
106
+ // 파이프를 쥔 채 남으면 close 가 영영 안 와 관측도 반환도 없다. 이 경로에서도 그룹(트리)
107
+ // 종료를 시도하고, close 가 오지 않으면 finish 를 직접 불러 관측·반환을 마무리한다.
108
+ let overrun = false;
109
+ let finished = false;
110
+ let forwardedExit: number | null = null;
111
+ let signalKillTimer: ReturnType<typeof setTimeout> | null = null;
112
+ const timer: ReturnType<typeof setTimeout> | null = maxRuntimeMs > 0
113
+ ? setTimeout(() => {
114
+ if (child.pid === undefined || finished) return;
115
+ overrun = true;
116
+ const leaderGone = child.exitCode !== null || child.signalCode !== null;
117
+ try { process.stderr.write(`cron-run overrun: ${maxRuntimeMs}ms 상한 초과 — 자식 트리(pid ${child.pid}) 종료${leaderGone ? ' — 리더 이미 종료, 파이프를 쥔 손자 정리' : ''}\n`); } catch { /* */ }
118
+ try { process.kill(-child.pid, 'SIGKILL'); }
119
+ catch { try { child.kill('SIGKILL'); } catch { /* 이미 종료 */ } }
120
+ // 그룹 밖(setsid) 잔존자가 파이프를 계속 쥐면 close 가 오지 않는다 — 관측까지 여기서
121
+ // 마무리한다. close 가 정상적으로 오면 finish 의 멱등 가드가 이 호출을 흡수한다.
122
+ setTimeout(() => finish(child.exitCode), OVERRUN_CLOSE_GRACE_MS);
123
+ }, maxRuntimeMs)
124
+ : null;
125
+
100
126
  const finish = (code: number | null): void => {
101
- const exit = code ?? 0;
127
+ if (finished) return; // 멱등 — close·error·상한 유예 경로가 겹쳐도 관측·반환은 1회
128
+ finished = true;
129
+ // 신호를 받은 뒤 리더가 먼저 닫혀도, SIGTERM을 무시하고 stdio를 닫은 손자가
130
+ // 그룹에 남을 수 있다. close가 온 시점에도 그룹 전체를 마지막으로 거둔다.
131
+ if (forwardedExit !== null && child.pid !== undefined) {
132
+ try { process.kill(-child.pid, 'SIGKILL'); } catch { /* 그룹 이미 종료 */ }
133
+ }
134
+ if (timer !== null) clearTimeout(timer);
135
+ if (signalKillTimer !== null) clearTimeout(signalKillTimer);
136
+ process.removeListener('SIGINT', onSigInt);
137
+ process.removeListener('SIGTERM', onSigTerm);
138
+ const exit = overrun ? 124 : forwardedExit ?? code ?? 0;
102
139
  try {
103
140
  const durationMs = Date.now() - start;
104
141
  const status: 'ok' | 'error' = exit === 0 ? 'ok' : 'error';
142
+ const overrunNote = overrun
143
+ ? `cron-run overrun: killed ${target} (pid ${child.pid ?? '?'}) after ${durationMs}ms — cap ${maxRuntimeMs}ms`
144
+ : null;
105
145
  const record = {
106
146
  status, exit, durationMs, via: 'crontab' as const,
107
- error: exit === 0 ? null : errTail.trim().split('\n').slice(-3).join('\n') || `exit ${exit}`,
147
+ error: overrunNote
148
+ ? [overrunNote, ...errTail.trim().split('\n').slice(-3).filter(Boolean)].join('\n')
149
+ : exit === 0 ? null : errTail.trim().split('\n').slice(-3).join('\n') || `exit ${exit}`,
108
150
  };
109
151
  const options = { ...(db ? { db } : {}), ...(id ? { id } : {}), prevStatus };
110
152
  const diagnostic = (kind: 'prerequisite' | 'registry record skipped' | 'registry selection ambiguous' | 'import' | 'record', error: unknown): Promise<void> => {
@@ -144,8 +186,59 @@ async function main(): Promise<void> {
144
186
  process.exit(exit);
145
187
  }
146
188
  };
189
+ const forwardSignal = (signal: 'SIGINT' | 'SIGTERM'): void => {
190
+ if (finished || forwardedExit !== null) return;
191
+ forwardedExit = signal === 'SIGINT' ? 130 : 143;
192
+ if (child.pid === undefined) { finish(forwardedExit); return; }
193
+ try { process.kill(-child.pid, signal); }
194
+ catch { try { child.kill(signal); } catch { /* 이미 종료 */ } }
195
+ signalKillTimer = setTimeout(() => {
196
+ try { process.kill(-child.pid!, 'SIGKILL'); }
197
+ catch { try { child.kill('SIGKILL'); } catch { /* 이미 종료 */ } }
198
+ finish(forwardedExit);
199
+ }, OVERRUN_CLOSE_GRACE_MS);
200
+ };
201
+ const onSigInt = (): void => forwardSignal('SIGINT');
202
+ const onSigTerm = (): void => forwardSignal('SIGTERM');
203
+ process.on('SIGINT', onSigInt);
204
+ process.on('SIGTERM', onSigTerm);
147
205
  child.on('close', finish);
148
206
  child.on('error', (e) => { process.stderr.write(`cron-run spawn error: ${e.message}\n`); finish(1); });
149
207
  }
150
208
 
209
+ const MAX_TIMER_MS = 2_147_483_647;
151
210
  void main().catch(() => process.exit(0));
211
+
212
+ // ⓐ LOGS-RETENTION-46MIN: 실행 시간 상한 — 상한 없이 살아남은 옛 판 크론이 6시간마다
213
+ // «오래된 행 50%» 삭제를 겹쳐 돌려 보존 창을 무너뜨린 사고(10-12)의 재발 방지.
214
+ // 우선순위: --max-runtime-ms > CRON_RUN_MAX_RUNTIME_MS > 기본 30분. 0 이하는 상한 끔.
215
+ //
216
+ // 래퍼 플래그는 대상 앞에서만 읽는다. 대상 뒤의 같은 이름은 자식 인자다.
217
+ // ⚠ main() 안쪽이 아니라 여기(helper)에 두는 이유: main() 머리에 줄을 늘리면 위쪽
218
+ // registerLogStoreSink 호출의 줄번호가 움직여 log-store-retention-callers.test.ts
219
+ // 가 git 색인과 대비하는 검사를 깬다(부메랑).
220
+ function extractMaxRuntimeArgs(argv: string[]): { argv: string[]; maxRuntimeMs: number } {
221
+ const args = [...argv];
222
+ if (args[0] === '--schedule-id') args.splice(0, 2);
223
+ if (args[0] === '--max-runtime-ms') {
224
+ const raw = args[1];
225
+ const parsed = Number(raw);
226
+ if (!raw || !Number.isSafeInteger(parsed) || parsed < 0 || parsed > MAX_TIMER_MS) {
227
+ process.stderr.write(`cron-run: --max-runtime-ms 인자는 0~${MAX_TIMER_MS} 사이의 정수여야 합니다\n`);
228
+ process.exit(2);
229
+ }
230
+ const flagIndex = argv.indexOf('--max-runtime-ms');
231
+ return { argv: argv.filter((_, index) => index !== flagIndex && index !== flagIndex + 1), maxRuntimeMs: parsed };
232
+ }
233
+ const rawEnv = process.env.CRON_RUN_MAX_RUNTIME_MS;
234
+ const fromEnv = Number(rawEnv);
235
+ if (rawEnv?.trim() && fromEnv > MAX_TIMER_MS) {
236
+ process.stderr.write(`cron-run: CRON_RUN_MAX_RUNTIME_MS 인자는 0~${MAX_TIMER_MS} 사이의 정수여야 합니다\n`);
237
+ process.exit(2);
238
+ }
239
+ return { argv, maxRuntimeMs: rawEnv?.trim() && Number.isSafeInteger(fromEnv) && fromEnv >= 0 && fromEnv <= MAX_TIMER_MS ? fromEnv : 30 * 60_000 };
240
+ }
241
+
242
+ // ⓐ 상한 시점의 그룹 종료 뒤에도 close 가 오지 않는 경로(파이프를 쥔 그룹 밖 손자)에서
243
+ // 관측(finish)을 마무리할 때까지 기다리는 유예.
244
+ const OVERRUN_CLOSE_GRACE_MS = 2_000;