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
@@ -1,8 +1,12 @@
1
1
  import { copyFileSync, lstatSync, mkdirSync, realpathSync } from 'node:fs';
2
2
  import { join, relative, resolve, sep } from 'node:path';
3
+ import { runGitCommand } from '../git-fs/runner.js';
3
4
  import { debug } from '../debug/log.js';
4
5
  import { judgeNextMove, retryMoveOf, SAME_MOVE_FAILURE_LIMIT } from './judge.js';
5
6
  import { checkCompletionEvidence } from './completion-evidence.js';
7
+ import { appendGreenSweepEvidence, decideGreenSweep, greenSweepCandidates, observeGreenSweep, type GreenSweepPr, type GreenSweepVerdict } from './green-sweep.js';
8
+ import type { TaskCard } from './task-hand.js';
9
+ import type { ChecklistItem } from '../release-loop/checklist.js';
6
10
 
7
11
  export type DeliveryKind = 'research-report' | 'artifact' | 'content';
8
12
  export interface DeliveryEvidence { ok: boolean; files: string[]; reason: string }
@@ -44,6 +48,8 @@ export interface NextAction {
44
48
  original: string;
45
49
  checklistId: string;
46
50
  history?: string[];
51
+ /** Only a producer bound to this PR may mark its owner worktree commit as harvesting. */
52
+ harvestState?: { pr: number; source: 'owner-worktree-commit'; head: string };
47
53
  mustFix?: string[];
48
54
  cwd?: string;
49
55
  risk?: 'money' | 'security' | 'irreversible-publication';
@@ -52,7 +58,7 @@ export interface NextAction {
52
58
  moveId?: string;
53
59
  }
54
60
  export interface ActionDeps {
55
- command(args: string[]): Promise<{ status: number; stdout: string; stderr?: string }>;
61
+ command(args: string[], cwd?: string): Promise<{ status: number; stdout: string; stderr?: string }>;
56
62
  mode?: string;
57
63
  landingsToday?: number;
58
64
  landingDay?: string;
@@ -73,6 +79,14 @@ export interface ActionDeps {
73
79
  retryLaunches?: { count: number };
74
80
  /** mbp 부하 관문(OP 신호 `loadMax`) — 지금 1분 부하가 `loadMax` 이상이거나 못 읽으면 발사하지 않고 shadow. 없으면 관문 없음(종전). */
75
81
  loadGate?: { loadMax: number; load1(): number | null };
82
+ /** GREEN-FROM-LEDGER-FU — green live 쓰기 문맥(관측 probe ⊕ 칸 원문·판본·과제 카드). 실행부 green 경로가 소비자
83
+ * `consumeGreenSweepForGreenWrite`를 지나 원문 대조가 모두 일치할 때만 checklist green 쓰기를 1회 한다.
84
+ * 없으면 종전 그대로 검증 안내 카드(fail-closed) — 문맥 없이 green 은 쓰지 않는다. */
85
+ greenSweep?: { probe: GreenSweepProbe; item: ChecklistItem; version: string; cards: readonly TaskCard[] };
86
+ /** Checklist green writes are a separate OP-authorized capability; default is observation only. */
87
+ greenWriteLive?: boolean;
88
+ /** Read-only owner checkout probe for review harvest verification. */
89
+ harvestGit?: (cwd: string, args: string[]) => { status: number | null; stdout: string };
76
90
  }
77
91
 
78
92
  /** 재발사는 한 판단 회차에 한 건만 발사한다. */
@@ -178,6 +192,28 @@ const RETRY_HINT: Record<Exclude<RetryVariant, 'wait'>, (action: NextAction) =>
178
192
  alternative: () => 'Alternative approach: the same move already failed twice. Choose a different approach than the previous runs.',
179
193
  };
180
194
 
195
+ export function ownerWorktreeHarvestState(input: { pr: number; cwd: string; head: string; branch: string; state: string },
196
+ gitRun?: (cwd: string, args: string[]) => { status: number | null; stdout: string }): NextAction['harvestState'] {
197
+ if (!Number.isSafeInteger(input.pr) || input.pr < 1 || input.state !== 'OPEN' || !/^[a-f0-9]{40}$/i.test(input.head)) return undefined;
198
+ const git = gitRun ?? ((cwd: string, args: string[]) => {
199
+ const result = runGitCommand(cwd, args, { encoding: 'utf-8' });
200
+ return { status: result.status, stdout: String(result.stdout ?? '') };
201
+ });
202
+ try {
203
+ const cwd = realpathSync(input.cwd);
204
+ const [branch, local, registry] = [git(cwd, ['branch', '--show-current']), git(cwd, ['rev-parse', 'HEAD']), git(cwd, ['worktree', 'list', '--porcelain'])];
205
+ const name = branch.stdout.trim();
206
+ const commit = local.stdout.trim();
207
+ if (branch.status !== 0 || !name || local.status !== 0 || !/^[a-f0-9]{40}$/i.test(commit) || registry.status !== 0) return undefined;
208
+ const owners = registry.stdout.trim().split(/\n\s*\n/).filter(entry => entry.split('\n').includes(`branch refs/heads/${name}`));
209
+ const ownerPath = owners[0]?.split('\n').find(line => line.startsWith('worktree '))?.slice('worktree '.length);
210
+ if (owners.length !== 1 || !ownerPath || realpathSync(ownerPath) !== cwd) return undefined;
211
+ if (input.branch !== name || input.head.toLowerCase() === commit.toLowerCase()) return undefined;
212
+ if (git(cwd, ['merge-base', '--is-ancestor', input.head, commit]).status !== 0) return undefined;
213
+ return { pr: input.pr, source: 'owner-worktree-commit', head: commit };
214
+ } catch { return undefined; }
215
+ }
216
+
181
217
  export async function executeNextAction(action: NextAction, deps: ActionDeps): Promise<string> {
182
218
  const record = (result: string, reason: string) => {
183
219
  if (result === 'failed' && (deps.failureCounts || deps.incrementFailure)) {
@@ -191,10 +227,16 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
191
227
  };
192
228
  const shadowReason = deps.mode === 'live' ? retryShadowReason(action, deps) : undefined;
193
229
  if (deps.mode !== 'live' || shadowReason) {
230
+ if (action.kind === 'green' && deps.greenSweep) {
231
+ const outcome = await consumeGreenSweepForGreenWrite({ deps, probe: deps.greenSweep.probe,
232
+ item: deps.greenSweep.item, version: deps.greenSweep.version, cards: deps.greenSweep.cards, writeLive: false });
233
+ return record(outcome.verdict === 'green' ? 'would-green' : 'refused', outcome.reason);
234
+ }
194
235
  const destination = action.delivery && action.kind === 'deliver'
195
236
  ? ` → ${join(action.delivery.projectTarget, 'elanous-out', action.taskId)}/${action.delivery.files.join(', ')}` : '';
196
237
  return record('shadow', `would ${action.kind}${action.variant ? `:${action.variant}` : ''}: ${action.rationale}${destination}${shadowReason ? ` · shadow: ${shadowReason}` : ''}`);
197
238
  }
239
+ const gh = (args: string[]) => deps.command(args, action.cwd);
198
240
  const card = async (reason: string) => {
199
241
  const evidence = JSON.stringify({ runId: action.runId, pr: action.pr, mustFix: action.mustFix ?? [], history: action.history ?? [], selected: action.kind, reason });
200
242
  const result = await deps.command(decisionRaiseArgs({ taskId: action.taskId, reason, ...(action.risk ? { risk: action.risk } : {}), evidence }));
@@ -204,7 +246,7 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
204
246
  if (sameMoveFailures(action, deps) >= SAME_MOVE_FAILURE_LIMIT) return card('same task/action failed twice');
205
247
  if (action.kind === 'land') {
206
248
  if (!action.cwd) return card('landing worktree unknown');
207
- const view = await deps.command(['gh', 'pr', 'view', String(action.pr), '--json', 'labels']);
249
+ const view = await gh(['gh', 'pr', 'view', String(action.pr), '--json', 'labels']);
208
250
  if (view.status !== 0) return card('PR labels unavailable');
209
251
  let labels: unknown;
210
252
  try { labels = (JSON.parse(view.stdout) as { labels?: unknown }).labels; }
@@ -250,12 +292,45 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
250
292
  const judgement = judgeNextMove({ deliveryEvidence: evidence });
251
293
  return record(judgement.move === 'propose-green' ? 'done' : 'waiting', `${judgement.move}: ${judgement.reason}`);
252
294
  }
253
- if (action.kind === 'green') return card('green requires a verified landing in this execution');
295
+ if (action.kind === 'green') {
296
+ // GREEN-FROM-LEDGER-FU 배선(shard 2) — 생산 진입점이 소비자를 지나 dry-run 판정 ⊕ 원문 대조 후 쓰기를 지킨다:
297
+ // 대조가 모두 일치하면 checklist green 명령 1회, 거부·unknown·mismatch 는 쓰기 0회 + 칸 상태 불변(fail-closed).
298
+ // 문맥(deps.greenSweep)이 없으면 종전 그대로 검증 안내 카드 — 호출부가 문맥을 안 싣는 동안 green 은 쓰지 않는다.
299
+ const greenSweep = deps.greenSweep;
300
+ if (!greenSweep) return card('green requires a verified landing in this execution');
301
+ const writeLive = deps.greenWriteLive === true;
302
+ const outcome = await consumeGreenSweepForGreenWrite({ deps, probe: greenSweep.probe, item: greenSweep.item,
303
+ version: greenSweep.version, cards: greenSweep.cards, writeLive });
304
+ return record(outcome.written ? 'done' : outcome.verdict === 'green-command-failed' ? 'failed'
305
+ : outcome.verdict === 'green' ? 'would-green' : 'refused', outcome.reason);
306
+ }
254
307
  // G1 — 기다림은 발사가 아니다: 대기 표지만 남기고 다음 틱이 다시 판단한다(카드로 올리지 않는다).
255
308
  if (action.kind === 'retry' && action.variant === 'wait') return record('waiting', `wait marker: ${action.rationale}`);
256
309
  // must-fix 없는 재발사가 카드로 가는 것은 갈래 없는(종전) retry 뿐이다 — narrow·salvage·alternative 는 갈래 문면으로 간다.
257
310
  if (action.kind === 'retry' && !action.variant && !action.mustFix?.length) return card('must-fix missing; cannot narrow retry');
258
311
  if (action.kind === 'review') {
312
+ let harvestState: NextAction['harvestState'];
313
+ if (action.harvestState?.source === 'owner-worktree-commit' && action.harvestState.pr === action.pr && action.cwd
314
+ && /^[a-f0-9]{40}$/i.test(action.harvestState.head)) {
315
+ try {
316
+ const response = await gh(['gh', 'pr', 'view', String(action.pr), '--json', 'state,headRefOid,headRefName']);
317
+ if (response.status === 0) {
318
+ const pr = JSON.parse(response.stdout) as { state?: unknown; headRefOid?: unknown; headRefName?: unknown };
319
+ if (typeof pr.headRefOid === 'string' && typeof pr.headRefName === 'string' && typeof pr.state === 'string') {
320
+ const current = ownerWorktreeHarvestState({ pr: action.pr, cwd: action.cwd, head: pr.headRefOid,
321
+ branch: pr.headRefName, state: pr.state }, deps.harvestGit);
322
+ if (current?.head.toLowerCase() === action.harvestState.head.toLowerCase()) harvestState = current;
323
+ }
324
+ }
325
+ } catch { /* Unverified caller signal preserves the review command. */ }
326
+ }
327
+ if (harvestState) {
328
+ action.harvestState = harvestState;
329
+ const reason = `review skipped: owner-worktree-commit PR #${action.pr} ${harvestState.head}`;
330
+ (action.history ??= []).push('review skipped: owner-worktree-commit');
331
+ record('skipped', reason);
332
+ return record('waiting', `${reason} · next: wait for exact-head review evidence`);
333
+ }
259
334
  const review = await deps.command(['self', 'review', String(action.pr), '--json']);
260
335
  if (review.status !== 0) return record('failed', 'review command failed');
261
336
  let parsed: { verdict?: string; mustFix?: string[]; reviewed?: boolean };
@@ -284,7 +359,7 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
284
359
  return record('failed', `${action.kind} command failed: ${outcome.stderr ?? ''}`);
285
360
  }
286
361
  if (action.kind === 'land') {
287
- const merged = await deps.command(['gh', 'pr', 'view', String(action.pr), '--json', 'state,mergeCommit']);
362
+ const merged = await gh(['gh', 'pr', 'view', String(action.pr), '--json', 'state,mergeCommit']);
288
363
  let sha: string | undefined;
289
364
  let notMerged = false;
290
365
  try {
@@ -309,6 +384,126 @@ export async function executeNextAction(action: NextAction, deps: ActionDeps): P
309
384
  return record('done', action.rationale);
310
385
  }
311
386
 
387
+ /**
388
+ * GREEN-FROM-LEDGER-FU — green live 쓰기 소비자: `green-sweep.ts`(순수 판정 · checklist/card 쓰기 0)의
389
+ * dry-run 결정을 소비해 실제 checklist green 쓰기를 수행하는 유닛. 쓰기 책임은 전부 이 소비자가 진다.
390
+ * 판정이 green 이고 후보의 OP 원문 대조가 모두 일치할 때만 `release checklist set --status green`
391
+ * (executeNextAction 의 착지 green 쓰기와 같은 명령면)을 deps.command 로 수행한다.
392
+ * 판정 거부 · 원문 대조 불일치 · 명령 실패는 전부 쓰기 0 — 거짓 green 을 쓰지 않는다(fail-closed).
393
+ * 원문 대조는 세 다리다: ① observeGreenSweep 표준 출력이 판정과 정확히 같은가 ② plannedEvidence 가
394
+ * 판정 원문(existingEvidence + evidence 행)과 정확히 같은가 ③ 쓰기 직전 칸 원문이 판정이 본 것과 같은가.
395
+ * ③ 은 칸 원문 재독기(cellEvidence)가 실제 일치를 확인했을 때만 'cell ok' 로 남는다 — 미제공·재독 불가는
396
+ * 자기 자신(item.evidence)과의 공전 대조를 하지 않고 unknown 상태로 보존해 쓰기를 거부한다.
397
+ * 결과는 deps.observe('task-agent.action', { kind: 'green', … }) 로 관측면에 남긴다.
398
+ */
399
+ export interface GreenSweepProbe {
400
+ /** 후보 PR 관측(gh pr view 상당). null = 못 읽었다(pr-unreadable). */
401
+ pr(pr: number): Promise<GreenSweepPr | null>;
402
+ /** 후보 merge sha 가 origin/main 조상인가. null = 못 읽었다. */
403
+ ancestor(sha: string): Promise<boolean | null>;
404
+ /** 트래픽 hold 여부. null = 못 읽었다. */
405
+ hold(): Promise<boolean | null>;
406
+ /** 후보 PR 이 이 칸의 저장소에 속하는가. 주지 않으면 판정이 record-only 로 거부한다. */
407
+ repositoryMatches?(pr: number): Promise<boolean | null>;
408
+ /** 다른 칸이 같은 PR 을 주장하나(ambiguousAcrossCells). */
409
+ ambiguousAcrossCells?(pr: number): boolean | null;
410
+ /** 칸 원문 재독기 — 판정이 본 증거(evidence)와 쓰기 직전 칸 원문이 같은지 대조한다. 못 읽으면 undefined(대조 불가 → 쓰기 거부).
411
+ * 필수 멤버다 — 미제공이면 소비자는 자기 자신(item.evidence)과의 공전 대조를 하지 않고 unknown 상태로 쓰기를 거부한다. */
412
+ cellEvidence(cell: string): Promise<string | undefined>;
413
+ }
414
+
415
+ export interface GreenSweepWriteOutcome {
416
+ cell: string;
417
+ pr: number | null;
418
+ /** true = `release checklist set --status green` 명령까지 성공했다. 그 외는 전부 쓰기 0. */
419
+ written: boolean;
420
+ /** green = 쓰기 성공 · evidence-unknown = 원문 대조를 수행할 수 없었다(칸 원문 미제공·재독 불가) · 그 외 판정·대조·명령 사유. */
421
+ verdict: GreenSweepVerdict | 'no-candidates' | 'evidence-mismatch' | 'evidence-unknown' | 'green-command-failed';
422
+ reason: string;
423
+ }
424
+
425
+ export async function consumeGreenSweepForGreenWrite(input: {
426
+ deps: Pick<ActionDeps, 'command' | 'observe'>;
427
+ probe: GreenSweepProbe;
428
+ item: ChecklistItem;
429
+ version: string;
430
+ cards: readonly TaskCard[];
431
+ writeLive?: boolean;
432
+ }): Promise<GreenSweepWriteOutcome> {
433
+ const { deps, probe, item, version, cards, writeLive = false } = input;
434
+ const candidates = greenSweepCandidates(item, version, cards);
435
+ const record = (outcome: GreenSweepWriteOutcome): GreenSweepWriteOutcome => {
436
+ deps.observe('task-agent.action', {
437
+ taskId: item.id, kind: 'green', result: outcome.written ? 'done'
438
+ : outcome.verdict === 'green-command-failed' ? 'failed'
439
+ : outcome.verdict === 'green' && !writeLive ? 'would-green' : 'refused', reason: outcome.reason,
440
+ });
441
+ return outcome;
442
+ };
443
+ if (!candidates.length) {
444
+ return record({ cell: item.id, pr: null, written: false, verdict: 'no-candidates', reason: 'GREEN-FROM-LEDGER-FU: dry-run 후보 없음' });
445
+ }
446
+ let last: GreenSweepWriteOutcome | undefined;
447
+ for (const candidate of candidates) {
448
+ const pr = await probe.pr(candidate.pr);
449
+ const mergeSha = pr?.mergeSha && /^[a-f0-9]{40}$/i.test(pr.mergeSha) ? pr.mergeSha : null;
450
+ const [ancestor, hold, repositoryMatches] = await Promise.all([
451
+ probe.ancestor(mergeSha ?? ''),
452
+ probe.hold(),
453
+ probe.repositoryMatches ? probe.repositoryMatches(candidate.pr) : Promise.resolve(null),
454
+ ]);
455
+ const decision = decideGreenSweep({
456
+ item, candidate, candidateCount: candidates.length, pr, ancestor, hold,
457
+ ...(repositoryMatches === null ? {} : { repositoryMatches }),
458
+ ...(probe.ambiguousAcrossCells ? { ambiguousAcrossCells: probe.ambiguousAcrossCells(candidate.pr) ?? undefined } : {}),
459
+ });
460
+ // 원문 대조 ① — observeGreenSweep 표준 출력(«OP 원문» 관측)이 판정과 정확히 같은가.
461
+ let observed: { category: string; event: string; data?: unknown } | undefined;
462
+ observeGreenSweep(decision, (category, event, data) => { observed = { category, event, data }; });
463
+ const emitted = observed?.data as { cell?: unknown; pr?: unknown; mergeSha?: unknown; reason?: unknown } | undefined;
464
+ const emissionMatches = observed?.category === 'task-agent.green-sweep'
465
+ && observed.event === decision.verdict
466
+ && emitted?.cell === decision.cell
467
+ && emitted?.pr === decision.pr
468
+ && emitted?.mergeSha === decision.mergeSha
469
+ && emitted?.reason === decision.reason;
470
+ // 원문 대조 ② — plannedEvidence 가 판정 원문(existingEvidence + evidence 행)과 정확히 같은가.
471
+ const plannedMatches = decision.plannedEvidence === appendGreenSweepEvidence(decision.existingEvidence, decision.evidence);
472
+ if (decision.verdict !== 'green') {
473
+ last = record({
474
+ cell: item.id, pr: candidate.pr, written: false, verdict: decision.verdict,
475
+ reason: `GREEN-FROM-LEDGER-FU: 판정 거부 — ${decision.evidence}`,
476
+ });
477
+ continue;
478
+ }
479
+ // 원문 대조 ③ — 쓰기 직전 칸 원문이 판정이 본 것과 같은가(판정 중 칸 변경 방지). green 판정에만 재독한다.
480
+ // cellEvidence 미제공·재독 불가는 자기 자신(item.evidence)과 대조하지 않는다 — 그 대조는 공전이므로
481
+ // unknown 상태로 보존해 쓰기를 거부한다(fail-closed). 'cell ok' 는 실제 재독 ⊕ 일치 확인에만 나온다.
482
+ const cellProbe = probe.cellEvidence;
483
+ const currentEvidence = typeof cellProbe === 'function' ? await cellProbe(item.id) : undefined;
484
+ const cellState: 'ok' | 'mismatch' | 'unreadable' | 'unprovided'
485
+ = typeof cellProbe !== 'function' ? 'unprovided'
486
+ : typeof currentEvidence !== 'string' ? 'unreadable'
487
+ : currentEvidence === decision.existingEvidence ? 'ok' : 'mismatch';
488
+ if (!emissionMatches || !plannedMatches || cellState !== 'ok') {
489
+ const mismatched = !emissionMatches || !plannedMatches || cellState === 'mismatch';
490
+ return record({
491
+ cell: item.id, pr: candidate.pr, written: false,
492
+ verdict: mismatched ? 'evidence-mismatch' : 'evidence-unknown',
493
+ reason: `GREEN-FROM-LEDGER-FU: ${mismatched ? '원문 대조 불일치' : '원문 대조 불가(칸 원문 unknown)'} — emission ${emissionMatches ? 'ok' : 'mismatch'} · planned ${plannedMatches ? 'ok' : 'mismatch'} · cell ${cellState}`,
494
+ });
495
+ }
496
+ if (!writeLive) return record({ cell: item.id, pr: candidate.pr, written: false, verdict: 'green',
497
+ reason: `would-green: ${decision.evidence} · live write disabled` });
498
+ const green = await deps.command(['release', 'checklist', 'set', item.id, '--status', 'green', '--evidence', decision.evidence]);
499
+ if (green.status !== 0) {
500
+ return record({ cell: item.id, pr: candidate.pr, written: false, verdict: 'green-command-failed', reason: `green command failed: ${green.stderr ?? ''}` });
501
+ }
502
+ return record({ cell: item.id, pr: candidate.pr, written: true, verdict: 'green', reason: decision.evidence });
503
+ }
504
+ return last ?? record({ cell: item.id, pr: null, written: false, verdict: 'no-candidates', reason: 'GREEN-FROM-LEDGER-FU: dry-run 후보 없음' });
505
+ }
506
+
312
507
  /** Execute the allowed candidates in a caller-supplied tick and emit one isolated denominator event. */
313
508
  export async function executeEntranceTick(candidates: readonly EntranceTickCandidate[], deps: ActionDeps): Promise<string[]> {
314
509
  const denominator = buildEntranceRefusalDenominator(candidates.map(({ action, refusal }) => ({
@@ -3,7 +3,7 @@ import { randomBytes } from 'node:crypto';
3
3
  import { loadRunLedger, runLedgerDir, type RunLedgerEntry } from '../self-implement/run-ledger.js';
4
4
  import { remoteLedgerMirrorDir } from './parent-host.js';
5
5
  import { prodInstanceRoot } from '../instance/resolve.js';
6
- import { cardPrNumber, updateTaskCard, type TaskCard } from './task-hand.js';
6
+ import { cardPrNumber, updateTaskCard, updateTaskCardsAtomically, type TaskCard } from './task-hand.js';
7
7
 
8
8
  export interface AdoptPrView {
9
9
  number: number; url: string; state: string; baseRefName: string; headRefOid: string;
@@ -20,6 +20,9 @@ export interface AdoptPrInput {
20
20
  unlinkedTerminal?: boolean;
21
21
  observedRun?: { runId?: string; runChildId?: string; parentHost?: string; launchId?: string };
22
22
  observedChecklist?: { id: string; version: string; status: string; cardVersion?: string };
23
+ /** --rebind: source snapshot and terminal proof (computed before taking the state lock). */
24
+ rebindSource?: { card: Pick<TaskCard, 'id' | 'status' | 'runId' | 'runChildId' | 'launchId' | 'parentHost' | 'checklistId' | 'checklistVersion' | 'pr'>;
25
+ terminalRunEvidence: boolean };
23
26
  checklistAtWrite?: () => { id: string; status: string } | undefined;
24
27
  }
25
28
 
@@ -60,7 +63,7 @@ export function adoptedRunTerminal(card: TaskCard, pr: AdoptPrView,
60
63
  }
61
64
 
62
65
  /** The PR is read from the selected repository before this call; rejudge checks it again before every live move. */
63
- export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created: boolean; changed: boolean } {
66
+ export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created: boolean; changed: boolean; previousCardId?: string } {
64
67
  const { pr } = input;
65
68
  const slug = pr.url.match(/^https:\/\/github\.com\/([^/]+\/[^/]+)\/pull\/\d+\/?$/)?.[1];
66
69
  if (!Number.isSafeInteger(pr.number) || pr.number < 1 || pr.state !== 'OPEN' || pr.baseRefName !== 'main'
@@ -68,6 +71,11 @@ export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created:
68
71
  || Number(pr.url.match(/\/pull\/(\d+)/)?.[1]) !== pr.number
69
72
  || !/^[a-f0-9]{40}$/i.test(pr.headRefOid)) throw new Error('입양할 PR은 현재 저장소의 OPEN/main PR 번호·URL·head SHA40이어야 한다');
70
73
  if ((input.cardId === undefined) === (input.checklist === undefined)) throw new Error('--card 또는 --checklist/--version 중 하나만 준다');
74
+ if (input.rebindSource) {
75
+ if (input.cardId || !input.checklist || !input.version || input.checklist.version !== input.version)
76
+ throw new Error('--rebind는 --checklist와 같은 --version을 지정하고 --card는 생략한다');
77
+ return rebindExistingPr(input, input.rebindSource);
78
+ }
71
79
  if (input.cardId && !input.version) throw new Error('기존 카드는 체크리스트 판을 확정해야 한다');
72
80
  if (input.checklist && (!input.checklist.id || !input.checklist.title || !input.checklist.version
73
81
  || ['green', 'done'].includes(input.checklist.status))) throw new Error('입양할 체크리스트 칸은 미완 판·id·제목이어야 한다');
@@ -138,3 +146,56 @@ export function adoptExistingPr(input: AdoptPrInput): { card: TaskCard; created:
138
146
  if (!result) throw new Error(`카드 쓰기 실패: ${id}`);
139
147
  return { card: result, created, changed };
140
148
  }
149
+
150
+ function rebindExistingPr(input: AdoptPrInput, sourceSnapshot: NonNullable<AdoptPrInput['rebindSource']>)
151
+ : { card: TaskCard; created: true; changed: true; previousCardId: string } {
152
+ const { pr, checklist, version } = input;
153
+ if (!checklist || !version) throw new Error('--rebind 대상 체크리스트 판이 없다');
154
+ const at = (input.now ?? new Date()).toISOString();
155
+ const id = `ta-${at.slice(0, 10).replaceAll('-', '')}-${randomBytes(3).toString('hex')}`;
156
+ const replacements = updateTaskCardsAtomically(input.statePath, (tasks) => {
157
+ if (tasks[id]) throw new Error(`새 카드 id 충돌: ${id}`);
158
+ const matches = Object.values(tasks).filter((card) => cardPrNumber(card) === pr.number);
159
+ if (matches.length !== 1) throw new Error(matches.length
160
+ ? `PR #${pr.number}가 여러 카드에 묶였다 — 임의로 rebind하지 않는다`
161
+ : `PR #${pr.number}가 기존 카드에 묶이지 않았다 — --rebind 대상 없음`);
162
+ const current = matches[0]!;
163
+ const observed = sourceSnapshot.card;
164
+ if (current.id !== observed.id || current.status !== observed.status || current.runId !== observed.runId
165
+ || current.runChildId !== observed.runChildId || current.launchId !== observed.launchId
166
+ || current.checklistId !== observed.checklistId || current.checklistVersion !== observed.checklistVersion
167
+ || current.parentHost?.host !== observed.parentHost?.host || cardPrNumber(current) !== cardPrNumber(observed)
168
+ || (typeof current.pr === 'object' ? current.pr.url : undefined) !== (typeof observed.pr === 'object' ? observed.pr.url : undefined))
169
+ throw new Error(`rebind 중 원본 카드가 바뀌었다: ${observed.id}`);
170
+ if (typeof current.pr === 'object' && current.pr.url && current.pr.url !== pr.url)
171
+ throw new Error(`원본 카드의 PR URL이 조회 결과와 다르다: ${current.id}`);
172
+ if (current.status !== 'failed' && (current.checklistVersion === version && current.checklistId === checklist.id))
173
+ throw new Error(`같은 판·칸의 failed 카드만 rebind할 수 있다: ${current.id}`);
174
+ if (current.status !== 'failed' && (current.status !== 'launched' || sourceSnapshot.terminalRunEvidence !== true))
175
+ throw new Error(`원본 런 종결·정확한 PR 근거가 없다: ${current.id}`);
176
+ if (Object.values(tasks).some((card) => card.id !== current.id && card.status === 'launched' && card.taLand === true
177
+ && cardPrNumber(card) !== undefined && card.checklistId === checklist.id && card.checklistVersion === version))
178
+ throw new Error(`칸 ${checklist.id}에 이미 TA 착지 후보 카드가 있다`);
179
+ const liveCell = input.checklistAtWrite?.();
180
+ if (input.checklistAtWrite && (!liveCell || liveCell.id !== checklist.id || ['green', 'done'].includes(liveCell.status)))
181
+ throw new Error(`입양 중 체크리스트 칸이 바뀌거나 완료됐다: ${checklist.id}`);
182
+
183
+ const { pr: _pr, adoptedPr: _adoptedPr, prTerminal: _prTerminal, taLand: _taLand, ...oldCard } = current;
184
+ const released: TaskCard = { ...oldCard, history: [...current.history, {
185
+ at, event: 'pr-rebound-out', pr: pr.number, head: pr.headRefOid,
186
+ detail: `PR 결속을 ${version}/${checklist.id} 새 카드 ${id}로 이동 · ${pr.url}`,
187
+ }] };
188
+ const adopted: TaskCard = {
189
+ id, text: checklist.title, checklistId: checklist.id, checklistVersion: version,
190
+ createdAt: at, status: 'launched', taLand: true, pr: { number: pr.number, url: pr.url },
191
+ adoptedPr: { pr: pr.number, url: pr.url, head: pr.headRefOid, at },
192
+ history: [{ at, event: 'pr-adopted', pr: pr.number, head: pr.headRefOid,
193
+ detail: `기존 PR rebind · 원본 카드 ${current.id} · ${pr.url} · 새 구현 발사 0` }],
194
+ };
195
+ return [released, adopted];
196
+ });
197
+ const card = replacements?.find((replacement) => replacement.id === id);
198
+ const previous = replacements?.find((replacement) => replacement.id !== id);
199
+ if (!card || !previous) throw new Error('PR rebind 원자 갱신 결과가 없다');
200
+ return { card, created: true, changed: true, previousCardId: previous.id };
201
+ }
@@ -0,0 +1,12 @@
1
+ import { createHash } from 'node:crypto';
2
+
3
+ /** Hash the exact typed mapping in the current title; ambiguity never inherits an old receipt. */
4
+ export function boundaryMappingHash(title: string): string | null {
5
+ const matches = [...title.matchAll(/^\s*-?\s*완료 경계 실물 검증:\s*(.+)$/gm)];
6
+ if (matches.length !== 1) return null;
7
+ try {
8
+ const mapping: unknown = JSON.parse(matches[0]![1]!);
9
+ if (!Array.isArray(mapping) || mapping.length < 1 || mapping.length > 8) return null;
10
+ return createHash('sha256').update(JSON.stringify(mapping)).digest('hex');
11
+ } catch { return null; }
12
+ }
@@ -0,0 +1,147 @@
1
+ import { existsSync, linkSync, mkdirSync, readFileSync, realpathSync, unlinkSync, writeFileSync } from 'node:fs';
2
+ import { dirname, isAbsolute, resolve } from 'node:path';
3
+ import { spawnElanousSync } from '../instance/spawn-elanous.js';
4
+ import { lastJsonObject } from '../graph-runner/runner.js';
5
+ import { boundaryMappingHash } from './boundary-proof-mapping.js';
6
+ import { parseGreenCloseEvidenceCommand, runGreenCloseEvidenceTest } from './green-close-recipe.js';
7
+
8
+ type Assertion = { path: string; equals: string | number | boolean };
9
+ type TestRun = { kind: 'test-run'; command: string };
10
+ type GraphRun = { kind: 'graph-run'; graphId: string; runId: string; nodeId: string; assertion: Assertion };
11
+ type CliJson = { kind: 'cli-json'; argv: string[]; assertion: Assertion };
12
+ export type BoundaryCheck = TestRun | GraphRun | CliJson;
13
+ export interface BoundaryProofInput {
14
+ title: string; cellId: string; mainSha: string; mapRunId: string; cardId: string;
15
+ graphRunId: string; stateRoot: string; repoRoot: string;
16
+ }
17
+ export interface BoundaryProofResult { outcome: 'pass' | 'hold'; reason: string; evidence: string[]; proofRef?: string }
18
+
19
+ const safeId = /^[A-Za-z0-9_-]{1,160}$/;
20
+ const sha = /^[a-f0-9]{40}$/i;
21
+ const safePath = /^[A-Za-z_][A-Za-z0-9_.-]*$/;
22
+ const safeGraphId = /^[A-Za-z0-9_-]+$/;
23
+
24
+ function object(value: unknown): Record<string, unknown> | null {
25
+ return value !== null && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : null;
26
+ }
27
+ function assertion(value: unknown): Assertion | null {
28
+ const raw = object(value);
29
+ if (!raw || typeof raw.path !== 'string' || !safePath.test(raw.path)
30
+ || !['string', 'number', 'boolean'].includes(typeof raw.equals)) return null;
31
+ return { path: raw.path, equals: raw.equals as Assertion['equals'] };
32
+ }
33
+ function atPath(value: unknown, path: string): unknown {
34
+ return path.split('.').reduce<unknown>((current, key) =>
35
+ Array.isArray(current) && /^\d+$/.test(key) ? current[Number(key)] : object(current)?.[key], value);
36
+ }
37
+
38
+ /** Explicit finite mapping; prose alone never becomes executable shell. */
39
+ export function parseBoundaryChecks(title: string): BoundaryCheck[] | null {
40
+ const line = /^\s*-?\s*완료 경계 실물 검증:\s*(.+)$/gm;
41
+ const matches = [...title.matchAll(line)];
42
+ if (matches.length !== 1) return null;
43
+ let parsed: unknown;
44
+ try { parsed = JSON.parse(matches[0]![1]!); } catch { return null; }
45
+ if (!Array.isArray(parsed) || parsed.length < 1 || parsed.length > 8) return null;
46
+ const checks: BoundaryCheck[] = [];
47
+ for (const value of parsed) {
48
+ const check = object(value);
49
+ if (!check) return null;
50
+ if (check.kind === 'test-run' && typeof check.command === 'string'
51
+ && parseGreenCloseEvidenceCommand(check.command).ok) {
52
+ checks.push({ kind: 'test-run', command: check.command });
53
+ } else if (check.kind === 'graph-run' && typeof check.graphId === 'string'
54
+ && safeGraphId.test(check.graphId) && typeof check.runId === 'string' && safeId.test(check.runId)
55
+ && typeof check.nodeId === 'string' && safeId.test(check.nodeId) && assertion(check.assertion)) {
56
+ checks.push({ kind: 'graph-run', graphId: check.graphId, runId: check.runId,
57
+ nodeId: check.nodeId, assertion: assertion(check.assertion)! });
58
+ } else if (check.kind === 'cli-json' && Array.isArray(check.argv)
59
+ && check.argv.every((arg) => typeof arg === 'string') && assertion(check.assertion)
60
+ && allowedReadOnlyCli(check.argv as string[])) {
61
+ checks.push({ kind: 'cli-json', argv: check.argv as string[], assertion: assertion(check.assertion)! });
62
+ } else return null;
63
+ }
64
+ return checks;
65
+ }
66
+
67
+ /** A deliberately small set of read-only production CLI calls. */
68
+ export function allowedReadOnlyCli(argv: readonly string[]): boolean {
69
+ if (argv.length !== 7 || argv[0] !== 'bun' || argv[1] !== 'bin/elanous.mjs'
70
+ || argv[2] !== 'release' || argv[3] !== 'checklist' || argv[4] !== 'status'
71
+ || argv[5] !== '--version' || !/^\d+\.\d+\.\d+(?:-[A-Za-z0-9.-]+)?$/.test(argv[6] ?? '')) return false;
72
+ return true;
73
+ }
74
+
75
+ function checkGraphRun(input: BoundaryProofInput, check: GraphRun): boolean {
76
+ const path = resolve(input.stateRoot, 'graph-runs', check.graphId, `${check.runId}.json`);
77
+ const root = realpathSync(input.stateRoot);
78
+ if (!realpathSync(path).startsWith(root + '/')) return false;
79
+ const run = JSON.parse(readFileSync(path, 'utf8')) as Record<string, unknown>;
80
+ const runInput = object(run.input);
81
+ const main = object(runInput?.main);
82
+ const node = Array.isArray(run.nodes) ? run.nodes.find((entry) => object(entry)?.nodeId === check.nodeId) : null;
83
+ const output = object(node)?.output;
84
+ const parsedOutput = typeof output === 'string' ? lastJsonObject(output) : output;
85
+ return run.graphId === check.graphId && run.runId === check.runId && run.status === 'done'
86
+ && runInput?.cellId === input.cellId && (runInput?.mainSha === input.mainSha || main?.sha === input.mainSha)
87
+ && object(node)?.ok === true && object(node)?.exit === 0
88
+ && atPath(parsedOutput, check.assertion.path) === check.assertion.equals;
89
+ }
90
+
91
+ function checkCliJson(input: BoundaryProofInput, check: CliJson): boolean {
92
+ const run = spawnElanousSync(['--config-dir', input.stateRoot, ...check.argv.slice(2), '--json'], {
93
+ bin: resolve(input.repoRoot, 'bin/elanous.mjs'), stateDir: input.stateRoot, cwd: input.repoRoot,
94
+ timeout: 30_000, maxBuffer: 2_000_000, encoding: 'utf8', stdio: ['ignore', 'pipe', 'pipe'],
95
+ });
96
+ if (run.status !== 0) return false;
97
+ return atPath(JSON.parse(String(run.stdout)), check.assertion.path) === check.assertion.equals;
98
+ }
99
+
100
+ function checkTestRun(input: BoundaryProofInput, check: TestRun): boolean {
101
+ const command = parseGreenCloseEvidenceCommand(check.command);
102
+ if (!command.ok) return false;
103
+ const result = runGreenCloseEvidenceTest(input.repoRoot, input.mainSha, command.args);
104
+ return result.reason === 'completion-command-passed' && result.exitCode === 0;
105
+ }
106
+
107
+ /** Produce one immutable receipt for this map card's current graph run. */
108
+ export function produceBoundaryProof(input: BoundaryProofInput): BoundaryProofResult {
109
+ const hold = (detail: string): BoundaryProofResult => ({ outcome: 'hold', reason: 'boundary-unproven', evidence: [detail] });
110
+ if (![input.cellId, input.mapRunId, input.cardId, input.graphRunId].every((id) => safeId.test(id))
111
+ || !sha.test(input.mainSha) || !input.title.includes('완료 경계 실물:')
112
+ || !isAbsolute(input.stateRoot) || !isAbsolute(input.repoRoot))
113
+ return hold('Boundary identity, absolute state root, or live clause missing');
114
+ const checks = parseBoundaryChecks(input.title);
115
+ const mappingHash = boundaryMappingHash(input.title);
116
+ if (!checks || !mappingHash) return hold('Live boundary has no supported, unambiguous verifier mapping');
117
+ try {
118
+ for (const check of checks) {
119
+ const pass = check.kind === 'test-run' ? checkTestRun(input, check)
120
+ : check.kind === 'graph-run' ? checkGraphRun(input, check) : checkCliJson(input, check);
121
+ if (!pass) return hold(`${check.kind} did not prove the live boundary`);
122
+ }
123
+ const live = /^\s*-?\s*완료 경계 실물:\s*(.+)$/m.exec(input.title)?.[1]?.trim();
124
+ if (!live) return hold('Live boundary line missing');
125
+ const proofRef = `boundary-proofs/${input.cellId}/${input.graphRunId}.json`;
126
+ const destination = resolve(input.stateRoot, proofRef);
127
+ if (existsSync(destination)) return hold('Existing boundary proof cannot be reused');
128
+ mkdirSync(dirname(destination), { recursive: true, mode: 0o700 });
129
+ const stateRoot = realpathSync(input.stateRoot);
130
+ if (!realpathSync(dirname(destination)).startsWith(stateRoot + '/'))
131
+ return hold('Boundary proof directory escapes the state root');
132
+ const temporary = `${destination}.${process.pid}.tmp`;
133
+ const proof = { schema: 'green-close-boundary-proof/v1', producer: 'green-close-boundary-producer/v1',
134
+ cellId: input.cellId, mainSha: input.mainSha, mapRunId: input.mapRunId, cardId: input.cardId,
135
+ graphRunId: input.graphRunId, runId: input.graphRunId, liveBoundary: live,
136
+ mappingHash,
137
+ outcome: 'pass', exitCode: 0, checks: checks.map((check) => ({ kind: check.kind, outcome: 'pass' })) };
138
+ try {
139
+ writeFileSync(temporary, `${JSON.stringify(proof)}\n`, { flag: 'wx', mode: 0o600 });
140
+ linkSync(temporary, destination); // atomic create; never replaces an existing receipt
141
+ } finally { if (existsSync(temporary)) unlinkSync(temporary); }
142
+ return { outcome: 'pass', reason: 'boundary-proof-produced', proofRef,
143
+ evidence: [`${checks.length} live boundary verifier(s) passed for ${input.graphRunId}`] };
144
+ } catch {
145
+ return hold('Live verifier failed or immutable proof could not be written');
146
+ }
147
+ }
@@ -148,7 +148,8 @@ export function checkCompletionEvidence(
148
148
  case 'decision-support': {
149
149
  if (!deps.ledger) { add('못 쟀다: 결정 원장'); break; }
150
150
  try {
151
- if (!deps.ledger.list({ status: 'all' }).some((entry) => entry.id === input.ref)) add('결정 기록');
151
+ // 결정 카드는 그 과제를 `refs` 로 가리킨다 — 기록 id 든 카드 참조든 «그 과제의 기록»이다.
152
+ if (!deps.ledger.list({ status: 'all' }).some((entry) => entry.id === input.ref || entry.refs?.includes(input.ref))) add('결정 기록');
152
153
  } catch { add('못 쟀다: 결정 원장 읽기'); }
153
154
  break;
154
155
  }
@@ -0,0 +1,42 @@
1
+ import { linesOutsideFencedCode, validateGoalDoneEvidenceCommand } from '../self-implement/goal-author.js';
2
+
3
+ const EVIDENCE_LINE = /^(\s*(?:[-*]\s*)?완료 경계 증거 명령\s*:\s*)(.*?)(\s*)$/;
4
+
5
+ /** Remove known result annotations from an evidence command, preserving every other line. */
6
+ export function normalizeEvidenceCommandLines(document: string): { text: string; warnings: string[]; unrecognized: string[] } {
7
+ const warnings: string[] = [];
8
+ const unrecognized: string[] = [];
9
+ const replacements: Array<{ start: number; old: string; next: string }> = [];
10
+ for (const line of linesOutsideFencedCode(document)) {
11
+ const match = EVIDENCE_LINE.exec(line.text);
12
+ if (!match) continue;
13
+ const original = match[2].trim();
14
+ if (!original) continue;
15
+ let candidate = original.replace(/\s*(?:→|->)\s*0\s+fail\s*$/i, '')
16
+ .replace(/\s*·\s*typecheck\s+PASS\s*$/i, '').trim();
17
+ // Some cards have both annotations; peel them in either order.
18
+ candidate = candidate.replace(/\s*(?:→|->)\s*0\s+fail\s*$/i, '')
19
+ .replace(/\s*·\s*typecheck\s+PASS\s*$/i, '').trim();
20
+ if (candidate.startsWith('`') && candidate.endsWith('`') && candidate.length > 2)
21
+ candidate = candidate.slice(1, -1).trim();
22
+ if (candidate === original) {
23
+ if (/[`→]|->|·\s*typecheck\b/i.test(original)) {
24
+ warnings.push(`완료 경계 증거 명령 정규화 불가: ${original}`);
25
+ unrecognized.push(original);
26
+ }
27
+ continue;
28
+ }
29
+ // An unrecognized decoration is never silently converted into a shell command.
30
+ if (!validateGoalDoneEvidenceCommand(candidate).command) {
31
+ warnings.push(`완료 경계 증거 명령 정규화 불가: ${original}`);
32
+ unrecognized.push(original);
33
+ continue;
34
+ }
35
+ replacements.push({ start: line.start, old: line.text, next: `${match[1]}${candidate}${match[3]}` });
36
+ warnings.push(`완료 경계 증거 명령 정규화: ${original} → ${candidate}`);
37
+ }
38
+ let text = document;
39
+ for (const replacement of replacements.reverse())
40
+ text = text.slice(0, replacement.start) + replacement.next + text.slice(replacement.start + replacement.old.length);
41
+ return { text, warnings, unrecognized };
42
+ }
@@ -0,0 +1,43 @@
1
+ import { lstatSync, readFileSync } from 'node:fs';
2
+ import { loadPrivateRedactions, privateRedactionsPath } from '../../scripts/public-export.js';
3
+ import { defaultSshRunner, type SshRunner } from './parent-host.js';
4
+ import { shellQuote } from './task-hand.js';
5
+
6
+ const ALLOWED_HOSTS = new Set(['node-b', 'elangram-wsl', 'host-e-wsl']);
7
+
8
+ /** Give a train host the same private list that release export-check reads on HQ.
9
+ * The list travels only over SSH stdin and is installed atomically at mode 0600.
10
+ * A missing or unreadable list is a failed preflight, never a weaker leak check. */
11
+ export function provisionExportRedactions(
12
+ host: string,
13
+ sourcePath = privateRedactionsPath(),
14
+ ssh: SshRunner = defaultSshRunner,
15
+ ): void {
16
+ if (!ALLOWED_HOSTS.has(host)) throw new Error('export redactions host not allowed');
17
+ let payload: string;
18
+ try {
19
+ const stat = lstatSync(sourcePath);
20
+ if (!stat.isFile() || (stat.mode & 0o077) !== 0 || stat.size === 0 || stat.size > 1_048_576) {
21
+ throw new Error('source is not a private regular file');
22
+ }
23
+ if (!loadPrivateRedactions(sourcePath)?.length) throw new Error('source has no redaction entries');
24
+ payload = readFileSync(sourcePath, 'utf8');
25
+ if (payload.includes('\0')) throw new Error('source contains NUL');
26
+ } catch {
27
+ throw new Error('export redactions source unavailable or invalid');
28
+ }
29
+
30
+ const code = [
31
+ 'const fs=require("node:fs"),path=require("node:path"),crypto=require("node:crypto");',
32
+ // Remote SSH execution has no repository resolver module. Match privateRedactionsPath():
33
+ // ELANOUS_EXPORT_REDACTIONS first, then the remote shell HOME default (OP #40040).
34
+ 'const home=process.env.HOME?.trim(),override=process.env.ELANOUS_EXPORT_REDACTIONS?.trim();',
35
+ 'const file=override||(home?path.join(home,".elanous","export-redactions.tsv"):"");if(!file||!path.isAbsolute(file))process.exit(2);const dir=path.dirname(file);',
36
+ 'const bytes=fs.readFileSync(0);if(!bytes.length||bytes.length>1048576||bytes.includes(0))process.exit(2);',
37
+ 'fs.mkdirSync(dir,{recursive:true,mode:0o700});fs.chmodSync(dir,0o700);',
38
+ 'const temp=file+"."+process.pid+"."+crypto.randomBytes(6).toString("hex")+".tmp";',
39
+ 'try{fs.writeFileSync(temp,bytes,{mode:0o600,flag:"wx"});fs.chmodSync(temp,0o600);fs.renameSync(temp,file)}catch{try{fs.rmSync(temp,{force:true})}catch{};process.exit(3)}',
40
+ ].join('');
41
+ const result = ssh(host, `umask 077; bun -e ${shellQuote(code)}`, 20_000, payload);
42
+ if (result.status !== 0) throw new Error(`export redactions provision failed (ssh rc=${result.status ?? 'unknown'})`);
43
+ }