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
@@ -10,6 +10,28 @@ export interface GoalDocSourceLine {
10
10
  readonly start: number;
11
11
  }
12
12
 
13
+ /** Parse the command on a goal's authored decision-signal Condition line. */
14
+ function authoredSignalCommandFromCondition(condition: string | undefined): string | undefined {
15
+ if (!condition?.trim()) return undefined;
16
+ return condition.trim()
17
+ .replace(/^`([^`]+)`(?=\s|를|$)/, '$1')
18
+ .replace(/\s*를\s*실행한다[.。]?$/, '')
19
+ .replace(/[.。]$/, '')
20
+ .trim();
21
+ }
22
+
23
+ export function authoredSignalCommandFromBody(value: string): string | undefined {
24
+ return authoredSignalCommandFromCondition(value.match(/^\s*- Condition:\s*(.+?)\s*$/m)?.[1]);
25
+ }
26
+
27
+ export function authoredSignalCommandFromGoal(goal: string): string | undefined {
28
+ const lines = goal.split(/\r?\n/);
29
+ const start = lines.findIndex((line) => line.trim() === '## 판정 신호');
30
+ if (start < 0) return undefined;
31
+ const next = lines.findIndex((line, index) => index > start && /^##\s/.test(line));
32
+ return authoredSignalCommandFromBody(lines.slice(start + 1, next < 0 ? lines.length : next).join('\n'));
33
+ }
34
+
13
35
  type GoalDocSectionOptions =
14
36
  | {
15
37
  readonly search: 'exact-trimmed-line';
@@ -1,6 +1,7 @@
1
+ import { createHash } from 'node:crypto';
1
2
  import { readFileSync, renameSync, writeFileSync } from 'node:fs';
2
3
  import { dirname, join } from 'node:path';
3
- import { extractGoalDocSections } from './goal-doc/section.js';
4
+ import { authoredSignalCommandFromBody, extractGoalDocSections } from './goal-doc/section.js';
4
5
 
5
6
  export interface SupervisorGoalFillEvidence {
6
7
  round: number;
@@ -8,37 +9,54 @@ export interface SupervisorGoalFillEvidence {
8
9
  reviewVerdict: 'pass' | 'warn' | 'fail';
9
10
  /** ⭐ 게이트 로그에서 **실제로 읽은** fail 수. 기대값이 아니다(리뷰 must-fix). */
10
11
  observedFail: number;
11
- /** 게이트 로그의 baseline 행 원문 — 독립 검사기가 **이 문자열을 다시 판정**한다. */
12
- baselineLine: string;
12
+ /** 실패 귀속 baseline이 실제 실행됐을 때만 있는 행. PASS에서는 실행하지 않는다. */
13
+ baselineLine?: string;
13
14
  /** ⭐ **원천 그대로** — 독립 검사기가 writer 의 파싱 결과가 아니라 **로그를 직접** 다시 읽는다. */
14
15
  gateLog: string;
16
+ authoredSignal?: { command: string; exitCode: number | null; stdout: string; stderr: string };
15
17
  }
16
18
 
17
19
  export interface SupervisorGoalFillInput {
18
20
  path: string;
19
21
  round: number;
20
- gate: { passed: boolean; log?: string };
22
+ gate: { passed: boolean; log?: string; testStepExecuted?: boolean; scopeReason?: string };
21
23
  review?: { verdict: 'pass' | 'warn' | 'fail' };
24
+ authoredSignal?: SupervisorGoalFillEvidence['authoredSignal'];
22
25
  /** An external checker, deliberately separate from this writer/parser. */
23
26
  independentlyCheck: (document: string, evidence: SupervisorGoalFillEvidence) => Promise<boolean>;
27
+ wiring?: 'wired' | 'unwired';
28
+ observeDeficit?: (observation: SupervisorGoalDeficit) => void;
24
29
  }
25
30
 
26
- export type SupervisorGoalFillResult = 'filled' | 'already-filled' | 'unverifiable' | 'rejected';
31
+ export interface SupervisorGoalDeficit {
32
+ evidenceId: string;
33
+ kind: 'unmeasured' | 'unwired' | 'unverified';
34
+ previousEvidence: string;
35
+ round: number;
36
+ gateLog?: string;
37
+ /** Decision branch, without gate log or goal text. */
38
+ reason?: 'missing-section' | 'missing-invariant-slot' | 'missing-signal-slot' | 'gate-evidence-unverified' | 'review-unavailable' | 'goal-unwired' | 'slot-format' | 'authored-signal-command-mismatch' | 'independent-check-failed';
39
+ /** Safe, bounded detail for a decision branch (for example, the authored test files absent from the measured command). */
40
+ reasonDetail?: string;
41
+ inputSummary?: { gatePassed: boolean; hasGateLog: boolean; hasReview: boolean; invariantSlot: boolean; signalSlot: boolean };
42
+ gateLogRef?: string;
43
+ }
44
+
45
+ export type SupervisorGoalFillResult = 'filled' | 'already-filled' | 'not-applicable' | 'unverifiable' | 'rejected';
27
46
 
28
47
  const UNVERIFIABLE = 'UNVERIFIABLE';
29
48
 
30
49
  interface VerifiedGateEvidence {
31
50
  command: string;
32
51
  observedFail: number;
33
- baselineLine: string;
52
+ baselineLine?: string;
34
53
  }
35
54
 
36
55
  /**
37
56
  * ⛔ **로그가 스스로 모순이면 채우지 않는다.** 종전 판은 ⓐ `[test] PASS` 접두와 명령 모양만 보고
38
- * ⓑ baseline 행이 **아예 없어도 통과**시켰다 ⇒ `[test] PASS bun test x — 0 pass | 5 fail` 같은
39
- * 로그로도 *"fail 0"* 을 채울 수 있었다(리뷰 must-fix).
40
- * ⇒ **fail 수를 실제로 읽고**, baseline 행을 **필수**로 하고, 그 원문을 증거에 실어 독립 검사기가
41
- * 같은 로그를 **다시** 판정할 수 있게 한다.
57
+ * ⓑ PASS 로그의 fail 수를 읽지 않아 `[test] PASS ... 5 fail`도 채울 수 있었다.
58
+ * ⇒ PASS의 실제 0 fail 요약을 필수로 읽는다. 실패 귀속용 baseline은 실행된 경우에만
59
+ * 원문을 검증하며, PASS에서 측정하지 않은 baseline 0건을 만들어 적지 않는다.
42
60
  */
43
61
  function verifiedGateEvidence(gate: SupervisorGoalFillInput['gate']): VerifiedGateEvidence | undefined {
44
62
  if (!gate.passed || !gate.log) return undefined;
@@ -54,11 +72,13 @@ function verifiedGateEvidence(gate: SupervisorGoalFillInput['gate']): VerifiedGa
54
72
  const observedFail = Number(failMatch[1]);
55
73
  if (observedFail !== 0) return undefined; // PASS 라고 적혀 있어도 fail 이 있으면 모순이다
56
74
 
57
- // ⛔ baseline 행은 **필수**다 — 없으면 "깨끗하다" 가 아니라 "안 쟀다" 이다.
75
+ // PASS 자체가 test 0 fail의 측정값이다. 실패 귀속 baseline은 PASS에서 실행되지 않는다.
76
+ // 행이 있다면 실제 값을 검증하고, 잘못된/모순된 행은 조용히 무시하지 않는다.
77
+ const rawBaseline = gate.log.split('\n').find((line) => line.startsWith('[gate-baseline]'));
58
78
  const baseline = gate.log.match(/^\[gate-baseline\]\s+introduced=(\d+),\s*preexisting=(\d+),\s*unknown=(\d+),\s*precondition-unmet=(\d+).*$/m);
59
- if (!baseline) return undefined;
60
- if (baseline.slice(1, 5).some((count) => count !== '0')) return undefined;
61
- return { command, observedFail, baselineLine: baseline[0].trim() };
79
+ if (rawBaseline && !baseline) return undefined;
80
+ if (baseline?.slice(1, 5).some((count) => count !== '0')) return undefined;
81
+ return { command, observedFail, ...(baseline ? { baselineLine: baseline[0].trim() } : {}) };
62
82
  }
63
83
 
64
84
  function section(document: string, heading: string): { start: number; end: number; body: string } | undefined {
@@ -69,17 +89,30 @@ function section(document: string, heading: string): { start: number; end: numbe
69
89
  })[0];
70
90
  }
71
91
 
92
+ /** Accept only explicit Bun test-file lists; never interpret shell syntax or options as file coverage. */
93
+ function testFiles(command: string): string[] | undefined {
94
+ const match = command.trim().match(/^bun\s+test\s+(.+)$/);
95
+ if (!match) return undefined;
96
+ const files = match[1].trim().split(/\s+/);
97
+ if (!files.length || files.some((file) => !/^[A-Za-z0-9_./-]+\.test\.(?:ts|tsx|js|jsx|mjs|cjs)$/.test(file))) return undefined;
98
+ return [...new Set(files)];
99
+ }
100
+
72
101
  /**
73
102
  * ⛔ **두 절은 서로 다른 것을 말한다** — 같은 문자열을 양쪽에 넣으면 무엇도 검증하지 않는다(리뷰 must-fix).
74
103
  * `불변식` = 이 골이 **지켜야 할 조건** · `판정 신호` = 그것을 **어떻게 관측하나**.
75
104
  * ⛔ 그리고 **기대값이 아니라 관측값**을 적는다 — 종전 판은 로그를 안 읽고 `기대 — fail 0` 을 박았다.
76
105
  */
77
106
  function invariantReplacement(evidence: SupervisorGoalFillEvidence): string {
78
- return `- filled-by: supervisor@round-${evidence.round}\n 조건 — ${evidence.command} 가 실패 없이 끝난다\n 이 라운드에서 관측됨 — fail ${evidence.observedFail}\n 근거 — round-${evidence.round} gate [test] PASS ${evidence.command} · ${evidence.baselineLine}`;
107
+ return `- filled-by: supervisor@round-${evidence.round}\n 조건 — ${evidence.command} 가 실패 없이 끝난다\n 이 라운드에서 관측됨 — fail ${evidence.observedFail}\n 근거 — round-${evidence.round} gate [test] PASS ${evidence.command} · ${evidence.baselineLine ?? 'baseline not run (test PASS)'}`;
79
108
  }
80
109
 
81
110
  function signalReplacement(evidence: SupervisorGoalFillEvidence): string {
82
- return `- filled-by: supervisor@round-${evidence.round}\n 관측 — \`${evidence.command}\` 요약 줄의 fail 수\n 이번 라운드 관측값 — fail ${evidence.observedFail}\n 근거 — round-${evidence.round} review ${evidence.reviewVerdict} · ${evidence.baselineLine}`;
111
+ if (evidence.authoredSignal) {
112
+ const output = `${evidence.authoredSignal.stdout}\n${evidence.authoredSignal.stderr}`.trim().slice(-1200) || '(출력 없음)';
113
+ return `- filled-by: supervisor@round-${evidence.round}\n 관측 — \`${evidence.authoredSignal.command}\` 실행 결과\n 이번 라운드 관측값 — exit ${evidence.authoredSignal.exitCode}\n 원문 출력 — ${output.replace(/\r?\n/g, ' ⏎ ')}\n gate 검증 — ${evidence.command} · fail ${evidence.observedFail} · ${evidence.baselineLine ?? 'baseline not run (test PASS)'}\n 근거 — authored signal command executed in this run · review ${evidence.reviewVerdict}`;
114
+ }
115
+ return `- filled-by: supervisor@round-${evidence.round}\n 관측 — \`${evidence.command}\` 요약 줄의 fail 수\n 이번 라운드 관측값 — fail ${evidence.observedFail}\n 근거 — round-${evidence.round} review ${evidence.reviewVerdict} · ${evidence.baselineLine ?? 'baseline not run (test PASS)'}`;
83
116
  }
