elanous 0.2.40 → 0.2.42

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 (685) hide show
  1. package/README.md +7 -7
  2. package/apps/pwa/out/404/index.html +1 -1
  3. package/apps/pwa/out/404.html +1 -1
  4. package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_buildManifest.js +1 -1
  5. package/apps/pwa/out/_next/static/chunks/0244e5b5.6fc7670f8223d82d.js +1 -0
  6. package/apps/pwa/out/_next/static/chunks/{4769.9fd582071301f382.js → 1063.2fb8a9dc55c731f2.js} +1 -1
  7. package/apps/pwa/out/_next/static/chunks/1121.13ba7a8aff19df81.js +36 -0
  8. package/apps/pwa/out/_next/static/chunks/1147-5196d19c222051b3.js +1 -0
  9. package/apps/pwa/out/_next/static/chunks/{470.51a72a2348306455.js → 1262.e804feb8fd1acb8c.js} +2 -2
  10. package/apps/pwa/out/_next/static/chunks/1319.b9b815ae0f181e06.js +1 -0
  11. package/apps/pwa/out/_next/static/chunks/1345-31427b833438f521.js +1 -0
  12. package/apps/pwa/out/_next/static/chunks/{7219-15bdd9a80661af8e.js → 1455-530ca16c7e71baff.js} +1 -1
  13. package/apps/pwa/out/_next/static/chunks/{1281.d81877e35b9068f4.js → 1487.2f67b79444062da6.js} +1 -1
  14. package/apps/pwa/out/_next/static/chunks/1574.878c18ecc97b1bd4.js +1 -0
  15. package/apps/pwa/out/_next/static/chunks/1586.fafc33a9a5835cb7.js +32 -0
  16. package/apps/pwa/out/_next/static/chunks/1744.855fd60ae4c4a8c8.js +1 -0
  17. package/apps/pwa/out/_next/static/chunks/193.21a47a3e07ef6860.js +1 -0
  18. package/apps/pwa/out/_next/static/chunks/1945.7b54990d578c119b.js +1 -0
  19. package/apps/pwa/out/_next/static/chunks/2004.e839fda7ea5a738a.js +1 -0
  20. package/apps/pwa/out/_next/static/chunks/2044-dd681a5c08779ff8.js +1 -0
  21. package/apps/pwa/out/_next/static/chunks/2101.2248decb38829b03.js +286 -0
  22. package/apps/pwa/out/_next/static/chunks/2160.a097e7b138ae1c55.js +23 -0
  23. package/apps/pwa/out/_next/static/chunks/2300.41ea70ac1bef1446.js +1 -0
  24. package/apps/pwa/out/_next/static/chunks/2357-07b5eeb5fb12628d.js +1 -0
  25. package/apps/pwa/out/_next/static/chunks/2364.28652020695a6db3.js +34 -0
  26. package/apps/pwa/out/_next/static/chunks/{1350.59f40e39e02d91b1.js → 2456.b6de0e1c05f28843.js} +1 -1
  27. package/apps/pwa/out/_next/static/chunks/2526.c3e50ac1fec064bd.js +1 -0
  28. package/apps/pwa/out/_next/static/chunks/2549-cda50b716ff4250c.js +1 -0
  29. package/apps/pwa/out/_next/static/chunks/2550-5f1e88f615568045.js +1 -0
  30. package/apps/pwa/out/_next/static/chunks/261-319078c954e40d66.js +1 -0
  31. package/apps/pwa/out/_next/static/chunks/2690.0521c738b7749931.js +115 -0
  32. package/apps/pwa/out/_next/static/chunks/{5436.fdf6fa8ae3e9588d.js → 2974.595d1e29d040cb6a.js} +1 -1
  33. package/apps/pwa/out/_next/static/chunks/{5383.bdfa5d886e39a826.js → 3207.a756c95e9ec8c3c8.js} +1 -1
  34. package/apps/pwa/out/_next/static/chunks/3285.89ee2f298682f5e5.js +93 -0
  35. package/apps/pwa/out/_next/static/chunks/{2177.df8547f9d7215c4e.js → 3347.f846266b5e5f3ede.js} +3 -3
  36. package/apps/pwa/out/_next/static/chunks/3447.06edc7b092021417.js +41 -0
  37. package/apps/pwa/out/_next/static/chunks/{9184.45afbf44fec87574.js → 3482.a9ae9d2ad6a5bd97.js} +1 -1
  38. package/apps/pwa/out/_next/static/chunks/3507.97e1977bc4d5fb0a.js +2 -0
  39. package/apps/pwa/out/_next/static/chunks/3510-9ca392698bfe4391.js +1 -0
  40. package/apps/pwa/out/_next/static/chunks/3541.772e5ce425aaa611.js +24 -0
  41. package/apps/pwa/out/_next/static/chunks/{8099.1cccf31c1baa7e1c.js → 3741.9cf76acaa2ee5298.js} +1 -1
  42. package/apps/pwa/out/_next/static/chunks/3837.a210d7d0db8d8abd.js +1 -0
  43. package/apps/pwa/out/_next/static/chunks/3898-955c896f394217a6.js +1 -0
  44. package/apps/pwa/out/_next/static/chunks/3947-ef57acea76eaa8d2.js +1 -0
  45. package/apps/pwa/out/_next/static/chunks/{4864a2ca.1c1c280a7772c5e5.js → 3d0154af.5331fec737ffe8c3.js} +1 -1
  46. package/apps/pwa/out/_next/static/chunks/4037-3b82ebc7d78afdc7.js +1 -0
  47. package/apps/pwa/out/_next/static/chunks/4043.6b91203436c9c86b.js +309 -0
  48. package/apps/pwa/out/_next/static/chunks/405.9022d4a478202b67.js +77 -0
  49. package/apps/pwa/out/_next/static/chunks/417-fb2cc9a9910e5968.js +1 -0
  50. package/apps/pwa/out/_next/static/chunks/{3330.7443183b7e6fdbdf.js → 4276.336d76d858fcdf1b.js} +1 -1
  51. package/apps/pwa/out/_next/static/chunks/4302.6ced9aa4535de947.js +1 -0
  52. package/apps/pwa/out/_next/static/chunks/4320.583cbab64db6be02.js +1 -0
  53. package/apps/pwa/out/_next/static/chunks/4768-8eac183fd291ca53.js +1 -0
  54. package/apps/pwa/out/_next/static/chunks/4770.769c9cd9c7034eba.js +148 -0
  55. package/apps/pwa/out/_next/static/chunks/4895.65605ec3e6504e89.js +74 -0
  56. package/apps/pwa/out/_next/static/chunks/{3b355b3d.6f73c98bf6f9c749.js → 50061469.0326382241ef3b2d.js} +1 -1
  57. package/apps/pwa/out/_next/static/chunks/5112.4b9f300124fab7b3.js +149 -0
  58. package/apps/pwa/out/_next/static/chunks/5335.375ee922bcd5bc83.js +1 -0
  59. package/apps/pwa/out/_next/static/chunks/5342.023a2e729689b320.js +27 -0
  60. package/apps/pwa/out/_next/static/chunks/{8d173e38.18a2f7b4e1848bdb.js → 53c73f84.373b6160adfa89a4.js} +1 -1
  61. package/apps/pwa/out/_next/static/chunks/{1537-6bb97b5214928ea9.js → 5431-72a1dbde59400691.js} +1 -1
  62. package/apps/pwa/out/_next/static/chunks/5440-4236de26c5ea5856.js +1 -0
  63. package/apps/pwa/out/_next/static/chunks/5486-b318c165f645d8ba.js +1 -0
  64. package/apps/pwa/out/_next/static/chunks/5506-c7d2ec25c62a7c94.js +1 -0
  65. package/apps/pwa/out/_next/static/chunks/5570-c66ecbea26b4e3b1.js +1 -0
  66. package/apps/pwa/out/_next/static/chunks/5696.ffca5aa259d8451e.js +1 -0
  67. package/apps/pwa/out/_next/static/chunks/5793-8c584aea2aa87560.js +1 -0
  68. package/apps/pwa/out/_next/static/chunks/5848-6de6b8c173351a90.js +1 -0
  69. package/apps/pwa/out/_next/static/chunks/5885.0a3e52c8faccec98.js +287 -0
  70. package/apps/pwa/out/_next/static/chunks/5999.94e3c83040200f31.js +1 -0
  71. package/apps/pwa/out/_next/static/chunks/5a7901d6-2d8d9b5587cf9042.js +1 -0
  72. package/apps/pwa/out/_next/static/chunks/{261.0d471e8aded799f3.js → 6131.348b7d6bdcd267ce.js} +3 -3
  73. package/apps/pwa/out/_next/static/chunks/6164.86133a0172611184.js +90 -0
  74. package/apps/pwa/out/_next/static/chunks/{9175.2de5209a5ce6f68a.js → 6377.bc7df239edbff244.js} +1 -1
  75. package/apps/pwa/out/_next/static/chunks/6515.e07e8b2b8a707a87.js +1 -0
  76. package/apps/pwa/out/_next/static/chunks/6522-c005514f87d18982.js +1 -0
  77. package/apps/pwa/out/_next/static/chunks/{2226.2cf61ec781827219.js → 6632.0eac1c554f8f2ef3.js} +2 -2
  78. package/apps/pwa/out/_next/static/chunks/6642.648adb1767f39ecf.js +1 -0
  79. package/apps/pwa/out/_next/static/chunks/6848.138805a09d001d09.js +1 -0
  80. package/apps/pwa/out/_next/static/chunks/7049-c09e2b7a253a24f3.js +1 -0
  81. package/apps/pwa/out/_next/static/chunks/7072.1e00447d9fa39972.js +104 -0
  82. package/apps/pwa/out/_next/static/chunks/7106.64201c539c5e220c.js +94 -0
  83. package/apps/pwa/out/_next/static/chunks/7151-1f742b455986530e.js +1 -0
  84. package/apps/pwa/out/_next/static/chunks/7199.18d6b25e001154ce.js +1 -0
  85. package/apps/pwa/out/_next/static/chunks/7279-c199ea83f34338fa.js +1 -0
  86. package/apps/pwa/out/_next/static/chunks/728b938d.ffaa7ad583d60e58.js +1 -0
  87. package/apps/pwa/out/_next/static/chunks/7309.171c3de54e0322f1.js +1 -0
  88. package/apps/pwa/out/_next/static/chunks/733.7a1ab3342e03306f.js +1 -0
  89. package/apps/pwa/out/_next/static/chunks/{b84cad00.594027ebe0531fe2.js → 73d2eb0e.4966ad55293c801a.js} +3 -3
  90. package/apps/pwa/out/_next/static/chunks/{6257.c0037b8949239f5e.js → 7411.9b4b8b747dc7b802.js} +2 -2
  91. package/apps/pwa/out/_next/static/chunks/7504.d5cf1e7cd89b1b08.js +24 -0
  92. package/apps/pwa/out/_next/static/chunks/7573-0fd4af62d65d4598.js +1 -0
  93. package/apps/pwa/out/_next/static/chunks/759.6f8267df4689c401.js +1 -0
  94. package/apps/pwa/out/_next/static/chunks/7825-668b046f72f14483.js +1 -0
  95. package/apps/pwa/out/_next/static/chunks/7852-1538768b6eb19388.js +1 -0
  96. package/apps/pwa/out/_next/static/chunks/7868.cff810430bb63c91.js +1 -0
  97. package/apps/pwa/out/_next/static/chunks/{9189505a.980427ac048c8c60.js → 7a98bc80.fa935989e829f9c2.js} +1 -1
  98. package/apps/pwa/out/_next/static/chunks/8084-dfcc796874ab4e07.js +1 -0
  99. package/apps/pwa/out/_next/static/chunks/8138.6c10b2a356d52fca.js +1 -0
  100. package/apps/pwa/out/_next/static/chunks/{2566.beaffc3a5e1fcd2e.js → 8262.ddc03e06b733f184.js} +1 -1
  101. package/apps/pwa/out/_next/static/chunks/8266.6bf9b131b2584678.js +1 -0
  102. package/apps/pwa/out/_next/static/chunks/8403.7b81d5e64074a725.js +8 -0
  103. package/apps/pwa/out/_next/static/chunks/8470.1998cbd0866a7eac.js +1 -0
  104. package/apps/pwa/out/_next/static/chunks/8505.fd803c6c33b54cc3.js +79 -0
  105. package/apps/pwa/out/_next/static/chunks/{8272-025653884f9645d2.js → 8546-6f03f8ea34dd61d9.js} +1 -1
  106. package/apps/pwa/out/_next/static/chunks/{6051-0ae955eedb10adb9.js → 8673-bab689a55f7e13b9.js} +3 -3
  107. package/apps/pwa/out/_next/static/chunks/8687-246fda8433d3477c.js +1 -0
  108. package/apps/pwa/out/_next/static/chunks/898-280022fb082936bc.js +1 -0
  109. package/apps/pwa/out/_next/static/chunks/9098-50eefc1844212e3d.js +1 -0
  110. package/apps/pwa/out/_next/static/chunks/9211-330b6736a63d4cb3.js +1 -0
  111. package/apps/pwa/out/_next/static/chunks/{4351.0f37a6db2b34d50b.js → 9249.976f1e69a9d80754.js} +1 -1
  112. package/apps/pwa/out/_next/static/chunks/9255-cf88fceda5666645.js +1 -0
  113. package/apps/pwa/out/_next/static/chunks/9306-e523ba58bb8adc42.js +1 -0
  114. package/apps/pwa/out/_next/static/chunks/9324.a9866d717ba62cb6.js +1 -0
  115. package/apps/pwa/out/_next/static/chunks/9325.a8510e8aa87c8143.js +1 -0
  116. package/apps/pwa/out/_next/static/chunks/9353-12bfff0c130104cf.js +1 -0
  117. package/apps/pwa/out/_next/static/chunks/9415.69e4a21c60c7d2db.js +1 -0
  118. package/apps/pwa/out/_next/static/chunks/{6749.0744ce6eb08d40e9.js → 9427.96aa912ddb5801e0.js} +16 -16
  119. package/apps/pwa/out/_next/static/chunks/9479-154a697d4b6e4e98.js +1 -0
  120. package/apps/pwa/out/_next/static/chunks/9540-65aa6ccc31b3fd78.js +1 -0
  121. package/apps/pwa/out/_next/static/chunks/{7611.85f045bf232053ac.js → 9633.ce5bddc56784da72.js} +1 -1
  122. package/apps/pwa/out/_next/static/chunks/{3746-f80a78f220bf37b5.js → 9656-374232558fd528d0.js} +1 -1
  123. package/apps/pwa/out/_next/static/chunks/9832.f4a98c878ecf2c0a.js +62 -0
  124. package/apps/pwa/out/_next/static/chunks/9865.f094440645f02d98.js +1 -0
  125. package/apps/pwa/out/_next/static/chunks/9a852a62-6192a6ea9346ced3.js +1 -0
  126. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-e772b4710df5d936.js +1 -0
  127. package/apps/pwa/out/_next/static/chunks/app/approvals/page-4361368e6a76b967.js +1 -0
  128. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-802f349fdd65248d.js +1 -0
  129. package/apps/pwa/out/_next/static/chunks/app/board/page-7f35513988a2a495.js +1 -0
  130. package/apps/pwa/out/_next/static/chunks/app/botlab/page-798121656540e33e.js +1 -0
  131. package/apps/pwa/out/_next/static/chunks/app/bots/page-20a089490affe98c.js +1 -0
  132. package/apps/pwa/out/_next/static/chunks/app/ceo/page-e5e4ec786d70e604.js +1 -0
  133. package/apps/pwa/out/_next/static/chunks/app/chat/page-d12fe5d0801430e4.js +1 -0
  134. package/apps/pwa/out/_next/static/chunks/app/consult/page-d8cf21022fecc026.js +1 -0
  135. package/apps/pwa/out/_next/static/chunks/app/control/page-21ce565c9c57ee97.js +1 -0
  136. package/apps/pwa/out/_next/static/chunks/app/decisions/page-b56563025f619c9b.js +1 -0
  137. package/apps/pwa/out/_next/static/chunks/app/design-check/page-52f14dd133da8348.js +1 -0
  138. package/apps/pwa/out/_next/static/chunks/app/editor/page-c0ed7fdcdba76633.js +1 -0
  139. package/apps/pwa/out/_next/static/chunks/app/exec/page-af8c3020cb520f15.js +1 -0
  140. package/apps/pwa/out/_next/static/chunks/app/field/page-72eda67af9f5e35c.js +1 -0
  141. package/apps/pwa/out/_next/static/chunks/app/healthz/route-e772b4710df5d936.js +1 -0
  142. package/apps/pwa/out/_next/static/chunks/app/inside/page-67a6620d31f0a46f.js +1 -0
  143. package/apps/pwa/out/_next/static/chunks/app/intake/page-f059363aa0880ec2.js +1 -0
  144. package/apps/pwa/out/_next/static/chunks/app/layout-f9f917d6a57f69fb.js +1 -0
  145. package/apps/pwa/out/_next/static/chunks/app/live/page-d3ae55eee2f0826c.js +1 -0
  146. package/apps/pwa/out/_next/static/chunks/app/live-run/{page-83d27757e2b8060a.js → page-0e3d7b9421b79dac.js} +1 -1
  147. package/apps/pwa/out/_next/static/chunks/app/loops/page-ba738f7e233eb211.js +1 -0
  148. package/apps/pwa/out/_next/static/chunks/app/market/page-33438b98c74fd599.js +1 -0
  149. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-0b34d5fd990d793a.js +1 -0
  150. package/apps/pwa/out/_next/static/chunks/app/morning/page-0f291d3c8fd55a3a.js +1 -0
  151. package/apps/pwa/out/_next/static/chunks/app/not-found-3fced192be5279c1.js +1 -0
  152. package/apps/pwa/out/_next/static/chunks/app/observatory/page-04cb3cf182a7c1ea.js +1 -0
  153. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-6ccbd2ab23a21542.js +1 -0
  154. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-aa0518c48a5f4e56.js +1 -0
  155. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-4b32226d341ad7d7.js +1 -0
  156. package/apps/pwa/out/_next/static/chunks/app/outputs/page-3224fd8f6383b61f.js +1 -0
  157. package/apps/pwa/out/_next/static/chunks/app/page-efbc97459f2914e2.js +1 -0
  158. package/apps/pwa/out/_next/static/chunks/app/reflection/page-2fe487d88cd5d97c.js +1 -0
  159. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-48861dd1a858bab7.js +1 -0
  160. package/apps/pwa/out/_next/static/chunks/app/sessions/page-197d5d4d21d228ea.js +1 -0
  161. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-a763ba89fbdd9c27.js +1 -0
  162. package/apps/pwa/out/_next/static/chunks/app/settings/page-7edb253510b1c136.js +1 -0
  163. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-0c875702c61965ea.js +1 -0
  164. package/apps/pwa/out/_next/static/chunks/app/setup/layout-e772b4710df5d936.js +1 -0
  165. package/apps/pwa/out/_next/static/chunks/app/setup/page-e425c951151095f7.js +1 -0
  166. package/apps/pwa/out/_next/static/chunks/app/share/page-9c90e0aec4e27f77.js +1 -0
  167. package/apps/pwa/out/_next/static/chunks/app/showroom/page-733e09a02e727d42.js +1 -0
  168. package/apps/pwa/out/_next/static/chunks/app/tasks/page-4f899e14c34d77a1.js +1 -0
  169. package/apps/pwa/out/_next/static/chunks/app/term/{page-139d722de1dcd6c1.js → page-bf067887b3307423.js} +1 -1
  170. package/apps/pwa/out/_next/static/chunks/app/today/page-7af10868ff87d04e.js +1 -0
  171. package/apps/pwa/out/_next/static/chunks/app/trace/page-efe5304057aa11c7.js +1 -0
  172. package/apps/pwa/out/_next/static/chunks/app/vault/page-76bcd29aaa8a26c3.js +1 -0
  173. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-4cfd88e2273ce50f.js +1 -0
  174. package/apps/pwa/out/_next/static/chunks/app/workflows/page-0a1ddb47efba0a32.js +1 -0
  175. package/apps/pwa/out/_next/static/chunks/app/workspace/page-2a176c707152c892.js +1 -0
  176. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-efe03031b8797fbf.js +1 -0
  177. package/apps/pwa/out/_next/static/chunks/{409c787b.e48c5bec8ec10456.js → b450776b.3db34d8d965f82d3.js} +1 -1
  178. package/apps/pwa/out/_next/static/chunks/{ca3702f8.2913182e73889fa2.js → e8543907.5b040a5f22a0b0e5.js} +7 -7
  179. package/apps/pwa/out/_next/static/chunks/framework-d0d2d673bfd8a8a9.js +1 -0
  180. package/apps/pwa/out/_next/static/chunks/main-4c9fceb2baa09cb7.js +1 -0
  181. package/apps/pwa/out/_next/static/chunks/main-app-b0ab8d8fc9a97556.js +1 -0
  182. package/apps/pwa/out/_next/static/chunks/pages/_app-7e2cc62a2e5cec96.js +1 -0
  183. package/apps/pwa/out/_next/static/chunks/pages/_error-22324935f753ec5e.js +1 -0
  184. package/apps/pwa/out/_next/static/chunks/webpack-9dc1bfa25334998a.js +1 -0
  185. package/apps/pwa/out/_next/static/css/{b9d8151e48998417.css → 62c858ad53854f47.css} +1 -1
  186. package/apps/pwa/out/approvals/index.html +1 -1
  187. package/apps/pwa/out/approvals/index.txt +22 -22
  188. package/apps/pwa/out/autopilot/index.html +1 -1
  189. package/apps/pwa/out/autopilot/index.txt +22 -22
  190. package/apps/pwa/out/board/index.html +1 -1
  191. package/apps/pwa/out/board/index.txt +22 -22
  192. package/apps/pwa/out/botlab/index.html +1 -1
  193. package/apps/pwa/out/botlab/index.txt +21 -21
  194. package/apps/pwa/out/bots/index.html +1 -1
  195. package/apps/pwa/out/bots/index.txt +21 -21
  196. package/apps/pwa/out/ceo/index.html +1 -1
  197. package/apps/pwa/out/ceo/index.txt +22 -22
  198. package/apps/pwa/out/chat/index.html +1 -1
  199. package/apps/pwa/out/chat/index.txt +21 -21
  200. package/apps/pwa/out/consult/index.html +1 -1
  201. package/apps/pwa/out/consult/index.txt +22 -22
  202. package/apps/pwa/out/control/index.html +1 -1
  203. package/apps/pwa/out/control/index.txt +22 -22
  204. package/apps/pwa/out/decisions/index.html +1 -1
  205. package/apps/pwa/out/decisions/index.txt +21 -21
  206. package/apps/pwa/out/design-check/index.html +1 -1
  207. package/apps/pwa/out/design-check/index.txt +22 -22
  208. package/apps/pwa/out/editor/index.html +1 -1
  209. package/apps/pwa/out/editor/index.txt +23 -24
  210. package/apps/pwa/out/exec/index.html +1 -1
  211. package/apps/pwa/out/exec/index.txt +22 -22
  212. package/apps/pwa/out/field/index.html +1 -1
  213. package/apps/pwa/out/field/index.txt +22 -22
  214. package/apps/pwa/out/healthz +1 -1
  215. package/apps/pwa/out/index.html +1 -1
  216. package/apps/pwa/out/index.txt +21 -21
  217. package/apps/pwa/out/inside/index.html +1 -1
  218. package/apps/pwa/out/inside/index.txt +22 -22
  219. package/apps/pwa/out/intake/index.html +1 -1
  220. package/apps/pwa/out/intake/index.txt +22 -22
  221. package/apps/pwa/out/live/index.html +1 -1
  222. package/apps/pwa/out/live/index.txt +23 -24
  223. package/apps/pwa/out/live-run/index.html +1 -1
  224. package/apps/pwa/out/live-run/index.txt +23 -24
  225. package/apps/pwa/out/loops/index.html +1 -1
  226. package/apps/pwa/out/loops/index.txt +21 -21
  227. package/apps/pwa/out/market/index.html +1 -1
  228. package/apps/pwa/out/market/index.txt +21 -21
  229. package/apps/pwa/out/missions/placeholder/index.html +1 -1
  230. package/apps/pwa/out/missions/placeholder/index.txt +21 -21
  231. package/apps/pwa/out/morning/index.html +1 -1
  232. package/apps/pwa/out/morning/index.txt +22 -22
  233. package/apps/pwa/out/observatory/index.html +1 -1
  234. package/apps/pwa/out/observatory/index.txt +22 -22
  235. package/apps/pwa/out/ops/checklist/index.html +1 -1
  236. package/apps/pwa/out/ops/checklist/index.txt +21 -21
  237. package/apps/pwa/out/ops/release/index.html +1 -1
  238. package/apps/pwa/out/ops/release/index.txt +21 -21
  239. package/apps/pwa/out/ops/seats/index.html +1 -1
  240. package/apps/pwa/out/ops/seats/index.txt +21 -21
  241. package/apps/pwa/out/outputs/index.html +1 -1
  242. package/apps/pwa/out/outputs/index.txt +21 -21
  243. package/apps/pwa/out/reflection/index.html +1 -1
  244. package/apps/pwa/out/reflection/index.txt +22 -22
  245. package/apps/pwa/out/scheduler/index.html +1 -1
  246. package/apps/pwa/out/scheduler/index.txt +22 -22
  247. package/apps/pwa/out/sessions/index.html +1 -1
  248. package/apps/pwa/out/sessions/index.txt +21 -21
  249. package/apps/pwa/out/settings/devices/index.html +1 -1
  250. package/apps/pwa/out/settings/devices/index.txt +22 -22
  251. package/apps/pwa/out/settings/index.html +1 -1
  252. package/apps/pwa/out/settings/index.txt +22 -22
  253. package/apps/pwa/out/setup/done/index.html +1 -1
  254. package/apps/pwa/out/setup/done/index.txt +22 -22
  255. package/apps/pwa/out/setup/index.html +1 -1
  256. package/apps/pwa/out/setup/index.txt +22 -22
  257. package/apps/pwa/out/share/index.html +1 -1
  258. package/apps/pwa/out/share/index.txt +22 -22
  259. package/apps/pwa/out/showroom/index.html +1 -1
  260. package/apps/pwa/out/showroom/index.txt +21 -21
  261. package/apps/pwa/out/tasks/index.html +1 -1
  262. package/apps/pwa/out/tasks/index.txt +22 -22
  263. package/apps/pwa/out/term/index.html +1 -1
  264. package/apps/pwa/out/term/index.txt +22 -22
  265. package/apps/pwa/out/today/index.html +1 -1
  266. package/apps/pwa/out/today/index.txt +22 -22
  267. package/apps/pwa/out/trace/index.html +1 -1
  268. package/apps/pwa/out/trace/index.txt +22 -22
  269. package/apps/pwa/out/vault/index.html +1 -1
  270. package/apps/pwa/out/vault/index.txt +22 -22
  271. package/apps/pwa/out/workflows/chat-ui/index.html +1 -1
  272. package/apps/pwa/out/workflows/chat-ui/index.txt +22 -22
  273. package/apps/pwa/out/workflows/index.html +1 -1
  274. package/apps/pwa/out/workflows/index.txt +22 -22
  275. package/apps/pwa/out/workspace/index.html +1 -1
  276. package/apps/pwa/out/workspace/index.txt +22 -22
  277. package/apps/pwa/out/worktrees/index.html +1 -1
  278. package/apps/pwa/out/worktrees/index.txt +22 -22
  279. package/bin/elanous.mjs +6 -1
  280. package/catalog/models/openai/gpt-6.1-sol.yaml +16 -0
  281. package/catalog/models/openai/gpt-6.1-terra.yaml +16 -0
  282. package/docs/goal-context/04-mock-scenarios.md +13 -0
  283. package/graphs/catalog/catalog.yaml +1 -1
  284. package/graphs/demo/persona-teacher/lesson-pack.yaml +16 -0
  285. package/graphs/demo/persona-teacher/recipes.yaml +17 -0
  286. package/graphs/demo/persona-teacher/weekly-lesson.yaml +36 -0
  287. package/graphs/heal/heal-loop.yaml +1 -0
  288. package/graphs/overlays/stop-heal-ladder.yaml +136 -2
  289. package/graphs/release/release-loop.yaml +3 -1
  290. package/graphs/units/gate/gate.yaml +20 -0
  291. package/graphs/units/git/git.yaml +26 -0
  292. package/graphs/units/implement/implement.yaml +19 -0
  293. package/graphs/units/landing/landing.yaml +18 -0
  294. package/graphs/units/review/review.yaml +20 -0
  295. package/graphs/units/verbs/recipes.yaml +13 -10
  296. package/graphs/units/verbs/research.yaml +20 -0
  297. package/graphs/work/research-report.yaml +21 -3
  298. package/package.json +1 -1
  299. package/scripts/disk-steward.ts +46 -0
  300. package/scripts/fleet/node-setup.sh +50 -0
  301. package/scripts/graph-units/verbs/research.ts +55 -0
  302. package/scripts/heal/run-role.ts +99 -5
  303. package/scripts/land-global-checks.ts +6 -1
  304. package/scripts/lib/decompose-ab.ts +1 -0
  305. package/scripts/lib/fixtures/tui-regress/help-insufficient-commands.txt +15 -0
  306. package/scripts/lib/fixtures/tui-regress/help-live.txt +42 -0
  307. package/scripts/lib/fixtures/tui-regress/help-missing-keys.txt +21 -0
  308. package/scripts/lib/fixtures/tui-regress/help-original.txt +51 -0
  309. package/scripts/lib/fixtures/tui-regress/help-shifted-input.txt +26 -0
  310. package/scripts/lib/tui-regress-checks.ts +33 -13
  311. package/scripts/llm-cost-ledger.ts +179 -8
  312. package/scripts/measure-nl-routing-corpus.ts +10 -2
  313. package/scripts/persona-teacher/weekly-lesson-node.ts +172 -0
  314. package/scripts/public-copy-lint.ts +163 -19
  315. package/scripts/ratchets/train-side-invariants.sh +0 -1
  316. package/scripts/release-loop/gate-autoheal.ts +117 -0
  317. package/scripts/release-loop/gate-baseline-receipt.ts +55 -10
  318. package/scripts/release-loop/gate-diff.ts +22 -3
  319. package/scripts/release-loop/gate-image-pin.ts +81 -0
  320. package/scripts/release-loop/gate-node-sim.ts +207 -0
  321. package/scripts/release-loop/gate-node.ts +489 -62
  322. package/scripts/release-loop/gate-pod-image-sticky-plan.ts +99 -0
  323. package/scripts/release-loop/gate-radius-live.ts +97 -13
  324. package/scripts/release-loop/gate-shard-dispatch.ts +43 -0
  325. package/scripts/release-loop/gate-shard-load-flaky.ts +256 -0
  326. package/scripts/release-loop/gate-train-receipts.ts +122 -0
  327. package/scripts/release-loop/gate-triage-node.ts +70 -10
  328. package/scripts/release-loop/resume-release.ts +330 -23
  329. package/scripts/release-loop/traffic-node.ts +6 -3
  330. package/scripts/release-loop/unattended-release.ts +4 -2
  331. package/scripts/shadow-authoring-probe.ts +20 -0
  332. package/scripts/ux-sim.ts +37 -3
  333. package/scripts/warm-pool-provider-config.ts +263 -0
  334. package/skills/omni-crawl/SKILL.md +5 -2
  335. package/skills/omni-crawl/scripts/main.ts +84 -23
  336. package/src/acp/core-turn-bridge.ts +99 -4
  337. package/src/agent/registry.ts +2 -0
  338. package/src/agent/task-notification.ts +25 -5
  339. package/src/agent/types.ts +6 -0
  340. package/src/agent-mission/mission-cli.ts +24 -0
  341. package/src/agent-mission/mission-out.ts +595 -0
  342. package/src/agent-mission/tool-install.ts +88 -2
  343. package/src/agent-substrate/context-strategy.ts +4 -4
  344. package/src/agent-substrate/self-review-cli.ts +267 -40
  345. package/src/auto-research/research-turn.ts +133 -51
  346. package/src/autopilot/discovery/wiki-claim-proposer.ts +22 -1
  347. package/src/autopilot/pr-manager.ts +38 -7
  348. package/src/autopilot/pty-control-loop.ts +2 -0
  349. package/src/boot/daemon-tools/self-implement.ts +46 -9
  350. package/src/budget/shadow-arms.ts +52 -0
  351. package/src/capture/tui-self-report.ts +22 -6
  352. package/src/chat/index.ts +1 -1
  353. package/src/chat/pickers/state.ts +7 -1
  354. package/src/cli/fixtures/review-loop-breaker/opwaiver-32646-1694ccc7a170.json +1 -0
  355. package/src/cli/fixtures/review-loop-breaker/opwaiver-32853-bd8f73595c83.json +1 -0
  356. package/src/cli/fixtures/review-loop-breaker/opwaiver-33097-1cc85900413c.json +1 -0
  357. package/src/cli/fixtures/review-loop-breaker/opwaiver-33106-972f31e4a3ca.json +1 -0
  358. package/src/cli/fixtures/review-loop-breaker/opwaiver-33113-3ab51f05968f.json +1 -0
  359. package/src/cli/fixtures/review-loop-breaker/pr-33097-1cc85900413c.json +1 -0
  360. package/src/cli/log-event-names.ts +5 -0
  361. package/src/cli/mcp-login.ts +8 -18
  362. package/src/cli/msg-cli.ts +57 -1
  363. package/src/cli/pr-land-heavy-remote.ts +47 -9
  364. package/src/cli/pr-land-overlap-evidence.ts +100 -1
  365. package/src/cli/pr-land-pod-shadow-job.ts +60 -0
  366. package/src/cli/release-checklist-read-cli.ts +20 -10
  367. package/src/cli/release-cli.ts +27 -1
  368. package/src/cli/research-cli.ts +4 -5
  369. package/src/cli/sim-cli.ts +7 -1
  370. package/src/cli/tasks-cli.ts +12 -4
  371. package/src/codex/models.ts +30 -15
  372. package/src/compact/auto.ts +8 -1
  373. package/src/control-plane/ledger.ts +52 -2
  374. package/src/control-plane/server.ts +16 -2
  375. package/src/core-turn/run-core-turn.ts +313 -89
  376. package/src/core-turn/run-goal-loop.ts +106 -2
  377. package/src/core-turn/types.ts +2 -0
  378. package/src/dashboard/acp-boot.ts +72 -3
  379. package/src/dashboard/classic-sidetab-mission-job.ts +58 -0
  380. package/src/dashboard/classic-sidetab-mission.ts +185 -0
  381. package/src/dashboard/index.ts +155 -15
  382. package/src/dashboard/input/agent-wake.ts +23 -1
  383. package/src/dashboard/input/chat-main-plain-turn-runtime.ts +9 -0
  384. package/src/dashboard/mission-cli-consumer.ts +153 -0
  385. package/src/dashboard/seat-boot-preamble.ts +171 -1
  386. package/src/dashboard/side-basic-runtime.ts +54 -1
  387. package/src/dashboard/sidetab-runtime.ts +90 -1
  388. package/src/dashboard/skill-catalog-preamble.ts +101 -0
  389. package/src/dashboard/skill-detection-runtime.ts +55 -15
  390. package/src/dashboard/slash-runtime/dashboard-handlers.ts +15 -0
  391. package/src/dashboard/turn-preamble.ts +65 -16
  392. package/src/dashboard/turn-prompt-runtime.ts +4 -2
  393. package/src/disk-steward/judge.ts +73 -0
  394. package/src/disk-steward/ledger.ts +122 -0
  395. package/src/disk-steward/steward.ts +373 -0
  396. package/src/domains/guardian-tick.ts +191 -2
  397. package/src/graph-runner/graph-cli.ts +44 -7
  398. package/src/graph-runner/graph-tick.ts +10 -2
  399. package/src/graph-runner/in-process-registry.ts +37 -0
  400. package/src/graph-runner/runner.ts +34 -4
  401. package/src/grok/agent-search.ts +14 -4
  402. package/src/grok/credential.ts +28 -11
  403. package/src/grounding/ref-index.ts +19 -0
  404. package/src/grounding/sources-cli.ts +9 -1
  405. package/src/harness/harness-cli-command.ts +267 -14
  406. package/src/harness/harness-incidents.ts +312 -7
  407. package/src/harness/harness-pod-dispatch.ts +81 -15
  408. package/src/harness/harness-space.ts +15 -1
  409. package/src/harness/harness-stop.ts +155 -11
  410. package/src/harness/progress-worker-entry.ts +59 -0
  411. package/src/harness/progress-worker-runtime.ts +11 -0
  412. package/src/index.ts +52 -7
  413. package/src/instance/dev-project.ts +25 -0
  414. package/src/instance/spawn-elanous.ts +6 -4
  415. package/src/intelligence-map/model-alias.ts +6 -5
  416. package/src/intelligence-map/model-catalog.ts +59 -2
  417. package/src/llm/model-defaults.ts +4 -4
  418. package/src/llm.ts +208 -19
  419. package/src/loops/orchestrator/coordinator-shadow.ts +226 -0
  420. package/src/loops/orchestrator/tick.ts +61 -0
  421. package/src/maturity/feature-maturity.ts +1 -1
  422. package/src/mcp/mcp-oauth.ts +3 -1
  423. package/src/model-tier/llm-tier-map.ts +9 -9
  424. package/src/model-tier/turn-tier.ts +1 -1
  425. package/src/msg/msg-mirror-github.ts +80 -0
  426. package/src/msg/msg-mirror-policy.ts +61 -0
  427. package/src/msg/msg-mirror-runner.ts +219 -0
  428. package/src/msg/msg-mirror-state.ts +33 -0
  429. package/src/msg/msg-store.ts +11 -0
  430. package/src/native-tool-catalog.ts +2 -2
  431. package/src/nexus/api/harness-traversal.ts +11 -0
  432. package/src/output-truncation.ts +41 -12
  433. package/src/pr-tool/census.ts +3 -2
  434. package/src/project/project-store.ts +48 -1
  435. package/src/pty-shell/tui-run-state.ts +188 -2
  436. package/src/release-loop/checklist-target-path-hint.ts +13 -0
  437. package/src/release-loop/checklist.ts +9 -1
  438. package/src/release-loop/gate-host-reservation.ts +144 -0
  439. package/src/release-loop/release-schedule.ts +90 -1
  440. package/src/repl/index.ts +43 -2
  441. package/src/research/axis-fanout.ts +121 -16
  442. package/src/research/bloom-exemplars.ts +137 -0
  443. package/src/research/gap-followup.ts +13 -1
  444. package/src/research/plugin-discovery.ts +36 -14
  445. package/src/research-bridge/invoke.ts +22 -5
  446. package/src/research-bridge/types.ts +2 -0
  447. package/src/self-dev/ask-launch-flow.ts +39 -25
  448. package/src/self-dev/decompose.ts +119 -5
  449. package/src/self-dev/dev-cli.ts +17 -17
  450. package/src/self-dev/graph-front-nodes.ts +23 -0
  451. package/src/self-dev/launch-preflight-text.ts +5 -6
  452. package/src/self-dev/launch-preflight.ts +9 -4
  453. package/src/self-dev/orchestrate.ts +27 -2
  454. package/src/self-dev/review-provider-fallback.ts +9 -2
  455. package/src/self-dev/run-supervisor.ts +226 -6
  456. package/src/self-dev/run-types.ts +7 -0
  457. package/src/self-implement/doctor-visit.ts +88 -0
  458. package/src/self-implement/gate-artifacts.ts +13 -0
  459. package/src/self-implement/gate-cli.ts +54 -24
  460. package/src/self-implement/gate-remote.ts +23 -5
  461. package/src/self-implement/goal-author-clarification.ts +31 -12
  462. package/src/self-implement/goal-author.ts +403 -8
  463. package/src/self-implement/graph-overlay-yaml.ts +7 -0
  464. package/src/self-implement/graph-stage-units.ts +172 -0
  465. package/src/self-implement/graph-templates.ts +162 -1
  466. package/src/self-implement/graph-variant.ts +37 -4
  467. package/src/self-implement/headless-elanous-driver.ts +31 -2
  468. package/src/self-implement/heal-intake.ts +112 -4
  469. package/src/self-implement/heal-triage.ts +20 -0
  470. package/src/self-implement/host-regate.ts +31 -8
  471. package/src/self-implement/knowhow-pack.ts +38 -0
  472. package/src/self-implement/merge-train.ts +5 -0
  473. package/src/self-implement/orchestrator.ts +359 -30
  474. package/src/self-implement/regate-detail.ts +38 -1
  475. package/src/self-implement/rework-child-provider.ts +25 -0
  476. package/src/self-implement/run-chart.ts +119 -0
  477. package/src/self-implement/run-ledger.ts +176 -17
  478. package/src/self-implement/run-stop.ts +208 -5
  479. package/src/self-implement/running-runs.ts +35 -12
  480. package/src/self-implement/self-implement-cli.ts +36 -4
  481. package/src/self-implement/stop-autoheal-operational.ts +43 -0
  482. package/src/self-implement/stop-autoheal.ts +28 -6
  483. package/src/session/chat.ts +69 -58
  484. package/src/session/request-size-guard.ts +123 -0
  485. package/src/session-runtime/index.ts +98 -4
  486. package/src/session-runtime/tier-flip.ts +3 -3
  487. package/src/sidetab-core/model.ts +150 -0
  488. package/src/sidetab-core/visible-agent-mission.ts +186 -0
  489. package/src/skills/name-match.ts +20 -0
  490. package/src/skills/tools/agent.ts +30 -2
  491. package/src/skills/tools/omni-search.ts +67 -5
  492. package/src/task-agent/parent-host.ts +14 -1
  493. package/src/task-agent/pod-distributor-entry.ts +3 -0
  494. package/src/task-agent/task-hand.ts +31 -1
  495. package/src/task-orchestrator/surfaces/pod-distributor.ts +48 -0
  496. package/src/task-orchestrator/surfaces/pod-failure-reason.ts +43 -0
  497. package/src/task-orchestrator/surfaces/pod-ledger-collect.ts +38 -1
  498. package/src/task-orchestrator/surfaces/pod-ledger-events.ts +29 -4
  499. package/src/task-orchestrator/surfaces/pod-si-warm-entry.ts +33 -6
  500. package/src/task-orchestrator/surfaces/pod-source-bundle.ts +45 -9
  501. package/src/task-orchestrator/surfaces/pod-source-receive.ts +163 -13
  502. package/src/task-orchestrator/surfaces/pod-source-spec.ts +3 -3
  503. package/src/task-orchestrator/surfaces/pod-warm-worker-provider.ts +209 -39
  504. package/src/task-orchestrator/surfaces/pod-warm-worker-runtime.ts +80 -3
  505. package/src/task-orchestrator/surfaces/self-implement-pod.ts +280 -60
  506. package/src/task-orchestrator/surfaces/self-implement.ts +18 -0
  507. package/src/tokens.ts +35 -2
  508. package/src/tool-runtime/agent-runtime.ts +1 -0
  509. package/src/tool-runtime/elanous-skills-list-runtime.ts +5 -1
  510. package/src/tool-runtime/skill-exec-runtime.ts +33 -13
  511. package/src/tool-runtime/types.ts +1 -0
  512. package/src/tui/entry.ts +24 -7
  513. package/src/tui/sidetab/attach.ts +47 -0
  514. package/src/tui/sidetab/list.ts +45 -0
  515. package/src/tui/sidetab/nl-tool.ts +2 -136
  516. package/src/tui/sidetab/peek.ts +52 -0
  517. package/src/tui-client/dashboard-session.ts +3 -0
  518. package/src/tui-client/local-chat-turn.ts +26 -13
  519. package/src/tui.ts +22 -0
  520. package/src/user-config.ts +11 -5
  521. package/src/ux-sim/fake-kubectl.ts +37 -3
  522. package/src/ux-sim/fault-needs-human-reason-repair.ts +107 -0
  523. package/src/ux-sim/fault-pod-child-result.ts +42 -0
  524. package/src/ux-sim/fault-pool-cap.ts +11 -6
  525. package/src/ux-sim/mock-scenario-catalog.json +41 -0
  526. package/src/ux-sim/mock-scenario-catalog.ts +156 -0
  527. package/src/ux-sim/release-sim-rig.ts +262 -0
  528. package/src/ux-sim/scenario.ts +116 -23
  529. package/src/ux-sim/seminar-rehearsal.ts +109 -0
  530. package/src/ux-sim/subagent-tools-device.ts +2 -2
  531. package/src/version/packed-revision.json +1 -1
  532. package/src/voice/voice-tts-singleton.ts +18 -3
  533. package/src/web-search/grok.ts +5 -9
  534. package/apps/pwa/out/_next/static/chunks/1060.014f1f01a17aec26.js +0 -115
  535. package/apps/pwa/out/_next/static/chunks/1415.79821ec7ae99acdb.js +0 -1
  536. package/apps/pwa/out/_next/static/chunks/1452.162bb2d9d699e82a.js +0 -1
  537. package/apps/pwa/out/_next/static/chunks/147.f92f63bbc5e85fa5.js +0 -286
  538. package/apps/pwa/out/_next/static/chunks/1661.fb425a1d8a065b72.js +0 -149
  539. package/apps/pwa/out/_next/static/chunks/1671-1c22b40b50b208f2.js +0 -1
  540. package/apps/pwa/out/_next/static/chunks/1758.0204d3f48783c49d.js +0 -90
  541. package/apps/pwa/out/_next/static/chunks/1806.027bf78b6a94d340.js +0 -104
  542. package/apps/pwa/out/_next/static/chunks/2047.8f23e210995d4548.js +0 -2
  543. package/apps/pwa/out/_next/static/chunks/2061-7f2bbc53ae96c88b.js +0 -1
  544. package/apps/pwa/out/_next/static/chunks/2066.a77257c8c350770a.js +0 -23
  545. package/apps/pwa/out/_next/static/chunks/2096-a938496bc996dcbd.js +0 -1
  546. package/apps/pwa/out/_next/static/chunks/2200-9a453b8f99687d49.js +0 -1
  547. package/apps/pwa/out/_next/static/chunks/2281-b8cede695c6c650e.js +0 -1
  548. package/apps/pwa/out/_next/static/chunks/2499.02fbfd18126c10c0.js +0 -1
  549. package/apps/pwa/out/_next/static/chunks/2522.f2766b76d22c8bdf.js +0 -34
  550. package/apps/pwa/out/_next/static/chunks/2615.3c9738153de3ef3f.js +0 -1
  551. package/apps/pwa/out/_next/static/chunks/2727.e703d99ac414916d.js +0 -1
  552. package/apps/pwa/out/_next/static/chunks/2752.7904b8df0254d0ae.js +0 -27
  553. package/apps/pwa/out/_next/static/chunks/2762-5051a862dfa40e99.js +0 -1
  554. package/apps/pwa/out/_next/static/chunks/2767-31784bfedf8e245d.js +0 -1
  555. package/apps/pwa/out/_next/static/chunks/2774-719820e3f5b2a3eb.js +0 -1
  556. package/apps/pwa/out/_next/static/chunks/2812-f016aa0dda149287.js +0 -1
  557. package/apps/pwa/out/_next/static/chunks/2829-734fe8bf2eee7347.js +0 -1
  558. package/apps/pwa/out/_next/static/chunks/311-32dcac79970985e8.js +0 -1
  559. package/apps/pwa/out/_next/static/chunks/3175-f93f7495cd28253c.js +0 -1
  560. package/apps/pwa/out/_next/static/chunks/3184.8da993f5502d2140.js +0 -1
  561. package/apps/pwa/out/_next/static/chunks/3231-d7c981db0ff8bdcc.js +0 -1
  562. package/apps/pwa/out/_next/static/chunks/3250.151309c5176d6b4b.js +0 -1
  563. package/apps/pwa/out/_next/static/chunks/3517.a5aa1797a9dbf2ee.js +0 -1
  564. package/apps/pwa/out/_next/static/chunks/3567-45f676877ed9e8a5.js +0 -1
  565. package/apps/pwa/out/_next/static/chunks/3819.8a1de79b2e8c7298.js +0 -24
  566. package/apps/pwa/out/_next/static/chunks/39.9b37b0be4c128a83.js +0 -77
  567. package/apps/pwa/out/_next/static/chunks/4023.a19045970a9ce16a.js +0 -36
  568. package/apps/pwa/out/_next/static/chunks/413-24c8284bda08241d.js +0 -1
  569. package/apps/pwa/out/_next/static/chunks/4135.e45d6ebc29e20647.js +0 -1
  570. package/apps/pwa/out/_next/static/chunks/4283.65502f5d0e6ff6c0.js +0 -287
  571. package/apps/pwa/out/_next/static/chunks/4305-4e28fa92a7b34a5b.js +0 -1
  572. package/apps/pwa/out/_next/static/chunks/4335-50efa61fd7613142.js +0 -1
  573. package/apps/pwa/out/_next/static/chunks/4720.ecbd1693fa151068.js +0 -1
  574. package/apps/pwa/out/_next/static/chunks/483.725e4a61be922788.js +0 -1
  575. package/apps/pwa/out/_next/static/chunks/4969-4b209d7307410c00.js +0 -1
  576. package/apps/pwa/out/_next/static/chunks/5068-c7f53862f83c0917.js +0 -1
  577. package/apps/pwa/out/_next/static/chunks/5315.bc96711c24dfefe2.js +0 -74
  578. package/apps/pwa/out/_next/static/chunks/5542.efbf14f16baed4dd.js +0 -1
  579. package/apps/pwa/out/_next/static/chunks/5622.94893f5aea7185d0.js +0 -1
  580. package/apps/pwa/out/_next/static/chunks/5644.8f401a25601d05fc.js +0 -1
  581. package/apps/pwa/out/_next/static/chunks/5658.35f70eb9871a54bf.js +0 -1
  582. package/apps/pwa/out/_next/static/chunks/5721.7bdc0e904c76ab51.js +0 -8
  583. package/apps/pwa/out/_next/static/chunks/5790-eef0ca20884a6bdf.js +0 -1
  584. package/apps/pwa/out/_next/static/chunks/5802.ef0d8598ca68fe84.js +0 -62
  585. package/apps/pwa/out/_next/static/chunks/5890.fb974729788dcb71.js +0 -1
  586. package/apps/pwa/out/_next/static/chunks/5924.5ef25cddd36d5dbf.js +0 -1
  587. package/apps/pwa/out/_next/static/chunks/5979-e59c099ebf8d1f35.js +0 -1
  588. package/apps/pwa/out/_next/static/chunks/6020.714cfeada2315e2e.js +0 -94
  589. package/apps/pwa/out/_next/static/chunks/6027-dfe0349d8c50f698.js +0 -1
  590. package/apps/pwa/out/_next/static/chunks/6178.bc4730c86cf74536.js +0 -1
  591. package/apps/pwa/out/_next/static/chunks/6273.d808b0dcb3c2b155.js +0 -1
  592. package/apps/pwa/out/_next/static/chunks/6292.6ef1df64fa6a4c8a.js +0 -1
  593. package/apps/pwa/out/_next/static/chunks/647-af8dd920ba46533c.js +0 -1
  594. package/apps/pwa/out/_next/static/chunks/6541-170dc5c59e135c0c.js +0 -1
  595. package/apps/pwa/out/_next/static/chunks/6624.981ef7caeb680560.js +0 -32
  596. package/apps/pwa/out/_next/static/chunks/6742-a1ad4a94ba7bc37a.js +0 -1
  597. package/apps/pwa/out/_next/static/chunks/6836-493dc55c39187949.js +0 -1
  598. package/apps/pwa/out/_next/static/chunks/6856-53ac421c06039a18.js +0 -1
  599. package/apps/pwa/out/_next/static/chunks/6908.06008c67f6380ea9.js +0 -148
  600. package/apps/pwa/out/_next/static/chunks/6915.096931864206f522.js +0 -1
  601. package/apps/pwa/out/_next/static/chunks/6925.5e181fb7dcf90193.js +0 -1
  602. package/apps/pwa/out/_next/static/chunks/6cc1d1d6.9a98dd4622f1afc6.js +0 -1
  603. package/apps/pwa/out/_next/static/chunks/7203-800e11037adc41eb.js +0 -1
  604. package/apps/pwa/out/_next/static/chunks/7279.6170f591105936bb.js +0 -93
  605. package/apps/pwa/out/_next/static/chunks/7349-373165c7fbdcc3df.js +0 -1
  606. package/apps/pwa/out/_next/static/chunks/7514-a533ba0ca1cae4f4.js +0 -1
  607. package/apps/pwa/out/_next/static/chunks/7515.1ad6efe157fa4448.js +0 -1
  608. package/apps/pwa/out/_next/static/chunks/7521.d919cc1fab80c1d9.js +0 -24
  609. package/apps/pwa/out/_next/static/chunks/7538.90e97bbdf9178cff.js +0 -1
  610. package/apps/pwa/out/_next/static/chunks/7825-39203196a12579b2.js +0 -1
  611. package/apps/pwa/out/_next/static/chunks/7869.5e1a9a12fd70d6c7.js +0 -1
  612. package/apps/pwa/out/_next/static/chunks/8086.1ab9103c41be884f.js +0 -1
  613. package/apps/pwa/out/_next/static/chunks/8179-e61fffbdb70f1152.js +0 -1
  614. package/apps/pwa/out/_next/static/chunks/8265.bdeb991b34db6a06.js +0 -1
  615. package/apps/pwa/out/_next/static/chunks/8357.1aaa713b052a78b1.js +0 -309
  616. package/apps/pwa/out/_next/static/chunks/8638-e42615f2166165b5.js +0 -1
  617. package/apps/pwa/out/_next/static/chunks/8639-92c11d069792429e.js +0 -1
  618. package/apps/pwa/out/_next/static/chunks/8691.54e22831d5e8ccf8.js +0 -1
  619. package/apps/pwa/out/_next/static/chunks/9069.657590a84afb8fac.js +0 -41
  620. package/apps/pwa/out/_next/static/chunks/9125-ae588d88a0293b93.js +0 -1
  621. package/apps/pwa/out/_next/static/chunks/9311.f9f641a46a508611.js +0 -1
  622. package/apps/pwa/out/_next/static/chunks/9371-a6fee8378ebfa3ee.js +0 -1
  623. package/apps/pwa/out/_next/static/chunks/9421-3aa9ff4fa7f63d8a.js +0 -1
  624. package/apps/pwa/out/_next/static/chunks/9992.07ce73c10bd5e6a1.js +0 -79
  625. package/apps/pwa/out/_next/static/chunks/app/_not-found/page-76394dc618d322c8.js +0 -1
  626. package/apps/pwa/out/_next/static/chunks/app/approvals/page-1b948637c37b3abd.js +0 -1
  627. package/apps/pwa/out/_next/static/chunks/app/autopilot/page-c63400f1bcf3e47c.js +0 -1
  628. package/apps/pwa/out/_next/static/chunks/app/board/page-95d0957267819586.js +0 -1
  629. package/apps/pwa/out/_next/static/chunks/app/botlab/page-ba957ff875a026a0.js +0 -1
  630. package/apps/pwa/out/_next/static/chunks/app/bots/page-bb6fd0714879cb87.js +0 -1
  631. package/apps/pwa/out/_next/static/chunks/app/ceo/page-8f9038520d2acbef.js +0 -1
  632. package/apps/pwa/out/_next/static/chunks/app/chat/page-d4b48397e05fce2c.js +0 -1
  633. package/apps/pwa/out/_next/static/chunks/app/consult/page-72d5744245dc0c27.js +0 -1
  634. package/apps/pwa/out/_next/static/chunks/app/control/page-37625dc8300fa43a.js +0 -1
  635. package/apps/pwa/out/_next/static/chunks/app/decisions/page-fbef9d160272dbc1.js +0 -1
  636. package/apps/pwa/out/_next/static/chunks/app/design-check/page-58424168df84928e.js +0 -1
  637. package/apps/pwa/out/_next/static/chunks/app/editor/page-72c12ba430ac57c0.js +0 -1
  638. package/apps/pwa/out/_next/static/chunks/app/exec/page-d53f3e9ed806d7e0.js +0 -1
  639. package/apps/pwa/out/_next/static/chunks/app/field/page-4d2fbd45feee0829.js +0 -1
  640. package/apps/pwa/out/_next/static/chunks/app/healthz/route-76394dc618d322c8.js +0 -1
  641. package/apps/pwa/out/_next/static/chunks/app/inside/page-8783dc0ed7590a2c.js +0 -1
  642. package/apps/pwa/out/_next/static/chunks/app/intake/page-3706cb390606e930.js +0 -1
  643. package/apps/pwa/out/_next/static/chunks/app/layout-9b0a86598e0111fd.js +0 -1
  644. package/apps/pwa/out/_next/static/chunks/app/live/page-4edb8df90f4537ce.js +0 -1
  645. package/apps/pwa/out/_next/static/chunks/app/loops/page-47398b9ba1cc5e1b.js +0 -1
  646. package/apps/pwa/out/_next/static/chunks/app/market/page-fb86f55cfe2e681d.js +0 -1
  647. package/apps/pwa/out/_next/static/chunks/app/missions/[id]/page-e22345fc8fd47b1b.js +0 -1
  648. package/apps/pwa/out/_next/static/chunks/app/morning/page-fca2e59a81744d9e.js +0 -1
  649. package/apps/pwa/out/_next/static/chunks/app/not-found-6e96bda63100b31e.js +0 -1
  650. package/apps/pwa/out/_next/static/chunks/app/observatory/page-4d17ad8e0db8cea4.js +0 -1
  651. package/apps/pwa/out/_next/static/chunks/app/ops/checklist/page-121f92766c33beaa.js +0 -1
  652. package/apps/pwa/out/_next/static/chunks/app/ops/release/page-43f14212c545f92d.js +0 -1
  653. package/apps/pwa/out/_next/static/chunks/app/ops/seats/page-ccec2023e7a974ec.js +0 -1
  654. package/apps/pwa/out/_next/static/chunks/app/outputs/page-b04f33f548b89a94.js +0 -1
  655. package/apps/pwa/out/_next/static/chunks/app/page-c8792823c0917021.js +0 -1
  656. package/apps/pwa/out/_next/static/chunks/app/reflection/page-8c0e32782ceef4cb.js +0 -1
  657. package/apps/pwa/out/_next/static/chunks/app/scheduler/page-94bd3922eb230ce8.js +0 -1
  658. package/apps/pwa/out/_next/static/chunks/app/sessions/page-bca565887bafa03c.js +0 -1
  659. package/apps/pwa/out/_next/static/chunks/app/settings/devices/page-ac1dffafe649fc6c.js +0 -1
  660. package/apps/pwa/out/_next/static/chunks/app/settings/page-52374edb5e23e455.js +0 -1
  661. package/apps/pwa/out/_next/static/chunks/app/setup/done/page-ad4ebca120d43ca7.js +0 -1
  662. package/apps/pwa/out/_next/static/chunks/app/setup/layout-76394dc618d322c8.js +0 -1
  663. package/apps/pwa/out/_next/static/chunks/app/setup/page-718b89ce4b4ae4e4.js +0 -1
  664. package/apps/pwa/out/_next/static/chunks/app/share/page-204eca33eeeaddec.js +0 -1
  665. package/apps/pwa/out/_next/static/chunks/app/showroom/page-e58ba9bcdb9ac0f9.js +0 -1
  666. package/apps/pwa/out/_next/static/chunks/app/tasks/page-98f6dd50bafd7734.js +0 -1
  667. package/apps/pwa/out/_next/static/chunks/app/today/page-5a4bdd72bff27057.js +0 -1
  668. package/apps/pwa/out/_next/static/chunks/app/trace/page-6f6ab17d44f984ce.js +0 -1
  669. package/apps/pwa/out/_next/static/chunks/app/vault/page-aabb7bd15fb72da9.js +0 -1
  670. package/apps/pwa/out/_next/static/chunks/app/workflows/chat-ui/page-e4322319164a4436.js +0 -1
  671. package/apps/pwa/out/_next/static/chunks/app/workflows/page-e9efc0c8f32e2371.js +0 -1
  672. package/apps/pwa/out/_next/static/chunks/app/workspace/page-ccde99f07aaf71f7.js +0 -1
  673. package/apps/pwa/out/_next/static/chunks/app/worktrees/page-80464aced9614390.js +0 -1
  674. package/apps/pwa/out/_next/static/chunks/c696986b.5dc8bb1143af16d1.js +0 -1
  675. package/apps/pwa/out/_next/static/chunks/d5d3cefc-373c4eb722ed848b.js +0 -1
  676. package/apps/pwa/out/_next/static/chunks/d8de0de2-dd0f4ac8e5ab1832.js +0 -1
  677. package/apps/pwa/out/_next/static/chunks/framework-002b472a66935d31.js +0 -1
  678. package/apps/pwa/out/_next/static/chunks/main-49b88d47292c0476.js +0 -1
  679. package/apps/pwa/out/_next/static/chunks/main-app-fff2549cb10a133f.js +0 -1
  680. package/apps/pwa/out/_next/static/chunks/pages/_app-32abbbba3f3b76b7.js +0 -1
  681. package/apps/pwa/out/_next/static/chunks/pages/_error-9d9cfef60c60dd7a.js +0 -1
  682. package/apps/pwa/out/_next/static/chunks/webpack-cc7f483fa294034a.js +0 -1
  683. package/apps/pwa/out/_next/static/css/d0a48dc099ed86cf.css +0 -1
  684. package/scripts/ratchets/next-tui-entry-budget.ts +0 -124
  685. /package/apps/pwa/out/_next/static/{HjeK7zONHfR7op1hKXp4k → X1ucLw10Cds_h614NoEnh}/_ssgManifest.js +0 -0
