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
@@ -2,6 +2,7 @@
2
2
  import { lstatSync, readFileSync, realpathSync, readdirSync, statSync } from 'node:fs';
3
3
  import { createHash } from 'node:crypto';
4
4
  import { join, relative, resolve, sep } from 'node:path';
5
+ import { parse as parseYaml } from 'yaml';
5
6
 
6
7
  export const KNOWHOW_PACK_MAX_BYTES = 4096;
7
8
  const MARKER = '[KNOWHOW-PACK v1';
@@ -12,6 +13,120 @@ export interface KnowhowPack {
12
13
  ids: string[];
13
14
  bytes: number;
14
15
  reason: 'selected' | 'marker-present' | 'source-unreadable' | 'no-promoted-section' | 'no-path-overlap' | 'over-budget';
16
+ sources?: Array<{ kind: 'goal' | 'blueprint'; path: string; bytes: number }>;
17
+ knowhowReason?: KnowhowPack['reason'];
18
+ }
19
+
20
+ export interface StartupBlueprintOptions { readonly goalFile?: string | null }
21
+
22
+ interface StartupSections { readonly text: string; readonly sources: Array<{ kind: 'goal' | 'blueprint'; path: string; bytes: number }> }
23
+
24
+ function safeRepositoryFile(root: string, path: string): { path: string; relativePath: string; text: string; bytes: number } | null {
25
+ try {
26
+ const repo = realpathSync(root);
27
+ const absolute = resolve(root, path);
28
+ if (lstatSync(absolute).isSymbolicLink()) return null;
29
+ const real = realpathSync(absolute);
30
+ if (!inside(repo, real) || !statSync(real).isFile() || statSync(real).size > 200_000) return null;
31
+ const text = readFileSync(real, 'utf8');
32
+ return { path: real, relativePath: relative(repo, real).split(sep).join('/'), text, bytes: Buffer.byteLength(text, 'utf8') };
33
+ } catch { return null; }
34
+ }
35
+
36
+ function yamlFiles(root: string): string[] {
37
+ try {
38
+ return readdirSync(root, { withFileTypes: true }).sort((a, b) => a.name.localeCompare(b.name)).flatMap((entry) => {
39
+ const path = join(root, entry.name);
40
+ if (entry.isSymbolicLink()) return [];
41
+ if (entry.isDirectory()) return yamlFiles(path);
42
+ return entry.isFile() && /\.ya?ml$/u.test(entry.name) ? [path] : [];
43
+ });
44
+ } catch { return []; }
45
+ }
46
+
47
+ function yamlObject(text: string): Record<string, unknown> | null {
48
+ try {
49
+ const value: unknown = parseYaml(text);
50
+ return value && typeof value === 'object' && !Array.isArray(value) ? value as Record<string, unknown> : null;
51
+ } catch { return null; }
52
+ }
53
+
54
+ function sourcePaths(value: unknown): string[] {
55
+ if (typeof value === 'string') return [value];
56
+ if (Array.isArray(value)) return value.flatMap(sourcePaths);
57
+ if (value && typeof value === 'object') return Object.values(value).flatMap(sourcePaths);
58
+ return [];
59
+ }
60
+
61
+ function startupSections(repo: string, goal: string, options?: StartupBlueprintOptions): StartupSections {
62
+ if (!options) return { text: '', sources: [] };
63
+ if (!options.goalFile?.trim()) return { text: '## GOAL DOCUMENT\nreason=goal-document-not-configured\n\n## GRAPH BLUEPRINT\nreason=goal-document-unavailable\n', sources: [] };
64
+ const goalFile = safeRepositoryFile(repo, options.goalFile);
65
+ if (!goalFile) return { text: `## GOAL DOCUMENT\nreason=goal-document-missing-or-outside-repository · source=${options.goalFile}\n\n## GRAPH BLUEPRINT\nreason=goal-document-unavailable\n`, sources: [] };
66
+
67
+ const allTargets = new Set([...mentionedPaths(goal), ...mentionedPaths(goalFile.text)]);
68
+ const root = realpathSync(repo);
69
+ const unitById = new Map<string, { relativePath: string; bytes: number; raw: string; doc: Record<string, unknown> }>();
70
+ for (const path of yamlFiles(join(root, 'graphs/units'))) {
71
+ const file = safeRepositoryFile(root, path);
72
+ if (!file) continue;
73
+ const doc = yamlObject(file.text);
74
+ if (typeof doc?.graph_id !== 'string') continue;
75
+ unitById.set(doc.graph_id, { relativePath: file.relativePath, bytes: file.bytes, raw: file.text, doc });
76
+ }
77
+ const relevant = new Set<string>();
78
+ for (const [id, unit] of unitById) {
79
+ const declared = sourcePaths(unit.doc.source);
80
+ const paths = declared.length ? declared : [...mentionedPaths(unit.raw)];
81
+ if (paths.some((source) => [...allTargets].some((target) => target === source || target.startsWith(`${source.replace(/\/$/u, '')}/`) || source.startsWith(`${target.replace(/\/$/u, '')}/`)))) relevant.add(id);
82
+ }
83
+
84
+ const chains = new Map<string, { rootId: string; paths: string[]; calls: string[] }>();
85
+ const graphFiles = yamlFiles(join(root, 'graphs/work'));
86
+ for (const path of graphFiles) {
87
+ const file = safeRepositoryFile(root, path);
88
+ if (!file) continue;
89
+ const rootDoc = yamlObject(file.text);
90
+ if (!rootDoc || typeof rootDoc.graph_id !== 'string' || !Array.isArray(rootDoc.nodes)) continue;
91
+ const visit = (doc: Record<string, unknown>, chainIds: string[], chainPaths: string[], calls: string[], ancestors: string[]): void => {
92
+ if (chainIds.length > 5) return;
93
+ for (const node of Array.isArray(doc.nodes) ? doc.nodes : []) {
94
+ if (!node || typeof node !== 'object' || Array.isArray(node)) continue;
95
+ const entry = node as Record<string, unknown>;
96
+ if (typeof entry.call !== 'string') continue;
97
+ const id = entry.call.split('@')[0]!;
98
+ const unit = unitById.get(id);
99
+ if (!unit || ancestors.includes(id)) continue;
100
+ const nextIds = [...chainIds, id];
101
+ const nextPaths = [...chainPaths, unit.relativePath];
102
+ const nextCalls = [...calls, typeof entry.node_id === 'string' ? entry.node_id : id];
103
+ if (relevant.has(id)) chains.set(`${file.relativePath}\0${nextIds.join(' → ')}`, { rootId: String(rootDoc.graph_id), paths: [file.relativePath, ...nextPaths], calls: nextCalls });
104
+ visit(unit.doc, nextIds, nextPaths, nextCalls, [...ancestors, id]);
105
+ }
106
+ };
107
+ visit(rootDoc, [], [], [], []);
108
+ }
109
+
110
+ const sources: StartupSections['sources'] = [{ kind: 'goal', path: goalFile.relativePath, bytes: goalFile.bytes }];
111
+ const maxGoalBytes = 2_200;
112
+ const goalText = goalFile.text.includes(MARKER)
113
+ ? '[goal document omitted; reason=knowhow-marker-already-present]'
114
+ : `${utf8Prefix(goalFile.text, maxGoalBytes)}${goalFile.bytes > maxGoalBytes ? `\n[goal document truncated; source bytes=${goalFile.bytes}]` : ''}`;
115
+ let text = `## GOAL DOCUMENT\nsource=${goalFile.relativePath} · bytes=${goalFile.bytes}\n${goalText.trim()}\n`;
116
+ if (!chains.size) {
117
+ text += `\n## GRAPH BLUEPRINT\nreason=no-related-blueprint · targetPaths=${allTargets.size}\n`;
118
+ } else {
119
+ text += '\n## GRAPH BLUEPRINT\n';
120
+ for (const [key, detail] of [...chains].sort(([a], [b]) => a.localeCompare(b))) {
121
+ const chain = key.slice(key.indexOf('\0') + 1);
122
+ const pathDetails = detail.paths.map((sourcePath) => safeRepositoryFile(root, sourcePath)).filter((item): item is NonNullable<typeof item> => item !== null);
123
+ if (!pathDetails.length) continue;
124
+ for (const source of pathDetails) sources.push({ kind: 'blueprint', path: source.relativePath, bytes: source.bytes });
125
+ text += `- ${detail.rootId} → ${chain}; calls=${detail.calls.join(' → ')}; sources=${pathDetails.map((item) => `${item.relativePath}(${item.bytes}B)`).join(', ')}\n`;
126
+ }
127
+ if (sources.length === 1) text += `reason=no-related-blueprint · targetPaths=${allTargets.size}\n`;
128
+ }
129
+ return { text, sources };
15
130
  }