84
117
 
85
118
  function replaceUnverifiableSlot(body: string, filled: string): string | undefined {
@@ -88,7 +121,7 @@ function replaceUnverifiableSlot(body: string, filled: string): string | undefin
88
121
  }
89
122
 
90
123
  /**
91
- * Fill only the two empty authored slots. Gate evidence is accepted only when
124
+ * Fill an empty invariant and either an empty signal or append an observation to an authored signal. Gate evidence is accepted only when
92
125
  * its logged test command and PASS status agree; baseline contradictions keep
93
126
  * the original document queued and byte-identical.
94
127
  */
@@ -96,27 +129,77 @@ export async function fillUnverifiableGoalSlots(input: SupervisorGoalFillInput):
96
129
  const original = readFileSync(input.path, 'utf8');
97
130
  const invariant = section(original, '## 불변식');
98
131
  const signals = section(original, '## 판정 신호');
99
- if (!invariant || !signals) return 'unverifiable';
100
- const invariantNeedsFill = invariant.body.includes(UNVERIFIABLE);
101
- const signalsNeedFill = signals.body.includes(UNVERIFIABLE);
102
- if (!invariantNeedsFill && !signalsNeedFill) return 'already-filled';
103
-
132
+ const invariantSlot = Boolean(invariant && /^- UNVERIFIABLE(?:[ \t]*:[^\r\n]*)?[ \t]*$/m.test(invariant.body));
133
+ const signalSlot = Boolean(signals && /^- UNVERIFIABLE(?:[ \t]*:[^\r\n]*)?[ \t]*$/m.test(signals.body));
104
134
  const gateEvidence = verifiedGateEvidence(input.gate);
