create-harness-vibe-coding 0.8.19 → 0.9.3

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 (656) hide show
  1. package/CHANGELOG.md +49 -0
  2. package/README-CN.md +4 -2
  3. package/README.md +23 -4
  4. package/package.json +17 -2
  5. package/src/generator.js +19 -6
  6. package/src/index.js +531 -38
  7. package/src/prompts.js +4 -4
  8. package/src/ui/dist/assets/AgentsRoute-BGGs90wH.js +7 -0
  9. package/src/ui/dist/assets/Assistant-Bold-gm-uSS1B.woff2 +0 -0
  10. package/src/ui/dist/assets/Assistant-Medium-DrcxCXg3.woff2 +0 -0
  11. package/src/ui/dist/assets/Assistant-Regular-DVxZuzxb.woff2 +0 -0
  12. package/src/ui/dist/assets/Assistant-SemiBold-SCI4bEL9.woff2 +0 -0
  13. package/src/ui/dist/assets/Combination-DhBLEmof.js +42 -0
  14. package/src/ui/dist/assets/KaTeX_AMS-Regular-BQhdFMY1.woff2 +0 -0
  15. package/src/ui/dist/assets/KaTeX_AMS-Regular-DMm9YOAa.woff +0 -0
  16. package/src/ui/dist/assets/KaTeX_AMS-Regular-DRggAlZN.ttf +0 -0
  17. package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-ATXxdsX0.ttf +0 -0
  18. package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-BEiXGLvX.woff +0 -0
  19. package/src/ui/dist/assets/KaTeX_Caligraphic-Bold-Dq_IR9rO.woff2 +0 -0
  20. package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-CTRA-rTL.woff +0 -0
  21. package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-Di6jR-x-.woff2 +0 -0
  22. package/src/ui/dist/assets/KaTeX_Caligraphic-Regular-wX97UBjC.ttf +0 -0
  23. package/src/ui/dist/assets/KaTeX_Fraktur-Bold-BdnERNNW.ttf +0 -0
  24. package/src/ui/dist/assets/KaTeX_Fraktur-Bold-BsDP51OF.woff +0 -0
  25. package/src/ui/dist/assets/KaTeX_Fraktur-Bold-CL6g_b3V.woff2 +0 -0
  26. package/src/ui/dist/assets/KaTeX_Fraktur-Regular-CB_wures.ttf +0 -0
  27. package/src/ui/dist/assets/KaTeX_Fraktur-Regular-CTYiF6lA.woff2 +0 -0
  28. package/src/ui/dist/assets/KaTeX_Fraktur-Regular-Dxdc4cR9.woff +0 -0
  29. package/src/ui/dist/assets/KaTeX_Main-Bold-Cx986IdX.woff2 +0 -0
  30. package/src/ui/dist/assets/KaTeX_Main-Bold-Jm3AIy58.woff +0 -0
  31. package/src/ui/dist/assets/KaTeX_Main-Bold-waoOVXN0.ttf +0 -0
  32. package/src/ui/dist/assets/KaTeX_Main-BoldItalic-DxDJ3AOS.woff2 +0 -0
  33. package/src/ui/dist/assets/KaTeX_Main-BoldItalic-DzxPMmG6.ttf +0 -0
  34. package/src/ui/dist/assets/KaTeX_Main-BoldItalic-SpSLRI95.woff +0 -0
  35. package/src/ui/dist/assets/KaTeX_Main-Italic-3WenGoN9.ttf +0 -0
  36. package/src/ui/dist/assets/KaTeX_Main-Italic-BMLOBm91.woff +0 -0
  37. package/src/ui/dist/assets/KaTeX_Main-Italic-NWA7e6Wa.woff2 +0 -0
  38. package/src/ui/dist/assets/KaTeX_Main-Regular-B22Nviop.woff2 +0 -0
  39. package/src/ui/dist/assets/KaTeX_Main-Regular-Dr94JaBh.woff +0 -0
  40. package/src/ui/dist/assets/KaTeX_Main-Regular-ypZvNtVU.ttf +0 -0
  41. package/src/ui/dist/assets/KaTeX_Math-BoldItalic-B3XSjfu4.ttf +0 -0
  42. package/src/ui/dist/assets/KaTeX_Math-BoldItalic-CZnvNsCZ.woff2 +0 -0
  43. package/src/ui/dist/assets/KaTeX_Math-BoldItalic-iY-2wyZ7.woff +0 -0
  44. package/src/ui/dist/assets/KaTeX_Math-Italic-DA0__PXp.woff +0 -0
  45. package/src/ui/dist/assets/KaTeX_Math-Italic-flOr_0UB.ttf +0 -0
  46. package/src/ui/dist/assets/KaTeX_Math-Italic-t53AETM-.woff2 +0 -0
  47. package/src/ui/dist/assets/KaTeX_SansSerif-Bold-CFMepnvq.ttf +0 -0
  48. package/src/ui/dist/assets/KaTeX_SansSerif-Bold-D1sUS0GD.woff2 +0 -0
  49. package/src/ui/dist/assets/KaTeX_SansSerif-Bold-DbIhKOiC.woff +0 -0
  50. package/src/ui/dist/assets/KaTeX_SansSerif-Italic-C3H0VqGB.woff2 +0 -0
  51. package/src/ui/dist/assets/KaTeX_SansSerif-Italic-DN2j7dab.woff +0 -0
  52. package/src/ui/dist/assets/KaTeX_SansSerif-Italic-YYjJ1zSn.ttf +0 -0
  53. package/src/ui/dist/assets/KaTeX_SansSerif-Regular-BNo7hRIc.ttf +0 -0
  54. package/src/ui/dist/assets/KaTeX_SansSerif-Regular-CS6fqUqJ.woff +0 -0
  55. package/src/ui/dist/assets/KaTeX_SansSerif-Regular-DDBCnlJ7.woff2 +0 -0
  56. package/src/ui/dist/assets/KaTeX_Script-Regular-C5JkGWo-.ttf +0 -0
  57. package/src/ui/dist/assets/KaTeX_Script-Regular-D3wIWfF6.woff2 +0 -0
  58. package/src/ui/dist/assets/KaTeX_Script-Regular-D5yQViql.woff +0 -0
  59. package/src/ui/dist/assets/KaTeX_Size1-Regular-C195tn64.woff +0 -0
  60. package/src/ui/dist/assets/KaTeX_Size1-Regular-Dbsnue_I.ttf +0 -0
  61. package/src/ui/dist/assets/KaTeX_Size1-Regular-mCD8mA8B.woff2 +0 -0
  62. package/src/ui/dist/assets/KaTeX_Size2-Regular-B7gKUWhC.ttf +0 -0
  63. package/src/ui/dist/assets/KaTeX_Size2-Regular-Dy4dx90m.woff2 +0 -0
  64. package/src/ui/dist/assets/KaTeX_Size2-Regular-oD1tc_U0.woff +0 -0
  65. package/src/ui/dist/assets/KaTeX_Size3-Regular-CTq5MqoE.woff +0 -0
  66. package/src/ui/dist/assets/KaTeX_Size3-Regular-DgpXs0kz.ttf +0 -0
  67. package/src/ui/dist/assets/KaTeX_Size4-Regular-BF-4gkZK.woff +0 -0
  68. package/src/ui/dist/assets/KaTeX_Size4-Regular-DWFBv043.ttf +0 -0
  69. package/src/ui/dist/assets/KaTeX_Size4-Regular-Dl5lxZxV.woff2 +0 -0
  70. package/src/ui/dist/assets/KaTeX_Typewriter-Regular-C0xS9mPB.woff +0 -0
  71. package/src/ui/dist/assets/KaTeX_Typewriter-Regular-CO6r4hn1.woff2 +0 -0
  72. package/src/ui/dist/assets/KaTeX_Typewriter-Regular-D3Ib7_Hf.ttf +0 -0
  73. package/src/ui/dist/assets/RolesRoute-DnodCSz0.js +2 -0
  74. package/src/ui/dist/assets/RuntimePicker-CucD8TGn.js +7 -0
  75. package/src/ui/dist/assets/SettingsRoute-DquMWjac.js +2 -0
  76. package/src/ui/dist/assets/TaskList-Bxc0Uktx.js +7 -0
  77. package/src/ui/dist/assets/TerminalDrawer-CDusYltc.js +36 -0
  78. package/src/ui/dist/assets/WorkflowRoute-BN8yHmUs.css +1 -0
  79. package/src/ui/dist/assets/WorkflowRoute-D-0wVDpY.js +334 -0
  80. package/src/ui/dist/assets/abnfDiagram-VRR7QNED-zkRKkaxO.js +2 -0
  81. package/src/ui/dist/assets/apl-B4CMkyY2.js +2 -0
  82. package/src/ui/dist/assets/ar-SA-G6X2FPQ2-BiHaArx5.js +11 -0
  83. package/src/ui/dist/assets/arc-CBnLtOFO.js +2 -0
  84. package/src/ui/dist/assets/architectureDiagram-ZJ3FMSHR-DWXRXsh1.js +37 -0
  85. package/src/ui/dist/assets/asciiarmor-Df11BRmG.js +2 -0
  86. package/src/ui/dist/assets/asn1-EdZsLKOL.js +2 -0
  87. package/src/ui/dist/assets/asterisk-B-8jnY81.js +2 -0
  88. package/src/ui/dist/assets/az-AZ-76LH7QW2-CiT05voO.js +2 -0
  89. package/src/ui/dist/assets/bg-BG-XCXSNQG7-L-UM9tNf.js +6 -0
  90. package/src/ui/dist/assets/blockDiagram-677ZJIJ3-BIyh3Bry.js +133 -0
  91. package/src/ui/dist/assets/bn-BD-2XOGV67Q-NdgbA0bC.js +6 -0
  92. package/src/ui/dist/assets/brainfuck-C4LP7Hcl.js +2 -0
  93. package/src/ui/dist/assets/c4Diagram-LMCZKHZV-CA54vWWM.js +11 -0
  94. package/src/ui/dist/assets/ca-ES-6MX7JW3Y-BKZZsQ5J.js +9 -0
  95. package/src/ui/dist/assets/channel-Da_-zcAu.js +2 -0
  96. package/src/ui/dist/assets/chunk-2Q5K7J3B-DE4cxr1v.js +2 -0
  97. package/src/ui/dist/assets/chunk-32BRIVSS-i7FwbEU9.js +2 -0
  98. package/src/ui/dist/assets/chunk-5VM5RSS4-BhIcOYSu.js +16 -0
  99. package/src/ui/dist/assets/chunk-EX3LRPZG-Ci9zZRIs.js +232 -0
  100. package/src/ui/dist/assets/chunk-JWPE2WC7-BFdkcz-G.js +2 -0
  101. package/src/ui/dist/assets/chunk-MOJQB5TN-Dzmapl_S.js +89 -0
  102. package/src/ui/dist/assets/chunk-RYQCIY6F-RTmp7FOy.js +2 -0
  103. package/src/ui/dist/assets/chunk-V7JOEXUC-DInU3v3D.js +207 -0
  104. package/src/ui/dist/assets/chunk-VR4S4FIN-BHoyGBQO.js +2 -0
  105. package/src/ui/dist/assets/chunk-XXDRQBXY-DfeLZNZx.js +2 -0
  106. package/src/ui/dist/assets/classDiagram-OUVF2IWQ-FKbUS0bu.js +2 -0
  107. package/src/ui/dist/assets/classDiagram-v2-EOCWNBFH-FKbUS0bu.js +2 -0
  108. package/src/ui/dist/assets/clike-B9uivgTg.js +2 -0
  109. package/src/ui/dist/assets/clojure-BMjYHr_A.js +2 -0
  110. package/src/ui/dist/assets/cmake-BQqOBYOt.js +2 -0
  111. package/src/ui/dist/assets/cobol-CWcv1MsR.js +2 -0
  112. package/src/ui/dist/assets/coffeescript-S37ZYGWr.js +2 -0
  113. package/src/ui/dist/assets/commonlisp-DBKNyK5s.js +2 -0
  114. package/src/ui/dist/assets/cose-bilkent-JH36ORCC-_5PUJ615.js +2 -0
  115. package/src/ui/dist/assets/crystal-SjHAIU92.js +2 -0
  116. package/src/ui/dist/assets/cs-CZ-2BRQDIVT-DnkfnhDU.js +12 -0
  117. package/src/ui/dist/assets/css-BnMrqG3P.js +2 -0
  118. package/src/ui/dist/assets/cynefin-VYW2F7L2-CmkcFv-b.js +179 -0
  119. package/src/ui/dist/assets/cynefinDiagram-TSTJHNR4-D72VZn8H.js +63 -0
  120. package/src/ui/dist/assets/cypher-C_CwsFkJ.js +2 -0
  121. package/src/ui/dist/assets/cytoscape.esm-DTSO7Bv0.js +332 -0
  122. package/src/ui/dist/assets/d-pRatUO7H.js +2 -0
  123. package/src/ui/dist/assets/da-DK-5WZEPLOC-C54tQUgd.js +6 -0
  124. package/src/ui/dist/assets/dagre-VKFMJZFB-0BsAkrmo.js +5 -0
  125. package/src/ui/dist/assets/de-DE-XR44H4JA-DGfZlR10.js +9 -0
  126. package/src/ui/dist/assets/defaultLocale-DX6XiGOO.js +2 -0
  127. package/src/ui/dist/assets/diagram-FQU43EPY-C1ZJDOca.js +4 -0
  128. package/src/ui/dist/assets/diagram-G47NLZAW-D3pr3FSP.js +25 -0
  129. package/src/ui/dist/assets/diagram-NH7WQ7WH-Bwry0NV-.js +25 -0
  130. package/src/ui/dist/assets/diagram-OA4YK3LP-L6g09cmV.js +31 -0
  131. package/src/ui/dist/assets/diagram-WEI45ONY-Bh1puYVX.js +42 -0
  132. package/src/ui/dist/assets/diff-DbItnlRl.js +2 -0
  133. package/src/ui/dist/assets/directory-open-01563666-DWU9wJ6I.js +2 -0
  134. package/src/ui/dist/assets/directory-open-4ed118d0-CunoC1EB.js +2 -0
  135. package/src/ui/dist/assets/dockerfile-BKs6k2Af.js +2 -0
  136. package/src/ui/dist/assets/dtd-DF_7sFjM.js +2 -0
  137. package/src/ui/dist/assets/dylan-DwRh75JA.js +2 -0
  138. package/src/ui/dist/assets/ebnf-CDyGwa7X.js +2 -0
  139. package/src/ui/dist/assets/ebnfDiagram-CCIWWBDH-BC_mBRR5.js +2 -0
  140. package/src/ui/dist/assets/ecl-Cabwm37j.js +2 -0
  141. package/src/ui/dist/assets/eiffel-CnydiIhH.js +2 -0
  142. package/src/ui/dist/assets/el-GR-BZB4AONW-DsnwWweL.js +11 -0
  143. package/src/ui/dist/assets/elm-vLlmbW-K.js +2 -0
  144. package/src/ui/dist/assets/erDiagram-Q63AITRT-Bkxam36l.js +86 -0
  145. package/src/ui/dist/assets/erlang-BNw1qcRV.js +2 -0
  146. package/src/ui/dist/assets/es-ES-U4NZUMDT-CRxBcQgC.js +10 -0
  147. package/src/ui/dist/assets/eu-ES-A7QVB2H4-CTd_E7YR.js +12 -0
  148. package/src/ui/dist/assets/excalidraw-default-bMWIgNCy.svg +1 -0
  149. package/src/ui/dist/assets/fa-IR-HGAKTJCU-DO56k7eG.js +9 -0
  150. package/src/ui/dist/assets/factor-kuTfRLto.js +2 -0
  151. package/src/ui/dist/assets/fcl-Kvtd6kyn.js +2 -0
  152. package/src/ui/dist/assets/fi-FI-Z5N7JZ37-DEDCF9WB.js +7 -0
  153. package/src/ui/dist/assets/file-open-002ab408-DIuFHtCF.js +2 -0
  154. package/src/ui/dist/assets/file-open-7c801643-684qeFg4.js +2 -0
  155. package/src/ui/dist/assets/file-save-3189631c-C1wFhQhH.js +2 -0
  156. package/src/ui/dist/assets/file-save-745eba88-Bb9F9Kg7.js +2 -0
  157. package/src/ui/dist/assets/flowDiagram-23GEKE2U-C3SAEao7.js +157 -0
  158. package/src/ui/dist/assets/forth-Ffai-XNe.js +2 -0
  159. package/src/ui/dist/assets/fortran-DYz_wnZ1.js +2 -0
  160. package/src/ui/dist/assets/fr-FR-RHASNOE6-DE2nPyDt.js +10 -0
  161. package/src/ui/dist/assets/ganttDiagram-NO4QXBWP-U-J_Xi-_.js +293 -0
  162. package/src/ui/dist/assets/gas-Bneqetm1.js +2 -0
  163. package/src/ui/dist/assets/gherkin-heZmZLOM.js +2 -0
  164. package/src/ui/dist/assets/gitGraphDiagram-IHSO6WYX-BADVbD-a.js +107 -0
  165. package/src/ui/dist/assets/gl-ES-HMX3MZ6V-mCqVgQHC.js +11 -0
  166. package/src/ui/dist/assets/graph-C9eacEi8.js +2 -0
  167. package/src/ui/dist/assets/groovy-D9Dt4D0W.js +2 -0
  168. package/src/ui/dist/assets/haskell-Cw1EW3IL.js +2 -0
  169. package/src/ui/dist/assets/haxe-H-WmDvRZ.js +2 -0
  170. package/src/ui/dist/assets/he-IL-6SHJWFNN-KnaLrCzw.js +11 -0
  171. package/src/ui/dist/assets/hi-IN-IWLTKZ5I-wuqiaaWt.js +5 -0
  172. package/src/ui/dist/assets/http-DBlCnlav.js +2 -0
  173. package/src/ui/dist/assets/hu-HU-A5ZG7DT2-DLg_zm22.js +8 -0
  174. package/src/ui/dist/assets/id-ID-SAP4L64H-MB2mXqcR.js +11 -0
  175. package/src/ui/dist/assets/idl-BEugSyMb.js +2 -0
  176. package/src/ui/dist/assets/image-blob-reduce.esm-HwCm7IZ0.js +8 -0
  177. package/src/ui/dist/assets/index-39SJtrt0.js +2 -0
  178. package/src/ui/dist/assets/index-BQ0LIrW-.js +2 -0
  179. package/src/ui/dist/assets/index-BcAUh2Nm.css +1 -0
  180. package/src/ui/dist/assets/index-BcThOK-i.js +331 -0
  181. package/src/ui/dist/assets/index-BnxV3k_S.js +3 -0
  182. package/src/ui/dist/assets/index-C7MZBHbT.js +117 -0
  183. package/src/ui/dist/assets/index-CCvKI2rM.js +2 -0
  184. package/src/ui/dist/assets/index-CZvmcCab.js +8 -0
  185. package/src/ui/dist/assets/index-Cp3hLKNl.js +2 -0
  186. package/src/ui/dist/assets/index-D7ayFxcx.js +2 -0
  187. package/src/ui/dist/assets/index-DAYxSQGU.js +2 -0
  188. package/src/ui/dist/assets/index-DD-HeMV0.css +1 -0
  189. package/src/ui/dist/assets/index-DPMxd3Qn.js +2 -0
  190. package/src/ui/dist/assets/index-DSe2jx3k.js +4 -0
  191. package/src/ui/dist/assets/index-DUirCkgW.js +2 -0
  192. package/src/ui/dist/assets/index-DaKPQ2hN.js +159 -0
  193. package/src/ui/dist/assets/index-DzpuR0Jg.js +2 -0
  194. package/src/ui/dist/assets/index-POndwsCI.js +2 -0
  195. package/src/ui/dist/assets/index-R8NM9I_9.js +2 -0
  196. package/src/ui/dist/assets/index-TCDuDhBj.js +2 -0
  197. package/src/ui/dist/assets/index-TckzASdM.js +2 -0
  198. package/src/ui/dist/assets/index-Yi5ytFFr.js +2 -0
  199. package/src/ui/dist/assets/infoDiagram-FWYZ7A6U-CiGBlFqH.js +3 -0
  200. package/src/ui/dist/assets/init-Gi6I4Gst.js +2 -0
  201. package/src/ui/dist/assets/ishikawaDiagram-FXEZZL3T-B1aheRbz.js +71 -0
  202. package/src/ui/dist/assets/it-IT-JPQ66NNP-DT3HSU7X.js +12 -0
  203. package/src/ui/dist/assets/ja-JP-DBVTYXUO-CsfJjjWt.js +9 -0
  204. package/src/ui/dist/assets/javascript-iXu5QeM3.js +2 -0
  205. package/src/ui/dist/assets/journeyDiagram-5HDEW3XC-DtnJPxub.js +140 -0
  206. package/src/ui/dist/assets/julia-DuME0IfC.js +2 -0
  207. package/src/ui/dist/assets/kaa-6HZHGXH3-DQz-1-Gn.js +2 -0
  208. package/src/ui/dist/assets/kab-KAB-ZGHBKWFO-CaH-LSoK.js +9 -0
  209. package/src/ui/dist/assets/kanban-definition-HUTT4EX6-CZatSm3e.js +90 -0
  210. package/src/ui/dist/assets/katex-C5jXJg4s.js +258 -0
  211. package/src/ui/dist/assets/kk-KZ-P5N5QNE5-BMXmcm55.js +2 -0
  212. package/src/ui/dist/assets/km-KH-HSX4SM5Z-ZeoJNBpN.js +12 -0
  213. package/src/ui/dist/assets/ko-KR-MTYHY66A-BeaLRKph.js +10 -0
  214. package/src/ui/dist/assets/ku-TR-6OUDTVRD-B_28KrkR.js +10 -0
  215. package/src/ui/dist/assets/layout-DEXfKzaS.js +2 -0
  216. package/src/ui/dist/assets/linear-CpEDnQRC.js +2 -0
  217. package/src/ui/dist/assets/livescript-BwQOo05w.js +2 -0
  218. package/src/ui/dist/assets/lt-LT-XHIRWOB4-BxDcnUhp.js +4 -0
  219. package/src/ui/dist/assets/lua-VAEuO923.js +2 -0
  220. package/src/ui/dist/assets/lv-LV-5QDEKY6T-DpKDl1_y.js +8 -0
  221. package/src/ui/dist/assets/map-Czzmt4hB.js +2 -0
  222. package/src/ui/dist/assets/mathematica-DTrFuWx2.js +2 -0
  223. package/src/ui/dist/assets/mbox-CNhZ1qSd.js +2 -0
  224. package/src/ui/dist/assets/mermaidLoader-CBO31t0J.js +305 -0
  225. package/src/ui/dist/assets/mermaidLoader-CEK31ho9.css +1 -0
  226. package/src/ui/dist/assets/mindmap-definition-LN4V7U3C-CQ0TccEr.js +97 -0
  227. package/src/ui/dist/assets/mirc-CjQqDB4T.js +2 -0
  228. package/src/ui/dist/assets/mllike-CXdrOF99.js +2 -0
  229. package/src/ui/dist/assets/modelica-Dc1JOy9r.js +2 -0
  230. package/src/ui/dist/assets/mr-IN-CRQNXWMA-BKCZT58p.js +14 -0
  231. package/src/ui/dist/assets/mscgen-BA5vi2Kp.js +2 -0
  232. package/src/ui/dist/assets/mumps-BT43cFF4.js +2 -0
  233. package/src/ui/dist/assets/my-MM-5M5IBNSE-D34k0G9T.js +2 -0
  234. package/src/ui/dist/assets/nb-NO-T6EIAALU-DXr_KW8J.js +11 -0
  235. package/src/ui/dist/assets/nginx-DdIZxoE0.js +2 -0
  236. package/src/ui/dist/assets/nl-NL-IS3SIHDZ-C1L0aVDR.js +9 -0
  237. package/src/ui/dist/assets/nn-NO-6E72VCQL-CLWVSxbZ.js +9 -0
  238. package/src/ui/dist/assets/nsis-LdVXkNf5.js +2 -0
  239. package/src/ui/dist/assets/ntriples-BfvgReVJ.js +2 -0
  240. package/src/ui/dist/assets/oc-FR-POXYY2M6-nf8_J3eR.js +9 -0
  241. package/src/ui/dist/assets/octave-Ck1zUtKM.js +2 -0
  242. package/src/ui/dist/assets/ordinal-Cboi1Yqb.js +2 -0
  243. package/src/ui/dist/assets/oz-BzwKVEFT.js +2 -0
  244. package/src/ui/dist/assets/pa-IN-N4M65BXN-CAMJ-xd6.js +5 -0
  245. package/src/ui/dist/assets/pascal--L3eBynH.js +2 -0
  246. package/src/ui/dist/assets/pegDiagram-2B236MQR-Bj2RcmRd.js +2 -0
  247. package/src/ui/dist/assets/percentages-BXMCSKIN-s9yWFdr6.js +160 -0
  248. package/src/ui/dist/assets/perl-CdXCOZ3F.js +2 -0
  249. package/src/ui/dist/assets/pica-BGv_AhAB.js +8 -0
  250. package/src/ui/dist/assets/pieDiagram-ENE6RG2P-obpzz8dC.js +40 -0
  251. package/src/ui/dist/assets/pig-CevX1Tat.js +2 -0
  252. package/src/ui/dist/assets/pl-PL-T2D74RX3-DKJ5H85v.js +10 -0
  253. package/src/ui/dist/assets/powershell-CFHJl5sT.js +2 -0
  254. package/src/ui/dist/assets/properties-C78fOPTZ.js +2 -0
  255. package/src/ui/dist/assets/protobuf-ChK-085T.js +2 -0
  256. package/src/ui/dist/assets/{proxy-D0vUbds5.js → proxy-BSmwef4H.js} +2 -2
  257. package/src/ui/dist/assets/pt-BR-5N22H2LF-B5kow-kN.js +10 -0
  258. package/src/ui/dist/assets/pt-PT-UZXXM6DQ-B2G34fso.js +10 -0
  259. package/src/ui/dist/assets/pug-DeIclll2.js +2 -0
  260. package/src/ui/dist/assets/puppet-DMA9R1ak.js +2 -0
  261. package/src/ui/dist/assets/python-BuPzkPfP.js +2 -0
  262. package/src/ui/dist/assets/q-pXgVlZs6.js +2 -0
  263. package/src/ui/dist/assets/quadrantDiagram-ABIIQ3AL-Cl-T7NkJ.js +8 -0
  264. package/src/ui/dist/assets/r-B6wPVr8A.js +2 -0
  265. package/src/ui/dist/assets/railroadDiagram-RFXS5EU6-DMq82RHg.js +2 -0
  266. package/src/ui/dist/assets/{refresh-cw-JNmExijd.js → refresh-cw-CbFd7guV.js} +2 -2
  267. package/src/ui/dist/assets/requirementDiagram-TGXJPOKE-tGInMDgU.js +85 -0
  268. package/src/ui/dist/assets/ro-RO-JPDTUUEW-BwLdZW91.js +12 -0
  269. package/src/ui/dist/assets/roundRect-0PYZxl1G.js +2 -0
  270. package/src/ui/dist/assets/rpm-CTu-6PCP.js +2 -0
  271. package/src/ui/dist/assets/ru-RU-B4JR7IUQ-DpdAgIJc.js +10 -0
  272. package/src/ui/dist/assets/ruby-B2Rjki9n.js +2 -0
  273. package/src/ui/dist/assets/runtimeBrand-BoKPimsz.js +2 -0
  274. package/src/ui/dist/assets/sankeyDiagram-HTMAVEWB-C7X-ET4m.js +41 -0
  275. package/src/ui/dist/assets/sas-B4kiWyti.js +2 -0
  276. package/src/ui/dist/assets/save-D1CXHwBw.js +12 -0
  277. package/src/ui/dist/assets/scheme-C41bIUwD.js +2 -0
  278. package/src/ui/dist/assets/sequenceDiagram-DBY2YBRQ-Bn24i_nY.js +163 -0
  279. package/src/ui/dist/assets/settings-2-DtSNAAcU.js +22 -0
  280. package/src/ui/dist/assets/shell-CjFT_Tl9.js +2 -0
  281. package/src/ui/dist/assets/shield-check-BVbJ8T_N.js +7 -0
  282. package/src/ui/dist/assets/si-LK-N5RQ5JYF-naJaUy5u.js +2 -0
  283. package/src/ui/dist/assets/sieve-C3Gn_uJK.js +2 -0
  284. package/src/ui/dist/assets/simple-mode-GW_nhZxv.js +2 -0
  285. package/src/ui/dist/assets/sizeCapture-X5ZJPWSS-DAQHfm82.js +2 -0
  286. package/src/ui/dist/assets/sk-SK-C5VTKIMK-1NPz1J_d.js +7 -0
  287. package/src/ui/dist/assets/sl-SI-NN7IZMDC-D8RfmNQw.js +7 -0
  288. package/src/ui/dist/assets/smalltalk-CnHTOXQT.js +2 -0
  289. package/src/ui/dist/assets/solr-DehyRSwq.js +2 -0
  290. package/src/ui/dist/assets/sparql-DkYu6x3z.js +2 -0
  291. package/src/ui/dist/assets/spreadsheet-BCZA_wO0.js +2 -0
  292. package/src/ui/dist/assets/sql-D0XecflT.js +2 -0
  293. package/src/ui/dist/assets/stateDiagram-2N3HPSRC-Ck48D1ck.js +2 -0
  294. package/src/ui/dist/assets/stateDiagram-v2-6OUMAXLB-CdfRCJAJ.js +2 -0
  295. package/src/ui/dist/assets/stex-C3f8Ysf7.js +2 -0
  296. package/src/ui/dist/assets/style-C3QI7VPf.css +1 -0
  297. package/src/ui/dist/assets/stylus-B533Al4x.js +2 -0
  298. package/src/ui/dist/assets/subset-shared.chunk-eAtLHmbi.js +85 -0
  299. package/src/ui/dist/assets/subset-worker.chunk-DeHCTnTk.js +2 -0
  300. package/src/ui/dist/assets/sv-SE-XGPEYMSR-BeOYCU-8.js +11 -0
  301. package/src/ui/dist/assets/swift-BzpIVaGY.js +2 -0
  302. package/src/ui/dist/assets/swimlanes-5IMT3BWC-DOy22UjP.js +3 -0
  303. package/src/ui/dist/assets/swimlanesDiagram-G3AALYLV-sicPbVOg.js +9 -0
  304. package/src/ui/dist/assets/ta-IN-2NMHFXQM-CtS68WDd.js +10 -0
  305. package/src/ui/dist/assets/tcl-DVfN8rqt.js +2 -0
  306. package/src/ui/dist/assets/{terminal-BBQvnOAK.js → terminal-DEby5Y_P.js} +2 -2
  307. package/src/ui/dist/assets/terminalControl-BkFeDVXo.js +134 -0
  308. package/src/ui/dist/assets/textile-CnDTJFAw.js +2 -0
  309. package/src/ui/dist/assets/th-TH-HPSO5L25-DCHY9-Co.js +3 -0
  310. package/src/ui/dist/assets/tiddlywiki-DO-Gjzrf.js +2 -0
  311. package/src/ui/dist/assets/tiki-DGYXhP31.js +2 -0
  312. package/src/ui/dist/assets/timeline-definition-FHXFAJF6-DVkG72qO.js +121 -0
  313. package/src/ui/dist/assets/toml-Bm5Em-hy.js +2 -0
  314. package/src/ui/dist/assets/tr-TR-DEFEU3FU-y5-vjTv8.js +8 -0
  315. package/src/ui/dist/assets/troff-wAsdV37c.js +2 -0
  316. package/src/ui/dist/assets/ttcn-CfJYG6tj.js +2 -0
  317. package/src/ui/dist/assets/ttcn-cfg-B9xdYoR4.js +2 -0
  318. package/src/ui/dist/assets/turtle-B1tBg_DP.js +2 -0
  319. package/src/ui/dist/assets/uk-UA-QMV73CPH-BRbR5It6.js +7 -0
  320. package/src/ui/dist/assets/useReducedMotion-D07XP52Q.js +12 -0
  321. package/src/ui/dist/assets/vb-CmGdzxic.js +2 -0
  322. package/src/ui/dist/assets/vbscript-BuJXcnF6.js +2 -0
  323. package/src/ui/dist/assets/velocity-D8B20fx6.js +2 -0
  324. package/src/ui/dist/assets/vennDiagram-L72KCM5P-DwMwBlf-.js +35 -0
  325. package/src/ui/dist/assets/verilog-C6RDOZhf.js +2 -0
  326. package/src/ui/dist/assets/vhdl-lSbBsy5d.js +2 -0
  327. package/src/ui/dist/assets/vi-VN-M7AON7JQ-s6wSBv2s.js +6 -0
  328. package/src/ui/dist/assets/wardleyDiagram-EHGQE667-CNuuvzEg.js +79 -0
  329. package/src/ui/dist/assets/webidl-ZXfAyPTL.js +2 -0
  330. package/src/ui/dist/assets/{x-DoIOGAJz.js → x-B84wq78k.js} +2 -2
  331. package/src/ui/dist/assets/xquery-DzFWVndE.js +2 -0
  332. package/src/ui/dist/assets/xychartDiagram-FW5EYKEG-dUpZxmn6.js +8 -0
  333. package/src/ui/dist/assets/yacas-BJ4BC0dw.js +2 -0
  334. package/src/ui/dist/assets/z80-Hz9HOZM7.js +2 -0
  335. package/src/ui/dist/assets/zh-CN-LNUGB5OW-Cu_-POQN.js +11 -0
  336. package/src/ui/dist/assets/zh-HK-E62DVLB3-BCx4W4qZ.js +2 -0
  337. package/src/ui/dist/assets/zh-TW-RAJ6MFWO-02wx_Mrj.js +10 -0
  338. package/src/ui/dist/icons/excalidraw.svg +1 -0
  339. package/src/ui/dist/icons/markdown.svg +1 -0
  340. package/src/ui/dist/index.html +2 -2
  341. package/src/ui/package.json +10 -0
  342. package/src/ui/playwright.config.ts +36 -0
  343. package/src/ui/pnpm-workspace.yaml +2 -0
  344. package/src/ui/public/icons/excalidraw.svg +1 -0
  345. package/src/ui/public/icons/markdown.svg +1 -0
  346. package/src/ui/tsconfig.json +2 -1
  347. package/src/ui/vite.config.ts +1 -0
  348. package/src/wf-ui-server/__tests__/a2a-store.test.mjs +432 -15
  349. package/src/wf-ui-server/__tests__/action-registry-loader.test.mjs +156 -0
  350. package/src/wf-ui-server/__tests__/claude-stream-json.test.mjs +397 -0
  351. package/src/wf-ui-server/__tests__/codex-appserver.test.mjs +392 -0
  352. package/src/wf-ui-server/__tests__/component-node-api.test.mjs +881 -0
  353. package/src/wf-ui-server/__tests__/component-node-store.test.mjs +401 -0
  354. package/src/wf-ui-server/__tests__/control-plane-acceptance.test.mjs +2027 -0
  355. package/src/wf-ui-server/__tests__/control-plane-cli-smoke.test.mjs +1014 -0
  356. package/src/wf-ui-server/__tests__/dispatch-lifecycle.test.mjs +330 -0
  357. package/src/wf-ui-server/__tests__/effort-compatibility-red-092.test.mjs +151 -0
  358. package/src/wf-ui-server/__tests__/graph-layout-agent-tree.test.mjs +254 -0
  359. package/src/wf-ui-server/__tests__/graph-layout-tidy.test.mjs +260 -0
  360. package/src/wf-ui-server/__tests__/graph-layout.test.mjs +84 -0
  361. package/src/wf-ui-server/__tests__/node-config-api.test.mjs +384 -0
  362. package/src/wf-ui-server/__tests__/opencode-server.test.mjs +526 -0
  363. package/src/wf-ui-server/__tests__/peer-capsule.test.mjs +2 -2
  364. package/src/wf-ui-server/__tests__/pty-adapter.test.mjs +71 -1
  365. package/src/wf-ui-server/__tests__/runtime-config.test.mjs +3 -3
  366. package/src/wf-ui-server/__tests__/runtime-detector.test.mjs +21 -0
  367. package/src/wf-ui-server/__tests__/runtime-review.test.mjs +828 -0
  368. package/src/wf-ui-server/__tests__/server.integration.test.mjs +1463 -11
  369. package/src/wf-ui-server/__tests__/session-cleanup.test.mjs +159 -0
  370. package/src/wf-ui-server/__tests__/session-registry.test.mjs +52 -3
  371. package/src/wf-ui-server/__tests__/settings.test.mjs +12 -2
  372. package/src/wf-ui-server/__tests__/spawn-gate.test.mjs +78 -0
  373. package/src/wf-ui-server/__tests__/task-group-parser.test.mjs +120 -0
  374. package/src/wf-ui-server/__tests__/task-group-tag.test.mjs +264 -0
  375. package/src/wf-ui-server/__tests__/task-parser.test.mjs +49 -3
  376. package/src/wf-ui-server/__tests__/terminal-context-hardening.test.mjs +122 -0
  377. package/src/wf-ui-server/__tests__/terminal-context.test.mjs +164 -0
  378. package/src/wf-ui-server/__tests__/terminal-store.test.mjs +4 -4
  379. package/src/wf-ui-server/__tests__/wf-browser-api.test.mjs +599 -0
  380. package/src/wf-ui-server/__tests__/wf-browser-store.test.mjs +184 -0
  381. package/src/wf-ui-server/__tests__/workflow-action-registry.test.mjs +282 -0
  382. package/src/wf-ui-server/__tests__/workflow-agent-communication.test.mjs +411 -0
  383. package/src/wf-ui-server/__tests__/workflow-agent-context.test.mjs +323 -0
  384. package/src/wf-ui-server/__tests__/workflow-agent-cooperation-permissions.test.mjs +318 -0
  385. package/src/wf-ui-server/__tests__/workflow-agent-messages-structured.test.mjs +458 -0
  386. package/src/wf-ui-server/__tests__/workflow-agent-routing.test.mjs +434 -0
  387. package/src/wf-ui-server/__tests__/workflow-agent-runtime.test.mjs +324 -0
  388. package/src/wf-ui-server/__tests__/workflow-api-integration.test.mjs +263 -0
  389. package/src/wf-ui-server/__tests__/workflow-api-phase3.test.mjs +1213 -0
  390. package/src/wf-ui-server/__tests__/workflow-claude-materialize.test.mjs +209 -0
  391. package/src/wf-ui-server/__tests__/workflow-cli-registry-manuals.test.mjs +173 -0
  392. package/src/wf-ui-server/__tests__/workflow-cli-surface.test.mjs +176 -0
  393. package/src/wf-ui-server/__tests__/workflow-codex-resume-id.test.mjs +556 -0
  394. package/src/wf-ui-server/__tests__/workflow-cooperation-enforcement.test.mjs +553 -0
  395. package/src/wf-ui-server/__tests__/workflow-depth-resume-dock.test.mjs +846 -0
  396. package/src/wf-ui-server/__tests__/workflow-display-node.test.mjs +150 -0
  397. package/src/wf-ui-server/__tests__/workflow-edge-update.test.mjs +296 -0
  398. package/src/wf-ui-server/__tests__/workflow-file-cache-lock-watch.test.mjs +380 -0
  399. package/src/wf-ui-server/__tests__/workflow-file-formats.test.mjs +994 -0
  400. package/src/wf-ui-server/__tests__/workflow-file-node-actions.test.mjs +294 -0
  401. package/src/wf-ui-server/__tests__/workflow-goal-actions.test.mjs +357 -0
  402. package/src/wf-ui-server/__tests__/workflow-goal-task-autoclose.test.mjs +256 -0
  403. package/src/wf-ui-server/__tests__/workflow-graceful-stop.test.mjs +108 -0
  404. package/src/wf-ui-server/__tests__/workflow-graph-undo.test.mjs +524 -0
  405. package/src/wf-ui-server/__tests__/workflow-layout.test.mjs +732 -0
  406. package/src/wf-ui-server/__tests__/workflow-magnetic-topology.test.mjs +222 -0
  407. package/src/wf-ui-server/__tests__/workflow-markdown-lock.test.mjs +359 -0
  408. package/src/wf-ui-server/__tests__/workflow-mcp-hub.test.mjs +174 -0
  409. package/src/wf-ui-server/__tests__/workflow-node-manual-schema.test.mjs +241 -0
  410. package/src/wf-ui-server/__tests__/workflow-node-runtime.test.mjs +1991 -0
  411. package/src/wf-ui-server/__tests__/workflow-node-store-utils.test.mjs +125 -0
  412. package/src/wf-ui-server/__tests__/workflow-registry-drift.test.mjs +296 -0
  413. package/src/wf-ui-server/__tests__/workflow-resource-handle-four-side.test.mjs +217 -0
  414. package/src/wf-ui-server/__tests__/workflow-role-profile.test.mjs +234 -0
  415. package/src/wf-ui-server/__tests__/workflow-set-model.test.mjs +261 -0
  416. package/src/wf-ui-server/__tests__/workflow-skill-group-context-enabled.test.mjs +131 -0
  417. package/src/wf-ui-server/__tests__/workflow-skill-group-enable-disable.test.mjs +186 -0
  418. package/src/wf-ui-server/__tests__/workflow-skills-hub.test.mjs +125 -0
  419. package/src/wf-ui-server/__tests__/workflow-state-reconcile.test.mjs +139 -0
  420. package/src/wf-ui-server/__tests__/workflow-subagent-strategy-matrix.test.mjs +529 -0
  421. package/src/wf-ui-server/__tests__/workflow-team-flow.test.mjs +278 -0
  422. package/src/wf-ui-server/__tests__/workflow-terminal-control-live.test.mjs +294 -0
  423. package/src/wf-ui-server/__tests__/workflow-terminal-control.test.mjs +631 -0
  424. package/src/wf-ui-server/__tests__/workflow-timer-wakeup.test.mjs +318 -0
  425. package/src/wf-ui-server/__tests__/workflow-unified-resume.test.mjs +537 -0
  426. package/src/wf-ui-server/__tests__/workspace-api-hardening.test.mjs +187 -0
  427. package/src/wf-ui-server/__tests__/workspace-api.test.mjs +382 -0
  428. package/src/wf-ui-server/__tests__/workspace-reveal.test.mjs +138 -0
  429. package/src/wf-ui-server/__tests__/workspace-store-hardening.test.mjs +255 -0
  430. package/src/wf-ui-server/__tests__/workspace-store.test.mjs +208 -0
  431. package/src/wf-ui-server/__tests__/ws-events.integration.test.mjs +52 -25
  432. package/src/wf-ui-server/__tests__/ws-terminal.integration.test.mjs +12 -6
  433. package/src/wf-ui-server/__tests__/ws-wf-browser.integration.test.mjs +488 -0
  434. package/src/wf-ui-server/a2a-store.mjs +3007 -89
  435. package/src/wf-ui-server/action-registry.mjs +277 -0
  436. package/src/wf-ui-server/bridge-store.mjs +276 -0
  437. package/src/wf-ui-server/chat-driver.mjs +220 -0
  438. package/src/wf-ui-server/chat-store.mjs +109 -0
  439. package/src/wf-ui-server/claude-transcript-materializer.mjs +235 -0
  440. package/src/wf-ui-server/codex-update-prompt.mjs +53 -0
  441. package/src/wf-ui-server/component-node-store.mjs +689 -0
  442. package/src/wf-ui-server/composition-api.mjs +436 -0
  443. package/src/wf-ui-server/control-plane-token.mjs +17 -0
  444. package/src/wf-ui-server/dispatch-contract.mjs +150 -0
  445. package/src/wf-ui-server/drivers/claude-stream-json.mjs +371 -0
  446. package/src/wf-ui-server/drivers/codex-appserver.mjs +513 -0
  447. package/src/wf-ui-server/drivers/opencode-server.mjs +486 -0
  448. package/src/wf-ui-server/excalidraw-svg.mjs +141 -0
  449. package/src/wf-ui-server/file-format-adapters.mjs +511 -0
  450. package/src/wf-ui-server/file-watcher.mjs +215 -0
  451. package/src/wf-ui-server/graph-layout.mjs +778 -0
  452. package/src/wf-ui-server/harness-env.mjs +46 -0
  453. package/src/wf-ui-server/json-store-utils.mjs +48 -0
  454. package/src/wf-ui-server/model-capability.mjs +773 -0
  455. package/src/wf-ui-server/node-config-store.mjs +233 -0
  456. package/src/wf-ui-server/node-store-utils.mjs +88 -0
  457. package/src/wf-ui-server/peer-capsule.mjs +56 -1
  458. package/src/wf-ui-server/pty-adapter.mjs +513 -11
  459. package/src/wf-ui-server/reveal-foreground.mjs +69 -0
  460. package/src/wf-ui-server/runtime-detector.mjs +52 -6
  461. package/src/wf-ui-server/server.mjs +5613 -403
  462. package/src/wf-ui-server/session-cleanup.mjs +363 -0
  463. package/src/wf-ui-server/session-registry.mjs +179 -3
  464. package/src/wf-ui-server/settings.mjs +25 -0
  465. package/src/wf-ui-server/spawn-gate.mjs +46 -0
  466. package/src/wf-ui-server/task-parser.mjs +88 -3
  467. package/src/wf-ui-server/terminal-store.mjs +225 -11
  468. package/src/wf-ui-server/timer-wakeup-scheduler.mjs +226 -0
  469. package/src/wf-ui-server/wf-browser-store.mjs +733 -0
  470. package/src/wf-ui-server/workflow-agent-context.mjs +1731 -0
  471. package/src/wf-ui-server/workflow-capability-node-store.mjs +676 -0
  472. package/src/wf-ui-server/workflow-event-node-store.mjs +623 -0
  473. package/src/wf-ui-server/workflow-goal-node-store.mjs +328 -0
  474. package/src/wf-ui-server/workflow-graph-store.mjs +623 -0
  475. package/src/wf-ui-server/workflow-mcp-hub.mjs +286 -0
  476. package/src/wf-ui-server/workflow-node-runtime.mjs +1767 -0
  477. package/src/wf-ui-server/workflow-node-settings-store.mjs +339 -0
  478. package/src/wf-ui-server/workflow-node-types/agent-node.mjs +920 -0
  479. package/src/wf-ui-server/workflow-node-types/display-node.mjs +151 -0
  480. package/src/wf-ui-server/workflow-node-types/excalidraw-node.mjs +145 -0
  481. package/src/wf-ui-server/workflow-node-types/file-node.mjs +484 -0
  482. package/src/wf-ui-server/workflow-node-types/github-trigger-node.mjs +207 -0
  483. package/src/wf-ui-server/workflow-node-types/goal-node.mjs +491 -0
  484. package/src/wf-ui-server/workflow-node-types/markdown-node.mjs +225 -0
  485. package/src/wf-ui-server/workflow-node-types/mcp-connector-node.mjs +71 -0
  486. package/src/wf-ui-server/workflow-node-types/role-profile-store.mjs +191 -0
  487. package/src/wf-ui-server/workflow-node-types/skill-group-node.mjs +98 -0
  488. package/src/wf-ui-server/workflow-node-types/timer-node.mjs +607 -0
  489. package/src/wf-ui-server/workflow-ontology.mjs +681 -0
  490. package/src/wf-ui-server/workflow-operation-store.mjs +115 -0
  491. package/src/wf-ui-server/workflow-skills-hub.mjs +366 -0
  492. package/src/wf-ui-server/workflow-skills-market.mjs +723 -0
  493. package/src/wf-ui-server/workspace-store.mjs +951 -0
  494. package/src/wf-ui-server/ws-chat.mjs +299 -0
  495. package/src/wf-ui-server/ws-events.mjs +45 -20
  496. package/src/wf-ui-server/ws-terminal.mjs +165 -22
  497. package/src/wf-ui-server/ws-wf-browser.mjs +419 -0
  498. package/templates/common/.claude/agents/review-manager.md +33 -29
  499. package/templates/common/.claude/commands/wf-browser.md +1 -1
  500. package/templates/common/.claude/commands/wf-help.md +5 -3
  501. package/templates/common/.claude/commands/wf-init.md +44 -0
  502. package/templates/common/.claude/commands/wf-learn.md +34 -8
  503. package/templates/common/.claude/commands/wf-max.md +19 -9
  504. package/templates/common/.claude/commands/wf-review.md +3 -3
  505. package/templates/common/.claude/commands/wf-search.md +55 -0
  506. package/templates/common/.claude/commands/wf-task-archive.md +5 -4
  507. package/templates/common/.claude/commands/wf-task-list.md +6 -3
  508. package/templates/common/.claude/commands/wf-task-record.md +10 -2
  509. package/templates/common/.claude/commands/wf-ui.md +12 -5
  510. package/templates/common/.claude/commands/wf-update.md +4 -0
  511. package/templates/common/.claude/commands/wf.md +12 -1
  512. package/templates/common/.claude/rules/ecc/common.md +10 -1
  513. package/templates/common/.claude/skills/wf/SKILL.md +36 -0
  514. package/templates/common/.claude/skills/wf-browser/SKILL.md +427 -122
  515. package/templates/common/.claude/skills/wf-browser/references/BROWSER_CONTROL_PATTERNS.md +43 -0
  516. package/templates/common/.claude/skills/wf-init/SKILL.md +33 -0
  517. package/templates/common/.claude/skills/wf-learn/SKILL.md +106 -26
  518. package/templates/common/.claude/skills/wf-max/SKILL.md +45 -11
  519. package/templates/common/.claude/skills/wf-review/SKILL.md +26 -54
  520. package/templates/common/.claude/skills/wf-search/SKILL.md +122 -0
  521. package/templates/common/.claude/skills/wf-search/references/evidence-contract.md +77 -0
  522. package/templates/common/.claude/skills/wf-search/references/policies/compare.md +38 -0
  523. package/templates/common/.claude/skills/wf-search/references/policies/fact.md +39 -0
  524. package/templates/common/.claude/skills/wf-search/references/policies/troubleshoot.md +39 -0
  525. package/templates/common/.claude/skills/wf-search/references/policies/verify.md +44 -0
  526. package/templates/common/.claude/skills/wf-search/references/source-routing.md +40 -0
  527. package/templates/common/.claude/skills/wf-search/references/tool-adapters.md +38 -0
  528. package/templates/common/.claude/skills/wf-ui/SKILL.md +146 -12
  529. package/templates/common/.claude/skills/wf-update/SKILL.md +5 -1
  530. package/templates/common/.harness-version +188 -85
  531. package/templates/common/.opencode/agents/review-manager.md +31 -27
  532. package/templates/common/.opencode/commands/wf-browser.md +1 -1
  533. package/templates/common/.opencode/commands/wf-help.md +5 -3
  534. package/templates/common/.opencode/commands/wf-init.md +44 -0
  535. package/templates/common/.opencode/commands/wf-learn.md +34 -8
  536. package/templates/common/.opencode/commands/wf-max.md +19 -9
  537. package/templates/common/.opencode/commands/wf-review.md +3 -3
  538. package/templates/common/.opencode/commands/wf-search.md +55 -0
  539. package/templates/common/.opencode/commands/wf-task-archive.md +5 -7
  540. package/templates/common/.opencode/commands/wf-task-list.md +6 -6
  541. package/templates/common/.opencode/commands/wf-task-record.md +10 -5
  542. package/templates/common/.opencode/commands/wf-ui.md +12 -5
  543. package/templates/common/.opencode/commands/wf-update.md +4 -0
  544. package/templates/common/.opencode/commands/wf.md +12 -1
  545. package/templates/common/CLAUDE.md +61 -3
  546. package/templates/common/Harness/MEMORY.md +8 -5
  547. package/templates/common/Harness/README.md +14 -10
  548. package/templates/common/Harness/a2a/action-registry.json +4397 -0
  549. package/templates/common/Harness/a2a/role-graph.json +16 -3
  550. package/templates/common/Harness/a2a/skills/terminal-control.json +45 -1
  551. package/templates/common/Harness/a2a/skills/wf-ui-map.json +50 -0
  552. package/templates/common/Harness/a2a/skills/workflow-agent-node.json +143 -0
  553. package/templates/common/Harness/a2a/skills/workflow-context.json +95 -0
  554. package/templates/common/Harness/a2a/skills/workflow-diagram-node.json +60 -0
  555. package/templates/common/Harness/a2a/skills/workflow-display-node.json +69 -0
  556. package/templates/common/Harness/a2a/skills/workflow-file-node.json +92 -0
  557. package/templates/common/Harness/a2a/skills/workflow-goal-node.json +76 -0
  558. package/templates/common/Harness/a2a/skills/workflow-markdown-node.json +79 -0
  559. package/templates/common/Harness/a2a/skills/workflow-mcp-connector-node.json +59 -0
  560. package/templates/common/Harness/a2a/skills/workflow-node-actions.json +105 -0
  561. package/templates/common/Harness/a2a/skills/workflow-node-map.json +71 -0
  562. package/templates/common/Harness/a2a/skills/workflow-ontology.json +54 -0
  563. package/templates/common/Harness/a2a/skills/workflow-resource-node.json +68 -0
  564. package/templates/common/Harness/a2a/skills/workflow-skill-group-node.json +56 -0
  565. package/templates/common/Harness/a2a/skills/workflow-timer-node.json +81 -0
  566. package/templates/common/Harness/a2a/workflows.json +33 -0
  567. package/templates/common/Harness/ownership.manifest.json +263 -2
  568. package/templates/common/Harness/project/architecture.md +499 -0
  569. package/templates/common/Harness/research/README.md +20 -0
  570. package/templates/common/Harness/scripts/README.md +70 -6
  571. package/templates/common/Harness/scripts/a2a-terminal.mjs +12 -4
  572. package/templates/common/Harness/scripts/context-budget.mjs +7 -3
  573. package/templates/common/Harness/scripts/lib/memory-context.mjs +400 -0
  574. package/templates/common/Harness/scripts/lib/path-scope.mjs +77 -0
  575. package/templates/common/Harness/scripts/lib/research-policy.mjs +99 -0
  576. package/templates/common/Harness/scripts/lib/wf-search.mjs +189 -0
  577. package/templates/common/Harness/scripts/memory-context.mjs +63 -0
  578. package/templates/common/Harness/scripts/research-policy.mjs +27 -0
  579. package/templates/common/Harness/scripts/task-context.mjs +547 -0
  580. package/templates/common/Harness/scripts/task-group-index.mjs +242 -0
  581. package/templates/common/Harness/scripts/task-state.mjs +659 -95
  582. package/templates/common/Harness/scripts/validate-harness.mjs +70 -28
  583. package/templates/common/Harness/scripts/wf-auto-update-prompt.mjs +24 -0
  584. package/templates/common/Harness/scripts/wf-remove.mjs +10 -0
  585. package/templates/common/Harness/scripts/wf-search.mjs +10 -0
  586. package/templates/common/Harness/scripts/wf-ui-control.mjs +3144 -0
  587. package/templates/common/Harness/scripts/wf-update-check.mjs +274 -51
  588. package/templates/common/Harness/scripts/wf-update-runner.mjs +53 -16
  589. package/templates/common/Harness/settings.json +10 -0
  590. package/templates/common/Harness/specs/guides/SETUP.md +4 -3
  591. package/templates/common/Harness/specs/protocols/HARNESS_BRIDGE.md +429 -48
  592. package/templates/common/Harness/specs/protocols/MEMORY_PROTOCOL.md +24 -0
  593. package/templates/common/Harness/specs/protocols/TASK_ARCHIVE.md +14 -11
  594. package/templates/common/Harness/specs/runtime/command-surface.json +28 -0
  595. package/templates/common/Harness/specs/runtime/context-loading.md +6 -0
  596. package/templates/common/Harness/specs/runtime/dispatch.md +9 -1
  597. package/templates/common/Harness/specs/runtime/subagents.md +20 -5
  598. package/templates/common/Harness/specs/workflows/WF-AUTO-SPARK.md +19 -0
  599. package/templates/common/Harness/specs/workflows/WF-AUTO.md +21 -0
  600. package/templates/common/Harness/specs/workflows/WF-KERNEL.md +4 -2
  601. package/templates/common/Harness/specs/workflows/WF-MAX.md +39 -12
  602. package/templates/common/Harness/specs/workflows/WF-STATE.md +62 -14
  603. package/templates/common/Harness/specs/workflows/WF.md +32 -0
  604. package/templates/common/Harness/tasks/INDEX.json +7 -0
  605. package/templates/common/Harness/tasks/INDEX.md +12 -0
  606. package/templates/common/Harness/tasks/_template/PLAN.md +6 -0
  607. package/templates/common/Harness/tasks/_template/PROGRESS.md +5 -0
  608. package/templates/common/Harness/tasks/_template/STATE.json +22 -0
  609. package/templates/common/Harness/templates/TEST_PLAN.template.md +5 -4
  610. package/templates/common/Harness/templates/UI_CONTRACT.template.md +7 -5
  611. package/templates/common/Harness/wf-browser/README.md +69 -0
  612. package/templates/common/README.md +17 -0
  613. package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js +0 -17
  614. package/src/ui/dist/assets/AgentsRoute-CuSKYmFu.js.map +0 -1
  615. package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js +0 -7
  616. package/src/ui/dist/assets/RolesRoute-DOzTYVRm.js.map +0 -1
  617. package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js +0 -12
  618. package/src/ui/dist/assets/SettingsRoute-DPU7jSQm.js.map +0 -1
  619. package/src/ui/dist/assets/TaskList-BN4r8s1i.js +0 -50
  620. package/src/ui/dist/assets/TaskList-BN4r8s1i.js.map +0 -1
  621. package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js +0 -74
  622. package/src/ui/dist/assets/TerminalDrawer-Cej4PxsH.js.map +0 -1
  623. package/src/ui/dist/assets/WorkflowRoute-BnuhLJ6X.css +0 -1
  624. package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js +0 -39
  625. package/src/ui/dist/assets/WorkflowRoute-C-clKe-j.js.map +0 -1
  626. package/src/ui/dist/assets/index-BOVYWntB.js +0 -117
  627. package/src/ui/dist/assets/index-BOVYWntB.js.map +0 -1
  628. package/src/ui/dist/assets/index-DaUObq0H.css +0 -1
  629. package/src/ui/dist/assets/maximize-2-LNrr_rKr.js +0 -7
  630. package/src/ui/dist/assets/maximize-2-LNrr_rKr.js.map +0 -1
  631. package/src/ui/dist/assets/plus-QuTJyoT3.js +0 -7
  632. package/src/ui/dist/assets/plus-QuTJyoT3.js.map +0 -1
  633. package/src/ui/dist/assets/proxy-D0vUbds5.js.map +0 -1
  634. package/src/ui/dist/assets/refresh-cw-JNmExijd.js.map +0 -1
  635. package/src/ui/dist/assets/terminal-BBQvnOAK.js.map +0 -1
  636. package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js +0 -7
  637. package/src/ui/dist/assets/useReducedMotion-BqmH0Tf7.js.map +0 -1
  638. package/src/ui/dist/assets/x-DoIOGAJz.js.map +0 -1
  639. package/src/ui/pnpm-lock.yaml +0 -1582
  640. package/src/ui/src/App.tsx +0 -86
  641. package/src/ui/src/api.ts +0 -93
  642. package/src/ui/src/components/AgentsRoute.tsx +0 -503
  643. package/src/ui/src/components/Footer.tsx +0 -69
  644. package/src/ui/src/components/Header.tsx +0 -175
  645. package/src/ui/src/components/LoadingView.tsx +0 -22
  646. package/src/ui/src/components/RolesRoute.tsx +0 -169
  647. package/src/ui/src/components/SettingsRoute.tsx +0 -166
  648. package/src/ui/src/components/TaskList.tsx +0 -388
  649. package/src/ui/src/components/TerminalDrawer.tsx +0 -611
  650. package/src/ui/src/components/WorkflowRoute.tsx +0 -670
  651. package/src/ui/src/hooks/useReducedMotion.ts +0 -17
  652. package/src/ui/src/hooks/useServerConnection.ts +0 -114
  653. package/src/ui/src/index.css +0 -281
  654. package/src/ui/src/main.tsx +0 -11
  655. package/src/ui/src/types.ts +0 -108
  656. /package/src/ui/dist/assets/{TerminalDrawer-6GBZ9nXN.css → terminalControl-6GBZ9nXN.css} +0 -0