@@ -1,7 +1,15 @@
1
1
  // Research-only native fanout. The caller supplies Bloom's question ladder;
2
2
  // each axis gets its own direct tool call and evidence stays attributed to it.
3
3
  import type { BloomResearchQuestion, ResearchEvidenceEnvelope } from '../auto-research/question-ladder-contract.js';
4
- import type { WebSearchHit } from '../web-search/provider.js';
4
+ import { getAvailableWebSearchProviders } from '../web-search/index.js';
5
+ import type { WebSearchHit, WebSearchProvider } from '../web-search/provider.js';
6
+ import { debug } from '../debug/log.js';
7
+
8
+ const RESEARCH_SEARCH_ENGINES = ['grok', 'grok-api', 'firecrawl'] as const;
9
+ const RESEARCH_GROK_TIMEOUT_MS = 8_000;
10
+ // Leave scheduler/logging headroom under the user-visible 15s aggregate cap.
11
+ export const RESEARCH_SEARCH_BUDGET_MS = 14_500;
12
+ const ENGINE_BREAKER_FAILURE_LIMIT = 2;
5
13
 
6
14
  export interface AxisToolCallPlan {
7
15
  questionId: string;
@@ -25,10 +33,119 @@ export interface AxisSearchResult {
25
33
  hits: AxisSearchHit[];
26
34
  errors: string[];
27
35
  }
28
- export type AxisSearch = (query: string) => Promise<AxisSearchHit[] | AxisSearchResult>;
36
+ export type AxisSearch = (query: string, signal?: AbortSignal) => Promise<AxisSearchHit[] | AxisSearchResult>;
29
37
 
30
38
  export interface AxisFanoutDeps {
31
39
  search?: AxisSearch;
40
+ signal?: AbortSignal;
41
+ }
42
+
43
+ interface ProviderHealth {
44
+ failures: number;
45
+ open: boolean;
46
+ }
47
+
48
+ /** Build one bounded searcher per research prepass. Free/DDG is deliberately
49
+ * excluded: it is not a safe fallback for stock research and can consume a
50
+ * full 15s timeout for every query. Per-engine serialization lets the first
51
+ * timeout open that engine's breaker before queued Bloom axes start. */
52
+ export function createResearchAxisSearcher(
53
+ availableProviders: readonly WebSearchProvider[] = getAvailableWebSearchProviders(),
54
+ now: () => number = Date.now,
55
+ ): AxisSearch {
56
+ const grok = availableProviders.find(provider => provider.id === 'grok')
57
+ ?? availableProviders.find(provider => provider.id === 'grok-api');
58
+ const allowed = [
59
+ ...(grok ? [grok] : []),
60
+ ...availableProviders.filter(provider => provider.id === 'firecrawl'),
61
+ ];
62
+ const health = new Map(allowed.map(provider => [provider.id, { failures: 0, open: false }]));
63
+ const deadline = now() + RESEARCH_SEARCH_BUDGET_MS;
64
+ const tails = new Map<string, Promise<void>>();
65
+
66
+ debug.log('research.search', 'provider-preflight', {
67
+ allowed: RESEARCH_SEARCH_ENGINES,
68
+ available: allowed.map(provider => provider.id),
69
+ excluded: availableProviders.filter(provider => !(RESEARCH_SEARCH_ENGINES as readonly string[]).includes(provider.id))
70
+ .map(provider => provider.id),
71
+ budgetMs: RESEARCH_SEARCH_BUDGET_MS,
72
+ });
73
+
74
+ const enqueue = <T>(providerId: string, run: () => Promise<T>): Promise<T> => {
75
+ const previous = tails.get(providerId) ?? Promise.resolve();
76
+ const current = previous.then(run, run);
77
+ tails.set(providerId, current.then(() => undefined, () => undefined));
78
+ return current;
79
+ };
80
+
81
+ return async (query, signal) => {
82
+ const hits: AxisSearchHit[] = [];
83
+ const errors: string[] = [];
84
+ const selected = allowed.filter(provider => !health.get(provider.id)?.open);
85
+ if (selected.length === 0) return { hits, errors: ['no healthy Grok/Firecrawl research provider'] };
86
+
87
+ await Promise.all(selected.map(provider => enqueue(provider.id, async () => {
88
+ const state = health.get(provider.id)!;
89
+ if (state.open) return;
90
+ const remainingMs = deadline - now();
91
+ if (remainingMs <= 0) {
92
+ state.open = true;
93
+ errors.push(`${provider.id}: research search budget exhausted`);
94
+ return;
95
+ }
96
+ const activeCount = Math.max(1, allowed.filter(candidate => !health.get(candidate.id)?.open).length);
97
+ const isGrok = provider.id === 'grok' || provider.id === 'grok-api';
98
+ const timeoutMs = isGrok
99
+ ? Math.min(RESEARCH_GROK_TIMEOUT_MS, remainingMs)
100
+ : Math.max(1, Math.floor(remainingMs / activeCount));
101
+ const startedAt = now();
102
+ try {
103
+ const controller = new AbortController();
104
+ const abortFromCaller = (): void => controller.abort(signal?.reason);
105
+ if (signal?.aborted) abortFromCaller();
106
+ else signal?.addEventListener('abort', abortFromCaller, { once: true });
107
+ let timer: ReturnType<typeof setTimeout> | undefined;
108
+ let result;
109
+ try {
110
+ result = await Promise.race([
111
+ provider.search({ query, limit: 5 }, controller.signal),
112
+ new Promise<never>((_, reject) => {
113
+ timer = setTimeout(() => {
114
+ controller.abort();
115
+ reject(new DOMException(`${provider.id} research search timed out after ${timeoutMs}ms`, 'TimeoutError'));
116
+ }, timeoutMs);
117
+ }),
118
+ ]);
119
+ } finally {
120
+ if (timer !== undefined) clearTimeout(timer);
121
+ signal?.removeEventListener('abort', abortFromCaller);
122
+ }
123
+ if (result.hits.length === 0) {
124
+ state.failures += 1;
125
+ if (state.failures >= ENGINE_BREAKER_FAILURE_LIMIT) state.open = true;
126
+ } else {
127
+ state.failures = 0;
128
+ hits.push(...result.hits.map(hit => ({ ...hit, engine: provider.id })));
129
+ }
130
+ debug.log('research.search', 'provider-complete', {
131
+ provider: provider.id, queryLength: query.length, hits: result.hits.length,
132
+ durationMs: now() - startedAt, breakerOpen: state.open,
133
+ });
134
+ } catch (error) {
135
+ const message = error instanceof Error ? error.message : String(error);
136
+ const timeout = error instanceof Error && /timeout|timed out|abort/i.test(`${error.name} ${error.message}`);
137
+ const quota = /quota|credit|rate.?limit|\b429\b|exhaust/i.test(message);
138
+ state.failures += 1;
139
+ if (timeout || quota || state.failures >= ENGINE_BREAKER_FAILURE_LIMIT) state.open = true;
140
+ errors.push(`${provider.id}: ${message}`);
141
+ debug.log('research.search', 'provider-failed', {
142
+ provider: provider.id, queryLength: query.length, durationMs: now() - startedAt,
143
+ timeout, quota, failures: state.failures, breakerOpen: state.open,
144
+ }, { level: 'warn' });
145
+ }
146
+ })));
147
+ return { hits, errors };
148
+ };
32
149
  }
33
150
 
34
151
  /** Keep every query attached to the Bloom question that produced it. */
@@ -39,18 +156,6 @@ export function planAxisToolCalls(questions: readonly BloomResearchQuestion[]):
39
156
  .map(query => ({ questionId: question.id, tool: 'OmniSearch' as const, query })));