105
- if (!invariantNeedsFill || !signalsNeedFill || !gateEvidence || !input.review) return 'unverifiable';
135
+ const deficit = (reason: NonNullable<SupervisorGoalDeficit['reason']>): void => input.observeDeficit?.({
136
+ evidenceId: createHash('sha256').update(JSON.stringify([input.path, input.round, original])).digest('hex').slice(0, 16),
137
+ kind: !gateEvidence || !input.review ? 'unmeasured' : input.wiring === 'unwired' ? 'unwired' : 'unverified',
138
+ previousEvidence: original,
139
+ round: input.round,
140
+ ...(input.gate.log !== undefined ? { gateLog: input.gate.log } : {}),
141
+ reason,
142
+ inputSummary: { gatePassed: input.gate.passed, hasGateLog: Boolean(input.gate.log), hasReview: Boolean(input.review), invariantSlot, signalSlot },
143
+ ...(input.gate.log ? { gateLogRef: `sha256:${createHash('sha256').update(input.gate.log).digest('hex').slice(0, 16)}` } : {}),
144
+ });
145
+ if (!invariant || !signals) {
146
+ // A sectionless goal has no slot the supervisor can measure or repair.
147
+ // Report a deficit only when a present section contains an actual slot.
148
+ if (invariantSlot || signalSlot) deficit('missing-section');
149
+ return 'unverifiable';
150
+ }
151
+ if (!invariantSlot && !signalSlot && !invariant.body.includes(UNVERIFIABLE) && !signals.body.includes(UNVERIFIABLE)
152
+ && input.wiring !== 'unwired') return 'already-filled';
153
+ if (!invariantSlot) { deficit('missing-invariant-slot'); return 'unverifiable'; }
154
+ if (!signalSlot && !signals.body.trim()) { deficit('missing-signal-slot'); return 'unverifiable'; }
155
+ // A docs-only PASS has no test measurement to put into the authored slots.
156
+ // Trust the gate's structured scope, never a free-text log line, and leave the goal unchanged.
157
+ if (input.gate.passed && input.gate.testStepExecuted === false && input.gate.scopeReason === 'docs-only'
158
+ && input.wiring !== 'unwired') {
159
+ return 'not-applicable';
160
+ }
161
+ if (!gateEvidence) { deficit('gate-evidence-unverified'); return 'unverifiable'; }
162
+ if (!input.review) { deficit('review-unavailable'); return 'unverifiable'; }
163
+ if (input.wiring === 'unwired') { deficit('goal-unwired'); return 'unverifiable'; }
164
+ // The authored completion signal must name the test we actually measured.
165
+ if (!signalSlot) {
166
+ const authoredCommand = authoredSignalCommandFromBody(signals.body);
167
+ const authoredFiles = authoredCommand ? testFiles(authoredCommand) : undefined;
168
+ const measuredFiles = testFiles(gateEvidence.command);
169
+ const missingFiles = authoredFiles && measuredFiles ? authoredFiles.filter((file) => !measuredFiles.includes(file)) : [];
170
+ const signalRun = input.authoredSignal;
171
+ const signalMeasured = authoredCommand && signalRun?.command === authoredCommand && signalRun.exitCode === 0;
172
+ if (!signalMeasured) {
173
+ const observation: SupervisorGoalDeficit = {
174
+ evidenceId: createHash('sha256').update(JSON.stringify([input.path, input.round, original])).digest('hex').slice(0, 16),
175
+ kind: 'unverified', previousEvidence: original, round: input.round,
176
+ ...(input.gate.log !== undefined ? { gateLog: input.gate.log } : {}),
177
+ reason: 'authored-signal-command-mismatch',
178
+ reasonDetail: missingFiles.length ? `authored test file(s) absent from passing gate command: ${missingFiles.join(', ')}`
179
+ : 'authored command has no matching successful execution evidence',
180
+ inputSummary: { gatePassed: input.gate.passed, hasGateLog: Boolean(input.gate.log), hasReview: Boolean(input.review), invariantSlot, signalSlot },
181
+ ...(input.gate.log ? { gateLogRef: `sha256:${createHash('sha256').update(input.gate.log).digest('hex').slice(0, 16)}` } : {}),
182
+ };
183
+ input.observeDeficit?.(observation);
184
+ return 'unverifiable';
185
+ }
186
+ }
106
187
 