@@ -0,0 +1,278 @@
1
+ import { describe, it, after } from 'node:test';
2
+ import assert from 'node:assert/strict';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import { makeHarnessTempRoot } from '../../../tests/support/temp-root.js';
6
+ import { autoConnectAgent, findAgents, loadWorkflowGraphMap, writeWorkflowGraphMap } from '../a2a-store.mjs';
7
+ import { executeNodeAction } from '../workflow-node-runtime.mjs';
8
+ import { createEventNode, getEventNode } from '../workflow-event-node-store.mjs';
9
+ import { listBridgeMessages } from '../bridge-store.mjs';
10
+ import { persistSession } from '../terminal-store.mjs';
11
+ import { createRoleProfile } from '../workflow-node-types/role-profile-store.mjs';
12
+ import { registerPtyProcess, unregisterPtyProcess } from '../ws-terminal.mjs';
13
+ import { isTimerSchedulerActive, stopTimerScheduler, syncTimerScheduler } from '../timer-wakeup-scheduler.mjs';
14
+
15
+ // F19/D17 (T3 full-flow): one in-process integration test driving the whole
16
+ // agent-team cooperation chain WITHOUT real PTY sessions — test-registry agent
17
+ // sessions, role profiles, find -> auto-connect -> structured request ->
18
+ // aggregated replies -> timer wakeup with goalNodeId -> goal check/complete.
19
+ // Same infrastructure as the other wf-ui-server __tests__ (no HTTP server; the
20
+ // backend functions are invoked in-process, PTY input is captured via
21
+ // registerPtyProcess).
22
+
23
+ function seedRoot() {
24
+ const root = makeHarnessTempRoot('wf-team-flow-');
25
+ fs.mkdirSync(path.join(root, 'Harness', 'tasks'), { recursive: true });
26
+ fs.mkdirSync(path.join(root, 'Harness', 'a2a'), { recursive: true });
27
+ return root;
28
+ }
29
+
30
+ function seedActiveTask(root, taskId = 'task-team-flow') {
31
+ fs.mkdirSync(path.join(root, 'Harness', 'tasks', taskId), { recursive: true });
32
+ fs.writeFileSync(path.join(root, 'Harness', 'PROGRESS.md'), `# PROGRESS.md\n\n## Active Task\n\n- ${taskId}\n`, 'utf8');
33
+ fs.writeFileSync(path.join(root, 'Harness', 'tasks', taskId, 'STATE.json'), JSON.stringify({
34
+ schemaVersion: 1,
35
+ taskId,
36
+ status: 'active',
37
+ title: 'Team flow goal',
38
+ nextAction: 'Route agents',
39
+ acceptance: [],
40
+ planItems: [],
41
+ phase: 'implement',
42
+ }));
43
+ return `goal-${taskId}`;
44
+ }
45
+
46
+ function seedAgent(root, { nodeId, sessionId, roleTitle, displayName, agentKind = 'subagent', role, runtime = 'claude', capabilities = [] }) {
47
+ persistSession(root, {
48
+ sessionId,
49
+ graphNodeId: nodeId,
50
+ runtime,
51
+ agentKind,
52
+ role: role || roleTitle || 'Subagent',
53
+ roleTitle,
54
+ displayName: displayName || roleTitle || '',
55
+ status: 'running',
56
+ attachMode: true,
57
+ taskId: null,
58
+ capabilities,
59
+ });
60
+ writeWorkflowGraphMap(root, {
61
+ ...loadWorkflowGraphMap(root),
62
+ version: loadWorkflowGraphMap(root).version + 1,
63
+ nodes: [
64
+ ...(loadWorkflowGraphMap(root).nodes || []).filter(node => (node.nodeId || node.id) !== nodeId),
65
+ { nodeId, sessionId, kind: 'terminal-session', runtime, agentKind, role: role || roleTitle || 'Agent', label: displayName || roleTitle || 'Agent', status: 'running' },
66
+ ],
67
+ });
68
+ if (roleTitle) {
69
+ createRoleProfile({ nodeId, roleTitle, displayName: displayName || roleTitle, agentKind, runtime, capabilities }, root);
70
+ }
71
+ return nodeId;
72
+ }
73
+
74
+ function dockLink(a, b) {
75
+ const pair = [a, b].sort();
76
+ return {
77
+ id: `dock:${pair[0]}::${pair[1]}`,
78
+ nodeIds: pair,
79
+ anchorId: pair[0],
80
+ draggedId: pair[1],
81
+ side: 'top',
82
+ edges: [],
83
+ connections: [
84
+ { source: a, target: b, relation: 'wf-bridge', direction: 'source-to-target', sourceHandle: 'dock', targetHandle: 'dock' },
85
+ ],
86
+ };
87
+ }
88
+
89
+ function wakeupEntries(root, timerNodeId, sessionId) {
90
+ return listBridgeMessages(root, { fromSessionId: `wakeup-${timerNodeId}`, toSessionId: sessionId }).entries;
91
+ }
92
+
93
+ // F17/D14 writes PTY input char-by-char (12ms gaps, single \r at the end), so
94
+ // a registered test PTY receives many small writes instead of one string.
95
+ // Aggregate a session's write log and wait until it settles (no new write for
96
+ // `settleMs` after at least one full typing duration has elapsed).
97
+ async function collectTypedInput(writes, { settleMs = 120, timeoutMs = 6000 } = {}) {
98
+ const deadline = Date.now() + timeoutMs;
99
+ let lastCount = -1;
100
+ let lastChange = Date.now();
101
+ while (Date.now() < deadline) {
102
+ if (writes.length !== lastCount) {
103
+ lastCount = writes.length;
104
+ lastChange = Date.now();
105
+ } else if (writes.length > 0 && Date.now() - lastChange >= settleMs) {
106
+ break;
107
+ }
108
+ await new Promise(resolve => setTimeout(resolve, 40));
109
+ }
110
+ // The trailing \r lands ~800ms after the last body char (enter delay);
111
+ // tolerate callers asserting before it arrives by allowing a suffix-less
112
+ // match, and keep polling out of the returned string.
113
+ return writes.join('');
114
+ }
115
+
116
+ // Wait until the session's aggregated input ends with the submit \r (the
117
+ // enter rides a delayed timer after the char-by-char body).
118
+ async function awaitSubmitEnter(writes, { timeoutMs = 4000 } = {}) {
119
+ const deadline = Date.now() + timeoutMs;
120
+ while (Date.now() < deadline) {
121
+ if (writes.length > 0 && writes[writes.length - 1] === '\r') return writes.join('');
122
+ await new Promise(resolve => setTimeout(resolve, 40));
123
+ }
124
+ return writes.join('');
125
+ }
126
+
127
+ function waitForWakeups(root, timerNodeId, sessionId, count, { timeout = 6000, step = 50 } = {}) {
128
+ return new Promise((resolve, reject) => {
129
+ const deadline = Date.now() + timeout;
130
+ const poll = () => {
131
+ const entries = wakeupEntries(root, timerNodeId, sessionId);
132
+ if (entries.length >= count) return resolve(entries);
133
+ if (Date.now() >= deadline) return reject(new Error(`waitForWakeups timed out; got ${entries.length}/${count}`));
134
+ setTimeout(poll, step);
135
+ };
136
+ poll();
137
+ });
138
+ }
139
+
140
+ after(() => {
141
+ stopTimerScheduler();
142
+ });
143
+
144
+ describe('T3/AC-024 full cooperation flow (F19/D17)', () => {
145
+ it('create -> find -> auto-connect -> structured request -> aggregated replies -> wakeup with goalNodeId -> goal complete', async () => {
146
+ const root = seedRoot();
147
+ const writes = { ceo: [], fe: [], qa: [] };
148
+ try {
149
+ // (1) Main + sub agent sessions with role profiles (test registry).
150
+ seedAgent(root, { nodeId: 'agent-ceo', sessionId: 'session-ceo', roleTitle: 'ceo', displayName: 'CEO', agentKind: 'main', capabilities: ['terminal-control'] });
151
+ seedAgent(root, { nodeId: 'agent-fe', sessionId: 'session-fe', roleTitle: 'implementer', displayName: 'Frontend Expert', capabilities: ['ui-control-plane'] });
152
+ seedAgent(root, { nodeId: 'agent-qa', sessionId: 'session-qa', roleTitle: 'reviewer', displayName: 'QA Reviewer', capabilities: ['playwright'] });
153
+ registerPtyProcess('session-ceo', { write: data => writes.ceo.push(String(data)) });
154
+ registerPtyProcess('session-fe', { write: data => writes.fe.push(String(data)) });
155
+ registerPtyProcess('session-qa', { write: data => writes.qa.push(String(data)) });
156
+
157
+ // (2) findAgents by role -> exactly one match.
158
+ const found = await findAgents(root, { role: 'implementer' });
159
+ assert.equal(found.count, 1, 'role=implementer must match exactly one agent');
160
+ assert.equal(found.matches[0].nodeId, 'agent-fe');
161
+ assert.equal(found.matches[0].connected, false, 'fresh agent starts unconnected');
162
+
163
+ // (3) auto-connect -> delegation edge exists (bidirectional).
164
+ const auto = autoConnectAgent(root, 'agent-ceo', 'agent-fe');
165
+ assert.equal(auto.ok, true);
166
+ const graphAfterConnect = loadWorkflowGraphMap(root);
167
+ const edgeExists = (graphAfterConnect.edges || []).some(edge =>
168
+ (edge.from === 'agent-ceo' && edge.to === 'agent-fe') || (edge.from === 'agent-fe' && edge.to === 'agent-ceo'));
169
+ assert.equal(edgeExists, true, 'auto-connect must create the delegation edge');
170
+ autoConnectAgent(root, 'agent-ceo', 'agent-qa');
171
+
172
+ // (4) structured request -> target message queue has the envelope AND the
173
+ // PTY input is composed with the [harness-request ...] prefix.
174
+ const sent = await executeNodeAction(root, 'agent-ceo', 'agent.sendMessage', {
175
+ to: 'agent-fe',
176
+ text: 'REVIEW_UI_FLOW',
177
+ requestId: 'req-t3-0001',
178
+ toRole: 'implementer',
179
+ contextRefs: [{ nodeId: 'markdown-ctx-1', relation: 'shared-context' }],
180
+ });
181
+ assert.equal(sent.ok, true);
182
+ assert.equal(sent.result.requestId, 'req-t3-0001');
183
+ const feInput = await awaitSubmitEnter(writes.fe, { timeoutMs: 4000 })
184
+ || await collectTypedInput(writes.fe);
185
+ assert.match(feInput, /^\[harness-request req-t3-0001 to-role=implementer contextRefs=markdown-ctx-1\] REVIEW_UI_FLOW\r$/);
186
+ const queued = listBridgeMessages(root, { fromSessionId: 'session-ceo', toSessionId: 'session-fe' }).entries;
187
+ assert.equal(queued.length, 1);
188
+ assert.equal(queued[0].requestId, 'req-t3-0001');
189
+ assert.equal(queued[0].deliveryMode, 'direct');
190
+ assert.equal(queued[0].data.replace(/\r$/, ''), 'REVIEW_UI_FLOW');
191
+
192
+ // (5) replies echo the requestId; readMessages aggregates by requestId.
193
+ const replyFe = await executeNodeAction(root, 'agent-fe', 'agent.sendMessage', {
194
+ to: 'agent-ceo',
195
+ text: 'EVIDENCE_FE',
196
+ requestId: 'req-t3-0001',
197
+ });
198
+ assert.equal(replyFe.ok, true);
199
+ const replyQa = await executeNodeAction(root, 'agent-qa', 'agent.sendMessage', {
200
+ to: 'agent-ceo',
201
+ text: 'EVIDENCE_QA',
202
+ requestId: 'req-t3-0001',
203
+ });
204
+ assert.equal(replyQa.ok, true);
205
+ const aggregated = await executeNodeAction(root, 'agent-ceo', 'agent.readMessages', { requestId: 'req-t3-0001' });
206
+ assert.equal(aggregated.ok, true);
207
+ assert.equal(aggregated.result.entries.length, 3, 'request + 2 replies must aggregate under the requestId');
208
+ const texts = aggregated.result.entries.map(entry => entry.data.replace(/\r$/, '')).sort();
209
+ assert.deepEqual(texts, ['EVIDENCE_FE', 'EVIDENCE_QA', 'REVIEW_UI_FLOW']);
210
+
211
+ // (6) timer with maxIterations=1 + group goal -> scheduler tick dispatches
212
+ // a wakeup whose envelope carries the goalNodeId.
213
+ const goalNodeId = seedActiveTask(root, 'task-team-flow');
214
+ const timer = await createEventNode(root, {
215
+ type: 'timer',
216
+ title: 'T3 Wakeup Timer',
217
+ enabled: true,
218
+ schedule: { mode: 'interval', intervalSeconds: 1 },
219
+ heartbeat: { base: { enabled: true, intervalSeconds: 1, nextDueAt: new Date(Date.now() - 2000).toISOString() } },
220
+ loop: { enabled: true, maxIterations: 1 },
221
+ });
222
+ const timerNodeId = timer.node.nodeId;
223
+ writeWorkflowGraphMap(root, {
224
+ ...loadWorkflowGraphMap(root),
225
+ version: loadWorkflowGraphMap(root).version + 1,
226
+ edges: [
227
+ ...(loadWorkflowGraphMap(root).edges || []),
228
+ { id: `agent-ceo->${goalNodeId}`, from: 'agent-ceo', to: goalNodeId, relation: 'goal', direction: 'bidirectional' },
229
+ ],
230
+ capsuleDockLinks: [
231
+ dockLink(goalNodeId, timerNodeId),
232
+ dockLink(timerNodeId, 'agent-ceo'),
233
+ ],
234
+ });
235
+
236
+ syncTimerScheduler(root, { intervalMs: 20 });
237
+ assert.equal(isTimerSchedulerActive(), true);
238
+ const wakeups = await waitForWakeups(root, timerNodeId, 'session-ceo', 1);
239
+ const envelope = JSON.parse(wakeups[0].data);
240
+ assert.equal(envelope.type, 'wakeup');
241
+ assert.equal(envelope.timerNodeId, timerNodeId);
242
+ assert.equal(envelope.goalNodeId, goalNodeId, 'wakeup must reference the group Goal node');
243
+ const timerAfter = getEventNode(root, timerNodeId);
244
+ assert.equal(timerAfter.state.loop.enabled, false, 'maxIterations=1 must complete the loop after one fire');
245
+ stopTimerScheduler();
246
+
247
+ // (7) goal.add -> goal.check all -> goal.complete -> proposed-complete.
248
+ const added = await executeNodeAction(root, goalNodeId, 'goal.add', {
249
+ planItems: [{ text: 'Review UI flow' }, { text: 'Fix findings' }],
250
+ });
251
+ assert.equal(added.ok, true);
252
+ const planItemIds = added.result.state.planItems.map(item => item.id);
253
+ assert.equal(planItemIds.length, 2);
254
+ assert.ok(planItemIds.every(id => /^P-\d{3}$/.test(id)));
255
+
256
+ const checked = await executeNodeAction(root, goalNodeId, 'goal.check', {
257
+ planItemIds,
258
+ actorNodeId: 'agent-ceo',
259
+ });
260
+ assert.equal(checked.ok, true);
261
+ assert.ok(checked.result.state.planItems.every(item => item.status === 'done'));
262
+
263
+ const completed = await executeNodeAction(root, goalNodeId, 'goal.complete', {
264
+ actorNodeId: 'agent-ceo',
265
+ evidenceRefs: ['wf-team-flow'],
266
+ });
267
+ assert.equal(completed.ok, true);
268
+ assert.equal(completed.result.state.status, 'proposed-complete');
269
+ assert.equal(completed.result.state.confirmation.state, 'proposed');
270
+ } finally {
271
+ stopTimerScheduler();
272
+ unregisterPtyProcess('session-ceo');
273
+ unregisterPtyProcess('session-fe');
274
+ unregisterPtyProcess('session-qa');
275
+ fs.rmSync(root, { recursive: true, force: true });
276
+ }
277
+ });
278
+ });
@@ -0,0 +1,294 @@
1
+ // workflow-terminal-control-live.test.mjs
2
+ //
3
+ // AC-CTRL-005 real-terminal probe (OPT-IN).
4
+ //
5
+ // These tests spawn a REAL codex process through the backend control plane and
6
+ // assert that an injected prompt triggers a real AI turn. Each run spends a
7
+ // real codex API call and can take minutes, so the whole suite is SKIPPED by
8
+ // default.
9
+ //
10
+ // Enable with:
11
+ // HARNESS_LIVE_TERMINAL_PROBE=1 node --test src/wf-ui-server/__tests__/workflow-terminal-control-live.test.mjs
12
+ //
13
+ // L1 - Enter-free trigger (AC-CTRL-002/005): spawn codex with initialPrompt
14
+ // as argv; the codex TUI auto-submits it — zero keyboard injection.
15
+ // L2 - single-\r submit (AC-CTRL-001/005): spawn codex without a prompt,
16
+ // wait for the prompt marker (›/❯), send input with submit:true (body +
17
+ // exactly one \r) and assert a real AI turn starts.
18
+ //
19
+ // Evidence rule: assertions match terminal-store STDOUT entries ONLY. The
20
+ // control plane records injected input as stdin entries, which must never
21
+ // satisfy an assertion (previous false positive: L2 matched the text the test
22
+ // itself sent). Output growth is likewise not evidence — TUI boot repaints
23
+ // were a previous false positive for L1. The expected token must also NOT be
24
+ // a substring of the prompt: the codex TUI repaints the typed/argv prompt
25
+ // into STDOUT (input-line render + queued-input banner), so substring tokens
26
+ // like the old probe-ok / probe-ok2 matched the echo before any AI turn.
27
+ // The current tokens (42 / 22) are arithmetic answers that can only come from
28
+ // a real AI reply. Sessions are kept alive for a fixed observation window
29
+ // after the trigger (a real AI turn takes ~30-90s) and only early-exit when
30
+ // the expected reply text renders in STDOUT.
31
+ //
32
+ // Evidence: the full terminal transcript is written to
33
+ // `Harness/.temp/live-terminal-probe-<timestamp>/` and the path is printed.
34
+ //
35
+ // Note: the deterministic byte-sequence / gating matrix lives in
36
+ // workflow-terminal-control.test.mjs; this file only adds real-process proof.
37
+ import { describe, it, before, after } from 'node:test';
38
+ import assert from 'node:assert/strict';
39
+ import fs from 'node:fs';
40
+ import path from 'node:path';
41
+ import http from 'node:http';
42
+ import { makeHarnessTempRoot } from '../../../tests/support/temp-root.js';
43
+ import { startServer, stopServer } from '../server.mjs';
44
+ import { SessionRegistry } from '../session-registry.mjs';
45
+
46
+ const LIVE = process.env.HARNESS_LIVE_TERMINAL_PROBE === '1';
47
+
48
+ // The marker the codex TUI prints when it is ready for input (› or ❯).
49
+ const PROMPT_MARKER_RE = /[›❯]/;
50
+
51
+ // Observation windows. A real codex AI turn takes ~30-90s, so the probe never
52
+ // stops on mere output growth; it keeps the session alive a fixed window after
53
+ // the trigger (spawn for L1, input write for L2) and only early-exits when the
54
+ // expected reply text actually renders in STDOUT.
55
+ const BOOT_WAIT_MS = 45000; // max wait for TUI boot / prompt marker
56
+ const OBSERVE_WINDOW_MS = 100000; // fixed observation window after trigger
57
+ // Per-test timeouts bound the whole suite: worst case L1 + L2 ≈ 5 min.
58
+ const L1_TIMEOUT_MS = 150000;
59
+ const L2_TIMEOUT_MS = 150000;
60
+
61
+ function jsonRequest(baseUrl, route, { method = 'GET', body } = {}) {
62
+ return new Promise((resolve, reject) => {
63
+ const url = new URL(route, baseUrl);
64
+ const payload = body ? JSON.stringify(body) : null;
65
+ const req = http.request({
66
+ hostname: url.hostname,
67
+ port: url.port,
68
+ path: `${url.pathname}${url.search}`,
69
+ method,
70
+ headers: payload ? { 'Content-Type': 'application/json', 'Content-Length': Buffer.byteLength(payload) } : {},
71
+ }, (res) => {
72
+ let data = '';
73
+ res.on('data', chunk => { data += chunk; });
74
+ res.on('end', () => {
75
+ try { resolve({ status: res.statusCode, body: JSON.parse(data) }); }
76
+ catch { resolve({ status: res.statusCode, body: data }); }
77
+ });
78
+ });
79
+ req.on('error', reject);
80
+ if (payload) req.write(payload);
81
+ req.end();
82
+ });
83
+ }
84
+
85
+ describe('Live terminal probe (AC-CTRL-005)', { skip: !LIVE }, () => {
86
+ let root;
87
+ let server;
88
+ let baseUrl;
89
+ let registry;
90
+ const spawnedSessions = [];
91
+
92
+ before(async () => {
93
+ root = makeHarnessTempRoot('live-terminal-probe-');
94
+ registry = new SessionRegistry();
95
+ const started = await startServer({
96
+ projectRoot: root,
97
+ host: '127.0.0.1',
98
+ port: 0,
99
+ sessionRegistry: registry,
100
+ eventsWs: false,
101
+ });
102
+ server = started.server;
103
+ baseUrl = `http://127.0.0.1:${started.port}`;
104
+ console.log(`[live-probe] backend on ${baseUrl}, evidence root ${root}`);
105
+ });
106
+
107
+ after(async () => {
108
+ for (const sessionId of spawnedSessions) {
109
+ try {
110
+ await jsonRequest(baseUrl, `/api/sessions/${sessionId}/stop`, { method: 'POST', body: {} });
111
+ } catch { /* already gone */ }
112
+ }
113
+ if (server) {
114
+ await stopServer(server);
115
+ server = null;
116
+ }
117
+ // Hard-exit fallback: the backend server / PTY handles must not keep the
118
+ // runner alive forever (observed hang: process killed at 600s). unref()
119
+ // keeps this timer from blocking a natural exit, and the runner's exit
120
+ // code is preserved so a failed probe still fails the run.
121
+ const exitTimer = setTimeout(() => process.exit(process.exitCode || 0), 5000);
122
+ exitTimer.unref();
123
+ // The temp root is intentionally kept: it holds the probe transcripts.
124
+ });
125
+
126
+ // ── helpers ──
127
+
128
+ // ANSI control-sequence stripper — same pattern as the production
129
+ // codex-update-prompt.mjs stripTerminalControls (CSI `\x1b[...[@-~]`, OSC
130
+ // `\x1b]...\x07`/`\x1b]...\x1b\`, and \r→\n), kept local so the probe stays
131
+ // self-contained. Raw PTY bytes otherwise carry escape sequences whose
132
+ // parameters can satisfy a substring match (e.g. "42" inside the cursor
133
+ // position `\x1b[20;42H`, "22" inside the SGR `\x1b[22m`), which is a
134
+ // false-positive source for the reply-token match.
135
+ const ANSI_PATTERN = /\x1b(?:\][^\x07]*(?:\x07|\x1b\\)|\[[0-?]*[ -/]*[@-~])/g;
136
+ function stripAnsi(value) {
137
+ return String(value || '')
138
+ .replace(ANSI_PATTERN, '')
139
+ .replace(/\r/g, '\n');
140
+ }
141
+
142
+ async function createCodexSession(extra = {}) {
143
+ const res = await jsonRequest(baseUrl, '/api/sessions', {
144
+ method: 'POST',
145
+ body: {
146
+ runtime: 'codex',
147
+ agentKind: 'main',
148
+ role: 'Main Agent',
149
+ objective: 'Live terminal probe',
150
+ attachGraphNode: true,
151
+ ...extra,
152
+ },
153
+ });
154
+ assert.equal(res.status, 201, JSON.stringify(res.body));
155
+ spawnedSessions.push(res.body.sessionId);
156
+ if (res.body.status === 'blocked') {
157
+ return { running: false, reason: res.body.blockedReason || res.body.blockedHint || 'blocked' };
158
+ }
159
+ return { running: true, sessionId: res.body.sessionId };
160
+ }
161
+
162
+ async function readOutput(sessionId) {
163
+ const res = await jsonRequest(baseUrl, `/api/terminals/${sessionId}/range?tail=4000`);
164
+ return res.body && Array.isArray(res.body.entries) ? res.body : { entries: [] };
165
+ }
166
+
167
+ // Real rendered evidence: STDOUT entries only. Terminal-store entries carry
168
+ // a `stream` field; the test's own injected text is recorded as `stdin` and
169
+ // never counts as a reply (L2 false positive: matched its own input echo).
170
+ // ANSI escapes are stripped BEFORE matching — raw bytes contain sequences
171
+ // (cursor positioning, SGR) whose parameters hold the expected token.
172
+ function stdoutText(range) {
173
+ return stripAnsi(
174
+ (range.entries || [])
175
+ .filter(entry => String(entry.stream || 'stdout') === 'stdout')
176
+ .map(entry => String(entry.data || ''))
177
+ .join(''),
178
+ );
179
+ }
180
+
181
+ // Full transcript text (stdout + stdin) for the evidence file.
182
+ function fullText(range) {
183
+ return (range.entries || []).map(entry => String(entry.data || '')).join('');
184
+ }
185
+
186
+ // Observe a fixed window starting at fromMs. Early-exit ONLY when the
187
+ // expected reply text renders in STDOUT; output growth is never evidence.
188
+ // Returns null when the window elapses without the reply.
189
+ // The match runs on ANSI-stripped text and additionally requires the token
190
+ // NOT to be part of a longer digit run: `(^|\D)<token>(\D|$)`.
191
+ async function waitForReplyText(sessionId, { expectText, fromMs, windowMs }) {
192
+ const deadline = fromMs + windowMs;
193
+ const expectedRe = new RegExp(`(^|\\D)${expectText}(\\D|$)`);
194
+ let last = null;
195
+ while (Date.now() < deadline) {
196
+ last = await readOutput(sessionId);
197
+ if (expectedRe.test(stdoutText(last))) {
198
+ return { evidence: `expected-text:${expectText}`, range: last };
199
+ }
200
+ await new Promise(resolve => setTimeout(resolve, 2000));
201
+ }
202
+ return null;
203
+ }
204
+
205
+ async function saveTranscript(sessionId, range) {
206
+ const dir = path.join(root, 'transcripts');
207
+ fs.mkdirSync(dir, { recursive: true });
208
+ const file = path.join(dir, `${sessionId}.txt`);
209
+ const entries = range.entries || [];
210
+ const stdoutCount = entries.filter(entry => String(entry.stream || 'stdout') === 'stdout').length;
211
+ const stdinCount = entries.length - stdoutCount;
212
+ fs.writeFileSync(
213
+ file,
214
+ `session: ${sessionId}\nentries: ${entries.length} (stdout: ${stdoutCount}, stdin: ${stdinCount})\n\n${fullText(range)}`,
215
+ 'utf8',
216
+ );
217
+ console.log(`[live-probe] transcript: ${file}`);
218
+ return file;
219
+ }
220
+
221
+ // ── L1: Enter-free trigger (AC-CTRL-002/005) ──
222
+ it('L1 - argv initialPrompt auto-submits in a real codex TUI (Enter-free)', async (t) => {
223
+ const spawnTime = Date.now();
224
+ const session = await createCodexSession({
225
+ initialPrompt: 'What is 21 times 2? Reply with the number only, nothing else.',
226
+ });
227
+ if (!session.running) {
228
+ t.skip(`codex not launchable: ${session.reason}`);
229
+ return;
230
+ }
231
+ // Wait for the TUI to boot (any STDOUT output), then observe a fixed
232
+ // window after spawn: the AI reply renders the number 42 in STDOUT.
233
+ // No output-growth shortcut — boot repaints are not AI-turn evidence.
234
+ const bootDeadline = spawnTime + BOOT_WAIT_MS;
235
+ let booted = null;
236
+ while (Date.now() < bootDeadline) {
237
+ booted = await readOutput(session.sessionId);
238
+ if (stdoutText(booted).length > 0) break;
239
+ await new Promise(resolve => setTimeout(resolve, 2000));
240
+ }
241
+ if (!booted || stdoutText(booted).length === 0) {
242
+ t.skip('codex TUI produced no output (spawn may be blocked)');
243
+ return;
244
+ }
245
+ const evidence = await waitForReplyText(session.sessionId, {
246
+ expectText: '42',
247
+ fromMs: spawnTime,
248
+ windowMs: OBSERVE_WINDOW_MS,
249
+ });
250
+ await saveTranscript(session.sessionId, evidence ? evidence.range : await readOutput(session.sessionId));
251
+ assert.ok(evidence, `no AI reply rendered in STDOUT within ${OBSERVE_WINDOW_MS}ms of spawn (evidence=${evidence?.evidence || 'none'})`);
252
+ console.log(`[live-probe] L1 evidence: ${evidence.evidence}`);
253
+ }, { timeout: L1_TIMEOUT_MS });
254
+
255
+ // ── L2: single-\r submit (AC-CTRL-001/005) ──
256
+ it('L2 - submit:true (single \\r) triggers a real AI turn in a real codex TUI', async (t) => {
257
+ const session = await createCodexSession({});
258
+ if (!session.running) {
259
+ t.skip(`codex not launchable: ${session.reason}`);
260
+ return;
261
+ }
262
+ // Wait for the TUI prompt marker so the ready gate has something to see.
263
+ const markerDeadline = Date.now() + BOOT_WAIT_MS;
264
+ let markerSeen = false;
265
+ while (Date.now() < markerDeadline) {
266
+ const booted = await readOutput(session.sessionId);
267
+ if (PROMPT_MARKER_RE.test(stdoutText(booted))) {
268
+ markerSeen = true;
269
+ break;
270
+ }
271
+ await new Promise(resolve => setTimeout(resolve, 2000));
272
+ }
273
+ if (!markerSeen) {
274
+ t.skip('codex TUI prompt marker never appeared');
275
+ return;
276
+ }
277
+ const sent = await jsonRequest(baseUrl, `/api/sessions/${session.sessionId}/input`, {
278
+ method: 'POST',
279
+ body: { data: 'What is 17 plus 5? Reply with the number only, nothing else.', submit: true },
280
+ });
281
+ assert.equal(sent.status, 200, JSON.stringify(sent.body));
282
+ // Fixed observation window starting at the input write. Only a STDOUT
283
+ // render of the number 22 counts; the stdin record of the injected text
284
+ // does not (see stdoutText).
285
+ const evidence = await waitForReplyText(session.sessionId, {
286
+ expectText: '22',
287
+ fromMs: Date.now(),
288
+ windowMs: OBSERVE_WINDOW_MS,
289
+ });
290
+ await saveTranscript(session.sessionId, evidence ? evidence.range : await readOutput(session.sessionId));
291
+ assert.ok(evidence, `no AI reply rendered in STDOUT within ${OBSERVE_WINDOW_MS}ms of submit (evidence=${evidence?.evidence || 'none'})`);
292
+ console.log(`[live-probe] L2 evidence: ${evidence.evidence}`);
293
+ }, { timeout: L2_TIMEOUT_MS });
294
+ });