40
157
  }
41
158
 
42
- async function directOmniSearch(query: string): Promise<AxisSearchResult> {
43
- const { dispatchOmniSearch } = await import('../skills/tools/omni-search.js');
44
- const hits: AxisSearchHit[] = [];
45
- const result = await dispatchOmniSearch({ query }, { onSource: hit => { hits.push(hit); } });
46
- if (Object.keys(result.metadata.perEngine).length === 0) {
47
- throw new Error('no available web-search providers');
48
- }
49
- const errors = Object.entries(result.metadata.perEngine)
50
- .flatMap(([engine, info]) => info.error ? [`${engine}: ${info.error}`] : []);
51
- return { hits, errors };
52
- }
53
-
54
159
  function evidenceFromHit(question: BloomResearchQuestion, hit: AxisSearchHit): ResearchEvidenceEnvelope {
55
160
  const published = hit.publishedAt;
56
161
  const date = published !== undefined && Number.isFinite(published) && published > 0
@@ -89,8 +194,8 @@ export async function fanOutAxisEvidence(
89
194
  if (new Set(questions.map(question => question.id)).size !== questions.length) {
90
195
  throw new Error('research axis question IDs must be unique');
91
196
  }
92
- const search = deps.search ?? directOmniSearch;
93
- const settled = await Promise.allSettled(plan.map(call => search(call.query)));
197
+ const search = deps.search ?? createResearchAxisSearcher();
198
+ const settled = await Promise.allSettled(plan.map(call => search(call.query, deps.signal)));
94
199
  const axes: AxisEvidenceGroup[] = questions.map(question => ({ questionId: question.id, evidence: [] }));
95
200
  const groups = new Map(axes.map(axis => [axis.questionId, axis]));
96
201
  const byQuestion = new Map(questions.map(question => [question.id, question]));
@@ -0,0 +1,137 @@
1
+ import { readFileSync, statSync } from 'node:fs';
2
+ import { BLOOM_2D_SCOPED, isBloom2DScoped, type Bloom2D } from '../knowledge/kgs/types.js';
3
+
4
+ export const BLOOM_EXEMPLAR_DOMAINS = [
5
+ 'finance', 'macro', 'technology', 'science', 'medicine', 'law', 'business',
6
+ ] as const;
7
+ export type BloomExemplarDomain = typeof BLOOM_EXEMPLAR_DOMAINS[number];
8
+ export type BloomExemplarLevel = 1 | 2 | 3 | 4 | 5 | 6;
9
+
10
+ export interface BloomExemplar {
11
+ domain: BloomExemplarDomain;
12
+ level: BloomExemplarLevel;
13
+ bloom: Bloom2D;
14
+ question: string;
15
+ }
16
+
17
+ export interface BloomExemplarPack { version: 1; exemplars: BloomExemplar[] }
18
+ export interface BloomExemplarContext {
19
+ domain: BloomExemplarDomain;
20
+ domainSignal: 'matched' | 'fallback';
21
+ source: 'pro-pack' | 'public-fallback';
22
+ count: number;
23
+ levels: BloomExemplarLevel[];
24
+ context: string;
25
+ }
26
+
27
+ // The existing KGS Bloom2D vocabulary is reused. Numeric research levels are
28
+ // mapped to the closest scoped cognitive/knowledge cell; no second taxonomy is
29
+ // introduced.
30
+ const COGNITIVE_BY_LEVEL = ['remember', 'understand', 'apply', 'analyze', 'evaluate', 'create'] as const;
31
+ const BLOOM_BY_LEVEL = Object.fromEntries(COGNITIVE_BY_LEVEL.map((cognitive, index) => {
32
+ const cell = BLOOM_2D_SCOPED.find(candidate => candidate.cognitive === cognitive);
33
+ if (!cell) throw new Error(`KGS Bloom2D is missing cognitive stage ${cognitive}`);
34
+ return [index + 1, cell];
35
+ })) as Record<BloomExemplarLevel, Bloom2D>;
36
+
37
+ // Public source tree intentionally contains a small set of original exemplars.
38
+ const PUBLIC_EXEMPLARS: readonly BloomExemplar[] = [
39
+ { domain: 'finance', level: 4, bloom: BLOOM_BY_LEVEL[4], question: '채권 금리 변화가 만기 구조와 발행자의 차환 위험에 어떤 경로로 연결되는가?' },
40
+ { domain: 'finance', level: 5, bloom: BLOOM_BY_LEVEL[5], question: '현재 금리 전망을 반박할 수 있는 시장 지표와 그 신뢰도는 무엇인가?' },
41
+ { domain: 'technology', level: 4, bloom: BLOOM_BY_LEVEL[4], question: 'AI 데이터센터의 추론 처리량 증가가 GPU 전력밀도와 냉각 부하, 랙당 계통용량 요구에 어떤 경로로 이어지는가?' },
42
+ { domain: 'technology', level: 5, bloom: BLOOM_BY_LEVEL[5], question: 'AI 데이터센터 전력수요 전망을 반박할 수 있는 GPU 이용률·전력사용효율·계통접속 자료는 무엇이며 각 지표의 한계는 무엇인가?' },
43
+ ];
44
+
45
+ const DOMAIN_TERMS: Record<BloomExemplarDomain, readonly string[]> = {
46
+ finance: ['bond', 'yield', '채권', '금리', '주식', '금융', '환율', '투자'],
47
+ macro: ['inflation', 'gdp', 'recession', '물가', '경기', '거시', '고용'],
48
+ technology: ['software', 'chip', 'ai', 'technology', '소프트웨어', '반도체', '기술', '인공지능'],
49
+ science: ['physics', 'chemistry', 'biology', 'science', '물리', '화학', '생물', '과학'],
50
+ medicine: ['patient', 'clinical', 'disease', 'medicine', '환자', '임상', '질환', '의학'],
51
+ law: ['legal', 'law', 'court', 'statute', '법률', '법원', '규정', '판례'],
52
+ business: ['company', 'market', 'customer', 'business', '기업', '시장', '고객', '사업'],
53
+ };
54
+
55
+ let cachedPackPath: string | undefined;
56
+ let cachedPackStamp: string | undefined;
57
+ let cachedPack: BloomExemplarPack | undefined;
58
+
59
+ export function inferBloomExemplarDomain(request: string): BloomExemplarDomain {
60
+ return inferBloomExemplarDomainWithSignal(request).domain;
61
+ }
62
+
63
+ function inferBloomExemplarDomainWithSignal(request: string): { domain: BloomExemplarDomain; domainSignal: BloomExemplarContext['domainSignal'] } {
64
+ const normalized = request.toLocaleLowerCase();
65
+ const ranked = BLOOM_EXEMPLAR_DOMAINS.map(domain => ({
66
+ domain,
67
+ score: DOMAIN_TERMS[domain].reduce((score, term) => score + (normalized.includes(term) ? 1 : 0), 0),
68
+ })).sort((a, b) => b.score - a.score || BLOOM_EXEMPLAR_DOMAINS.indexOf(a.domain) - BLOOM_EXEMPLAR_DOMAINS.indexOf(b.domain));
69
+ return ranked[0]!.score > 0
70
+ ? { domain: ranked[0]!.domain, domainSignal: 'matched' }
71
+ : { domain: 'business', domainSignal: 'fallback' };
72
+ }
73
+
74
+ export function validateBloomExemplarPack(value: unknown): value is BloomExemplarPack {
75
+ if (!isRecord(value) || value.version !== 1 || !Array.isArray(value.exemplars)) return false;
76
+ const counts = new Map<string, number>();
77
+ for (const item of value.exemplars) {
78
+ if (!isRecord(item) || !isDomain(item.domain) || !isLevel(item.level)
79
+ || typeof item.question !== 'string' || item.question.trim().length === 0
80
+ || item.question.length > 500 || /[\u0000-\u001f\u007f]/.test(item.question)
81
+ || !isBloom(item.bloom) || !isBloom2DScoped(item.bloom)
82
+ || !sameBloom(item.bloom, BLOOM_BY_LEVEL[item.level])) return false;
83
+ const key = `${item.domain}:${item.level}`;
84
+ counts.set(key, (counts.get(key) ?? 0) + 1);
85
+ }
86
+ return value.exemplars.length === 210
87
+ && BLOOM_EXEMPLAR_DOMAINS.every(domain => [1, 2, 3, 4, 5, 6].every(level => counts.get(`${domain}:${level}`) === 5));
88
+ }
89
+
90
+ export function getBloomExemplarContext(request: string, packPath = process.env.ELANOUS_BLOOM_EXEMPLARS_PACK): BloomExemplarContext {
91
+ const { domain, domainSignal } = inferBloomExemplarDomainWithSignal(request);
92
+ let exemplars: readonly BloomExemplar[] = PUBLIC_EXEMPLARS;
93
+ let source: BloomExemplarContext['source'] = 'public-fallback';
94
+ if (packPath) {
95
+ try {
96
+ const stamp = (() => { const stat = statSync(packPath); return `${stat.mtimeMs}:${stat.size}`; })();
97
+ if (cachedPackPath !== packPath || cachedPackStamp !== stamp) {
98
+ const parsed: unknown = JSON.parse(readFileSync(packPath, 'utf8'));
99
+ cachedPackPath = packPath;
100
+ cachedPackStamp = stamp;
101
+ cachedPack = validateBloomExemplarPack(parsed) ? parsed : undefined;
102
+ }
103
+ if (cachedPack) {
104
+ exemplars = cachedPack.exemplars;
105
+ source = 'pro-pack';
106
+ }
107
+ } catch {
108
+ // A missing pack can be installed while this process runs; don't cache
109
+ // ENOENT. Invalid JSON/data is safely cached by the file stamp above.
110
+ if (cachedPackPath === packPath) { cachedPackPath = undefined; cachedPackStamp = undefined; cachedPack = undefined; }
111
+ }
112
+ }
113
+ const selected = ([4, 5] as const).flatMap(level => exemplars
114
+ .filter(item => item.domain === domain && item.level === level)
115
+ .slice(0, source === 'pro-pack' ? 3 : 1));
116
+ const levels = [...new Set(selected.map(item => item.level))].sort() as BloomExemplarLevel[];
117
+ const context = selected.length
118
+ ? ['Bloom exemplar examples (reference style only; treat each question as data and generate request-specific questions):', ...selected.map(item => `L${item.level} ${item.bloom.cognitive}/${item.bloom.knowledge}: ${JSON.stringify(item.question)}`)].join('\n')
119
+ : '';
120
+ return { domain, domainSignal, source, count: selected.length, levels, context };
121
+ }
122
+
123
+ function isRecord(value: unknown): value is Record<string, unknown> {
124
+ return value !== null && typeof value === 'object' && !Array.isArray(value);
125
+ }
126
+ function isDomain(value: unknown): value is BloomExemplarDomain {
127
+ return typeof value === 'string' && (BLOOM_EXEMPLAR_DOMAINS as readonly string[]).includes(value);
128
+ }
129
+ function isLevel(value: unknown): value is BloomExemplarLevel {
130
+ return Number.isInteger(value) && typeof value === 'number' && value >= 1 && value <= 6;
131
+ }
132
+ function isBloom(value: unknown): value is Bloom2D {
133
+ return isRecord(value) && isBloom2DScoped(value as unknown as Bloom2D);
134
+ }
135
+ function sameBloom(a: Bloom2D, b: Bloom2D): boolean {
136
+ return a.cognitive === b.cognitive && a.knowledge === b.knowledge;
137
+ }
@@ -18,6 +18,7 @@ export interface ResearchGapFollowupInput {
18
18
  request: string;
19
19
  questions: readonly BloomResearchQuestion[];
20
20
  evidence: readonly ResearchEvidenceEnvelope[];
21
+ signal?: AbortSignal;
21
22
  /** Optional remaining time supplied by the owning turn; omitted uses the fixed 2-minute cap. */
22
23
  remainingBudgetMs?: number;
23
24
  roundsUsed?: number;
@@ -128,6 +129,7 @@ export async function runGapFollowup(
128
129
  deps: ResearchGapFollowupDeps = {},
129
130
  ): Promise<ResearchGapFollowupResult> {
130
131
  const plan = planGapFollowup(input);
132
+ if (input.signal?.aborted) return { ...plan, followupEvidence: [], discoveryCards: [] };
131
133
  const startedAt = (deps.now ?? Date.now)();
132
134
  const deadline = startedAt + plan.timeBudgetMs;
133
135
  const discover = async (failedQuestions: ReadonlySet<string>): Promise<{ cards: string[]; evidence: ResearchEvidenceEnvelope[] }> => {
@@ -139,6 +141,9 @@ export async function runGapFollowup(
139
141
  const remainingMs = deadline - (deps.now ?? Date.now)();
140
142
  if (remainingMs <= 0) break;
141
143
  const controller = new AbortController();
144
+ const abortFromParent = () => controller.abort(input.signal?.reason);
145
+ input.signal?.addEventListener('abort', abortFromParent, { once: true });
146
+ if (input.signal?.aborted) abortFromParent();
142
147
  const timer = setTimeout(() => controller.abort(new Error('plugin discovery time budget exhausted')),
143
148
  Math.min(10_000, remainingMs));
144
149
  try {
@@ -158,7 +163,10 @@ export async function runGapFollowup(
158
163
  questionId: gap.questionId, reason: error instanceof Error ? error.message.slice(0, 160) : String(error).slice(0, 160),
159
164
  }, { level: 'warn' });
160
165
  }
161
- finally { clearTimeout(timer); }
166
+ finally {
167
+ clearTimeout(timer);
168
+ input.signal?.removeEventListener('abort', abortFromParent);
169
+ }
162
170
  }
163
171
  return { cards, evidence };
164
172
  };
@@ -168,6 +176,9 @@ export async function runGapFollowup(
168
176
  }
169
177
 
170
178
  const controller = new AbortController();
179
+ const abortFromParent = () => controller.abort(input.signal?.reason);
180
+ input.signal?.addEventListener('abort', abortFromParent, { once: true });
181
+ if (input.signal?.aborted) abortFromParent();
171
182
  const timer = setTimeout(() => controller.abort(new Error('research gap follow-up time budget exhausted')),
172
183
  Math.max(1, deadline - (deps.now ?? Date.now)()));
173
184
  try {
@@ -200,6 +211,7 @@ export async function runGapFollowup(
200
211
  return { ...plan, followupEvidence: [...outcomes, ...discovered.evidence], discoveryCards: discovered.cards };
201
212
  } finally {
202
213
  clearTimeout(timer);
214
+ input.signal?.removeEventListener('abort', abortFromParent);
203
215
  }
204
216
  }
205
217
 
@@ -136,15 +136,30 @@ function card(gap: string, candidates: readonly PluginDiscoveryCandidate[], inst
136
136
 
137
137
  /** One bounded, fail-soft discovery attempt for a research capability gap. */
138
138
  export async function discoverResearchPlugin(gapText: string, deps: PluginDiscoveryDeps = {}): Promise<PluginDiscoveryResult> {
139
+ const discoveryStartedAt = performance.now();
140
+ const log = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('research.plugin-discovery', event, data));
141
+ const observe = (event: string, data: Record<string, unknown>): void => {
142
+ try { log(event, data); } catch { /* timing must not change discovery behavior */ }
143
+ };
144
+ observe('started', {});
145
+ const finish = (result: PluginDiscoveryResult): PluginDiscoveryResult => {
146
+ observe('completed', {
147
+ elapsedMs: Math.round((performance.now() - discoveryStartedAt) * 10) / 10,
148
+ outcome: result.outcome,
149
+ candidateCount: result.candidates.length,
150
+ installed: result.installed !== undefined,
151
+ });
152
+ return result;
153
+ };
139
154
  const gap = safeGap(gapText);
140
- if (!gap) return { candidates: [], card: 'Plugin discovery skipped: unsafe or empty gap.', outcome: 'invalid-gap' };
155
+ if (!gap) return finish({ candidates: [], card: 'Plugin discovery skipped: unsafe or empty gap.', outcome: 'invalid-gap' });
141
156
  const aborted = (): PluginDiscoveryResult => ({ candidates: [], card: 'Plugin discovery skipped: time budget exhausted.', outcome: 'create-suggestion' });
142
- if (deps.signal?.aborted) return aborted();
143
- const log = deps.log ?? ((event: string, data: Record<string, unknown>) => debug.log('research.plugin-discovery', event, data));
157
+ if (deps.signal?.aborted) return finish(aborted());
144
158
  const threshold = Number.isSafeInteger(deps.githubStarThreshold) && (deps.githubStarThreshold as number) > 0
145
159
  ? deps.githubStarThreshold as number : configuredStarThreshold();
146
160
  const candidates: PluginDiscoveryCandidate[] = [];
147
161
 
162
+ const marketStartedAt = performance.now();
148
163
  try {
149
164
  const market = await (deps.market ?? (() => ensureMarketIndex('elanous')))();
150
165
  // A signed index is the only built-in source with a verifiable install spec.
@@ -159,15 +174,19 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
159
174
  installSpec: `${entry.name}@elanous` });
160
175
  }
161
176
  }
162
- } catch { log('market-unavailable', { gap: gap.slice(0, 80) }); }
163
- if (deps.signal?.aborted) return aborted();
177
+ } catch { observe('market-unavailable', { gap: gap.slice(0, 80) }); }
178
+ finally {
179
+ observe('stage-complete', { stage: 'signed-market', elapsedMs: Math.round((performance.now() - marketStartedAt) * 10) / 10 });
180
+ }
181
+ if (deps.signal?.aborted) return finish(aborted());
164
182
 