107
188
  const evidence: SupervisorGoalFillEvidence = {
108
189
  round: input.round,
109
190
  command: gateEvidence.command,
110
191
  reviewVerdict: input.review.verdict,
111
192
  observedFail: gateEvidence.observedFail,
112
- baselineLine: gateEvidence.baselineLine,
193
+ ...(gateEvidence.baselineLine ? { baselineLine: gateEvidence.baselineLine } : {}),
113
194
  gateLog: input.gate.log ?? '',
195
+ ...(input.authoredSignal ? { authoredSignal: input.authoredSignal } : {}),
114
196
  };
115
197
  const invariantBody = replaceUnverifiableSlot(invariant.body, invariantReplacement(evidence));
116
- const signalBody = replaceUnverifiableSlot(signals.body, signalReplacement(evidence));
117
- if (invariantBody === undefined || signalBody === undefined) return 'unverifiable';
198
+ const signalBody = signalSlot ? replaceUnverifiableSlot(signals.body, signalReplacement(evidence))
199
+ : `${signals.body.replace(/\s*$/, '')}\n${signalReplacement(evidence)}\n`;
200
+ if (invariantBody === undefined || signalBody === undefined) { deficit('slot-format'); return 'unverifiable'; }
118
201
  const candidate = `${original.slice(0, invariant.start)}## 불변식${invariantBody}${original.slice(invariant.end, signals.start)}## 판정 신호${signalBody}${original.slice(signals.end)}`;
119
- if (!await input.independentlyCheck(candidate, evidence)) return 'rejected';
202
+ if (!await input.independentlyCheck(candidate, evidence)) { deficit('independent-check-failed'); return 'rejected'; }
120
203
 