16
131
 
17
132
  export interface SelectedAuthoringLessons {
@@ -60,15 +175,15 @@ function authoringAskPaths(ask: string): string[] {
60
175
  }
61
176
 
62
177
  /** Select up to two relevant lessons, capped by rendered prompt size. Bad optional ledgers only emit observation. */
63
- export function selectRelevantAuthoringLessons(root: string, ask: string): SelectedAuthoringLessons {
178
+ export function selectRelevantAuthoringLessons(root: string, ask: string, feedbackStateDir?: string): SelectedAuthoringLessons {
64
179
  const path = join(root, 'docs', 'goal-context', '05-authoring-lessons.jsonl');
65
- let source: string;
180
+ let source = '';
181
+ let sourceStatus: SelectedAuthoringLessons['status'] = 'loaded';
66
182
  try { source = readFileSync(path, 'utf8'); }
67
- catch (error) {
68
- return { ids: [], prompt: '', status: (error as NodeJS.ErrnoException).code === 'ENOENT' ? 'missing' : 'unreadable', invalidRows: 0 };
69
- }
183
+ catch (error) { sourceStatus = (error as NodeJS.ErrnoException).code === 'ENOENT' ? 'missing' : 'unreadable'; }
70
184
  const rows: Record<string, unknown>[] = [];
71
185
  let invalidRows = 0;
186
+ let malformed = false;
72
187
  for (const line of source.split(/\r?\n/u)) {
73
188
  if (!line.trim()) continue;
74
189
  try {
@@ -82,10 +197,42 @@ export function selectRelevantAuthoringLessons(root: string, ask: string): Selec
82
197
  rows.push(row);
83
198
  } catch {
84
199
  invalidRows += 1;
85
- return { ids: [], prompt: '', status: 'malformed', invalidRows };
200
+ malformed = true;
201
+ continue;
86
202
  }
87
203
  }
88
- if (rows.length === 0) return { ids: [], prompt: '', status: 'empty', invalidRows };
204
+ // Landed implementation feedback lives in the operational run ledger. Read it as
205
+ // additive authoring context so the next related goal actually receives the findings.
206
+ try {
207
+ const ledgerDir = feedbackStateDir ? join(feedbackStateDir, 'run-ledger') : undefined;
208
+ if (!ledgerDir) throw new Error('feedback source not enabled');
209
+ const feedbackFiles = readdirSync(ledgerDir).filter((name) => name.endsWith('.jsonl')).sort().slice(-128);
210
+ for (const file of feedbackFiles) {
211
+ const filePath = join(ledgerDir, file);
212
+ if (statSync(filePath).size > 256_000) continue;
213
+ const lines = readFileSync(filePath, 'utf8').split(/\r?\n/u);
214
+ for (const line of lines) {
215
+ if (!line.trim()) continue;
216
+ try {
217
+ const entry = JSON.parse(line) as Record<string, unknown>;
218
+ if (entry.event !== 'impl-findings-feedback' || !entry.data || typeof entry.data !== 'object') continue;
219
+ const data = entry.data as Record<string, unknown>;
220
+ const paths = Array.isArray(data.paths) ? data.paths.filter((value): value is string => typeof value === 'string') : [];
221
+ if (!paths.length) continue;
222
+ const requirements = typeof data.requirements === 'string' ? data.requirements.trim() : '';
223
+ const newScope = typeof data.newScope === 'string' ? data.newScope.trim() : '';
224
+ const remaining = Array.isArray(data.remaining) ? data.remaining.filter((value): value is string => typeof value === 'string') : [];
225
+ const lesson = [
226
+ ...(requirements ? [`구현이 밝힌 요구사항: ${requirements}`] : []),
227
+ ...(newScope ? [`새 범위: ${newScope}`] : []),
228
+ ...remaining.map((item) => `남은 것: ${item}`),
229
+ ].join(' · ');
230
+ if (lesson) rows.push({ id: `IF-${String(data.prNumber ?? 'unknown')}`, class: 'f-unaware-of-code', lesson, paths: paths.join(' · '), cell: `PR #${String(data.prNumber ?? '?')}` });
231
+ } catch { invalidRows += 1; }
232
+ }
233
+ }
234
+ } catch { /* Optional, explicit operational feedback source may not exist or be readable. */ }
235
+ if (rows.length === 0) return { ids: [], prompt: '', status: malformed ? 'malformed' : sourceStatus === 'loaded' ? 'empty' : sourceStatus, invalidRows };
89
236
  const targetPaths = authoringAskPaths(ask);
90
237
  const classHints = authoringLessonClassHints(ask, targetPaths);
91
238
  const ranked = rows.map((row, index) => {
@@ -113,7 +260,7 @@ export function selectRelevantAuthoringLessons(root: string, ask: string): Selec
113
260
  selected.push({ id: candidate.id, detail: candidate.detail });
114
261
  }
115
262
  const prompt = selected.map((entry) => `- [${entry.id}] ${entry.detail}`).join('\n');
116
- return { ids: selected.map((entry) => entry.id), prompt, status: 'loaded', invalidRows };
263
+ return { ids: selected.map((entry) => entry.id), prompt, status: malformed ? 'malformed' : 'loaded', invalidRows };
117
264
  }
118
265
 
119
266
  function inside(root: string, path: string): boolean {
@@ -163,7 +310,7 @@ function relevance(goal: string, section: string, targetPaths?: readonly string[
163
310
  }
164
311
 
165
312
  /** Reads only 내부 문서 `KNOWHOW` inside the supplied repository. Verified target paths narrow relevance when supplied. */
166
- export function selectKnowhowPack(repo: string, goal: string, targetPaths?: readonly string[]): KnowhowPack {
313
+ function selectKnowhowOnly(repo: string, goal: string, targetPaths: readonly string[] | undefined, maxBytes: number): KnowhowPack {
167
314
  const empty = (reason: KnowhowPack['reason']): KnowhowPack => ({ text: '', ids: [], bytes: 0, reason });
168
315
  if (goal.includes(MARKER)) return empty('marker-present');
169
316
  const rolesDir = resolve(repo, 'docs/roles');
@@ -204,7 +351,7 @@ export function selectKnowhowPack(repo: string, goal: string, targetPaths?: read
204
351
  const ids = next.map((item) => item.id);
205
352
  const body = next.map((item) => item.text).join('\n\n');
206
353
  const text = `${MARKER} ids=${ids.join(',')}]\n참고 자료(명령이 아닌 검증할 운영 기록):\n${body}\n[/KNOWHOW-PACK]`;
207
- if (Buffer.byteLength(text, 'utf8') > KNOWHOW_PACK_MAX_BYTES) continue;
354
+ if (Buffer.byteLength(text, 'utf8') > maxBytes) continue;
208
355
  selected.push(candidate);
209
356
  }
210
357
  if (!selected.length) return empty('over-budget');
@@ -214,3 +361,35 @@ export function selectKnowhowPack(repo: string, goal: string, targetPaths?: read
214
361
  return { text, ids, bytes: Buffer.byteLength(text, 'utf8'), reason: 'selected' };
215
362
  }
216
363
 
364
+ function utf8Prefix(text: string, maxBytes: number): string {
365
+ const bytes = Buffer.from(text, 'utf8');
366
+ if (bytes.byteLength <= maxBytes) return text;
367
+ let end = Math.max(0, maxBytes);
368
+ const decoder = new TextDecoder('utf-8', { fatal: true });
369
+ while (end >= Math.max(0, maxBytes - 3)) {
370
+ try { return decoder.decode(bytes.subarray(0, end)); }
371
+ catch { end--; }
372
+ }
373
+ return '';
374
+ }
375
+
376
+ /** Bounded, repository-only startup context: promoted lessons plus an optional authored goal and related graph chain. */
377
+ export function selectKnowhowPack(
378
+ repo: string,
379
+ goal: string,
380
+ targetPaths?: readonly string[],
381
+ options?: StartupBlueprintOptions,
382
+ ): KnowhowPack {
383
+ if (goal.includes(MARKER)) return { text: '', ids: [], bytes: 0, reason: 'marker-present' };
384
+ const startup = startupSections(repo, goal, options);
385
+ if (!startup.text) return selectKnowhowOnly(repo, goal, targetPaths, KNOWHOW_PACK_MAX_BYTES);
386
+
387
+ // Goal and graph context have priority; promoted lessons use only the bytes left in the shared hard cap.
388
+ const startupText = utf8Prefix(startup.text, KNOWHOW_PACK_MAX_BYTES - 1_200);
389
+ const startupBytes = Buffer.byteLength(startupText, 'utf8');
390
+ const knowhow = selectKnowhowOnly(repo, goal, targetPaths, Math.max(0, KNOWHOW_PACK_MAX_BYTES - startupBytes - 2));
391
+ const text = `${startupText}${knowhow.text ? `\n${knowhow.text}` : ''}`;
392
+ const bytes = Buffer.byteLength(text, 'utf8');
393
+ return { text, ids: knowhow.ids, bytes, reason: text ? 'selected' : knowhow.reason, knowhowReason: knowhow.reason, sources: startup.sources };
394
+ }
395
+
@@ -563,3 +563,127 @@ export function coverRequiredEvidence(
563
563
  uncoveredCount: uncovered.length,
564
564
  };
565
565
  }
566
+
567
+ // ── TDD 를 로직으로 (S4 · 대표 10-26 20:5x «쪼개기·TDD 가 로직에 박혀 있나») ──────
568
+ //
569
+ // ⛔ **왜 필요한가** — 조각 골(device-first)은 «검증 계획(TDD)» 문면만 조립하고, 사후 판정은
570
+ // 증거 명령이 덮였는지만 본다(required-evidence-uncovered). ⇒ 자식이 **시험을 먼저 쓰고 구현 전에
571
+ // RED 를 확인했는지**를 검사하는 경로가 전혀 없다. TDD 가 문면 요청으로만 존재한다.
572
+ // ⇒ 오케스트레이터가 **첫 조각 커밋에 피처 시험·구현 전 실행 RED 기록**을 요구하고
573
+ // **구현 뒤 같은 명령의 GREEN 기록**을 요구한다. 판정은 기존 태그 동등 문법과 같다:
574
+ // 자식은 `EVIDENCE: [tdd-red] … || <명령>` ⊕ `RESULT: <실패>` ·
575
+ // `EVIDENCE: [tdd-green] … || <같은 명령>` ⊕ `RESULT: <통과>` 를 남긴다.
576
+
577
+ /** 자식이 남겨야 하는 TDD 증거 태그. ⛔ 판정은 **태그 동등**이다(해석 금지). */
578
+ export const TDD_RED_TAG = 'tdd-red';
579
+ export const TDD_GREEN_TAG = 'tdd-green';
580
+ export type TddRecordTag = typeof TDD_RED_TAG | typeof TDD_GREEN_TAG;
581
+
582
+ /** 골 문서의 «검증 계획(TDD)» 절 형식(완료 경계 증거 명령이 골 문서가 아니라 조각 계획에 박혀 있다). */
583
+ const TDD_PLAN_HEADING = /^#{2,3}\s*검증\s*계획\s*\(TDD\)\s*$/iu;
584
+ const TDD_RED_PLAN_PREFIX = /^[-*]\s*③\s*먼저\s*쓸\s*시험\(RED\)\s*:\s*/u;
585
+ const TDD_GREEN_PLAN_PREFIX = /^[-*]\s*④\s*GREEN\s*뒤\s*같은\s*명령\s*:\s*/u;
586
+ /** device-first 조각 계획의 한 줄 형식 — «피처 시험 bun test <경로>» 를 같은 명령으로 잡는다. 경로 토큰 경계([\\w./-]) 로 조사·역따옴표를 삼키지 않는다. */
587
+ const TDD_PLAN_INLINE = /(?:--test-)?bun(?:x)?\s+test\s+(?:src|test)\/[\w./-]+/iu;
588
+ /** `RESULT:` 한 줄이 통과 기록인가 — 기존 bun test 판정 문법(`0 fail`)과 같은 신호. */
589
+ const TDD_PASS_RESULT = /(?:^|\s)0\s+fail/iu;
590
+
591
+ export interface TddPlan {
592
+ readonly planned: boolean;
593
+ /** ③ 먼저 쓸 시험(RED) 문면(앞뒤 공백만 정리). */
594
+ readonly redStage: string | undefined;
595
+ /** ④ GREEN 뒤 같은 명령(예: `bun test <대상>.test.ts`). */
596
+ readonly greenCommand: string | undefined;
597
+ }
598
+
599
+ /** 골 문서에서 «검증 계획(TDD)» 절을 읽는다. **순수** — 절이 없으면 `planned: false`(추측 금지). */
600
+ export function tddPlanFromGoal(goal: string): TddPlan {
601
+ const lines = goal.split(/\r?\n/);
602
+ const headingIndex = lines.findIndex((line) => TDD_PLAN_HEADING.test(line.trim()));
603
+ if (headingIndex >= 0) {
604
+ const section: string[] = [];
605
+ for (const line of lines.slice(headingIndex + 1)) {
606
+ const text = line.trim();
607
+ // ⛔ 다음 절 제목(`#`·`###` 도 절이다)에서 멈춘다 — requiredEvidenceFromGoal 과 같은 규율.
608
+ if (/^#{1,6}\s/.test(text)) break;
609
+ section.push(text);
610
+ }
611
+ const redStage = section.find((line) => TDD_RED_PLAN_PREFIX.test(line))
612
+ ?.replace(TDD_RED_PLAN_PREFIX, '').trim() || undefined;
613
+ const greenBody = section.find((line) => TDD_GREEN_PLAN_PREFIX.test(line))
614
+ ?.replace(TDD_GREEN_PLAN_PREFIX, '').trim();
615
+ const greenCommand = greenBody ? TDD_PLAN_INLINE.exec(greenBody)?.[0]?.trim() : undefined;
616
+ return { planned: true, redStage, greenCommand: greenCommand || undefined };
617
+ }
618
+ // device-first 조각 계획의 한 줄 형식 — «검증 계획(TDD): … 피처 시험 bun test <경로> …».
619
+ const inlineLine = lines.find((line) => /검증\s*계획\s*\(TDD\)\s*:\s*\S/u.test(line) && TDD_PLAN_INLINE.test(line));
620
+ const greenCommand = inlineLine ? TDD_PLAN_INLINE.exec(inlineLine)?.[0]?.trim() : undefined;
621
+ if (!greenCommand) return { planned: false, redStage: undefined, greenCommand: undefined };
622
+ return { planned: true, redStage: undefined, greenCommand };
623
+ }
624
+
625
+ export interface TddEvidenceRecord {
626
+ readonly tag: TddRecordTag;
627
+ /** 자식이 남긴 `EVIDENCE: [tag] …` 한 건(태그를 떼지 않는다). */
628
+ readonly claim: string;
629
+ /** 재현 명령. 없으면 기록이 아니다(기존 파서 규율과 같다). */
630
+ readonly verify: string | undefined;
631
+ /** 바로 다음 `RESULT:` 줄 — RED 는 실패 기록, GREEN 은 통과 기록이어야 한다. */
632
+ readonly result: string | undefined;
633
+ readonly observed: boolean;
634
+ }
635
+
636
+ export interface TddEvidenceJudgment {
637
+ readonly planned: boolean;
638
+ readonly red: TddEvidenceRecord;
639
+ readonly green: TddEvidenceRecord;
640
+ /** RED·GREEN 이 **같은 증거 명령**인가 — «GREEN 뒤 같은 명령» 계약의 판정. */
641
+ readonly sameCommand: boolean;
642
+ /** 결손 태그(관측·수리 지시의 원천). */
643
+ readonly missing: readonly TddRecordTag[];
644
+ /** 계획이 있는데 결손이 있다 — 오케스트레이터가 수리 라운드를 돌린다. */
645
+ readonly needsRepair: boolean;
646
+ }
647
+
648
+ /** 자식 기록 한 건의 태그를 뗀다 — coverRequiredEvidence 와 같은 문법. */
649
+ function tddClaimTag(claim: string): string | undefined {
650
+ return claim.match(/^\s*\[([^\]]+)\]/)?.[1]?.trim() || undefined;
651
+ }
652
+
653
+ /** 태그 하나에 대한 자식 기록을 판정한다. RED 는 실패 기록(`0 fail` 없음), GREEN 은 통과 기록이다. */
654
+ function tddRecordFromItems(items: readonly OffDiffEvidenceParse['items'][number][], tag: TddRecordTag): TddEvidenceRecord {
655
+ const item = items.find((candidate) => tddClaimTag(candidate.claim) === tag);
656
+ if (!item) return { tag, claim: '', verify: undefined, result: undefined, observed: false };
657
+ const verify = item.verify.trim() || undefined;
658
+ const result = item.result?.trim() || undefined;
659
+ const resultPasses = result !== undefined && TDD_PASS_RESULT.test(result);
660
+ const observed = tag === TDD_RED_TAG
661
+ ? verify !== undefined && result !== undefined && !resultPasses
662
+ : verify !== undefined && result !== undefined && resultPasses;
663
+ return { tag, claim: item.claim, verify, result, observed };
664
+ }
665
+
666
+ /**
667
+ * ★ TDD 를 로직으로 판정한다. **순수**.
668
+ *
669
+ * 판정은 셋이다: ① 골이 «검증 계획(TDD)» 을 계획했는가 ② 자식이 [tdd-red] RED 기록(구현 전 실패)을
670
+ * 남겼는가 ③ [tdd-green] GREEN 기록(구현 뒤 **같은 명령** 통과)을 남겼는가. 셋째는 문면이 아니라
671
+ * **명령 동등**으로 판정한다 — RED 의 명령과 GREEN 의 명령이 문자열로 같아야 한다.
672
+ */
673
+ export function judgeTddEvidence(goal: string, evidence: OffDiffEvidenceParse): TddEvidenceJudgment {
674
+ const plan = tddPlanFromGoal(goal);
675
+ const red = tddRecordFromItems(evidence.items, TDD_RED_TAG);
676
+ const green = tddRecordFromItems(evidence.items, TDD_GREEN_TAG);
677
+ const sameCommand = red.verify !== undefined && red.verify === green.verify;
678
+ const missing: TddRecordTag[] = [];
679
+ if (!red.observed) missing.push(TDD_RED_TAG);
680
+ if (!green.observed || (red.verify !== undefined && green.verify !== undefined && !sameCommand)) missing.push(TDD_GREEN_TAG);
681
+ return {
682
+ planned: plan.planned,
683
+ red,
684
+ green,
685
+ sameCommand,
686
+ missing,
687
+ needsRepair: plan.planned && missing.length > 0,
688
+ };
689
+ }
@@ -226,7 +226,7 @@ import { formatGateFailedId, type PremiseReviewCard, type PremiseReviewInput } f
226
226
  import { runWorkflowToCompletion } from '../workflow-runtime/executor.js';
227
227
  import { mapReworkVerdict, supervisionObservationFields } from './supervision-vocabulary.js';
228
228
  import { resolveRunOutcome } from './run-outcome.js';
229
- import { authorLimitationCountFromGoal, authoredSignalExecution, harvestEvidenceLines, harvestedEvidenceObservation, MAX_HARVESTED_EVIDENCE_CHARS, parseOffDiffEvidence, requiredEvidenceFromGoal, createRequiredEvidenceBudget, coverRequiredEvidence, settleUncoveredEvidence, formatUncoveredEvidenceFeedback, type OffDiffEvidenceParse } from './off-diff-evidence.js';
229
+ import { authorLimitationCountFromGoal, authoredSignalExecution, harvestEvidenceLines, harvestedEvidenceObservation, MAX_HARVESTED_EVIDENCE_CHARS, parseOffDiffEvidence, judgeTddEvidence, requiredEvidenceFromGoal, createRequiredEvidenceBudget, coverRequiredEvidence, settleUncoveredEvidence, formatUncoveredEvidenceFeedback, type OffDiffEvidenceParse } from './off-diff-evidence.js';
230
230
  import { resolveEvidenceHeadCommit } from './evidence-command-budget.js';
231
231
  import { pressDecisionSignals, type DecisionSignalPressResult } from './decision-signal-press.js';
232
232
  import { inspectDecisionObservations, inspectDecisionSignalKinds, inspectDecisionSignalObservations } from '../../scripts/ask-marker-check.js';
@@ -2180,6 +2180,8 @@ export function appendGoalExecutionRecord(goalFile: string, record: GoalExecutio
2180
2180
  }
2181
2181
 
2182
2182
  export interface SelfImplementOptions {
2183
+ /** Parent managed-task cancellation, linked to the active implementation child. */
2184
+ signal?: AbortSignal;
2183
2185
  /** ⭐ 걸음을 «호출부»로 흘리는 이음매 — 노드에 들어갈 때마다 한 번.
2184
2186
  * 🩸 2026-09-08: 이 콜백은 «내부에» 있었고 ***호출부가 0*** 이라 걸음이 런 밖으로 안 나갔다.
2185
2187
  * ⇒ 런 슈퍼바이저는 「시도의 요약 판정」만 보고 「어떻게 걸었나」를 «못 봤다».
@@ -5465,13 +5467,20 @@ async function runSelfImplementInner(
5465
5467
  }
5466
5468
 
5467
5469
  // The repository copy travels with both local and Pod worktrees. Operational HQ ledgers are never read here.
5468
- const knowhow = selectKnowhowPack(wt.path, opts.feature);
5469
- if (knowhow.text) round0Feature = `${knowhow.text}\n\n${round0Feature}`;
5470
+ const knowhow = selectKnowhowPack(
5471
+ wt.path,
5472
+ opts.feature,
5473
+ undefined,
5474
+ { goalFile: opts.goalFile ?? null },
5475
+ );
5476
+ // Keep the original ask first: the child preflight and PR title read its first line.
5477
+ const injectKnowhow = getUserConfig().harness?.knowhowChildInjection === true;
5478
+ if (injectKnowhow && knowhow.text) round0Feature = `${round0Feature}\n\n${knowhow.text}`;
5470
5479
  const knowhowRevisionRead = runGitCommand(wt.path, ['rev-parse', '--verify', 'HEAD'], { encoding: 'utf8', timeout: 10_000 });
5471
5480
  const knowhowRevision = knowhowRevisionRead.status === 0 && /^[0-9a-f]{40,64}$/i.test(knowhowRevisionRead.stdout.trim())
5472
5481
  ? knowhowRevisionRead.stdout.trim() : null;
5473
- observe('knowhow-pack', { ids: knowhow.ids, bytes: knowhow.bytes, injected: knowhow.bytes > 0,
5474
- reason: knowhow.reason, repoPath: wt.path, repoRevision: knowhowRevision });
5482
+ observe('knowhow-pack', { goal: opts.feature.slice(0, 4096), ids: knowhow.ids, bytes: knowhow.bytes, sources: knowhow.sources ?? [], injected: injectKnowhow && knowhow.bytes > 0,
5483
+ reason: knowhow.reason, knowhowReason: knowhow.knowhowReason ?? knowhow.reason, repoPath: wt.path, repoRevision: knowhowRevision });
5475
5484
 
5476
5485
  // E1 착수 구체화(RFC-progressive-goal-elaboration §2 E1 · §7 간선 ①) — 고정 층(KPI·판정 신호)은 그대로, 카드만 덧붙인다.
5477
5486
  const elaboration = await (await import('./goal-elaborate.js')).runArrivalElaboration({ goal: opts.feature, prompt: round0Feature, cwd: wt.path, callLLM: s.elaborateCallLLM, observe });
@@ -7270,6 +7279,9 @@ async function runSelfImplementInner(
7270
7279
  throw error;
7271
7280
  }
7272
7281
  const implementAbortController = new AbortController();
7282
+ const abortImplementation = (): void => implementAbortController.abort(opts.signal?.reason);
7283
+ if (opts.signal?.aborted) abortImplementation();
7284
+ else opts.signal?.addEventListener('abort', abortImplementation, { once: true });
7273
7285
  let implementPromise: ReturnType<SelfImplementSeams['implement']>;
7274
7286
  // Rework needs landed sibling PRs only after the initial round; shard eligibility avoids an expensive impossible lookup.
7275
7287
  const landedSiblings = round > 0
@@ -7336,7 +7348,10 @@ async function runSelfImplementInner(
7336
7348
  }
7337
7349
  finalizeSupervisorDeliveries(error instanceof StepTimeoutError ? 'next-round-implement-timeout' : 'next-round-implement-rejected');
7338
7350
  throw error;
7351
+ } finally {
7352
+ opts.signal?.removeEventListener('abort', abortImplementation);
7339
7353
  }
7354
+ if (opts.signal?.aborted) throw opts.signal.reason ?? new Error('SelfImplement aborted');
7340
7355
  // ⭐ 성공 경로에서도 닫는다 — 이 호출은 끝났고, 이후 자식이 늦게 보내는 입력은
7341
7356
  // 「이 라운드의 재투입」이 아니다(다음 라운드는 자기 콜백을 새로 만든다).
7342
7357
  closeSupervisorInput();
@@ -7452,6 +7467,69 @@ async function runSelfImplementInner(
7452
7467
  impl = { ...impl, ok: true, completionDisposition: undefined };
7453
7468
  }
7454
7469
  }
7470
+ // ⭐ TDD 를 로직으로(S4) — 문면(device-first 조각 계획)이 아니라 실행 판정으로 끼운다.
7471
+ // ① 자식의 [tdd-red]/[tdd-green] 기록을 태그·같은 명령·결과로 판정한다.
7472
+ // ② 첫 조각 커밋의 피처 시험·구현 전 실행 RED 기록과 구현 뒤 같은 명령 GREEN 기록이
7473
+ // 없으면 수리 라운드 1회(완료 경계·기존 동작은 보존), 그래도 없으면 fail-closed.
7474
+ // ③ 관측 원장에 tdd-red/tdd-green 이벤트를 남긴다.
7475
+ let tddJudgment = judgeTddEvidence(roundGoal, parseOffDiffEvidence(impl.evidenceTranscript?.trim() || impl.summary));
7476
+ if (tddJudgment.needsRepair && impl.ok && round < effectiveMax && opts.goalFile
7477
+ && !hasCurrentProviderError() && !hasCurrentCredentialFailure()) {
7478
+ let goalDocument: string | undefined;
7479
+ try { goalDocument = readFileSync(opts.goalFile, 'utf8'); } catch { goalDocument = undefined; }
7480
+ if (goalDocument !== undefined) {
7481
+ const tddRetryNote = [
7482
+ '[구현 재작업 · tdd-evidence-missing]',
7483
+ `대상 경로: ${declaredPathsFromGoalDocumentText(goalDocument).paths.join(' · ') || '골 문서에 선언된 대상 경로 없음'}`,
7484
+ '첫 조각 커밋에 피처 시험을 먼저 쓰고 구현 전 실행 RED 기록을 남기고, 구현 뒤 같은 명령의 GREEN 기록을 남겨라.',
7485
+ "기록 양식(두 줄씩): 'EVIDENCE: [tdd-red] <무엇을 확인했나> || <증거 명령>' 다음 줄 'RESULT: <실패 요약 한 줄>' ·",
7486
+ "'EVIDENCE: [tdd-green] <무엇을 확인했나> || <같은 증거 명령>' 다음 줄 'RESULT: <통과 요약 한 줄>'.",
7487
+ `지금 잡힌 결손: ${tddJudgment.missing.join(' · ')}`,
7488
+ '원래 골 문서(완료 경계 포함):',
7489
+ goalDocument,
7490
+ ].join('\n');
7491
+ const tddRetryRound = round + 1;
7492
+ observe('implementation-tdd-rework', { status: 'started', round: tddRetryRound, missing: [...tddJudgment.missing] }, { level: 'warn' });
7493
+ progress('implementing', `[구현 재작업 · tdd-evidence-missing] 수리 라운드 ${tddRetryRound} 시작 — RED/GREEN 기록 결손`);
7494
+ onNodeEntry(node('rework'), tddRetryRound);
7495
+ onNodeEntry(node('implement'), tddRetryRound);
7496
+ const tddRetryAbort = new AbortController();
7497
+ const beforeTddRetry = impl;
7498
+ let tddRetryImpl = impl;
7499
+ try {
7500
+ tddRetryImpl = await stepTimeout(s.implement({
7501
+ sessionId, cwd: wt.path, feature: `${feature}\n\n${tddRetryNote}`, runId, shardIdentity, signal: tddRetryAbort.signal,
7502
+ ...(harnessSeededPaths.length ? { harnessSeededPaths } : {}),
7503
+ onSurfaceProgress: (line) => progress('implementing', line.trimEnd()),
7504
+ roundContext: { round: tddRetryRound, effectiveMax, previousRoundFailure: tddRetryNote },
7505
+ ...(opts.childLlm ? { childLlm: opts.childLlm } : {}),
7506
+ ...(opts.documentReferences ? { documentReferences: opts.documentReferences } : {}),
7507
+ }), T.implement, 'implement');
7508
+ } catch (error) {
7509
+ tddRetryAbort.abort();
7510
+ tddRetryImpl = { ...beforeTddRetry, ok: false, summary: `[구현 재작업 · tdd-evidence-missing] 수리 라운드 실패 — ${safeErrorDescription(error)}` };
7511
+ }
7512
+ const tddRetryJudgment = judgeTddEvidence(roundGoal, parseOffDiffEvidence(tddRetryImpl.evidenceTranscript?.trim() || tddRetryImpl.summary));
7513
+ if (tddRetryImpl.ok && !tddRetryJudgment.needsRepair) {
7514
+ observe('implementation-tdd-rework', { status: 'succeeded', round: tddRetryRound, missing: [] });
7515
+ tddJudgment = tddRetryJudgment;
7516
+ impl = tddRetryImpl;
7517
+ round = tddRetryRound;
7518
+ } else {
7519
+ observe('implementation-tdd-rework', { status: 'exhausted', round: tddRetryRound, missing: [...tddRetryJudgment.missing] }, { level: 'warn' });
7520
+ impl = { ...beforeTddRetry, ok: false, summary: `[구현 재작업 · tdd-evidence-missing] RED/GREEN 기록 결손 — ${beforeTddRetry.summary}` };
7521
+ }
7522
+ }
7523
+ }
7524
+ observe('tdd-red', {
7525
+ round, planned: tddJudgment.planned, observed: tddJudgment.red.observed, missing: tddJudgment.red.observed ? [] : ['tdd-red'],
7526
+ verify: tddJudgment.red.verify ?? null, result: tddJudgment.red.result ?? null,
7527
+ }, tddJudgment.planned && !tddJudgment.red.observed ? { level: 'warn' } : {});
7528
+ observe('tdd-green', {
7529
+ round, planned: tddJudgment.planned, observed: tddJudgment.green.observed, sameCommand: tddJudgment.sameCommand,
7530
+ missing: tddJudgment.green.observed && tddJudgment.sameCommand ? [] : ['tdd-green'],
7531
+ verify: tddJudgment.green.verify ?? null, result: tddJudgment.green.result ?? null,
7532
+ }, tddJudgment.planned && !(tddJudgment.green.observed && tddJudgment.sameCommand) ? { level: 'warn' } : {});
7455
7533
  // A finished child can leave edits without a commit. Measure them before any
7456
7534
  // diff/no-changes classification, and commit only paths declared in the goal.
7457
7535
  finishedChildCommitMissing = false;
@@ -9046,9 +9124,9 @@ async function runSelfImplementInner(
9046
9124
  const mergedBase = m.baseRefName?.trim() || observedPrBase;
9047
9125
  if (mergedBase && displayBranchName(mergedBase) === 'main') {
9048
9126
  try {
9049
- const { syncMergedPrChecklist } = await import('../release-loop/merged-pr-checklist.js');
9127
+ const { syncMergedPrChecklistWithFeedback } = await import('../release-loop/merged-pr-checklist.js');
9050
9128
  const goalFile = opts.goalFile ?? (opts.goalId ? s.goalDocumentPathByGoalId?.(opts.goalId) : undefined);
9051
- syncMergedPrChecklist(pr.number, wt.path, goalFile);
9129
+ await syncMergedPrChecklistWithFeedback(pr.number, wt.path, goalFile);
9052
9130
  } catch (error) {
9053
9131
  observe('merged-pr-checklist-sync-failed', { number: pr.number, error: safeErrorDescription(error) }, { level: 'warn' });
9054
9132
  }
@@ -719,7 +719,9 @@ export interface RunLedgerCheckedAppendOutcome<T> {
719
719
  * Thrown (typed, with the stable `runId-mismatch` reason) when a checked-append
720
720
  * decision returns an entry whose `runId` differs from the locked `runId`. Callers
721
721
  * classify identity violations from `error.reason === 'runId-mismatch'` instead of
722
- * parsing message substrings.
722
+ * parsing message substrings. `RunLedgerEntryRunIdMismatchError` below is the same
723
+ * identity violation observed on already-written ledger bytes, so one `instanceof`
724
+ * covers both producers.
723
725
  */
724
726
  export class RunLedgerCheckedAppendRunIdMismatchError extends Error {
725
727
  readonly reason = 'runId-mismatch' as const;
@@ -731,6 +733,21 @@ export class RunLedgerCheckedAppendRunIdMismatchError extends Error {
731
733
  }
732
734
  }
733
735
 
736
+ /**
737
+ * Thrown (typed, same `runId-mismatch` reason) when a stored ledger *row* declares a
738
+ * `runId` other than the one being loaded. The message prefixes the stable reason and keeps
739
+ * the parser's existing wording, so message-based classifiers (`goal-archive`, the
740
+ * doctor-compare caller's own regression test) keep recognizing it, while
741
+ * `decisionRunId`/`lockedRunId` travel as typed fields so no caller has to re-parse it.
742
+ */
743
+ export class RunLedgerEntryRunIdMismatchError extends RunLedgerCheckedAppendRunIdMismatchError {
744
+ constructor(decisionRunId: string, lockedRunId: string, readonly lineNumber: number) {
745
+ super(decisionRunId, lockedRunId);
746
+ this.name = 'RunLedgerEntryRunIdMismatchError';
747
+ this.message = `runId-mismatch: invalid run ledger entry at line ${lineNumber}: runId does not match ${lockedRunId}`;
748
+ }
749
+ }
750
+
734
751
  /**
735
752
  * Atomically decide-and-append under a single per-run lock: the caller-supplied
736
753
  * decision runs on the loaded ledger inside `withRunLedgerLock`, and at most one
@@ -896,7 +913,7 @@ function parseRunLedgerEntry(line: string, lineNumber: number, expectedRunId: st
896
913
  throw new Error(`invalid run ledger entry at line ${lineNumber}: expected optional timestamp, goalId, shard identity, runId, event, and object data`);
897
914
  }
898
915
  if (entry.runId !== expectedRunId) {
899
- throw new Error(`invalid run ledger entry at line ${lineNumber}: runId does not match ${expectedRunId}`);
916
+ throw new RunLedgerEntryRunIdMismatchError(entry.runId, expectedRunId, lineNumber);
900
917
  }
901
918
  return entry as RunLedgerEntry;
902
919
  }
@@ -1154,15 +1171,24 @@ export interface GraphAdaptReport {
1154
1171
  nonAdapted: { landed: number; denominator: number; rate: number | null };
1155
1172
  excludedCount: number;
1156
1173
  exclusionReasons: Record<string, number>;
1174
+ unmeasuredCount: number;
1175
+ unmeasuredReasons: Record<string, number>;
1176
+ window: { since: string | null; until: string | null };
1157
1177
  }
1158
1178
 
1159
1179
  /** Measure only producer-observed traversals and variant applications; never activate adaptation. */
1160
- export function queryGraphAdaptReport(goalId: string, stateDir = elanousStateRoot()): GraphAdaptReport {
1180
+ export function queryGraphAdaptReport(goalId: string, stateDir = elanousStateRoot(), window: { since?: string; until?: string } = {}): GraphAdaptReport {
1161
1181
  const dir = runLedgerDir(stateDir);
1162
1182
  const signatures = new Set<string>();
1163
1183
  const counts = { adapted: { landed: 0, denominator: 0 }, nonAdapted: { landed: 0, denominator: 0 } };
1164
1184
  const exclusionReasons: Record<string, number> = {};
1185
+ const unmeasuredReasons: Record<string, number> = {};
1165
1186
  const exclude = (reason: string): void => { exclusionReasons[reason] = (exclusionReasons[reason] ?? 0) + 1; };
1187
+ const unmeasured = (reason: string): void => { unmeasuredReasons[reason] = (unmeasuredReasons[reason] ?? 0) + 1; };
1188
+ const since = window.since === undefined ? null : Date.parse(window.since);
1189
+ const until = window.until === undefined ? null : Date.parse(window.until);
1190
+ if ((since !== null && !Number.isFinite(since)) || (until !== null && !Number.isFinite(until)) ||
1191
+ (since !== null && until !== null && since > until)) throw new Error('invalid adaptation measurement window');
1166
1192
  let unitCallCount = 0;
1167
1193
  let adaptationCount = 0;
1168
1194
  let fileNames: string[];
@@ -1181,6 +1207,15 @@ export function queryGraphAdaptReport(goalId: string, stateDir = elanousStateRoo
1181
1207
  const goalIds = new Set(ledger.map(entry => entry.goalId).filter((id): id is string => typeof id === 'string' && id.length > 0));
1182
1208
  if (goalIds.size === 1 && !goalIds.has(goalId)) continue;
1183
1209
  if (goalIds.size !== 1) { exclude('goal-id-missing-or-conflicting'); continue; }
1210
+ const start = ledger.find(entry => entry.event === 'start');
1211
+ const startedAt = start && typeof start.timestamp === 'string' ? Date.parse(start.timestamp) : NaN;
1212
+ if (!Number.isFinite(startedAt)) { unmeasured('start-time-missing-or-invalid'); continue; }
1213
+ if ((since !== null && startedAt < since) || (until !== null && startedAt >= until)) { exclude('outside-start-window'); continue; }
1214
+ const lastStatus = [...ledger].reverse().find(entry => entry.event === 'run-status');
1215
+ if (lastStatus && !['completed', 'failed', 'cancelled'].includes(String(lastStatus.data.runStatus))) {
1216
+ exclude('in-flight'); continue;
1217
+ }
1218
+ if (!lastStatus && !ledger.some(entry => entry.event === 'merged')) { exclude('in-flight'); continue; }
1184
1219
  const traversals = ledger.filter(entry => entry.event === 'pipeline-traversal-shadow');
1185
1220
  const paths = traversals.map(entry => entry.data.observedNodes);
1186
1221
  if (paths.length === 0 || paths.some(path => !Array.isArray(path) || path.length === 0 || !path.every(node => typeof node === 'string' && node.length > 0))) {
@@ -1189,12 +1224,13 @@ export function queryGraphAdaptReport(goalId: string, stateDir = elanousStateRoo
1189
1224
  let graphRun: unknown;
1190
1225
  try { graphRun = JSON.parse(readFileSync(join(stateDir, 'graph-runs', 'self-implement', `${runId}.json`), 'utf8')); }
1191
1226
  catch (error) {
1192
- if ((error as NodeJS.ErrnoException).code !== 'ENOENT') { exclude('graph-run-unreadable'); continue; }
1227
+ unmeasured((error as NodeJS.ErrnoException).code === 'ENOENT' ? 'graph-run-missing' : 'graph-run-unreadable');
1228
+ continue;
1193
1229
  }
1194
1230
  const recorded = graphRun && typeof graphRun === 'object' && !Array.isArray(graphRun) ? graphRun as Record<string, unknown> : null;
1195
- if (recorded && (recorded.runId !== runId || recorded.graphId !== 'self-implement' ||
1196
- (recorded.unitCalls !== undefined && !Array.isArray(recorded.unitCalls)))) {
1197
- exclude('unit-calls-invalid'); continue;
1231
+ if (!recorded || recorded.runId !== runId || recorded.graphId !== 'self-implement' ||
1232
+ (recorded.unitCalls !== undefined && !Array.isArray(recorded.unitCalls))) {
1233
+ unmeasured('graph-run-invalid'); continue;
1198
1234
  }
1199
1235
  const merge = [...ledger].reverse().find(entry => entry.event === 'merged');
1200
1236
  if (merge && typeof merge.data.merged !== 'boolean') { exclude('landing-invalid'); continue; }
@@ -1210,7 +1246,9 @@ export function queryGraphAdaptReport(goalId: string, stateDir = elanousStateRoo
1210
1246
  return { goalId, runCount: counts.adapted.denominator + counts.nonAdapted.denominator,
1211
1247
  uniquePathSignatures: signatures.size, unitCallCount, adaptationCount,
1212
1248
  adapted: rate(counts.adapted), nonAdapted: rate(counts.nonAdapted),
1213
- excludedCount: Object.values(exclusionReasons).reduce((total, count) => total + count, 0), exclusionReasons };
1249
+ excludedCount: Object.values(exclusionReasons).reduce((total, count) => total + count, 0), exclusionReasons,
1250
+ unmeasuredCount: Object.values(unmeasuredReasons).reduce((total, count) => total + count, 0), unmeasuredReasons,
1251
+ window: { since: window.since ?? null, until: window.until ?? null } };
1214
1252
  }
1215
1253
 
1216
1254
  export interface GoalSourceDistributionQuery {