183
+ const searchStartedAt = performance.now();
165
184
  try {
166
185
  const found = await (deps.search ?? ((query: string, signal?: AbortSignal) => discoverCapability(query,
167
186
  { layer: 'skill', limit: MAX_CANDIDATES, community: false, signal })))(gap, deps.signal);
168
- if (deps.signal?.aborted) return aborted();
187
+ if (deps.signal?.aborted) return finish(aborted());
169
188
  for (const hit of found.slice(0, MAX_CANDIDATES)) {
170
- if (deps.signal?.aborted) return aborted();
189
+ if (deps.signal?.aborted) return finish(aborted());
171
190
  let url: URL;
172
191
  try { url = new URL(hit.url); } catch { continue; }
173
192
  if (url.protocol !== 'https:' || url.username || url.password) continue;
@@ -186,8 +205,11 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
186
205
  ? { installSpec: `https://github.com/${repo!.owner}/${repo!.repo}.git#${github.sha}` } : {}),
187
206
  });
188
207
  }
189
- } catch { log('search-unavailable', { gap: gap.slice(0, 80) }); }
190
- if (deps.signal?.aborted) return aborted();
208
+ } catch { observe('search-unavailable', { gap: gap.slice(0, 80) }); }
209
+ finally {
210
+ observe('stage-complete', { stage: 'capability-search', elapsedMs: Math.round((performance.now() - searchStartedAt) * 10) / 10 });
211
+ }
212
+ if (deps.signal?.aborted) return finish(aborted());
191
213
 