121
204
  const temporary = join(dirname(input.path), `.${Math.random().toString(16).slice(2)}.goal-fill.tmp`);
122
205
  try {
@@ -4,10 +4,42 @@ import ts from 'typescript';
4
4
 
5
5
  const IMPORTER_TEST_DISPLAY_LIMIT = 20;
6
6
 
7
+ /** 런타임 간선 클래스 — 시험이 소스를 **실제 프로세스**·`git`·파일 상태로 건드리는 경우다.
8
+ * 임포트 그래프에는 이 간선이 «없다»: `import` 문이 없으니 `testsBySource` 에도 안 잡힌다. */
9
+ export type RuntimeEdgeKind = 'spawn' | 'git' | 'file-state';
10
+
11
+ /** 시험 1건이 만든 런타임 간선 1건. `source` 가 `null` 이면 그 명령은 파일을 지목하지 않는다(`git`). */
12
+ export interface RuntimeEdge {
13
+ readonly test: string;
14
+ readonly kind: RuntimeEdgeKind;
15
+ readonly source: string | null;
16
+ }
17
+
18
+ /** 런타임 간선의 **영향 크기** — 임포트 그래프가 표현할 수 없는 간선이 변경 감시에 «얼마나 더하는가».
19
+ *
20
+ * ⛔ #28322 착지분(BFS 분포·사람용 표)을 재구현하지 않는다 — 여기는 **수**만 낸다. */
21
+ export interface RuntimeEdgeImpact {
22
+ /** 변경 소스에 «임포트가 아니라 런타임으로» 닿는 (시험, 소스) 짝의 수 — 임포트 그래프 위에 더해지는 크기. */
23
+ readonly pairs: number;
24
+ /** 클래스별 크기 — 그 클래스의 런타임 간선**만**이 변경 소스에 닿는 시험 수. */
25
+ readonly byKind: Readonly<Record<RuntimeEdgeKind, number>>;
26
+ /** 손으로 관리하는 착지 열차 spawn-lane 목록(`GATE_SPAWN_LANE_FILES`)이 **빠뜨린** 실측 시험들.
27
+ * ⛔ 손 목록은 구조적으로 드리프트한다 — 그 드리프트 «크기»를 재는 자리다(고치지는 않는다). */
28
+ readonly unlistedSpawnLaneTests: readonly string[];
29
+ /** 실재 소스로 풀리지 않은 런타임 경로 리터럴 수 — `unresolvedRelativeSpecifiers` 와 «같은» 정직성 계수. */
30
+ readonly unresolvedRuntimeTargets: number;
31
+ /** 「쟀다」표 — `runtimeEdges` 가 없는 색인은 «못 잰 것»이므로 `measured: false` 다(`pairs: 0` 과 섞지 않는다). */
32
+ readonly measured: boolean;
33
+ }
34
+
7
35
  export interface ImporterTestIndex {
8
36
  readonly testsBySource: ReadonlyMap<string, readonly string[]>;
9
37
  readonly testPaths?: readonly string[];
10
38
  readonly unresolvedRelativeSpecifiers: number;
39
+ /** 측정된 런타임 간선(선택) — 없으면 「안 쟀다」이지 「0건」이 아니다(`measureRuntimeEdgeImpact` 참조). */
40
+ readonly runtimeEdges?: readonly RuntimeEdge[];
41
+ /** 소스로 풀리지 않은 런타임 경로 리터럴 수(선택 · 위와 같은 이유로 optional). */
42
+ readonly unresolvedRuntimeTargets?: number;
11
43
  }
12
44
 
13
45
  // ⛔⭐ `\S+` 를 쓰지 않는다(무인 리뷰 should-fix) — 공백이 든 «유효한» 추적 경로가 «조용히» 빠진다.
@@ -80,10 +112,143 @@ export function sourceCandidates(testPath: string, specifier: string): readonly
80
112
  ];
81
113
  }
82
114
 
