elanous 0.2.36 → 0.2.38

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 (741) 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/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{9250-072df22eaadaa6b5.js → 1026-44010f405704050c.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +27 -0
  6. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +1 -0
  7. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{4304.e9b2512834a9e23e.js → 1632.7d87f998e714bede.js} +1 -1
  10. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1938.0e6c60ee91c4d7f5.js +148 -0
  14. package/apps/pwa/out/_next/static/chunks/{7784.1f0ac4a16d190cf4.js → 2104.70e086d5174a4736.js} +1 -1
  15. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +1 -0
  16. package/apps/pwa/out/_next/static/chunks/{6566.926a1d1b7c911442.js → 214.186a430da28338f1.js} +1 -1
  17. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +93 -0
  18. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +104 -0
  19. package/apps/pwa/out/_next/static/chunks/{5711.957b095705c12560.js → 2415.738b777642a02233.js} +1 -1
  20. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +1 -0
  22. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +1 -0
  26. package/apps/pwa/out/_next/static/chunks/{4286.b70c4520306817e8.js → 3086.fb14b60ce98b53d3.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/{3148-98efd4869d660a87.js → 3124-561f7f037943cde2.js} +1 -1
  28. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +24 -0
  31. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/{3727.7949ccaacaa71242.js → 3291.f6c1005387d514bd.js} +2 -2
  33. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +36 -0
  34. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +287 -0
  38. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/{8904.7d51af2dc033965c.js → 3528.e4b8ab70d339f965.js} +2 -2
  40. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +1 -0
  41. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +94 -0
  45. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +1 -0
  46. package/apps/pwa/out/_next/static/chunks/3f0de3de-2340c532c00395db.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +1 -0
  48. package/apps/pwa/out/_next/static/chunks/{3031-85328a92fcce4da6.js → 4199-f7c6eb40cd0322f8.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +1 -0
  56. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +32 -0
  57. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +90 -0
  58. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +79 -0
  60. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/5041-5aada92ca215ffdd.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/{528.38ce20ef8aa251ff.js → 5203.51e5d8b5f1dcfe53.js} +16 -16
  65. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +286 -0
  68. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/{2683.c9773a0c589b031b.js → 5307.d7328020227880c2.js} +4 -4
  70. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +8 -0
  73. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/{552.b7d061ad91eeac51.js → 5638.107314dc479e2f37.js} +2 -2
  75. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +1 -0
  78. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6142.913b44e260a3f925.js +64 -0
  80. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/{6925.562d532110879886.js → 6493.27ad77de7aac7966.js} +1 -1
  84. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +62 -0
  88. package/apps/pwa/out/_next/static/chunks/{275-02ea4c2a33980422.js → 7161-8f22db3ec5ed005e.js} +3 -3
  89. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +1 -0
  90. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{3136.30aaaa5fa03662a3.js → 7488.966b116789f3d41a.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/{4116.a84a92a2492c080e.js → 7524.ce973525d30b3d52.js} +1 -1
  94. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +77 -0
  95. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/{3324.a09703033abcbd2f.js → 7628.6b16863ac3972333.js} +1 -1
  97. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/{3410.7f9af5ab77cbe65f.js → 7954.4f7a8832663ee979.js} +1 -1
  100. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/{771.c3cdb6c1f7f47c02.js → 8019.21ca554a821dad01.js} +16 -16
  102. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/{4615.8525eb0add35eba6.js → 8487.291666583bebe640.js} +1 -1
  107. package/apps/pwa/out/_next/static/chunks/8509.3a54d4e61893d7cb.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/{6943.c6b24124853a47b2.js → 8879.ac06755bcf3e44a1.js} +1 -1
  110. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +149 -0
  111. package/apps/pwa/out/_next/static/chunks/{575.d929793a53f27c4b.js → 8911.bf5e712acb25fb6c.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/{9f31e478.fefcbcd3c388ebc5.js → 8994d93e.33ba491f95345fc2.js} +1 -1
  113. package/apps/pwa/out/_next/static/chunks/{da5ecc5c-b005ad8cac737d57.js → 89d6c04f-6b8ab341748e468a.js} +1 -1
  114. package/apps/pwa/out/_next/static/chunks/{599.c39c571b6733f2a2.js → 9223.cbcc88e0e9950426.js} +2 -2
  115. package/apps/pwa/out/_next/static/chunks/9299.24e2a7d9b6d1f91b.js +226 -0
  116. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +24 -0
  117. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{8037.e254fd797aa224d1.js → 9581.da63ddf41acfad46.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +2 -0
  121. package/apps/pwa/out/_next/static/chunks/{ceba0382.650712b56b85b582.js → 9fe1b809.738da85c8b17e3fb.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +1 -0
  123. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/botlab/page-866aac5ff226a7f3.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/outputs/{page-e7abc34a48a6f71e.js → page-291ab19fe2acb173.js} +1 -1
  153. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/term/{page-c15958835534404b.js → page-6b140f77593576eb.js} +1 -1
  166. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/{3a3d9966.cc4d4585a2708e7c.js → b7459770.6539b11860eb8a9c.js} +7 -7
  174. package/apps/pwa/out/_next/static/chunks/{053a429e.9a63436527cc751c.js → b7478fef.5917716286213fcc.js} +3 -3
  175. package/apps/pwa/out/_next/static/chunks/bb6987f9.3647e1a23b0e3217.js +122 -0
  176. package/apps/pwa/out/_next/static/chunks/{2812ca6a.3b9f4a7a08885744.js → de8b930d.d94c0f42acf807fc.js} +1 -1
  177. package/apps/pwa/out/_next/static/chunks/{873d6c12.09bd499f57171543.js → eaad0cba.771200940c529df7.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/framework-4b12a946f352cee2.js +1 -0
  179. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +1 -0
  184. package/apps/pwa/out/_next/static/css/{b5d88eba78a3d7bf.css → be9019f696217521.css} +1 -1
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +23 -23
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +23 -23
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +23 -23
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +22 -22
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +22 -22
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +23 -23
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +22 -22
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +23 -23
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +23 -23
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +22 -22
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +23 -23
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +23 -23
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +23 -23
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +23 -23
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +22 -22
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +22 -22
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +23 -23
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +23 -23
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +23 -23
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +22 -22
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +22 -22
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +22 -22
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +23 -23
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +23 -23
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +22 -22
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +22 -22
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +22 -22
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +22 -22
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +23 -23
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +23 -23
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +22 -22
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +23 -23
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +23 -23
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +23 -23
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +23 -23
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +23 -23
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +22 -22
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +23 -23
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +23 -23
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +23 -23
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +23 -23
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +23 -23
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +23 -23
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +23 -23
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +23 -23
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +23 -23
  278. package/graphs/drafts/recipes.yaml +27 -7
  279. package/graphs/release/recipes.yaml +9 -0
  280. package/graphs/release/release-loop.yaml +26 -18
  281. package/graphs/work/draft-close.yaml +54 -0
  282. package/graphs/work/green-close.yaml +37 -0
  283. package/graphs/work/recipes.yaml +46 -1
  284. package/graphs/work/run-research.yaml +35 -0
  285. package/package.json +1 -1
  286. package/scripts/__fixtures__/authoring-paths-10x3.json +32 -0
  287. package/scripts/ask-op-inbox-once.ts +17 -0
  288. package/scripts/boundary-proof-mapping-audit.ts +88 -0
  289. package/scripts/brand/check.ts +13 -4
  290. package/scripts/codex-fallback-live-probe.ts +17 -15
  291. package/scripts/fleet/node-setup.sh +32 -2
  292. package/scripts/fleet/run-light-worker.sh +9 -0
  293. package/scripts/gate-0226-accepted-remaining-90.txt +91 -0
  294. package/scripts/gate-0226-failure-census.ts +546 -0
  295. package/scripts/goals/authoring-metrics.ts +258 -0
  296. package/scripts/graph-units/draft-close-node.ts +222 -0
  297. package/scripts/hook-order-sweep.ts +7 -4
  298. package/scripts/intake-collect-telegram-saved-stage.ts +48 -0
  299. package/scripts/land-global-checks.ts +69 -1
  300. package/scripts/measure-nl-routing-corpus.ts +207 -2
  301. package/scripts/provision-export-redactions.ts +15 -0
  302. package/scripts/public-copy-lint.ts +122 -0
  303. package/scripts/public-export.ts +69 -2
  304. package/scripts/ratchets/next-tui-entry-budget.ts +124 -0
  305. package/scripts/ratchets/train-side-invariants.sh +7 -1
  306. package/scripts/release-loop/cut-branch.ts +61 -12
  307. package/scripts/release-loop/docs-node.ts +140 -0
  308. package/scripts/release-loop/gate-closure.ts +48 -0
  309. package/scripts/release-loop/gate-diff.ts +2 -1
  310. package/scripts/release-loop/gate-node.ts +161 -25
  311. package/scripts/release-loop/gate-partial.ts +82 -3
  312. package/scripts/release-loop/gate-prewarm-plan.ts +35 -0
  313. package/scripts/release-loop/gate-radius-live.ts +4 -2
  314. package/scripts/release-loop/known-issues-node.ts +6 -4
  315. package/scripts/release-loop/notes-repair.ts +216 -0
  316. package/scripts/release-loop/prepare-node.ts +61 -5
  317. package/scripts/release-loop/resume-cap.ts +2 -1
  318. package/scripts/release-loop/resume-release.ts +406 -7
  319. package/scripts/release-loop/resume-test-traffic.ts +10 -0
  320. package/scripts/release-loop/resume.ts +13 -5
  321. package/scripts/release-loop/traffic-node.ts +12 -4
  322. package/scripts/release-loop/traffic-transition.ts +53 -13
  323. package/scripts/release-loop/version-node.ts +109 -15
  324. package/scripts/train/green-leg.ts +176 -0
  325. package/scripts/tui-continue-real-evidence.ts +47 -0
  326. package/scripts/ux-sim.ts +1 -1
  327. package/scripts/video-pipeline.ts +2 -2
  328. package/src/acp/client.ts +31 -5
  329. package/src/acp/core-turn-bridge.ts +12 -1
  330. package/src/acp/stderr-summary.ts +49 -0
  331. package/src/agent/monad-agent-turn.ts +1 -0
  332. package/src/agent/run-context.ts +1 -1
  333. package/src/agent/task-notification.ts +3 -1
  334. package/src/agent/terminal-surface.ts +217 -0
  335. package/src/agent-substrate/pr-reviewer.ts +11 -3
  336. package/src/agent-substrate/review-observation.ts +10 -0
  337. package/src/agent-substrate/self-review-cli.ts +537 -57
  338. package/src/auto-research/question-ladder-contract.ts +137 -0
  339. package/src/auto-research/research-turn.ts +134 -0
  340. package/src/autopilot/discovery/doc-lint.ts +1 -1
  341. package/src/autopilot/lineage/sources.ts +1 -1
  342. package/src/autopilot/pr-manager.ts +64 -13
  343. package/src/boot/daemon-runtime.ts +35 -3
  344. package/src/boot/daemon-tools/pty-shell.ts +2 -1
  345. package/src/bots/screen-probe.ts +1 -1
  346. package/src/budget/run-usage-rollup.ts +12 -7
  347. package/src/budget/unified-usage.ts +20 -0
  348. package/src/capture/tui-self-report.ts +42 -5
  349. package/src/chat/index.ts +1 -0
  350. package/src/chat/tool-render/dispatch.ts +8 -1
  351. package/src/cli/autopilot-cli.ts +24 -9
  352. package/src/cli/decisions-cli.ts +7 -4
  353. package/src/cli/doctor-cli.ts +116 -7
  354. package/src/cli/guardian-cli.ts +3 -1
  355. package/src/cli/intake-cli.ts +48 -12
  356. package/src/cli/lesson-cli.ts +69 -9
  357. package/src/cli/logs-cli.ts +357 -2
  358. package/src/cli/memory-cli.ts +30 -1
  359. package/src/cli/msg-cli.ts +15 -11
  360. package/src/cli/pr-granularity.ts +5 -3
  361. package/src/cli/pr-land-overlap-evidence.ts +38 -5
  362. package/src/cli/pr-land-refusal.ts +1 -1
  363. package/src/cli/pty-takeover-cli.ts +58 -5
  364. package/src/cli/release-checklist-read-cli.ts +112 -4
  365. package/src/cli/release-cli.ts +89 -18
  366. package/src/cli/review-carry.ts +77 -0
  367. package/src/cli/self-update.ts +24 -6
  368. package/src/cli/self-utterances-cli.ts +13 -16
  369. package/src/cli/tasks-card-show.ts +31 -1
  370. package/src/cli/tasks-cli.ts +370 -33
  371. package/src/cli/tasks-read-cli.ts +13 -5
  372. package/src/cli/usage-cli.ts +12 -10
  373. package/src/context-bus/claude-memory-import.ts +99 -0
  374. package/src/context-bus/context-now.ts +86 -2
  375. package/src/context-bus/long-term-memory.ts +125 -0
  376. package/src/core-turn/run-core-turn.ts +9 -2
  377. package/src/core-turn/run-goal-loop.ts +5 -2
  378. package/src/core-turn/types.ts +5 -0
  379. package/src/dashboard/chat/acp-chat.ts +9 -0
  380. package/src/dashboard/index.ts +115 -30
  381. package/src/dashboard/input/agent-wake.ts +43 -0
  382. package/src/dashboard/input/chat-main-acp-dispatch.ts +21 -1
  383. package/src/dashboard/input/terminal-modal-router.ts +8 -159
  384. package/src/dashboard/replay-preview.ts +25 -0
  385. package/src/dashboard/side-basic-runtime.ts +61 -0
  386. package/src/dashboard/slash-runtime/dashboard-handlers.ts +19 -8
  387. package/src/dashboard/synchronized-frame-output.ts +74 -0
  388. package/src/dashboard/term-slash-runtime.ts +2 -0
  389. package/src/dashboard/turn-preamble.ts +28 -4
  390. package/src/display/coordinator.ts +45 -12
  391. package/src/display/resize-listener.ts +41 -20
  392. package/src/display/synchronized-output-region.ts +60 -0
  393. package/src/domains/guardian-tick.ts +9 -0
  394. package/src/domains/surface-events.ts +80 -1
  395. package/src/exec-requests/planner.ts +37 -2
  396. package/src/execution-loop/launch-gate.ts +4 -3
  397. package/src/git-fs/cli-stderr.ts +45 -0
  398. package/src/git-fs/gh-cli.ts +6 -3
  399. package/src/git-fs/git-cli.ts +11 -5
  400. package/src/git-fs/watcher.ts +27 -22
  401. package/src/git-fs/worktree.ts +19 -3
  402. package/src/graph-runner/graph-cli.ts +26 -2
  403. package/src/graph-runner/graph-grow.ts +37 -9
  404. package/src/graph-runner/graph-run-api.ts +3 -2
  405. package/src/graph-runner/runner.ts +34 -7
  406. package/src/graph-wizard/generate.ts +29 -6
  407. package/src/grok/credential.ts +107 -36
  408. package/src/harness/harness-cli-command.ts +179 -33
  409. package/src/harness/review-adapter.ts +26 -6
  410. package/src/hq/fence-wrapper.ts +1 -1
  411. package/src/hq/transfer.ts +1 -1
  412. package/src/index.ts +151 -18
  413. package/src/instance/test-write-guard-real-transport.fixture.ts +52 -0
  414. package/src/intake-plane/collect-telegram-saved.ts +54 -5
  415. package/src/interactive-terminal-modal.ts +3 -0
  416. package/src/keybindings.ts +17 -22
  417. package/src/llm/provider-credentials.ts +1 -1
  418. package/src/llm/route-decision.ts +13 -0
  419. package/src/llm-tool-name.ts +37 -0
  420. package/src/llm-tool-schema.ts +55 -0
  421. package/src/llm.ts +203 -21
  422. package/src/loops/checker.ts +100 -0
  423. package/src/loops/consensus.ts +26 -2
  424. package/src/loops/loop-cli.ts +9 -4
  425. package/src/loops/orchestrator/anomaly-cluster.ts +243 -0
  426. package/src/loops/orchestrator/inbox-once.ts +28 -0
  427. package/src/loops/orchestrator/inbox.ts +130 -1
  428. package/src/loops/orchestrator/tick.ts +55 -7
  429. package/src/maturity/feature-maturity.ts +1 -0
  430. package/src/model-tier/llm-tier-map.ts +12 -17
  431. package/src/msg/msg-store.ts +17 -0
  432. package/src/native-tool-catalog.ts +1 -1
  433. package/src/nexus/api/channel-ask-op.ts +96 -0
  434. package/src/nexus/api/discord-trigger-bot.ts +28 -1
  435. package/src/nexus/api/graph-wizard-api.ts +27 -2
  436. package/src/nexus/api/grid.ts +24 -4
  437. package/src/nexus/api/http-server.ts +1 -1
  438. package/src/nexus/api/ops-api.ts +14 -6
  439. package/src/nexus/api/telegram-trigger-bot.ts +24 -0
  440. package/src/nexus/api/terminals.ts +28 -6
  441. package/src/nexus/state/state.ts +7 -1
  442. package/src/oauth/codex-account-store.ts +34 -1
  443. package/src/ops/loops-map.ts +46 -0
  444. package/src/ops/overview-cache.ts +22 -4
  445. package/src/ops/overview.ts +41 -5
  446. package/src/patents/ledger.ts +18 -1
  447. package/src/policy/llm-policy.ts +3 -1
  448. package/src/preview/terminal.ts +4 -2
  449. package/src/prompt-cache/anthropic.ts +2 -0
  450. package/src/prompt-enhance/enhance.ts +9 -4
  451. package/src/pty-shell/availability.ts +7 -0
  452. package/src/pty-shell/herdr-agent-report.ts +40 -31
  453. package/src/pty-shell/herdr-prune-stale.ts +17 -0
  454. package/src/pty-shell/herdr-sequence-lease.ts +60 -0
  455. package/src/pty-shell/pty-control-ipc.ts +187 -18
  456. package/src/pty-shell/pty-manifest.ts +16 -2
  457. package/src/pty-shell/registry.ts +25 -15
  458. package/src/pty-shell/tui-run-state.ts +235 -1
  459. package/src/release-loop/checklist.ts +50 -5
  460. package/src/release-loop/feature-store.ts +9 -9
  461. package/src/release-loop/gate-shards.ts +61 -0
  462. package/src/release-loop/landed-but-yellow.ts +93 -12
  463. package/src/release-loop/light-rc.ts +7 -4
  464. package/src/release-loop/rehearsal.ts +1 -1
  465. package/src/repl/index.ts +18 -0
  466. package/src/research/axis-fanout.ts +133 -0
  467. package/src/research/edge-decision.ts +88 -0
  468. package/src/research/output-router.ts +127 -0
  469. package/src/research-bridge/format.ts +16 -1
  470. package/src/research-bridge/index.ts +1 -0
  471. package/src/research-bridge/invoke.ts +41 -5
  472. package/src/seat-loop/seat-report.ts +1 -0
  473. package/src/self-dev/ask-launch-flow.ts +86 -10
  474. package/src/self-dev/decompose-proposal.ts +29 -18
  475. package/src/self-dev/decompose.ts +45 -9
  476. package/src/self-dev/dev-pipeline.ts +29 -7
  477. package/src/self-dev/draft-residue.ts +221 -2
  478. package/src/self-dev/draft-sweep.ts +254 -16
  479. package/src/self-dev/draft-triage-rules.ts +19 -5
  480. package/src/self-dev/orchestrate.ts +1 -0
  481. package/src/self-dev/review-provider-fallback.ts +45 -7
  482. package/src/self-dev/run-supervisor.ts +22 -7
  483. package/src/self-dev/shard-plan.ts +48 -0
  484. package/src/self-dev/shard-run.ts +310 -6
  485. package/src/self-implement/comment-only-source.ts +54 -0
  486. package/src/self-implement/doctor-visit.ts +108 -0
  487. package/src/self-implement/gate-artifacts.ts +6 -2
  488. package/src/self-implement/gate-baseline.ts +99 -1
  489. package/src/self-implement/gate-cli.ts +231 -82
  490. package/src/self-implement/gate-failure-signature.ts +44 -0
  491. package/src/self-implement/gate-remote.ts +30 -4
  492. package/src/self-implement/gate-scope.ts +13 -1
  493. package/src/self-implement/goal-author.ts +407 -21
  494. package/src/self-implement/goal-doc/section.ts +22 -0
  495. package/src/self-implement/goal-supervisor-fill.ts +110 -27
  496. package/src/self-implement/importer-test-index.ts +215 -2
  497. package/src/self-implement/knowhow-pack.ts +125 -12
  498. package/src/self-implement/l8-merge-queue.ts +198 -32
  499. package/src/self-implement/off-diff-evidence.ts +23 -0
  500. package/src/self-implement/orchestrator.ts +369 -33
  501. package/src/self-implement/pod-inplace-worktree.ts +82 -0
  502. package/src/self-implement/pod-warm-pool-profile.ts +2 -2
  503. package/src/self-implement/premise-review.ts +7 -5
  504. package/src/self-implement/review-round-brief.ts +300 -0
  505. package/src/self-implement/rework-policy.ts +14 -0
  506. package/src/self-implement/run-ledger.ts +428 -6
  507. package/src/self-implement/run-stop.ts +1 -1
  508. package/src/self-implement/running-runs.ts +17 -3
  509. package/src/self-implement/seams.ts +45 -16
  510. package/src/self-implement/self-implement-cli.ts +26 -2
  511. package/src/self-implement/stop-autoheal.ts +1 -0
  512. package/src/self-implement/test-seams.ts +13 -1
  513. package/src/self-implement/train-reach-grouping.ts +8 -2
  514. package/src/session/channel-ask-op-envelope.ts +36 -0
  515. package/src/session/channel-op-reply-route.ts +200 -0
  516. package/src/session/chat.ts +10 -1
  517. package/src/session/id-prefix.ts +60 -0
  518. package/src/session/index.ts +6 -0
  519. package/src/session-runtime/index.ts +18 -23
  520. package/src/skills/runner.ts +7 -3
  521. package/src/skills/tools/dev-harness.ts +2 -2
  522. package/src/skills/tools/pty.ts +5 -0
  523. package/src/skills/tools/schedule-wakeup.ts +1 -6
  524. package/src/status/bar.ts +3 -3
  525. package/src/status/metrics.ts +12 -1
  526. package/src/steward/rejudge-tick.ts +12 -5
  527. package/src/steward/resync-tick.ts +31 -4
  528. package/src/storage/file-lock.ts +17 -4
  529. package/src/task-agent/actions.ts +199 -4
  530. package/src/task-agent/adopt-pr.ts +63 -2
  531. package/src/task-agent/boundary-proof-mapping.ts +12 -0
  532. package/src/task-agent/boundary-proof-producer.ts +147 -0
  533. package/src/task-agent/completion-evidence.ts +2 -1
  534. package/src/task-agent/evidence-command-normalize.ts +42 -0
  535. package/src/task-agent/export-redactions-provision.ts +43 -0
  536. package/src/task-agent/green-close-recipe.ts +239 -0
  537. package/src/task-agent/green-sweep.ts +64 -10
  538. package/src/task-agent/live-moves.ts +48 -3
  539. package/src/task-agent/map-host-adapter.ts +134 -0
  540. package/src/task-agent/map-reduce.ts +158 -0
  541. package/src/task-agent/map-run-ledger.ts +226 -0
  542. package/src/task-agent/parent-host.ts +74 -17
  543. package/src/task-agent/rejudge-on-head.ts +72 -5
  544. package/src/task-agent/repair-cycle.ts +108 -8
  545. package/src/task-agent/repair-next-move.ts +12 -2
  546. package/src/task-agent/repair-worker.ts +37 -1
  547. package/src/task-agent/review-prior-fix.ts +12 -2
  548. package/src/task-agent/shadow.ts +188 -5
  549. package/src/task-agent/task-hand.ts +253 -20
  550. package/src/task-agent/task-parent-role-llm.ts +9 -0
  551. package/src/task-agent/tier-split.ts +40 -5
  552. package/src/task-agent/work-order.ts +53 -2
  553. package/src/task-orchestrator/dispatcher.ts +46 -1
  554. package/src/task-orchestrator/generator-prompt.ts +6 -0
  555. package/src/task-orchestrator/surfaces/pod-artifact-return.ts +16 -6
  556. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +31 -4
  557. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +8 -6
  558. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +97 -0
  559. package/src/task-orchestrator/surfaces/pod-pool.ts +77 -8
  560. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +15 -9
  561. package/src/task-orchestrator/surfaces/self-implement-pod.ts +338 -79
  562. package/src/task-orchestrator/surfaces/self-implement.ts +37 -2
  563. package/src/terminal/session-registry.ts +1 -0
  564. package/src/terminal/terminal-modal-router.ts +156 -0
  565. package/src/testing/linux-env.ts +177 -0
  566. package/src/tool-hints/gate.ts +6 -4
  567. package/src/tool-hints/signals.ts +33 -1
  568. package/src/tui/chat/background-job-status.ts +8 -2
  569. package/src/tui/chat/goal-interim.ts +5 -1
  570. package/src/tui/entry.ts +722 -30
  571. package/src/tui/input/at-picker.ts +55 -0
  572. package/src/tui/sidetab/attach.ts +304 -0
  573. package/src/tui/sidetab/list.ts +176 -0
  574. package/src/tui/sidetab/nl-tool.ts +136 -0
  575. package/src/tui/slash/resume-command.ts +23 -0
  576. package/src/tui/slash/resume.ts +38 -35
  577. package/src/tui/slash/signals.ts +114 -0
  578. package/src/tui/slash/term-next.ts +72 -0
  579. package/src/tui-client/local-chat-turn.ts +31 -9
  580. package/src/user-config.ts +30 -3
  581. package/src/ux-sim/boot-daemon-tools-pty-shell-device.ts +136 -0
  582. package/src/ux-sim/classic-tui-seat-scenarios.ts +158 -4
  583. package/src/ux-sim/fake-gh.ts +174 -0
  584. package/src/ux-sim/fake-kubectl.ts +142 -0
  585. package/src/ux-sim/fake-llm.ts +17 -6
  586. package/src/ux-sim/next-tui-seat-scenarios.ts +176 -6
  587. package/src/ux-sim/resume-picker-device.ts +173 -0
  588. package/src/ux-sim/session-id-seed.ts +60 -0
  589. package/src/ux-sim/skills-tools-shell-device.ts +156 -0
  590. package/src/ux-sim/task-agent-parent-host-device.ts +264 -0
  591. package/src/ux-sim/task-agent-rejudge-on-head-device.ts +114 -0
  592. package/src/version/packed-revision.json +1 -1
  593. package/apps/pwa/out/_next/static/chunks/109.f196abf3484bb97f.js +0 -287
  594. package/apps/pwa/out/_next/static/chunks/1201.afbfc5b1c5e5cbe4.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/1517.9275b89572098ff3.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/1574.ad11f8db8396ab45.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/1614.7a8c5c40aee0261f.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/1871-f1eb29d8dbb4065b.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/190.285c832bd9626f8c.js +0 -64
  600. package/apps/pwa/out/_next/static/chunks/2193.0ea24c4a7aa1d004.js +0 -36
  601. package/apps/pwa/out/_next/static/chunks/223-ad865c1e80491d78.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/2265-f0d90b6dbec05f81.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/2267.eb4a62a209f09ec4.js +0 -149
  604. package/apps/pwa/out/_next/static/chunks/2341-86cd06c0cf01aa33.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/2352.9abc42422bade876.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/2397-c1653a816061842d.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/2500.cbc1257b774aae52.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/2709.8e1889034255fc5f.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/284.ac77c0db55bfd3a8.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/2941.3c3546f96bc6efa7.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/2976.b000698a3c6512dc.js +0 -24
  612. package/apps/pwa/out/_next/static/chunks/2986.45d7652e4f13557e.js +0 -2
  613. package/apps/pwa/out/_next/static/chunks/3155.2587a55196ecb394.js +0 -226
  614. package/apps/pwa/out/_next/static/chunks/3277.785db1cf09f98601.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/3320-f9c77381f85a2c0a.js +0 -1
  616. package/apps/pwa/out/_next/static/chunks/3386-91049feabff9a94e.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/339.80afb7e8839372af.js +0 -8
  618. package/apps/pwa/out/_next/static/chunks/3538.a445e50bb359d068.js +0 -32
  619. package/apps/pwa/out/_next/static/chunks/3540c645.2595a6af01a97672.js +0 -1
  620. package/apps/pwa/out/_next/static/chunks/3621.581b2054cc14bee4.js +0 -286
  621. package/apps/pwa/out/_next/static/chunks/3676.8c28d16fd84ca843.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/375-b84540853523fe52.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/3757-180308bc61021b05.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/379.ee262e37586fe1ae.js +0 -74
  625. package/apps/pwa/out/_next/static/chunks/3840-5825d56d46976a92.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/3969-81054381eaec4c4c.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/4067-bf9aa60547972937.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/4176.e5729c93c29151eb.js +0 -104
  629. package/apps/pwa/out/_next/static/chunks/4227-e6c84686bc8946ca.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/4327.b9e08a71c0009348.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/4946.bd106eafd668f248.js +0 -148
  632. package/apps/pwa/out/_next/static/chunks/5085-bce4904931767ca6.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/5125.2eb9968b83767193.js +0 -93
  634. package/apps/pwa/out/_next/static/chunks/5128-75b733fd74a9a1eb.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/5489f3fe.4bb1458b09f6dead.js +0 -122
  636. package/apps/pwa/out/_next/static/chunks/5560-2a4648f6a30f16e7.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/5772-e29e14f8ff127122.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/5887.5b2f5b44ce0f7e9a.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/5899-4c112a2d908cf97f.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/6041.1b65efb796ebc2a5.js +0 -79
  641. package/apps/pwa/out/_next/static/chunks/6057-765c0a26028c86b2.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/6142.f289e0d039f453a6.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/6199-6bcd61d2a3910e04.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/6236.cdf7293e710a9b2d.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/6387-237e079dac9a3ae6.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/6448-b6d272d074276e14.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/6466-92e65a48490b68a9.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/6580-cdc0e4a634ce4708.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/6659-b242dc31b20b3f29.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/6690.c5d9b321b1f79384.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/671-e9b6ad0c771c5514.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/6862.bcbf89dd0f4496b3.js +0 -27
  653. package/apps/pwa/out/_next/static/chunks/6912-7b375ee48732c767.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/727.7deb87749b0a343a.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/7481.39f7a4654907bf6e.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/7545.b1aa42cd15503319.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/7551-416d298c2dc4a9ab.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/7870-309de463786ac1fc.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/7888-e29b151bb6a3bb8b.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/7891.03f910124a737985.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/7905-6ba78d9234608f79.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/8207.f527886b7c464529.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/856.50bda61439d465e6.js +0 -62
  664. package/apps/pwa/out/_next/static/chunks/9031-92e9b487edb681ee.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/9060.5410d9f6a95f6287.js +0 -90
  666. package/apps/pwa/out/_next/static/chunks/914.8abefd48d579547b.js +0 -94
  667. package/apps/pwa/out/_next/static/chunks/9187-c87a2207d4ac5d46.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/9289.3e92f278821e18e0.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/9319.7816d3cc741cd34f.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/9327-e016bb9f1674d24f.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/9365.3de48bf75193ff9a.js +0 -77
  672. package/apps/pwa/out/_next/static/chunks/9383.5b5e9aa56b5fea97.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/9387-cb929573ef436f39.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/9489.c27becacc3283dec.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/9514.131c52cc75fe6439.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/9536.28962663c7734376.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/9686-12286f5bbf15a5a0.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/9776.289d40cc5a4c342a.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/9789.60f723d18097ec30.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/989.f0c17523c5e61f65.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/9972-1df393aa8d4f7d52.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-96750aba7430959f.js +0 -1
  683. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4105e5bbbb043024.js +0 -1
  684. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-5d4fa75c2acb113e.js +0 -1
  685. package/apps/pwa/out/_next/static/chunks/app/board/page-a79a9bdb3b2142bf.js +0 -1
  686. package/apps/pwa/out/_next/static/chunks/app/botlab/page-f1c2047484992a35.js +0 -1
  687. package/apps/pwa/out/_next/static/chunks/app/bots/page-15ffc49b2d8c70e2.js +0 -1
  688. package/apps/pwa/out/_next/static/chunks/app/ceo/page-67d53a3fc8734135.js +0 -1
  689. package/apps/pwa/out/_next/static/chunks/app/chat/page-e30c8dc696491336.js +0 -1
  690. package/apps/pwa/out/_next/static/chunks/app/consult/page-2136e04fa77696e2.js +0 -1
  691. package/apps/pwa/out/_next/static/chunks/app/control/page-fecd2814790c2e12.js +0 -1
  692. package/apps/pwa/out/_next/static/chunks/app/decisions/page-280aa4a98fc5bb44.js +0 -1
  693. package/apps/pwa/out/_next/static/chunks/app/design-check/page-c14e96b65fb4b883.js +0 -1
  694. package/apps/pwa/out/_next/static/chunks/app/editor/page-187dac74825ed6bf.js +0 -1
  695. package/apps/pwa/out/_next/static/chunks/app/exec/page-6bc7246ea8c92448.js +0 -1
  696. package/apps/pwa/out/_next/static/chunks/app/field/page-083747f1d4518f61.js +0 -1
  697. package/apps/pwa/out/_next/static/chunks/app/healthz/route-96750aba7430959f.js +0 -1
  698. package/apps/pwa/out/_next/static/chunks/app/inside/page-15ca95a16ec96e1f.js +0 -1
  699. package/apps/pwa/out/_next/static/chunks/app/intake/page-a8ac031b3810eb64.js +0 -1
  700. package/apps/pwa/out/_next/static/chunks/app/layout-8835f93110494cda.js +0 -1
  701. package/apps/pwa/out/_next/static/chunks/app/live/page-e2de2e59111c9aad.js +0 -1
  702. package/apps/pwa/out/_next/static/chunks/app/live-run/page-f2b2e4bf6e981450.js +0 -1
  703. package/apps/pwa/out/_next/static/chunks/app/loops/page-5b92b7f75df20948.js +0 -1
  704. package/apps/pwa/out/_next/static/chunks/app/market/page-468eddf2b1a84ecb.js +0 -1
  705. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-2af16e62c12f22df.js +0 -1
  706. package/apps/pwa/out/_next/static/chunks/app/morning/page-18b40867a77a5793.js +0 -1
  707. package/apps/pwa/out/_next/static/chunks/app/not-found-fe934f2979f5a4a2.js +0 -1
  708. package/apps/pwa/out/_next/static/chunks/app/observatory/page-3eec435537357170.js +0 -1
  709. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-ff88cbfd2aa99fc8.js +0 -1
  710. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-a5b39fb780c70ab5.js +0 -1
  711. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ae465dde1d1b3933.js +0 -1
  712. package/apps/pwa/out/_next/static/chunks/app/page-cab9674fde9ead26.js +0 -1
  713. package/apps/pwa/out/_next/static/chunks/app/reflection/page-1da49bc8712284d0.js +0 -1
  714. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-5e8aa657551ac912.js +0 -1
  715. package/apps/pwa/out/_next/static/chunks/app/sessions/page-fcc36f36c6dc1fe2.js +0 -1
  716. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-d22db22f2a7296ca.js +0 -1
  717. package/apps/pwa/out/_next/static/chunks/app/settings/page-d12dc7b1773878f0.js +0 -1
  718. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-99debec9ea7fbec0.js +0 -1
  719. package/apps/pwa/out/_next/static/chunks/app/setup/layout-96750aba7430959f.js +0 -1
  720. package/apps/pwa/out/_next/static/chunks/app/setup/page-2a088a78bad7e924.js +0 -1
  721. package/apps/pwa/out/_next/static/chunks/app/share/page-2e8ed57db7e69993.js +0 -1
  722. package/apps/pwa/out/_next/static/chunks/app/showroom/page-4b3a16213c2ae8fe.js +0 -1
  723. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f098747ddf38c98b.js +0 -1
  724. package/apps/pwa/out/_next/static/chunks/app/today/page-68279e3c843c1fd7.js +0 -1
  725. package/apps/pwa/out/_next/static/chunks/app/trace/page-a34a74453367a39d.js +0 -1
  726. package/apps/pwa/out/_next/static/chunks/app/vault/page-8767a7db2155a5bd.js +0 -1
  727. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-bd5976683460d7f2.js +0 -1
  728. package/apps/pwa/out/_next/static/chunks/app/workflows/page-b7364835e7f2ef54.js +0 -1
  729. package/apps/pwa/out/_next/static/chunks/app/workspace/page-311af16b3ee0ffca.js +0 -1
  730. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-fb670757274ae990.js +0 -1
  731. package/apps/pwa/out/_next/static/chunks/ccae1c4b-0cf414f5eff1b10d.js +0 -1
  732. package/apps/pwa/out/_next/static/chunks/f9a61e4d.1fc2c1dbdd49fe46.js +0 -1
  733. package/apps/pwa/out/_next/static/chunks/framework-6d497cbf1eef04c6.js +0 -1
  734. package/apps/pwa/out/_next/static/chunks/main-app-012f5edec932f337.js +0 -1
  735. package/apps/pwa/out/_next/static/chunks/main-da5aeb809edc94a2.js +0 -1
  736. package/apps/pwa/out/_next/static/chunks/pages/_app-5ee319af6f749dfe.js +0 -1
  737. package/apps/pwa/out/_next/static/chunks/pages/_error-4bc84653a718d6c6.js +0 -1
  738. package/apps/pwa/out/_next/static/chunks/webpack-8a96cf6775c73d6e.js +0 -1
  739. package/scripts/migrate-monad-to-elanous.ts +0 -195
  740. package/scripts/rebrand-elanous.ts +0 -242
  741. /package/apps/pwa/out/_next/static/{uC-N0emedeNOFuaBQFv-I → RrjXTwz-urRAbChP1bX02}/_ssgManifest.js +0 -0
@@ -0,0 +1,158 @@
1
+ /**
2
+ * MAPREDUCE-FANOUT backend. Inventory and card execution are ports so the CLI can
3
+ * bind the existing checklist/draft readers and tasks hand Pod launcher separately.
4
+ * A run snapshots its inventory before any card starts; one terminal row belongs
5
+ * to each item. This module never changes a checklist or closes a PR.
6
+ */
7
+ import { randomUUID } from 'node:crypto';
8
+ import { debug } from '../debug/log.js';
9
+ import {
10
+ appendMapRunRow, createMapRun, readMapRun, reduceMapRun,
11
+ type MapRecipe, type MapRowKind, type MapRunRow, type MapRunStart,
12
+ } from './map-run-ledger.js';
13
+
14
+ export type MapSource = 'landed-but-yellow' | 'drafts';
15
+ export interface MapItem { id: string }
16
+ export interface MapInventory<T extends MapItem> {
17
+ items: readonly T[];
18
+ complete: boolean;
19
+ snapshotTime: string;
20
+ snapshotRef: string;
21
+ recipeSha: string;
22
+ mainSha: string;
23
+ checklistSnapshotPath: string | null;
24
+ requestedPool: string;
25
+ selectedPool: string | null;
26
+ imageCommit: string | null;
27
+ /** A failed inventory is recorded as a suppressed HOLD row. */
28
+ reason?: string;
29
+ }
30
+ export interface MapCard {
31
+ id: string;
32
+ itemId: string;
33
+ mapRunId: string;
34
+ recipe: MapRecipe;
35
+ text: string;
36
+ }
37
+ export interface MapContext {
38
+ mapRunId: string;
39
+ recipe: MapRecipe;
40
+ source: MapSource;
41
+ dryRun: boolean;
42
+ }
43
+ export interface MapPorts<T extends MapItem> {
44
+ inventory: (recipe: MapRecipe, source: MapSource, limit: number | undefined) => Promise<MapInventory<T>>;
45
+ /** Pure card authoring. Do not persist or launch here. */
46
+ buildCard: (item: T, context: MapContext) => MapCard;
47
+ /** Production adapter must launch through tasks hand and wait for its terminal recipe result. */
48
+ launchCard: (card: MapCard, item: T, context: MapContext) => Promise<MapRunRow>;
49
+ /** Optional pure preview; default dry-run yields a HOLD without invoking launchCard. */
50
+ previewCard?: (card: MapCard, item: T, context: MapContext) => MapRunRow | Promise<MapRunRow>;
51
+ log?: (event: string, data: Record<string, unknown>) => void;
52
+ }
53
+ export interface MapRequest {
54
+ recipe: MapRecipe;
55
+ source: MapSource;
56
+ limit?: number;
57
+ concurrency?: number;
58
+ dryRun?: boolean;
59
+ root?: string;
60
+ mapRunId?: string;
61
+ }
62
+ export interface MapResult { mapRunId: string; expected: number; observed: number; dryRun: boolean }
63
+
64
+ const validPairs: Readonly<Record<MapRecipe, MapSource>> = {
65
+ 'green-close': 'landed-but-yellow', 'draft-close': 'drafts',
66
+ };
67
+ const idPattern = /^[A-Za-z0-9][A-Za-z0-9_-]{0,95}$/;
68
+
69
+ function checkPositive(value: number | undefined, label: string): void {
70
+ if (value !== undefined && (!Number.isSafeInteger(value) || value < 1)) throw new Error(`map ${label} must be a positive integer`);
71
+ }
72
+ function hold(context: MapContext, itemId: string | null, reason: string, suppressed = false): MapRunRow {
73
+ return { event: 'row', mapRunId: context.mapRunId, itemId, recipe: context.recipe,
74
+ kind: 'hold', verdict: 'hold', reason, evidence: [], ...(suppressed ? { rowsSuppressed: true, pr: null } : {}) };
75
+ }
76
+ function record(log: MapPorts<MapItem>['log'], event: string, data: Record<string, unknown>): void {
77
+ try { (log ?? ((name, fields) => debug.log('task-agent.map-reduce', name, fields)))(event, data); }
78
+ catch { /* diagnostics must not turn a completed item into a failed one */ }
79
+ }
80
+
81
+ /** Bounded workers, with no unbounded Promise.all fanout. Default is a read-only preview. */
82
+ export async function mapInventory<T extends MapItem>(request: MapRequest, ports: MapPorts<T>): Promise<MapResult> {
83
+ if (validPairs[request.recipe] !== request.source) throw new Error('map recipe/source mismatch');
84
+ checkPositive(request.limit, 'limit');
85
+ checkPositive(request.concurrency, 'concurrency');
86
+ const concurrency = request.concurrency ?? 2;
87
+ const dryRun = request.dryRun !== false;
88
+ const mapRunId = request.mapRunId ?? `map-${randomUUID()}`;
89
+ if (!idPattern.test(mapRunId)) throw new Error('map invalid run id');
90
+ const context: MapContext = { mapRunId, recipe: request.recipe, source: request.source, dryRun };
91
+ const inventory = await ports.inventory(request.recipe, request.source, request.limit);
92
+ // A limit is a selection boundary, not permission to silently truncate a partial inventory.
93
+ const items = inventory.complete ? inventory.items.slice(0, request.limit) : [];
94
+ const start: MapRunStart = { event: 'start', mapRunId, recipe: request.recipe,
95
+ recipeSha: inventory.recipeSha, snapshotTime: inventory.snapshotTime, snapshotRef: inventory.snapshotRef,
96
+ mainSha: inventory.mainSha, checklistSnapshotPath: inventory.checklistSnapshotPath,
97
+ inventoryComplete: inventory.complete, itemIds: items.map((item) => item.id),
98
+ requestedPool: inventory.requestedPool, selectedPool: inventory.selectedPool,
99
+ imageCommit: inventory.imageCommit, dryRun };
100
+ createMapRun(start, request.root);
101
+ record(ports.log, 'start', { mapRunId, recipe: request.recipe, source: request.source, count: items.length, concurrency, dryRun });
102
+ if (!inventory.complete) {
103
+ appendMapRunRow(hold(context, null, inventory.reason || 'inventory-incomplete', true), request.root);
104
+ record(ports.log, 'inventory-hold', { mapRunId, reason: inventory.reason ?? 'inventory-incomplete' });
105
+ return { mapRunId, expected: 0, observed: 1, dryRun };
106
+ }
107
+ let next = 0;
108
+ let observed = 0;
109
+ async function worker(): Promise<void> {
110
+ while (next < items.length) {
111
+ const item = items[next++]!;
112
+ let row: MapRunRow;
113
+ try {
114
+ const card = ports.buildCard(item, context);
115
+ if (!card || !idPattern.test(card.id) || card.itemId !== item.id || card.mapRunId !== mapRunId
116
+ || card.recipe !== request.recipe || !card.text.trim()) throw new Error('card identity mismatch');
117
+ row = dryRun
118
+ ? ports.previewCard ? await ports.previewCard(card, item, context) : hold(context, item.id, 'dry-run-preview')
119
+ : await ports.launchCard(card, item, context);
120
+ if (row.mapRunId !== mapRunId || row.itemId !== item.id || row.recipe !== request.recipe)
121
+ throw new Error('result identity mismatch');
122
+ row = { ...row, result: { ...row.result, cardId: card.id } };
123
+ } catch (error) {
124
+ row = hold(context, item.id, `map-item-failed: ${error instanceof Error ? error.message : String(error)}`);
125
+ }
126
+ // The ledger validates recipe-specific evidence and rejects duplicate/unknown rows.
127
+ // An invalid result is a hard error; never launder it into a successful map run.
128
+ appendMapRunRow(row, request.root);
129
+ observed++;
130
+ record(ports.log, 'item', { mapRunId, itemId: item.id, kind: row.kind, reason: row.reason });
131
+ }
132
+ }
133
+ await Promise.all(Array.from({ length: Math.min(concurrency, items.length) }, () => worker()));
134
+ record(ports.log, 'finished', { mapRunId, expected: items.length, observed });
135
+ return { mapRunId, expected: items.length, observed, dryRun };
136
+ }
137
+
138
+ export interface MapReduceTable { mapRunId: string; markdown: string; writes: 0 }
139
+ const countKinds: readonly MapRowKind[] = ['green-candidate', 'mock-pr', 'implementation-remains', 'harvest', 'close-candidate', 'hold'];
140
+ function cell(value: unknown): string { return String(value ?? '').replaceAll('|', '\\|').replaceAll(/\r?\n/g, ' '); }
141
+
142
+ /** Read-only aggregation. Applying green/close candidates belongs to a separate guarded reducer. */
143
+ export function renderMapReduceTable(mapRunId: string, root?: string): MapReduceTable {
144
+ const { start, rows } = readMapRun(mapRunId, root);
145
+ const summary = reduceMapRun(mapRunId, root);
146
+ const lines = [
147
+ `# Map run ${cell(mapRunId)}`,
148
+ '',
149
+ `Recipe: ${start.recipe} · snapshot: ${cell(start.snapshotRef)} · dry-run: ${start.dryRun} · verdict: ${summary.verdict} (${summary.reason})`,
150
+ `Expected: ${summary.expected} · observed: ${summary.observed} · writes: 0`,
151
+ `Counts: ${countKinds.map((kind) => `${kind} ${summary.counts[kind]}`).join(' · ')}`,
152
+ '',
153
+ '| Item | Card | Result | PR | Reason |',
154
+ '| --- | --- | --- | --- | --- |',
155
+ ...rows.map((row) => `| ${cell(row.itemId ?? 'inventory')} | ${cell(row.result?.cardId)} | ${row.kind} | ${cell(row.pr)} | ${cell(row.reason)} |`),
156
+ ];
157
+ return { mapRunId, markdown: `${lines.join('\n')}\n`, writes: 0 };
158
+ }
@@ -0,0 +1,226 @@
1
+ /**
2
+ * MAPREDUCE-FANOUT: one immutable inventory snapshot, followed by one result per item.
3
+ * The reducer is read-only. A partial inventory or missing/duplicate result is a hold,
4
+ * never evidence for a checklist change or a draft close.
5
+ */
6
+ import { appendFileSync, closeSync, existsSync, mkdirSync, openSync, readFileSync, writeSync } from 'node:fs';
7
+ import { dirname, isAbsolute, join } from 'node:path';
8
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
9
+ import { withFileLockSync } from '../storage/file-lock.js';
10
+
11
+ export type MapRecipe = 'green-close' | 'draft-close';
12
+ export type MapRowKind = 'green-candidate' | 'mock-pr' | 'implementation-remains'
13
+ | 'harvest' | 'close-candidate' | 'hold';
14
+ export type MapEvidenceVerdict = 'pass' | 'fail' | 'hold' | 'unmeasured';
15
+
16
+ export interface MapRunStart {
17
+ event: 'start';
18
+ mapRunId: string;
19
+ recipe: MapRecipe;
20
+ recipeSha: string;
21
+ snapshotTime: string;
22
+ snapshotRef: string;
23
+ /** Exact origin/main captured with the inventory, independent of the image or recipe commit. */
24
+ mainSha: string;
25
+ /** The checklist snapshot artifact used by green-close; draft-close records null. */
26
+ checklistSnapshotPath: string | null;
27
+ inventoryComplete: boolean;
28
+ /** Stable identities from the complete inventory; item display titles are never keys. */
29
+ itemIds: string[];
30
+ requestedPool: string;
31
+ selectedPool: string | null;
32
+ imageCommit: string | null;
33
+ dryRun: boolean;
34
+ }
35
+
36
+ export interface MapRunRow {
37
+ event: 'row';
38
+ mapRunId: string;
39
+ itemId: string | null;
40
+ recipe: MapRecipe;
41
+ kind: MapRowKind;
42
+ verdict: MapRowKind;
43
+ reason: string;
44
+ evidence: string[];
45
+ e1?: { verdict: MapEvidenceVerdict; mergeSha?: string; mainAncestor?: boolean };
46
+ e2?: { verdict: MapEvidenceVerdict; command?: string; exitCode?: number };
47
+ e2Source?: 'completion-boundary' | 'prior-evidence' | 'missing';
48
+ e3?: { verdict: MapEvidenceVerdict; reason: string };
49
+ /** Only an inventory-wide failure uses this form; it suppresses all item rows and requires pr:null. */
50
+ rowsSuppressed?: boolean;
51
+ pr?: number | null;
52
+ prUrl?: string | null;
53
+ headOid?: string | null;
54
+ podJob?: string | null;
55
+ podUid?: string | null;
56
+ startedAt?: string | null;
57
+ endedAt?: string | null;
58
+ rc?: number | null;
59
+ result?: Record<string, unknown>;
60
+ }
61
+
62
+ export interface MapRunRead {
63
+ start: MapRunStart;
64
+ rows: MapRunRow[];
65
+ }
66
+
67
+ export interface MapRunReduce {
68
+ mapRunId: string;
69
+ verdict: 'complete' | 'hold';
70
+ reason: string;
71
+ expected: number;
72
+ observed: number;
73
+ counts: Record<MapRowKind, number>;
74
+ /** A dry-run has no write authority, even when every item is a candidate. */
75
+ writes: 0;
76
+ }
77
+
78
+ const ID = /^[A-Za-z0-9][A-Za-z0-9_-]{0,95}$/;
79
+ const SHA = /^[0-9a-f]{40}$/;
80
+ const KINDS = new Set<MapRowKind>(['green-candidate', 'mock-pr', 'implementation-remains', 'harvest', 'close-candidate', 'hold']);
81
+ const RECIPE_KINDS: Record<MapRecipe, ReadonlySet<MapRowKind>> = {
82
+ 'green-close': new Set(['green-candidate', 'mock-pr', 'implementation-remains', 'hold']),
83
+ 'draft-close': new Set(['harvest', 'close-candidate', 'hold']),
84
+ };
85
+
86
+ function checkId(value: string, label: string): void {
87
+ if (!ID.test(value)) throw new Error(`map-run invalid ${label}: ${value}`);
88
+ }
89
+
90
+ export function mapRunLedgerPath(mapRunId: string, root = effectiveInstanceRoot()): string {
91
+ checkId(mapRunId, 'id');
92
+ return join(root, 'map-runs', `${mapRunId}.jsonl`);
93
+ }
94
+
95
+ function validateStart(start: MapRunStart): void {
96
+ checkId(start.mapRunId, 'id');
97
+ if (start.recipe !== 'green-close' && start.recipe !== 'draft-close') throw new Error('map-run unknown recipe');
98
+ if (!SHA.test(start.recipeSha)) throw new Error('map-run recipe SHA missing');
99
+ if (!start.snapshotTime || !start.snapshotRef) throw new Error('map-run snapshot identity missing');
100
+ if (!SHA.test(start.mainSha) || !('checklistSnapshotPath' in start)
101
+ || (start.recipe === 'green-close' && (!start.checklistSnapshotPath || !isAbsolute(start.checklistSnapshotPath)))
102
+ || (start.recipe === 'draft-close' && start.checklistSnapshotPath !== null)) {
103
+ throw new Error('map-run main or checklist snapshot provenance missing');
104
+ }
105
+ if (!Array.isArray(start.itemIds) || start.itemIds.some((id) => typeof id !== 'string' || !ID.test(id))
106
+ || new Set(start.itemIds).size !== start.itemIds.length) throw new Error('map-run item identities missing or duplicate');
107
+ if (typeof start.inventoryComplete !== 'boolean' || typeof start.dryRun !== 'boolean') throw new Error('map-run completeness or dry-run missing');
108
+ if (!start.inventoryComplete && start.itemIds.length) throw new Error('map-run partial inventory cannot name items');
109
+ if (!start.requestedPool || !('selectedPool' in start) || !('imageCommit' in start)) throw new Error('map-run pool or image provenance missing');
110
+ }
111
+
112
+ function validateRow(row: MapRunRow, start: MapRunStart): void {
113
+ if (row.mapRunId !== start.mapRunId || row.recipe !== start.recipe || !KINDS.has(row.kind) || row.verdict !== row.kind
114
+ || !Array.isArray(row.evidence)
115
+ || row.evidence.some((value) => typeof value !== 'string') || typeof row.reason !== 'string') {
116
+ throw new Error('map-run row contract mismatch');
117
+ }
118
+ if (!RECIPE_KINDS[start.recipe].has(row.kind)) throw new Error('map-run kind outside recipe');
119
+ if (row.rowsSuppressed) {
120
+ if (start.inventoryComplete || row.itemId !== null || row.pr !== null || row.kind !== 'hold') {
121
+ throw new Error('map-run suppressed row must hold an incomplete inventory without a PR');
122
+ }
123
+ } else if (!start.inventoryComplete) {
124
+ throw new Error('map-run incomplete inventory suppresses item rows');
125
+ } else if (!row.itemId || !start.itemIds.includes(row.itemId)) {
126
+ throw new Error(`map-run unknown item: ${row.itemId}`);
127
+ }
128
+ if (row.kind === 'hold' && !row.reason.trim()) throw new Error('map-run hold needs a reason');
129
+ if (row.kind !== 'hold' && row.evidence.length === 0) throw new Error('map-run candidate needs evidence');
130
+ if (row.kind === 'green-candidate'
131
+ && (row.e1?.verdict !== 'pass' || row.e2?.verdict !== 'pass' || row.e3?.verdict !== 'pass'
132
+ || !SHA.test(row.e1.mergeSha ?? '') || row.e1.mainAncestor !== true
133
+ || !row.e3.reason.trim()
134
+ || typeof row.pr !== 'number' || !Number.isSafeInteger(row.pr) || row.pr <= 0
135
+ || !row.prUrl || !row.e2Source || row.e2Source === 'missing'
136
+ || !row.e2.command?.trim() || row.e2.exitCode !== 0)) {
137
+ throw new Error('map-run green candidate needs E1/E2/E3 and PR proof');
138
+ }
139
+ if ((row.kind === 'harvest' || row.kind === 'close-candidate')
140
+ && (typeof row.pr !== 'number' || !Number.isSafeInteger(row.pr) || row.pr <= 0 || !SHA.test(row.headOid ?? ''))) {
141
+ throw new Error('map-run draft decision needs exact PR head');
142
+ }
143
+ if (row.rc != null && row.rc !== 0 && row.kind !== 'hold') throw new Error('map-run failed Pod cannot yield a candidate');
144
+ for (const field of ['podJob', 'podUid', 'startedAt', 'endedAt'] as const) {
145
+ const value = row[field];
146
+ if (value != null && (typeof value !== 'string' || !value.trim())) throw new Error(`map-run invalid ${field}`);
147
+ }
148
+ if (row.result != null && (typeof row.result !== 'object' || Array.isArray(row.result))) {
149
+ throw new Error('map-run invalid result');
150
+ }
151
+ }
152
+
153
+ /** Exclusive create prevents a retry from silently replacing the original inventory. */
154
+ export function createMapRun(start: MapRunStart, root?: string): string {
155
+ validateStart(start);
156
+ const path = mapRunLedgerPath(start.mapRunId, root);
157
+ mkdirSync(dirname(path), { recursive: true });
158
+ const fd = openSync(path, 'wx', 0o600);
159
+ try { writeSync(fd, `${JSON.stringify(start)}\n`); }
160
+ finally { closeSync(fd); }
161
+ return path;
162
+ }
163
+
164
+ export function readMapRun(mapRunId: string, root?: string): MapRunRead {
165
+ const path = mapRunLedgerPath(mapRunId, root);
166
+ if (!existsSync(path)) throw new Error(`map-run missing: ${mapRunId}`);
167
+ const raw = readFileSync(path, 'utf8');
168
+ if (!raw.endsWith('\n')) throw new Error('map-run truncated JSONL tail');
169
+ const lines = raw.trimEnd().split('\n');
170
+ let start: MapRunStart;
171
+ try { start = JSON.parse(lines[0]!) as MapRunStart; }
172
+ catch { throw new Error('map-run invalid start JSON'); }
173
+ if (start.event !== 'start' || start.mapRunId !== mapRunId) throw new Error('map-run invalid start');
174
+ validateStart(start);
175
+ const rows: MapRunRow[] = [];
176
+ const seen = new Set<string>();
177
+ for (const line of lines.slice(1)) {
178
+ let row: MapRunRow;
179
+ try { row = JSON.parse(line) as MapRunRow; }
180
+ catch { throw new Error('map-run invalid row JSON'); }
181
+ if (row.event !== 'row') throw new Error('map-run unexpected event');
182
+ validateRow(row, start);
183
+ const key = row.rowsSuppressed ? '__inventory_hold__' : row.itemId!;
184
+ if (seen.has(key)) throw new Error(`map-run duplicate row: ${key}`);
185
+ seen.add(key);
186
+ rows.push(row);
187
+ }
188
+ if (rows.some((row) => row.rowsSuppressed) && rows.length !== 1) throw new Error('map-run suppressed inventory has item rows');
189
+ return { start, rows };
190
+ }
191
+
192
+ /** The lock protects the read-before-append duplicate check across concurrent Pod completions. */
193
+ export function appendMapRunRow(row: MapRunRow, root?: string): void {
194
+ const path = mapRunLedgerPath(row.mapRunId, root);
195
+ withFileLockSync(`${path}.lock`, () => {
196
+ const current = readMapRun(row.mapRunId, root);
197
+ validateRow(row, current.start);
198
+ const key = row.rowsSuppressed ? '__inventory_hold__' : row.itemId!;
199
+ if (current.rows.some((existing) => (existing.rowsSuppressed ? '__inventory_hold__' : existing.itemId) === key)) {
200
+ throw new Error(`map-run duplicate row: ${key}`);
201
+ }
202
+ if (row.rowsSuppressed && current.rows.length) throw new Error('map-run inventory hold cannot follow item rows');
203
+ if (current.rows.some((existing) => existing.rowsSuppressed)) throw new Error('map-run inventory hold suppresses item rows');
204
+ appendFileSync(path, `${JSON.stringify(row)}\n`);
205
+ });
206
+ }
207
+
208
+ /** No consumer of this result can write: incomplete evidence remains an explicit hold. */
209
+ export function reduceMapRun(mapRunId: string, root?: string): MapRunReduce {
210
+ const { start, rows } = readMapRun(mapRunId, root);
211
+ const counts: Record<MapRowKind, number> = {
212
+ 'green-candidate': 0, 'mock-pr': 0, 'implementation-remains': 0,
213
+ harvest: 0, 'close-candidate': 0, hold: 0,
214
+ };
215
+ for (const row of rows) counts[row.kind]++;
216
+ const accounted = start.inventoryComplete && rows.length === start.itemIds.length
217
+ && rows.every((row) => !row.rowsSuppressed);
218
+ const complete = accounted && start.itemIds.length > 0 && counts.hold === 0;
219
+ return {
220
+ mapRunId, verdict: complete ? 'complete' : 'hold',
221
+ reason: !start.inventoryComplete ? 'inventory-incomplete' : start.itemIds.length === 0 ? 'empty-inventory'
222
+ : !accounted ? 'results-missing'
223
+ : counts.hold ? 'item-hold' : 'all-items-accounted',
224
+ expected: start.itemIds.length, observed: rows.length, counts, writes: 0,
225
+ };
226
+ }
@@ -44,6 +44,8 @@ export const PARENT_HOST_ENV = 'ELANOUS_TA_PARENT_HOST';
44
44
  const DEFAULT_REMOTE_ELANOUS = '$HOME/.local/share/elanous/bin/elanous';
45
45
  const DEFAULT_REMOTE_CONFIG_DIR = '$HOME/.elanous';
46
46
  const HOST_RE = /^[A-Za-z0-9][A-Za-z0-9._@-]{0,127}$/;
47
+ /** A parent can wait for a child for tens of minutes; the two-minute HTTP refresh floor is too short here. */
48
+ export const PARENT_CHILD_CREDENTIAL_MIN_REMAINING_MS = 60 * 60_000;
47
49
 
48
50
  /** Missing child-provider metadata keeps the established Pod default: the HQ Codex mirror is needed. */
49
51
  export function shouldInstallRemoteCodexAccess(effectiveChildProvider: string | undefined): boolean {
@@ -81,7 +83,7 @@ export function resolveParentHosts(config: ParentHostSetting | undefined, env: N
81
83
  }
82
84
 
83
85
  /** Capacity sample is read on the host before launch. Unknown or saturated capacity is not a positive weight. */
84
- export interface ParentHostCapacity { approvalHeadroom: number; load: number }
86
+ export interface ParentHostCapacity { active: number; waiting: number; limit: number; headroom: number; approvalHeadroom: number; load: number }
85
87
 
86
88
  export interface ParentHostPodFit {
87
89
  state: 'fits' | 'never-fits' | 'unmeasured';
@@ -127,26 +129,36 @@ export function readParentHostPodFit(target: ParentHostConfig, memoryLimit: stri
127
129
  }
128
130
 
129
131
  const CAPACITY_MARKER = '__ELANOUS_PARENT_CAPACITY__';
132
+ const CAPACITY_ERROR_MARKER = '__ELANOUS_PARENT_CAPACITY_ERROR__';
130
133
  const APPROVAL_MARKER = '__ELANOUS_PARENT_APPROVALS__';
131
134
  const LOAD_MARKER = '__ELANOUS_PARENT_LOAD__';
135
+ /** Best-effort macOS `ps` fallback; Linux/WSL uses argv boundaries below. */
136
+ export const PARENT_HOST_ACTIVE_FILTER = String.raw`/^(([^ ]+\/)?(bun|node|nodejs) )?([^ ]+\/)?elanous(\.mjs)?( --config-dir [^ ]+)? harness (say|ask)( |$)/ && / --no-auto-merge( |$)/ && !/ --substrate local( |$)/ && !/^([^ ]+\/)?[^ ]*sh -c/`;
137
+ /** Count exact Linux argv entries so Pod-local commands and goal text cannot masquerade as host parents. */
138
+ export const PARENT_HOST_PROC_COUNT_SCRIPT = "count=0; proc_root=${1:-/proc}; for file in \"$proc_root\"/[0-9]*/cmdline; do [ -r \"$file\" ] || continue; argv=(); while IFS= read -r -d '' arg; do argv+=(\"$arg\"); done < \"$file\" 2>/dev/null || true; [ ${#argv[@]} -ge 3 ] || continue; program=\"${argv[0]##*/}\"; case \"$program\" in elanous|elanous.mjs) ;; bun|node|nodejs) script_match=0; for ((i=1; i<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == */elanous.mjs ]]; then script_match=1; break; fi; [[ \"${argv[i]}\" == harness ]] && break; done; [ \"$script_match\" -eq 1 ] || continue ;; *) continue ;; esac; harness=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == harness && ( \"${argv[i+1]}\" == say || \"${argv[i+1]}\" == ask ) ]]; then harness=1; break; fi; done; [ \"$harness\" -eq 1 ] || continue; has_no_auto_merge=0; for arg in \"${argv[@]}\"; do [[ \"$arg\" == --no-auto-merge ]] && has_no_auto_merge=1; done; [ \"$has_no_auto_merge\" -eq 1 ] || continue; local_substrate=0; for ((i=0; i+1<${#argv[@]}; i++)); do if [[ \"${argv[i]}\" == --substrate && \"${argv[i+1]}\" == local ]]; then local_substrate=1; break; fi; done; [ \"$local_substrate\" -eq 1 ] && continue; cgroup_file=${file%cmdline}cgroup; if [ ! -r $cgroup_file ]; then [ ! -d ${file%/cmdline} ] && continue; printf '__ELANOUS_PARENT_CAPACITY_ERROR__cgroup-unreadable\\n'; exit 1; fi; cgroup=$(cat $cgroup_file 2>/dev/null) || { [ ! -d ${file%/cmdline} ] && continue; printf '__ELANOUS_PARENT_CAPACITY_ERROR__cgroup-unreadable\\n'; exit 1; }; case $cgroup in *docker*|*kubepods*|*containerd*|*libpod*|*lxc*) continue;; esac; count=$((count+1)); done; printf '__ELANOUS_PARENT_CAPACITY__%s\\n' \"$count\""
132
139
  /** Recent admission decisions are the host's measured approval backlog, not an inferred process count. */
133
140
  export function readParentHostCapacity(target: ParentHostConfig, ssh: SshRunner = defaultSshRunner): ParentHostCapacity | null {
134
141
  const executable = remotePath(target.elanous ?? DEFAULT_REMOTE_ELANOUS);
135
142
  const configDir = remotePath(target.configDir ?? DEFAULT_REMOTE_CONFIG_DIR);
136
- const script = `parents=$(ps -Ao command) || exit 1; printf '%s\\n' "$parents" | awk '/[e]lanous.*harness (say|ask)/ { n++ } END { print "${CAPACITY_MARKER}" n+0 }'; `
143
+ const unavailable = (reason: string): null => { try { debug.log('task-agent.parent-host', 'capacity-unavailable', { host: target.host, reason }); } catch { /* fail-soft */ } return null; };
144
+ const processCount = `if [ -r /proc/self/cmdline ]; then if command -v bash >/dev/null 2>&1; then bash -c ${shellQuote(PARENT_HOST_PROC_COUNT_SCRIPT)} -- /proc || exit 1; else printf "${CAPACITY_ERROR_MARKER}bash-unavailable\\n"; exit 1; fi; else parents=$(ps -Ao command) || exit 1; printf '%s\\n' "$parents" | awk '${PARENT_HOST_ACTIVE_FILTER} { n++ } END { print "${CAPACITY_MARKER}" n+0 }'; fi`;
145
+ const script = `${processCount}; `
137
146
  + `${executable} --config-dir ${configDir} logs --event admit-by-usage --since 5m --json --limit 1000 || exit 1; `
138
147
  + `printf '\\n${APPROVAL_MARKER}\\n'; `
139
148
  + `cpu=$(ps -Ao %cpu=) || exit 1; printf '%s\\n' "$cpu" | awk '{ total += $1 } END { printf "${LOAD_MARKER}%.3f\\n", total+0 }'; `
140
149
  + `cores=$(getconf _NPROCESSORS_ONLN 2>/dev/null || sysctl -n hw.ncpu 2>/dev/null) || exit 1; printf '${LOAD_MARKER}cores=%s\\n' "$cores"`;
141
150
  try {
142
151
  const result = ssh(target.host, script, 15_000);
143
- if (result.status !== 0) return null;
152
+ if (result.status !== 0) return unavailable(result.stdout.includes(`${CAPACITY_ERROR_MARKER}bash-unavailable`) ? 'bash-unavailable'
153
+ : result.stdout.includes(`${CAPACITY_ERROR_MARKER}cgroup-unreadable`) ? 'cgroup-unreadable' : 'remote-command-failed');
144
154
  const activeMatch = new RegExp(`^${CAPACITY_MARKER}(\\d+)$`, 'm').exec(result.stdout);
145
155
  const boundary = result.stdout.indexOf(`\n${APPROVAL_MARKER}\n`);
146
156
  const logsStart = result.stdout.indexOf('\n');
147
157
  const cpuMatch = new RegExp(`^${LOAD_MARKER}([0-9]+(?:\\.[0-9]+)?)$`, 'm').exec(result.stdout);
148
158
  const coresMatch = new RegExp(`^${LOAD_MARKER}cores=(\\d+)$`, 'm').exec(result.stdout);
149
- if (!activeMatch || activeMatch.index !== 0 || logsStart < 0 || boundary < logsStart || !cpuMatch || !coresMatch) return null;
159
+ if (!activeMatch || activeMatch.index !== 0) return unavailable('active-count-marker-missing');
160
+ if (logsStart < 0 || boundary < logsStart) return unavailable('approval-boundary-missing');
161
+ if (!cpuMatch || !coresMatch) return unavailable('load-marker-missing');
150
162
  const active = Number(activeMatch[1]);
151
163
  const cores = Number(coresMatch[1]);
152
164
  const cpu = Number(cpuMatch[1]);
@@ -172,23 +184,25 @@ export function readParentHostCapacity(target: ParentHostConfig, ssh: SshRunner
172
184
  decisions.set(data.runId, data.recommended as number);
173
185
  }
174
186
  const waiting = [...decisions.values()].filter((n) => n === 0).length;
175
- return { approvalHeadroom: Math.max(0, capacity - active - waiting), load: Math.max(0, cpu / (cores * 100)) };
176
- } catch { return null; }
187
+ const headroom = Math.max(0, capacity - active - waiting);
188
+ return { active, waiting, limit: capacity, headroom, approvalHeadroom: headroom, load: Math.max(0, cpu / (cores * 100)) };
189
+ } catch { return unavailable('capacity-parse-failed'); }
177
190
  }
178
191
 
179
- /** Weighted rendezvous: stable per run, no shared counter or dependence on dispatch order. */
180
- export function orderParentHosts(targets: readonly ParentHostConfig[], runId: string, capacities: Readonly<Record<string, ParentHostCapacity | null>>): ParentHostConfig[] {
192
+ /** Weighted rendezvous rank with evidence fields for launch-time observation. */
193
+ export function rankParentHosts(targets: readonly ParentHostConfig[], runId: string, capacities: Readonly<Record<string, Pick<ParentHostCapacity, 'approvalHeadroom' | 'load'> | null>>): Array<{ target: ParentHostConfig; weight: number; score: number }> {
181
194
  return targets.map((target, index) => {
182
195
  const sample = capacities[target.host];
183
196
  const weight = sample && Number.isSafeInteger(sample.approvalHeadroom) && sample.approvalHeadroom > 0 && Number.isFinite(sample.load) && sample.load >= 0
184
197
  ? sample.approvalHeadroom / (1 + sample.load) : 0;
185
198
  const hash = createHash('sha256').update(`${runId}\0${target.host}`).digest();
186
199
  const fraction = (hash.readUIntBE(0, 6) + 1) / (2 ** 48 + 1);
187
- return { target, index, score: weight > 0 ? -Math.log(fraction) / weight : Infinity };
188
- }).sort((a, b) => a.score - b.score || a.index - b.index).map(({ target }) => target);
200
+ return { target, index, weight, score: weight > 0 ? -Math.log(fraction) / weight : Infinity };
201
+ }).sort((a, b) => a.score - b.score || a.index - b.index).map(({ target, weight, score }) => ({ target, weight, score }));
189
202
  }
190
203
 
191
- /** `$HOME/…` 은 원격 셸이 풀도록 따옴표 밖에 둔다 — 나머지는 shellQuote. */
204
+
205
+ /** Keep `$HOME/...` outside quotes so the remote shell expands it; quote every other path. */
192
206
  function remotePath(path: string): string {
193
207
  return path.startsWith('$HOME/') ? `"$HOME"/${shellQuote(path.slice('$HOME/'.length))}` : shellQuote(path);
194
208
  }
@@ -254,14 +268,22 @@ export interface ParentHostPreflight { ok: boolean; gaps: string[]; warnings: st
254
268
  export function preflightScript(target: ParentHostConfig): string {
255
269
  const elanous = remotePath(target.elanous ?? DEFAULT_REMOTE_ELANOUS);
256
270
  const configDir = remotePath(target.configDir ?? DEFAULT_REMOTE_CONFIG_DIR);
271
+ const grokCredentialFloorSeconds = Math.ceil(PARENT_CHILD_CREDENTIAL_MIN_REMAINING_MS / 1_000);
257
272
  return [
258
273
  `echo "version=$(${elanous} --version 2>/dev/null | tail -1 | cut -d' ' -f1)"`,
259
274
  `test -f ${configDir}/config.json && echo config=1`,
260
275
  `grep -Eq '"podPool"[[:space:]]*:[[:space:]]*"[^"[:space:]]+' ${configDir}/config.json 2>/dev/null && echo podPool=1`,
261
276
  `(cd ${shellQuote(target.cwd)} 2>/dev/null && git rev-parse --is-inside-work-tree >/dev/null 2>&1) && echo repo=1`,
262
277
  `command -v kubectl >/dev/null 2>&1 && echo kubectl=1`,
278
+ `{ command -v grok >/dev/null 2>&1 || [ -x "$HOME/.grok/bin/grok" ]; } && echo grokCli=1`,
279
+ `{ command -v codex >/dev/null 2>&1 || [ -x "$HOME/.local/bin/codex" ]; } && echo codexCli=1`,
263
280
  `n=$(grep -Ec '^[[:space:]]*"openai-codex(:[^"]*)?"[[:space:]]*:[[:space:]]*\\{' ${configDir}/auth.json 2>/dev/null); echo "codexAccounts=\${n:-0}"`,
264
281
  `{ grep -Eq '"key"[[:space:]]*:[[:space:]]*"[^"]+"' "$HOME/.grok/auth.json" 2>/dev/null || [ -n "\${XAI_API_KEY:-}\${GROK_API_KEY:-}\${GROK_CODE_XAI_API_KEY:-}" ]; } && echo grok=1`,
282
+ // The remote host owns its device-auth session. Ignore the legacy HQ mirror entry; it can outlive and mask the host credential.
283
+ // Read only expiry metadata, never credential values, and compare against the shared minimum lifetime.
284
+ `grokProbe=$(if [ ! -f "$HOME/.grok/auth.json" ]; then printf '0|'; else bun -e 'const fs=require("node:fs");try{const auth=JSON.parse(fs.readFileSync(process.argv[1],"utf8"));const entries=Object.entries(auth).filter(([id])=>id!=="https://auth.x.ai::hq-mirror");const hasKey=entries.some(([,entry])=>typeof entry?.key==="string"&&entry.key.length>0);const expiries=entries.filter(([,entry])=>typeof entry?.expires_at==="string").map(([,entry])=>entry.expires_at).sort();process.stdout.write((hasKey?"1":"0")+"|"+(expiries.length?expiries[expiries.length-1]:""))}catch{}' "$HOME/.grok/auth.json" 2>/dev/null; fi); grokOtherKey=\${grokProbe%%|*}; grokExp=\${grokProbe#*|}`,
285
+ `grokFloor=$(date -u -d "@$(( $(date +%s) + ${grokCredentialFloorSeconds} ))" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || date -u -r "$(( $(date +%s) + ${grokCredentialFloorSeconds} ))" +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true); grokNow=$(date -u +%Y-%m-%dT%H:%M:%SZ 2>/dev/null || true)`,
286
+ `grokHost=$(if [ -n "$XAI_API_KEY$GROK_API_KEY$GROK_CODE_XAI_API_KEY" ]; then echo valid; elif [ -z "$grokProbe" ]; then echo unknown; elif [ -z "$grokExp" ]; then [ "$grokOtherKey" = 1 ] && echo unknown || echo missing; elif [ -z "$grokFloor" ] || [ -z "$grokNow" ]; then echo unknown; else printf '%s\n%s\n%s\n' "$grokExp" "$grokFloor" "$grokNow" | awk 'NR==1{e=$0} NR==2{f=$0} NR==3{n=$0} END{if (e >= f) print "valid"; else if (e >= n) print "expiring"; else print "expired"}'; fi); echo "grokHost=$grokHost"`,
265
287
  `{ [ -s "\${ELANOUS_KEY_CACHE_DIR:-$HOME/.cache}/openrouter_api_key" ] || [ -n "\${OPENROUTER_API_KEY:-}" ]; } && echo openrouter=1`,
266
288
  `true`,
267
289
  ].join('; ');
@@ -273,6 +295,8 @@ export interface PreflightInput {
273
295
  localVersion: string;
274
296
  /** HQ 착지 동결이 «발사도 막는» 상태인가 — 원격 부모는 그 동결을 못 본다. */
275
297
  launchHoldActive: boolean;
298
+ /** Provider that the detached parent will use for its child. */
299
+ childProvider?: string;
276
300
  ssh?: SshRunner;
277
301
  }
278
302
 
@@ -296,11 +320,34 @@ export function judgeParentHostFacts(facts: Record<string, string>, input: Omit<
296
320
  if (facts.podPool !== '1' && !input.podPoolOverride) gaps.push('remote-pod-pool-unset');
297
321
  if (facts.repo !== '1') gaps.push('remote-repo-missing');
298
322
  if (facts.kubectl !== '1') gaps.push('remote-kubectl-missing');
323
+ if (input.childProvider === 'grok' && facts.grokCli !== '1') gaps.push('grok-cli-missing');
324
+ if ((input.childProvider === 'openai-codex' || input.childProvider === 'codex') && facts.codexCli !== '1') gaps.push('codex-cli-missing');
299
325
  }
300
326
  if (input.launchHoldActive) gaps.push('hq-launch-freeze-active');
301
327
  return gaps;
302
328
  }
303
329
 
330
+ /** Host-side Grok credential states the preflight probe reports; HQ never sees the token itself. */
331
+ export type ParentHostGrokCredentialState = 'valid' | 'expiring' | 'expired' | 'missing' | 'unknown';
332
+
333
+ /**
334
+ * 순수 판정 — 원격 호스트가 스스로 보고한 grok 자격 상태 → **막는** gap 목록(GROK-MIRROR-REAL-SCOPE · 10-20 방향 전환).
335
+ *
336
+ * 왜 경고가 아니라 gap 인가: access-only 미러(4필드)는 원격 grok CLI 1.0.41 에서 `session/new` -32000 으로
337
+ * 거부됐고, HQ refresh_token 복사는 단일 주인 원칙 위반이다. ⇒ 호스트가 각자 device-auth 세션을 스스로
338
+ * 갱신하고, HQ 는 「쓸 수 있나」만 재서 **무효면 Grok 자식 발사 전에** 막는다(발사 뒤 -32000 반복 금지).
339
+ *
340
+ * ⛔ 상태를 «안 보고한» 호스트(구 판)는 막지 않는다 — 모름을 「죽었다」로 읽으면 멀쩡한 호스트가 조용히 빠진다.
341
+ */
342
+ export function judgeParentHostGrokCredential(facts: Record<string, string>, opts: { childProvider?: string } = {}): string[] {
343
+ if (opts.childProvider !== 'grok' || facts.unreachable) return [];
344
+ const state = facts.grokHost as ParentHostGrokCredentialState | undefined;
345
+ if (state === 'missing') return ['grok-credential-missing'];
346
+ if (state === 'expiring') return ['grok-credential-expiring'];
347
+ if (state === 'expired') return ['grok-credential-expired'];
348
+ return [];
349
+ }
350
+
304
351
  /** 순수 판정 — 원격 LLM 자격 사실 → 경고 목록(막지 않는다 · gaps 와 별개). 못 닿은 호스트는 사실이 없으므로 경고도 없다. */
305
352
  export function judgeParentHostCredentials(facts: Record<string, string>): string[] {
306
353
  if (facts.unreachable) return [];
@@ -320,7 +367,16 @@ export function preflightParentHost(input: PreflightInput): ParentHostPreflight
320
367
  const at = line.indexOf('=');
321
368
  if (at > 0) facts[line.slice(0, at).trim()] = line.slice(at + 1).trim();
322
369
  }
323
- const gaps = judgeParentHostFacts(facts, { localVersion: input.localVersion, launchHoldActive: input.launchHoldActive, podPoolOverride: Boolean(input.target.podPool) });
370
+ const gaps = judgeParentHostFacts(facts, { localVersion: input.localVersion, launchHoldActive: input.launchHoldActive, podPoolOverride: Boolean(input.target.podPool), ...(input.childProvider ? { childProvider: input.childProvider } : {}) });
371
+ // 호스트 자체 grok 자격은 «경고»가 아니라 발사 전 «차단» 축이다 — 무효면 OP 재로그인 요청 신호를 남긴다.
372
+ const credentialGaps = judgeParentHostGrokCredential(facts, { ...(input.childProvider ? { childProvider: input.childProvider } : {}) });
373
+ if (credentialGaps.length) {
374
+ try {
375
+ debug.log('task-agent.parent-host', 'grok-relogin-required', {
376
+ host: input.target.host, state: facts.grokHost ?? 'unknown', gaps: credentialGaps,
377
+ });
378
+ } catch { /* fail-soft */ }
379
+ }
324
380
  const warnings = judgeParentHostCredentials(facts);
325
381
  if (warnings.length) {
326
382
  try {
@@ -332,7 +388,8 @@ export function preflightParentHost(input: PreflightInput): ParentHostPreflight
332
388
  });
333
389
  } catch { /* fail-soft */ }
334
390
  }
335
- return { ok: gaps.length === 0, gaps, warnings, facts };
391
+ const blocking = [...gaps, ...credentialGaps];
392
+ return { ok: blocking.length === 0, gaps: blocking, warnings, facts };
336
393
  }
337
394
 
338
395
  /** 원격이 «확실히 안 띄웠다»고 답했다 — 호출부가 로컬로 돌아가도 중복 발사가 아니다. */
@@ -350,9 +407,7 @@ export function launchRemoteParent(
350
407
  args: readonly string[],
351
408
  env: Record<string, string>,
352
409
  ssh: SshRunner = defaultSshRunner,
353
- grokMirrorResolver: () => OwnerGrokAccessMirror = resolveOwnerGrokAccessMirror,
354
410
  effectiveChildProvider?: string,
355
- now: () => number = Date.now,
356
411
  ): { pid: number; log: string } {
357
412
  const argvProvider = childProviderFromArgs(args);
358
413
  if (effectiveChildProvider && argvProvider && argvProvider !== effectiveChildProvider) {
@@ -361,9 +416,11 @@ export function launchRemoteParent(
361
416
  const launchArgs = effectiveChildProvider && !argvProvider
362
417
  ? [...args.slice(0, 2), '--child-llm-provider', effectiveChildProvider, ...args.slice(2)]
363
418
  : args;
419
+ // GROK-MIRROR-REAL-SCOPE: 원격 부모는 HQ access 미러를 «설치하지 않는다»(4필드 미러는 grok 1.0.41 에서
420
+ // `session/new` -32000 · HQ refresh_token 복사는 단일 주인 원칙 위반). 호스트가 각자 device-auth 로
421
+ // 자체 갱신 세션을 쓰고, HQ 는 preflight 에서 «유효성»만 재서 무효면 발사 전에 막는다.
364
422
  if ((effectiveChildProvider ?? argvProvider) === 'grok') {
365
- const mirror = grokMirrorResolver();
366
- installRemoteGrokAccess(target, mirror, ssh, now);
423
+ try { debug.log('task-agent.parent-host', 'grok-host-credential', { host: target.host, runId: env.ELANOUS_RUN_ID ?? 'unknown', source: 'host-device-auth' }); } catch { /* fail-soft */ }
367
424
  }
368
425
  const result = ssh(target.host, remoteLaunchScript(target, launchArgs, env), 30_000);
369
426
  const log = remoteParentLogPath(target, env.ELANOUS_RUN_ID ?? 'unknown');