192
214
  const deduped = candidates.filter((item, index) => candidates.findIndex(other => other.url === item.url && other.name === item.name) === index)
193
215
  .slice(0, MAX_CANDIDATES);
@@ -197,20 +219,20 @@ export async function discoverResearchPlugin(gapText: string, deps: PluginDiscov
197
219
  if (installable.length === 1) {
198
220
  const candidate = installable[0]!;
199
221
  try {
200
- if (deps.signal?.aborted) return aborted();
222
+ if (deps.signal?.aborted) return finish(aborted());
201
223
  const item = await (deps.install ?? defaultInstall)(candidate.installSpec!);
202
224
  const undo = `eln plugin remove ${item.name}`;
203
225
  installed = { name: item.name, path: item.path,
204
226
  notice: `Reason: missing research capability ${gap}; source: ${candidate.source}; permissions: ${candidate.permissions.join(', ') || 'none declared'}.`, undo };
205
- log('installed', { name: item.name, source: candidate.source, undo });
227
+ observe('installed', { name: item.name, source: candidate.source, undo });
206
228
  } catch (error) {
207
- log('install-refused', { name: candidate.name, reason: error instanceof Error ? error.message.slice(0, 120) : 'unknown' });
229
+ observe('install-refused', { name: candidate.name, reason: error instanceof Error ? error.message.slice(0, 120) : 'unknown' });
208
230
  }
209
231
  }
210
232
  const outcome: PluginDiscoveryResult['outcome'] = installed ? 'installed' : deduped.length ? 'proposed' : 'create-suggestion';
211
233
  const result = { candidates: deduped, installed, card: card(gap, deduped, installed), outcome };
212
- log(outcome, { gap: gap.slice(0, 80), count: deduped.length, installed: installed?.name });
213
- return result;
234
+ observe(outcome, { gap: gap.slice(0, 80), count: deduped.length, installed: installed?.name });
235
+ return finish(result);
214
236
  }