115
+ /** 실물 자식 프로세스·파일 상태를 만드는 «런타임 모듈 임포트»의 호출 이름 → 클래스. ⛔⭐ 호출 이름의
116
+ * 마지막 조각만 보지 않는다(무인 리뷰 must-fix) — 수신 객체·맨살 callee 의 **임포트 바인딩** 출처를
117
+ * 확인한다(`runtimeEdgeImports`·`declaredRuntimeEdgeKind`). 그래서 `/re/.exec(str)`·`db.exec(...)`·
118
+ * `fsMock.readFile(...)` 같은 일반 호출은 이 표와 «이름이 같아도» 간선이 되지 않는다. */
119
+ const RUNTIME_EDGE_CALLS: Readonly<Record<string, RuntimeEdgeKind>> = {
120
+ spawn: 'spawn', spawnSync: 'spawn', exec: 'spawn', execSync: 'spawn', execFile: 'spawn', execFileSync: 'spawn',
121
+ readFile: 'file-state', readFileSync: 'file-state', writeFile: 'file-state', writeFileSync: 'file-state',
122
+ appendFileSync: 'file-state', copyFileSync: 'file-state', cpSync: 'file-state', renameSync: 'file-state',
123
+ existsSync: 'file-state', statSync: 'file-state', lstatSync: 'file-state', readdir: 'file-state',
124
+ readdirSync: 'file-state', mkdirSync: 'file-state', rmSync: 'file-state', unlinkSync: 'file-state',
125
+ accessSync: 'file-state', openSync: 'file-state', chmodSync: 'file-state', truncateSync: 'file-state',
126
+ readlinkSync: 'file-state', realpathSync: 'file-state',
127
+ };
128
+
129
+ /** URL·절대경로는 저장소 경로가 아니다 — 후보 해석에도, 「못 풀었다」에도 넣지 않는다. */
130
+ function isRepoRelativeLiteral(literal: string): boolean {
131
+ if (!literal.includes('/')) return false;
132
+ if (literal.startsWith('/')) return false;
133
+ return !/^[a-zA-Z][a-zA-Z0-9+.-]*:\/\//.test(literal);
134
+ }
135
+
136
+ /** 런타임 리터럴 → 실재 소스. 루트 기준 리터럴(`bin/elanous.mjs`)은 «상대 지정자»가 아니므로 `''` 를 기준점으로
137
+ * 쓴다 — 그래야 확장자·쿼리 규칙이 임포트 해석(`sourceCandidates`)과 **갈리지 않는다**. */
138
+ function resolveRuntimeTarget(testPath: string, literal: string, sources: ReadonlySet<string>): string | null {
139
+ if (!isRepoRelativeLiteral(literal)) return null;
140
+ const candidates = literal.startsWith('.')
141
+ ? sourceCandidates(testPath, literal)
142
+ : [normalize(stripModuleQuery(literal)), ...sourceCandidates('', literal)];
143
+ return candidates.find((candidate) => sources.has(candidate)) ?? null;
144
+ }
145
+
146
+ interface RuntimeEdgeCall { readonly kind: RuntimeEdgeKind; readonly literals: readonly string[] }
147
+
148
+ /** 런타임 간선을 만드는 모듈 — `node:` 접두사는 벗겨 비교한다. `Bun` 은 전역이라 임포트가 없고, 수신
149
+ * 객체 이름으로만 허용한다(`declaredRuntimeEdgeKind`). */
150
+ const RUNTIME_EDGE_MODULES: ReadonlySet<string> = new Set(['child_process', 'fs', 'fs/promises', 'bun']);
151
+
152
+ function isRuntimeEdgeModule(specifier: string): boolean {
153
+ return RUNTIME_EDGE_MODULES.has(specifier.startsWith('node:') ? specifier.slice('node:'.length) : specifier);
154
+ }
155
+
156
+ /** 시험 파일의 런타임 모듈 임포트 바인딩 — 로컬 이름 → 임포트된 이름(네임스페이스·기본 임포트는 `'*'`).
157
+ * ⛔⭐ 임포트 출처를 알 수 없는 수신 객체는 간선을 만들지 «않는다»(무인 리뷰 must-fix) — `db.exec(...)`·
158
+ * `fsMock.readFile(...)` 같은 호출 이름이 spawn·file-state 간선으로 승격되던 오탐을 고치는 자리다. */
159
+ function runtimeEdgeImports(sourceFile: ts.SourceFile): ReadonlyMap<string, string> {
160
+ const bindings = new Map<string, string>();
161
+ for (const statement of sourceFile.statements) {
162
+ if (!ts.isImportDeclaration(statement) || !statement.moduleSpecifier || !ts.isStringLiteral(statement.moduleSpecifier)) continue;
163
+ if (!isRuntimeEdgeModule(statement.moduleSpecifier.text)) continue;
164
+ const clause = statement.importClause;
165
+ if (!clause) continue;
166
+ if (clause.name) bindings.set(clause.name.text, '*');
167
+ const named = clause.namedBindings;
168
+ if (!named) continue;
169
+ if (ts.isNamespaceImport(named)) bindings.set(named.name.text, '*');
170
+ else for (const element of named.elements) {
171
+ if (element.isTypeOnly) continue;
172
+ bindings.set(element.name.text, element.propertyName?.text ?? element.name.text);
173
+ }
174
+ }
175
+ return bindings;
176
+ }
177
+
178
+ /** 수신 객체·맨살 callee 가 런타임 모듈에서 왔는지 임포트 바인딩으로 확인하고, 그럴 때만 클래스를 낸다.
179
+ * - `obj.method`: 수신 객체가 런타임 모듈 바인딩이거나 전역 `Bun` 일 때만.
180
+ * - 맨살 `fn(...)`: 런타임 모듈의 named import 이고 «임포트된 이름»이 표에 있을 때만(`as` 별칭도 잡는다).
181
+ * - 정규식 리터럴(`/re/.exec`)·출처를 알 수 없는 수신 객체는 `undefined` — 간선이 아니다. */
182
+ function declaredRuntimeEdgeKind(callee: ts.Expression, imports: ReadonlyMap<string, string>): RuntimeEdgeKind | undefined {
183
+ if (ts.isPropertyAccessExpression(callee)) {
184
+ const receiver = callee.expression;
185
+ if (!ts.isIdentifier(receiver)) return undefined;
186
+ if (receiver.text !== 'Bun' && !imports.has(receiver.text)) return undefined;
187
+ return RUNTIME_EDGE_CALLS[callee.name.text];
188
+ }
189
+ if (ts.isIdentifier(callee)) {
190
+ const imported = imports.get(callee.text);
191
+ if (imported === undefined || imported === '*') return undefined;
192
+ return RUNTIME_EDGE_CALLS[imported];
193
+ }
194
+ return undefined;
195
+ }
196
+
197
+ /** 시험 소스에서 런타임 호출을 찾아 «무엇을 지목했는지»까지 모은다. */
198
+ function runtimeEdgeCalls(text: string, path: string): RuntimeEdgeCall[] {
199
+ const sourceFile = ts.createSourceFile(path, text, ts.ScriptTarget.Latest, false);
200
+ const calls: RuntimeEdgeCall[] = [];
201
+ const literalsOf = (node: ts.Node, out: string[]): void => {
202
+ if (ts.isStringLiteral(node) || ts.isNoSubstitutionTemplateLiteral(node)) out.push(node.text);
203
+ else ts.forEachChild(node, (child) => literalsOf(child, out));
204
+ };
205
+ const runtimeImports = runtimeEdgeImports(sourceFile);
206
+ const visit = (node: ts.Node): void => {
207
+ if (ts.isCallExpression(node)) {
208
+ const declared = declaredRuntimeEdgeKind(node.expression, runtimeImports);
209
+ if (declared) {
210
+ const literals: string[] = [];
211
+ for (const argument of node.arguments) literalsOf(argument, literals);
212
+ // `git` 은 파일을 «지목하지 않는» 별도 클래스다(`spawnSync('git', ['diff', …])` · `execSync('git …')`).
213
+ const command = literals[0] ?? '';
214
+ calls.push({ kind: /^git\b/.test(command) ? 'git' : declared, literals });
215
+ }
216
+ }
217
+ ts.forEachChild(node, visit);
218
+ };
219
+ visit(sourceFile);
220
+ return calls;
221
+ }
222
+
223
+ /** 시험 1건의 런타임 간선과 «못 푼» 경로 리터럴. 지목한 소스가 하나도 없으면 `source: null` 간선 하나를 남긴다
224
+ * — 파일을 안 지목해도 실물 프로세스를 띄운 사실은 사라지지 않는다. */
225
+ function runtimeEdgesOfTest(text: string, testPath: string, sources: ReadonlySet<string>): { edges: RuntimeEdge[]; unresolved: readonly string[] } {
226
+ const edges: RuntimeEdge[] = [];
227
+ const unresolved: string[] = [];
228
+ for (const call of runtimeEdgeCalls(text, testPath)) {
229
+ const targets = call.literals.map((literal) => resolveRuntimeTarget(testPath, literal, sources));
230
+ call.literals.forEach((literal, position) => {
231
+ if (targets[position] !== null) return;
232
+ if (!isRepoRelativeLiteral(literal) || !isSourceLikeSpecifier(literal)) return;
233
+ // `.json`·`.css` 같은 자원은 «런타임 대상»이지 못 푼 소스가 아니다(`isSourceLikeSpecifier` 가 이미 거른다).
234
+ if (!unresolved.includes(literal)) unresolved.push(literal);
235
+ });
236
+ const resolved = targets.filter((target): target is string => target !== null);
237
+ for (const source of resolved.length > 0 ? resolved : [null]) edges.push({ test: testPath, kind: call.kind, source });
238
+ }
239
+ return { edges, unresolved };
240
+ }
241
+
242
+ /** 경로 정렬 — 기존 표시 순서(`localeCompare` 수치)와 같은 자를 쓴다. */
243
+ function comparePaths(left: string, right: string): number { return left.localeCompare(right, undefined, { numeric: true }); }
244
+
83
245
  export function buildImporterTestIndex(cwd: string, testPaths: readonly string[], sourcePaths: readonly string[]): ImporterTestIndex | null {
84
246
  const sources = new Set(sourcePaths);
85
247
  const testsBySource = new Map<string, string[]>();
86
248
  let unresolvedRelativeSpecifiers = 0;
249
+ const runtimeEdges: RuntimeEdge[] = [];
250
+ const seenRuntimeEdges = new Set<string>();
251
+ const unresolvedRuntimeTargets = new Set<string>();
87
252
  for (const testPath of testPaths) {
88
253
  if (!TEST_PATH_RE.test(testPath)) continue;
89
254
  let text: string;
@@ -107,8 +272,16 @@ export function buildImporterTestIndex(cwd: string, testPaths: readonly string[]
107
272
  if (!importers.includes(testPath)) importers.push(testPath);
108
273
  testsBySource.set(source, importers);
109
274
  }
275
+ const runtime = runtimeEdgesOfTest(text, testPath, sources);
276
+ for (const edge of runtime.edges) {
277
+ const key = `${edge.test}\u0000${edge.kind}\u0000${edge.source ?? ''}`;
278
+ if (seenRuntimeEdges.has(key)) continue;
279
+ seenRuntimeEdges.add(key);
280
+ runtimeEdges.push(edge);
281
+ }
282
+ for (const literal of runtime.unresolved) unresolvedRuntimeTargets.add(`${testPath}\u0000${literal}`);
110
283
  }
111
- return { testsBySource, testPaths, unresolvedRelativeSpecifiers };
284
+ return { testsBySource, testPaths, unresolvedRelativeSpecifiers, runtimeEdges, unresolvedRuntimeTargets: unresolvedRuntimeTargets.size };
112
285
  }
