elanous 0.2.28 → 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 (818) 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/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{ab4d57c2.e90bc2cb31949045.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/{5492-e05e26a033ba80d2.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/1654.32de4b324981a188.js +23 -0
  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/1913.7cc6fb6055b1ed3f.js +41 -0
  18. package/apps/pwa/out/_next/static/chunks/2001.6c7e0fd02190886c.js +1 -0
  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/{8578.dff22d988cc2b106.js → 2213.2ccbada92c33ea0f.js} +3 -3
  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/{5081.a240b63fad28663a.js → 2871.0bca6137343b3f76.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/2898.fd781bc7cf01a7b7.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2940-619bfd8ef337c611.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/{2846.d6a433b8663819a5.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/{f4dfbfc0.a69fb12f854882aa.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/3541-ce3a5424ed5ad7f1.js +1 -0
  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/{3143.257997a5f1ed79df.js → 3902.e1e71aaac850a045.js} +1 -1
  39. package/apps/pwa/out/_next/static/chunks/4063-03284b5de59965f3.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{16e57f67.3ea19e893461e611.js → 409f1e57.d0649fc47691ebfe.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/{1146.80d15ea7c6e6ee95.js → 4111.2bfedbb233ad206b.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/{1516.83dd2c1b86b4e507.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/{9938.b23e4d4dfa0114cd.js → 4999.c064a4000c2a9e94.js} +2 -2
  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/{1157.f08bf2b70915e176.js → 5304.04d24756f242a094.js} +2 -2
  57. package/apps/pwa/out/_next/static/chunks/{7752.5cbdd0b433c54af9.js → 5307.60f2209e809bd627.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/5415-997980f828667736.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/{9917-9e26abc5f7772735.js → 5458-16cd7a2b51b74c8c.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/{6196.34d6b229079e9e28.js → 5525.86debf231e181813.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{4593.10f5b9bd702d4a6c.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/{7483.ba01c6c209b81bba.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/{9974.e77b4ff4884557b3.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/{3309.364573ceedbdfd5f.js → 6323.8672b4817a306928.js} +1 -1
  74. package/apps/pwa/out/_next/static/chunks/{94.4cfed21c0b781a06.js → 6433.fc573af22bbc9ab7.js} +4 -4
  75. package/apps/pwa/out/_next/static/chunks/6444.7d1fdcb9b09ae71c.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/{949.1e7d45ccb71580aa.js → 6517.4147878ac06d584d.js} +2 -2
  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/{2528.3868070ef1be69f9.js → 6767.ea607cf0c20a25af.js} +2 -2
  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/{1743.563d3168e95825ef.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/{5408.377c8c543635b81f.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/{65ebff95.081daeff622d238e.js → 7a1887c4.f36b88fba31da8fd.js} +1 -1
  99. package/apps/pwa/out/_next/static/chunks/{2697.76ca2ac3efef6f3b.js → 8018.a32663f04a6fc5f9.js} +1 -1
  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/9138.b6e80031afb1d973.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/9188-d36e4fc869ddc166.js +1 -0
  112. package/apps/pwa/out/_next/static/chunks/{4204.a409ab6250c0f6a8.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/{5785-ea8d2c633b6688e3.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/9398-6aed28f0a96d0d6f.js +1 -0
  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/997ce8a5-2ad501927003b41b.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{9311.24c8f5ea793253dd.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-fa46d4588e8442c2.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-ced0bcfc6542b3fc.js → page-349f2752d8cd37ad.js} +1 -1
  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-cb249e81ed339318.js → page-0a07363b130182a1.js} +1 -1
  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-521ee23ac8c0abfa.js +1 -0
  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-149dc1caba411bb9.js +1 -0
  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/{6def8a8e.c81f9ca41028eccf.js → b313b242.cb1265eea908db61.js} +1 -1
  174. package/apps/pwa/out/_next/static/chunks/{e87d89b9.2e71c0ae475d28a1.js → e5012ffe.f727e23c231f4342.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/ea695e3c-1f1d70d740cf3031.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{e117f801.e92bf10242653497.js → ebc7d829.264a0bcb6c750b50.js} +1 -1
  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 +15 -7
  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/plugins/agent-team/agents/research.md +1 -0
  289. package/scripts/check-native-tool-wiring.ts +3 -2
  290. package/scripts/ci-android-unit-tests.ts +16 -0
  291. package/scripts/ci-typecheck-changed.ts +40 -11
  292. package/scripts/coord-channel-watch.sh +45 -19
  293. package/scripts/coord-role-pack.ts +222 -0
  294. package/scripts/cron-run.ts +96 -3
  295. package/scripts/detect-test-interference.ts +38 -5
  296. package/scripts/gate-pr-cache.ts +65 -0
  297. package/scripts/gh-surface/capture.ts +126 -0
  298. package/scripts/gh-surface/gh +40 -0
  299. package/scripts/import-graph-scc.ts +38 -0
  300. package/scripts/install.ps1 +19 -0
  301. package/scripts/intake-social.ts +181 -0
  302. package/scripts/lecture-note/node.ts +71 -4
  303. package/scripts/lib/android-toolchain.ts +32 -0
  304. package/scripts/lib/deterministic-env.ts +62 -0
  305. package/scripts/lib/gate-test-env.ts +19 -0
  306. package/scripts/lib/morning-report-options.ts +41 -0
  307. package/scripts/measure-goal-grounding-corpus.ts +2 -1
  308. package/scripts/pr-land-extra-remote-gates.ts +49 -0
  309. package/scripts/ratchets/test-interference-patterns.allowlist.txt +257 -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-batch-safe.ts +23 -0
  317. package/scripts/release-loop/gate-closure.ts +12 -8
  318. package/scripts/release-loop/gate-diff.ts +1 -1
  319. package/scripts/release-loop/gate-history.ts +422 -0
  320. package/scripts/release-loop/gate-host-mirror.ts +66 -0
  321. package/scripts/release-loop/gate-node.ts +806 -94
  322. package/scripts/release-loop/gate-partial.ts +106 -9
  323. package/scripts/release-loop/gate-pr-cache.ts +66 -0
  324. package/scripts/release-loop/gate-prewarm-plan.ts +66 -0
  325. package/scripts/release-loop/gate-r2-verdict.ts +189 -0
  326. package/scripts/release-loop/gate-recheck-plan-node.ts +52 -0
  327. package/scripts/release-loop/gate-triage-node.ts +190 -0
  328. package/scripts/release-loop/gate-warm-artifacts.ts +253 -0
  329. package/scripts/release-loop/import-graph-scc-run.ts +54 -0
  330. package/scripts/release-loop/import-graph-scc.ts +215 -0
  331. package/scripts/release-loop/node-verdict.ts +2 -0
  332. package/scripts/release-loop/probe-pod-host-dirs-live.ts +113 -0
  333. package/scripts/release-loop/resume-release.ts +33 -4
  334. package/scripts/release-loop/resume.ts +13 -5
  335. package/scripts/release-loop/spawn-lane.ts +51 -0
  336. package/scripts/release-loop/tui-node-checks.ts +23 -0
  337. package/scripts/release-loop/tui-sim-node.ts +3 -2
  338. package/scripts/release-loop/unattended-release.ts +16 -0
  339. package/scripts/release-loop/version-node.ts +62 -4
  340. package/scripts/test-deterministic.ts +46 -73
  341. package/scripts/train-reach-grouping.ts +48 -0
  342. package/scripts/tsc-incremental-cache.ts +86 -0
  343. package/scripts/tsc-incremental-diagnostics.ts +76 -0
  344. package/scripts/tsc-main-safety-net.ts +2 -2
  345. package/scripts/usage-rollup.ts +11 -3
  346. package/src/acp/client.ts +4 -1
  347. package/src/acp/core-turn-bridge.ts +145 -24
  348. package/src/acp/elanous-extensions.ts +2 -0
  349. package/src/acp/server.ts +2 -0
  350. package/src/ad-pipeline/run.ts +4 -2
  351. package/src/agent/ref-grounding.ts +18 -0
  352. package/src/agent/runner.ts +169 -3
  353. package/src/agent/subagent-callable.ts +3 -2
  354. package/src/agent-mission/review-loop.ts +6 -3
  355. package/src/agent-substrate/acp-implementer.ts +14 -2
  356. package/src/agent-substrate/pr-reviewer.ts +41 -21
  357. package/src/agent-substrate/self-review-cli.ts +30 -4
  358. package/src/autopilot/pr-manager.ts +62 -7
  359. package/src/briefing/brief-items.ts +24 -22
  360. package/src/budget/pty-usage-reemit.ts +7 -0
  361. package/src/budget/run-usage-rollup.ts +9 -0
  362. package/src/budget/usage-daily-store.ts +98 -0
  363. package/src/capture/tui-self-report.ts +37 -4
  364. package/src/chat/chat-cli.ts +10 -2
  365. package/src/chat/index.ts +107 -20
  366. package/src/chat/input-control-key.ts +5 -3
  367. package/src/chat/pickers/modal-runtime.ts +1 -0
  368. package/src/chat/pickers/modals.ts +3 -1
  369. package/src/chat/tool-interrupt-behavior.ts +38 -0
  370. package/src/chat/tool-render/dispatch.ts +5 -1
  371. package/src/chat/turn-typeahead.ts +191 -29
  372. package/src/cli/__fixtures__/agent-help-before/agent.txt +4 -2
  373. package/src/cli/agent-cli.ts +41 -13
  374. package/src/cli/config-audit.ts +123 -0
  375. package/src/cli/dashboard-name-flag.ts +48 -0
  376. package/src/cli/decisions-cli.ts +80 -6
  377. package/src/cli/doctor-cli.ts +80 -0
  378. package/src/cli/log-event-names.ts +19 -0
  379. package/src/cli/mcp-login.ts +21 -5
  380. package/src/cli/msg-cli.ts +133 -2
  381. package/src/cli/pr-cli.ts +546 -112
  382. package/src/cli/pr-land-heavy-remote.ts +233 -0
  383. package/src/cli/pr-land-overlap-evidence.ts +167 -14
  384. package/src/cli/pr-land-pod-shadow-job.ts +83 -0
  385. package/src/cli/pr-land-pod-shadow.ts +16 -3
  386. package/src/cli/pr-land-virtual-rebase.ts +108 -0
  387. package/src/cli/pty-takeover-cli.ts +125 -16
  388. package/src/cli/release-cli.ts +122 -14
  389. package/src/cli/remote-resolve.ts +2 -1
  390. package/src/cli/seat-cli.ts +164 -19
  391. package/src/cli/self-update.ts +5 -2
  392. package/src/cli/tasks-cli.ts +105 -21
  393. package/src/cli/usage-cli.ts +146 -12
  394. package/src/cli/usage-daily-cli.ts +84 -0
  395. package/src/context-bus/context-first.ts +13 -0
  396. package/src/context-bus/context-now.ts +95 -7
  397. package/src/context-bus/ops-events.ts +75 -0
  398. package/src/control-plane/lease-holder.ts +12 -8
  399. package/src/control-plane/ledger.ts +163 -4
  400. package/src/control-plane/server.ts +91 -11
  401. package/src/core-turn/auth-rejected-notice.ts +41 -0
  402. package/src/core-turn/run-core-turn.ts +14 -2
  403. package/src/core-turn/run-goal-loop.ts +239 -4
  404. package/src/core-turn/seat-turn-cap.ts +79 -0
  405. package/src/core-turn/short-question.ts +78 -13
  406. package/src/core-turn/types.ts +10 -0
  407. package/src/dashboard/acp-active-model.ts +40 -0
  408. package/src/dashboard/acp-boot.ts +3 -0
  409. package/src/dashboard/auto-compact-runtime.ts +2 -0
  410. package/src/dashboard/boot-banner.ts +80 -0
  411. package/src/dashboard/dashboard-status-lines.ts +11 -0
  412. package/src/dashboard/detail-viewer-runtime.ts +15 -2
  413. package/src/dashboard/event-loop-stall-monitor.ts +4 -0
  414. package/src/dashboard/goal-loop-thinking.ts +16 -0
  415. package/src/dashboard/hitl-boot.ts +9 -4
  416. package/src/dashboard/index.ts +448 -998
  417. package/src/dashboard/input/chat-main-entry-runtime.ts +2 -0
  418. package/src/dashboard/input/chat-main-log-actions.ts +4 -0
  419. package/src/dashboard/input/chat-main-log-command.ts +12 -1
  420. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +176 -4
  421. package/src/dashboard/input/chat-main-session.ts +14 -3
  422. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  423. package/src/dashboard/input/chat-main-turn.ts +14 -4
  424. package/src/dashboard/input/compact-prepass-recovery.ts +130 -0
  425. package/src/dashboard/input/dashboard-chord-actions.ts +10 -1
  426. package/src/dashboard/input/dashboard-chord-runtime.ts +2 -0
  427. package/src/dashboard/input/external-input-host.ts +71 -0
  428. package/src/dashboard/input/internal-turn.ts +261 -0
  429. package/src/dashboard/input/log-fold-binding.ts +18 -0
  430. package/src/dashboard/input/mouse-wiring.ts +17 -4
  431. package/src/dashboard/input/seat-autowake.ts +318 -0
  432. package/src/dashboard/input/turn-steer-bridge.ts +164 -0
  433. package/src/dashboard/log-click-runtime.ts +5 -3
  434. package/src/dashboard/loop-scheduler.ts +72 -0
  435. package/src/dashboard/running-build-status.ts +74 -0
  436. package/src/dashboard/seat-boot-preamble.ts +131 -0
  437. package/src/dashboard/seat-local-instructions.ts +305 -0
  438. package/src/dashboard/skill-runtime.ts +2 -0
  439. package/src/dashboard/slash-runtime/dashboard-handlers.ts +220 -1203
  440. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -1
  441. package/src/dashboard/slash-runtime/index.ts +13 -0
  442. package/src/dashboard/slash-runtime/model-choices.ts +35 -0
  443. package/src/dashboard/term-slash-runtime.ts +15 -0
  444. package/src/dashboard/turn-busy-teardown.ts +50 -0
  445. package/src/dashboard/turn-preamble.ts +30 -2
  446. package/src/dashboard/turn-session-layers.ts +176 -0
  447. package/src/dashboard/turn-stream-formatter.ts +14 -6
  448. package/src/dashboard/turn-stream-presentation-applier.ts +8 -0
  449. package/src/decisions/decision-ledger.ts +45 -4
  450. package/src/discord-self-message.ts +4 -4
  451. package/src/domains/release-tool.ts +26 -10
  452. package/src/domains/surface-events.ts +4 -1
  453. package/src/domains/watch-default-scheduler.ts +8 -9
  454. package/src/field-note/transcribe.ts +17 -0
  455. package/src/fold-stack.ts +24 -1
  456. package/src/git-fs/dirty.ts +32 -4
  457. package/src/git-fs/index.ts +43 -1
  458. package/src/github/remote-call.ts +81 -0
  459. package/src/goals/registry.ts +46 -6
  460. package/src/goals/types.ts +7 -1
  461. package/src/graph-runner/runner.ts +2 -0
  462. package/src/grok/credential.ts +26 -0
  463. package/src/harness/harness-clean.ts +2 -1
  464. package/src/harness/harness-cli-command.ts +52 -5
  465. package/src/harness/harness-gc.ts +34 -6
  466. package/src/harness/harness-incidents.ts +57 -20
  467. package/src/harness/harness-pod-dispatch.ts +87 -10
  468. package/src/harness/harness-queue.ts +53 -4
  469. package/src/harness/harness-stop.ts +4 -3
  470. package/src/harness/harness-substrate-default.ts +78 -7
  471. package/src/harness/harness-worktree-auto.ts +2 -1
  472. package/src/harness/harness-worktrees.ts +3 -2
  473. package/src/hooks/dispatch.ts +2 -1
  474. package/src/index.ts +166 -26
  475. package/src/input/external-input-queue.ts +251 -0
  476. package/src/intake-plane/slash.ts +14 -3
  477. package/src/interactive-terminal-modal.ts +13 -0
  478. package/src/keybindings.ts +4 -1
  479. package/src/llm/route-decision.ts +25 -0
  480. package/src/llm/tool-loop-steered-rejection.ts +33 -0
  481. package/src/llm-stream-retry-display.ts +59 -0
  482. package/src/llm.ts +391 -74
  483. package/src/log-entry.ts +3 -3
  484. package/src/log-pane/search.ts +29 -4
  485. package/src/loops/agent-reply.ts +256 -0
  486. package/src/loops/budget.ts +37 -7
  487. package/src/loops/consensus.ts +348 -0
  488. package/src/loops/loop-cli.ts +3 -2
  489. package/src/loops/msg-address.ts +57 -0
  490. package/src/loops/msg-wake.ts +484 -0
  491. package/src/loops/observe.ts +19 -3
  492. package/src/loops/orchestrator/inbox.ts +60 -3
  493. package/src/loops/orchestrator/tick.ts +80 -6
  494. package/src/loops/orchestrator/traffic.ts +64 -1
  495. package/src/loops/registry.ts +72 -4
  496. package/src/market/signed-index.ts +14 -0
  497. package/src/mcp/mcp-oauth.ts +54 -5
  498. package/src/memory.ts +20 -5
  499. package/src/models/prompts.ts +28 -0
  500. package/src/msg/msg-sse-client.ts +223 -0
  501. package/src/msg/msg-store.ts +86 -2
  502. package/src/mss/logging/log-store.ts +225 -1
  503. package/src/native-tool-catalog.ts +125 -0
  504. package/src/nexus/DAEMON-THIN-inventory-2026-10-15.md +122 -0
  505. package/src/nexus/api/http-server.ts +59 -15
  506. package/src/nexus/api/loop-resources.ts +19 -3
  507. package/src/nexus/api/ops-api.ts +13 -0
  508. package/src/nexus/api/project-autopsy.ts +127 -0
  509. package/src/nexus/api/terminals.ts +3 -0
  510. package/src/nexus/api/workflow-approvals.ts +2 -0
  511. package/src/nexus/daemon-thin-inventory.md +37 -0
  512. package/src/nexus/index.ts +70 -0
  513. package/src/nexus/onboarding/first-boot-wizard.ts +56 -2
  514. package/src/nexus/state/state.ts +1 -0
  515. package/src/oauth/codex-account-store.ts +15 -3
  516. package/src/oauth/codex-billing-route.ts +31 -0
  517. package/src/oauth/store.ts +32 -7
  518. package/src/onboarding/first-run.ts +28 -3
  519. package/src/ops/overview-cache.ts +16 -4
  520. package/src/ops/overview-collect.ts +19 -2
  521. package/src/ops/resources.ts +82 -0
  522. package/src/panes/log-pane.ts +67 -8
  523. package/src/persona/presets.ts +44 -0
  524. package/src/plugins/maker/connector-maker.ts +41 -0
  525. package/src/plugins/maker/skill-maker.ts +42 -0
  526. package/src/plugins/maker/wizard-generate.ts +6 -4
  527. package/src/pr-tool/census.ts +288 -0
  528. package/src/preview/terminal.ts +14 -1
  529. package/src/prompt-cache/types.ts +2 -0
  530. package/src/prompt-enhance/enhance.ts +24 -8
  531. package/src/prompt-library/chat-conciseness.ts +13 -0
  532. package/src/prompt-library/universal-preamble.ts +283 -61
  533. package/src/pty-shell/pty-control-ipc.ts +4 -1
  534. package/src/pty-shell/pty-manifest.ts +77 -5
  535. package/src/pty-shell/registry.ts +19 -2
  536. package/src/pty-shell/tui-run-state.ts +253 -0
  537. package/src/release-loop/gate-host-reservation.ts +97 -0
  538. package/src/release-loop/landing-freeze.ts +5 -0
  539. package/src/release-loop/light-rc.ts +32 -4
  540. package/src/release-loop/placement.ts +92 -1
  541. package/src/release-loop/rehearsal-shard-plan.ts +149 -0
  542. package/src/release-loop/rehearsal.ts +73 -17
  543. package/src/render.ts +5 -1
  544. package/src/repl/index.ts +20 -2
  545. package/src/seat-loop/seat-knowhow.ts +282 -0
  546. package/src/seat-loop/seat-loop.ts +41 -2
  547. package/src/seat-loop/seat-report.ts +42 -2
  548. package/src/seat-loop/traffic-signal.ts +3 -0
  549. package/src/self-dev/ask-launch-flow.ts +24 -3
  550. package/src/self-dev/decompose-compose-graph.ts +28 -27
  551. package/src/self-dev/decompose-proposal.ts +53 -38
  552. package/src/self-dev/decompose.ts +17 -0
  553. package/src/self-dev/dev-pipeline.ts +31 -2
  554. package/src/self-dev/draft-residue.ts +24 -9
  555. package/src/self-dev/draft-sweep.ts +59 -4
  556. package/src/self-dev/external-call-zero.ts +77 -0
  557. package/src/self-dev/launch-preflight-text.ts +6 -0
  558. package/src/self-dev/launch-preflight.ts +25 -3
  559. package/src/self-dev/local-supervisor-judge.ts +185 -0
  560. package/src/self-dev/run-supervisor.ts +300 -24
  561. package/src/self-dev/run-types.ts +20 -0
  562. package/src/self-dev/shard-aggregate.ts +15 -2
  563. package/src/self-dev/shard-plan.ts +47 -0
  564. package/src/self-dev/shard-run.ts +135 -12
  565. package/src/self-dev/spawn-lane-files.ts +19 -0
  566. package/src/self-health/signatures.ts +132 -0
  567. package/src/self-implement/app-api-budget.ts +51 -11
  568. package/src/self-implement/config-gate.ts +2 -1
  569. package/src/self-implement/doctor-visit.ts +118 -0
  570. package/src/self-implement/expose-gate.ts +2 -1
  571. package/src/self-implement/gate-artifacts.ts +405 -0
  572. package/src/self-implement/gate-cli.ts +212 -18
  573. package/src/self-implement/gate-remote.ts +110 -25
  574. package/src/self-implement/gate-scenario.ts +85 -0
  575. package/src/self-implement/goal-author-decompose.ts +80 -16
  576. package/src/self-implement/goal-author.ts +270 -76
  577. package/src/self-implement/goal-authoring-grounding.ts +1 -1
  578. package/src/self-implement/goal-file-name.ts +65 -0
  579. package/src/self-implement/graph-authority.ts +38 -6
  580. package/src/self-implement/graph-overlay-condition.ts +92 -1
  581. package/src/self-implement/ground-goal.ts +2 -1
  582. package/src/self-implement/heal-triage.ts +79 -0
  583. package/src/self-implement/host-regate.ts +74 -2
  584. package/src/self-implement/orchestrator.ts +14 -123
  585. package/src/self-implement/pr-title.ts +123 -0
  586. package/src/self-implement/review-mustfix-class.ts +115 -0
  587. package/src/self-implement/run-checkpoint.ts +235 -0
  588. package/src/self-implement/run-ledger.ts +266 -17
  589. package/src/self-implement/run-stop.ts +4 -3
  590. package/src/self-implement/run-ttl.ts +28 -4
  591. package/src/self-implement/running-runs.ts +10 -6
  592. package/src/self-implement/seams.ts +2 -0
  593. package/src/self-implement/self-implement-runtime.ts +32 -0
  594. package/src/self-implement/shadow-stage.ts +7 -6
  595. package/src/self-implement/stop-autoheal.ts +2 -1
  596. package/src/self-implement/train-gate-remote.ts +37 -8
  597. package/src/self-implement/train-reach-grouping.ts +157 -0
  598. package/src/self-implement/train-scenario-layers.ts +133 -0
  599. package/src/self-implement/uncommitted-work.ts +2 -0
  600. package/src/session/pending-input.ts +81 -11
  601. package/src/session/session-start.ts +224 -0
  602. package/src/session-runtime/index.ts +7 -1
  603. package/src/session-runtime/parallel-dispatch.ts +22 -5
  604. package/src/skills/tools/dev-harness.ts +6 -4
  605. package/src/skills/tools/ops-ledger.ts +707 -0
  606. package/src/skills/tools/persistent-grounding.ts +47 -7
  607. package/src/skills/tools/shell.ts +117 -1
  608. package/src/status/bar.ts +32 -2
  609. package/src/status/status-provider-info.ts +58 -0
  610. package/src/steward/resync-tick.ts +114 -23
  611. package/src/steward/ta-repair-event-collect.ts +158 -0
  612. package/src/task-agent/card-evidence.ts +25 -1
  613. package/src/task-agent/green-sweep.ts +8 -3
  614. package/src/task-agent/judge.ts +76 -0
  615. package/src/task-agent/land-queue.ts +79 -0
  616. package/src/task-agent/live-moves.ts +30 -9
  617. package/src/task-agent/postland-card.ts +5 -0
  618. package/src/task-agent/prelaunch-already-done.ts +98 -0
  619. package/src/task-agent/real-launch-guard.ts +37 -0
  620. package/src/task-agent/rejudge-on-head.ts +93 -13
  621. package/src/task-agent/remote-rejudge-bind.ts +62 -13
  622. package/src/task-agent/repair-cycle.ts +58 -7
  623. package/src/task-agent/repair-worker.ts +7 -0
  624. package/src/task-agent/run-identity.ts +200 -0
  625. package/src/task-agent/shadow.ts +50 -3
  626. package/src/task-agent/task-hand.ts +158 -5
  627. package/src/task-agent/train-landing.ts +77 -0
  628. package/src/task-agent/work-order.ts +104 -0
  629. package/src/task-orchestrator/surfaces/kubectl-transient-retry.ts +51 -0
  630. package/src/task-orchestrator/surfaces/pod-command-job.ts +138 -22
  631. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +88 -19
  632. package/src/task-orchestrator/surfaces/pod-host-acp-review.ts +2 -1
  633. package/src/task-orchestrator/surfaces/pod-image-source.ts +2 -1
  634. package/src/task-orchestrator/surfaces/pod-install-slots.ts +122 -15
  635. package/src/task-orchestrator/surfaces/pod-lease.ts +20 -6
  636. package/src/task-orchestrator/surfaces/pod-lifecycle-stages.ts +169 -0
  637. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +103 -0
  638. package/src/task-orchestrator/surfaces/pod-result-marker-wait.ts +33 -0
  639. package/src/task-orchestrator/surfaces/pod-reuse-cleanup.ts +63 -0
  640. package/src/task-orchestrator/surfaces/pod-source-receive.ts +19 -3
  641. package/src/task-orchestrator/surfaces/pod-warm-switch.ts +141 -0
  642. package/src/task-orchestrator/surfaces/pod-warm-ta-shadow.ts +85 -0
  643. package/src/task-orchestrator/surfaces/pod-warm-worker-protocol.ts +153 -0
  644. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +208 -0
  645. package/src/task-orchestrator/surfaces/self-implement-pod.ts +237 -46
  646. package/src/telegram.ts +2 -4
  647. package/src/terminal/session-registry.ts +6 -0
  648. package/src/thinking-line.ts +12 -3
  649. package/src/tool-runtime/index.ts +4 -0
  650. package/src/tool-runtime/ops-ledger-runtimes.ts +84 -0
  651. package/src/tool-runtime/ref-consult-runtime.ts +17 -2
  652. package/src/tool-runtime/run-shell-runtime.ts +4 -1
  653. package/src/tool-runtime/self-cognition-runtimes.ts +5 -1
  654. package/src/tui/input/pickers.ts +732 -0
  655. package/src/tui/slash/mission.ts +492 -0
  656. package/src/tui/slash/term.ts +877 -0
  657. package/src/tui-client/dashboard-session.ts +9 -0
  658. package/src/tui.ts +53 -0
  659. package/src/user-config/gemini-server-tools.ts +9 -0
  660. package/src/user-config.ts +106 -21
  661. package/src/util/spawn-sync-output.ts +7 -0
  662. package/src/ux-sim/fake-bin.ts +154 -0
  663. package/src/ux-sim/fake-clock.ts +36 -0
  664. package/src/ux-sim/fake-llm.ts +29 -0
  665. package/src/ux-sim/headless-tui.ts +72 -0
  666. package/src/ux-sim/in-process-cli.ts +176 -0
  667. package/src/ux-sim/temp-git-remote.ts +82 -0
  668. package/src/version/packed-revision.json +1 -1
  669. package/src/video-pipeline/recipes/vlog.ts +25 -7
  670. package/apps/pwa/out/_next/static/chunks/1027.a0f04663d24c2779.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/1038.676007ae505822e7.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/1113.a37eadf7f740d955.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/112-fa7c526c20ce1405.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/1144.5fa1fa1d48dbcd12.js +0 -36
  675. package/apps/pwa/out/_next/static/chunks/119b405e.8fdd0e44d1ff37aa.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/1296.04560d98e73fbf51.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/1314-f604ba013ec535b0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/1454-29d1d773d5996a49.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/1464.f3209af0d8ae4ff2.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/1729-d73dd25e564679d4.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/1843.5924c24295243261.js +0 -27
  682. package/apps/pwa/out/_next/static/chunks/1987.e28149724b92918b.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/2066-5ca18ffa5a4be68b.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/2240.d10a66695155fd93.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/2391.e2cbc98d4abbb41a.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/2566-734cb83bbd405886.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/275.0e6bad414729bfa0.js +0 -32
  688. package/apps/pwa/out/_next/static/chunks/2803-33bdae771855a8d1.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/3259-86f3be56e43eaf6a.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/3280-e177c33bfbdcfb0a.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/3294-2b6a6d45a46a6c1c.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/3522.758840fc5e7fe630.js +0 -287
  693. package/apps/pwa/out/_next/static/chunks/3525-a7c989c1a661e880.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/3694.b1a66387756458c0.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/370.124f9e678a76fc01.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/3797-9643105335e660fe.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/4084.15ecaf4240bd9e77.js +0 -286
  698. package/apps/pwa/out/_next/static/chunks/4089-b3382b8843114eee.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/4293.928a8d573c16aab7.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/4402.f9238a3b18a7bd43.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/4490-9b090b0f9427f902.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/4548.13502d0ca3b4f862.js +0 -8
  703. package/apps/pwa/out/_next/static/chunks/4565-67e4c620597965c8.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/4599-548bc96cda44a5a7.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/4625.206574e33a9e7ae8.js +0 -104
  706. package/apps/pwa/out/_next/static/chunks/4862-392c9a71f0d8dfb4.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/5054.2906d1b02542edc5.js +0 -149
  708. package/apps/pwa/out/_next/static/chunks/5102-c822bbbee5a022a4.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/5194-8c93f2e7e4b6f717.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/5305-bacd7eca0b9a5848.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/5311.9071ee3f44fd7ff5.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/5369.9f34353442daa421.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/589-49d730cb8138b397.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/5904-264a6412ae3c9028.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/5980.728531d5c566535c.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/599-56f2c0a5cc4a7295.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/6011.f525002e21bef0ac.js +0 -23
  718. package/apps/pwa/out/_next/static/chunks/6132.4381ab93683f1acf.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/6149.2e698635e454d8f6.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/6356-0afafc4230cf9767.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/6406.64756073f7df35b8.js +0 -77
  722. package/apps/pwa/out/_next/static/chunks/6479-16e62aedafa0e310.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/6599.b5246b46a2453329.js +0 -64
  724. package/apps/pwa/out/_next/static/chunks/6610.5c26eec011565acb.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/666.37d18474edc1c552.js +0 -2
  726. package/apps/pwa/out/_next/static/chunks/6904.a0b5b1ed4f2d2c20.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/7247-1f4aba94aba50d9f.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/7274-e71a7c5b7760cd02.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/7290.1fcaeef3adb5d0d4.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/7477-2c64e42760f82f33.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/7505-47002b76ff1aef6c.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/7600-11884ca4da68e5d9.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/7607.40d8bb3689697ccb.js +0 -62
  734. package/apps/pwa/out/_next/static/chunks/7763.f51fcc19ca1414ec.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/7785.846140c859b1adf6.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/7807-a0fdac6393e0bf36.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/7837-20a63b4b7e9342b1.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/800.7815414cf280545d.js +0 -1
  739. package/apps/pwa/out/_next/static/chunks/8085-1e5fce59500a2cc2.js +0 -1
  740. package/apps/pwa/out/_next/static/chunks/8100.415f2105faa63e97.js +0 -1
  741. package/apps/pwa/out/_next/static/chunks/8290.701aa42ed13aa767.js +0 -226
  742. package/apps/pwa/out/_next/static/chunks/83a80514-b897b64df43ce108.js +0 -1
  743. package/apps/pwa/out/_next/static/chunks/8444.d9c74214a3145a43.js +0 -93
  744. package/apps/pwa/out/_next/static/chunks/8569.98c915534928c7f9.js +0 -24
  745. package/apps/pwa/out/_next/static/chunks/8591.b1c7f876e5ec7cfb.js +0 -1
  746. package/apps/pwa/out/_next/static/chunks/8715-f63756021d3ab989.js +0 -1
  747. package/apps/pwa/out/_next/static/chunks/8879.776c2ec7732aa114.js +0 -115
  748. package/apps/pwa/out/_next/static/chunks/8881.ddca15b3c82c490c.js +0 -1
  749. package/apps/pwa/out/_next/static/chunks/8946.5da5c87f32a2e1a8.js +0 -41
  750. package/apps/pwa/out/_next/static/chunks/9117.080b9b75be90e14d.js +0 -74
  751. package/apps/pwa/out/_next/static/chunks/9167.f3ecb28f367d6e69.js +0 -94
  752. package/apps/pwa/out/_next/static/chunks/9224.66095370ee28c93b.js +0 -1
  753. package/apps/pwa/out/_next/static/chunks/9238-0682b013c83d6449.js +0 -1
  754. package/apps/pwa/out/_next/static/chunks/9449.d3ed795da4befb1c.js +0 -1
  755. package/apps/pwa/out/_next/static/chunks/9638-d268329f2c6f4f8d.js +0 -1
  756. package/apps/pwa/out/_next/static/chunks/973cbf1b.3bbcf2b41548eca7.js +0 -1
  757. package/apps/pwa/out/_next/static/chunks/9842-d6644eb53d3dc6bf.js +0 -1
  758. package/apps/pwa/out/_next/static/chunks/9863.94ca3263e760696e.js +0 -1
  759. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-d9babd8795f396a5.js +0 -1
  760. package/apps/pwa/out/_next/static/chunks/app/approvals/page-5ab1e47978577c5e.js +0 -1
  761. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-24453f6a302816b4.js +0 -1
  762. package/apps/pwa/out/_next/static/chunks/app/board/page-6c131d30bb1cf871.js +0 -1
  763. package/apps/pwa/out/_next/static/chunks/app/bots/page-dc0772b11861af51.js +0 -1
  764. package/apps/pwa/out/_next/static/chunks/app/ceo/page-66ad46ed0279feb9.js +0 -1
  765. package/apps/pwa/out/_next/static/chunks/app/chat/page-5159dc8752c6cd29.js +0 -1
  766. package/apps/pwa/out/_next/static/chunks/app/consult/page-c5a2478861c08b87.js +0 -1
  767. package/apps/pwa/out/_next/static/chunks/app/control/page-f722a9dec084e08b.js +0 -1
  768. package/apps/pwa/out/_next/static/chunks/app/decisions/page-256ffd365d32e100.js +0 -1
  769. package/apps/pwa/out/_next/static/chunks/app/design-check/page-e0de78ae7b99f01c.js +0 -1
  770. package/apps/pwa/out/_next/static/chunks/app/editor/page-cfbdc44b708d9801.js +0 -1
  771. package/apps/pwa/out/_next/static/chunks/app/exec/page-4c741eb760f2f77c.js +0 -1
  772. package/apps/pwa/out/_next/static/chunks/app/field/page-e9ba98f5f1440a21.js +0 -1
  773. package/apps/pwa/out/_next/static/chunks/app/healthz/route-d9babd8795f396a5.js +0 -1
  774. package/apps/pwa/out/_next/static/chunks/app/inside/page-dafc901bb1b72b5f.js +0 -1
  775. package/apps/pwa/out/_next/static/chunks/app/intake/page-2f6f303fa114ec24.js +0 -1
  776. package/apps/pwa/out/_next/static/chunks/app/layout-1634081c5272006c.js +0 -1
  777. package/apps/pwa/out/_next/static/chunks/app/live-run/page-bb1f05cd51c38944.js +0 -1
  778. package/apps/pwa/out/_next/static/chunks/app/loops/page-646b50f63b6fe732.js +0 -1
  779. package/apps/pwa/out/_next/static/chunks/app/market/page-db069b48a59c8c00.js +0 -1
  780. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-f736324afa2117c1.js +0 -1
  781. package/apps/pwa/out/_next/static/chunks/app/morning/page-6f131b51193a36f9.js +0 -1
  782. package/apps/pwa/out/_next/static/chunks/app/not-found-435f5e2faf02bc01.js +0 -1
  783. package/apps/pwa/out/_next/static/chunks/app/observatory/page-497e0eedf20e7890.js +0 -1
  784. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-a8d28fdf995e16ea.js +0 -1
  785. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-8966452228753c5e.js +0 -1
  786. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-fd5d18656cb432b6.js +0 -1
  787. package/apps/pwa/out/_next/static/chunks/app/outputs/page-5663779cb1a37609.js +0 -1
  788. package/apps/pwa/out/_next/static/chunks/app/page-66a67eb19ebd976b.js +0 -1
  789. package/apps/pwa/out/_next/static/chunks/app/reflection/page-3b492aa78cf3c4a6.js +0 -1
  790. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-c71267e7681da982.js +0 -1
  791. package/apps/pwa/out/_next/static/chunks/app/sessions/page-a21d1e1797172692.js +0 -1
  792. package/apps/pwa/out/_next/static/chunks/app/settings/page-781cfc5114e097da.js +0 -1
  793. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-478157214db6a023.js +0 -1
  794. package/apps/pwa/out/_next/static/chunks/app/setup/layout-d9babd8795f396a5.js +0 -1
  795. package/apps/pwa/out/_next/static/chunks/app/setup/page-86141f12cf090b7f.js +0 -1
  796. package/apps/pwa/out/_next/static/chunks/app/share/page-7256c73bb1c36751.js +0 -1
  797. package/apps/pwa/out/_next/static/chunks/app/showroom/page-5c738ca7adef3de5.js +0 -1
  798. package/apps/pwa/out/_next/static/chunks/app/tasks/page-0138c8091ec17224.js +0 -1
  799. package/apps/pwa/out/_next/static/chunks/app/term/page-cc2f24f16d85e735.js +0 -1
  800. package/apps/pwa/out/_next/static/chunks/app/today/page-979d318a534e92da.js +0 -1
  801. package/apps/pwa/out/_next/static/chunks/app/trace/page-182d394f7e6e096b.js +0 -1
  802. package/apps/pwa/out/_next/static/chunks/app/vault/page-21050928a697ed7a.js +0 -1
  803. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-44b9d807005a9030.js +0 -1
  804. package/apps/pwa/out/_next/static/chunks/app/workflows/page-601fb77340e63c9a.js +0 -1
  805. package/apps/pwa/out/_next/static/chunks/app/workspace/page-75d3fb5d47af0edf.js +0 -1
  806. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-11bf9e5725a72c22.js +0 -1
  807. package/apps/pwa/out/_next/static/chunks/dcf24383-2f82e35f2d827393.js +0 -1
  808. package/apps/pwa/out/_next/static/chunks/framework-bf135b997155e90e.js +0 -1
  809. package/apps/pwa/out/_next/static/chunks/main-5571537543bea91c.js +0 -1
  810. package/apps/pwa/out/_next/static/chunks/main-app-25c51c7df7f3a442.js +0 -1
  811. package/apps/pwa/out/_next/static/chunks/pages/_app-e3b2c1f5d82abd65.js +0 -1
  812. package/apps/pwa/out/_next/static/chunks/pages/_error-083f2e23e9bc3641.js +0 -1
  813. package/apps/pwa/out/_next/static/chunks/webpack-e94d22b7a028217b.js +0 -1
  814. package/src/dashboard/bench-slash-runtime.ts +0 -40
  815. package/src/dashboard/input/search-modal-router.ts +0 -9
  816. package/src/dashboard/modals/pane-key-router.ts +0 -27
  817. package/src/dashboard/view-slash-runtime.ts +0 -48
  818. /package/apps/pwa/out/_next/static/{y1ltt7oCZxVpC6zVPhZ2O → LSXfY0u9QtfDbejY0Ukf_}/_ssgManifest.js +0 -0
@@ -7,7 +7,7 @@
7
7
  import { C, stripAnsi, truncate, visibleWidth } from '../tui.js';
8
8
  import type { FoldMode } from '../log-entry.js';
9
9
  import { paneTitle } from './pane-title.js';
10
- import { highlightLineSegments } from '../log-pane/search.js';
10
+ import { highlightLineSegments, type LogSearchResult } from '../log-pane/search.js';
11
11
  import type { PaneSpec, RenderCtx } from '../plugins/core/types.js';
12
12
 
13
13
  export interface LogPaneState {
@@ -60,6 +60,64 @@ export interface LogPaneViewport {
60
60
  visibleLineIndices: number[];
61
61
  }
62
62
 
63
+ /** Dashboard scroll offsets count painted rows, while freeze/copy indices
64
+ * still address original entries. Match the pane's filter before scrolling.
65
+ * The common no-filter path counts delimiters without allocating rows. */
66
+ export function physicalLogRowCount(
67
+ lines: readonly string[],
68
+ beforeIndex = lines.length,
69
+ filterQuery = '',
70
+ ): number {
71
+ let count = 0;
72
+ const query = filterQuery.trim().toLowerCase();
73
+ for (let i = 0; i < Math.min(beforeIndex, lines.length); i++) {
74
+ const entry = lines[i] ?? '';
75
+ if (query) {
76
+ count += entry.split(/\r\n|\r|\n/).filter(line => stripAnsi(line).toLowerCase().includes(query)).length;
77
+ continue;
78
+ }
79
+ count++;
80
+ for (let j = 0; j < entry.length; j++) {
81
+ if (entry[j] === '\n') count++;
82
+ else if (entry[j] === '\r') {
83
+ count++;
84
+ if (entry[j + 1] === '\n') j++;
85
+ }
86
+ }
87
+ }
88
+ return count;
89
+ }
90
+
91
+ export function visibleSearchRowOffset(
92
+ lines: readonly string[],
93
+ result: LogSearchResult,
94
+ filterQuery = '',
95
+ ): number {
96
+ const precedingRows = physicalLogRowCount(lines, result.lineIdx, filterQuery);
97
+ const entryRowsBeforeMatch = (lines[result.lineIdx] ?? '')
98
+ .split(/\r\n|\r|\n/)
99
+ .slice(0, result.physicalRowInEntry ?? 0);
100
+ const filter = filterQuery.trim().toLowerCase();
101
+ const withinEntry = filter
102
+ ? entryRowsBeforeMatch.filter(line => stripAnsi(line).toLowerCase().includes(filter)).length
103
+ : entryRowsBeforeMatch.length;
104
+ return precedingRows + withinEntry;
105
+ }
106
+
107
+ export function logPaneContentHeight(height: number, hasFooter: boolean, hasQueueRow: boolean): number {
108
+ return Math.max(0, height - 1 - (hasFooter ? (hasQueueRow ? 3 : 2) : 0));
109
+ }
110
+
111
+ export function maxLogPaneScroll(
112
+ lines: readonly string[],
113
+ height: number,
114
+ opts: { filterQuery?: string; frozenTailIndex?: number | null; hasFooter?: boolean; hasQueueRow?: boolean } = {},
115
+ ): number {
116
+ const sourceCount = opts.frozenTailIndex ?? lines.length;
117
+ const visibleRows = physicalLogRowCount(lines, sourceCount, opts.filterQuery);
118
+ return Math.max(0, visibleRows - logPaneContentHeight(height, !!opts.hasFooter, !!opts.hasQueueRow));
119
+ }
120
+
63
121
  function buildScrollStatusLine(opts: {
64
122
  start: number;
65
123
  visibleCount: number;
@@ -96,11 +154,13 @@ export function buildLogPaneViewport(state: LogPaneState, ctx: RenderCtx): LogPa
96
154
  const frozenLines = frozen != null ? state.lines.slice(0, frozen) : state.lines;
97
155
  const hiddenBehindFreeze = frozen != null ? Math.max(0, state.lines.length - frozen) : 0;
98
156
  const filterQuery = state.filterQuery?.trim() ?? '';
99
- const filtered = frozenLines.flatMap((line, index) => {
100
- if (!filterQuery) return [{ line, index }];
101
- return stripAnsi(line).toLowerCase().includes(filterQuery.toLowerCase())
102
- ? [{ line, index }]
103
- : [];
157
+ // Each source entry can contain embedded newlines. Expand it before
158
+ // viewport math so one array item never paints over the footer/input rows.
159
+ const physicalLines = frozenLines.flatMap((entry, index) =>
160
+ entry.split(/\r\n|\r|\n/).map(line => ({ line, index })));
161
+ const filtered = physicalLines.filter(({ line }) => {
162
+ if (!filterQuery) return true;
163
+ return stripAnsi(line).toLowerCase().includes(filterQuery.toLowerCase());
104
164
  });
105
165
  const visibleLines = filtered.map(item => item.line);
106
166
  const visibleLineIndices = filtered.map(item => item.index);
@@ -130,8 +190,7 @@ export function buildLogPaneViewport(state: LogPaneState, ctx: RenderCtx): LogPa
130
190
  // breathing gap above + 1-row footer) so the streamed text doesn't
131
191
  // feel crammed against the indicator.
132
192
  const hasQueueRow = hasFooter && state.queueRow != null && state.queueRow !== '';
133
- const footerReserve = hasFooter ? (hasQueueRow ? 3 : 2) : 0;
134
- const contentH = Math.max(0, bodyH - footerReserve);
193
+ const contentH = logPaneContentHeight(ctx.height, hasFooter, hasQueueRow);
135
194
  const maxScroll = Math.max(0, visibleLines.length - contentH);
136
195
  const start = state.scrollOffset < 0
137
196
  ? maxScroll
@@ -225,3 +225,47 @@ export function describePreset(p: PersonaPreset): string[] {
225
225
  ` 하지 않는 것: ${p.doesNot.join(' / ')}`,
226
226
  ];
227
227
  }
228
+
229
+ // ── 0.2.29 PERSONA-STARTER — 첫 실행 직업 질문의 «경영» 스타터 계약 ────────
230
+ //
231
+ // persona-presets/*.yaml(MK 카탈로그)와는 다른 층이다: 첫 실행 wizard 의 직업
232
+ // 질문에서 «경영»을 고른 순간 «한 장» 만들어 주는 계약 원본. 카탈로그 YAML
233
+ // 원본은 그대로 두고 이 계약은 presets.ts 에서 정의해 기존 clonePreset 파이프라인으로
234
+ // persona store 에 복제한다(마케팅·현장·교육 스타터는 후속 조각).
235
+
236
+ /** 첫 실행 «경영» 스타터 — persona store 에 정확히 한 장 쓰인다. */
237
+ const MANAGEMENT_STARTER_PRESET: PersonaPreset = {
238
+ personaId: 'starter-management',
239
+ displayName: '경영 스타터',
240
+ names: ['경영 스타터', '경영', 'starter-management'],
241
+ role: '경영 파트너',
242
+ title: '첫 실행 스타터',
243
+ oneLine: '회사 방향·판단·운영을 같이 세우는 짝.',
244
+ voice: {
245
+ rule: '짧고 단정하게 — 결론 먼저, 근거 한 줄.',
246
+ examples: [
247
+ '이번 주 우선순위는 셋뿐입니다. 첫째는 매출 회수입니다.',
248
+ '그 결정은 근거가 부족합니다 — 가장 싼 실험부터 하시죠.',
249
+ ],
250
+ },
251
+ tasks: [
252
+ { when: '아침 루프', what: '할 일·일정·미결 회의를 한 화면에 모아 첫 판단을 준다' },
253
+ { when: '판단이 갈릴 때', what: '선택지를 셋으로 좁혀 근거·비용·되돌림 수단을 나란히 놓는다' },
254
+ { when: '주간 정산', what: '지난 결정과 실제 결과를 대조해 다음 판단 기준을 고친다' },
255
+ ],
256
+ tools: [],
257
+ firstQuestions: [
258
+ '지금 가장 급한 경영 판단은 무엇인가요?',
259
+ '이번 주에 꼭 정해야 할 일이 있나요?',
260
+ ],
261
+ doesNot: [
262
+ '회사 기밀을 외부에 전송하지 않는다',
263
+ '합의되지 않은 지출·계약을 대신 실행하지 않는다',
264
+ ],
265
+ forWhom: '처음 elanous 를 여는 경영자 — 방향·판단·운영을 함께 시작하려는 사람.',
266
+ };
267
+
268
+ /** 첫 실행 «경영» 선택이 부르는 유일한 제작 입구 — 스타터 계약 한 장을 persona store 에 쓴다. */
269
+ export function createManagementStarterContract(opts: PersonaWriteOptions = {}): PersonaWriteResult {
270
+ return clonePreset(MANAGEMENT_STARTER_PRESET, MANAGEMENT_STARTER_PRESET.displayName, opts);
271
+ }
@@ -0,0 +1,41 @@
1
+ import { lstatSync, readFileSync, realpathSync, writeFileSync } from 'node:fs';
2
+ import { basename, dirname, join, resolve } from 'node:path';
3
+ import { loadPluginManifestFromDir } from '../core/manifest.js';
4
+ import type { PluginDraft } from './plugin-maker.js';
5
+
6
+ export interface MakeConnectorOptions {
7
+ dir: string;
8
+ gap: PluginDraft['connectors'][number];
9
+ id: string;
10
+ }
11
+
12
+ /** Add one connector's credential-name-only draft to the existing extension manifest. */
13
+ export function makeConnector({ dir: inputDir, gap, id }: MakeConnectorOptions): string {
14
+ if (!/^[a-z0-9][a-z0-9-]{1,31}$/.test(id) || !gap || !gap.name.trim() || gap.name === '미확인'
15
+ || !gap.use.trim() || !Array.isArray(gap.evidence) || !gap.evidence.every(source => typeof source === 'string')
16
+ || !Array.isArray(gap.missingCredentials)) throw new Error('invalid connector gap or id');
17
+ const dir = resolve(inputDir);
18
+ const path = join(dir, 'plugin.json');
19
+ const stat = lstatSync(path, { throwIfNoEntry: false });
20
+ if (!stat?.isFile() || stat.isSymbolicLink() || lstatSync(dir).isSymbolicLink()
21
+ || realpathSync(dir) !== join(realpathSync(dirname(dir)), basename(dir))) {
22
+ throw new Error('plugin.json missing or unsafe');
23
+ }
24
+ const raw: unknown = JSON.parse(readFileSync(path, 'utf8'));
25
+ if (!raw || typeof raw !== 'object' || Array.isArray(raw)) throw new Error('invalid plugin.json');
26
+ const data = raw as Record<string, unknown>;
27
+ const extensions = data.extensions as Record<string, unknown> | undefined;
28
+ const extension = extensions?.['ai.elanous'];
29
+ if (!extension || typeof extension !== 'object' || Array.isArray(extension)) throw new Error('missing ai.elanous extension');
30
+ const entry = extension as Record<string, unknown>;
31
+ if (entry.connectors !== undefined && !Array.isArray(entry.connectors)) throw new Error('invalid connectors');
32
+ const manifest = loadPluginManifestFromDir(dir, { id: 'local-plugin' }).manifest;
33
+ if (manifest.contributes.connectors?.some(connector => connector.id === id)) throw new Error(`connector already exists: ${id}`);
34
+ const credentials = gap.missingCredentials.filter(name => /^[A-Za-z_][A-Za-z0-9_-]*$/.test(name));
35
+ if (new Set(credentials).size !== credentials.length) throw new Error('duplicate connector credential name');
36
+ entry.connectors = [...(entry.connectors as unknown[] | undefined ?? []), {
37
+ id, fields: credentials.map(name => ({ name, secret: true })),
38
+ }];
39
+ writeFileSync(path, JSON.stringify(data, null, 2) + '\n');
40
+ return path;
41
+ }
@@ -0,0 +1,42 @@
1
+ import { lstatSync, mkdirSync, realpathSync, writeFileSync } from 'node:fs';
2
+ import { basename, dirname, join, resolve } from 'node:path';
3
+ import { stringify as stringifyYaml } from 'yaml';
4
+ import { loadPluginManifestFromDir } from '../core/manifest.js';
5
+ import type { PluginDraft } from './plugin-maker.js';
6
+
7
+ export interface MakeSkillOptions {
8
+ dir: string;
9
+ gap: PluginDraft['skills'][number];
10
+ id: string;
11
+ }
12
+
13
+ /** Write one researched skill as the wizard's SKILL.md draft, without altering the plugin manifest. */
14
+ export function makeSkill({ dir: inputDir, gap, id }: MakeSkillOptions): string {
15
+ if (!/^[a-z0-9][a-z0-9-]{1,31}$/.test(id) || !gap || !gap.name.trim() || gap.name === '미확인'
16
+ || !gap.use.trim() || !Array.isArray(gap.evidence) || !gap.evidence.every(source => typeof source === 'string')) {
17
+ throw new Error('invalid skill gap or id');
18
+ }
19
+ const dir = resolve(inputDir);
20
+ const manifestPath = join(dir, 'plugin.json');
21
+ const manifestEntry = lstatSync(manifestPath, { throwIfNoEntry: false });
22
+ if (!manifestEntry?.isFile() || manifestEntry.isSymbolicLink()) {
23
+ throw new Error('plugin.json missing or unsafe');
24
+ }
25
+ loadPluginManifestFromDir(dir, { id: 'local-plugin' });
26
+ const skillsDir = join(dir, 'skills');
27
+ const skillDir = join(skillsDir, id);
28
+ const path = join(skillDir, 'SKILL.md');
29
+ // An ancestor can be a platform alias (macOS /var -> /private/var); the plugin directory itself cannot be a link.
30
+ if (lstatSync(dir).isSymbolicLink()
31
+ || realpathSync(dir) !== join(realpathSync(dirname(dir)), basename(dir))) {
32
+ throw new Error('unsafe plugin directory');
33
+ }
34
+ const skillsEntry = lstatSync(skillsDir, { throwIfNoEntry: false });
35
+ if (skillsEntry && !skillsEntry.isDirectory()) throw new Error('unsafe skills directory');
36
+ if (lstatSync(skillDir, { throwIfNoEntry: false })) throw new Error(`skill already exists: ${id}`);
37
+ const instructions = gap.use + (gap.evidence.length ? `\n\nResearch sources:\n${gap.evidence.join(', ')}` : '');
38
+ const content = `---\n${stringifyYaml({ name: id, description: gap.use, requires: [] })}---\n\n${instructions}\n`;
39
+ mkdirSync(skillDir, { recursive: true });
40
+ writeFileSync(path, content, { flag: 'wx' });
41
+ return path;
42
+ }
@@ -63,8 +63,9 @@ export function generateWizardFiles(dir: string, slug: string, draft: WizardRese
63
63
  }
64
64
  const skillPath = join(dir, `skills/${slug}/SKILL.md`);
65
65
  const readmePath = join(dir, 'README.md');
66
- const wizardReadme = options.regenerate && existsSync(readmePath) &&
67
- readFileSync(readmePath, 'utf8').includes('Research draft only. Connector declarations contain credential names, not values.');
66
+ const readmeNotice = 'Research draft only. Connector declarations contain credential names, not values. The graph cannot perform the requested processing yet: implement and validate its steps, then remove extensions["ai.elanous"].researchDraft from plugin.json before installing or running it. No messages are sent.';
67
+ const wizardReadme = options.regenerate && existing && existsSync(readmePath) &&
68
+ readFileSync(readmePath, 'utf8') === `# ${slug}\n\n${existing.description}\n\n${readmeNotice}\n`;
68
69
  if (options.regenerate) {
69
70
  if (!existing || existing.extensions['ai.elanous'].researchDraft !== true || !existsSync(skillPath)) {
70
71
  throw new Error('wizard regeneration requires an existing research draft');
@@ -80,7 +81,8 @@ export function generateWizardFiles(dir: string, slug: string, draft: WizardRese
80
81
  requires: undefined as { knowledgePacks?: string[]; [key: string]: unknown } | undefined,
81
82
  extensions: { 'ai.elanous': { graphs: [`./graphs/${slug}.yaml`],
82
83
  capabilities: ['fs:workdir', 'proc:bun', 'proc:elanous'], connectors: [] as unknown[], researchDraft: true } } };
83
- if (options.regenerate) manifest.description = draft.description;
84
+ // A maker scaffold may have no description or an earlier description; the research draft owns this field.
85
+ manifest.description = draft.description;
84
86
  if (draft.requires?.knowledgePacks !== undefined) {
85
87
  manifest.requires = { ...manifest.requires, knowledgePacks: [...new Set(draft.requires.knowledgePacks)] };
86
88
  }
@@ -108,7 +110,7 @@ console.log(JSON.stringify({ outcome: 'fail', error: step === 'prepare' || step
108
110
  process.exitCode = 1;
109
111
  `],
110
112
  ['examples/input.json', '{}\n'],
111
- ['README.md', `# ${slug}\n\n${draft.description}\n\nResearch draft only. Connector declarations contain credential names, not values. The graph cannot perform the requested processing yet: implement and validate its steps, then remove extensions["ai.elanous"].researchDraft from plugin.json before installing or running it. No messages are sent.\n`],
113
+ ['README.md', `# ${slug}\n\n${draft.description}\n\n${readmeNotice}\n`],
112
114
  [`skills/${slug}/SKILL.md`, `---\n${stringifyYaml({ name: slug, description: draft.skill?.description ?? draft.description, requires: [...new Set(requires)] })}---\n\n${draft.skill?.instructions ?? draft.description}\n`],
113
115
  ];
114
116
  const generated = existing ? files.filter(([path]) => path === 'plugin.json' || path.startsWith('skills/') ||
@@ -0,0 +1,288 @@
1
+ /** Shared PR inventory and creation guard for the CLI and harness. All incomplete reads stay unknown. */
2
+ import { debug } from '../debug/log.js';
3
+ import { existsSync, mkdirSync, readFileSync, writeFileSync } from 'node:fs';
4
+ import { join } from 'node:path';
5
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
6
+ import { withFileLockSync } from '../storage/file-lock.js';
7
+ import { resolveHostId } from '../platform/host-id.js';
8
+
9
+ export interface PrToolCommandResult { ok: boolean; out: string; err?: string }
10
+ export type PrToolCommand = (command: string, args: readonly string[], opts?: { cwd?: string }) => PrToolCommandResult;
11
+ export type Seat = 'OP' | 'TC' | 'MK' | 'UX';
12
+ export interface OpenPr {
13
+ number: number;
14
+ title: string;
15
+ draft: boolean;
16
+ updatedAt: string;
17
+ headSha: string;
18
+ labels: readonly string[];
19
+ files: readonly string[];
20
+ seat: Seat | null;
21
+ lastCommitAt?: string;
22
+ cellId: string | null;
23
+ hunks?: readonly DiffHunk[];
24
+ }
25
+ export type Inventory = { status: 'checked'; prs: readonly OpenPr[] } | { status: 'unknown'; reason: string };
26
+ export interface CensusRow { seat: Seat | 'unknown'; open: number; goalOnly: number; staleDraft: number; supersededOpen: number }
27
+ export type Census = { status: 'checked'; total: number; rows: readonly CensusRow[]; closeCandidates: readonly { number: number; reason: 'goal-only' | 'stale-draft' | 'superseded-open' }[] }
28
+ | { status: 'unknown'; reason: string };
29
+ export interface DiffHunk { path: string; start: number; end: number }
30
+ export type GuardCode = 'inventory-unknown' | 'candidate-unknown' | 'goal-only' | 'file-overlap' | 'hunk-overlap' | 'same-cell' | 'seat-cap' | 'seat-unattributed';
31
+ export interface GuardReason { code: GuardCode; detail: string; prs?: readonly number[] }
32
+ export interface GuardVerdict { status: 'allow' | 'refuse' | 'unknown'; reasons: readonly GuardReason[]; warnings: readonly GuardReason[] }
33
+
34
+ const SEATS = ['OP', 'TC', 'MK', 'UX'] as const;
35
+ const DEFAULT_SEAT_CAP = 30;
36
+ const DRAFT_STALE_MS = 2 * 24 * 60 * 60 * 1000;
37
+ const MAX_PAGES = 100;
38
+ const MAX_FILES = 3000; // GitHub does not expose more than 3000 PR files.
39
+ const UNMEASURED_WINDOW_MS = 60 * 60 * 1000;
40
+ const UNMEASURED_ALLOW_COUNT = 3;
41
+
42
+ function unknown(reason: string): Inventory { return { status: 'unknown', reason }; }
43
+ function seatValue(value: unknown): Seat | null { return SEATS.find(seat => seat === value) ?? null; }
44
+ function seatFromLabels(labels: readonly string[]): Seat | null {
45
+ return SEATS.find(seat => labels.includes(`seat:${seat}`)) ?? null;
46
+ }
47
+ export function cellIdFromBody(body: string): string | null {
48
+ return /^\s*(?:[-*]\s*)?칸\s*:\s*([A-Z][A-Z0-9-]{2,})\s*$/m.exec(body)?.[1] ?? null;
49
+ }
50
+
51
+ export function parseDiffHunks(patch: string): DiffHunk[] {
52
+ const hunks: DiffHunk[] = [];
53
+ let path: string | null = null;
54
+ let fileHeaderPending = false;
55
+ for (const line of patch.split('\n')) {
56
+ if (line.startsWith('diff --git ')) { path = null; fileHeaderPending = true; continue; }
57
+ if (fileHeaderPending && line.startsWith('--- ')) {
58
+ if (line.startsWith('--- a/')) path = line.slice('--- a/'.length);
59
+ continue;
60
+ }
61
+ if (fileHeaderPending && line.startsWith('+++ ')) {
62
+ if (line.startsWith('+++ b/')) path = line.slice('+++ b/'.length);
63
+ fileHeaderPending = false;
64
+ continue;
65
+ }
66
+ const match = /^@@ -(\d+)(?:,(\d+))? \+(\d+)(?:,(\d+))? @@/.exec(line);
67
+ if (path && match) {
68
+ // This is an approximate comparison of old-side lines; PRs with different
69
+ // base trees can shift line numbers. The full merge gate remains authoritative.
70
+ // An insertion or new file has no old-side lines: use its insertion anchor.
71
+ const oldStart = Number(match[1]);
72
+ const oldCount = match[2] === undefined ? 1 : Number(match[2]);
73
+ const start = oldCount === 0 && oldStart === 0 ? Number(match[3]) : oldStart;
74
+ const count = oldCount === 0 ? 1 : oldCount;
75
+ hunks.push({ path, start, end: start + Math.max(1, count) - 1 });
76
+ }
77
+ }
78
+ return hunks;
79
+ }
80
+
81
+ /** `gh api --paginate --slurp` must return every REST page, including the last page. */
82
+ function pages(run: PrToolCommand, endpoint: string, cwd?: string): readonly unknown[] {
83
+ const result = run('gh', ['api', '--paginate', '--slurp', endpoint], cwd ? { cwd } : undefined);
84
+ if (!result.ok) throw new Error(`gh api ${endpoint}: ${result.err || result.out || '조회 실패'}`);
85
+ let parsed: unknown;
86
+ try { parsed = JSON.parse(result.out); } catch { throw new Error(`gh api ${endpoint}: JSON 오류`); }
87
+ if (!Array.isArray(parsed) || parsed.length >= MAX_PAGES || !parsed.every(page => Array.isArray(page) && page.length <= 100)) {
88
+ throw new Error(`gh api ${endpoint}: 페이지 형식·상한 판정 불가`);
89
+ }
90
+ return parsed.flat();
91
+ }
92
+
93
+ function object(value: unknown): Record<string, unknown> {
94
+ if (value === null || typeof value !== 'object' || Array.isArray(value)) throw new Error('PR 응답 행 형식 오류');
95
+ return value as Record<string, unknown>;
96
+ }
97
+ function text(value: unknown, name: string): string {
98
+ if (typeof value !== 'string' || !value.trim()) throw new Error(`${name} 누락`);
99
+ return value;
100
+ }
101
+ function date(value: unknown, name: string): string {
102
+ const raw = text(value, name);
103
+ if (!Number.isFinite(Date.parse(raw))) throw new Error(`${name} 날짜 오류`);
104
+ return raw;
105
+ }
106
+ function pathsForPr(run: PrToolCommand, number: number, cwd?: string): string[] {
107
+ const rows = pages(run, `repos/{owner}/{repo}/pulls/${number}/files?per_page=100`, cwd);
108
+ if (rows.length >= MAX_FILES) throw new Error(`PR #${number}: 파일 ${MAX_FILES}개 GitHub 상한에 닿음`);
109
+ return rows.map(row => text(object(row).filename, `PR #${number} 파일명`));
110
+ }
111
+
112
+ /** Fast file projection; the REST page census below remains the authority for which PRs exist. */
113
+ function projectedFiles(run: PrToolCommand, count: number, cwd?: string): Map<number, string[]> {
114
+ const result = run('gh', ['pr', 'list', '--state', 'open', '--limit', String(Math.max(count, 1)), '--json', 'number,changedFiles,files'], cwd ? { cwd } : undefined);
115
+ if (!result.ok) return new Map();
116
+ let rows: unknown;
117
+ try { rows = JSON.parse(result.out); } catch { return new Map(); }
118
+ if (!Array.isArray(rows)) return new Map();
119
+ const projection = new Map<number, string[]>();
120
+ for (const value of rows) {
121
+ try {
122
+ const row = object(value);
123
+ if (!Number.isSafeInteger(row.number) || (row.number as number) <= 0 || !Number.isSafeInteger(row.changedFiles) || (row.changedFiles as number) < 0 || !Array.isArray(row.files)) continue;
124
+ const paths = row.files.map(file => text(object(file).path, 'PR 파일명'));
125
+ if (paths.length === row.changedFiles && paths.length < MAX_FILES && !projection.has(row.number as number)) projection.set(row.number as number, paths);
126
+ } catch { /* malformed projection: REST file endpoint below decides this PR */ }
127
+ }
128
+ return projection;
129
+ }
130
+
131
+ export function readOpenPrs(run: PrToolCommand, options: {
132
+ cwd?: string;
133
+ seatOfPr?: (pr: { number: number; headRefName: string; body: string; labels: readonly string[] }) => Seat | null;
134
+ includeDraftCommitDates?: boolean;
135
+ candidateFiles?: readonly string[];
136
+ } = {}): Inventory {
137
+ try {
138
+ const rows = pages(run, 'repos/{owner}/{repo}/pulls?state=open&per_page=100', options.cwd);
139
+ const projected = projectedFiles(run, rows.length, options.cwd);
140
+ const prs: OpenPr[] = [];
141
+ const seen = new Set<number>();
142
+ for (const value of rows) {
143
+ const row = object(value);
144
+ const number = row.number;
145
+ if (!Number.isSafeInteger(number) || (number as number) <= 0 || seen.has(number as number)) throw new Error('PR 번호 누락·중복');
146
+ seen.add(number as number);
147
+ if (row.state !== 'open' || typeof row.draft !== 'boolean') throw new Error(`PR #${number}: OPEN 상태·draft 판정 불가`);
148
+ const head = object(row.head);
149
+ const labels = row.labels;
150
+ if (!Array.isArray(labels)) throw new Error(`PR #${number}: 라벨 판정 불가`);
151
+ const labelNames = labels.map(label => text(object(label).name, `PR #${number} 라벨`));
152
+ const headRefName = text(head.ref, `PR #${number} head ref`);
153
+ const headSha = text(head.sha, `PR #${number} head sha`);
154
+ const body = typeof row.body === 'string' ? row.body : '';
155
+ const seat = seatValue(options.seatOfPr?.({ number: number as number, headRefName, body, labels: labelNames })) ?? seatFromLabels(labelNames);
156
+ const pr: OpenPr = {
157
+ number: number as number, title: text(row.title, `PR #${number} title`), draft: row.draft,
158
+ updatedAt: date(row.updated_at, `PR #${number} updated_at`), headSha, labels: labelNames,
159
+ files: projected.get(number as number) ?? pathsForPr(run, number as number, options.cwd), seat,
160
+ cellId: cellIdFromBody(body),
161
+ };
162
+ if (options.candidateFiles?.some(file => pr.files.includes(file))) {
163
+ const patch = run('gh', ['pr', 'diff', String(number), '--patch'], options.cwd ? { cwd: options.cwd } : undefined);
164
+ if (!patch.ok) throw new Error(`PR #${number}: 수정 줄 조회 실패: ${patch.err || patch.out}`);
165
+ pr.hunks = parseDiffHunks(patch.out);
166
+ }
167
+ if (pr.draft && options.includeDraftCommitDates) {
168
+ const commit = run('gh', ['api', `repos/{owner}/{repo}/commits/${headSha}`, '--jq', '.commit.committer.date'], options.cwd ? { cwd: options.cwd } : undefined);
169
+ if (!commit.ok) throw new Error(`PR #${number}: 마지막 커밋 날짜 조회 실패: ${commit.err || commit.out}`);
170
+ pr.lastCommitAt = date(commit.out.trim(), `PR #${number} 마지막 커밋`);
171
+ }
172
+ prs.push(pr);
173
+ }
174
+ return { status: 'checked', prs };
175
+ } catch (error) {
176
+ return unknown(error instanceof Error ? error.message : String(error));
177
+ }
178
+ }
179
+
180
+ export function isGoalOnly(files: readonly string[]): boolean {
181
+ return files.length > 0 && files.every(path => path.startsWith('docs/goals/') && path.length > 'docs/goals/'.length);
182
+ }
183
+
184
+ export function censusOpenPrs(inventory: Inventory, now = Date.now()): Census {
185
+ if (inventory.status === 'unknown') {
186
+ debug.log('pr.tool', 'census', { status: 'unknown', reason: inventory.reason });
187
+ return inventory;
188
+ }
189
+ const rows = new Map<Seat | 'unknown', CensusRow>();
190
+ const closeCandidates: Array<{ number: number; reason: 'goal-only' | 'stale-draft' | 'superseded-open' }> = [];
191
+ for (const pr of inventory.prs) {
192
+ const key = pr.seat ?? 'unknown';
193
+ const row = rows.get(key) ?? { seat: key, open: 0, goalOnly: 0, staleDraft: 0, supersededOpen: 0 };
194
+ row.open += 1;
195
+ if (isGoalOnly(pr.files)) { row.goalOnly += 1; closeCandidates.push({ number: pr.number, reason: 'goal-only' }); }
196
+ if (pr.draft) {
197
+ if (!pr.lastCommitAt) {
198
+ const reason = `PR #${pr.number}: draft 마지막 커밋 날짜 없음`;
199
+ debug.log('pr.tool', 'census', { status: 'unknown', reason });
200
+ return { status: 'unknown', reason };
201
+ }
202
+ if (now - Date.parse(pr.lastCommitAt) >= DRAFT_STALE_MS) { row.staleDraft += 1; closeCandidates.push({ number: pr.number, reason: 'stale-draft' }); }
203
+ }
204
+ if (pr.labels.includes('elanous:superseded')) { row.supersededOpen += 1; closeCandidates.push({ number: pr.number, reason: 'superseded-open' }); }
205
+ rows.set(key, row);
206
+ }
207
+ const result: Census = { status: 'checked', total: inventory.prs.length, rows: [...rows.values()], closeCandidates };
208
+ debug.log('pr.tool', 'census', { status: 'checked', total: result.total, candidates: closeCandidates.length });
209
+ return result;
210
+ }
211
+
212
+ export function guardNewPr(input: { files: readonly string[] | null; seat?: Seat | null; seatCap?: number; cellId?: string | null; hunks?: readonly DiffHunk[] }, inventory: Inventory): GuardVerdict {
213
+ if (!input.files || input.files.length === 0 || input.files.some(file => !file || file.startsWith('/') || file.includes('..'))) {
214
+ const reasons: GuardReason[] = [{ code: 'candidate-unknown', detail: '새 PR 변경 파일을 확인할 수 없음' }];
215
+ debug.log('pr.tool', 'guard-refuse', { status: 'unknown', reasons });
216
+ return { status: 'unknown', reasons, warnings: [] };
217
+ }
218
+ if (inventory.status === 'unknown') {
219
+ const reasons: GuardReason[] = [{ code: 'inventory-unknown', detail: inventory.reason }];
220
+ return { status: 'unknown', reasons, warnings: [] };
221
+ }
222
+ const reasons: GuardReason[] = [];
223
+ const warnings: GuardReason[] = [];
224
+ if (isGoalOnly(input.files)) reasons.push({ code: 'goal-only', detail: '골 문서만 변경 · 구현 0' });
225
+ const candidate = new Set(input.files);
226
+ const sameCell = input.cellId ? inventory.prs.filter(pr => pr.cellId === input.cellId) : [];
227
+ if (sameCell.length) reasons.push({ code: 'same-cell', detail: `같은 칸 ${input.cellId} OPEN PR이 있음`, prs: sameCell.map(pr => pr.number) });
228
+ const overlaps = inventory.prs.filter(pr => pr.files.some(file => candidate.has(file)));
229
+ const sameHunk = overlaps.filter(pr => pr.hunks?.some(other => input.hunks?.some(own => own.path === other.path && own.start <= other.end && other.start <= own.end)));
230
+ if (sameHunk.length) reasons.push({ code: 'hunk-overlap', detail: '같은 파일의 수정 줄 범위가 겹침', prs: sameHunk.map(pr => pr.number) });
231
+ if (overlaps.length) warnings.push({ code: 'file-overlap', detail: '같은 파일의 OPEN PR이 있음 · 줄 겹침은 별도 판정', prs: overlaps.map(pr => pr.number) });
232
+ const seat = seatValue(input.seat);
233
+ if (input.seat !== undefined && input.seat !== null && !seat) reasons.push({ code: 'candidate-unknown', detail: '호출자 자리 값 오류' });
234
+ const cap = input.seatCap ?? DEFAULT_SEAT_CAP;
235
+ if (!Number.isSafeInteger(cap) || cap < 1) {
236
+ reasons.push({ code: 'candidate-unknown', detail: '자리별 PR 상한 설정 오류' });
237
+ } else if (!seat) {
238
+ warnings.push({ code: 'seat-unattributed', detail: `호출자 자리 미상 · 전체 OPEN PR ${inventory.prs.length}건` });
239
+ } else {
240
+ const count = inventory.prs.filter(pr => pr.seat === seat).length;
241
+ if (count >= cap) warnings.push({ code: 'seat-cap', detail: `${seat} OPEN PR ${count}건 · 상한 ${cap}` });
242
+ const unattributed = inventory.prs.filter(pr => pr.seat === null).length;
243
+ if (unattributed) warnings.push({ code: 'seat-unattributed', detail: `귀속 미상 ${unattributed}건 · 전체 OPEN PR ${inventory.prs.length}건` });
244
+ }
245
+ const status = reasons.some(reason => reason.code === 'candidate-unknown') ? 'unknown' : reasons.length ? 'refuse' : 'allow';
246
+ if (status !== 'allow') debug.log('pr.tool', 'guard-refuse', { status, reasons, warnings });
247
+ else if (warnings.length) debug.log('pr.tool', 'guard-warn', { warnings });
248
+ return { status, reasons, warnings };
249
+ }
250
+
251
+ /** Persist the unknown-read budget across harness processes sharing one instance state root. */
252
+ export function recordGuardUnmeasured(input: { seat: Seat | null; reason: string; stateRoot?: string; host?: string; now?: number }): { count: number; blocked: boolean; reason?: string } {
253
+ const now = input.now ?? Date.now();
254
+ const seat = input.seat ?? 'unknown';
255
+ const host = input.host ?? resolveHostId();
256
+ try {
257
+ const dir = join(input.stateRoot ?? effectiveInstanceRoot(), 'pr-tool');
258
+ mkdirSync(dir, { recursive: true });
259
+ const file = join(dir, 'guard-unmeasured.jsonl');
260
+ return withFileLockSync(`${file}.lock`, () => {
261
+ const rows = existsSync(file) ? readFileSync(file, 'utf8').split('\n').filter(Boolean) : [];
262
+ const retained: Array<{ at: number; seat: string; host: string }> = [];
263
+ let count = 0;
264
+ for (const line of rows) {
265
+ let value: unknown;
266
+ try { value = JSON.parse(line); } catch { return { count: 0, blocked: true, reason: '판정 불가 원장 JSON 오류' }; }
267
+ if (value && typeof value === 'object') {
268
+ const row = value as { at?: unknown; seat?: unknown; host?: unknown };
269
+ if (typeof row.at !== 'number' || typeof row.seat !== 'string' || typeof row.host !== 'string') return { count: 0, blocked: true, reason: '판정 불가 원장 행 형식 오류' };
270
+ if (row.at > now - UNMEASURED_WINDOW_MS && row.at <= now) {
271
+ retained.push({ at: row.at, seat: row.seat, host: row.host });
272
+ if (row.seat === seat && row.host === host) count += 1;
273
+ }
274
+ } else return { count: 0, blocked: true, reason: '판정 불가 원장 행 형식 오류' };
275
+ }
276
+ retained.push({ at: now, seat, host });
277
+ count += 1;
278
+ writeFileSync(file, `${retained.map(row => JSON.stringify(row)).join('\n')}\n`);
279
+ const blocked = count > UNMEASURED_ALLOW_COUNT;
280
+ debug.log('pr-tool.open-guard', 'guard-unmeasured', { seat, host, count, blocked, reason: input.reason });
281
+ return { count, blocked };
282
+ });
283
+ } catch (error) {
284
+ const reason = error instanceof Error ? error.message : String(error);
285
+ debug.log('pr-tool.open-guard', 'guard-unmeasured', { seat, host, blocked: true, reason: `원장 오류: ${reason}` });
286
+ return { count: 0, blocked: true, reason };
287
+ }
288
+ }
@@ -85,6 +85,13 @@ export interface PreviewTerminalOpts {
85
85
  * 로 받아 같은 에뮬레이터/탭에 먹인다(정체성·크로스서피스 goto 획득). bun onData-死는 registry bun-native
86
86
  * openpty 가 해결. ⚠️ 라이브 렌더(yazi DA2·마우스·커서·alt-screen) 검증은 기기 세션 필요(대표) → 기본 off. */
87
87
  useRegistry?: boolean;
88
+ /** Shared PTY identity for registry-backed popups. Defaults to preview. */
89
+ registryKind?: string;
90
+ /** Human-readable purpose shown by PTY inventory. */
91
+ registryNickname?: string;
92
+ registryOrigin?: { originRoot: string; controller?: string };
93
+ registryPurpose?: string;
94
+ registrySeat?: string;
88
95
  /** P13 — OSC 9/99/777 notification hook. Fires when the child
89
96
  * emits one of:
90
97
  * ESC ] 9 ; <title> BEL (iTerm2 growl)
@@ -337,7 +344,13 @@ export class PreviewTerminal {
337
344
  this.registryHandle = this.registryDeps.startPty({
338
345
  // 합성자 = registry(resolveSpawnShape) — 여기서는 overlay 만 넘긴다.
339
346
  cmd: shell, args, workdir: this.opts.cwd, env: childEnv,
340
- cols: this.term.cols, rows: this.term.rows, kind: 'preview', accessMode: 'write',
347
+ cols: this.term.cols, rows: this.term.rows,
348
+ kind: this.opts.registryKind ?? 'preview',
349
+ nickname: this.opts.registryNickname,
350
+ origin: this.opts.registryOrigin,
351
+ purpose: this.opts.registryPurpose,
352
+ seat: this.opts.registrySeat,
353
+ accessMode: 'write',
341
354
  });
342
355
  this.alive = true;
343
356
  } else {
@@ -15,6 +15,8 @@
15
15
  export interface LLMUsage {
16
16
  /** Origin provider — lets the metrics module tag accumulated tokens. */
17
17
  provider?: 'anthropic' | 'openai';
18
+ /** 이 사용량을 낸 턴의 모델(내보내는 쪽이 알 때만). 턴 지표가 설정 모델 대신 이것으로 ctx 최대치·단가를 잡는다. */
19
+ model?: string;
18
20
  inputTokens?: number;
19
21
  outputTokens?: number;
20
22
  cacheReadInputTokens?: number;