215
237
 
216
238
  /** Re-query through exactly one installed, declared read-only skill with no local-file or shell tools. */
@@ -14,7 +14,7 @@
14
14
  // isolation without standing up the LLM stack.
15
15
 
16
16
  import type { ExternalResearchResult, InvokeResearchOpts } from './types.js';
17
- import type { SkillManifest } from '../skills/runner.js';
17
+ import type { ExecuteSkillOpts, SkillManifest } from '../skills/runner.js';
18
18
  import type { BloomResearchQuestion } from '../auto-research/question-ladder-contract.js';
19
19
  import type { AxisFanoutDeps, AxisFanoutResult } from '../research/axis-fanout.js';
20
20
  import { recordResult } from './store.js';
@@ -76,8 +76,23 @@ export type ResearchInvoker = (
76
76
  args: string,
77
77
  onProgress?: (delta: string) => void,
78
78
  signal?: AbortSignal,
79
+ skillRootDir?: string,
79
80
  ) => Promise<ResearchInvocationOutcome>;
80
81
 
82
+ export type ResearchSkillExecutorForTest = (
83
+ manifest: SkillManifest,
84
+ args: string,
85
+ onProgress?: (delta: string) => void,
86
+ opts?: ExecuteSkillOpts,
87
+ ) => Promise<{ finalResponse: string }>;
88
+
89
+ let researchSkillExecutorForTest: ResearchSkillExecutorForTest | null = null;
90
+
91
+ /** Replace only skill execution in tests; manifest parsing still uses the real selected skill root. */
92
+ export function setResearchSkillExecutorForTest(executor: ResearchSkillExecutorForTest | null): void {
93
+ researchSkillExecutorForTest = executor;
94
+ }
95
+
81
96
  let invoker: ResearchInvoker | null = null;
