elanous 0.2.38 → 0.2.40

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 (615) 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/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_buildManifest.js +1 -1
  4. package/apps/pwa/out/_next/static/chunks/{7954.4f7a8832663ee979.js → 1060.014f1f01a17aec26.js} +1 -1
  5. package/apps/pwa/out/_next/static/chunks/{8911.bf5e712acb25fb6c.js → 1281.d81877e35b9068f4.js} +1 -1
  6. package/apps/pwa/out/_next/static/chunks/{2104.70e086d5174a4736.js → 1350.59f40e39e02d91b1.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +1 -0
  8. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +286 -0
  10. package/apps/pwa/out/_next/static/chunks/1537-6bb97b5214928ea9.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +149 -0
  12. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +1 -0
  13. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +90 -0
  14. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +104 -0
  15. package/apps/pwa/out/_next/static/chunks/2047.8f23e210995d4548.js +2 -0
  16. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/{1632.7d87f998e714bede.js → 2066.a77257c8c350770a.js} +1 -1
  18. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/{8019.21ca554a821dad01.js → 2177.df8547f9d7215c4e.js} +3 -3
  20. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/{3528.e4b8ab70d339f965.js → 2226.2cf61ec781827219.js} +2 -2
  22. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +1 -0
  23. package/apps/pwa/out/_next/static/chunks/{6493.27ad77de7aac7966.js → 2499.02fbfd18126c10c0.js} +1 -1
  24. package/apps/pwa/out/_next/static/chunks/{7628.6b16863ac3972333.js → 2522.f2766b76d22c8bdf.js} +1 -1
  25. package/apps/pwa/out/_next/static/chunks/{3086.fb14b60ce98b53d3.js → 2566.beaffc3a5e1fcd2e.js} +1 -1
  26. package/apps/pwa/out/_next/static/chunks/{9299.24e2a7d9b6d1f91b.js → 261.0d471e8aded799f3.js} +3 -3
  27. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +27 -0
  30. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +1 -0
  32. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +1 -0
  33. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +1 -0
  34. package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +1 -0
  35. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +1 -0
  36. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +1 -0
  37. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +1 -0
  38. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +1 -0
  39. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/{7524.ce973525d30b3d52.js → 3330.7443183b7e6fdbdf.js} +1 -1
  41. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +1 -0
  42. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/{3124-561f7f037943cde2.js → 3746-f80a78f220bf37b5.js} +1 -1
  44. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +24 -0
  45. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +77 -0
  46. package/apps/pwa/out/_next/static/chunks/{bb6987f9.3647e1a23b0e3217.js → 3b355b3d.6f73c98bf6f9c749.js} +1 -1
  47. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +36 -0
  48. package/apps/pwa/out/_next/static/chunks/{8994d93e.33ba491f95345fc2.js → 409c787b.e48c5bec8ec10456.js} +1 -1
  49. package/apps/pwa/out/_next/static/chunks/{5041-5aada92ca215ffdd.js → 413-24c8284bda08241d.js} +1 -1
  50. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +1 -0
  51. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +287 -0
  52. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4351.0f37a6db2b34d50b.js +1 -0
  55. package/apps/pwa/out/_next/static/chunks/{5638.107314dc479e2f37.js → 470.51a72a2348306455.js} +2 -2
  56. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +1 -0
  57. package/apps/pwa/out/_next/static/chunks/{8487.291666583bebe640.js → 4769.9fd582071301f382.js} +1 -1
  58. package/apps/pwa/out/_next/static/chunks/{8509.3a54d4e61893d7cb.js → 483.725e4a61be922788.js} +1 -1
  59. package/apps/pwa/out/_next/static/chunks/{9fe1b809.738da85c8b17e3fb.js → 4864a2ca.1c1c280a7772c5e5.js} +1 -1
  60. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +1 -0
  61. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +1 -0
  62. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +74 -0
  63. package/apps/pwa/out/_next/static/chunks/{8879.ac06755bcf3e44a1.js → 5383.bdfa5d886e39a826.js} +1 -1
  64. package/apps/pwa/out/_next/static/chunks/{6142.913b44e260a3f925.js → 5436.fdf6fa8ae3e9588d.js} +1 -1
  65. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +8 -0
  70. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +62 -0
  72. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +1 -0
  73. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +1 -0
  74. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +1 -0
  75. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +94 -0
  76. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{7161-8f22db3ec5ed005e.js → 6051-0ae955eedb10adb9.js} +3 -3
  78. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/{3291.f6c1005387d514bd.js → 6257.c0037b8949239f5e.js} +2 -2
  80. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +1 -0
  82. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +1 -0
  83. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +32 -0
  85. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/{5203.51e5d8b5f1dcfe53.js → 6749.0744ce6eb08d40e9.js} +3 -3
  87. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/{1938.0e6c60ee91c4d7f5.js → 6908.06008c67f6380ea9.js} +2 -2
  90. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +1 -0
  91. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +1 -0
  92. package/apps/pwa/out/_next/static/chunks/{de8b930d.d94c0f42acf807fc.js → 6cc1d1d6.9a98dd4622f1afc6.js} +1 -1
  93. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7219-15bdd9a80661af8e.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +93 -0
  96. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +1 -0
  98. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +24 -0
  100. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +1 -0
  101. package/apps/pwa/out/_next/static/chunks/7611.85f045bf232053ac.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +1 -0
  103. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +1 -0
  105. package/apps/pwa/out/_next/static/chunks/8099.1cccf31c1baa7e1c.js +1 -0
  106. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +1 -0
  107. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/{1026-44010f405704050c.js → 8272-025653884f9645d2.js} +1 -1
  109. package/apps/pwa/out/_next/static/chunks/{5307.d7328020227880c2.js → 8357.1aaa713b052a78b1.js} +4 -4
  110. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{4199-f7c6eb40cd0322f8.js → 8639-92c11d069792429e.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/8d173e38.18a2f7b4e1848bdb.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +41 -0
  115. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9175.2de5209a5ce6f68a.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9184.45afbf44fec87574.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{eaad0cba.771200940c529df7.js → 9189505a.980427ac048c8c60.js} +1 -1
  119. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +1 -0
  122. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +79 -0
  123. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +1 -0
  124. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/botlab/{page-866aac5ff226a7f3.js → page-ba957ff875a026a0.js} +1 -1
  128. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/live-run/page-83d27757e2b8060a.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +1 -0
  147. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/term/page-139d722de1dcd6c1.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +1 -0
  170. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/{b7478fef.5917716286213fcc.js → b84cad00.594027ebe0531fe2.js} +1 -1
  175. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/{b7459770.6539b11860eb8a9c.js → ca3702f8.2913182e73889fa2.js} +7 -7
  177. package/apps/pwa/out/_next/static/chunks/{3f0de3de-2340c532c00395db.js → d5d3cefc-373c4eb722ed848b.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{89d6c04f-6b8ab341748e468a.js → d8de0de2-dd0f4ac8e5ab1832.js} +1 -1
  179. package/apps/pwa/out/_next/static/chunks/{framework-4b12a946f352cee2.js → framework-002b472a66935d31.js} +1 -1
  180. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +1 -0
  185. package/apps/pwa/out/approvals/index.html +1 -1
  186. package/apps/pwa/out/approvals/index.txt +22 -22
  187. package/apps/pwa/out/autopilot/index.html +1 -1
  188. package/apps/pwa/out/autopilot/index.txt +22 -22
  189. package/apps/pwa/out/board/index.html +1 -1
  190. package/apps/pwa/out/board/index.txt +22 -22
  191. package/apps/pwa/out/botlab/index.html +1 -1
  192. package/apps/pwa/out/botlab/index.txt +21 -21
  193. package/apps/pwa/out/bots/index.html +1 -1
  194. package/apps/pwa/out/bots/index.txt +21 -21
  195. package/apps/pwa/out/ceo/index.html +1 -1
  196. package/apps/pwa/out/ceo/index.txt +22 -22
  197. package/apps/pwa/out/chat/index.html +1 -1
  198. package/apps/pwa/out/chat/index.txt +21 -21
  199. package/apps/pwa/out/consult/index.html +1 -1
  200. package/apps/pwa/out/consult/index.txt +22 -22
  201. package/apps/pwa/out/control/index.html +1 -1
  202. package/apps/pwa/out/control/index.txt +22 -22
  203. package/apps/pwa/out/decisions/index.html +1 -1
  204. package/apps/pwa/out/decisions/index.txt +21 -21
  205. package/apps/pwa/out/design-check/index.html +1 -1
  206. package/apps/pwa/out/design-check/index.txt +22 -22
  207. package/apps/pwa/out/editor/index.html +1 -1
  208. package/apps/pwa/out/editor/index.txt +22 -22
  209. package/apps/pwa/out/exec/index.html +1 -1
  210. package/apps/pwa/out/exec/index.txt +22 -22
  211. package/apps/pwa/out/field/index.html +1 -1
  212. package/apps/pwa/out/field/index.txt +22 -22
  213. package/apps/pwa/out/healthz +1 -1
  214. package/apps/pwa/out/index.html +1 -1
  215. package/apps/pwa/out/index.txt +21 -21
  216. package/apps/pwa/out/inside/index.html +1 -1
  217. package/apps/pwa/out/inside/index.txt +21 -21
  218. package/apps/pwa/out/intake/index.html +1 -1
  219. package/apps/pwa/out/intake/index.txt +22 -22
  220. package/apps/pwa/out/live/index.html +1 -1
  221. package/apps/pwa/out/live/index.txt +22 -22
  222. package/apps/pwa/out/live-run/index.html +1 -1
  223. package/apps/pwa/out/live-run/index.txt +22 -22
  224. package/apps/pwa/out/loops/index.html +1 -1
  225. package/apps/pwa/out/loops/index.txt +21 -21
  226. package/apps/pwa/out/market/index.html +1 -1
  227. package/apps/pwa/out/market/index.txt +21 -21
  228. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  229. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  230. package/apps/pwa/out/morning/index.html +1 -1
  231. package/apps/pwa/out/morning/index.txt +22 -22
  232. package/apps/pwa/out/observatory/index.html +1 -1
  233. package/apps/pwa/out/observatory/index.txt +22 -22
  234. package/apps/pwa/out/ops/checklist/index.html +1 -1
  235. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  236. package/apps/pwa/out/ops/release/index.html +1 -1
  237. package/apps/pwa/out/ops/release/index.txt +21 -21
  238. package/apps/pwa/out/ops/seats/index.html +1 -1
  239. package/apps/pwa/out/ops/seats/index.txt +21 -21
  240. package/apps/pwa/out/outputs/index.html +1 -1
  241. package/apps/pwa/out/outputs/index.txt +21 -21
  242. package/apps/pwa/out/reflection/index.html +1 -1
  243. package/apps/pwa/out/reflection/index.txt +22 -22
  244. package/apps/pwa/out/scheduler/index.html +1 -1
  245. package/apps/pwa/out/scheduler/index.txt +22 -22
  246. package/apps/pwa/out/sessions/index.html +1 -1
  247. package/apps/pwa/out/sessions/index.txt +21 -21
  248. package/apps/pwa/out/settings/devices/index.html +1 -1
  249. package/apps/pwa/out/settings/devices/index.txt +22 -22
  250. package/apps/pwa/out/settings/index.html +1 -1
  251. package/apps/pwa/out/settings/index.txt +22 -22
  252. package/apps/pwa/out/setup/done/index.html +1 -1
  253. package/apps/pwa/out/setup/done/index.txt +22 -22
  254. package/apps/pwa/out/setup/index.html +1 -1
  255. package/apps/pwa/out/setup/index.txt +22 -22
  256. package/apps/pwa/out/share/index.html +1 -1
  257. package/apps/pwa/out/share/index.txt +22 -22
  258. package/apps/pwa/out/showroom/index.html +1 -1
  259. package/apps/pwa/out/showroom/index.txt +21 -21
  260. package/apps/pwa/out/tasks/index.html +1 -1
  261. package/apps/pwa/out/tasks/index.txt +22 -22
  262. package/apps/pwa/out/term/index.html +1 -1
  263. package/apps/pwa/out/term/index.txt +22 -22
  264. package/apps/pwa/out/today/index.html +1 -1
  265. package/apps/pwa/out/today/index.txt +22 -22
  266. package/apps/pwa/out/trace/index.html +1 -1
  267. package/apps/pwa/out/trace/index.txt +22 -22
  268. package/apps/pwa/out/vault/index.html +1 -1
  269. package/apps/pwa/out/vault/index.txt +22 -22
  270. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  271. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  272. package/apps/pwa/out/workflows/index.html +1 -1
  273. package/apps/pwa/out/workflows/index.txt +22 -22
  274. package/apps/pwa/out/workspace/index.html +1 -1
  275. package/apps/pwa/out/workspace/index.txt +22 -22
  276. package/apps/pwa/out/worktrees/index.html +1 -1
  277. package/apps/pwa/out/worktrees/index.txt +22 -22
  278. package/graphs/demo/persona-marketer/fixtures/marketer-scenario.yaml +10 -0
  279. package/graphs/demo/persona-marketer/persona-marketer.yaml +25 -0
  280. package/graphs/demo/persona-marketer/recipes.yaml +19 -0
  281. package/graphs/video/explainer-line.yaml +4 -1
  282. package/package.json +1 -1
  283. package/scripts/dead-code/report.ts +169 -0
  284. package/scripts/lib/morning-report-options.ts +3 -4
  285. package/scripts/lib/tui-regress-evidence.ts +56 -0
  286. package/scripts/morning-report.ts +5 -1
  287. package/scripts/public-export.ts +15 -7
  288. package/scripts/release-loop/export-check-node.ts +21 -3
  289. package/scripts/release-loop/gate-node.ts +379 -48
  290. package/scripts/release-loop/gate-shard-dispatch.ts +128 -0
  291. package/scripts/release-loop/gate-shard-receipts.ts +89 -0
  292. package/scripts/release-loop/gate-wall.ts +5 -5
  293. package/scripts/release-loop/preflight.ts +6 -2
  294. package/scripts/release-loop/resume-release.ts +20 -5
  295. package/scripts/release-loop/resume.ts +48 -0
  296. package/scripts/release-loop/version-node.ts +7 -2
  297. package/scripts/release-story/draft.ts +1 -1
  298. package/scripts/research-bench/README.md +53 -0
  299. package/scripts/research-bench/questions.json +66 -0
  300. package/scripts/research-bench/rubric.md +33 -0
  301. package/scripts/research-bench/run.ts +523 -0
  302. package/scripts/tui-regress.ts +85 -10
  303. package/src/acp/core-turn-bridge.ts +8 -0
  304. package/src/agent/autonomous-tools.ts +10 -3
  305. package/src/agent/monad-agent-turn.ts +4 -1
  306. package/src/agent/registry.ts +26 -2
  307. package/src/agent/shared-app-tools.ts +1 -1
  308. package/src/agent/surface-ux/build.ts +12 -3
  309. package/src/agent/surface-ux/types.ts +1 -1
  310. package/src/agent/task-notification.ts +75 -6
  311. package/src/agent/types.ts +3 -0
  312. package/src/agent-mission/driver.ts +29 -3
  313. package/src/agent-mission/mission-cli.ts +2 -1
  314. package/src/agent-substrate/review-context-pack.ts +365 -0
  315. package/src/agent-substrate/self-review-cli.ts +226 -17
  316. package/src/ask-user-question/index.ts +6 -0
  317. package/src/ask-user-question/inline-resolver.ts +49 -0
  318. package/src/auto-research/question-ladder-contract.ts +22 -3
  319. package/src/auto-research/research-turn.ts +350 -17
  320. package/src/autopilot/agent-loop.ts +1 -1
  321. package/src/autopilot/pty-control-loop.ts +8 -1
  322. package/src/boot/daemon-tools/index.ts +4 -3
  323. package/src/boot/daemon-tools/self-implement.ts +270 -2
  324. package/src/boot/daemon-tools/types.ts +2 -0
  325. package/src/budget/llm-cost.ts +44 -5
  326. package/src/budget/unified-usage.ts +17 -1
  327. package/src/capture/tui-self-report.ts +14 -0
  328. package/src/chat/index.ts +33 -7
  329. package/src/cli/agent-cli.ts +43 -8
  330. package/src/cli/intake-cli.ts +22 -1
  331. package/src/cli/lesson-cli.ts +19 -3
  332. package/src/cli/log-event-names.ts +1 -0
  333. package/src/cli/pod-cli.ts +17 -2
  334. package/src/cli/pty-takeover-cli.ts +67 -7
  335. package/src/cli/release-cli.ts +52 -6
  336. package/src/cli/repo-cli.ts +2 -1
  337. package/src/cli/tasks-cli.ts +36 -9
  338. package/src/control-plane/ledger.ts +21 -4
  339. package/src/core-turn/run-core-turn.ts +44 -3
  340. package/src/core-turn/run-goal-loop.ts +152 -8
  341. package/src/core-turn/types.ts +9 -0
  342. package/src/dashboard/chat/acp-chat.ts +2 -2
  343. package/src/dashboard/classic-sigquit.ts +16 -0
  344. package/src/dashboard/index.ts +321 -27
  345. package/src/dashboard/input/chat-main-interaction-opts.ts +3 -0
  346. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +7 -2
  347. package/src/dashboard/input/chat-main-slash-command.ts +7 -0
  348. package/src/dashboard/input/dashboard-plain-turn-stream.ts +4 -0
  349. package/src/dashboard/input/dashboard-priority-key-route.ts +21 -5
  350. package/src/dashboard/input/external-input-host.ts +2 -0
  351. package/src/dashboard/sidetab-runtime.ts +228 -0
  352. package/src/dashboard/slash-runtime/ask-clarification.ts +7 -1
  353. package/src/dashboard/slash-runtime/dashboard-handlers.ts +20 -8
  354. package/src/dashboard/slash-runtime/help-from-registry.ts +2 -2
  355. package/src/dashboard/term-slash-runtime.ts +16 -18
  356. package/src/dashboard/turn-preamble.ts +2 -0
  357. package/src/domains/knowledge.ts +1 -1
  358. package/src/esc-abort-gate.ts +33 -1
  359. package/src/execution-loop/launch-gate.ts +206 -1
  360. package/src/graph-runner/graph-cli.ts +6 -4
  361. package/src/graph-runner/runner.ts +31 -9
  362. package/src/graph-wizard/generate.ts +16 -7
  363. package/src/graph-wizard/mission-compose.ts +201 -0
  364. package/src/grok/agent-search.ts +8 -2
  365. package/src/grok/credential.ts +5 -0
  366. package/src/grounding/ref-index.ts +11 -0
  367. package/src/grounding/ref-vector.ts +61 -0
  368. package/src/grounding/sources-cli.ts +2 -2
  369. package/src/grounding/sources.ts +15 -1
  370. package/src/harness/harness-cli-command.ts +38 -9
  371. package/src/harness/harness-pod-dispatch.ts +7 -1
  372. package/src/index.ts +18 -4
  373. package/src/input/external-input-queue.ts +10 -0
  374. package/src/intake-plane/collect-telegram-saved.ts +36 -1
  375. package/src/intake-plane/intake-to-tasks.ts +246 -3
  376. package/src/lessons/friction-ledger.ts +154 -0
  377. package/src/live-supply/collector.ts +149 -0
  378. package/src/live-supply/probes.ts +52 -0
  379. package/src/live-supply/snapshot.ts +40 -0
  380. package/src/llm.ts +431 -76
  381. package/src/loops/orchestrator/tick.ts +8 -0
  382. package/src/nexus/api/harness-api.ts +2 -1
  383. package/src/pty/snapshot.py +132 -0
  384. package/src/pty-shell/pty-control-ipc.ts +29 -2
  385. package/src/pty-shell/pty-manifest.ts +59 -3
  386. package/src/pty-shell/registry.ts +2 -0
  387. package/src/pty-shell/tui-run-state.ts +80 -3
  388. package/src/release-loop/gate-host-reservation.ts +13 -4
  389. package/src/release-loop/gate-shard-ledger.ts +68 -0
  390. package/src/release-loop/merged-pr-checklist.ts +25 -2
  391. package/src/release-loop/rehearsal-shard-plan.ts +6 -1
  392. package/src/release-loop/rehearsal.ts +27 -0
  393. package/src/research/edge-decision.ts +124 -15
  394. package/src/research/gap-followup.ts +249 -0
  395. package/src/research/lenses/counter-evidence.ts +100 -0
  396. package/src/research/lenses/working-backwards.ts +89 -0
  397. package/src/research/plugin-discovery.ts +242 -0
  398. package/src/research-bridge/invoke.ts +4 -2
  399. package/src/research-bridge/types.ts +2 -0
  400. package/src/self-dev/ask-launch-flow.ts +34 -106
  401. package/src/self-dev/dev-cli.ts +2 -0
  402. package/src/self-dev/dev-pipeline.ts +8 -4
  403. package/src/self-dev/graph-journey-route.ts +10 -2
  404. package/src/self-dev/launch-preflight-text.ts +2 -2
  405. package/src/self-dev/launch-preflight.ts +38 -7
  406. package/src/self-dev/orchestrate-cli.ts +1 -0
  407. package/src/self-dev/run-supervisor.ts +19 -0
  408. package/src/self-implement/device-first.ts +8 -2
  409. package/src/self-implement/doctor-visit.ts +76 -58
  410. package/src/self-implement/gate-artifacts.ts +3 -0
  411. package/src/self-implement/gate-baseline.ts +75 -4
  412. package/src/self-implement/gate-cli.ts +317 -9
  413. package/src/self-implement/gate-receipt-registry.ts +180 -0
  414. package/src/self-implement/gate-remote.ts +145 -22
  415. package/src/self-implement/goal-author-clarification.ts +178 -24
  416. package/src/self-implement/goal-author-decompose.ts +24 -15
  417. package/src/self-implement/goal-author.ts +9 -5
  418. package/src/self-implement/host-regate.ts +120 -45
  419. package/src/self-implement/impl-findings-feedback.ts +188 -0
  420. package/src/self-implement/knowhow-pack.ts +189 -10
  421. package/src/self-implement/off-diff-evidence.ts +124 -0
  422. package/src/self-implement/orchestrator.ts +85 -7
  423. package/src/self-implement/run-ledger.ts +46 -8
  424. package/src/self-implement/run-stop.ts +12 -0
  425. package/src/self-implement/seams.ts +6 -3
  426. package/src/self-implement/self-implement-cli.ts +4 -2
  427. package/src/session/chat.ts +89 -15
  428. package/src/session-runtime/provider-circuit.ts +140 -0
  429. package/src/shell-runner/file-engine.ts +1 -0
  430. package/src/shell-runner/types.ts +4 -0
  431. package/src/sidetab-core/model.ts +176 -0
  432. package/src/skills/tools/schedule-wakeup.ts +23 -1
  433. package/src/skills/tools/shell.ts +51 -5
  434. package/src/steward/directive-audit.ts +354 -0
  435. package/src/surface/child-process.ts +31 -0
  436. package/src/surface/tui-stderr-owner.ts +48 -0
  437. package/src/task-agent/cover.ts +30 -12
  438. package/src/task-agent/judge.ts +56 -0
  439. package/src/task-agent/postland-card.ts +35 -2
  440. package/src/task-agent/rejudge-on-head.ts +46 -2
  441. package/src/task-agent/repair-cycle.ts +1 -1
  442. package/src/task-agent/task-hand.ts +129 -24
  443. package/src/task-agent/tier-split.ts +105 -21
  444. package/src/task-orchestrator/surfaces/pod-command-job.ts +330 -2
  445. package/src/task-orchestrator/surfaces/pod-config-snapshot.ts +123 -0
  446. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +27 -2
  447. package/src/task-orchestrator/surfaces/pod-mirror-seed.ts +11 -8
  448. package/src/task-orchestrator/surfaces/pod-si-warm-protocol.ts +1 -1
  449. package/src/task-orchestrator/surfaces/pod-source-receive.ts +74 -6
  450. package/src/task-orchestrator/surfaces/pod-warm-worker-pod.ts +2 -1
  451. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +56 -15
  452. package/src/task-orchestrator/surfaces/self-implement-pod.ts +186 -33
  453. package/src/tool-runtime/skill-exec-runtime.ts +95 -5
  454. package/src/tui/entry.ts +15 -2
  455. package/src/tui/inline-choice.ts +188 -0
  456. package/src/tui/sidetab/list.ts +2 -176
  457. package/src/tui/slash/term.ts +12 -1
  458. package/src/tui-client/dashboard-session.ts +7 -1
  459. package/src/user-config.ts +34 -4
  460. package/src/ux-sim/classic-tui-seat-scenarios.ts +1 -7
  461. package/src/ux-sim/fake-land-queue.ts +88 -0
  462. package/src/ux-sim/gate-shard-host-reroute.ts +82 -0
  463. package/src/ux-sim/goal-interim-trace.ts +24 -0
  464. package/src/ux-sim/next-tui-seat-scenarios.ts +8 -13
  465. package/src/ux-sim/task-orchestrator-surfaces-self-implement-pod-device.ts +4 -1
  466. package/src/version/packed-revision.json +1 -1
  467. package/src/video-pipeline/recipes/explainer.ts +54 -2
  468. package/src/web-search/grok.ts +32 -6
  469. package/src/web-search/index.ts +8 -7
  470. package/src/workflow-runtime/node-catalog.ts +53 -4
  471. package/apps/pwa/out/_next/static/chunks/1118.a8a74ea29aac3e46.js +0 -27
  472. package/apps/pwa/out/_next/static/chunks/1204-2aa830479adf80f4.js +0 -1
  473. package/apps/pwa/out/_next/static/chunks/1341-43b7d2dc77d45c9d.js +0 -1
  474. package/apps/pwa/out/_next/static/chunks/1440-c3ea8882badfd9bf.js +0 -1
  475. package/apps/pwa/out/_next/static/chunks/1698-9c11cbf97f13717e.js +0 -1
  476. package/apps/pwa/out/_next/static/chunks/1770-3b1fc92253ef9f2f.js +0 -1
  477. package/apps/pwa/out/_next/static/chunks/1923-5c1695332240246a.js +0 -1
  478. package/apps/pwa/out/_next/static/chunks/213-20675f20673ba22a.js +0 -1
  479. package/apps/pwa/out/_next/static/chunks/214.186a430da28338f1.js +0 -1
  480. package/apps/pwa/out/_next/static/chunks/2277.3bd4c0ac7f1b5996.js +0 -93
  481. package/apps/pwa/out/_next/static/chunks/240.e09f433f71c78ff4.js +0 -104
  482. package/apps/pwa/out/_next/static/chunks/2415.738b777642a02233.js +0 -1
  483. package/apps/pwa/out/_next/static/chunks/2417.02151393605a7cd0.js +0 -1
  484. package/apps/pwa/out/_next/static/chunks/2463.cd2641a76daaa9ff.js +0 -1
  485. package/apps/pwa/out/_next/static/chunks/2576.b9e9c629c4b84c52.js +0 -1
  486. package/apps/pwa/out/_next/static/chunks/265-c021de53f0865bd9.js +0 -1
  487. package/apps/pwa/out/_next/static/chunks/2998-b1cc13956cd6a6e7.js +0 -1
  488. package/apps/pwa/out/_next/static/chunks/2e4782d3.ba2f0ab2b63a53e7.js +0 -1
  489. package/apps/pwa/out/_next/static/chunks/3130.626b54382b4dc379.js +0 -1
  490. package/apps/pwa/out/_next/static/chunks/3221-1bb3f99a55088613.js +0 -1
  491. package/apps/pwa/out/_next/static/chunks/3280.24edb1ffd03a7f3f.js +0 -24
  492. package/apps/pwa/out/_next/static/chunks/3288-eb3c22a1cbf2ae68.js +0 -1
  493. package/apps/pwa/out/_next/static/chunks/33.ef99e8374f96c6c4.js +0 -36
  494. package/apps/pwa/out/_next/static/chunks/3341-f09b9efbd7a82f70.js +0 -1
  495. package/apps/pwa/out/_next/static/chunks/3389.012c70767a872f9b.js +0 -1
  496. package/apps/pwa/out/_next/static/chunks/3410-d7c0f14b329d6fda.js +0 -1
  497. package/apps/pwa/out/_next/static/chunks/3421.c87d6313a7d670f7.js +0 -287
  498. package/apps/pwa/out/_next/static/chunks/3422-83a3953f9bd67e26.js +0 -1
  499. package/apps/pwa/out/_next/static/chunks/3587-002e24e368c515a9.js +0 -1
  500. package/apps/pwa/out/_next/static/chunks/3644.f12a7d821ab940af.js +0 -1
  501. package/apps/pwa/out/_next/static/chunks/3660.d7516588e2d875c3.js +0 -1
  502. package/apps/pwa/out/_next/static/chunks/3695.b82e2610f4cd4ea9.js +0 -1
  503. package/apps/pwa/out/_next/static/chunks/3858.ca1f5bc0f577eac9.js +0 -94
  504. package/apps/pwa/out/_next/static/chunks/3959-e6ac4a139d9d4bcc.js +0 -1
  505. package/apps/pwa/out/_next/static/chunks/4032.53f62176514ec0ea.js +0 -1
  506. package/apps/pwa/out/_next/static/chunks/4204-ef8484cbecd5d62f.js +0 -1
  507. package/apps/pwa/out/_next/static/chunks/4259-163129ca79913c4b.js +0 -1
  508. package/apps/pwa/out/_next/static/chunks/428-eaa77df3d0c85969.js +0 -1
  509. package/apps/pwa/out/_next/static/chunks/4432-97e400ffa1e161f5.js +0 -1
  510. package/apps/pwa/out/_next/static/chunks/449-aa427cf2cbb75f50.js +0 -1
  511. package/apps/pwa/out/_next/static/chunks/4491-39a0fd32bbaf3840.js +0 -1
  512. package/apps/pwa/out/_next/static/chunks/4588.b7cf06d382953979.js +0 -1
  513. package/apps/pwa/out/_next/static/chunks/4690.70ec8060825366ab.js +0 -32
  514. package/apps/pwa/out/_next/static/chunks/4804.6012b5cd33c22792.js +0 -90
  515. package/apps/pwa/out/_next/static/chunks/4881.e4d22d730e3b9df5.js +0 -1
  516. package/apps/pwa/out/_next/static/chunks/4937.ce2e340dc29cad3e.js +0 -79
  517. package/apps/pwa/out/_next/static/chunks/5-bb1c08d84bd71df3.js +0 -1
  518. package/apps/pwa/out/_next/static/chunks/5005.de98df23b37cdf3c.js +0 -1
  519. package/apps/pwa/out/_next/static/chunks/5035.dc64a89cad5573cc.js +0 -74
  520. package/apps/pwa/out/_next/static/chunks/5207.1a224035455790fd.js +0 -1
  521. package/apps/pwa/out/_next/static/chunks/5255-1b60d50eabe9f057.js +0 -1
  522. package/apps/pwa/out/_next/static/chunks/5269.d0436ee6d773382a.js +0 -286
  523. package/apps/pwa/out/_next/static/chunks/5300.677c97e0393742e6.js +0 -1
  524. package/apps/pwa/out/_next/static/chunks/5309.3367c4d50f52b489.js +0 -1
  525. package/apps/pwa/out/_next/static/chunks/552-689827d49780fa00.js +0 -1
  526. package/apps/pwa/out/_next/static/chunks/5539.34cc9d60622cb69b.js +0 -8
  527. package/apps/pwa/out/_next/static/chunks/5568.218dea0c00ca2ec7.js +0 -1
  528. package/apps/pwa/out/_next/static/chunks/5645.b7e3b055455a04ea.js +0 -1
  529. package/apps/pwa/out/_next/static/chunks/5662.18cc0f30353cbd96.js +0 -1
  530. package/apps/pwa/out/_next/static/chunks/5671.da24fc9dc5e98325.js +0 -1
  531. package/apps/pwa/out/_next/static/chunks/5b141171.324c40fd49cb6821.js +0 -1
  532. package/apps/pwa/out/_next/static/chunks/6175-d4621f6a10b0cfab.js +0 -1
  533. package/apps/pwa/out/_next/static/chunks/6290.3eb53a20746b72ce.js +0 -1
  534. package/apps/pwa/out/_next/static/chunks/6415-9307f3eafa90837f.js +0 -1
  535. package/apps/pwa/out/_next/static/chunks/6579-3de35d00aacd71b5.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/680-2f324c4e039a5b67.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/6845-331b3c7481da3ba3.js +0 -1
  538. package/apps/pwa/out/_next/static/chunks/7000.28157393caaf5343.js +0 -62
  539. package/apps/pwa/out/_next/static/chunks/7311-60a7ea80d23c7521.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/7401.525d0a12f7d02c06.js +0 -1
  541. package/apps/pwa/out/_next/static/chunks/7438.c2cf72b66dca6aa4.js +0 -1
  542. package/apps/pwa/out/_next/static/chunks/7488.966b116789f3d41a.js +0 -1
  543. package/apps/pwa/out/_next/static/chunks/7573.2376e13c9c21f1f8.js +0 -77
  544. package/apps/pwa/out/_next/static/chunks/7577.ea6e9ac72e035520.js +0 -1
  545. package/apps/pwa/out/_next/static/chunks/7657.8d1fb3d2f7ebe273.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/7903-1435d5d2f0dd7807.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/7978-30a91192c5dbe3c2.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/8025-8795821525cf1a07.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/8191.3674a00f0b565c23.js +0 -1
  550. package/apps/pwa/out/_next/static/chunks/8217-604955d8885c5ef2.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/8298-eed6f5f2585a63f4.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/8758.ac421f726a189125.js +0 -1
  553. package/apps/pwa/out/_next/static/chunks/891.d6c723a51a067b36.js +0 -149
  554. package/apps/pwa/out/_next/static/chunks/9223.cbcc88e0e9950426.js +0 -41
  555. package/apps/pwa/out/_next/static/chunks/9317.6a9869039c231bb3.js +0 -24
  556. package/apps/pwa/out/_next/static/chunks/9383.e4755f275b3c11ff.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/9581.da63ddf41acfad46.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/9715.8c5529a0a5c41a36.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/9817.3009d65f0889ef1f.js +0 -2
  560. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76873dd80da4f715.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/app/approvals/page-ed32b6ec5dea8f23.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-fdd40e15babf3d25.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/app/board/page-384efc78e85e400b.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/app/bots/page-d91809c5aeed319a.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/app/ceo/page-128f3522f89a81ab.js +0 -1
  566. package/apps/pwa/out/_next/static/chunks/app/chat/page-595961abf3b43ad1.js +0 -1
  567. package/apps/pwa/out/_next/static/chunks/app/consult/page-f41dccb76d8c0263.js +0 -1
  568. package/apps/pwa/out/_next/static/chunks/app/control/page-a3205c2e28b7d0d9.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/app/decisions/page-c39a80277814a3f4.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/app/design-check/page-1ab3f98194513195.js +0 -1
  571. package/apps/pwa/out/_next/static/chunks/app/editor/page-a5246f7e254d77d0.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/app/exec/page-0f92287bdb81217d.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/app/field/page-5a37131ff63793ef.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76873dd80da4f715.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/app/inside/page-ac4bd14bb2348bfd.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/app/intake/page-c348a3959c5b5fc6.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/app/layout-2addd81c0d3e2906.js +0 -1
  578. package/apps/pwa/out/_next/static/chunks/app/live/page-da6b765f58a3eefb.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/app/live-run/page-0661e40f8780c32c.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/app/loops/page-b89af1b1c8e4875b.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/app/market/page-da8aeb82ba751cdb.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-cc71317b239439db.js +0 -1
  583. package/apps/pwa/out/_next/static/chunks/app/morning/page-bde7fc1d64ffe369.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/app/not-found-e2797214f713fa58.js +0 -1
  585. package/apps/pwa/out/_next/static/chunks/app/observatory/page-2a35bcda70defaf6.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-3af03deedde45032.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-d1d1210f99f620ae.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-46d1b5500885861d.js +0 -1
  589. package/apps/pwa/out/_next/static/chunks/app/outputs/page-291ab19fe2acb173.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/app/page-7f569e533ddeecba.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/app/reflection/page-990129c9fee46d8f.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-7737f785ebb1cdaf.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/app/sessions/page-9f3c73a4f7ffd2f8.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-03be7fb347f01058.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/app/settings/page-96b0280625e4df2b.js +0 -1
  596. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-56855545049eb56d.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76873dd80da4f715.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/app/setup/page-79a909c9981f0338.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/app/share/page-a9d9a3e66459c1e0.js +0 -1
  600. package/apps/pwa/out/_next/static/chunks/app/showroom/page-c383cbf2013f7069.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/app/tasks/page-f57c6a2e54dbdca4.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/app/term/page-6b140f77593576eb.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/app/today/page-6b767ae2d9d0adfc.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/app/trace/page-116d6198d5da0e3d.js +0 -1
  605. package/apps/pwa/out/_next/static/chunks/app/vault/page-b9c9b778c7501370.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-a6c78392ab8f6335.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/app/workflows/page-455183deb4ed0cfe.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/app/workspace/page-6a63e99526bd63d0.js +0 -1
  609. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-31c22caafe788c08.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/main-941155250ed2644b.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/main-app-f8b6765abed6d149.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/pages/_app-78432194c85388f9.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/pages/_error-cdf7390829512b1b.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/webpack-d5f0964a9c2e92d2.js +0 -1
  615. /package/apps/pwa/out/_next/static/{RrjXTwz-urRAbChP1bX02 → HjeK7zONHfR7op1hKXp4k}/_ssgManifest.js +0 -0
@@ -1,6 +1,9 @@
1
1
  import { createHash } from 'node:crypto';
2
- import { readFileSync } from 'node:fs';
2
+ import { closeSync, constants, fstatSync, lstatSync, mkdirSync, openSync, readdirSync, readFileSync, writeSync } from 'node:fs';
3
+ import { join, resolve } from 'node:path';
3
4
  import { debug } from '../debug/log.js';
5
+ import { effectiveInstanceRoot } from '../instance/resolve.js';
6
+ import { assertLedgerPathPolicy } from '../harness/launch-utterance-ledger.js';
4
7
  import { extractVerbatimOriginalAsk } from '../self-implement/goal-author.js';
5
8
  import { loadRunLedger } from '../self-implement/run-ledger.js';
6
9
  import { queryRunningRuns, type QueriedRunningRunsResult } from '../self-implement/running-runs.js';
@@ -252,6 +255,8 @@ export interface PreLaunchGateInput {
252
255
 
253
256
  export interface PreLaunchGateDeps extends ActiveRunsForGoalDeps {
254
257
  activeRuns?: (goalId: string) => ActiveRunsForGoal;
258
+ /** LAUNCH-SINGLE-DOOR-1C — 주입 우선 단일문: 시험 우주가 격리 루트의 문을 끼워 생산 배선을 그대로 검증한다. */
259
+ launchDoor?: LaunchRequestDoor;
255
260
  }
256
261
 
257
262
  export interface PreLaunchGateDecision {
@@ -279,3 +284,203 @@ function decidePreLaunch(input: PreLaunchGateInput, deps: PreLaunchGateDeps): Pr
279
284
  }
280
285
  return { action: 'proceed', sameGoalActiveRuns, budget, reason: sameGoalActiveRuns === 'unknown' ? 'active runs unknown' : input.forceLaunch && sameGoalActiveRuns.length > 0 ? 'duplicate overridden by force-launch' : 'no confirmed duplicate' };
281
286
  }
287
+
288
+ // ─────────────────────────────────────────────────────────────────────────────────────
289
+ // LAUNCH-SINGLE-DOOR-1C — 발사 요청의 단일 문.
290
+ // ─────────────────────────────────────────────────────────────────────────────────────
291
+
292
+ /** Env contract: hand 가 소비한 requestId 를 자식 say 가 물려받아 같은 문을 다시 두드리지 않게 한다(한 번만 상속). */
293
+ export const LAUNCH_DOOR_RECEIPT_ENV = 'ELANOUS_LAUNCH_DOOR_RECEIPT';
294
+
295
+ /** append 전용 요청 원장의 행 종류 — 요청(중복 포함)·소비·거절·강제·실패·단일문 사용 불가 관측. */
296
+ export type LaunchRequestLedgerEvent = 'requested' | 'consumed' | 'refused-duplicate' | 'forced-duplicate' | 'launch-failed' | 'door-unavailable';
297
+
298
+ /** append 전용 요청 원장의 한 행 — 행은 지우거나 고치지 않는다(관측 전용). */
299
+ export interface LaunchRequestLedgerRow {
300
+ readonly event: LaunchRequestLedgerEvent;
301
+ readonly requestId: string;
302
+ readonly at: string;
303
+ readonly source?: string;
304
+ readonly receiptId?: string;
305
+ readonly reason?: string;
306
+ }
307
+
308
+ /** requestId 단위 소비 영수증 — 최초 1회만 발급된다(O_EXCL 파일이 곧 영수증이다). */
309
+ export interface LaunchRequestReceipt {
310
+ readonly requestId: string;
311
+ readonly receiptId: string;
312
+ readonly at: string;
313
+ readonly source?: string;
314
+ }
315
+
316
+ /** `consume` 의 답 — `refused` 는 기존 영수증을 읽어 사유와 함께 거절한 것이다. */
317
+ export type LaunchRequestConsumption =
318
+ | { readonly status: 'consumed'; readonly requestId: string; readonly receiptId: string; readonly receiptAt: string; readonly inherited?: true }
319
+ | { readonly status: 'forced'; readonly requestId: string; readonly receiptId: string | null; readonly receiptAt: string | null; readonly reason: string }
320
+ | { readonly status: 'refused'; readonly requestId: string; readonly receiptId: string | null; readonly receiptAt: string | null; readonly reason: string }
321
+ | { readonly status: 'unavailable'; readonly requestId: string; readonly reason: string };
322
+
323
+ /** 발사 요청의 단일 문 — 원장 append · 단일 소비 · 실패 기록 · 원장 조회. */
324
+ export interface LaunchRequestDoor {
325
+ /** 요청 한 건을 원장에 append 하고 그 requestId 를 돌려준다(중복 재요청도 매번 append 된다). */
326
+ requestId(ask: string): string;
327
+ /** requestId 단위 단일 소비 — 영수증은 최초 1회만 발급된다(두 번째는 기존 영수증과 사유로 거절). */
328
+ consume(requestId: string, opts?: { readonly force?: boolean; readonly inheritedReceipt?: string }): LaunchRequestConsumption;
329
+ /** 발사 실패 사유를 원장에 append 한다(관측 — 발사를 막지 않는다). */
330
+ fail(requestId: string, reason: string): void;
331
+ /** 원장 조회 — 중복 거절·실패·재시도 사유를 읽는다(인자를 주면 그 requestId 의 행만). */
332
+ rows(requestId?: string): readonly LaunchRequestLedgerRow[];
333
+ }
334
+
335
+ /** 단일문 deps — 원장 뿌리(기본 = 이 우주의 실효 인스턴스 루트)·시계·요청 출처 표지. */
336
+ export interface LaunchRequestDoorDeps {
337
+ readonly root?: string;
338
+ readonly now?: () => Date;
339
+ readonly source?: string;
340
+ }
341
+
342
+ const LAUNCH_REQUEST_ID_PATTERN = /^[A-Za-z0-9][A-Za-z0-9._-]{0,127}$/;
343
+ const LAUNCH_REQUEST_DATE_FILE = /^\d{4}-\d{2}-\d{2}\.jsonl$/;
344
+
345
+ function launchRequestLedgerDir(root: string): string {
346
+ return join(resolve(root), 'launch-requests');
347
+ }
348
+
349
+ /** 단일문을 연다 — 문 자체는 상태를 갖지 않고, 원장·영수증은 이 우주의 인스턴스 루트 아래 파일로 남는다. */
350
+ export function openLaunchRequestDoor(deps: LaunchRequestDoorDeps = {}): LaunchRequestDoor {
351
+ const dir = launchRequestLedgerDir(deps.root ?? effectiveInstanceRoot());
352
+ const receiptsDir = join(dir, 'receipts');
353
+ const now = deps.now ?? (() => new Date());
354
+ const source = deps.source;
355
+
356
+ const observe = (event: string, data: Record<string, unknown>): void => {
357
+ try { debug.log('execution-loop.launch-gate', event, data, { level: 'warn' }); } catch { /* 관측은 fail-soft */ }
358
+ };
359
+
360
+ const appendRow = (row: LaunchRequestLedgerRow): boolean => {
361
+ try {
362
+ assertLedgerPathPolicy(dir);
363
+ mkdirSync(dir, { recursive: true, mode: 0o700 });
364
+ assertLedgerPathPolicy(dir);
365
+ if (!lstatSync(dir).isDirectory()) throw new Error(`launch request ledger dir is not a directory: ${dir}`);
366
+ const file = join(dir, `${row.at.slice(0, 10)}.jsonl`);
367
+ const fd = openSync(file, constants.O_WRONLY | constants.O_APPEND | constants.O_CREAT | constants.O_NOFOLLOW, 0o600);
368
+ try {
369
+ if (!fstatSync(fd).isFile()) throw new Error(`launch request ledger file is not a regular file: ${file}`);
370
+ writeSync(fd, `${JSON.stringify(row)}\n`);
371
+ } finally { closeSync(fd); }
372
+ return true;
373
+ } catch (error) {
374
+ observe('request-ledger-unwritten', { event: row.event, requestId: row.requestId, reason: error instanceof Error ? error.message : String(error) });
375
+ return false;
376
+ }
377
+ };
378
+
379
+ const readReceipt = (requestId: string): LaunchRequestReceipt | null => {
380
+ try {
381
+ const fd = openSync(join(receiptsDir, `${requestId}.json`), constants.O_RDONLY | constants.O_NOFOLLOW);
382
+ try {
383
+ if (!fstatSync(fd).isFile()) return null;
384
+ const parsed = JSON.parse(readFileSync(fd, 'utf8')) as LaunchRequestReceipt;
385
+ return parsed && typeof parsed === 'object' && parsed.requestId === requestId
386
+ && typeof parsed.receiptId === 'string' && typeof parsed.at === 'string' ? parsed : null;
387
+ } finally { closeSync(fd); }
388
+ } catch { return null; }
389
+ };
390
+
391
+ const requestId = (ask: string): string => {
392
+ const id = launchRequestId(ask);
393
+ appendRow({ event: 'requested', requestId: id, at: now().toISOString(), ...(source ? { source } : {}) });
394
+ return id;
395
+ };
396
+
397
+ const consume = (id: string, opts: { readonly force?: boolean; readonly inheritedReceipt?: string } = {}): LaunchRequestConsumption => {
398
+ if (!LAUNCH_REQUEST_ID_PATTERN.test(id)) {
399
+ return { status: 'unavailable', requestId: id, reason: `requestId 가 원장 키로 쓸 수 없다: ${JSON.stringify(id)}` };
400
+ }
401
+ const at = now().toISOString();
402
+ // 부모(hand)가 같은 requestId 를 이미 소비했다면 상속 영수증으로 지나간다 — 새 영수증을 만들지 않는다.
403
+ if (opts.inheritedReceipt !== undefined && opts.inheritedReceipt === id) {
404
+ const inherited = readReceipt(id);
405
+ if (inherited !== null) {
406
+ try { debug.log('execution-loop.launch-gate', 'request-consumption-inherited', { requestId: id, receiptId: inherited.receiptId }); } catch { /* 관측은 fail-soft */ }
407
+ return { status: 'consumed', requestId: id, receiptId: inherited.receiptId, receiptAt: inherited.at, inherited: true };
408
+ }
409
+ }
410
+ const receipt: LaunchRequestReceipt = { requestId: id,
411
+ receiptId: `receipt-${createHash('sha256').update(`${id}:${at}`).digest('hex').slice(0, 12)}`, at,
412
+ ...(source ? { source } : {}) };
413
+ let created = true;
414
+ try {
415
+ assertLedgerPathPolicy(receiptsDir);
416
+ mkdirSync(receiptsDir, { recursive: true, mode: 0o700 });
417
+ assertLedgerPathPolicy(receiptsDir);
418
+ const fd = openSync(join(receiptsDir, `${id}.json`), constants.O_WRONLY | constants.O_CREAT | constants.O_EXCL | constants.O_NOFOLLOW, 0o600);
419
+ try {
420
+ if (!fstatSync(fd).isFile()) throw new Error(`소비 영수증이 일반 파일이 아니다: ${id}`);
421
+ writeSync(fd, JSON.stringify(receipt));
422
+ } finally { closeSync(fd); }
423
+ } catch (error) {
424
+ if ((error as NodeJS.ErrnoException)?.code !== 'EEXIST') {
425
+ const reason = error instanceof Error ? error.message : String(error);
426
+ observe('request-receipt-unavailable', { requestId: id, reason });
427
+ appendRow({ event: 'door-unavailable', requestId: id, at, ...(source ? { source } : {}), reason });
428
+ return { status: 'unavailable', requestId: id, reason: `소비 영수증을 만들지 못했다 — 발사를 막지 않는다: ${reason}` };
429
+ }
430
+ created = false;
431
+ }
432
+ if (created) {
433
+ appendRow({ event: 'consumed', requestId: id, at, ...(source ? { source } : {}), receiptId: receipt.receiptId });
434
+ return { status: 'consumed', requestId: id, receiptId: receipt.receiptId, receiptAt: receipt.at };
435
+ }
436
+ const existing = readReceipt(id);
437
+ if (existing === null) {
438
+ const reason = `requestId ${id} 의 소비 영수증이 이미 있지만 읽지 못했다 — 중복 발사 거절`;
439
+ appendRow({ event: 'refused-duplicate', requestId: id, at, ...(source ? { source } : {}), reason });
440
+ return { status: 'refused', requestId: id, receiptId: null, receiptAt: null, reason };
441
+ }
442
+ if (opts.force === true) {
443
+ const reason = `requestId ${id} 는 영수증 ${existing.receiptId} (${existing.at}) 로 이미 소비됐다 — force 로 다시 띄운다`;
444
+ appendRow({ event: 'forced-duplicate', requestId: id, at, ...(source ? { source } : {}), receiptId: existing.receiptId, reason });
445
+ return { status: 'forced', requestId: id, receiptId: existing.receiptId, receiptAt: existing.at, reason };
446
+ }
447
+ const reason = `requestId ${id} 는 영수증 ${existing.receiptId} (${existing.at}) 로 이미 소비됐다 — 중복 발사 거절`;
448
+ appendRow({ event: 'refused-duplicate', requestId: id, at, ...(source ? { source } : {}), receiptId: existing.receiptId, reason });
449
+ return { status: 'refused', requestId: id, receiptId: existing.receiptId, receiptAt: existing.at, reason };
450
+ };
451
+
452
+ const fail = (id: string, reason: string): void => {
453
+ appendRow({ event: 'launch-failed', requestId: id, at: now().toISOString(),
454
+ ...(source ? { source } : {}), reason: reason.trim() || '사유 없음' });
455
+ };
456
+
457
+ const rows = (requestId?: string): readonly LaunchRequestLedgerRow[] => {
458
+ const result: LaunchRequestLedgerRow[] = [];
459
+ let names: string[];
460
+ try {
461
+ assertLedgerPathPolicy(dir);
462
+ names = readdirSync(dir);
463
+ } catch { return result; }
464
+ for (const name of names.filter((candidate) => LAUNCH_REQUEST_DATE_FILE.test(candidate)).sort()) {
465
+ let text: string;
466
+ try {
467
+ const fd = openSync(join(dir, name), constants.O_RDONLY | constants.O_NOFOLLOW);
468
+ try {
469
+ if (!fstatSync(fd).isFile()) continue;
470
+ text = readFileSync(fd, 'utf8');
471
+ } finally { closeSync(fd); }
472
+ } catch { continue; }
473
+ for (const line of text.split('\n')) {
474
+ if (!line) continue;
475
+ try {
476
+ const row = JSON.parse(line) as LaunchRequestLedgerRow;
477
+ if (row && typeof row === 'object' && typeof row.event === 'string' && typeof row.requestId === 'string'
478
+ && typeof row.at === 'string' && (requestId === undefined || row.requestId === requestId)) result.push(row);
479
+ } catch { /* 찢어진 줄은 건너뛴다 */ }
480
+ }
481
+ }
482
+ return result;
483
+ };
484
+
485
+ return { requestId, consume, fail, rows };
486
+ }
@@ -31,19 +31,21 @@ export function registerGraphCommands(program: Command, runsDeps: { root?: strin
31
31
  graph.command('adapt-report')
32
32
  .description('Measure recorded graph path diversity, unit calls, adaptations and landings for one goal')
33
33
  .requiredOption('--goal <id>', 'Goal ID to measure')
34
+ .option('--from <timestamp>', 'Include runs started at or after this ISO timestamp')
35
+ .option('--to <timestamp>', 'Exclude runs started at or after this ISO timestamp')
34
36
  .option('--json', 'Print measurement as JSON')
35
- .action(async (opts: { goal: string; json?: boolean }) => {
37
+ .action(async (opts: { goal: string; from?: string; to?: string; json?: boolean }) => {
36
38
  try {
37
39
  const { queryGraphAdaptReport } = await import('../self-implement/run-ledger.js');
38
- const report = queryGraphAdaptReport(opts.goal);
40
+ const report = queryGraphAdaptReport(opts.goal, undefined, { since: opts.from, until: opts.to });
39
41
  if (opts.json) await writeStdoutJson(JSON.stringify(report) + '\n');
40
- else if (report.runCount === 0) console.log(`graph adapt-report: ${opts.goal} · 표본 0 · 제외 ${report.excludedCount} ${JSON.stringify(report.exclusionReasons)}`);
42
+ else if (report.runCount === 0) console.log(`graph adapt-report: ${opts.goal} · 표본 0 · 제외 ${report.excludedCount} ${JSON.stringify(report.exclusionReasons)} · 미측정 ${report.unmeasuredCount} ${JSON.stringify(report.unmeasuredReasons)}`);
41
43
  else {
42
44
  const landing = (group: typeof report.adapted) => group.denominator
43
45
  ? `${group.landed}/${group.denominator} (${(group.rate! * 100).toFixed(1)}%)` : '표본 0';
44
46
  console.log(`graph adapt-report: ${opts.goal} · 경로 ${report.uniquePathSignatures} · 유닛 호출 ${report.unitCallCount} · 적응 ${report.adaptationCount}`);
45
47
  console.log(`적응 착지율 ${landing(report.adapted)} · 비적응 착지율 ${landing(report.nonAdapted)}`);
46
- console.log(`제외 ${report.excludedCount} ${JSON.stringify(report.exclusionReasons)}`);
48
+ console.log(`제외 ${report.excludedCount} ${JSON.stringify(report.exclusionReasons)} · 미측정 ${report.unmeasuredCount} ${JSON.stringify(report.unmeasuredReasons)}`);
47
49
  }
48
50
  } catch (error) {
49
51
  console.error(`graph adapt-report: ${error instanceof Error ? error.message : String(error)}`);
@@ -28,7 +28,7 @@ import { executeBashNode } from '../workflow-runtime/nodes/bash.js';
28
28
  import { executeClassifyNode } from '../workflow-runtime/nodes/classify.js';
29
29
  import { interpolate } from '../workflow-runtime/variables.js';
30
30
  import type { BashNode, ClassifyNode, NodeExecContext, NodeOutput, WorkflowDeps } from '../workflow-runtime/types.js';
31
- import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeGatePodPool, releaseResumeWaiver, type AcceptedRegression, type GateExecutorOverride, type GatePodPoolOverride } from '../../scripts/release-loop/resume.js';
31
+ import { releaseResumeAcceptedRegressions, releaseResumeGateExecutor, releaseResumeGatePodPool, releaseResumeGateShardReroute, releaseResumeWaiver, type AcceptedRegression, type GateExecutorOverride, type GatePodPoolOverride, type GateShardRerouteOverride } from '../../scripts/release-loop/resume.js';
32
32
 
33
33
  type BashRun = WorkflowDeps['runBash'];
34
34
  const DEFAULT_BASH_TIMEOUT_MS = 5 * 60 * 1_000;
@@ -148,7 +148,8 @@ export interface GraphRunState {
148
148
  reason?: string;
149
149
  path: string[];
150
150
  /** startedAt/endedAt (ISO) and seconds are written when the node runs; ledgers before GRAPH-NODE-TIMES (0.2.19) have none. */
151
- nodes: Array<{ nodeId: string; ok: boolean; exit: number | null; executed: boolean; output?: unknown; error?: string; reason?: string; decidedBy?: string; decidedAt?: string;
151
+ nodes: Array<{ nodeId: string; ok: boolean; exit: number | null; executed: boolean; output?: unknown; error?: string; reason?: string;
152
+ failure?: { errorCode: string; message: string; stage: string }; decidedBy?: string; decidedAt?: string;
152
153
  startedAt?: string; endedAt?: string; seconds?: number;
153
154
  waiver?: { reason: string; at: string; /** RELEASE-WAIVE-UNMEASURED — why the waived gate had no verdict. */ unmeasured?: string; original: { exit: number | null; output?: unknown; error?: string } } }>;
154
155
  /** The node now running and when it started; cleared when its record is written. */
@@ -170,7 +171,7 @@ export interface GraphRunState {
170
171
  growthPark?: { from: string; outcome: string; reason: string; decisionId: string; decisionRef: string; growth: GraphGrowth; command?: GrowthCommand; approval?: string };
171
172
  resume?: { from: string; at: string; previousStatus: GraphRunState['status']; graph?: 'snapshot' | 'current' };
172
173
  /** GATE-HOST-EXECUTOR — every explicit input change a resume made (what was set and what it replaced), oldest first. */
173
- inputOverrides?: Array<GateExecutorOverride | GatePodPoolOverride>;
174
+ inputOverrides?: Array<GateExecutorOverride | GatePodPoolOverride | GateShardRerouteOverride>;
174
175
  executed: number;
175
176
  dryRun: boolean;
176
177
  statePath: string;
@@ -241,6 +242,8 @@ export interface GraphRunOptions {
241
242
  releaseGateExecutor?: { executor: string; host?: string };
242
243
  /** Release-only (RESUME-GATE-POOL-OVERRIDE): replace the saved gate pool for this resumed gate. */
243
244
  releaseGatePodPool?: string;
245
+ /** Release-only: remeasure a shard after the same-commit resume preflight. */
246
+ releaseGateShardReroute?: { shard: string; host?: string; os?: 'darwin' | 'linux' };
244
247
  useCurrentGraph?: boolean;
245
248
  /** Internal unit invocation context, propagated only by runGraph. */
246
249
  unitContext?: { parentRunId: string; ancestors: readonly string[]; remainingSteps: number; entryNodeId?: string };
@@ -652,6 +655,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
652
655
  if (options.releaseAcceptedRegressions && (!options.resumeRunId || !options.fromNodeId || options.releaseWaiver)) throw new Error('accepted regressions require a release resume boundary');
653
656
  if (options.releaseGateExecutor && (!options.resumeRunId || !options.fromNodeId)) throw new Error('gate executor override requires a release resume boundary');
654
657
  if (options.releaseGatePodPool !== undefined && (!options.resumeRunId || !options.fromNodeId)) throw new Error('gate pod pool override requires a release resume boundary');
658
+ if (options.releaseGateShardReroute && (!options.resumeRunId || options.fromNodeId !== 'gate')) throw new Error('shard reroute requires release resume --from gate');
655
659
  const root = options.deps?.root ?? effectiveInstanceRoot();
656
660
  const matchingRuns = options.resumeRunId && !options.resumeGraphId
657
661
  ? listGraphRuns(root).runs.filter((run) => run.runId === options.resumeRunId && run.graphPath === resolve(path)) : [];
@@ -718,6 +722,8 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
718
722
  return existsSync(graphsDir) && graphFile.startsWith(`${realpathSync(graphsDir)}${sep}`);
719
723
  });
720
724
  const credentials = owner ? pluginEnv(owner.name, pluginRoot) : {};
725
+ const redactCredentials = (text: string) => Object.values(credentials).filter(value => value.length > 0)
726
+ .reduce((safe, value) => safe.replaceAll(value, '[REDACTED]'), text);
721
727
  const declaredEnv = [...new Set(installed.map(item => item.name))]
722
728
  .flatMap(name => credentialStatus(name, pluginRoot).fields.map(field => field.env));
723
729
  const credentialFields = owner ? credentialStatus(owner.name, pluginRoot).fields.filter(field => field.set).map(field => field.name) : [];
@@ -921,6 +927,13 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
921
927
  state.inputOverrides = [...(state.inputOverrides ?? []), override];
922
928
  debug.log('graph.runs', 'input-override', { graphId, runId, ...override });
923
929
  }
930
+ if (options.releaseGateShardReroute) {
931
+ if (graphId !== 'release-loop') throw new Error('shard reroute requires the release-loop graph');
932
+ const override = releaseResumeGateShardReroute(state, { from: options.fromNodeId, ...options.releaseGateShardReroute });
933
+ state.input = { ...(state.input as Record<string, unknown>), ...override.set };
934
+ state.inputOverrides = [...(state.inputOverrides ?? []), override];
935
+ debug.log('graph.runs', 'input-override', { graphId, runId, ...override });
936
+ }
924
937
  if (state.unitCalls) {
925
938
  const calls = state.unitCalls;
926
939
  state.unitCalls = calls.filter(call => {
@@ -1102,8 +1115,6 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
1102
1115
  mkdirSync(dirname(contextPath), { recursive: true });
1103
1116
  writeFileSync(contextPath, JSON.stringify({ graphId, runId, startedAt: state.startedAt, nodeId: current, input: state.input ?? null, outputs }, null, 2) + '\n');
1104
1117
  let code: number | null = null;
1105
- const redactCredentials = (text: string) => Object.values(credentials).filter(value => value.length > 0)
1106
- .reduce((safe, value) => safe.replaceAll(value, '[REDACTED]'), text);
1107
1118
  const runBash: BashRun = async (body, opts) => {
1108
1119
  const commandRoot = verifyReleaseSource();
1109
1120
  // Hash the actual /bin/bash argv after interpolation. Keep the command text (which may contain
@@ -1243,7 +1254,7 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
1243
1254
  log('graph.unit', { ...info, phase: 'exit', exit: childExit, steps });
1244
1255
  } catch (cause) {
1245
1256
  ok = false;
1246
- error = cause instanceof Error ? cause.message : String(cause);
1257
+ error = redactCredentials(cause instanceof Error ? cause.message : String(cause));
1247
1258
  if (entered) {
1248
1259
  debug.log('graph.unit', 'exit', { ...info, error });
1249
1260
  log('graph.unit', { ...info, phase: 'exit', error });
@@ -1326,7 +1337,16 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
1326
1337
  output = JSON.stringify({ outcome: ok ? 'approved' : 'rejected', graphId, runId, nodeId: current,
1327
1338
  ...(state.pending?.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending?.decidedAt ?? null });
1328
1339
  }
1329
- state.nodes.push({ nodeId: current, ok, exit, executed: !waiving && ((!!command && (!state.dryRun || !!command.dry_run_command)) || (!!prompt && !state.dryRun) || (node.kind === 'classify' && !state.dryRun) || unitExecuted), ...((waiving || harnessLoopRoute || units.has(current) || ((command || prompt || approval || node.kind === 'classify') && (!state.dryRun || !!command?.dry_run_command))) && output !== undefined ? { output } : {}), ...(error ? { error } : {}), ...(commandFailureReason ? { reason: commandFailureReason } : {}),
1340
+ const failureMessage = !ok
1341
+ ? redactCredentials(commandFailureReason ?? error ?? `Node ${current} failed without a diagnostic.`)
1342
+ : undefined;
1343
+ const failure = failureMessage === undefined ? undefined : {
1344
+ errorCode: error?.startsWith('unit input missing:') ? 'GRAPH_UNIT_INPUT_MISSING' : 'GRAPH_NODE_FAILED',
1345
+ message: failureMessage,
1346
+ stage: units.has(current) ? 'unit-invocation' : command ? 'command-execution' : prompt ? 'prompt-execution' : 'node-execution',
1347
+ };
1348
+ state.nodes.push({ nodeId: current, ok, exit, executed: !waiving && ((!!command && (!state.dryRun || !!command.dry_run_command)) || (!!prompt && !state.dryRun) || (node.kind === 'classify' && !state.dryRun) || unitExecuted), ...((waiving || harnessLoopRoute || units.has(current) || ((command || prompt || approval || node.kind === 'classify') && (!state.dryRun || !!command?.dry_run_command))) && output !== undefined ? { output } : {}), ...(error ? { error } : {}),
1349
+ ...(failure ? { reason: failure.message, failure } : {}), ...(commandFailureReason && !failure ? { reason: commandFailureReason } : {}),
1330
1350
  ...(waiving ? { waiver: { reason: options.releaseWaiver!.reason, at: nodeEndedAt, ...(options.releaseWaiver!.unmeasured === undefined ? {} : { unmeasured: options.releaseWaiver!.unmeasured }), original: { exit: waivedRecord!.exit, ...(waivedRecord!.output === undefined ? {} : { output: waivedRecord!.output }), ...(waivedRecord!.error === undefined ? {} : { error: waivedRecord!.error }) } } } : {}),
1331
1351
  ...(approval && state.pending ? { ...(state.pending.decidedBy === undefined ? {} : { decidedBy: state.pending.decidedBy }), decidedAt: state.pending.decidedAt } : {}),
1332
1352
  startedAt: nodeStartedAt, endedAt: nodeEndedAt, seconds });
@@ -1342,12 +1362,14 @@ export async function runGraph(path: string, options: GraphRunOptions = {}): Pro
1342
1362
  const reported: unknown = waiving || harnessLoopRoute || units.has(current) || (prompt && !state.dryRun) || (command && (!state.dryRun || command.dry_run_command)) ? lastJsonObject(resumingCompleted ? completed?.output : output)?.outcome : undefined;
1343
1363
  const namedOutcome: string | undefined = typeof reported === 'string' ? reported : undefined;
1344
1364
  if (!options.quiet) console.error(`[graph] ${current} ${ok ? 'ok' : 'fail'} (${seconds.toFixed(2)}s)`);
1365
+ const nodeFailure = state.nodes.at(-1)?.nodeId === current ? state.nodes.at(-1)?.failure : undefined;
1366
+ const nodeReason = state.nodes.at(-1)?.nodeId === current ? state.nodes.at(-1)?.reason : undefined;
1345
1367
  debug.log('graph.run', 'node', { graphId, runId, nodeId: current, phase: ok ? 'ok' : 'fail', seconds, exit,
1346
- ...(commandFailureReason ? { reason: commandFailureReason } : {}) });
1368
+ ...(nodeReason ? { reason: nodeReason } : {}), ...(nodeFailure ? { failure: nodeFailure } : {}) });
1347
1369
  publishInsideEvent({ kind: 'node', graphId, runId, nodeId: current, phase: ok ? 'ok' : 'fail', seconds });
1348
1370
  publishInsideEvent({ kind: 'verdict', graphId, runId, nodeId: current, verdict: ok ? 'ok' : 'fail', ...(namedOutcome === undefined ? {} : { outcome: namedOutcome }) });
1349
1371
  log('node-end', { graphId, runId, nodeId: current, ok, exit,
1350
- ...(commandFailureReason ? { reason: commandFailureReason } : {}),
1372
+ ...(nodeReason ? { reason: nodeReason } : {}), ...(nodeFailure ? { failure: nodeFailure } : {}),
1351
1373
  ...(namedOutcome === undefined ? {} : { outcome: namedOutcome }), dryRun: state.dryRun });
1352
1374
  if (!resumingCompleted) {
1353
1375
  // Recipe commands expose stdout/exit but no provider usage; never infer zero from success.
@@ -34,6 +34,8 @@ export interface GraphWizardRequest {
34
34
  history?: GraphWizardTurn[];
35
35
  /** Installed pack selected for a knowledge (RAG) node. */
36
36
  packId?: string;
37
+ /** Task hand composition: only existing verb units and terminal gates, never free-form commands. */
38
+ missionBase?: { id: string; text: string };
37
39
  }
38
40
 
39
41
  export interface GraphWizardResult {
@@ -653,6 +655,11 @@ function buildPrompt(input: {
653
655
  if (req.history?.length) {
654
656
  lines.push('', '지금까지의 대화:', ...req.history.slice(-10).map((t) => `${t.role === 'user' ? '사용자' : '마법사'}: ${t.text.slice(0, 500)}`));
655
657
  }
658
+ if (req.missionBase) {
659
+ lines.push('', '미션 조합: 기존 graphs/work 표준 조합의 동사 단위(subgraph call: verb-…@정수판)와 끝 gate 만 사용한다.',
660
+ 'cmd·새 권한·외부 효과를 추가하지 마라. merge 앞에는 gate·freeze-check·review 가 모든 경로에서 먼저 와야 한다.',
661
+ `표준 조합 ${req.missionBase.id}:`, '```yaml', req.missionBase.text.trim(), '```');
662
+ }
656
663
  if (editing) {
657
664
  lines.push('', '지금 그래프(이것을 고친다 — 바뀌지 않는 노드의 id 는 그대로 둔다):', '```yaml', req.currentYaml!.trim(), '```',
658
665
  '', `사용자의 수정 지시: ${req.prompt}`,
@@ -705,7 +712,7 @@ export async function generateGraphFromPrompt(req: GraphWizardRequest, deps: Gra
705
712
  let id = editing ? currentId! : wizardGraphId(prompt, undefined, taken);
706
713
  const callLLM = deps.callLLM ?? defaultCallLLM;
707
714
  const maxAttempts = Math.max(1, deps.maxAttempts ?? GRAPH_WIZARD_MAX_ATTEMPTS);
708
- let base = keywordBase?.id;
715
+ let base = req.missionBase?.id ?? keywordBase?.id;
709
716
  let yaml = '';
710
717
  let issues: string[] = [];
711
718
  let llmSummary: string | undefined;
@@ -726,7 +733,7 @@ export async function generateGraphFromPrompt(req: GraphWizardRequest, deps: Gra
726
733
  }
727
734
  if (attempts === 1 && !editing) {
728
735
  const picked = lineValue(text, 'BASE');
729
- if (picked && picked !== base && templates.some((t) => t.id === picked)) { base = picked; baseReason = `LLM 재선택 (키워드 후보 ${keywordBase?.id ?? '-'})`; }
736
+ if (!req.missionBase && picked && picked !== base && templates.some((t) => t.id === picked)) { base = picked; baseReason = `LLM 재선택 (키워드 후보 ${keywordBase?.id ?? '-'})`; }
730
737
  const slug = lineValue(text, 'SLUG');
731
738
  if (slug && !currentId) id = wizardGraphId(prompt, slug, taken);
732
739
  }
@@ -746,13 +753,15 @@ export async function generateGraphFromPrompt(req: GraphWizardRequest, deps: Gra
746
753
  recipes = undefined;
747
754
  dryRun = undefined;
748
755
  if (kind === 'harness' && issues.length === 0) {
749
- issues = stepIssues(yaml, steps);
756
+ if (!req.missionBase) issues = stepIssues(yaml, steps);
750
757
  const nodes = ((parseYaml(yaml) as { nodes?: Array<{ node_id?: unknown; recipe?: unknown }> }).nodes ?? [])
751
758
  .map((n) => ({ nodeId: String(n.node_id), recipe: typeof n.recipe === 'string' ? n.recipe : '' }));
752
- recipes = recipesYamlFor(nodes, steps);
753
- const walked = await dryRunWizardGraph(yaml, recipes);
754
- dryRun = { status: walked.status, path: walked.path };
755
- if (walked.status !== 'done') issues.push(`graph run --dry-run: ${walked.status}${walked.error ? ` — ${walked.error}` : ''} (경로 ${walked.path.join(' → ')})`);
759
+ if (!req.missionBase) {
760
+ recipes = recipesYamlFor(nodes, steps);
761
+ const walked = await dryRunWizardGraph(yaml, recipes);
762
+ dryRun = { status: walked.status, path: walked.path };
763
+ if (walked.status !== 'done') issues.push(`graph run --dry-run: ${walked.status}${walked.error ? ` — ${walked.error}` : ''} (경로 ${walked.path.join(' → ')})`);
764
+ }
756
765
  }
757
766
  debug.log('graph.wizard', 'attempt', { id, attempt: attempts, base, ok: issues.length === 0, issues: issues.slice(0, 10) });
758
767
  if (issues.length === 0) break;
@@ -0,0 +1,201 @@
1
+ import { existsSync, mkdirSync, readFileSync, readdirSync, writeFileSync } from 'node:fs';
2
+ import { dirname, join } from 'node:path';
3
+ import { parse as parseYaml } from 'yaml';
4
+ import { validateGraphYaml } from '../nexus/api/graph-kinds.js';
5
+ import { edgeMapOf, parseGraphTemplateYaml, type GraphTemplateSpec } from '../self-implement/graph-yaml.js';
6
+ import { resolveGraphUnit } from '../self-implement/graph-unit-resolver.js';
7
+ import { inspectPipelineGraph } from '../self-implement/pipeline-shape.js';
8
+ import { debug } from '../debug/log.js';
9
+ import { generateGraphFromPrompt, type GraphWizardDeps } from './generate.js';
10
+ import type { CompletionKind, CompositionSelection } from '../task-agent/task-hand.js';
11
+
12
+ export interface MissionComposeInput {
13
+ text: string;
14
+ completion: CompletionKind;
15
+ root: string;
16
+ ledgerPath: string;
17
+ cardId: string;
18
+ standard: CompositionSelection;
19
+ }
20
+
21
+ /** The LLM may choose the order of existing verb calls, but not their authority or the hand's launcher. */
22
+ export function missionGraphIssues(yaml: string, baseYaml: string, root: string, generatedPath?: string): string[] {
23
+ const checked = validateGraphYaml('harness', yaml);
24
+ const issues = checked.errors.map(error => typeof error === 'string' ? error : JSON.stringify(error));
25
+ const parsed = parseGraphTemplateYaml(yaml);
26
+ const base = parseGraphTemplateYaml(baseYaml);
27
+ issues.push(...parsed.errors.map(error => `${error.path}: ${error.message}`));
28
+ if (!parsed.template || !base.template) return issues;
29
+ const graph = parsed.template;
30
+ const standard = base.template;
31
+ const raw = parseYaml(yaml) as Record<string, unknown>;
32
+ const baseRaw = parseYaml(baseYaml) as Record<string, unknown>;
33
+ if (raw.launcher !== baseRaw.launcher) issues.push('I6: 표준 launcher 제어를 바꿀 수 없다');
34
+ for (const key of new Set([...Object.keys(baseRaw), ...Object.keys(raw)])) {
35
+ if (['graph_id', 'loop', 'nodes', 'edges'].includes(key)) continue;
36
+ if (JSON.stringify(raw[key]) !== JSON.stringify(baseRaw[key])) issues.push(`I6: 표준 제어 ${key} 변경 금지`);
37
+ }
38
+ if (raw.entry_node !== baseRaw.entry_node) issues.push('I6: 표준 진입 노드를 바꿀 수 없다');
39
+ if (JSON.stringify(raw.terminal_nodes) !== JSON.stringify(baseRaw.terminal_nodes)) issues.push('I4: 표준 종료 노드를 바꿀 수 없다');
40
+ const baseLoop = baseRaw.loop as { trigger?: unknown } | undefined;
41
+ const loop = raw.loop as { trigger?: unknown } | undefined;
42
+ if (JSON.stringify(loop?.trigger) !== JSON.stringify(baseLoop?.trigger)) issues.push('I6: 표준 트리거 변경 금지');
43
+ const rawNodes = Array.isArray(raw.nodes) ? raw.nodes as Array<Record<string, unknown>> : [];
44
+ const baseNodes = Array.isArray(baseRaw.nodes) ? baseRaw.nodes as Array<Record<string, unknown>> : [];
45
+ for (const node of rawNodes) {
46
+ const original = baseNodes.find(candidate => candidate.call && candidate.call === node.call)
47
+ ?? baseNodes.find(candidate => candidate.node_id === node.node_id && candidate.kind === 'gate');
48
+ if (!original) continue;
49
+ const keys = new Set([...Object.keys(node), ...Object.keys(original)]);
50
+ for (const key of keys) {
51
+ if (key === 'node_id' || key === 'max_visits') continue;
52
+ if (JSON.stringify(node[key]) !== JSON.stringify(original[key])) issues.push(`I6: ${String(node.node_id)} 권한 ${key} 변경 금지`);
53
+ }
54
+ }
55
+ const rawEdges = Array.isArray(raw.edges) ? raw.edges as Array<Record<string, unknown>> : [];
56
+ if (rawEdges.some(edge => Object.keys(edge).some(key => !['from', 'to', 'on', 'map'].includes(key))))
57
+ issues.push('I6: 간선 조건·폴백 권한 추가 금지');
58
+ const allowed = new Map(standard.nodes.filter(n => n.kind === 'subgraph' && n.call?.startsWith('verb-')).map(n => [n.call!, n]));
59
+ const standardById = new Map(standard.nodes.map(n => [n.nodeId, n]));
60
+ const seenCalls = new Set<string>();
61
+ for (const node of graph.nodes) {
62
+ const original = standardById.get(node.nodeId);
63
+ if (!original && /(?:merge|publish|send|pay|charge|deploy|release)/i.test(`${node.nodeId} ${node.call ?? ''}`))
64
+ issues.push(`I5: 외부 효과 동사 추가 금지 (${node.nodeId})`);
65
+ if (original?.kind === 'gate' && node.kind === 'gate'
66
+ && JSON.stringify(node) === JSON.stringify(original)) continue;
67
+ const known = node.kind === 'subgraph' && node.call ? allowed.get(node.call) : undefined;
68
+ if (!known || node.recipe !== 'none' || node.maxVisits > known.maxVisits
69
+ || JSON.stringify(node.contract) !== JSON.stringify(known.contract)
70
+ || JSON.stringify(node.budget) !== JSON.stringify(known.budget)
71
+ || node.skipWhen !== undefined || node.callEntry !== undefined)
72
+ issues.push(`권한 표: ${node.nodeId} 는 허용된 동사 단위가 아니다`);
73
+ if (node.call) seenCalls.add(node.call);
74
+ }
75
+ for (const call of allowed.keys()) if (!seenCalls.has(call)) issues.push(`권한 표: 표준 동사 단위 ${call} 누락`);
76
+ for (const required of standard.nodes.filter(n => n.kind === 'gate' || ['gate', 'freeze-check', 'review'].includes(n.nodeId))) {
77
+ if (!graph.nodes.some(n => n.nodeId === required.nodeId && JSON.stringify(n) === JSON.stringify(required))) issues.push(`권한 표: 보호 노드 ${required.nodeId} 누락 또는 변경`);
78
+ }
79
+ for (const terminal of standard.terminalNodes) if (!graph.terminalNodes.includes(terminal)) issues.push(`I4: 종료 ${terminal} 누락`);
80
+ const edges = edgeMapOf(graph);
81
+ issues.push(...inspectPipelineGraph(edges, graph.entryNode).map(defect => `I4: ${JSON.stringify(defect)}`));
82
+ for (const node of graph.nodes) {
83
+ const reachable = new Set<string>();
84
+ const queue = [node.nodeId];
85
+ while (queue.length) {
86
+ const id = queue.shift()!;
87
+ if (reachable.has(id)) continue;
88
+ reachable.add(id);
89
+ queue.push(...(edges[id] ?? []));
90
+ }
91
+ if (![...reachable].some(id => graph.terminalNodes.includes(id))) issues.push(`I4: ${node.nodeId} 에서 종료 불가`);
92
+ }
93
+ const mergeNodes = graph.nodes.filter(n => n.nodeId.includes('merge') || n.call?.includes('merge'));
94
+ for (const merge of mergeNodes) {
95
+ const prerequisites = ['gate', 'freeze-check', 'review'];
96
+ const walk = (id: string, seen: Set<string>, met: Set<string>): void => {
97
+ if (id === merge.nodeId) {
98
+ for (const required of prerequisites) if (!met.has(required)) issues.push(`I1~I3: merge 앞 ${required} 없음`);
99
+ return;
100
+ }
101
+ if (seen.has(id)) return;
102
+ const nextMet = new Set(met);
103
+ if (prerequisites.includes(id)) nextMet.add(id);
104
+ const nextSeen = new Set(seen).add(id);
105
+ for (const target of edges[id] ?? []) walk(target, nextSeen, nextMet);
106
+ };
107
+ walk(graph.entryNode, new Set(), new Set());
108
+ }
109
+ for (const node of graph.nodes.filter(n => n.kind === 'subgraph')) {
110
+ if (!node.call || !allowed.has(node.call)) continue;
111
+ try {
112
+ const canonical = resolveGraphUnit(node.call, join(root, 'graphs/work', 'generated.yaml'));
113
+ const actual = resolveGraphUnit(node.call, generatedPath ?? join(root, 'graphs/work', 'generated.yaml'));
114
+ const unit = actual.template;
115
+ if (actual.hash !== canonical.hash || `${unit.graphId}@${unit.version}` !== node.call || !unit.unit ||
116
+ JSON.stringify(unit.unit.inputs) !== JSON.stringify(node.contract?.inputs) ||
117
+ JSON.stringify(unit.unit.outputs) !== JSON.stringify(node.contract?.outputs)) issues.push(`권한 표: 동사 단위 미해석 ${node.call}`);
118
+ } catch { issues.push(`권한 표: 동사 단위 미해석 ${node.call}`); }
119
+ }
120
+ return [...new Set(issues)];
121
+ }
122
+
123
+ export async function composeMissionGraph(input: MissionComposeInput, deps: Pick<GraphWizardDeps, 'callLLM'> & { deferPersistence?: boolean } = {}): Promise<{
124
+ selection: CompositionSelection; reason: string; persist: () => void;
125
+ }> {
126
+ const fallback = input.standard;
127
+ let files: string[] = [];
128
+ try { files = readdirSync(join(input.root, 'graphs/work')).filter(name => name.endsWith('.yaml') && name !== 'recipes.yaml'); }
129
+ catch { /* The fixed selection already carries the missing or unreadable-template reason. */ }
130
+ const candidates = files.flatMap(file => {
131
+ const path = join(input.root, 'graphs/work', file);
132
+ try {
133
+ const yaml = readFileSync(path, 'utf8');
134
+ const parsed = parseGraphTemplateYaml(yaml, path);
135
+ return parsed.template && !parsed.errors.length && (parseYaml(yaml) as { launcher?: unknown }).launcher
136
+ ? [{ file: `graphs/work/${file}`, yaml, template: parsed.template }] : [];
137
+ } catch { return []; }
138
+ });
139
+ const standardFile = fallback.composition?.file;
140
+ const words = input.text.toLowerCase().match(/[\p{L}\p{N}]+/gu) ?? [];
141
+ const score = (item: { file: string; template: GraphTemplateSpec }) => {
142
+ const label = `${item.file} ${item.template.graphId} ${item.template.loop?.title ?? ''} ${item.template.loop?.description ?? ''}`.toLowerCase();
143
+ return words.reduce((total, word) => total + (word.length > 1 && label.includes(word) ? 1 : 0), 0);
144
+ };
145
+ const standardLauncher = standardFile ? candidates.find(item => item.file === standardFile) : undefined;
146
+ const compatible = candidates.filter(item => (parseYaml(item.yaml) as { launcher: unknown }).launcher ===
147
+ (standardLauncher ? (parseYaml(standardLauncher.yaml) as { launcher: unknown }).launcher : undefined)
148
+ && item.template.nodes.every(node => node.kind === 'gate' || node.kind === 'subgraph' && node.call?.startsWith('verb-')));
149
+ const base = compatible.sort((a, b) => score(b) - score(a) || Number(b.file === standardFile) - Number(a.file === standardFile))[0];
150
+ const prefix = base ? `문면 선택 ${base.file} (일치 ${score(base)})` : '표준 조합 없음';
151
+ let generated = '';
152
+ let issues: string[] = [];
153
+ let selection = fallback;
154
+ if (base && base.file !== standardFile && fallback.launcher === 'graph-run' && !fallback.error) {
155
+ const missingUnits: string[] = [];
156
+ const { validateUnitCalls } = await import('../graph-runner/runner.js');
157
+ try { validateUnitCalls(base.template, join(input.root, base.file), [], call => missingUnits.push(call)); }
158
+ catch (error) { issues.push(`표준 조합 단위 해석 오류: ${error instanceof Error ? error.message : String(error)}`); }
159
+ if (!issues.length && !missingUnits.length) selection = {
160
+ composition: { file: base.file, version: base.template.version }, launcher: 'graph-run', unitsResolved: true, missingUnits: [],
161
+ };
162
+ else if (missingUnits.length) issues.push(`표준 조합 단위 미해석: ${missingUnits.join(', ')}`);
163
+ }
164
+ if (base && selection.composition && !selection.error && !issues.length &&
165
+ (base.file === standardFile || selection.launcher === 'graph-run')) {
166
+ try {
167
+ const proposal = await generateGraphFromPrompt({ prompt: input.text, kind: 'harness', missionBase: { id: base.template.graphId, text: base.yaml } },
168
+ { callLLM: deps.callLLM, graphsDir: join(input.root, 'graphs'), existingIds: () => new Set(), maxAttempts: 1 });
169
+ generated = proposal.yaml;
170
+ const launcher = (parseYaml(base.yaml) as { launcher: string }).launcher;
171
+ if (!(parseYaml(generated) as { launcher?: unknown }).launcher)
172
+ generated = generated.replace(/^(graph_id:\s*[^\n]+\n)/, `$1launcher: ${launcher}\n`);
173
+ issues = missionGraphIssues(generated, base.yaml, input.root,
174
+ join(dirname(input.ledgerPath), `${input.cardId}.generated.yaml`));
175
+ if (!proposal.ok) issues.push(...proposal.issues);
176
+ if (launcher !== 'graph-run') issues.push('권한 표: harness-say 는 생성된 graph-run 조합으로 전환할 수 없다');
177
+ const directory = dirname(input.ledgerPath);
178
+ const recipePath = join(directory, 'recipes.yaml');
179
+ if (existsSync(recipePath) && readFileSync(recipePath, 'utf8') !== readFileSync(join(input.root, 'graphs/work/recipes.yaml'), 'utf8'))
180
+ issues.push('권한 표: 원장 옆 recipes.yaml 이 표준과 다르다');
181
+ if (!issues.length) {
182
+ const target = join(dirname(input.ledgerPath), `${input.cardId}.generated.yaml`);
183
+ selection = { composition: { file: target, version: parseGraphTemplateYaml(generated).template!.version },
184
+ launcher: launcher as 'graph-run' | 'harness-say', unitsResolved: true, missingUnits: [] };
185
+ }
186
+ } catch (error) { issues.push(`생성 실패: ${error instanceof Error ? error.message : String(error)}`); }
187
+ } else if (!issues.length) issues.push('표준 조합을 읽을 수 없다');
188
+ const reason = issues.length ? `${prefix} → fallback-standard: ${issues.join('; ')}` : `${prefix} → composed: 동사 단위 검증 통과`;
189
+ const persist = (): void => {
190
+ const directory = dirname(input.ledgerPath);
191
+ mkdirSync(directory, { recursive: true });
192
+ if (generated) writeFileSync(join(directory, `${input.cardId}.generated.yaml`), generated);
193
+ if (selection.composition?.file === join(directory, `${input.cardId}.generated.yaml`) && !existsSync(join(directory, 'recipes.yaml')))
194
+ writeFileSync(join(directory, 'recipes.yaml'), readFileSync(join(input.root, 'graphs/work/recipes.yaml'), 'utf8'), { flag: 'wx' });
195
+ writeFileSync(join(directory, `${input.cardId}.composition.json`), JSON.stringify({ base: base?.file ?? null,
196
+ selected: selection.composition?.file ?? null, reason, issues, generated: generated ? `${input.cardId}.generated.yaml` : null }));
197
+ };
198
+ if (!deps.deferPersistence) persist();
199
+ debug.log('graph.compose', issues.length ? 'fallback-standard' : 'composed', { card: input.cardId, base: base?.file ?? null, reason });
200
+ return { selection, reason, persist };
201
+ }