113
286
 
114
287
  export function importerTestsNotInRunSet(
@@ -117,7 +290,47 @@ export function importerTestsNotInRunSet(
117
290
  runSet: readonly string[],
118
291
  ): { readonly total: number; readonly files: readonly string[]; readonly truncated: boolean; readonly unresolvedRelativeSpecifiers: number } {
119
292
  const names = [...new Set(changed.flatMap((source) => index.testsBySource.get(source) ?? []).filter((test) => !runSet.includes(test)))]
120
- .sort((left, right) => left.localeCompare(right, undefined, { numeric: true }));
293
+ .sort(comparePaths);
121
294
  const files = names.slice(0, IMPORTER_TEST_DISPLAY_LIMIT);
122
295
  return { total: names.length, files, truncated: names.length > files.length, unresolvedRelativeSpecifiers: index.unresolvedRelativeSpecifiers };
123
296
  }
297
+
298
+ /** ⭐ 런타임 간선의 **영향 크기 실측** — 임포트 그래프가 «표현할 수 없는» 간선이 변경 감시에 얼마나 더하는가.
299
+ *
300
+ * ⛔ #28322 착지분(BFS 분포·사람용 표 렌더링)은 여기서 재구현하지 않는다 — 이 함수는 **수**만 낸다.
301
+ * ⛔ «색인이 안 실렸다»와 «런타임 간선 0건»은 다른 값이다: `runtimeEdges` 가 없는 색인은 `pairs: 0` 이
302
+ * 아니라 **못 잰 것**이므로 `measured: false` 로 드러낸다.
303
+ *
304
+ * `handListed` 는 «손으로 관리하는 목록»이다(착지 열차의 `GATE_SPAWN_LANE_FILES`). 그 목록이 빠뜨린
305
+ * 실측 시험 수가 곧 착지 열차 소비자의 영향 크기다.
306
+ */
307
+ export function measureRuntimeEdgeImpact(
308
+ index: ImporterTestIndex,
309
+ changed: readonly string[],
310
+ opts: { readonly handListed?: readonly string[] } = {},
311
+ ): RuntimeEdgeImpact {
312
+ const edges = index.runtimeEdges;
313
+ const changedSet = new Set(changed);
314
+ const pairs = new Set<string>();
315
+ const testsByKind: Record<RuntimeEdgeKind, Set<string>> = { spawn: new Set(), git: new Set(), 'file-state': new Set() };
316
+ for (const edge of edges ?? []) {
317
+ if (edge.source === null || !changedSet.has(edge.source)) continue;
318
+ // 이미 «임포트» 간선이 있는 짝은 런타임 간선의 몫이 아니다 — 같은 커버리지를 두 번 세지 않는다.
319
+ if ((index.testsBySource.get(edge.source) ?? []).includes(edge.test)) continue;
320
+ pairs.add(`${edge.test}\u0000${edge.source}`);
321
+ testsByKind[edge.kind].add(edge.test);
322
+ }
323
+ const handListed = new Set(opts.handListed ?? []);
324
+ const unlistedSpawnLaneTests = [...new Set((edges ?? [])
325
+ .filter((edge) => edge.kind === 'spawn' || edge.kind === 'git')
326
+ .map((edge) => edge.test))]
327
+ .filter((test) => !handListed.has(test))
328
+ .sort(comparePaths);
329
+ return {
330
+ measured: edges !== undefined,
331
+ pairs: pairs.size,
332
+ byKind: { spawn: testsByKind.spawn.size, git: testsByKind.git.size, 'file-state': testsByKind['file-state'].size },
333
+ unlistedSpawnLaneTests,
334
+ unresolvedRuntimeTargets: index.unresolvedRuntimeTargets ?? 0,
335
+ };
336
+ }