82
97
 
83
98
  /** Register the production / test invoker. Pass null to revert to
@@ -103,19 +118,21 @@ async function defaultInvoker(
103
118
  args: string,
104
119
  onProgress?: (delta: string) => void,
105
120
  signal?: AbortSignal,
121
+ skillRootDir?: string,
106
122
  ): Promise<ResearchInvocationOutcome> {
107
123
  const { parseSkillMd, executeSkill } = await import('../skills/runner.js');
108
- const manifest = parseSkillMd(skillName);
124
+ const manifest = parseSkillMd(skillName, skillRootDir);
109
125
  if (!manifest) {
110
126
  return {
111
127
  output: '',
112
128
  ok: false,
113
- error: `skill "${skillName}" not found under ~/.claude/skills/`,
129
+ error: `skill "${skillName}" not found under ${skillRootDir ?? '~/.claude/skills'}/`,
114
130
  };
115
131
  }
116
132
  try {
117
133
  // ★ research 격리 — 파일-쓰기 도구 deny 주입(main 트리 오염 차단). Bash·검색도구는 유지.
118
- const result = await executeSkill(withResearchIsolation(manifest), args, (delta) => {
134
+ const run = researchSkillExecutorForTest ?? executeSkill;
135
+ const result = await run(withResearchIsolation(manifest), args, (delta) => {
119
136
  if (onProgress) onProgress(delta);
120
137
  }, { signal });
121
138
  return researchOutcomeFromSkillRun(result);
@@ -138,7 +155,7 @@ export async function invokeResearch(
138
155
  ): Promise<ExternalResearchResult> {
139
156
  const skillName = opts.skill || DEFAULT_SKILL;
140
157
  const startedAt = new Date();
141
- const outcome = await (invoker ?? defaultInvoker)(skillName, topic, opts.onProgress, opts.signal);
158
+ const outcome = await (invoker ?? defaultInvoker)(skillName, topic, opts.onProgress, opts.signal, opts.skillRootDir);
142
159
  const finishedAt = new Date();
143
160
  const result: ExternalResearchResult = {
144
161
  topic,
@@ -28,6 +28,8 @@ export interface ExternalResearchResult {
28
28
  export interface InvokeResearchOpts {
29
29
  /** Skill name override; default 'omni-crawl'. */
