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,234 @@
1
+ import test 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 { SessionRegistry } from '../session-registry.mjs';
7
+ import {
8
+ createRoleProfile,
9
+ readRoleProfile,
10
+ listRoleProfiles,
11
+ roleProfileRefFor,
12
+ profileSessionFields,
13
+ } from '../workflow-node-types/role-profile-store.mjs';
14
+ import { buildAgentContext, findAgentGraphNode } from '../workflow-agent-context.mjs';
15
+ import { loadWorkflowGraphMap, writeWorkflowGraphMap } from '../a2a-store.mjs';
16
+ import { createNode } from '../workflow-node-runtime.mjs';
17
+
18
+ const STATE_JSON_PROHIBITION = 'Never edit `Harness/a2a/**/state.json` directly — use typed actions.';
19
+
20
+ function makeProject() {
21
+ const root = makeHarnessTempRoot('wf-role-profile-');
22
+ fs.mkdirSync(path.join(root, 'Harness', 'a2a', 'skills'), { recursive: true });
23
+ return root;
24
+ }
25
+
26
+ function seedAgentGraph(root, { nodeId, role = 'implementer' } = {}) {
27
+ const registry = new SessionRegistry();
28
+ const session = registry.create({
29
+ runtime: 'claude',
30
+ agentKind: 'subagent',
31
+ role,
32
+ graphNodeId: nodeId,
33
+ });
34
+ registry.update(session.sessionId, { status: 'running' });
35
+ writeWorkflowGraphMap(root, {
36
+ schemaVersion: 1,
37
+ version: 1,
38
+ nodes: [{
39
+ nodeId,
40
+ sessionId: session.sessionId,
41
+ kind: 'terminal-session',
42
+ agentKind: 'subagent',
43
+ runtime: 'claude',
44
+ role,
45
+ label: role,
46
+ status: 'running',
47
+ }],
48
+ edges: [],
49
+ positions: {},
50
+ });
51
+ return { registry, session, nodeId };
52
+ }
53
+
54
+ // AC-001: create-agent writes role profile (ROLE-1). createRoleProfile writes
55
+ // the markdown profile file and returns the roleProfileRef; the session record
56
+ // carries displayName / roleTitle / responsibility / capabilities /
57
+ // roleProfileRef.
58
+ test('AC-001 createRoleProfile writes the .md profile and session record carries role identity', async () => {
59
+ const root = makeProject();
60
+ try {
61
+ const nodeId = 'agent-role-1';
62
+ const result = createRoleProfile({
63
+ nodeId,
64
+ roleTitle: 'implementer',
65
+ displayName: 'Frontend Expert',
66
+ responsibility: 'Implement UI changes inside the assigned write set; run typecheck and build; return evidence.',
67
+ runtime: 'claude',
68
+ provider: 'anthropic',
69
+ model: 'claude-sonnet-4-5',
70
+ capabilities: ['ui-control-plane', 'typescript', 'playwright'],
71
+ }, root);
72
+
73
+ assert.equal(result.roleProfileRef, roleProfileRefFor(nodeId), 'roleProfileRef must point at the markdown profile');
74
+ assert.equal(result.profile.nodeId, nodeId);
75
+ assert.equal(result.profile.roleTitle, 'implementer');
76
+ assert.equal(result.profile.displayName, 'Frontend Expert');
77
+ assert.equal(result.profile.roleProfileRef, result.roleProfileRef);
78
+ assert.ok(Array.isArray(result.profile.capabilities), 'capabilities must be an array');
79
+
80
+ const mdPath = path.join(root, 'Harness', 'a2a', 'agent-roles', `${nodeId}.md`);
81
+ assert.ok(fs.existsSync(mdPath), '.md profile file must exist');
82
+ const md = fs.readFileSync(mdPath, 'utf8');
83
+ assert.ok(md.includes('# Role Profile'), '.md must be a markdown role profile');
84
+ assert.ok(md.includes('Frontend Expert'), '.md must carry displayName');
85
+ assert.ok(md.includes('implementer'), '.md must carry roleTitle');
86
+ assert.ok(md.includes('Implement UI changes'), '.md must carry responsibility prose');
87
+
88
+ const readBack = readRoleProfile(nodeId, root);
89
+ assert.deepEqual(readBack, result.profile, 'readRoleProfile must return the stored profile');
90
+
91
+ const listed = listRoleProfiles(root);
92
+ assert.ok(listed.some(profile => profile.nodeId === nodeId), 'listRoleProfiles must include the profile');
93
+
94
+ // Session record carries the role identity fields (create defaults first).
95
+ const registry = new SessionRegistry();
96
+ const session = registry.create({
97
+ runtime: 'claude',
98
+ agentKind: 'subagent',
99
+ role: 'terminal-agent',
100
+ });
101
+ assert.equal(session.roleProfileRef, null, 'roleProfileRef must be null until a profile is written');
102
+ assert.equal(session.responsibility, '', 'responsibility must default to empty');
103
+ assert.equal(session.roleTitle, 'terminal-agent', 'legacy default roleTitle must remain terminal-agent');
104
+
105
+ // Profile fields land on the session record through profileSessionFields.
106
+ registry.update(session.sessionId, profileSessionFields(result.profile));
107
+ const updated = registry.get(session.sessionId);
108
+ assert.equal(updated.displayName, 'Frontend Expert');
109
+ assert.equal(updated.roleTitle, 'implementer');
110
+ assert.equal(updated.responsibility, result.profile.responsibility);
111
+ assert.deepEqual(updated.capabilities, ['ui-control-plane', 'typescript', 'playwright']);
112
+ assert.equal(updated.roleProfileRef, result.roleProfileRef);
113
+ } finally {
114
+ fs.rmSync(root, { recursive: true, force: true });
115
+ }
116
+ });
117
+
118
+ // AC-002: agent init/context prompt strongly injects its own role profile
119
+ // (ROLE-2). buildAgentContext exposes the agent's own displayName, roleTitle,
120
+ // responsibility, capabilities and roleProfileRef path before any task text.
121
+ test('AC-002 agent context exposes its own role profile and roleProfileRef', async () => {
122
+ const root = makeProject();
123
+ try {
124
+ const { nodeId } = seedAgentGraph(root, { nodeId: 'agent-role-2' });
125
+ createRoleProfile({
126
+ nodeId,
127
+ roleTitle: 'reviewer',
128
+ displayName: 'Code Reviewer',
129
+ responsibility: 'Review the implementation and return evidence.',
130
+ runtime: 'claude',
131
+ provider: 'anthropic',
132
+ capabilities: ['code-review'],
133
+ }, root);
134
+
135
+ const graph = loadWorkflowGraphMap(root);
136
+ const graphNode = findAgentGraphNode(graph, nodeId);
137
+ assert.ok(graphNode, 'agent node must be present in the workflow graph');
138
+
139
+ const context = buildAgentContext(root, graphNode, graph).context;
140
+ assert.equal(context.roleProfile.nodeId, nodeId);
141
+ assert.equal(context.roleProfile.displayName, 'Code Reviewer');
142
+ assert.equal(context.roleProfile.roleTitle, 'reviewer');
143
+ assert.equal(context.roleProfile.responsibility, 'Review the implementation and return evidence.');
144
+ assert.deepEqual(context.roleProfile.capabilities, ['code-review']);
145
+ assert.equal(context.roleProfile.roleProfileRef, `Harness/a2a/agent-roles/${nodeId}.md`);
146
+ assert.equal(context.identity.displayName, 'Code Reviewer');
147
+ assert.equal(context.identity.roleTitle, 'reviewer');
148
+ assert.equal(context.identity.responsibility, 'Review the implementation and return evidence.');
149
+ assert.equal(context.identity.roleProfileRef, `Harness/a2a/agent-roles/${nodeId}.md`);
150
+ } finally {
151
+ fs.rmSync(root, { recursive: true, force: true });
152
+ }
153
+ });
154
+
155
+ // AC-021 (MANUAL-2): when an agent node is connected to a node, the connected
156
+ // node's manual is injected into the agent's context. AC-022 (MANUAL-3): the
157
+ // injected manual text carries the state.json prohibition verbatim.
158
+ test('AC-021/AC-022 connected node manual is injected into context with the state.json prohibition', async () => {
159
+ const root = makeProject();
160
+ try {
161
+ const { nodeId } = seedAgentGraph(root, { nodeId: 'agent-role-3' });
162
+ const markdown = await createNode(root, {
163
+ type: 'markdown',
164
+ title: 'Shared Notes',
165
+ markdown: '# Notes',
166
+ });
167
+ const graphMap = loadWorkflowGraphMap(root);
168
+ writeWorkflowGraphMap(root, {
169
+ ...graphMap,
170
+ edges: [
171
+ { id: 'edge-role-md', from: nodeId, to: markdown.node.nodeId, relation: 'default-output', direction: 'bidirectional', sourceHandle: 'output', targetHandle: 'markdown' },
172
+ ],
173
+ });
174
+ fs.writeFileSync(path.join(root, 'Harness', 'a2a', 'skills', 'workflow-markdown-node.json'), JSON.stringify({
175
+ schemaVersion: 1,
176
+ skillId: 'workflow-markdown-node',
177
+ nodeType: 'markdown',
178
+ description: 'Markdown node guide: shared durable notes between team agents.',
179
+ commands: [
180
+ {
181
+ name: 'markdown-append',
182
+ command: 'workflow-node-action --node <markdownNodeId> --action markdown.append --payload \'{"markdown":"..."}\'',
183
+ description: 'Append text to the connected markdown node through typed actions.',
184
+ },
185
+ ],
186
+ policy: { denied: ['direct-json-state-mutation'] },
187
+ prohibitions: [STATE_JSON_PROHIBITION],
188
+ }, null, 2));
189
+
190
+ const graph = loadWorkflowGraphMap(root);
191
+ const graphNode = findAgentGraphNode(graph, nodeId);
192
+ const context = buildAgentContext(root, graphNode, graph).context;
193
+
194
+ assert.ok(Array.isArray(context.connectedNodeManuals), 'connectedNodeManuals must be an array');
195
+ const manual = context.connectedNodeManuals.find(item => item.nodeType === 'markdown');
196
+ assert.ok(manual, 'connected markdown manual must be injected');
197
+ assert.equal(manual.nodeId, markdown.node.nodeId);
198
+ assert.equal(manual.skillId, 'workflow-markdown-node');
199
+ assert.ok(manual.text.includes('Markdown node guide'), 'manual description must be injected');
200
+ assert.ok(manual.text.includes('markdown.append'), 'manual commands must be injected');
201
+ assert.ok(manual.text.includes(STATE_JSON_PROHIBITION), 'manual must carry the state.json prohibition verbatim (AC-022)');
202
+ } finally {
203
+ fs.rmSync(root, { recursive: true, force: true });
204
+ }
205
+ });
206
+
207
+ // AC-024 (partial) + T13/AC-008: the agent context carries the team-organization
208
+ // decision flow (steps 1-10) including the ask-user gate for ambiguous targets.
209
+ test('AC-024/T13 agent context carries team-organization guidance with the ask-user gate', async () => {
210
+ const root = makeProject();
211
+ try {
212
+ const { nodeId } = seedAgentGraph(root, { nodeId: 'agent-role-4' });
213
+ const graph = loadWorkflowGraphMap(root);
214
+ const graphNode = findAgentGraphNode(graph, nodeId);
215
+ const context = buildAgentContext(root, graphNode, graph).context;
216
+
217
+ const guidance = context.teamGuidance;
218
+ assert.ok(typeof guidance === 'string' && guidance.length > 0, 'teamGuidance must be a non-empty text block');
219
+ // §2 step 1: understand the task.
220
+ assert.ok(/understand the task/i.test(guidance), 'guidance must open with understanding the task');
221
+ // §2 step 2: decide whether team collaboration is needed.
222
+ assert.ok(/team collaboration is needed/i.test(guidance), 'guidance must include the team-needed decision (T1)');
223
+ // §2 step 3: choose roles from the roleTitle vocabulary.
224
+ assert.ok(/implementer/.test(guidance), 'guidance must name roles from the canonical vocabulary');
225
+ // §2 step 7 / §4.4 (T13): ambiguous target -> ask the user, never blind create/connect.
226
+ assert.ok(/ask the user/i.test(guidance), 'guidance must surface the ask-user gate for ambiguous targets (T13/AC-008)');
227
+ assert.ok(/never blindly create or connect/i.test(guidance), 'guidance must forbid blind create/connect on ambiguity');
228
+ // §2 steps 8-10: share context via Markdown, structured requests, Goal completion.
229
+ assert.ok(/Markdown/i.test(guidance), 'guidance must mention Markdown node sharing');
230
+ assert.ok(/Goal/i.test(guidance), 'guidance must mention Goal completion');
231
+ } finally {
232
+ fs.rmSync(root, { recursive: true, force: true });
233
+ }
234
+ });
@@ -0,0 +1,261 @@
1
+ // workflow-set-model.test.mjs
2
+ //
3
+ // agent.setModel backend action — model selection via project-scope runtime
4
+ // config files (no TUI keystrokes needed).
5
+ //
6
+ // M1: setModel on a codex session → 200, project .codex/config.toml model
7
+ // line updated, other lines preserved byte-for-byte, session record
8
+ // model updated + restartRequired true
9
+ // M2: unknown node → 404
10
+ // M3: runtime without project config (deepseek: user-scope only) → 409
11
+ // NO_PROJECT_MODEL_CONFIG
12
+ // M4: empty model → 400
13
+ // M5: only user-scope config exists (~/.codex) → 409
14
+ // NO_PROJECT_MODEL_CONFIG, user file untouched
15
+ // M6: JSON project config (.claude/settings.json) model field updated,
16
+ // other fields preserved
17
+ //
18
+ // Pattern: in-process node:test + HTTP server on port 0, one temp project
19
+ // root for the server; config files and graph nodes are seeded under that
20
+ // same root (the action resolves project config paths against the server's
21
+ // project root). The user home is redirected to a temp dir BEFORE server.mjs
22
+ // is imported — runtime-detector.mjs captures os.homedir() at module load —
23
+ // so user-scope config paths (~/.codex/...) resolve inside the temp root and
24
+ // the real user home is never read or written. node --test runs each file in
25
+ // its own process, so the override stays local.
26
+ //
27
+ // Run: node --test src/wf-ui-server/__tests__/workflow-set-model.test.mjs
28
+ import { after, before, describe, it } from 'node:test';
29
+ import assert from 'node:assert/strict';
30
+ import fs from 'node:fs';
31
+ import http from 'node:http';
32
+ import path from 'node:path';
33
+ import { makeHarnessTempRoot } from '../../../tests/support/temp-root.js';
34
+ import { SessionRegistry } from '../session-registry.mjs';
35
+
36
+ // ── fake home redirect (must precede the server.mjs import) ──
37
+ const fakeHomeDir = makeHarnessTempRoot('wf-ui-set-model-home-');
38
+ process.env.USERPROFILE = fakeHomeDir;
39
+ process.env.HOMEDRIVE = path.parse(fakeHomeDir).root;
40
+ process.env.HOMEPATH = fakeHomeDir.slice(path.parse(fakeHomeDir).root.length);
41
+ process.env.HOME = fakeHomeDir;
42
+
43
+ const { createServer } = await import('../server.mjs');
44
+
45
+ // ── project seeding + helpers ──
46
+ function tempProjectRoot(prefix) {
47
+ const root = makeHarnessTempRoot(prefix);
48
+ const a2a = path.join(root, 'Harness', 'a2a');
49
+ fs.mkdirSync(path.join(a2a, 'component-nodes'), { recursive: true });
50
+ fs.writeFileSync(path.join(a2a, 'component-nodes', 'index.json'), JSON.stringify({ schemaVersion: 1, nodes: [] }));
51
+ fs.writeFileSync(path.join(a2a, 'workflow-map.json'), JSON.stringify({
52
+ schemaVersion: 1,
53
+ version: 1,
54
+ nodes: [],
55
+ edges: [],
56
+ positions: {},
57
+ undoStack: [],
58
+ redoStack: [],
59
+ deletedNodes: [],
60
+ }));
61
+ return root;
62
+ }
63
+
64
+ function addGraphNode(root, { nodeId, sessionId, runtime }) {
65
+ const file = path.join(root, 'Harness', 'a2a', 'workflow-map.json');
66
+ const graph = JSON.parse(fs.readFileSync(file, 'utf8'));
67
+ graph.nodes.push({
68
+ nodeId,
69
+ sessionId,
70
+ kind: 'terminal-session',
71
+ agentKind: 'main',
72
+ runtime,
73
+ status: 'running',
74
+ cwd: root,
75
+ position: { x: 120, y: 90 },
76
+ });
77
+ graph.positions[nodeId] = { x: 120, y: 90 };
78
+ fs.writeFileSync(file, `${JSON.stringify(graph, null, 2)}\n`, 'utf8');
79
+ }
80
+
81
+ function makeAgentNode(registry, root, { runtime, graphNodeId }) {
82
+ const session = registry.create({
83
+ runtime,
84
+ agentKind: 'main',
85
+ role: 'main',
86
+ objective: 'agent.setModel test',
87
+ projectRoot: root,
88
+ cwd: root,
89
+ graphNodeId,
90
+ });
91
+ registry.update(session.sessionId, { status: 'running', graphNodeId });
92
+ addGraphNode(root, { nodeId: graphNodeId, sessionId: session.sessionId, runtime });
93
+ return { session: registry.get(session.sessionId), graphNodeId };
94
+ }
95
+
96
+ function jsonRequest(url, { method = 'GET', body } = {}) {
97
+ return new Promise((resolve, reject) => {
98
+ const req = http.request(url, { method, headers: { 'content-type': 'application/json' } }, (res) => {
99
+ let data = '';
100
+ res.on('data', chunk => { data += chunk; });
101
+ res.on('end', () => {
102
+ try { resolve({ status: res.statusCode, body: JSON.parse(data) }); }
103
+ catch { resolve({ status: res.statusCode, body: data }); }
104
+ });
105
+ });
106
+ req.on('error', reject);
107
+ if (body !== undefined) req.write(JSON.stringify(body));
108
+ req.end();
109
+ });
110
+ }
111
+
112
+ describe('agent.setModel workflow node action', () => {
113
+ let root;
114
+ let registry;
115
+ let server;
116
+ let baseUrl;
117
+
118
+ before(async () => {
119
+ root = tempProjectRoot('wf-ui-set-model-');
120
+ registry = new SessionRegistry();
121
+ server = createServer({ projectRoot: root, sessionRegistry: registry, token: '' });
122
+ await new Promise(resolve => server.listen(0, resolve));
123
+ baseUrl = `http://127.0.0.1:${server.address().port}`;
124
+ });
125
+
126
+ after(() => {
127
+ if (server) server.close();
128
+ try { fs.rmSync(root, { recursive: true, force: true }); } catch {}
129
+ try { fs.rmSync(fakeHomeDir, { recursive: true, force: true }); } catch {}
130
+ });
131
+
132
+ it('M1: setModel updates the project .codex/config.toml model line and the session record', async () => {
133
+ const configDir = path.join(root, '.codex');
134
+ fs.mkdirSync(configDir, { recursive: true });
135
+ try {
136
+ const seed = [
137
+ '# codex project config',
138
+ 'model = "gpt-5.4"',
139
+ 'model_provider = "openai"',
140
+ '',
141
+ '[model_providers.anthropic]',
142
+ 'name = "anthropic"',
143
+ ].join('\n');
144
+ fs.writeFileSync(path.join(configDir, 'config.toml'), seed, 'utf8');
145
+
146
+ const { session, graphNodeId } = makeAgentNode(registry, root, { runtime: 'codex', graphNodeId: 'setmodel-m1' });
147
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/${graphNodeId}/actions/agent.setModel`, {
148
+ method: 'POST',
149
+ body: { model: 'gpt-5.5' },
150
+ });
151
+ assert.equal(res.status, 200, JSON.stringify(res.body));
152
+ assert.equal(res.body.ok, true);
153
+ assert.equal(res.body.action, 'agent.setModel');
154
+ assert.equal(res.body.model, 'gpt-5.5');
155
+ assert.equal(res.body.configFile, '.codex/config.toml');
156
+ assert.equal(res.body.restartRequired, true);
157
+
158
+ const text = fs.readFileSync(path.join(configDir, 'config.toml'), 'utf8');
159
+ assert.equal(text, [
160
+ '# codex project config',
161
+ 'model = "gpt-5.5"',
162
+ 'model_provider = "openai"',
163
+ '',
164
+ '[model_providers.anthropic]',
165
+ 'name = "anthropic"',
166
+ ].join('\n'), 'only the top-level model line may change; every other byte preserved');
167
+
168
+ const updated = registry.get(session.sessionId);
169
+ assert.equal(updated.model, 'gpt-5.5');
170
+ assert.equal(updated.restartRequired, true);
171
+ assert.ok(updated.restartRequiredFields.includes('model'), 'restartRequiredFields must include model');
172
+
173
+ const disk = JSON.parse(fs.readFileSync(
174
+ path.join(root, 'Harness', 'a2a', 'sessions', session.sessionId, 'STATE.json'), 'utf8'));
175
+ assert.equal(disk.model, 'gpt-5.5');
176
+ assert.equal(disk.restartRequired, true);
177
+ } finally {
178
+ fs.rmSync(configDir, { recursive: true, force: true });
179
+ }
180
+ });
181
+
182
+ it('M2: unknown node → 404', async () => {
183
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/setmodel-does-not-exist/actions/agent.setModel`, {
184
+ method: 'POST',
185
+ body: { model: 'gpt-6' },
186
+ });
187
+ assert.equal(res.status, 404);
188
+ assert.equal(res.body.error.code, 'NOT_FOUND');
189
+ });
190
+
191
+ it('M3: runtime without a project config → 409 NO_PROJECT_MODEL_CONFIG', async () => {
192
+ // deepseek defines only a user-scope config (~/.deepseek/config.toml),
193
+ // so no project-scope model config is known for the runtime.
194
+ const { graphNodeId } = makeAgentNode(registry, root, { runtime: 'deepseek', graphNodeId: 'setmodel-m3' });
195
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/${graphNodeId}/actions/agent.setModel`, {
196
+ method: 'POST',
197
+ body: { model: 'deepseek-v4' },
198
+ });
199
+ assert.equal(res.status, 409);
200
+ assert.equal(res.body.error.code, 'NO_PROJECT_MODEL_CONFIG');
201
+ });
202
+
203
+ it('M4: empty model → 400', async () => {
204
+ const { graphNodeId } = makeAgentNode(registry, root, { runtime: 'codex', graphNodeId: 'setmodel-m4' });
205
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/${graphNodeId}/actions/agent.setModel`, {
206
+ method: 'POST',
207
+ body: { model: ' ' },
208
+ });
209
+ assert.equal(res.status, 400);
210
+ assert.equal(res.body.error.code, 'BAD_REQUEST');
211
+ });
212
+
213
+ it('M5: user-scope config is never touched — only user config exists → 409', async () => {
214
+ // Seed the USER-scope codex config inside the redirected fake home; the
215
+ // project itself has no .codex/config.toml.
216
+ const userConfigPath = path.join(fakeHomeDir, '.codex', 'config.toml');
217
+ fs.mkdirSync(path.dirname(userConfigPath), { recursive: true });
218
+ fs.writeFileSync(userConfigPath, 'model = "user-model"\n', 'utf8');
219
+
220
+ const { graphNodeId } = makeAgentNode(registry, root, { runtime: 'codex', graphNodeId: 'setmodel-m5' });
221
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/${graphNodeId}/actions/agent.setModel`, {
222
+ method: 'POST',
223
+ body: { model: 'gpt-6' },
224
+ });
225
+ assert.equal(res.status, 409);
226
+ assert.equal(res.body.error.code, 'NO_PROJECT_MODEL_CONFIG');
227
+ assert.equal(fs.readFileSync(userConfigPath, 'utf8'), 'model = "user-model"\n', 'user-scoped config must remain untouched');
228
+ });
229
+
230
+ it('M6: JSON project config (.claude/settings.json) model updated, other fields preserved', async () => {
231
+ const settingsDir = path.join(root, '.claude');
232
+ fs.mkdirSync(settingsDir, { recursive: true });
233
+ try {
234
+ fs.writeFileSync(path.join(settingsDir, 'settings.json'), JSON.stringify({
235
+ model: 'claude-opus-4-0',
236
+ env: { MY_VAR: 'keep-me' },
237
+ permissions: { allow: ['Bash'] },
238
+ }, null, 2), 'utf8');
239
+
240
+ const { session, graphNodeId } = makeAgentNode(registry, root, { runtime: 'claude', graphNodeId: 'setmodel-m6' });
241
+ const res = await jsonRequest(`${baseUrl}/api/workflow/nodes/${graphNodeId}/actions/agent.setModel`, {
242
+ method: 'POST',
243
+ body: { model: 'claude-opus-4-1' },
244
+ });
245
+ assert.equal(res.status, 200, JSON.stringify(res.body));
246
+ assert.equal(res.body.configFile, '.claude/settings.json');
247
+ assert.equal(res.body.restartRequired, true);
248
+
249
+ const data = JSON.parse(fs.readFileSync(path.join(settingsDir, 'settings.json'), 'utf8'));
250
+ assert.equal(data.model, 'claude-opus-4-1');
251
+ assert.deepEqual(data.env, { MY_VAR: 'keep-me' });
252
+ assert.deepEqual(data.permissions, { allow: ['Bash'] });
253
+
254
+ const updated = registry.get(session.sessionId);
255
+ assert.equal(updated.model, 'claude-opus-4-1');
256
+ assert.equal(updated.restartRequired, true);
257
+ } finally {
258
+ fs.rmSync(settingsDir, { recursive: true, force: true });
259
+ }
260
+ });
261
+ });
@@ -0,0 +1,131 @@
1
+ import { describe, it, before, after } from 'node:test';
2
+ import assert from 'node:assert';
3
+ import fs from 'node:fs';
4
+ import path from 'node:path';
5
+ import crypto from 'node:crypto';
6
+
7
+ // ── Helpers ──
8
+ function tempProjectRoot() {
9
+ const id = crypto.randomBytes(4).toString('hex');
10
+ const dir = path.join(process.cwd(), '.tmp-skill-group-context-enabled-' + id);
11
+ fs.mkdirSync(path.join(dir, 'Harness', 'a2a', 'component-nodes'), { recursive: true });
12
+ fs.writeFileSync(path.join(dir, 'Harness', 'a2a', 'component-nodes', 'index.json'), JSON.stringify({ schemaVersion: 1, nodes: [] }));
13
+ fs.mkdirSync(path.join(dir, 'Harness', 'a2a'), { recursive: true });
14
+ fs.writeFileSync(path.join(dir, 'Harness', 'a2a', 'workflow-map.json'), JSON.stringify({ schemaVersion: 1, version: 1, nodes: [], edges: [], positions: {}, undoStack: [], redoStack: [], deletedNodes: [] }));
15
+ return dir;
16
+ }
17
+
18
+ function cleanup(dir) {
19
+ try { fs.rmSync(dir, { recursive: true, force: true }); } catch {}
20
+ }
21
+
22
+ function seedAgentGraphNode(root, nodeId = 'session-skill-context-agent-01', overrides = {}) {
23
+ const graph = runtime.loadWorkflowGraphMap(root);
24
+ const sessionId = overrides.sessionId || `${nodeId}-pty`;
25
+ runtime.writeWorkflowGraphMap(root, {
26
+ ...graph,
27
+ version: graph.version + 1,
28
+ nodes: [
29
+ ...(graph.nodes || []),
30
+ {
31
+ nodeId,
32
+ sessionId,
33
+ agentKind: overrides.agentKind || 'main',
34
+ runtime: overrides.runtime || 'codex',
35
+ status: overrides.status || 'stopped',
36
+ label: overrides.label || 'Skill Context Agent',
37
+ cwd: root,
38
+ taskId: null,
39
+ role: overrides.role || overrides.agentKind || 'main',
40
+ },
41
+ ],
42
+ positions: {
43
+ ...(graph.positions || {}),
44
+ [nodeId]: { x: 100, y: 120 },
45
+ },
46
+ });
47
+ return nodeId;
48
+ }
49
+
50
+ let runtime;
51
+ let graphStore;
52
+ let SkillGroupNode;
53
+
54
+ before(async () => {
55
+ runtime = await import('../workflow-node-runtime.mjs');
56
+ graphStore = await import('../workflow-graph-store.mjs');
57
+ SkillGroupNode = await import('../workflow-node-types/skill-group-node.mjs');
58
+ });
59
+
60
+ describe('effectiveSkillGroups skillRefs enabled projection (W38-BE-FOLLOWUP)', () => {
61
+ const roots = [];
62
+ after(() => roots.forEach(cleanup));
63
+
64
+ function seedPack(root) {
65
+ return runtime.createNode(root, {
66
+ type: 'skill-group',
67
+ title: 'Agent Skill Pack',
68
+ sourceGroup: { id: 'source:workflow', label: 'Workflow', kind: 'source' },
69
+ skills: [
70
+ { id: 'skill:wf-ui', name: 'wf-ui', title: 'WF-UI Adapter', source: 'project' },
71
+ { id: 'skill:browser-lab', name: 'browser-lab', title: 'Browser Lab', source: 'project' },
72
+ { id: 'skill:api-lab', name: 'api-lab', title: 'API Lab', source: 'project' },
73
+ ],
74
+ });
75
+ }
76
+
77
+ it('projects enabled:false onto effectiveSkillGroups[].skillRefs after setSkillEnabled(false)', async () => {
78
+ const root = tempProjectRoot();
79
+ roots.push(root);
80
+ const pack = await seedPack(root);
81
+ const nodeId = pack.node.nodeId;
82
+ const agentId = seedAgentGraphNode(root);
83
+ graphStore.connectNodes(root, {
84
+ from: agentId,
85
+ to: nodeId,
86
+ relation: 'capability',
87
+ sourceHandle: 'right',
88
+ targetHandle: 'capability:left',
89
+ });
90
+
91
+ // Default state: every projected skillRef reports enabled:true
92
+ const before = await runtime.getNodeContext(root, agentId);
93
+ assert.equal(before.context.effectiveSkillGroups.length, 1);
94
+ const skillRefsBefore = before.context.effectiveSkillGroups[0].skillRefs;
95
+ assert.ok(Array.isArray(skillRefsBefore));
96
+ assert.equal(skillRefsBefore.length, 3);
97
+ for (const ref of skillRefsBefore) {
98
+ assert.equal(ref.enabled, true, `skill ${ref.name} should default to enabled:true`);
99
+ }
100
+
101
+ // Toggle one skill off
102
+ SkillGroupNode.setSkillEnabled(nodeId, root, { skillId: 'skill:browser-lab', enabled: false });
103
+
104
+ const after = await runtime.getNodeContext(root, agentId);
105
+ assert.equal(after.context.effectiveSkillGroups.length, 1);
106
+ const skillRefsAfter = after.context.effectiveSkillGroups[0].skillRefs;
107
+ const browserLab = skillRefsAfter.find(s => s.name === 'browser-lab');
108
+ const wfUi = skillRefsAfter.find(s => s.name === 'wf-ui');
109
+ const apiLab = skillRefsAfter.find(s => s.name === 'api-lab');
110
+ assert.equal(browserLab.enabled, false, 'toggled skill must surface enabled:false in skillRefs');
111
+ assert.equal(wfUi.enabled, true, 'untouched skills must remain enabled:true');
112
+ assert.equal(apiLab.enabled, true, 'untouched skills must remain enabled:true');
113
+
114
+ // Toggle back to true
115
+ SkillGroupNode.setSkillEnabled(nodeId, root, { skillId: 'skill:browser-lab', enabled: true });
116
+ const restored = await runtime.getNodeContext(root, agentId);
117
+ const skillRefsRestored = restored.context.effectiveSkillGroups[0].skillRefs;
118
+ const browserLabRestored = skillRefsRestored.find(s => s.name === 'browser-lab');
119
+ assert.equal(browserLabRestored.enabled, true, 'toggled-back skill must surface enabled:true in skillRefs');
120
+
121
+ // skillRefs remain body-free (no SKILL.md body, no absolute project path, no description)
122
+ const serialized = JSON.stringify(restored.context.effectiveSkillGroups);
123
+ assert.ok(!serialized.includes('SKILL.md'), 'effectiveSkillGroups.skillRefs must not leak SKILL.md body');
124
+ assert.ok(!serialized.includes(root), 'effectiveSkillGroups.skillRefs must not leak absolute project path');
125
+ for (const ref of skillRefsRestored) {
126
+ const keys = Object.keys(ref).sort();
127
+ // Body-free: only the lightweight projected fields are allowed
128
+ assert.deepEqual(keys, ['enabled', 'id', 'name', 'source', 'state', 'title'], `unexpected skillRef fields: ${keys.join(',')}`);
129
+ }
130
+ });
131
+ });