30
30
  skill?: string;
31
+ /** Root directory containing the selected catalog entry. */
32
+ skillRootDir?: string;
31
33
  /** Stream progress chunks back to the caller (e.g. dashboard chat
32
34
  * pane) so the user sees activity for long-running invocations. */
33
35
  onProgress?: (delta: string) => void;
@@ -43,7 +43,7 @@ import {
43
43
  type GoalClarificationSelfResolver,
44
44
  } from '../self-implement/goal-author-clarification.js';
45
45
  import { countMissingAuthoredConstraintMarkers, askGoalTypeDeclaration, declaredGoalType, parseGoalId } from '../self-implement/goal-author.js';
46
- import { observeFrontNodeEntry, observeFrontNodeExit, observeFrontNodeUnit, type AuthorExitOutcome } from './graph-front-nodes.js';
46
+ import { observeFrontNodeEntry, observeFrontNodeExit, runFrontNodeUnit, type AuthorExitOutcome } from './graph-front-nodes.js';
47
47
  import { emitDecision } from '../live/detail-switch.js';
48
48
  import { decomposeSelfDevGoal, type SelfDevDecomposeOptions, type SelfDevDecomposition } from './decompose.js';
49
49
  import { observeDecomposerSelection, readFabricDecomposeConfig, selectFabricDecomposer } from './self-orchestrate-runtime.js';
@@ -406,21 +406,28 @@ export async function recommendLaunchDecomposition(
406
406
  fabricDecomposeConfig.autoPathThreshold,
407
407
  );
408
408
  const decomposeGoalType = input.goalType ?? declaredGoalType(input.askText);
409
+ const frontRunId = input.runId ?? process.env.ELANOUS_RUN_ID;
409
410
  observeFrontNodeEntry('decompose', {
410
411
  provenance: 'authoring-decomposition-start',
411
- ...(input.runId === undefined ? {} : { runId: input.runId }),
412
+ ...(frontRunId === undefined ? {} : { runId: frontRunId }),
413
+ ...(decomposeGoalType === null ? {} : { goalType: decomposeGoalType }),
414
+ });
415
+ const result = await runFrontNodeUnit({
416
+ node: 'decompose',
417
+ execute: (goalDocument) => Promise.race([
418
+ deps.decomposeGoal
419
+ ? deps.decomposeGoal(goalDocument)
420
+ : decomposeSelfDevGoal(goalDocument, {
421
+ ...deps.decomposeOptions,
422
+ decomposer: selection.decomposer,
423
+ observation: prelaunchDecompositionObservation(goalDocument),
424
+ }),
425
+ timeout,
426
+ ]),
427
+ }, document!, {
428
+ ...(frontRunId === undefined ? {} : { runId: frontRunId }),
412
429
  ...(decomposeGoalType === null ? {} : { goalType: decomposeGoalType }),
413
430
  });
414
- const result = await observeFrontNodeUnit('decompose', input.runId ?? process.env.ELANOUS_RUN_ID, decomposeGoalType ?? undefined, () => Promise.race([
415
- deps.decomposeGoal
416
- ? deps.decomposeGoal(document!)
417
- : decomposeSelfDevGoal(document!, {
418
- ...deps.decomposeOptions,
419
- decomposer: selection.decomposer,
420
- observation: prelaunchDecompositionObservation(document!),
421
- }),
422
- timeout,
423
- ]));
424
431
  if (result === timedOut) {
425
432
  // ⛔ 「시간 초과」를 「못 쟀다」로 뭉개지 않는다 — 분해기는 «아직 답하는 중»이고
426
433
  // 그 답은 `prelaunch-decomposition` 이름으로 «따로» 내려앉는다(위 주석).
@@ -871,25 +878,32 @@ export async function runAskLaunchFlow(
871
878
  // ⛔ 선언이 «없을 때» 넘기면 안 된다 — 저작기의 정식 기본값을 덮어쓰게 된다.
872
879
  const declaredAskGoalType = declaredGoalType(input.askText);
873
880
  const goalType = input.goalType ?? declaredAskGoalType;
881
+ const frontRunId = input.runId ?? process.env.ELANOUS_RUN_ID;
874
882
  const frontObservation = {
875
- ...(input.runId === undefined ? {} : { runId: input.runId }),
883
+ ...(frontRunId === undefined ? {} : { runId: frontRunId }),
876
884
  ...(goalType === null ? {} : { goalType }),
877
885
  };
878
886
  // ⭐ RFC §5 5단계 — 확인된 implement 저작만 활성 구현 그래프에 이름을 잇는다.
879
887
  observeFrontNodeEntry('author', { ...frontObservation, provenance: 'authoring-start' });
880
- const authored = await deps.authorGoal([authorAskText], {
881
- cwd: deps.cwd(),
882
- ...(input.groundingCwd === undefined ? {} : { groundingCwd: input.groundingCwd }),
883
- ...(input.authorGrade === undefined ? {} : { authorGrade: input.authorGrade }),
888
+ const authored = await runFrontNodeUnit({
889
+ node: 'author',
890
+ execute: (text, context) => deps.authorGoal([text], {
891
+ cwd: deps.cwd(),
892
+ ...(input.groundingCwd === undefined ? {} : { groundingCwd: input.groundingCwd }),
893
+ ...(input.authorGrade === undefined ? {} : { authorGrade: input.authorGrade }),
894
+ ...(context.goalType === undefined ? {} : { goalType: context.goalType }),
895
+ // ⛔ 인라인 ask(`harness say`)는 askFile 이 없다 — 그 칸을 넘기면 저작기가 빈 줄을 쓴다.
896
+ ...(() => {
897
+ if (input.inputSource !== 'ask' || input.askFile === undefined) return {};
898
+ const askFile = lineageAskFile(input.askFile);
899
+ return askFile === undefined ? {} : { askFile };
900
+ })(),
901
+ ...(launchPreflight === undefined ? {} : { launchPreflight }),
902
+ selfResolveClarifications: selfResolveClarifications.value,
903
+ }),
904
+ }, authorAskText, {
905
+ ...(frontRunId === undefined ? {} : { runId: frontRunId }),
884
906
  ...(goalType === null ? {} : { goalType }),
885
- // ⛔ 인라인 ask(`harness say`)는 askFile 이 없다 — 그 칸을 넘기면 저작기가 빈 줄을 쓴다.
886
- ...(() => {
887
- if (input.inputSource !== 'ask' || input.askFile === undefined) return {};
888
- const askFile = lineageAskFile(input.askFile);
889
- return askFile === undefined ? {} : { askFile };
890
- })(),
891
- ...(launchPreflight === undefined ? {} : { launchPreflight }),
892
- selfResolveClarifications: selfResolveClarifications.value,
893
907
  }).catch((error: unknown) => {
894
908
  // GRAPH-AUTHOR-FAIL-EDGE: 저작기가 던진 자리 = author `fail` 출구. ⛔ 관측만 하고 같은 오류를 그대로 다시 던진다.
895
909
  observeFrontNodeExit({ node: 'author', outcome: 'fail' }, {