@vibeflow-tools/cli 0.10.0 → 0.12.0

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 (214) hide show
  1. package/CHANGELOG.md +121 -23
  2. package/dist/chunk-22ZK3AD6.js +6 -0
  3. package/dist/chunk-2CI62NHU.js +8 -0
  4. package/dist/chunk-2FTOVVDE.js +10 -0
  5. package/dist/chunk-2HKRXAUP.js +10 -0
  6. package/dist/chunk-2L7GDWKA.js +8 -0
  7. package/dist/chunk-32Z32W7T.js +2 -0
  8. package/dist/chunk-3V7HLRIS.js +6 -0
  9. package/dist/chunk-4KWRHSXU.js +10 -0
  10. package/dist/chunk-ACDVAO4P.js +6 -0
  11. package/dist/chunk-BBIA4IIO.js +2 -0
  12. package/dist/chunk-BOPGIKZN.js +8 -0
  13. package/dist/chunk-BUQI2W5H.js +2 -0
  14. package/dist/chunk-BZDBSBRV.js +2 -0
  15. package/dist/chunk-CKNX42Z3.js +10 -0
  16. package/dist/chunk-CQ524DVH.js +2 -0
  17. package/dist/chunk-D4FZTZHO.js +8 -0
  18. package/dist/chunk-EAYTSVCN.js +2 -0
  19. package/dist/chunk-EDJNSJXJ.js +10 -0
  20. package/dist/chunk-ES3JTCZ7.js +8 -0
  21. package/dist/chunk-EZX6HYC3.js +8 -0
  22. package/dist/chunk-FYRJDWDC.js +2 -0
  23. package/dist/chunk-GN436FFO.js +10 -0
  24. package/dist/chunk-GQQIUROY.js +2 -0
  25. package/dist/chunk-GTZDS3U3.js +6 -0
  26. package/dist/chunk-I3WFKPN7.js +8 -0
  27. package/dist/chunk-ICO6AZHJ.js +10 -0
  28. package/dist/chunk-IJ67OEKX.js +2 -0
  29. package/dist/chunk-ILUMCOF2.js +2 -0
  30. package/dist/chunk-JAWQQLJC.js +8 -0
  31. package/dist/chunk-JQTURVVN.js +2 -0
  32. package/dist/chunk-KZZ4ADHY.js +6 -0
  33. package/dist/chunk-L6EJ7QTO.js +6 -0
  34. package/dist/chunk-LYJHU4LP.js +10 -0
  35. package/dist/chunk-N5PXJMOU.js +6 -0
  36. package/dist/chunk-NHVKGOSV.js +10 -0
  37. package/dist/chunk-O4LGEPMQ.js +8 -0
  38. package/dist/chunk-P63ZVL36.js +2 -0
  39. package/dist/chunk-PFOVGF7M.js +10 -0
  40. package/dist/chunk-PGGJRQCO.js +2 -0
  41. package/dist/chunk-PN5C7EHL.js +8 -0
  42. package/dist/chunk-PWP474PZ.js +2 -0
  43. package/dist/chunk-PYMUW2HM.js +8 -0
  44. package/dist/chunk-Q7MEW67Z.js +8 -0
  45. package/dist/chunk-QJMBWTAZ.js +8 -0
  46. package/dist/chunk-R5NQALFI.js +2 -0
  47. package/dist/chunk-RBBUTBE3.js +6 -0
  48. package/dist/chunk-RRQ5P63N.js +2 -0
  49. package/dist/chunk-SQPWTIQO.js +2 -0
  50. package/dist/chunk-TCTUG3QV.js +8 -0
  51. package/dist/chunk-TTWEWSD3.js +6 -0
  52. package/dist/chunk-WARORREB.js +2 -0
  53. package/dist/chunk-WHXU37AT.js +10 -0
  54. package/dist/chunk-WKEMBLJR.js +2 -0
  55. package/dist/chunk-WVRMKUU5.js +6 -0
  56. package/dist/chunk-WZ2QQDYW.js +2 -0
  57. package/dist/chunk-X3VLCXWS.js +6 -0
  58. package/dist/chunk-X4CQRMD4.js +6 -0
  59. package/dist/chunk-X4RGF6JJ.js +2 -0
  60. package/dist/chunk-XHZXHACL.js +2 -0
  61. package/dist/chunk-XJ35INCK.js +10 -0
  62. package/dist/chunk-XYZECVJ4.js +8 -0
  63. package/dist/chunk-YMBPKWZ4.js +2 -0
  64. package/dist/chunk-ZHA4Y2KB.js +8 -0
  65. package/dist/cli/chunk-22ZK3AD6.js +6 -0
  66. package/dist/cli/chunk-2CI62NHU.js +8 -0
  67. package/dist/cli/chunk-2FTOVVDE.js +10 -0
  68. package/dist/cli/chunk-2HKRXAUP.js +10 -0
  69. package/dist/cli/chunk-2L7GDWKA.js +8 -0
  70. package/dist/cli/chunk-32Z32W7T.js +2 -0
  71. package/dist/cli/chunk-3V7HLRIS.js +6 -0
  72. package/dist/cli/chunk-4KWRHSXU.js +10 -0
  73. package/dist/cli/chunk-ACDVAO4P.js +6 -0
  74. package/dist/cli/chunk-BBIA4IIO.js +2 -0
  75. package/dist/cli/chunk-BOPGIKZN.js +8 -0
  76. package/dist/cli/chunk-BUQI2W5H.js +2 -0
  77. package/dist/cli/chunk-BZDBSBRV.js +2 -0
  78. package/dist/cli/chunk-CKNX42Z3.js +10 -0
  79. package/dist/cli/chunk-CQ524DVH.js +2 -0
  80. package/dist/cli/chunk-D4FZTZHO.js +8 -0
  81. package/dist/cli/chunk-EAYTSVCN.js +2 -0
  82. package/dist/cli/chunk-EDJNSJXJ.js +10 -0
  83. package/dist/cli/chunk-ES3JTCZ7.js +8 -0
  84. package/dist/cli/chunk-EZX6HYC3.js +8 -0
  85. package/dist/cli/chunk-FYRJDWDC.js +2 -0
  86. package/dist/cli/chunk-GN436FFO.js +10 -0
  87. package/dist/cli/chunk-GQQIUROY.js +2 -0
  88. package/dist/cli/chunk-GTZDS3U3.js +6 -0
  89. package/dist/cli/chunk-I3WFKPN7.js +8 -0
  90. package/dist/cli/chunk-ICO6AZHJ.js +10 -0
  91. package/dist/cli/chunk-IJ67OEKX.js +2 -0
  92. package/dist/cli/chunk-ILUMCOF2.js +2 -0
  93. package/dist/cli/chunk-JAWQQLJC.js +8 -0
  94. package/dist/cli/chunk-JQTURVVN.js +2 -0
  95. package/dist/cli/chunk-KZZ4ADHY.js +6 -0
  96. package/dist/cli/chunk-L6EJ7QTO.js +6 -0
  97. package/dist/cli/chunk-LYJHU4LP.js +10 -0
  98. package/dist/cli/chunk-N5PXJMOU.js +6 -0
  99. package/dist/cli/chunk-NHVKGOSV.js +10 -0
  100. package/dist/cli/chunk-O4LGEPMQ.js +8 -0
  101. package/dist/cli/chunk-P63ZVL36.js +2 -0
  102. package/dist/cli/chunk-PFOVGF7M.js +10 -0
  103. package/dist/cli/chunk-PGGJRQCO.js +2 -0
  104. package/dist/cli/chunk-PN5C7EHL.js +8 -0
  105. package/dist/cli/chunk-PWP474PZ.js +2 -0
  106. package/dist/cli/chunk-PYMUW2HM.js +8 -0
  107. package/dist/cli/chunk-Q7MEW67Z.js +8 -0
  108. package/dist/cli/chunk-QJMBWTAZ.js +8 -0
  109. package/dist/cli/chunk-R5NQALFI.js +2 -0
  110. package/dist/cli/chunk-RBBUTBE3.js +6 -0
  111. package/dist/cli/chunk-RRQ5P63N.js +2 -0
  112. package/dist/cli/chunk-SQPWTIQO.js +2 -0
  113. package/dist/cli/chunk-TCTUG3QV.js +8 -0
  114. package/dist/cli/chunk-TTWEWSD3.js +6 -0
  115. package/dist/cli/chunk-WARORREB.js +2 -0
  116. package/dist/cli/chunk-WHXU37AT.js +10 -0
  117. package/dist/cli/chunk-WKEMBLJR.js +2 -0
  118. package/dist/cli/chunk-WVRMKUU5.js +6 -0
  119. package/dist/cli/chunk-WZ2QQDYW.js +2 -0
  120. package/dist/cli/chunk-X3VLCXWS.js +6 -0
  121. package/dist/cli/chunk-X4CQRMD4.js +6 -0
  122. package/dist/cli/chunk-X4RGF6JJ.js +2 -0
  123. package/dist/cli/chunk-XHZXHACL.js +2 -0
  124. package/dist/cli/chunk-XJ35INCK.js +10 -0
  125. package/dist/cli/chunk-XYZECVJ4.js +8 -0
  126. package/dist/cli/chunk-YMBPKWZ4.js +2 -0
  127. package/dist/cli/chunk-ZHA4Y2KB.js +8 -0
  128. package/dist/cli/comments-5LRGOYLT.js +2 -0
  129. package/dist/cli/comments-D3SKM2F4.js +2 -0
  130. package/dist/cli/comments-GGE2X2EE.js +2 -0
  131. package/dist/cli/comments-GZ6HQMHL.js +2 -0
  132. package/dist/cli/comments-LHSMBKJ3.js +2 -0
  133. package/dist/cli/comments-M5HDNHXR.js +2 -0
  134. package/dist/cli/comments-MJP5KLEE.js +2 -0
  135. package/dist/cli/comments-TQHWMRB4.js +2 -0
  136. package/dist/cli/comments-VSWJW47E.js +2 -0
  137. package/dist/cli/files-3GGL6AHA.js +2 -0
  138. package/dist/cli/files-4M7AX2IR.js +2 -0
  139. package/dist/cli/files-4O3JKNKY.js +2 -0
  140. package/dist/cli/files-7GFBKISD.js +2 -0
  141. package/dist/cli/files-7H73XU4Z.js +2 -0
  142. package/dist/cli/files-BMMCSJZ3.js +2 -0
  143. package/dist/cli/files-CZEVX3KX.js +2 -0
  144. package/dist/cli/files-F2EISWAF.js +2 -0
  145. package/dist/cli/files-FL23FKMK.js +2 -0
  146. package/dist/cli/files-FW2FWYFX.js +2 -0
  147. package/dist/cli/files-GQPP5SSP.js +2 -0
  148. package/dist/cli/files-QO35EIJI.js +2 -0
  149. package/dist/cli/files-R6BRCQQX.js +2 -0
  150. package/dist/cli/files-RNEVXCMZ.js +2 -0
  151. package/dist/cli/files-TGBQRRBH.js +2 -0
  152. package/dist/cli/files-WH4W5IPG.js +2 -0
  153. package/dist/cli/files-XKVCQQMI.js +2 -0
  154. package/dist/cli/git-NH6PGXOM.js +2 -0
  155. package/dist/cli/index.js +67 -55
  156. package/dist/cli/push-25YMX4RZ.js +2 -0
  157. package/dist/cli/push-26JSGYHL.js +2 -0
  158. package/dist/cli/push-5NNA77B2.js +2 -0
  159. package/dist/cli/push-7M34G4OW.js +2 -0
  160. package/dist/cli/push-AARMGHSL.js +2 -0
  161. package/dist/cli/push-EVBLKP53.js +2 -0
  162. package/dist/cli/push-HG6EPV6P.js +2 -0
  163. package/dist/cli/push-RFYHMZBR.js +2 -0
  164. package/dist/cli/push-RQJQM7U7.js +2 -0
  165. package/dist/cli/push-S4G36KHW.js +2 -0
  166. package/dist/cli/push-S5XSREE5.js +2 -0
  167. package/dist/cli/push-SWN2KN2R.js +2 -0
  168. package/dist/cli/review-gate-QR2E4REN.js +2 -0
  169. package/dist/cli/settings-KKHPB344.js +2 -0
  170. package/dist/cli/settings-PYRZJJ4H.js +2 -0
  171. package/dist/cli/tasks-3HXDHCPS.js +2 -0
  172. package/dist/cli/tasks-5X5AAK2N.js +2 -0
  173. package/dist/cli/tasks-MUL5SYJQ.js +2 -0
  174. package/dist/cli/tasks-N3AEGAEB.js +2 -0
  175. package/dist/cli/tasks-NSLXFEXZ.js +2 -0
  176. package/dist/cli/tasks-OJTUAWAN.js +2 -0
  177. package/dist/cli/tasks-SV7ZVS7W.js +2 -0
  178. package/dist/cli/tasks-VCU3JVNJ.js +2 -0
  179. package/dist/cli/verify-44MRXSPT.js +2 -0
  180. package/dist/cli/verify-AXMQ27UT.js +2 -0
  181. package/dist/cli/verify-BJ62CQI3.js +2 -0
  182. package/dist/cli/verify-DEG2BZOB.js +2 -0
  183. package/dist/cli/verify-DGL7A4WD.js +2 -0
  184. package/dist/cli/verify-GP427VCE.js +2 -0
  185. package/dist/cli/verify-QUCASFYP.js +2 -0
  186. package/dist/cli/verify-RY7B6C2P.js +2 -0
  187. package/dist/cli/verify-TTAW3GG6.js +2 -0
  188. package/dist/cli/verify-VLVCMBBW.js +2 -0
  189. package/dist/cli/verify-XL7JI7LN.js +2 -0
  190. package/dist/cli/verify-ZOAIUNRD.js +2 -0
  191. package/dist/cli/workspace-AJAVENKA.js +2 -0
  192. package/dist/client/kanban-browser.js +17 -11
  193. package/dist/client/kanban.css +1 -1
  194. package/dist/client/overlay-browser.js +6 -6
  195. package/dist/files-3GGL6AHA.js +2 -0
  196. package/dist/files-4M7AX2IR.js +2 -0
  197. package/dist/files-4O3JKNKY.js +2 -0
  198. package/dist/files-7GFBKISD.js +2 -0
  199. package/dist/files-7H73XU4Z.js +2 -0
  200. package/dist/files-BMMCSJZ3.js +2 -0
  201. package/dist/files-CZEVX3KX.js +2 -0
  202. package/dist/files-F2EISWAF.js +2 -0
  203. package/dist/files-FL23FKMK.js +2 -0
  204. package/dist/files-FW2FWYFX.js +2 -0
  205. package/dist/files-GQPP5SSP.js +2 -0
  206. package/dist/files-QO35EIJI.js +2 -0
  207. package/dist/files-R6BRCQQX.js +2 -0
  208. package/dist/files-RNEVXCMZ.js +2 -0
  209. package/dist/files-TGBQRRBH.js +2 -0
  210. package/dist/files-WH4W5IPG.js +2 -0
  211. package/dist/files-XKVCQQMI.js +2 -0
  212. package/dist/index.js +67 -55
  213. package/dist/workspace-AJAVENKA.js +2 -0
  214. package/package.json +2 -1
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{i as k,j as i,k as p,m as l,p as u}from"./chunk-EZX6HYC3.js";import{mkdirSync as x,writeFileSync as y,renameSync as P}from"fs";import{dirname as w}from"path";import{randomBytes as O}from"crypto";function T(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function v(t,n){let r=i(t,n);return((r?l(r):null)?.comments??[]).filter(m=>!m.deleted).map(T)}function S(t){return p(t)}function B(t,n,r,o,m,s,a){o=S(o);let e=i(t,n),h=(e?l(e):null)?.comments??[],g={id:O(8).toString("hex"),author:r,text:o,...m&&m.length>0?{files:m}:{},...s&&s!=="comment"?{type:s}:{},createdAt:new Date().toISOString(),source:a??"cli"},f=[...h,g];if(!u(t,n,{comments:f})){let d=k(t,n,new Date().toISOString());x(w(d),{recursive:!0});let C=d+".tmp";y(C,JSON.stringify({id:n,comments:f},null,2),"utf-8"),P(C,d)}return g}function E(t,n,r,o){let m=i(t,n),a=(m?l(m):null)?.comments??[],e=a.find(c=>c.id===r&&!c.deleted);return e?(e.text=S(o),e.updatedAt=new Date().toISOString(),u(t,n,{comments:a}),T(e)):null}function J(t,n,r){let o=i(t,n),s=(o?l(o):null)?.comments??[],a=s.findIndex(e=>e.id===r&&!e.deleted);return a===-1?!1:(s[a]={...s[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},u(t,n,{comments:s}),!0)}export{v as a,S as b,B as c,E as d,J as e};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{existsSync as l,readFileSync as L,writeFileSync as v,mkdirSync as f,readdirSync as p,unlinkSync as m,renameSync as y,openSync as B,statSync as _}from"fs";import{join as u,extname as T}from"path";import{randomBytes as U}from"crypto";var E=["backlog","todo","in-progress","review","done"];function A(e){let i=(e??"Medium").trim().toLowerCase();return i==="critical"?0:i==="high"?1:i==="low"?3:2}function $(e,i){let n=A(e.priority),r=A(i.priority);return n!==r?n-r:new Date(e.created).getTime()-new Date(i.created).getTime()}var d=".vibeflow",R="tasks",C="tasks/files",k="tasks/screenshots",ne="config.json";import{openSync as q,statSync as J,unlinkSync as O,mkdirSync as N,existsSync as H}from"fs";import{dirname as V,join as I}from"path";var F=new Map;function S(e,i){let n=I(e,d,"tasks",".locks");try{H(n)||N(n,{recursive:!0})}catch{}return I(n,`${i}.lock`)}function W(e,i,n){let r=Date.now()+i;for(;;)try{q(e,"wx");return}catch(o){if(o.code==="ENOENT"){try{N(V(e),{recursive:!0})}catch{}continue}if(o.code!=="EEXIST")throw o;try{let a=J(e);if(Date.now()-a.mtimeMs>n){try{O(e)}catch{}continue}}catch{continue}if(Date.now()>=r)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);if(r-Date.now()<=0)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);let s=Date.now()+Math.min(10,r-Date.now());for(;Date.now()<s;);}}function z(e){try{O(e)}catch{}}async function ae(e,i,n){let r=n?.timeoutMs??5e3,o=n?.staleMs??1e4,s=(F.get(e)??Promise.resolve()).then(async()=>{W(e,r,o);try{return await i()}finally{z(e)}});return F.set(e,s.catch(()=>{})),s}function X(){return U(15).toString("hex")}function h(e){return u(e,d,R)}function G(e){let i=u(e,d),n=u(i,"files"),r=u(i,C),o=u(i,"screenshots"),t=u(i,k);if(l(n)){f(r,{recursive:!0});for(let s of p(n)){let a=u(n,s),c=u(r,s);if(!l(c))try{y(a,c)}catch{}}}if(l(o)){f(t,{recursive:!0});for(let s of p(o)){let a=u(o,s),c=u(t,s);if(!l(c))try{y(a,c)}catch{}}}}function pe(e){G(e),f(h(e),{recursive:!0}),f(u(e,d,k),{recursive:!0})}function w(e){return e.slice(0,10)}function Y(e,i,n){let r=h(e);return n?u(r,w(n),`${i}.json`):u(r,`${i}.json`)}function j(e,i){let n=h(e);if(!l(n))return null;for(let r of p(n,{withFileTypes:!0}))if(r.isDirectory()){let o=u(n,r.name,`${i}.json`);if(l(o))return o}else if(r.name===`${i}.json`)return u(n,r.name);return null}function Q(e){return{...e,text:e.text??e.content??""}}function Z(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:E.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>Q(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function M(e,i){let n=u(h(e),w(i.created));f(n,{recursive:!0});let r=u(n,`${i.id}.json`),o=r+".tmp";v(o,JSON.stringify(i,null,2),"utf-8"),y(o,r)}function ee(e,i){let n=e+".tmp";v(n,JSON.stringify(i,null,2),"utf-8"),y(n,e)}function P(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function he(e,i){let n=(()=>{let o=(i.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),r={...i,title:P(i.title??"").trim(),description:P(i.description??"").trim(),priority:n,id:X(),created:new Date().toISOString(),comments:[],files:[]};return M(e,r),r}function g(e){try{let i=L(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:Z(n)}return null}catch{return null}}function K(e){let i=h(e);if(!l(i))return[];let n=[];for(let r of p(i,{withFileTypes:!0}))if(r.isDirectory()){let o=u(i,r.name);for(let t of p(o))if(T(t)===".json"){let s=u(o,t),a=g(s);a&&n.push({task:a,filePath:s})}}else if(T(r.name)===".json"){let o=u(i,r.name),t=g(o);t&&n.push({task:t,filePath:o})}return n}function ge(e){return K(e).map(({task:i})=>i)}function te(e){return K(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function ye(e,i,n){let r=S(e,i),o=null,t=Date.now()+5e3;for(;Date.now()<t;)try{B(r,"wx");break}catch(s){if(s.code!=="EEXIST")throw s;try{let c=_(r);if(Date.now()-c.mtimeMs>1e4){try{m(r)}catch{}continue}}catch{continue}let a=Date.now();for(;Date.now()-a<10&&Date.now()<t;);}try{let s=j(e,i),a=s?g(s):null;if(!a)return null;let c={...a,...n,updated:new Date().toISOString()};if(M(e,c),s&&s!==Y(e,i,c.created))try{m(s)}catch{}o=c}finally{try{m(r)}catch{}}return o}function ke(e,i){let n=j(e,i);return n?(m(n),!0):!1}function Se(e,i={}){let n=S(e,"claim"),r=null,o=Date.now()+5e3;for(;Date.now()<o;)try{B(n,"wx");break}catch(t){if(t.code!=="EEXIST")throw t;try{let a=_(n);if(Date.now()-a.mtimeMs>1e4){try{m(n)}catch{}continue}}catch{continue}let s=Date.now();for(;Date.now()-s<10&&Date.now()<o;);}try{let s=te(e).filter(a=>a.status==="todo");i.type&&(s=s.filter(a=>a.type===i.type)),i.user&&(s=s.filter(a=>a.author===i.user)),i.tag&&i.tag.length>0&&(s=s.filter(a=>a.tags&&i.tag.every(c=>a.tags.includes(c)))),s.sort($);for(let a of s){let c=g(a.filePath);if(!c||c.status!=="todo")continue;let x={status:"in-progress",updated:new Date().toISOString()};i.author&&(x.author=i.author);let D={...c,...x};ee(a.filePath,D),r=D;break}}finally{try{m(n)}catch{}}return r}function Te(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function ve(e,i,n,r,o){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let s of e.commits)t.push(` ${s.sha.slice(0,8)} ${s.timestamp} ${s.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let s of e.description.split(`
4
+ `))t.push(` ${s}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let s of n){let a=s.updatedAt?` (edited ${s.updatedAt})`:"";t.push(` [${s.author??"user"}] ${s.createdAt}${a}`);for(let c of s.text.split(`
5
+ `))t.push(` ${c}`)}}if(r.length>0){t.push(` linked files (${r.length}):`);for(let s of r){t.push(` - ${s.name} ${s.url}`);let a=s.linkedPath??u(o,".vibeflow","files",e.id,s.name);if(/\.(md|txt)$/i.test(s.name)&&s.size<1e5&&l(a))try{let c=L(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let b of c.split(`
6
+ `))t.push(` \u2502 ${b}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
7
+ `)}function we(e){let{autoCommit:i,autoPush:n,autoComment:r,createBranch:o}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),o?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),e.requireVerifyBeforeReview)if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)"),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"'),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}else{if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let c=["--set-status review"];i&&c.push('--commit-message "<one-line summary>"'),r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let c=["--set-status review"];r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`)}let a=o?"6":"5";t.push(` ${a}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.")}return r&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),r&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),o&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.requireVerifyBeforeReview&&t.push(" [setting] Verify gate ON: run vibeflow verify before setting status to review (skipped for tasks without URL/selector)."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
8
+ `)}function be(e){let i=h(e);if(!l(i))return 0;let n=0;for(let r of p(i,{withFileTypes:!0})){if(r.isDirectory()||T(r.name)!==".json")continue;let o=u(i,r.name),t=g(o);if(!t)continue;let s=u(i,w(t.created)),a=u(s,r.name);o!==a&&(f(s,{recursive:!0}),v(a,JSON.stringify(t,null,2),"utf-8"),m(o),n++)}return n}export{E as a,A as b,d as c,R as d,C as e,k as f,ne as g,S as h,ae as i,X as j,h as k,pe as l,Y as m,j as n,M as o,ee as p,P as q,he as r,g as s,ge as t,te as u,ye as v,ke as w,Se as x,Te as y,ve as z,we as A,be as B};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{d as y,f as S,o as R,s as T,v as x}from"./chunk-2CI62NHU.js";import{readdirSync as A,writeFileSync as z,readFileSync as O,unlinkSync as m,statSync as g,mkdirSync as $,existsSync as f}from"fs";import{join as l,basename as d}from"path";var h=".linked.json";function c(e,n){return l(e,y,S,n)}function b(e,n){$(c(e,n),{recursive:!0})}function L(e,n){let s=l(c(e,n),h);if(!f(s))return[];try{return JSON.parse(O(s,"utf-8"))}catch{return[]}}function F(e,n){let s=R(e,n),r=s?T(s):null;return!r?.files||r.files.length===0?[]:r.files}function P(e,n){return F(e,n)}function k(e,n,s){x(e,n,{files:s})}function p(e,n){let s=F(e,n),r=l(c(e,n),h);if(!f(r))return s;let i=L(e,n);if(i.length===0){try{m(r)}catch{}return s}let t=s.slice(),o=!1;for(let a of i)t.find(u=>u.linkedPath===a.path||u.name===a.name&&u.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&k(e,n,t);try{m(r)}catch{}return t}function v(e,n){let s=c(e,n),r=P(e,n),i=new Map;for(let t of r){if(t.linkedPath&&f(t.linkedPath)){let a=g(t.linkedPath);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=l(s,t.name);if(f(o)){let a=g(o);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(f(s))for(let t of A(s,{withFileTypes:!0})){if(!t.isFile()||t.name===h||i.has(t.name))continue;let o=l(s,t.name),a=g(o);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(i.values())}function U(e,n,s,r){let i=d(s);b(e,n),z(l(c(e,n),i),r);let t=p(e,n);return t.find(o=>o.name===i&&!o.linkedPath)||(t.push({name:i,addedAt:new Date().toISOString()}),k(e,n,t)),{name:i,size:r.length,url:`/api/tasks/${n}/files/${encodeURIComponent(i)}`}}function E(e,n,s){let r=d(s),i=p(e,n),t=i.findIndex(a=>a.name===r);if(t!==-1){let[a]=i.splice(t,1);if(k(e,n,i),a&&!a.linkedPath){let u=l(c(e,n),r);f(u)&&m(u)}return!0}let o=l(c(e,n),r);return f(o)?(m(o),!0):!1}function _(e,n,s){let r=d(s),i=P(e,n).find(o=>o.name===r&&o.linkedPath);if(i?.linkedPath&&f(i.linkedPath))return i.linkedPath;let t=l(c(e,n),r);return f(t)?t:null}function M(e,n){return v(e,n).length}async function B(e){let{listTasks:n}=await import("./tasks-OJTUAWAN.js"),s=n(e),r=0;for(let i of s)try{let t=P(e,i.id);p(e,i.id),F(e,i.id).length!==t.length&&r++}catch{}return r}export{c as a,b,P as c,v as d,U as e,E as f,_ as g,M as h,B as i};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as A,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as F}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let i=u(e,g),n=u(i,"files"),s=u(i,S),r=u(i,"screenshots"),t=u(i,v);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(s,o);if(!f(c))try{F(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{F(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,i,n){let s=k(e);return n?u(s,D(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=k(e);if(!f(n))return null;for(let s of h(n,{withFileTypes:!0}))if(s.isDirectory()){let r=u(n,s.name,`${i}.json`);if(f(r))return r}else if(s.name===`${i}.json`)return u(n,s.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,i){let n=u(k(e),D(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),r=s+".tmp";z(r,JSON.stringify(i,null,2),"utf-8"),F(r,s)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,i){let n=(()=>{let r=(i.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),s={...i,title:O(i.title??"").trim(),description:O(i.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,s),s}function y(e){try{let i=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let i=k(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let r=u(i,s.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(s.name)===".json"){let r=u(i,s.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:i})=>i)}function le(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function B(e,i,n){let s=T(e,i),r=s?y(s):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),s&&s!==U(e,i,t.created))try{w(s)}catch{}return t}function me(e,i){let n=T(e,i);return n?(w(n),!0):!1}function fe(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function de(e,i,n,s,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
4
+ `))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
5
+ `))t.push(` ${c}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let o of s){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
6
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
7
+ `)}function ge(e){let{autoCommit:i,autoPush:n,autoComment:s,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),i){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),s&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),s&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
8
+ `)}var $=".linked.json";function d(e,i){return m(e,g,S,i)}function Q(e,i){Y(d(e,i),{recursive:!0})}function X(e,i){let n=m(d(e,i),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function C(e,i,n){B(e,i,{files:n})}function x(e,i){let n=Z(e,i),s=m(d(e,i),$);if(!l(s))return n;let r=X(e,i);if(r.length===0){try{b(s)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,i,t);try{b(s)}catch{}return t}function ee(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&l(t.linkedPath)){let a=A(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,i,n,s){let r=R(n);Q(e,i),V(m(d(e,i),r),s);let t=x(e,i);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function xe(e,i,n){let s=R(n),r=x(e,i),t=r.findIndex(a=>a.name===s);if(t!==-1){let[a]=r.splice(t,1);if(C(e,i,r),a&&!a.linkedPath){let c=m(d(e,i),s);l(c)&&b(c)}return!0}let o=m(d(e,i),s);return l(o)?(b(o),!0):!1}function ve(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return l(t)?t:null}function Fe(e,i){return ee(e,i).length}export{g as a,P as b,S as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Fe as z};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{a as D,c as E,d as f,e as A,f as R,g as k}from"./chunk-XHZXHACL.js";import{existsSync as l,readFileSync as P,writeFileSync as v,mkdirSync as m,readdirSync as h,unlinkSync as d,renameSync as y,openSync as B,statSync as L}from"fs";import{join as u,extname as T}from"path";import{randomBytes as W}from"crypto";import{openSync as q,statSync as J,unlinkSync as F,mkdirSync as O,existsSync as K}from"fs";import{dirname as V,join as I}from"path";var C=new Map;function S(e,i){let n=I(e,f,"tasks",".locks");try{K(n)||O(n,{recursive:!0})}catch{}return I(n,`${i}.lock`)}function z(e,i,n){let r=Date.now()+i;for(;;)try{q(e,"wx");return}catch(o){if(o.code==="ENOENT"){try{O(V(e),{recursive:!0})}catch{}continue}if(o.code!=="EEXIST")throw o;try{let a=J(e);if(Date.now()-a.mtimeMs>n){try{F(e)}catch{}continue}}catch{continue}if(Date.now()>=r)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);if(r-Date.now()<=0)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);let s=Date.now()+Math.min(10,r-Date.now());for(;Date.now()<s;);}}function H(e){try{F(e)}catch{}}async function se(e,i,n){let r=n?.timeoutMs??5e3,o=n?.staleMs??1e4,s=(C.get(e)??Promise.resolve()).then(async()=>{z(e,r,o);try{return await i()}finally{H(e)}});return C.set(e,s.catch(()=>{})),s}function U(){return W(15).toString("hex")}function p(e){return u(e,f,A)}function X(e){let i=u(e,f),n=u(i,"files"),r=u(i,R),o=u(i,"screenshots"),t=u(i,k);if(l(n)){m(r,{recursive:!0});for(let s of h(n)){let a=u(n,s),c=u(r,s);if(!l(c))try{y(a,c)}catch{}}}if(l(o)){m(t,{recursive:!0});for(let s of h(o)){let a=u(o,s),c=u(t,s);if(!l(c))try{y(a,c)}catch{}}}}function de(e){X(e),m(p(e),{recursive:!0}),m(u(e,f,k),{recursive:!0})}function w(e){return e.slice(0,10)}function G(e,i,n){let r=p(e);return n?u(r,w(n),`${i}.json`):u(r,`${i}.json`)}function j(e,i){let n=p(e);if(!l(n))return null;for(let r of h(n,{withFileTypes:!0}))if(r.isDirectory()){let o=u(n,r.name,`${i}.json`);if(l(o))return o}else if(r.name===`${i}.json`)return u(n,r.name);return null}function Y(e){return{...e,text:e.text??e.content??""}}function Q(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:D.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>Y(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function M(e,i){let n=u(p(e),w(i.created));m(n,{recursive:!0});let r=u(n,`${i.id}.json`),o=r+".tmp";v(o,JSON.stringify(i,null,2),"utf-8"),y(o,r)}function Z(e,i){let n=e+".tmp";v(n,JSON.stringify(i,null,2),"utf-8"),y(n,e)}function N(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function fe(e,i){let n=(()=>{let o=(i.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),r={...i,title:N(i.title??"").trim(),description:N(i.description??"").trim(),priority:n,id:U(),created:new Date().toISOString(),comments:[],files:[]};return M(e,r),r}function g(e){try{let i=P(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:Q(n)}return null}catch{return null}}function _(e){let i=p(e);if(!l(i))return[];let n=[];for(let r of h(i,{withFileTypes:!0}))if(r.isDirectory()){let o=u(i,r.name);for(let t of h(o))if(T(t)===".json"){let s=u(o,t),a=g(s);a&&n.push({task:a,filePath:s})}}else if(T(r.name)===".json"){let o=u(i,r.name),t=g(o);t&&n.push({task:t,filePath:o})}return n}function me(e){return _(e).map(({task:i})=>i)}function ee(e){return _(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function he(e,i,n){let r=S(e,i),o=null,t=Date.now()+5e3;for(;Date.now()<t;)try{B(r,"wx");break}catch(s){if(s.code!=="EEXIST")throw s;try{let c=L(r);if(Date.now()-c.mtimeMs>1e4){try{d(r)}catch{}continue}}catch{continue}let a=Date.now();for(;Date.now()-a<10&&Date.now()<t;);}try{let s=j(e,i),a=s?g(s):null;if(!a)return null;let c={...a,...n,updated:new Date().toISOString()};if(M(e,c),s&&s!==G(e,i,c.created))try{d(s)}catch{}o=c}finally{try{d(r)}catch{}}return o}function pe(e,i){let n=j(e,i);return n?(d(n),!0):!1}function ge(e,i={}){let n=S(e,"claim"),r=null,o=Date.now()+5e3;for(;Date.now()<o;)try{B(n,"wx");break}catch(t){if(t.code!=="EEXIST")throw t;try{let a=L(n);if(Date.now()-a.mtimeMs>1e4){try{d(n)}catch{}continue}}catch{continue}let s=Date.now();for(;Date.now()-s<10&&Date.now()<o;);}try{let s=ee(e).filter(a=>a.status==="todo");i.type&&(s=s.filter(a=>a.type===i.type)),i.user&&(s=s.filter(a=>a.author===i.user)),i.tag&&i.tag.length>0&&(s=s.filter(a=>a.tags&&i.tag.every(c=>a.tags.includes(c)))),s.sort(E);for(let a of s){let c=g(a.filePath);if(!c||c.status!=="todo")continue;let x={status:"in-progress",updated:new Date().toISOString()};i.author&&(x.author=i.author);let $={...c,...x};Z(a.filePath,$),r=$;break}}finally{try{d(n)}catch{}}return r}function ye(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function ke(e,i,n,r,o){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let s of e.commits)t.push(` ${s.sha.slice(0,8)} ${s.timestamp} ${s.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let s of e.description.split(`
4
+ `))t.push(` ${s}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let s of n){let a=s.updatedAt?` (edited ${s.updatedAt})`:"";t.push(` [${s.author??"user"}] ${s.createdAt}${a}`);for(let c of s.text.split(`
5
+ `))t.push(` ${c}`)}}if(r.length>0){t.push(` linked files (${r.length}):`);for(let s of r){t.push(` - ${s.name} ${s.url}`);let a=s.linkedPath??u(o,".vibeflow","files",e.id,s.name);if(/\.(md|txt)$/i.test(s.name)&&s.size<1e5&&l(a))try{let c=P(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let b of c.split(`
6
+ `))t.push(` \u2502 ${b}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
7
+ `)}function Se(e){let{autoCommit:i,autoPush:n,autoComment:r,createBranch:o}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),o?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),e.requireVerifyBeforeReview)if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)"),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"'),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}else{if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let c=["--set-status review"];i&&c.push('--commit-message "<one-line summary>"'),r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let c=["--set-status review"];r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`)}let a=o?"6":"5";t.push(` ${a}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.")}return r&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),r&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),o&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.requireVerifyBeforeReview&&t.push(" [setting] Verify gate ON: run vibeflow verify before setting status to review (skipped for tasks without URL/selector)."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
8
+ `)}function Te(e){let i=p(e);if(!l(i))return 0;let n=0;for(let r of h(i,{withFileTypes:!0})){if(r.isDirectory()||T(r.name)!==".json")continue;let o=u(i,r.name),t=g(o);if(!t)continue;let s=u(i,w(t.created)),a=u(s,r.name);o!==a&&(m(s,{recursive:!0}),v(a,JSON.stringify(t,null,2),"utf-8"),d(o),n++)}return n}export{S as a,se as b,U as c,p as d,de as e,G as f,j as g,M as h,Z as i,N as j,fe as k,g as l,me as m,ee as n,he as o,pe as p,ge as q,ye as r,ke as s,Se as t,Te as u};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{a as q}from"./chunk-X4RGF6JJ.js";import{existsSync as l,readFileSync as L,writeFileSync as B,mkdirSync as f,readdirSync as p,unlinkSync as m,renameSync as S,openSync as _,statSync as j}from"fs";import{join as u,extname as T}from"path";import{randomBytes as U}from"crypto";var A=["backlog","todo","in-progress","review","done"];function E(e){let i=(e??"Medium").trim().toLowerCase();return i==="critical"?0:i==="high"?1:i==="low"?3:2}function $(e,i){let n=E(e.priority),r=E(i.priority);return n!==r?n-r:new Date(e.created).getTime()-new Date(i.created).getTime()}var d=".vibeflow",R="tasks",C="tasks/files",y="tasks/screenshots",te="config.json";import{openSync as H,statSync as J,unlinkSync as O,mkdirSync as P,existsSync as V}from"fs";import{join as I}from"path";var F=new Map;function k(e,i){let n=I(e,d,"tasks",".locks");try{V(n)||P(n,{recursive:!0})}catch{}return I(n,`${i}.lock`)}function W(e,i,n){let r=Date.now()+i,{dirname:o}=q("path");for(;;)try{H(e,"wx");return}catch(t){if(t.code==="ENOENT"){try{P(o(e),{recursive:!0})}catch{}continue}if(t.code!=="EEXIST")throw t;try{let c=J(e);if(Date.now()-c.mtimeMs>n){try{O(e)}catch{}continue}}catch{continue}if(Date.now()>=r)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);if(r-Date.now()<=0)throw new Error(`Failed to acquire lock ${e} within ${i}ms`);let a=Date.now()+Math.min(10,r-Date.now());for(;Date.now()<a;);}}function z(e){try{O(e)}catch{}}async function oe(e,i,n){let r=n?.timeoutMs??5e3,o=n?.staleMs??1e4,s=(F.get(e)??Promise.resolve()).then(async()=>{W(e,r,o);try{return await i()}finally{z(e)}});return F.set(e,s.catch(()=>{})),s}function X(){return U(15).toString("hex")}function h(e){return u(e,d,R)}function G(e){let i=u(e,d),n=u(i,"files"),r=u(i,C),o=u(i,"screenshots"),t=u(i,y);if(l(n)){f(r,{recursive:!0});for(let s of p(n)){let a=u(n,s),c=u(r,s);if(!l(c))try{S(a,c)}catch{}}}if(l(o)){f(t,{recursive:!0});for(let s of p(o)){let a=u(o,s),c=u(t,s);if(!l(c))try{S(a,c)}catch{}}}}function fe(e){G(e),f(h(e),{recursive:!0}),f(u(e,d,y),{recursive:!0})}function v(e){return e.slice(0,10)}function Y(e,i,n){let r=h(e);return n?u(r,v(n),`${i}.json`):u(r,`${i}.json`)}function M(e,i){let n=h(e);if(!l(n))return null;for(let r of p(n,{withFileTypes:!0}))if(r.isDirectory()){let o=u(n,r.name,`${i}.json`);if(l(o))return o}else if(r.name===`${i}.json`)return u(n,r.name);return null}function Q(e){return{...e,text:e.text??e.content??""}}function Z(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:A.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>Q(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function w(e,i){let n=u(h(e),v(i.created));f(n,{recursive:!0});let r=u(n,`${i.id}.json`),o=r+".tmp";B(o,JSON.stringify(i,null,2),"utf-8"),S(o,r)}function N(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function pe(e,i){let n=(()=>{let o=(i.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),r={...i,title:N(i.title??"").trim(),description:N(i.description??"").trim(),priority:n,id:X(),created:new Date().toISOString(),comments:[],files:[]};return w(e,r),r}function g(e){try{let i=L(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:Z(n)}return null}catch{return null}}function K(e){let i=h(e);if(!l(i))return[];let n=[];for(let r of p(i,{withFileTypes:!0}))if(r.isDirectory()){let o=u(i,r.name);for(let t of p(o))if(T(t)===".json"){let s=u(o,t),a=g(s);a&&n.push({task:a,filePath:s})}}else if(T(r.name)===".json"){let o=u(i,r.name),t=g(o);t&&n.push({task:t,filePath:o})}return n}function he(e){return K(e).map(({task:i})=>i)}function ee(e){return K(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function ge(e,i,n){let r=k(e,i),o=null,t=Date.now()+5e3;for(;Date.now()<t;)try{_(r,"wx");break}catch(s){if(s.code!=="EEXIST")throw s;try{let c=j(r);if(Date.now()-c.mtimeMs>1e4){try{m(r)}catch{}continue}}catch{continue}let a=Date.now();for(;Date.now()-a<10&&Date.now()<t;);}try{let s=M(e,i),a=s?g(s):null;if(!a)return null;let c={...a,...n,updated:new Date().toISOString()};if(w(e,c),s&&s!==Y(e,i,c.created))try{m(s)}catch{}o=c}finally{try{m(r)}catch{}}return o}function ye(e,i){let n=M(e,i);return n?(m(n),!0):!1}function ke(e,i={}){let n=k(e,"claim"),r=null,o=Date.now()+5e3;for(;Date.now()<o;)try{_(n,"wx");break}catch(t){if(t.code!=="EEXIST")throw t;try{let a=j(n);if(Date.now()-a.mtimeMs>1e4){try{m(n)}catch{}continue}}catch{continue}let s=Date.now();for(;Date.now()-s<10&&Date.now()<o;);}try{let s=ee(e).filter(a=>a.status==="todo");i.type&&(s=s.filter(a=>a.type===i.type)),i.user&&(s=s.filter(a=>a.author===i.user)),i.tag&&i.tag.length>0&&(s=s.filter(a=>a.tags&&i.tag.every(c=>a.tags.includes(c)))),s.sort($);for(let a of s){let c=g(a.filePath);if(!c||c.status!=="todo")continue;let x={status:"in-progress",updated:new Date().toISOString()};i.author&&(x.author=i.author);let D={...c,...x};w(e,D),r=D;break}}finally{try{m(n)}catch{}}return r}function Se(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function Te(e,i,n,r,o){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let s of e.commits)t.push(` ${s.sha.slice(0,8)} ${s.timestamp} ${s.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let s of e.description.split(`
4
+ `))t.push(` ${s}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let s of n){let a=s.updatedAt?` (edited ${s.updatedAt})`:"";t.push(` [${s.author??"user"}] ${s.createdAt}${a}`);for(let c of s.text.split(`
5
+ `))t.push(` ${c}`)}}if(r.length>0){t.push(` linked files (${r.length}):`);for(let s of r){t.push(` - ${s.name} ${s.url}`);let a=s.linkedPath??u(o,".vibeflow","files",e.id,s.name);if(/\.(md|txt)$/i.test(s.name)&&s.size<1e5&&l(a))try{let c=L(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let b of c.split(`
6
+ `))t.push(` \u2502 ${b}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
7
+ `)}function ve(e){let{autoCommit:i,autoPush:n,autoComment:r,createBranch:o}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),o?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),e.requireVerifyBeforeReview)if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)"),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"'),t.push(` ${o?"5":"4"}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.");let a=["--set-status review"];r&&a.push('--comment "<report>"'),t.push(` ${o?"6":"5"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}else{if(i){t.push(o?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let c=["--set-status review"];i&&c.push('--commit-message "<one-line summary>"'),r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(o?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let c=["--set-status review"];r&&c.push('--comment "<report>"'),t.push(` ${o?"5":"4"}. vibeflow tasks --edit <id> ${c.join(" ")}`)}let a=o?"6":"5";t.push(` ${a}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix.")}return r&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),r&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),o&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.requireVerifyBeforeReview&&t.push(" [setting] Verify gate ON: run vibeflow verify before setting status to review (skipped for tasks without URL/selector)."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
8
+ `)}function we(e){let i=h(e);if(!l(i))return 0;let n=0;for(let r of p(i,{withFileTypes:!0})){if(r.isDirectory()||T(r.name)!==".json")continue;let o=u(i,r.name),t=g(o);if(!t)continue;let s=u(i,v(t.created)),a=u(s,r.name);o!==a&&(f(s,{recursive:!0}),B(a,JSON.stringify(t,null,2),"utf-8"),m(o),n++)}return n}export{A as a,E as b,d as c,R as d,C as e,y as f,te as g,k as h,oe as i,X as j,h as k,fe as l,Y as m,M as n,w as o,N as p,pe as q,g as r,he as s,ee as t,ge as u,ye as v,ke as w,Se as x,Te as y,ve as z,we as A};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{d as y,f as S,o as R,s as T,v as x}from"./chunk-JAWQQLJC.js";import{readdirSync as A,writeFileSync as z,readFileSync as O,unlinkSync as m,statSync as g,mkdirSync as $,existsSync as f}from"fs";import{join as l,basename as d}from"path";var h=".linked.json";function c(e,n){return l(e,y,S,n)}function b(e,n){$(c(e,n),{recursive:!0})}function L(e,n){let s=l(c(e,n),h);if(!f(s))return[];try{return JSON.parse(O(s,"utf-8"))}catch{return[]}}function F(e,n){let s=R(e,n),r=s?T(s):null;return!r?.files||r.files.length===0?[]:r.files}function P(e,n){return F(e,n)}function k(e,n,s){x(e,n,{files:s})}function p(e,n){let s=F(e,n),r=l(c(e,n),h);if(!f(r))return s;let i=L(e,n);if(i.length===0){try{m(r)}catch{}return s}let t=s.slice(),o=!1;for(let a of i)t.find(u=>u.linkedPath===a.path||u.name===a.name&&u.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&k(e,n,t);try{m(r)}catch{}return t}function v(e,n){let s=c(e,n),r=P(e,n),i=new Map;for(let t of r){if(t.linkedPath&&f(t.linkedPath)){let a=g(t.linkedPath);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=l(s,t.name);if(f(o)){let a=g(o);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(f(s))for(let t of A(s,{withFileTypes:!0})){if(!t.isFile()||t.name===h||i.has(t.name))continue;let o=l(s,t.name),a=g(o);i.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${n}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(i.values())}function U(e,n,s,r){let i=d(s);b(e,n),z(l(c(e,n),i),r);let t=p(e,n);return t.find(o=>o.name===i&&!o.linkedPath)||(t.push({name:i,addedAt:new Date().toISOString()}),k(e,n,t)),{name:i,size:r.length,url:`/api/tasks/${n}/files/${encodeURIComponent(i)}`}}function E(e,n,s){let r=d(s),i=p(e,n),t=i.findIndex(a=>a.name===r);if(t!==-1){let[a]=i.splice(t,1);if(k(e,n,i),a&&!a.linkedPath){let u=l(c(e,n),r);f(u)&&m(u)}return!0}let o=l(c(e,n),r);return f(o)?(m(o),!0):!1}function _(e,n,s){let r=d(s),i=P(e,n).find(o=>o.name===r&&o.linkedPath);if(i?.linkedPath&&f(i.linkedPath))return i.linkedPath;let t=l(c(e,n),r);return f(t)?t:null}function M(e,n){return v(e,n).length}async function B(e){let{listTasks:n}=await import("./tasks-NSLXFEXZ.js"),s=n(e),r=0;for(let i of s)try{let t=P(e,i.id);p(e,i.id),F(e,i.id).length!==t.length&&r++}catch{}return r}export{c as a,b,P as c,v as d,U as e,E as f,_ as g,M as h,B as i};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{a as C,b as M}from"./chunk-KJ5LYG6A.js";import{a as _,b as W}from"./chunk-YMBPKWZ4.js";import{a as P}from"./chunk-BZDBSBRV.js";import{g as F,j as L}from"./chunk-BBIA4IIO.js";import{n as N}from"./chunk-Q7MEW67Z.js";import{d as T,e as j,g as B}from"./chunk-XHZXHACL.js";import m from"chalk";import{unlinkSync as K,readFileSync as de,existsSync as E}from"fs";import{resolve as pe,join as O}from"path";import A from"fs/promises";import Q from"os";import D from"path";var X=D.join(Q.homedir(),".vibeflow"),x=D.join(X,"token");async function R(){try{return(await A.readFile(x,"utf8")).trim()||null}catch{return null}}async function z(t){await A.mkdir(D.dirname(x),{recursive:!0}),await A.writeFile(x,t,{mode:384})}async function we(){try{await A.unlink(x)}catch{}}import s from"chalk";import Z from"open";import H from"readline";import ee from"@inquirer/select";import{existsSync as te,readdirSync as q,readFileSync as oe}from"fs";import{join as v,resolve as re}from"path";var se="https://app.vibeflow.tools",ne=300*1e3;function G(){return process.env.VIBEFLOW_API_URL??se}async function ie(t){return new Promise(n=>setTimeout(n,t))}async function ae(t){return t.length===1?(console.log(s.dim(` Using board: ${t[0].icon??""} ${t[0].name}`)),t[0]):await ee({message:"Select a board to use:",choices:t.map(o=>({name:`${o.icon??""} ${o.name}`,value:o}))})}async function J(t,n){try{let o=await fetch(`${t}/api/cli/settings`,{headers:{Authorization:`Bearer ${n}`}});if(!o.ok)return;let i=await o.json();i.settings&&Object.keys(i.settings).length>0&&W({...i.settings,_settingsRefreshedAt:Date.now()})}catch{}}async function Ce(){try{let t=await R();if(!t)return;let o=_()._settingsRefreshedAt??0;if(Date.now()-o<ne)return;let i=G();J(i,t)}catch{}}async function le(t,n){try{let[o,i]=await Promise.all([fetch(`${t}/api/cli/workspaces`,{headers:{Authorization:`Bearer ${n}`}}),fetch(`${t}/api/cli/profile`,{headers:{Authorization:`Bearer ${n}`}})]);if(!o.ok)return;let a=await o.json();if(!a.workspaces?.length){console.log(s.yellow(" No boards found. Create a board in the web app first."));return}let l=i.ok?await i.json():null,d=await ae(a.workspaces);await M({...d,email:l?.email??null}),console.log(s.green(` Board set: ${d.icon??""} ${d.name}`)),console.log(s.dim(` Open at: ${d.url}`))}catch{}}async function ce(t,n,o,i){let a=v(t,T,j);if(!te(a))return;let l=[];try{for(let e of q(a,{withFileTypes:!0}))if(e.isDirectory()){let p=v(a,e.name);for(let k of q(p).filter(c=>c.endsWith(".json")))l.push(v(p,k))}else e.isFile()&&e.name.endsWith(".json")&&l.push(v(a,e.name))}catch{return}if(l.length===0)return;let d=l.flatMap(e=>{try{return[JSON.parse(oe(e,"utf-8"))]}catch{return[]}}),y=new Set;try{let e=await fetch(`${n}/api/cli/tasks?boardId=${i.id}`,{headers:{Authorization:`Bearer ${o}`}}).catch(()=>null);if(e?.ok){let p=await e.json();y=new Set((p.tasks??[]).flatMap(k=>[k.id,...k.cliId?[k.cliId]:[]]))}}catch{}let g=d.filter(e=>!y.has(e.id));if(g.length===0)return;console.log(),console.log(s.bold(` ${g.length} local task${g.length!==1?"s are":" is"} not yet synced to the board:`));let h=g.slice(0,10);for(let e of h){let p=e.status?s.dim(` [${e.status}]`):"";console.log(s.dim(` \u2022 ${e.title??e.id}${p}`))}return g.length>10&&console.log(s.dim(` \u2026 and ${g.length-10} more`)),new Promise(e=>{let p=H.createInterface({input:process.stdin,output:process.stdout});p.question(s.cyan(`
3
+ Push them to your board now? [Y/n]: `),async k=>{if(p.close(),k.trim().toLowerCase()==="n"){console.log(s.dim(" Skipped. You can push later with: vibeflow push")),e();return}let c=H.createInterface({input:process.stdin,output:process.stdout});c.question(s.cyan(" Delete local task files after push? [y/N]: "),async $=>{c.close();let b=$.trim().toLowerCase()!=="y";try{let f=await fetch(`${n}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({boardId:i.id,tasks:g,keepLocalFiles:b})}),u={};try{u=await f.json()}catch{}f.ok?(console.log(s.green(` \u2713 Pushed ${u.imported??0} task${(u.imported??0)!==1?"s":""} to ${i.name}`)),(u.skipped??0)>0&&console.log(s.dim(` (${u.skipped} already existed and were skipped)`))):console.log(s.red(` Push failed: ${u.error??`HTTP ${f.status}`}`))}catch(f){console.log(s.red(` Push failed: ${f instanceof Error?f.message:"Network error"}`))}e()})})})}async function V(t=re(".")){let n=G();console.log(s.cyan(" Initiating device login flow..."));let o;try{o=await fetch(`${n}/api/cli/auth/device-init`,{method:"POST",headers:{"Content-Type":"application/json"}})}catch(h){console.error(s.red(` Failed to connect to login server: ${h instanceof Error?h.message:"Network error"}`)),process.exitCode=P.AUTH;return}if(!o.ok){console.error(s.red(` Failed to initiate login: ${o.status} ${o.statusText}`)),process.exitCode=P.AUTH;return}let{deviceCode:i,userCode:a,verificationUrl:l,expiresIn:d}=await o.json();console.log(),console.log(s.bold(" Open this URL in your browser to authorize:")),console.log(s.underline(` ${l}`)),console.log();try{await Z(l),console.log(s.dim(" (Browser opened automatically)"))}catch{}let y=Date.now()+d*1e3,g=3e3;for(;Date.now()<y;){await ie(g);let h=null;try{h=await fetch(`${n}/api/cli/auth/device-poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:i})})}catch{console.error(s.red(" Poll request failed (network error). Retrying..."));continue}if(!h.ok){console.error(s.red(" Poll request failed. Retrying..."));continue}let e=await h.json();if("token"in e){await z(e.token),console.log(),console.log(s.green(" Logged in successfully. Now operating in SaaS mode.")),await Promise.all([le(n,e.token),J(n,e.token)]);let{readWorkspace:p}=await import("./workspace-KGOQ67YV.js"),k=await p();k&&await ce(t,n,e.token,k);return}if("expired"in e){console.error(s.red(" Device code expired. Please try again.")),process.exitCode=P.AUTH;return}process.stdout.write(s.dim("."))}console.error(s.red(`
4
+ Login timed out. Please try again.`)),process.exitCode=P.AUTH}var fe="https://app.vibeflow.tools";function ue(){return process.env.VIBEFLOW_API_URL??fe}function me(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function Y(t,n,o=24){let i=Math.round(t/n*o);return`[${"\u2588".repeat(i)+"\u2591".repeat(o-i)}]`}async function ge(t,n,o,i){let a=[];for(let{localId:c,remoteId:$}of i){let b=L(o,c);for(let f of b){let u=f.linkedPath??O(F(o,c),f.name);E(u)&&a.push({remoteId:$,name:f.name,filePath:u,size:f.size})}}if(a.length===0)return{uploaded:0,failed:0,failedFiles:[]};let l=a.length,d=a.reduce((c,$)=>c+$.size,0);console.log(m.cyan(`
5
+ Uploading ${l} file(s) (${me(d)})...`));let y=0,g=0,h=0,e=Date.now(),p=[];for(let c of a){let $=Math.round(y/l*100),b=Y(y,l),f=(Date.now()-e)/1e3,u=h/Math.max(f,.01),r=d-h,w=u>0?Math.ceil(r/u):0,I=w>60?`${Math.ceil(w/60)}m`:`${w}s`;process.stdout.write(`\r ${b} ${$}% ${c.name.slice(0,28)} ETA: ${I} `);try{let S=de(c.filePath),U=await fetch(`${t}/api/tasks/${encodeURIComponent(c.remoteId)}/files`,{method:"POST",headers:{Authorization:`Bearer ${n}`,"Content-Type":"application/octet-stream","x-filename":encodeURIComponent(c.name)},body:S});U.ok?(y++,h+=c.size):(g++,p.push({name:c.name,reason:`HTTP ${U.status}`}))}catch(S){g++,p.push({name:c.name,reason:S instanceof Error?S.message:String(S)})}}let k=Y(l,l);return process.stdout.write(`\r ${k} 100% Done${" ".repeat(40)}
6
+ `),{uploaded:y,failed:g,failedFiles:p}}async function He(t,n){let o=pe(t),i=await R();if(!i&&(console.log(m.yellow(" Not logged in. Starting login flow...")),await V(),i=await R(),!i)){console.error(m.red(" Login failed. Please run `vibeflow login` and try again.")),process.exitCode=P.AUTH;return}let a=N(o);if(a.length===0)return console.log(m.dim(" No local tasks found. Nothing to push.")),{dryRun:!!n.dryRun,tasks:0,files:0,steps:["No tasks"]};let l=0;for(let r of a){let w=L(o,r.id);l+=w.length}let d=n.workspace;if(!d){let r=await C();r&&(d=r.id)}let y=d?(await C().catch(()=>null))?.name??d:"(no board selected)";if(n.dryRun)return console.log(m.cyan(` Dry run: ${a.length} task(s), ${l} file(s), board: ${y}`)),{dryRun:!0,tasks:a.length,files:l,board:y,steps:["Dry run: no changes made"]};console.log(m.cyan(` Found ${a.length} local task(s). Pushing to SaaS...`));let g=ue(),h={tasks:a};d&&(h.workspaceId=d);let e;try{let r=await fetch(`${g}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${i}`},body:JSON.stringify(h)});if(!r.ok){let w=await r.json().catch(()=>({}));console.error(m.red(` Import failed: ${r.status} ${w.error??r.statusText}`)),process.exitCode=P.GENERAL;return}e=await r.json()}catch(r){let w=r instanceof Error?r.message:String(r);console.error(m.red(` Network error: ${w}`)),process.exitCode=P.GENERAL;return}console.log(m.green(` \u2713 Pushed ${e.imported} task(s) to SaaS`)),e.skipped&&e.skipped>0&&console.log(m.dim(` Skipped ${e.skipped} already-imported task(s).`)),console.log(m.dim(` Board: ${y}`));let p=e.idMap??{},k=a.filter(r=>r.id&&p[r.id]).map(r=>({localId:r.id,remoteId:p[r.id]})),{uploaded:c,failed:$,failedFiles:b}=await ge(g,i,o,k);if(c>0&&console.log(m.green(` \u2713 Uploaded ${c} file(s) to storage`)),$>0){console.log(m.yellow(` \u26A0 ${$} file(s) failed to upload`));for(let r of b)console.log(m.dim(` - ${r.name}: ${r.reason}`))}if(n.keepLocalFiles){console.log(m.dim(" Local task files kept (--keep-local-files)."));return}let f=0,u=0;for(let r of a){try{K(r.filePath),f++}catch{}try{let w=F(o,r.id);if(E(w)){let{rmSync:I}=await import("fs");I(w,{recursive:!0,force:!0}),u++}}catch{}try{let w=O(o,T,B),I=O(w,`${r.id}.png`);E(I)&&(K(I),u++)}catch{}}return console.log(m.dim(` Deleted ${f} local task file(s).`)),u>0&&console.log(m.dim(` Cleaned ${u} orphaned asset dir(s).`)),{dryRun:!1,tasks:f,files:l,board:y,steps:["Push completed"]}}export{R as a,we as b,Ce as c,V as d,me as e,Y as f,He as g};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{i as d,j as f,n as S,o as c,p as g,q as p,s as u}from"./chunk-O4LGEPMQ.js";import{mkdirSync as w,writeFileSync as O,renameSync as F}from"fs";import{dirname as b}from"path";import{randomBytes as z}from"crypto";function P(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function B(t,n){let r=c(t,n);return((r?u(r):null)?.comments??[]).filter(e=>!e.deleted).map(P)}function x(t){return p(t)}async function E(t,n,r,i,e,o,m){i=x(i);let a=d(t,n);return f(a,()=>{let s=c(t,n),l=s?u(s):null,y=l?.comments??[],C={id:z(8).toString("hex"),author:r,text:i,...e&&e.length>0?{files:e}:{},...o&&o!=="comment"?{type:o}:{},createdAt:new Date().toISOString(),source:m??"cli"},T=[...y,C];if(l)g(t,{...l,comments:T});else{let k=S(t,n,new Date().toISOString());w(b(k),{recursive:!0});let h=k+".tmp";O(h,JSON.stringify({id:n,comments:T},null,2),"utf-8"),F(h,k)}return C})}async function N(t,n,r,i){let e=d(t,n);return f(e,()=>{let o=c(t,n),m=o?u(o):null,a=m?.comments??[],s=a.find(l=>l.id===r&&!l.deleted);return s?(s.text=x(i),s.updatedAt=new Date().toISOString(),m&&g(t,{...m,comments:a}),P(s)):null})}async function G(t,n,r){let i=d(t,n);return f(i,()=>{let e=c(t,n),o=e?u(e):null,m=o?.comments??[],a=m.findIndex(s=>s.id===r&&!s.deleted);return a===-1?!1:(m[a]={...m[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},o&&g(t,{...o,comments:m}),!0)})}export{B as a,x as b,E as c,N as d,G as e};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{h as d,i as f,m as S,n as c,o as g,p,r as u}from"./chunk-QJMBWTAZ.js";import{mkdirSync as w,writeFileSync as O,renameSync as F}from"fs";import{dirname as b}from"path";import{randomBytes as z}from"crypto";function P(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function B(t,n){let r=c(t,n);return((r?u(r):null)?.comments??[]).filter(e=>!e.deleted).map(P)}function x(t){return p(t)}async function E(t,n,r,i,e,o,m){i=x(i);let a=d(t,n);return f(a,()=>{let s=c(t,n),l=s?u(s):null,y=l?.comments??[],C={id:z(8).toString("hex"),author:r,text:i,...e&&e.length>0?{files:e}:{},...o&&o!=="comment"?{type:o}:{},createdAt:new Date().toISOString(),source:m??"cli"},T=[...y,C];if(l)g(t,{...l,comments:T});else{let k=S(t,n,new Date().toISOString());w(b(k),{recursive:!0});let h=k+".tmp";O(h,JSON.stringify({id:n,comments:T},null,2),"utf-8"),F(h,k)}return C})}async function N(t,n,r,i){let e=d(t,n);return f(e,()=>{let o=c(t,n),m=o?u(o):null,a=m?.comments??[],s=a.find(l=>l.id===r&&!l.deleted);return s?(s.text=x(i),s.updatedAt=new Date().toISOString(),m&&g(t,{...m,comments:a}),P(s)):null})}async function G(t,n,r){let i=d(t,n);return f(i,()=>{let e=c(t,n),o=e?u(e):null,m=o?.comments??[],a=m.findIndex(s=>s.id===r&&!s.deleted);return a===-1?!1:(m[a]={...m[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},o&&g(t,{...o,comments:m}),!0)})}export{B as a,x as b,E as c,N as d,G as e};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as A,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as F}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let i=u(e,g),n=u(i,"files"),s=u(i,S),r=u(i,"screenshots"),t=u(i,v);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(s,o);if(!f(c))try{F(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{F(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,i,n){let s=k(e);return n?u(s,D(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=k(e);if(!f(n))return null;for(let s of h(n,{withFileTypes:!0}))if(s.isDirectory()){let r=u(n,s.name,`${i}.json`);if(f(r))return r}else if(s.name===`${i}.json`)return u(n,s.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,i){let n=u(k(e),D(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),r=s+".tmp";z(r,JSON.stringify(i,null,2),"utf-8"),F(r,s)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,i){let n=(()=>{let r=(i.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),s={...i,title:O(i.title??"").trim(),description:O(i.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,s),s}function y(e){try{let i=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let i=k(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let r=u(i,s.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(s.name)===".json"){let r=u(i,s.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:i})=>i)}function le(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function B(e,i,n){let s=T(e,i),r=s?y(s):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),s&&s!==U(e,i,t.created))try{w(s)}catch{}return t}function me(e,i){let n=T(e,i);return n?(w(n),!0):!1}function fe(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function de(e,i,n,s,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
4
+ `))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
5
+ `))t.push(` ${c}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let o of s){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
6
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
7
+ `)}function ge(e){let{autoCommit:i,autoPush:n,autoComment:s,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),i){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),s&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),s&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
8
+ `)}var $=".linked.json";function d(e,i){return m(e,g,S,i)}function Q(e,i){Y(d(e,i),{recursive:!0})}function X(e,i){let n=m(d(e,i),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function C(e,i,n){B(e,i,{files:n})}function x(e,i){let n=Z(e,i),s=m(d(e,i),$);if(!l(s))return n;let r=X(e,i);if(r.length===0){try{b(s)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,i,t);try{b(s)}catch{}return t}function ee(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&l(t.linkedPath)){let a=A(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,i,n,s){let r=R(n);Q(e,i),V(m(d(e,i),r),s);let t=x(e,i);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function xe(e,i,n){let s=R(n),r=x(e,i),t=r.findIndex(a=>a.name===s);if(t!==-1){let[a]=r.splice(t,1);if(C(e,i,r),a&&!a.linkedPath){let c=m(d(e,i),s);l(c)&&b(c)}return!0}let o=m(d(e,i),s);return l(o)?(b(o),!0):!1}function ve(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return l(t)?t:null}function Fe(e,i){return ee(e,i).length}export{g as a,P as b,v as c,te as d,M as e,ae as f,U as g,T as h,O as i,ue as j,y as k,ce as l,le as m,B as n,me as o,fe as p,de as q,ge as r,d as s,Q as t,ee as u,be as v,xe as w,ve as x,Fe as y};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{a as C,b as M}from"./chunk-KJ5LYG6A.js";import{a as _,b as W}from"./chunk-YMBPKWZ4.js";import{a as P}from"./chunk-BZDBSBRV.js";import{g as F,j as L}from"./chunk-BBIA4IIO.js";import{n as N}from"./chunk-Q7MEW67Z.js";import{d as T,e as j,g as B}from"./chunk-XHZXHACL.js";import u from"chalk";import{unlinkSync as K,readFileSync as de,existsSync as E}from"fs";import{resolve as pe,join as O}from"path";import A from"fs/promises";import Q from"os";import D from"path";var X=D.join(Q.homedir(),".vibeflow"),x=D.join(X,"token");async function R(){try{return(await A.readFile(x,"utf8")).trim()||null}catch{return null}}async function z(t){await A.mkdir(D.dirname(x),{recursive:!0}),await A.writeFile(x,t,{mode:384})}async function we(){try{await A.unlink(x)}catch{}}import n from"chalk";import Z from"open";import H from"readline";import ee from"@inquirer/select";import{existsSync as te,readdirSync as q,readFileSync as oe}from"fs";import{join as v,resolve as re}from"path";var se="https://app.vibeflow.tools",ne=300*1e3;function G(){return process.env.VIBEFLOW_API_URL??se}async function ie(t){return new Promise(i=>setTimeout(i,t))}async function ae(t){return t.length===1?(console.log(n.dim(` Using board: ${t[0].icon??""} ${t[0].name}`)),t[0]):await ee({message:"Select a board to use:",choices:t.map(o=>({name:`${o.icon??""} ${o.name}`,value:o}))})}async function J(t,i){try{let o=await fetch(`${t}/api/cli/settings`,{headers:{Authorization:`Bearer ${i}`}});if(!o.ok)return;let s=await o.json();s.settings&&Object.keys(s.settings).length>0&&W({...s.settings,_settingsRefreshedAt:Date.now()})}catch{}}async function Ce(){try{let t=await R();if(!t)return;let o=_()._settingsRefreshedAt??0;if(Date.now()-o<ne)return;let s=G();J(s,t)}catch{}}async function le(t,i){try{let[o,s]=await Promise.all([fetch(`${t}/api/cli/workspaces`,{headers:{Authorization:`Bearer ${i}`}}),fetch(`${t}/api/cli/profile`,{headers:{Authorization:`Bearer ${i}`}})]);if(!o.ok)return;let l=await o.json();if(!l.workspaces?.length){console.log(n.yellow(" No boards found. Create a board in the web app first."));return}let a=s.ok?await s.json():null,m=await ae(l.workspaces);await M({...m,email:a?.email??null}),console.log(n.green(` Board set: ${m.icon??""} ${m.name}`)),console.log(n.dim(` Open at: ${m.url}`))}catch{}}async function ce(t,i,o,s){let l=v(t,T,j);if(!te(l))return;let a=[];try{for(let e of q(l,{withFileTypes:!0}))if(e.isDirectory()){let d=v(l,e.name);for(let k of q(d).filter(c=>c.endsWith(".json")))a.push(v(d,k))}else e.isFile()&&e.name.endsWith(".json")&&a.push(v(l,e.name))}catch{return}if(a.length===0)return;let m=a.flatMap(e=>{try{return[JSON.parse(oe(e,"utf-8"))]}catch{return[]}}),h=new Set;try{let e=await fetch(`${i}/api/cli/tasks?boardId=${s.id}`,{headers:{Authorization:`Bearer ${o}`}}).catch(()=>null);if(e?.ok){let d=await e.json();h=new Set((d.tasks??[]).flatMap(k=>[k.id,...k.cliId?[k.cliId]:[]]))}}catch{}let g=m.filter(e=>!h.has(e.id));if(g.length===0)return;console.log(),console.log(n.bold(` ${g.length} local task${g.length!==1?"s are":" is"} not yet synced to the board:`));let y=g.slice(0,10);for(let e of y){let d=e.status?n.dim(` [${e.status}]`):"";console.log(n.dim(` \u2022 ${e.title??e.id}${d}`))}return g.length>10&&console.log(n.dim(` \u2026 and ${g.length-10} more`)),new Promise(e=>{let d=H.createInterface({input:process.stdin,output:process.stdout});d.question(n.cyan(`
3
+ Push them to your board now? [Y/n]: `),async k=>{if(d.close(),k.trim().toLowerCase()==="n"){console.log(n.dim(" Skipped. You can push later with: vibeflow push")),e();return}let c=H.createInterface({input:process.stdin,output:process.stdout});c.question(n.cyan(" Delete local task files after push? [y/N]: "),async $=>{c.close();let b=$.trim().toLowerCase()!=="y";try{let p=await fetch(`${i}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({boardId:s.id,tasks:g,keepLocalFiles:b})}),f={};try{f=await p.json()}catch{}p.ok?(console.log(n.green(` \u2713 Pushed ${f.imported??0} task${(f.imported??0)!==1?"s":""} to ${s.name}`)),(f.skipped??0)>0&&console.log(n.dim(` (${f.skipped} already existed and were skipped)`))):console.log(n.red(` Push failed: ${f.error??`HTTP ${p.status}`}`))}catch(p){console.log(n.red(` Push failed: ${p instanceof Error?p.message:"Network error"}`))}e()})})})}async function V(t=re(".")){let i=G();console.log(n.cyan(" Initiating device login flow..."));let o;try{o=await fetch(`${i}/api/cli/auth/device-init`,{method:"POST",headers:{"Content-Type":"application/json"}})}catch(y){console.error(n.red(` Failed to connect to login server: ${y instanceof Error?y.message:"Network error"}`)),process.exitCode=P.AUTH;return}if(!o.ok){console.error(n.red(` Failed to initiate login: ${o.status} ${o.statusText}`)),process.exitCode=P.AUTH;return}let{deviceCode:s,userCode:l,verificationUrl:a,expiresIn:m}=await o.json();console.log(),console.log(n.bold(" Open this URL in your browser to authorize:")),console.log(n.underline(` ${a}`)),console.log();try{await Z(a),console.log(n.dim(" (Browser opened automatically)"))}catch{}let h=Date.now()+m*1e3,g=3e3;for(;Date.now()<h;){await ie(g);let y=null;try{y=await fetch(`${i}/api/cli/auth/device-poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:s})})}catch{console.error(n.red(" Poll request failed (network error). Retrying..."));continue}if(!y.ok){console.error(n.red(" Poll request failed. Retrying..."));continue}let e=await y.json();if("token"in e){await z(e.token),console.log(),console.log(n.green(" Logged in successfully. Now operating in SaaS mode.")),await Promise.all([le(i,e.token),J(i,e.token)]);let{readWorkspace:d}=await import("./workspace-KGOQ67YV.js"),k=await d();k&&await ce(t,i,e.token,k);return}if("expired"in e){console.error(n.red(" Device code expired. Please try again.")),process.exitCode=P.AUTH;return}process.stdout.write(n.dim("."))}console.error(n.red(`
4
+ Login timed out. Please try again.`)),process.exitCode=P.AUTH}var fe="https://app.vibeflow.tools";function ue(){return process.env.VIBEFLOW_API_URL??fe}function me(t){return t<1024?`${t} B`:t<1024*1024?`${(t/1024).toFixed(1)} KB`:`${(t/(1024*1024)).toFixed(1)} MB`}function Y(t,i,o=24){let s=Math.round(t/i*o);return`[${"\u2588".repeat(s)+"\u2591".repeat(o-s)}]`}async function ge(t,i,o,s){let l=[];for(let{localId:c,remoteId:$}of s){let b=L(o,c);for(let p of b){let f=p.linkedPath??O(F(o,c),p.name);E(f)&&l.push({remoteId:$,name:p.name,filePath:f,size:p.size})}}if(l.length===0)return{uploaded:0,failed:0,failedFiles:[]};let a=l.length,m=l.reduce((c,$)=>c+$.size,0);console.log(u.cyan(`
5
+ Uploading ${a} file(s) (${me(m)})...`));let h=0,g=0,y=0,e=Date.now(),d=[];for(let c of l){let $=Math.round(h/a*100),b=Y(h,a),p=(Date.now()-e)/1e3,f=y/Math.max(p,.01),r=m-y,w=f>0?Math.ceil(r/f):0,I=w>60?`${Math.ceil(w/60)}m`:`${w}s`;process.stdout.write(`\r ${b} ${$}% ${c.name.slice(0,28)} ETA: ${I} `);try{let S=de(c.filePath),U=await fetch(`${t}/api/tasks/${encodeURIComponent(c.remoteId)}/files`,{method:"POST",headers:{Authorization:`Bearer ${i}`,"Content-Type":"application/octet-stream","x-filename":encodeURIComponent(c.name)},body:S});U.ok?(h++,y+=c.size):(g++,d.push({name:c.name,reason:`HTTP ${U.status}`}))}catch(S){g++,d.push({name:c.name,reason:S instanceof Error?S.message:String(S)})}}let k=Y(a,a);return process.stdout.write(`\r ${k} 100% Done${" ".repeat(40)}
6
+ `),{uploaded:h,failed:g,failedFiles:d}}async function He(t,i){let o=pe(t),s=N(o);if(s.length===0)return console.log(u.dim(" No local tasks found. Nothing to push.")),{dryRun:!!i.dryRun,tasks:0,files:0,steps:["No tasks"]};let l=0;for(let r of s){let w=L(o,r.id);l+=w.length}let a=i.workspace;if(!a){let r=await C().catch(()=>null);r&&(a=r.id)}let m=a?(await C().catch(()=>null))?.name??a:"(no board selected)";if(i.dryRun)return console.log(u.cyan(` Dry run: ${s.length} task(s), ${l} file(s), board: ${m}`)),{dryRun:!0,tasks:s.length,files:l,board:m,steps:["Dry run: no changes made"]};let h=await R();if(!h&&(console.log(u.yellow(" Not logged in. Starting login flow...")),await V(),h=await R(),!h)){console.error(u.red(" Login failed. Please run `vibeflow login` and try again.")),process.exitCode=P.AUTH;return}console.log(u.cyan(` Found ${s.length} local task(s). Pushing to SaaS...`));let g=ue(),y={tasks:s};a&&(y.workspaceId=a);let e;try{let r=await fetch(`${g}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${h}`},body:JSON.stringify(y)});if(!r.ok){let w=await r.json().catch(()=>({}));console.error(u.red(` Import failed: ${r.status} ${w.error??r.statusText}`)),process.exitCode=P.GENERAL;return}e=await r.json()}catch(r){let w=r instanceof Error?r.message:String(r);console.error(u.red(` Network error: ${w}`)),process.exitCode=P.GENERAL;return}console.log(u.green(` \u2713 Pushed ${e.imported} task(s) to SaaS`)),e.skipped&&e.skipped>0&&console.log(u.dim(` Skipped ${e.skipped} already-imported task(s).`)),console.log(u.dim(` Board: ${m}`));let d=e.idMap??{},k=s.filter(r=>r.id&&d[r.id]).map(r=>({localId:r.id,remoteId:d[r.id]})),{uploaded:c,failed:$,failedFiles:b}=await ge(g,h,o,k);if(c>0&&console.log(u.green(` \u2713 Uploaded ${c} file(s) to storage`)),$>0){console.log(u.yellow(` \u26A0 ${$} file(s) failed to upload`));for(let r of b)console.log(u.dim(` - ${r.name}: ${r.reason}`))}if(i.keepLocalFiles){console.log(u.dim(" Local task files kept (--keep-local-files)."));return}let p=0,f=0;for(let r of s){try{K(r.filePath),p++}catch{}try{let w=F(o,r.id);if(E(w)){let{rmSync:I}=await import("fs");I(w,{recursive:!0,force:!0}),f++}}catch{}try{let w=O(o,T,B),I=O(w,`${r.id}.png`);E(I)&&(K(I),f++)}catch{}}return console.log(u.dim(` Deleted ${p} local task file(s).`)),f>0&&console.log(u.dim(` Cleaned ${f} orphaned asset dir(s).`)),{dryRun:!1,tasks:p,files:l,board:m,steps:["Push completed"]}}export{R as a,we as b,Ce as c,V as d,me as e,Y as f,He as g};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{i as d,j as f,n as S,o as c,p as g,q as p,s as u}from"./chunk-JAWQQLJC.js";import{mkdirSync as w,writeFileSync as O,renameSync as F}from"fs";import{dirname as b}from"path";import{randomBytes as z}from"crypto";function P(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function B(t,n){let r=c(t,n);return((r?u(r):null)?.comments??[]).filter(e=>!e.deleted).map(P)}function x(t){return p(t)}async function E(t,n,r,i,e,o,m){i=x(i);let a=d(t,n);return f(a,()=>{let s=c(t,n),l=s?u(s):null,y=l?.comments??[],C={id:z(8).toString("hex"),author:r,text:i,...e&&e.length>0?{files:e}:{},...o&&o!=="comment"?{type:o}:{},createdAt:new Date().toISOString(),source:m??"cli"},T=[...y,C];if(l)g(t,{...l,comments:T});else{let k=S(t,n,new Date().toISOString());w(b(k),{recursive:!0});let h=k+".tmp";O(h,JSON.stringify({id:n,comments:T},null,2),"utf-8"),F(h,k)}return C})}async function N(t,n,r,i){let e=d(t,n);return f(e,()=>{let o=c(t,n),m=o?u(o):null,a=m?.comments??[],s=a.find(l=>l.id===r&&!l.deleted);return s?(s.text=x(i),s.updatedAt=new Date().toISOString(),m&&g(t,{...m,comments:a}),P(s)):null})}async function G(t,n,r){let i=d(t,n);return f(i,()=>{let e=c(t,n),o=e?u(e):null,m=o?.comments??[],a=m.findIndex(s=>s.id===r&&!s.deleted);return a===-1?!1:(m[a]={...m[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},o&&g(t,{...o,comments:m}),!0)})}export{B as a,x as b,E as c,N as d,G as e};
@@ -0,0 +1,10 @@
1
+ #!/usr/bin/env node
2
+ import{c as st}from"./chunk-WZ2QQDYW.js";import{a as U}from"./chunk-BZDBSBRV.js";import{g as b,k as R,m as I}from"./chunk-P63ZVL36.js";import{c as tt,g as et,n as ot,s as nt,v as rt}from"./chunk-ZHA4Y2KB.js";import c from"chalk";import{resolve as wt,join as N}from"path";import{readFileSync as z}from"fs";import{statSync as Nt,readdirSync as Tt,unlinkSync as At}from"fs";import M from"crypto";var vt="vibeflow-auth-v1",xt=1440*60*1e3;function it(t){return M.scryptSync(t,vt,32)}function jt(t,e){let o=it(e),n=M.randomBytes(16),r=M.createCipheriv("aes-256-gcm",o,n),s=JSON.stringify(t),i=Buffer.concat([r.update(s),r.final()]),y=r.getAuthTag();return{version:1,createdAt:new Date().toISOString(),expiresAt:new Date(Date.now()+xt).toISOString(),iv:n.toString("hex"),tag:y.toString("hex"),data:i.toString("hex")}}function at(t,e){if(new Date(t.expiresAt)<new Date)return null;try{let o=it(e),n=M.createDecipheriv("aes-256-gcm",o,Buffer.from(t.iv,"hex"));n.setAuthTag(Buffer.from(t.tag,"hex"));let r=Buffer.concat([n.update(Buffer.from(t.data,"hex")),n.final()]);return JSON.parse(r.toString())}catch{return null}}function bt(t,e){return Math.abs(t.x-e.x)>2||Math.abs(t.y-e.y)>2||Math.abs(t.width-e.width)>2||Math.abs(t.height-e.height)>2}function H(t,e){let o=!!e.outerHTML,n=t.outerHTML!==e.outerHTML,r={},s=new Set([...Object.keys(t.computedStyles),...Object.keys(e.computedStyles)]);for(let l of s){let E=t.computedStyles[l],x=e.computedStyles[l];E!==x&&(r[l]=[E??"",x??""])}let i=bt(t.position.boundingBox,e.position.boundingBox),y=new Set(t.consoleErrors),g=e.consoleErrors.filter(l=>!y.has(l));return{selectorResolves:o,htmlChanged:n,stylesChanged:r,positionChanged:i,newConsoleErrors:g}}function ct(t,e){let o=[];if(t.selectorResolves){t.htmlChanged&&o.push("HTML changed");let n=Object.keys(t.stylesChanged).length;if(n>0){let r=Object.keys(t.stylesChanged).slice(0,5).join(", "),s=n>5?` (+${n-5} more)`:"";o.push(`${n} style property change(s): ${r}${s}`)}t.positionChanged&&o.push("position shifted"),t.newConsoleErrors.length>0&&o.push(`${t.newConsoleErrors.length} new console error(s)`),o.length===0&&o.push("no structural changes detected")}else o.push(`Selector "${e}" no longer resolves`);return o.join("; ")}import{readFileSync as lt,writeFileSync as Ht,mkdirSync as Jt,existsSync as ft}from"fs";import{join as gt,basename as Rt}from"path";import{execSync as Ct}from"child_process";var G={port:3700};function Ot(t){return gt(t,tt,et)}function ut(t){let e=Ot(t);if(!ft(e))return{...G};let o=lt(e,"utf-8"),n;try{n=JSON.parse(o)}catch{return{...G}}return{...G,...n}}function Wt(t){let e=gt(t,"package.json");if(ft(e))try{let o=JSON.parse(lt(e,"utf-8"));if(o.name)return o.name}catch{}return Rt(t)}function zt(t){try{return Ct("git branch --show-current",{cwd:t,encoding:"utf-8",stdio:["pipe","pipe","pipe"]}).trim()||null}catch{return null}}var W=["display","visibility","opacity","position","overflow","overflow-x","overflow-y","width","min-width","max-width","height","min-height","max-height","margin","margin-top","margin-right","margin-bottom","margin-left","padding","padding-top","padding-right","padding-bottom","padding-left","border","border-width","border-style","border-color","border-radius","background-color","background-image","color","font-size","font-weight","font-style","font-family","line-height","letter-spacing","text-align","text-decoration","text-overflow","white-space","flex-direction","flex-wrap","flex","justify-content","align-items","gap","row-gap","column-gap","grid-template-columns","grid-template-rows","z-index","box-shadow","transform","transition","cursor","user-select","pointer-events","top","left","right","bottom"];function dt(t){let e=[],o=t;for(;o&&o!==document.documentElement;){let n=o.parentElement;if(!n)break;let r=Array.from(n.children).indexOf(o);e.unshift(r),o=n}return e.join("/")}function ht(t){let e=t.tagName.toLowerCase(),o=t.getAttribute("data-task-id");if(o)return`${e}.task-card[data-task-id=${o}]`;let n=t.getAttribute("data-status");if(n&&t.classList.contains("column-scroll"))return`${e}.column-scroll[data-status=${n}]`;let r=t.getAttribute("data-column-id");if(r)return`${e}[data-column-id=${r}]`;let s=Array.from(t.classList).slice(0,2),i=e;s.length&&(i+="."+s.join("."));let y=t.parentElement;if(y){let g=Array.from(y.children).filter(l=>l.tagName===t.tagName);if(g.length>1){let l=g.indexOf(t)+1;i+=`:nth-of-type(${l})`}}return i}function mt(t,e=W){let o=window.getComputedStyle(t),n={};for(let r of e)n[r]=o.getPropertyValue(r);return n}function pt(t,e=200){return t.replace(/\s+/g," ").trim().slice(0,e)}function yt(t){let e=new Map;for(let o of t){let n=o.tagName.toLowerCase(),r=Array.from(o.classList).slice(0,2).join("."),s=r?`${n}.${r}`:n;e.set(s,(e.get(s)||0)+1)}return Array.from(e.entries()).map(([o,n])=>`${o} \xD7${n}`).slice(0,10)}var p=class extends Error{constructor(o,n,r){super(n);this.code=o;this.suggestion=r;this.name="VerifyError"}code;suggestion};async function Pt(){try{return await import("playwright")}catch{throw new p("E_PLAYWRIGHT_MISSING","Playwright is not installed.","Run: npx playwright install chromium")}}async function kt(t,e,o={}){let n=wt(t),r=ot(n,e);if(!r)throw new p("E_NOT_FOUND",`Task not found: ${e}`,"Run 'vibeflow tasks' to see available task IDs.");let s=nt(r);if(!s)throw new p("E_NOT_FOUND",`Task not found: ${e}`);let i,y=s.baselineElementFile||"baseline-element.json",g=I(n,e,y);if(g)try{i=JSON.parse(z(g,"utf-8"))}catch{}if(!i&&s.baseline&&(i=s.baseline),!i)throw new p("E_NO_BASELINE","Task has no baseline. Re-annotate to capture one.");let l=[],E={},x={};if(s.authStateEnc&&s.author)try{let m=JSON.parse(s.authStateEnc),f=at(m,s.author);if(!f)throw new p("E_AUTH_EXPIRED","Auth state expired. Re-annotate to capture fresh cookies.");l=f.cookies,E=f.localStorage,x=f.sessionStorage}catch(m){throw m instanceof p?m:new p("E_AUTH_CORRUPT","Auth state corrupted. Re-annotate.")}let v=o.url??s.url;if(!v)throw new p("E_NO_URL","Task has no URL. Cannot verify without a target URL.","Re-annotate the element with a URL, or use --url to override.");let C=ut(n).port??3700,A=v.startsWith("http")?v:`http://localhost:${C}${v.startsWith("/")?v:"/"+v}`,S=s.cssSelector??s.selector;if(!S||S==="/")throw new p("E_NO_SELECTOR","Task has no CSS selector. Cannot verify without a selector.");let j=await Pt(),$;try{$=await j.chromium.launch({headless:!0})}catch(m){let f=m instanceof Error?m.message:String(m);throw f.includes("not found")||f.includes("not installed")||f.includes("Executable doesn't exist")?new p("E_PLAYWRIGHT_MISSING","Chromium is not installed.","Run: npx playwright install chromium"):new p("E_PLAYWRIGHT_CRASH",`Verification failed: ${f}`,"Try again.")}let k;try{let m=i.position?.viewport;k=await $.newContext({viewport:m?{width:m.width,height:m.height}:void 0,deviceScaleFactor:m?.dpr,userAgent:i.browser||void 0}),l.length>0&&await k.addCookies(l.map(a=>({name:a.name,value:a.value,domain:a.domain,path:a.path,expires:a.expires,httpOnly:a.httpOnly,secure:a.secure,sameSite:a.sameSite})));let f=await k.newPage(),T=[];f.on("console",a=>{a.type()==="error"&&T.push(a.text())}),f.on("pageerror",a=>{T.push(a.message)});try{await f.goto(A,{waitUntil:"networkidle",timeout:15e3})}catch(a){let u=a instanceof Error?a.message:String(a);throw u.includes("ERR_CONNECTION_REFUSED")||u.includes("ECONNREFUSED")?new p("E_APP_NOT_RUNNING",`Cannot connect to ${A}. Is the dev server running?`):new p("E_NAVIGATION_FAILED",`Failed to navigate to ${A}: ${u}`)}try{Object.keys(E).length>0&&await f.evaluate(a=>{for(let[u,d]of Object.entries(a))window.localStorage.setItem(u,d)},E),Object.keys(x).length>0&&await f.evaluate(a=>{for(let[u,d]of Object.entries(a))window.sessionStorage.setItem(u,d)},x)}catch{}let P=0;try{await f.waitForSelector(S,{timeout:1e4}),P=await f.locator(S).count()}catch{let a={outerHTML:"",computedStyles:{},selector:S,position:i.position,browser:i.browser,consoleErrors:T,capturedAt:new Date().toISOString()},u=H(i,a);return K(s.id,s.description,i,a,u,[],S)}if(P>1){let a={outerHTML:"",computedStyles:{},selector:S,position:i.position,browser:i.browser,consoleErrors:T,capturedAt:new Date().toISOString()},u=H(i,a),d=`Selector matches ${P} elements. The selector may need to be more specific.`;return K(s.id,s.description,i,a,u,[],S,d)}let L=await Lt(f,S,i,T),_=null,B=s.baselineFile||"baseline-page.json",F=I(n,e,B);if(F)try{_=JSON.parse(z(F,"utf-8"))}catch{}let h=H(i,L),O=await _t(n,e,i,L,h,T,f,S);if(_&&_.elements){let a=I(n,e,"verify-all-styles.json");if(a)try{let u=JSON.parse(z(a,"utf-8"));if(u&&u.elements){let d={},St=Object.entries(u.elements);for(let[Y,X]of St){let J=_.elements[Y]?.after;if(J){X.baseline=J;let V={};for(let[q,Q]of Object.entries(X.after)){let Z=J[q];Z!==Q&&(V[q]=[Z,Q])}Object.keys(V).length>0&&(d[Y]=V)}}R(n,e,"verify-all-styles.json",Buffer.from(JSON.stringify(u,null,2)));let Et=JSON.stringify({totalChanged:Object.keys(d).length,elements:d},null,2);R(n,e,"verify-page-diff.json",Buffer.from(Et)),O.push(N(b(n,e),"verify-page-diff.json"))}}catch{}}let D=K(s.id,s.description,i,L,h,O,S);return rt(n,e,{verified:D.ok}),D}finally{await k?.close(),await $?.close()}}async function Lt(t,e,o,n){let r=t.locator(e).first(),s=await r.evaluate(l=>l.outerHTML).catch(()=>""),i=await r.evaluate(l=>{let E=window.getComputedStyle(l),x={};for(let v=0;v<E.length;v++){let w=E[v];x[w]=E.getPropertyValue(w)}return x}).catch(()=>({})),g={boundingBox:await r.boundingBox().catch(()=>null)??o.position.boundingBox,scrollPosition:await t.evaluate(()=>({x:window.scrollX,y:window.scrollY})),viewport:await t.evaluate(()=>({width:window.innerWidth,height:window.innerHeight,dpr:window.devicePixelRatio})),stackingContext:o.position.stackingContext};return{outerHTML:s,computedStyles:i,selector:e,position:g,browser:o.browser,consoleErrors:n,capturedAt:new Date().toISOString()}}async function _t(t,e,o,n,r,s,i,y){let g=[],l=b(t,e);try{let w=Tt(l);for(let C of w)(C.startsWith("verify-")||C==="baseline.json")&&At(N(l,C))}catch{}let E=JSON.stringify(n,null,2);R(t,e,"verify-after.json",Buffer.from(E)),g.push(N(b(t,e),"verify-after.json"));let x=JSON.stringify(r,null,2);R(t,e,"verify-diff.json",Buffer.from(x)),g.push(N(b(t,e),"verify-diff.json"));let v=s.length>0?s.join(`
3
+ `):"(no console errors)";if(R(t,e,"verify-console.txt",Buffer.from(v)),g.push(N(b(t,e),"verify-console.txt")),i){try{let w=await i.content();R(t,e,"verify-page.html",Buffer.from(w)),g.push(N(b(t,e),"verify-page.html"))}catch{}try{let C=await i.evaluate(({buildKeyFn:A,buildSelectorFn:S,filterStylesFn:j,childSignatureFn:$,normalizeTextFn:k,styles:m,maxElements:f})=>{let T={},P=0,L=!1,_=document.createTreeWalker(document.body,NodeFilter.SHOW_ELEMENT,{acceptNode(h){if(P>=f)return NodeFilter.FILTER_REJECT;let O=h;return O.classList.length>0||O.hasAttribute("data-task-id")||O.hasAttribute("data-status")||O.hasAttribute("data-column-id")?NodeFilter.FILTER_ACCEPT:NodeFilter.FILTER_SKIP}}),B=[],F;for(;F=_.nextNode();)B.push(F);for(let h of B){if(P>=f){L=!0;break}let O=A(h),D=Array.from(h.children),a={};for(let d of Array.from(h.attributes))d.name.startsWith("data-")&&(a[d.name.slice(5)]=d.value);let u={x:0,y:0,width:0,height:0};try{let d=h.getBoundingClientRect();u={x:Math.round(d.x),y:Math.round(d.y),width:Math.round(d.width),height:Math.round(d.height)}}catch{}T[O]={key:O,selector:S(h),tag:h.tagName.toLowerCase(),classes:Array.from(h.classList),dataAttrs:a,parentKey:h.parentElement?A(h.parentElement):"",childCount:D.length,childSignature:$(D),text:k(h.textContent??""),position:u,baseline:j(h,m),after:j(h,m)},P++}return{version:1,capturedAt:new Date().toISOString(),truncated:L,elements:T}},{buildKeyFn:dt,buildSelectorFn:ht,filterStylesFn:mt,childSignatureFn:yt,normalizeTextFn:pt,styles:W,maxElements:1e3});if(C){let A=JSON.stringify(C,null,2);R(t,e,"verify-all-styles.json",Buffer.from(A)),g.push(N(b(t,e),"verify-all-styles.json"))}}catch{}try{let w=await i.screenshot({fullPage:!1});R(t,e,"verify-screenshot.png",w),g.push(N(b(t,e),"verify-screenshot.png"))}catch{}if(y)try{let w=await i.locator(y).first().evaluate(C=>C.outerHTML);R(t,e,"verify-element.html",Buffer.from(w)),g.push(N(b(t,e),"verify-element.html"))}catch{}}if(o){let w=JSON.stringify(o,null,2);R(t,e,"baseline.json",Buffer.from(w)),g.push(N(b(t,e),"baseline.json"))}return g}function K(t,e,o,n,r,s,i,y){let g=r.selectorResolves&&r.newConsoleErrors.length===0,l=y??ct(r,i);return{taskId:t,ok:g,taskDescription:e,baseline:{selector:o.selector,url:"",capturedAt:o.capturedAt,snapshot:o},after:{snapshot:n,consoleErrors:n.consoleErrors},diff:r,evidenceFiles:s,verdict:l}}async function ce(t,e,o){let n=wt(t);try{let r=await kt(n,e,o);await $t(n,e,r),o.json?console.log(JSON.stringify(r,null,2)):Ft(r)}catch(r){if(r instanceof p)o.json?process.stderr.write(JSON.stringify({ok:!1,error:{code:r.code,message:r.message,suggestion:r.suggestion}})+`
4
+ `):(process.stderr.write(c.red(`\u2717 ${r.message}
5
+ `)),r.suggestion&&process.stderr.write(c.dim(` ${r.suggestion}
6
+ `))),process.exitCode=U.GENERAL;else{let s=r instanceof Error?r.message:String(r);o.json?process.stderr.write(JSON.stringify({ok:!1,error:{code:"E_UNKNOWN",message:s}})+`
7
+ `):process.stderr.write(c.red(`\u2717 Verification failed: ${s}
8
+ `)),process.exitCode=U.GENERAL}}}async function $t(t,e,o){let n=`**Verification ${o.ok?"\u2705 passed":"\u26A0\uFE0F issues detected"}**
9
+
10
+ ${o.verdict}`;st(t,e,"agent",n,void 0,"system")}function Ft(t){let e=t.ok?c.green("\u2705"):c.yellow("\u26A0\uFE0F");console.log(),console.log(` ${e} Evidences collected for task ${t.taskId}`),console.log(c.dim("\u2500".repeat(60))),console.log(c.dim(` Verdict: ${t.verdict}`)),console.log();let o=t.diff;if(o.selectorResolves){o.htmlChanged?console.log(c.cyan(" \u2713 HTML changed")):console.log(c.dim(" \xB7 HTML unchanged"));let n=Object.keys(o.stylesChanged).length;if(n>0){console.log(c.cyan(` \u2713 ${n} style property change(s):`));for(let[r,[s,i]]of Object.entries(o.stylesChanged).slice(0,8))console.log(c.dim(` ${r}: ${s} \u2192 ${i}`));n>8&&console.log(c.dim(` ... and ${n-8} more`))}if(o.positionChanged&&console.log(c.cyan(" \u2713 Position shifted")),o.newConsoleErrors.length>0){console.log(c.yellow(` \u26A0 ${o.newConsoleErrors.length} new console error(s):`));for(let r of o.newConsoleErrors.slice(0,3))console.log(c.dim(` ${r.slice(0,120)}`))}}else console.log(c.red(" \u26A0 Target element not found \u2014 the fix may have renamed/removed it."));if(t.evidenceFiles.length>0){console.log(c.cyan(` Evidence files (${t.evidenceFiles.length}):`));for(let n of t.evidenceFiles){let r=n.split("/").pop()??n;try{let i=(Nt(n).size/1024).toFixed(1);console.log(c.dim(` ${r} (${i} KB)`))}catch{console.log(c.dim(` ${r}`))}}}console.log(),console.log(c.cyan(" Explore evidence (agent tools):")),console.log(c.dim(` vibeflow verify style_query ${t.taskId} <property>`)),console.log(c.dim(` vibeflow verify style_diff ${t.taskId} [--filter <pattern>]`)),console.log(c.dim(` vibeflow verify element_info ${t.taskId}`)),console.log(c.dim(` vibeflow verify html_diff ${t.taskId}`)),console.log(),console.log(c.cyan(" Review evidences:")),console.log(c.dim(" 1. Check if the fix is confirmed (styles match expectations)")),console.log(c.dim(` 2. If confirmed \u2192 vibeflow tasks --edit ${t.taskId} --set-status review --comment "Verified: <what you confirmed>"`)),console.log(c.dim(" 3. If not sure \u2192 leave a comment explaining uncertainty")),console.log(c.dim(` 4. If wrong \u2192 vibeflow tasks --edit ${t.taskId} --set-status in-progress`)),console.log(),t.ok||(console.log(c.yellow(" \u26A0 Verification failed \u2014 move to in-progress and fix:")),console.log(c.dim(` vibeflow tasks --edit ${t.taskId} --set-status in-progress`)))}export{jt as a,ut as b,Wt as c,zt as d,p as e,kt as f,ce as g,$t as h};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{a as d,b as f,f as S,g as c,h as g,j as p,l as u}from"./chunk-Q7MEW67Z.js";import{mkdirSync as w,writeFileSync as O,renameSync as F}from"fs";import{dirname as b}from"path";import{randomBytes as z}from"crypto";function P(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function B(t,n){let r=c(t,n);return((r?u(r):null)?.comments??[]).filter(e=>!e.deleted).map(P)}function x(t){return p(t)}async function E(t,n,r,i,e,o,m){i=x(i);let a=d(t,n);return f(a,()=>{let s=c(t,n),l=s?u(s):null,y=l?.comments??[],C={id:z(8).toString("hex"),author:r,text:i,...e&&e.length>0?{files:e}:{},...o&&o!=="comment"?{type:o}:{},createdAt:new Date().toISOString(),source:m??"cli"},T=[...y,C];if(l)g(t,{...l,comments:T});else{let k=S(t,n,new Date().toISOString());w(b(k),{recursive:!0});let h=k+".tmp";O(h,JSON.stringify({id:n,comments:T},null,2),"utf-8"),F(h,k)}return C})}async function N(t,n,r,i){let e=d(t,n);return f(e,()=>{let o=c(t,n),m=o?u(o):null,a=m?.comments??[],s=a.find(l=>l.id===r&&!l.deleted);return s?(s.text=x(i),s.updatedAt=new Date().toISOString(),m&&g(t,{...m,comments:a}),P(s)):null})}async function G(t,n,r){let i=d(t,n);return f(i,()=>{let e=c(t,n),o=e?u(e):null,m=o?.comments??[],a=m.findIndex(s=>s.id===r&&!s.deleted);return a===-1?!1:(m[a]={...m[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},o&&g(t,{...o,comments:m}),!0)})}export{B as a,x as b,E as c,N as d,G as e};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{a as w}from"./chunk-BZDBSBRV.js";import{a as B,d as U}from"./chunk-R5NQALFI.js";import{d as P,e as E,u as N}from"./chunk-JAWQQLJC.js";import{a as A,b as _}from"./chunk-KJ5LYG6A.js";import g from"chalk";import{unlinkSync as ye,readFileSync as ke,existsSync as we}from"fs";import{resolve as Se,join as $e}from"path";import I from"fs/promises";import oe from"os";import F from"path";var re=F.join(oe.homedir(),".vibeflow"),T=F.join(re,"token");async function b(){try{return(await I.readFile(T,"utf8")).trim()||null}catch{return null}}async function j(e){await I.mkdir(F.dirname(T),{recursive:!0}),await I.writeFile(T,e,{mode:384})}async function Ae(){try{await I.unlink(T)}catch{}}import i from"chalk";import ie from"open";import V from"readline";import ae from"@inquirer/select";import{existsSync as L,readFileSync as D,writeFileSync as W,mkdirSync as M,renameSync as z}from"fs";import{join as x}from"path";import G from"os";var ne="settings.json";function H(){return x(G.homedir(),".vibeflow","settings.json")}function J(e){return x(e,P,ne)}function O(){try{return JSON.parse(D(H(),"utf-8"))}catch{return{}}}function q(e){let r=x(G.homedir(),".vibeflow");L(r)||M(r,{recursive:!0});let o=H(),n=o+".tmp";W(n,JSON.stringify(e,null,2),"utf-8"),z(n,o)}function se(e){let r=O(),o=J(e);if(!L(o))return r;try{let n=JSON.parse(D(o,"utf-8"));return{...r,...n}}catch{return r}}function Ne(e,r){let o=x(e,P);L(o)||M(o,{recursive:!0});let n=J(e),c={...se(e),...r},p=n+".tmp";return W(p,JSON.stringify(c,null,2),"utf-8"),z(p,n),c}import{existsSync as ce,readdirSync as K,readFileSync as le}from"fs";import{join as R,resolve as de}from"path";var pe="https://app.vibeflow.tools",fe=300*1e3;function Y(){return process.env.VIBEFLOW_API_URL??pe}async function ue(e){return new Promise(r=>setTimeout(r,e))}async function ge(e){return e.length===1?(console.log(i.dim(` Using board: ${e[0].icon??""} ${e[0].name}`)),e[0]):await ae({message:"Select a board to use:",choices:e.map(o=>({name:`${o.icon??""} ${o.name}`,value:o}))})}async function Q(e,r){try{let o=await fetch(`${e}/api/cli/settings`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)return;let n=await o.json();n.settings&&Object.keys(n.settings).length>0&&q({...n.settings,_settingsRefreshedAt:Date.now()})}catch{}}async function Ve(){try{let e=await b();if(!e)return;let o=O()._settingsRefreshedAt??0;if(Date.now()-o<fe)return;let n=Y();Q(n,e)}catch{}}async function me(e,r){try{let[o,n]=await Promise.all([fetch(`${e}/api/cli/workspaces`,{headers:{Authorization:`Bearer ${r}`}}),fetch(`${e}/api/cli/profile`,{headers:{Authorization:`Bearer ${r}`}})]);if(!o.ok)return;let a=await o.json();if(!a.workspaces?.length){console.log(i.yellow(" No boards found. Create a board in the web app first."));return}let c=n.ok?await n.json():null,p=await ge(a.workspaces);await _({...p,email:c?.email??null}),console.log(i.green(` Board set: ${p.icon??""} ${p.name}`)),console.log(i.dim(` Open at: ${p.url}`))}catch{}}async function he(e,r,o,n){let a=R(e,P,E);if(!ce(a))return;let c=[];try{for(let s of K(a,{withFileTypes:!0}))if(s.isDirectory()){let f=R(a,s.name);for(let m of K(f).filter(d=>d.endsWith(".json")))c.push(R(f,m))}else s.isFile()&&s.name.endsWith(".json")&&c.push(R(a,s.name))}catch{return}if(c.length===0)return;let p=c.flatMap(s=>{try{return[JSON.parse(le(s,"utf-8"))]}catch{return[]}}),y=new Set;try{let s=await fetch(`${r}/api/cli/tasks?boardId=${n.id}`,{headers:{Authorization:`Bearer ${o}`}}).catch(()=>null);if(s?.ok){let f=await s.json();y=new Set((f.tasks??[]).flatMap(m=>[m.id,...m.cliId?[m.cliId]:[]]))}}catch{}let l=p.filter(s=>!y.has(s.id));if(l.length===0)return;console.log(),console.log(i.bold(` ${l.length} local task${l.length!==1?"s are":" is"} not yet synced to the board:`));let h=l.slice(0,10);for(let s of h){let f=s.status?i.dim(` [${s.status}]`):"";console.log(i.dim(` \u2022 ${s.title??s.id}${f}`))}return l.length>10&&console.log(i.dim(` \u2026 and ${l.length-10} more`)),new Promise(s=>{let f=V.createInterface({input:process.stdin,output:process.stdout});f.question(i.cyan(`
3
+ Push them to your board now? [Y/n]: `),async m=>{if(f.close(),m.trim().toLowerCase()==="n"){console.log(i.dim(" Skipped. You can push later with: vibeflow push")),s();return}let d=V.createInterface({input:process.stdin,output:process.stdout});d.question(i.cyan(" Delete local task files after push? [y/N]: "),async k=>{d.close();let S=k.trim().toLowerCase()!=="y";try{let t=await fetch(`${r}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({boardId:n.id,tasks:l,keepLocalFiles:S})}),u={};try{u=await t.json()}catch{}t.ok?(console.log(i.green(` \u2713 Pushed ${u.imported??0} task${(u.imported??0)!==1?"s":""} to ${n.name}`)),(u.skipped??0)>0&&console.log(i.dim(` (${u.skipped} already existed and were skipped)`))):console.log(i.red(` Push failed: ${u.error??`HTTP ${t.status}`}`))}catch(t){console.log(i.red(` Push failed: ${t instanceof Error?t.message:"Network error"}`))}s()})})})}async function X(e=de(".")){let r=Y();console.log(i.cyan(" Initiating device login flow..."));let o;try{o=await fetch(`${r}/api/cli/auth/device-init`,{method:"POST",headers:{"Content-Type":"application/json"}})}catch(h){console.error(i.red(` Failed to connect to login server: ${h instanceof Error?h.message:"Network error"}`)),process.exitCode=w.AUTH;return}if(!o.ok){console.error(i.red(` Failed to initiate login: ${o.status} ${o.statusText}`)),process.exitCode=w.AUTH;return}let{deviceCode:n,userCode:a,verificationUrl:c,expiresIn:p}=await o.json();console.log(),console.log(i.bold(" Open this URL in your browser to authorize:")),console.log(i.underline(` ${c}`)),console.log();try{await ie(c),console.log(i.dim(" (Browser opened automatically)"))}catch{}let y=Date.now()+p*1e3,l=3e3;for(;Date.now()<y;){await ue(l);let h=null;try{h=await fetch(`${r}/api/cli/auth/device-poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:n})})}catch{console.error(i.red(" Poll request failed (network error). Retrying..."));continue}if(!h.ok){console.error(i.red(" Poll request failed. Retrying..."));continue}let s=await h.json();if("token"in s){await j(s.token),console.log(),console.log(i.green(" Logged in successfully. Now operating in SaaS mode.")),await Promise.all([me(r,s.token),Q(r,s.token)]);let{readWorkspace:f}=await import("./workspace-AJAVENKA.js"),m=await f();m&&await he(e,r,s.token,m);return}if("expired"in s){console.error(i.red(" Device code expired. Please try again.")),process.exitCode=w.AUTH;return}process.stdout.write(i.dim("."))}console.error(i.red(`
4
+ Login timed out. Please try again.`)),process.exitCode=w.AUTH}var Pe="https://app.vibeflow.tools";function be(){return process.env.VIBEFLOW_API_URL??Pe}function Ie(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Z(e,r,o=24){let n=Math.round(e/r*o);return`[${"\u2588".repeat(n)+"\u2591".repeat(o-n)}]`}async function Te(e,r,o,n){let a=[];for(let{localId:d,remoteId:k}of n){let S=U(o,d);for(let t of S){let u=t.linkedPath??$e(B(o,d),t.name);we(u)&&a.push({remoteId:k,name:t.name,filePath:u,size:t.size})}}if(a.length===0)return{uploaded:0,failed:0,failedFiles:[]};let c=a.length,p=a.reduce((d,k)=>d+k.size,0);console.log(g.cyan(`
5
+ Uploading ${c} file(s) (${Ie(p)})...`));let y=0,l=0,h=0,s=Date.now(),f=[];for(let d of a){let k=Math.round(y/c*100),S=Z(y,c),t=(Date.now()-s)/1e3,u=h/Math.max(t,.01),ee=p-h,v=u>0?Math.ceil(ee/u):0,te=v>60?`${Math.ceil(v/60)}m`:`${v}s`;process.stdout.write(`\r ${S} ${k}% ${d.name.slice(0,28)} ETA: ${te} `);try{let $=ke(d.filePath),C=await fetch(`${e}/api/tasks/${encodeURIComponent(d.remoteId)}/files`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/octet-stream","x-filename":encodeURIComponent(d.name)},body:$});C.ok?(y++,h+=d.size):(l++,f.push({name:d.name,reason:`HTTP ${C.status}`}))}catch($){l++,f.push({name:d.name,reason:$ instanceof Error?$.message:String($)})}}let m=Z(c,c);return process.stdout.write(`\r ${m} 100% Done${" ".repeat(40)}
6
+ `),{uploaded:y,failed:l,failedFiles:f}}async function it(e,r){let o=Se(e),n=await b();if(!n&&(console.log(g.yellow(" Not logged in. Starting login flow...")),await X(),n=await b(),!n)){console.error(g.red(" Login failed. Please run `vibeflow login` and try again.")),process.exitCode=w.AUTH;return}let a=N(o);if(a.length===0){console.log(g.dim(" No local tasks found. Nothing to push."));return}console.log(g.cyan(` Found ${a.length} local task(s). Pushing to SaaS...`));let c=be(),p=r.workspace;if(!p){let t=await A();t&&(p=t.id,console.log(g.dim(` Using board: ${t.icon??""} ${t.name}`)))}let y={tasks:a};p&&(y.workspaceId=p);let l;try{let t=await fetch(`${c}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(y)});if(!t.ok){let u=await t.json().catch(()=>({}));console.error(g.red(` Import failed: ${t.status} ${u.error??t.statusText}`)),process.exitCode=w.GENERAL;return}l=await t.json()}catch(t){let u=t instanceof Error?t.message:String(t);console.error(g.red(` Network error: ${u}`)),process.exitCode=w.GENERAL;return}console.log(g.green(` \u2713 Pushed ${l.imported} task(s) to SaaS`)),l.skipped&&l.skipped>0&&console.log(g.dim(` Skipped ${l.skipped} already-imported task(s).`));let h=(await A())?.name??l.workspaceId;console.log(g.dim(` Board: ${h}`));let s=l.idMap??{},f=a.filter(t=>t.id&&s[t.id]).map(t=>({localId:t.id,remoteId:s[t.id]})),{uploaded:m,failed:d,failedFiles:k}=await Te(c,n,o,f);if(m>0&&console.log(g.green(` \u2713 Uploaded ${m} file(s) to storage`)),d>0){console.log(g.yellow(` \u26A0 ${d} file(s) failed to upload`));for(let t of k)console.log(g.dim(` - ${t.name}: ${t.reason}`))}if(r.keepLocalFiles){console.log(g.dim(" Local task files kept (--keep-local-files)."));return}let S=0;for(let t of a)try{ye(t.filePath),S++}catch{}console.log(g.dim(` Deleted ${S} local task file(s).`))}export{b as a,Ae as b,se as c,Ne as d,Ve as e,X as f,Ie as g,Z as h,it as i};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{h as d,i as f,m as S,n as c,o as g,q as p,s as u}from"./chunk-ZHA4Y2KB.js";import{mkdirSync as w,writeFileSync as O,renameSync as F}from"fs";import{dirname as b}from"path";import{randomBytes as z}from"crypto";function P(t){let n=t;return{...t,text:t.text||n.body||"",author:t.author??"agent"}}function B(t,n){let r=c(t,n);return((r?u(r):null)?.comments??[]).filter(e=>!e.deleted).map(P)}function x(t){return p(t)}async function E(t,n,r,i,e,o,m){i=x(i);let a=d(t,n);return f(a,()=>{let s=c(t,n),l=s?u(s):null,y=l?.comments??[],C={id:z(8).toString("hex"),author:r,text:i,...e&&e.length>0?{files:e}:{},...o&&o!=="comment"?{type:o}:{},createdAt:new Date().toISOString(),source:m??"cli"},T=[...y,C];if(l)g(t,{...l,comments:T});else{let k=S(t,n,new Date().toISOString());w(b(k),{recursive:!0});let h=k+".tmp";O(h,JSON.stringify({id:n,comments:T},null,2),"utf-8"),F(h,k)}return C})}async function N(t,n,r,i){let e=d(t,n);return f(e,()=>{let o=c(t,n),m=o?u(o):null,a=m?.comments??[],s=a.find(l=>l.id===r&&!l.deleted);return s?(s.text=x(i),s.updatedAt=new Date().toISOString(),m&&g(t,{...m,comments:a}),P(s)):null})}async function G(t,n,r){let i=d(t,n);return f(i,()=>{let e=c(t,n),o=e?u(e):null,m=o?.comments??[],a=m.findIndex(s=>s.id===r&&!s.deleted);return a===-1?!1:(m[a]={...m[a],deleted:!0,text:"[Comment deleted]",updatedAt:new Date().toISOString()},o&&g(t,{...o,comments:m}),!0)})}export{B as a,x as b,E as c,N as d,G as e};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{a as w}from"./chunk-BZDBSBRV.js";import{g as B,j as U}from"./chunk-P63ZVL36.js";import{c as P,d as E,u as N}from"./chunk-ZHA4Y2KB.js";import{a as A,b as _}from"./chunk-KJ5LYG6A.js";import g from"chalk";import{unlinkSync as ye,readFileSync as ke,existsSync as we}from"fs";import{resolve as Se,join as $e}from"path";import I from"fs/promises";import oe from"os";import F from"path";var re=F.join(oe.homedir(),".vibeflow"),T=F.join(re,"token");async function b(){try{return(await I.readFile(T,"utf8")).trim()||null}catch{return null}}async function j(e){await I.mkdir(F.dirname(T),{recursive:!0}),await I.writeFile(T,e,{mode:384})}async function Ae(){try{await I.unlink(T)}catch{}}import i from"chalk";import ie from"open";import V from"readline";import ae from"@inquirer/select";import{existsSync as L,readFileSync as D,writeFileSync as W,mkdirSync as M,renameSync as z}from"fs";import{join as x}from"path";import G from"os";var ne="settings.json";function H(){return x(G.homedir(),".vibeflow","settings.json")}function J(e){return x(e,P,ne)}function O(){try{return JSON.parse(D(H(),"utf-8"))}catch{return{}}}function q(e){let r=x(G.homedir(),".vibeflow");L(r)||M(r,{recursive:!0});let o=H(),n=o+".tmp";W(n,JSON.stringify(e,null,2),"utf-8"),z(n,o)}function se(e){let r=O(),o=J(e);if(!L(o))return r;try{let n=JSON.parse(D(o,"utf-8"));return{...r,...n}}catch{return r}}function Ne(e,r){let o=x(e,P);L(o)||M(o,{recursive:!0});let n=J(e),c={...se(e),...r},p=n+".tmp";return W(p,JSON.stringify(c,null,2),"utf-8"),z(p,n),c}import{existsSync as ce,readdirSync as K,readFileSync as le}from"fs";import{join as R,resolve as de}from"path";var pe="https://app.vibeflow.tools",fe=300*1e3;function Y(){return process.env.VIBEFLOW_API_URL??pe}async function ue(e){return new Promise(r=>setTimeout(r,e))}async function ge(e){return e.length===1?(console.log(i.dim(` Using board: ${e[0].icon??""} ${e[0].name}`)),e[0]):await ae({message:"Select a board to use:",choices:e.map(o=>({name:`${o.icon??""} ${o.name}`,value:o}))})}async function Q(e,r){try{let o=await fetch(`${e}/api/cli/settings`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)return;let n=await o.json();n.settings&&Object.keys(n.settings).length>0&&q({...n.settings,_settingsRefreshedAt:Date.now()})}catch{}}async function Ve(){try{let e=await b();if(!e)return;let o=O()._settingsRefreshedAt??0;if(Date.now()-o<fe)return;let n=Y();Q(n,e)}catch{}}async function me(e,r){try{let[o,n]=await Promise.all([fetch(`${e}/api/cli/workspaces`,{headers:{Authorization:`Bearer ${r}`}}),fetch(`${e}/api/cli/profile`,{headers:{Authorization:`Bearer ${r}`}})]);if(!o.ok)return;let a=await o.json();if(!a.workspaces?.length){console.log(i.yellow(" No boards found. Create a board in the web app first."));return}let c=n.ok?await n.json():null,p=await ge(a.workspaces);await _({...p,email:c?.email??null}),console.log(i.green(` Board set: ${p.icon??""} ${p.name}`)),console.log(i.dim(` Open at: ${p.url}`))}catch{}}async function he(e,r,o,n){let a=R(e,P,E);if(!ce(a))return;let c=[];try{for(let s of K(a,{withFileTypes:!0}))if(s.isDirectory()){let f=R(a,s.name);for(let m of K(f).filter(d=>d.endsWith(".json")))c.push(R(f,m))}else s.isFile()&&s.name.endsWith(".json")&&c.push(R(a,s.name))}catch{return}if(c.length===0)return;let p=c.flatMap(s=>{try{return[JSON.parse(le(s,"utf-8"))]}catch{return[]}}),y=new Set;try{let s=await fetch(`${r}/api/cli/tasks?boardId=${n.id}`,{headers:{Authorization:`Bearer ${o}`}}).catch(()=>null);if(s?.ok){let f=await s.json();y=new Set((f.tasks??[]).flatMap(m=>[m.id,...m.cliId?[m.cliId]:[]]))}}catch{}let l=p.filter(s=>!y.has(s.id));if(l.length===0)return;console.log(),console.log(i.bold(` ${l.length} local task${l.length!==1?"s are":" is"} not yet synced to the board:`));let h=l.slice(0,10);for(let s of h){let f=s.status?i.dim(` [${s.status}]`):"";console.log(i.dim(` \u2022 ${s.title??s.id}${f}`))}return l.length>10&&console.log(i.dim(` \u2026 and ${l.length-10} more`)),new Promise(s=>{let f=V.createInterface({input:process.stdin,output:process.stdout});f.question(i.cyan(`
3
+ Push them to your board now? [Y/n]: `),async m=>{if(f.close(),m.trim().toLowerCase()==="n"){console.log(i.dim(" Skipped. You can push later with: vibeflow push")),s();return}let d=V.createInterface({input:process.stdin,output:process.stdout});d.question(i.cyan(" Delete local task files after push? [y/N]: "),async k=>{d.close();let S=k.trim().toLowerCase()!=="y";try{let t=await fetch(`${r}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({boardId:n.id,tasks:l,keepLocalFiles:S})}),u={};try{u=await t.json()}catch{}t.ok?(console.log(i.green(` \u2713 Pushed ${u.imported??0} task${(u.imported??0)!==1?"s":""} to ${n.name}`)),(u.skipped??0)>0&&console.log(i.dim(` (${u.skipped} already existed and were skipped)`))):console.log(i.red(` Push failed: ${u.error??`HTTP ${t.status}`}`))}catch(t){console.log(i.red(` Push failed: ${t instanceof Error?t.message:"Network error"}`))}s()})})})}async function X(e=de(".")){let r=Y();console.log(i.cyan(" Initiating device login flow..."));let o;try{o=await fetch(`${r}/api/cli/auth/device-init`,{method:"POST",headers:{"Content-Type":"application/json"}})}catch(h){console.error(i.red(` Failed to connect to login server: ${h instanceof Error?h.message:"Network error"}`)),process.exitCode=w.AUTH;return}if(!o.ok){console.error(i.red(` Failed to initiate login: ${o.status} ${o.statusText}`)),process.exitCode=w.AUTH;return}let{deviceCode:n,userCode:a,verificationUrl:c,expiresIn:p}=await o.json();console.log(),console.log(i.bold(" Open this URL in your browser to authorize:")),console.log(i.underline(` ${c}`)),console.log();try{await ie(c),console.log(i.dim(" (Browser opened automatically)"))}catch{}let y=Date.now()+p*1e3,l=3e3;for(;Date.now()<y;){await ue(l);let h=null;try{h=await fetch(`${r}/api/cli/auth/device-poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:n})})}catch{console.error(i.red(" Poll request failed (network error). Retrying..."));continue}if(!h.ok){console.error(i.red(" Poll request failed. Retrying..."));continue}let s=await h.json();if("token"in s){await j(s.token),console.log(),console.log(i.green(" Logged in successfully. Now operating in SaaS mode.")),await Promise.all([me(r,s.token),Q(r,s.token)]);let{readWorkspace:f}=await import("./workspace-AJAVENKA.js"),m=await f();m&&await he(e,r,s.token,m);return}if("expired"in s){console.error(i.red(" Device code expired. Please try again.")),process.exitCode=w.AUTH;return}process.stdout.write(i.dim("."))}console.error(i.red(`
4
+ Login timed out. Please try again.`)),process.exitCode=w.AUTH}var Pe="https://app.vibeflow.tools";function be(){return process.env.VIBEFLOW_API_URL??Pe}function Ie(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Z(e,r,o=24){let n=Math.round(e/r*o);return`[${"\u2588".repeat(n)+"\u2591".repeat(o-n)}]`}async function Te(e,r,o,n){let a=[];for(let{localId:d,remoteId:k}of n){let S=U(o,d);for(let t of S){let u=t.linkedPath??$e(B(o,d),t.name);we(u)&&a.push({remoteId:k,name:t.name,filePath:u,size:t.size})}}if(a.length===0)return{uploaded:0,failed:0,failedFiles:[]};let c=a.length,p=a.reduce((d,k)=>d+k.size,0);console.log(g.cyan(`
5
+ Uploading ${c} file(s) (${Ie(p)})...`));let y=0,l=0,h=0,s=Date.now(),f=[];for(let d of a){let k=Math.round(y/c*100),S=Z(y,c),t=(Date.now()-s)/1e3,u=h/Math.max(t,.01),ee=p-h,v=u>0?Math.ceil(ee/u):0,te=v>60?`${Math.ceil(v/60)}m`:`${v}s`;process.stdout.write(`\r ${S} ${k}% ${d.name.slice(0,28)} ETA: ${te} `);try{let $=ke(d.filePath),C=await fetch(`${e}/api/tasks/${encodeURIComponent(d.remoteId)}/files`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/octet-stream","x-filename":encodeURIComponent(d.name)},body:$});C.ok?(y++,h+=d.size):(l++,f.push({name:d.name,reason:`HTTP ${C.status}`}))}catch($){l++,f.push({name:d.name,reason:$ instanceof Error?$.message:String($)})}}let m=Z(c,c);return process.stdout.write(`\r ${m} 100% Done${" ".repeat(40)}
6
+ `),{uploaded:y,failed:l,failedFiles:f}}async function it(e,r){let o=Se(e),n=await b();if(!n&&(console.log(g.yellow(" Not logged in. Starting login flow...")),await X(),n=await b(),!n)){console.error(g.red(" Login failed. Please run `vibeflow login` and try again.")),process.exitCode=w.AUTH;return}let a=N(o);if(a.length===0){console.log(g.dim(" No local tasks found. Nothing to push."));return}console.log(g.cyan(` Found ${a.length} local task(s). Pushing to SaaS...`));let c=be(),p=r.workspace;if(!p){let t=await A();t&&(p=t.id,console.log(g.dim(` Using board: ${t.icon??""} ${t.name}`)))}let y={tasks:a};p&&(y.workspaceId=p);let l;try{let t=await fetch(`${c}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(y)});if(!t.ok){let u=await t.json().catch(()=>({}));console.error(g.red(` Import failed: ${t.status} ${u.error??t.statusText}`)),process.exitCode=w.GENERAL;return}l=await t.json()}catch(t){let u=t instanceof Error?t.message:String(t);console.error(g.red(` Network error: ${u}`)),process.exitCode=w.GENERAL;return}console.log(g.green(` \u2713 Pushed ${l.imported} task(s) to SaaS`)),l.skipped&&l.skipped>0&&console.log(g.dim(` Skipped ${l.skipped} already-imported task(s).`));let h=(await A())?.name??l.workspaceId;console.log(g.dim(` Board: ${h}`));let s=l.idMap??{},f=a.filter(t=>t.id&&s[t.id]).map(t=>({localId:t.id,remoteId:s[t.id]})),{uploaded:m,failed:d,failedFiles:k}=await Te(c,n,o,f);if(m>0&&console.log(g.green(` \u2713 Uploaded ${m} file(s) to storage`)),d>0){console.log(g.yellow(` \u26A0 ${d} file(s) failed to upload`));for(let t of k)console.log(g.dim(` - ${t.name}: ${t.reason}`))}if(r.keepLocalFiles){console.log(g.dim(" Local task files kept (--keep-local-files)."));return}let S=0;for(let t of a)try{ye(t.filePath),S++}catch{}console.log(g.dim(` Deleted ${S} local task file(s).`))}export{b as a,Ae as b,se as c,Ne as d,Ve as e,X as f,Ie as g,Z as h,it as i};
@@ -0,0 +1,6 @@
1
+ #!/usr/bin/env node
2
+ import{a as w}from"./chunk-BZDBSBRV.js";import{a as B,d as U}from"./chunk-GQQIUROY.js";import{c as P,d as E,t as N}from"./chunk-QJMBWTAZ.js";import{a as A,b as _}from"./chunk-KJ5LYG6A.js";import g from"chalk";import{unlinkSync as ye,readFileSync as ke,existsSync as we}from"fs";import{resolve as Se,join as $e}from"path";import I from"fs/promises";import oe from"os";import F from"path";var re=F.join(oe.homedir(),".vibeflow"),T=F.join(re,"token");async function b(){try{return(await I.readFile(T,"utf8")).trim()||null}catch{return null}}async function j(e){await I.mkdir(F.dirname(T),{recursive:!0}),await I.writeFile(T,e,{mode:384})}async function Ae(){try{await I.unlink(T)}catch{}}import i from"chalk";import ie from"open";import V from"readline";import ae from"@inquirer/select";import{existsSync as L,readFileSync as D,writeFileSync as W,mkdirSync as M,renameSync as z}from"fs";import{join as x}from"path";import G from"os";var ne="settings.json";function H(){return x(G.homedir(),".vibeflow","settings.json")}function J(e){return x(e,P,ne)}function O(){try{return JSON.parse(D(H(),"utf-8"))}catch{return{}}}function q(e){let r=x(G.homedir(),".vibeflow");L(r)||M(r,{recursive:!0});let o=H(),n=o+".tmp";W(n,JSON.stringify(e,null,2),"utf-8"),z(n,o)}function se(e){let r=O(),o=J(e);if(!L(o))return r;try{let n=JSON.parse(D(o,"utf-8"));return{...r,...n}}catch{return r}}function Ne(e,r){let o=x(e,P);L(o)||M(o,{recursive:!0});let n=J(e),c={...se(e),...r},p=n+".tmp";return W(p,JSON.stringify(c,null,2),"utf-8"),z(p,n),c}import{existsSync as ce,readdirSync as K,readFileSync as le}from"fs";import{join as R,resolve as de}from"path";var pe="https://app.vibeflow.tools",fe=300*1e3;function Y(){return process.env.VIBEFLOW_API_URL??pe}async function ue(e){return new Promise(r=>setTimeout(r,e))}async function ge(e){return e.length===1?(console.log(i.dim(` Using board: ${e[0].icon??""} ${e[0].name}`)),e[0]):await ae({message:"Select a board to use:",choices:e.map(o=>({name:`${o.icon??""} ${o.name}`,value:o}))})}async function Q(e,r){try{let o=await fetch(`${e}/api/cli/settings`,{headers:{Authorization:`Bearer ${r}`}});if(!o.ok)return;let n=await o.json();n.settings&&Object.keys(n.settings).length>0&&q({...n.settings,_settingsRefreshedAt:Date.now()})}catch{}}async function Ve(){try{let e=await b();if(!e)return;let o=O()._settingsRefreshedAt??0;if(Date.now()-o<fe)return;let n=Y();Q(n,e)}catch{}}async function me(e,r){try{let[o,n]=await Promise.all([fetch(`${e}/api/cli/workspaces`,{headers:{Authorization:`Bearer ${r}`}}),fetch(`${e}/api/cli/profile`,{headers:{Authorization:`Bearer ${r}`}})]);if(!o.ok)return;let a=await o.json();if(!a.workspaces?.length){console.log(i.yellow(" No boards found. Create a board in the web app first."));return}let c=n.ok?await n.json():null,p=await ge(a.workspaces);await _({...p,email:c?.email??null}),console.log(i.green(` Board set: ${p.icon??""} ${p.name}`)),console.log(i.dim(` Open at: ${p.url}`))}catch{}}async function he(e,r,o,n){let a=R(e,P,E);if(!ce(a))return;let c=[];try{for(let s of K(a,{withFileTypes:!0}))if(s.isDirectory()){let f=R(a,s.name);for(let m of K(f).filter(d=>d.endsWith(".json")))c.push(R(f,m))}else s.isFile()&&s.name.endsWith(".json")&&c.push(R(a,s.name))}catch{return}if(c.length===0)return;let p=c.flatMap(s=>{try{return[JSON.parse(le(s,"utf-8"))]}catch{return[]}}),y=new Set;try{let s=await fetch(`${r}/api/cli/tasks?boardId=${n.id}`,{headers:{Authorization:`Bearer ${o}`}}).catch(()=>null);if(s?.ok){let f=await s.json();y=new Set((f.tasks??[]).flatMap(m=>[m.id,...m.cliId?[m.cliId]:[]]))}}catch{}let l=p.filter(s=>!y.has(s.id));if(l.length===0)return;console.log(),console.log(i.bold(` ${l.length} local task${l.length!==1?"s are":" is"} not yet synced to the board:`));let h=l.slice(0,10);for(let s of h){let f=s.status?i.dim(` [${s.status}]`):"";console.log(i.dim(` \u2022 ${s.title??s.id}${f}`))}return l.length>10&&console.log(i.dim(` \u2026 and ${l.length-10} more`)),new Promise(s=>{let f=V.createInterface({input:process.stdin,output:process.stdout});f.question(i.cyan(`
3
+ Push them to your board now? [Y/n]: `),async m=>{if(f.close(),m.trim().toLowerCase()==="n"){console.log(i.dim(" Skipped. You can push later with: vibeflow push")),s();return}let d=V.createInterface({input:process.stdin,output:process.stdout});d.question(i.cyan(" Delete local task files after push? [y/N]: "),async k=>{d.close();let S=k.trim().toLowerCase()!=="y";try{let t=await fetch(`${r}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${o}`},body:JSON.stringify({boardId:n.id,tasks:l,keepLocalFiles:S})}),u={};try{u=await t.json()}catch{}t.ok?(console.log(i.green(` \u2713 Pushed ${u.imported??0} task${(u.imported??0)!==1?"s":""} to ${n.name}`)),(u.skipped??0)>0&&console.log(i.dim(` (${u.skipped} already existed and were skipped)`))):console.log(i.red(` Push failed: ${u.error??`HTTP ${t.status}`}`))}catch(t){console.log(i.red(` Push failed: ${t instanceof Error?t.message:"Network error"}`))}s()})})})}async function X(e=de(".")){let r=Y();console.log(i.cyan(" Initiating device login flow..."));let o;try{o=await fetch(`${r}/api/cli/auth/device-init`,{method:"POST",headers:{"Content-Type":"application/json"}})}catch(h){console.error(i.red(` Failed to connect to login server: ${h instanceof Error?h.message:"Network error"}`)),process.exitCode=w.AUTH;return}if(!o.ok){console.error(i.red(` Failed to initiate login: ${o.status} ${o.statusText}`)),process.exitCode=w.AUTH;return}let{deviceCode:n,userCode:a,verificationUrl:c,expiresIn:p}=await o.json();console.log(),console.log(i.bold(" Open this URL in your browser to authorize:")),console.log(i.underline(` ${c}`)),console.log();try{await ie(c),console.log(i.dim(" (Browser opened automatically)"))}catch{}let y=Date.now()+p*1e3,l=3e3;for(;Date.now()<y;){await ue(l);let h=null;try{h=await fetch(`${r}/api/cli/auth/device-poll`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({deviceCode:n})})}catch{console.error(i.red(" Poll request failed (network error). Retrying..."));continue}if(!h.ok){console.error(i.red(" Poll request failed. Retrying..."));continue}let s=await h.json();if("token"in s){await j(s.token),console.log(),console.log(i.green(" Logged in successfully. Now operating in SaaS mode.")),await Promise.all([me(r,s.token),Q(r,s.token)]);let{readWorkspace:f}=await import("./workspace-AJAVENKA.js"),m=await f();m&&await he(e,r,s.token,m);return}if("expired"in s){console.error(i.red(" Device code expired. Please try again.")),process.exitCode=w.AUTH;return}process.stdout.write(i.dim("."))}console.error(i.red(`
4
+ Login timed out. Please try again.`)),process.exitCode=w.AUTH}var Pe="https://app.vibeflow.tools";function be(){return process.env.VIBEFLOW_API_URL??Pe}function Ie(e){return e<1024?`${e} B`:e<1024*1024?`${(e/1024).toFixed(1)} KB`:`${(e/(1024*1024)).toFixed(1)} MB`}function Z(e,r,o=24){let n=Math.round(e/r*o);return`[${"\u2588".repeat(n)+"\u2591".repeat(o-n)}]`}async function Te(e,r,o,n){let a=[];for(let{localId:d,remoteId:k}of n){let S=U(o,d);for(let t of S){let u=t.linkedPath??$e(B(o,d),t.name);we(u)&&a.push({remoteId:k,name:t.name,filePath:u,size:t.size})}}if(a.length===0)return{uploaded:0,failed:0,failedFiles:[]};let c=a.length,p=a.reduce((d,k)=>d+k.size,0);console.log(g.cyan(`
5
+ Uploading ${c} file(s) (${Ie(p)})...`));let y=0,l=0,h=0,s=Date.now(),f=[];for(let d of a){let k=Math.round(y/c*100),S=Z(y,c),t=(Date.now()-s)/1e3,u=h/Math.max(t,.01),ee=p-h,v=u>0?Math.ceil(ee/u):0,te=v>60?`${Math.ceil(v/60)}m`:`${v}s`;process.stdout.write(`\r ${S} ${k}% ${d.name.slice(0,28)} ETA: ${te} `);try{let $=ke(d.filePath),C=await fetch(`${e}/api/tasks/${encodeURIComponent(d.remoteId)}/files`,{method:"POST",headers:{Authorization:`Bearer ${r}`,"Content-Type":"application/octet-stream","x-filename":encodeURIComponent(d.name)},body:$});C.ok?(y++,h+=d.size):(l++,f.push({name:d.name,reason:`HTTP ${C.status}`}))}catch($){l++,f.push({name:d.name,reason:$ instanceof Error?$.message:String($)})}}let m=Z(c,c);return process.stdout.write(`\r ${m} 100% Done${" ".repeat(40)}
6
+ `),{uploaded:y,failed:l,failedFiles:f}}async function it(e,r){let o=Se(e),n=await b();if(!n&&(console.log(g.yellow(" Not logged in. Starting login flow...")),await X(),n=await b(),!n)){console.error(g.red(" Login failed. Please run `vibeflow login` and try again.")),process.exitCode=w.AUTH;return}let a=N(o);if(a.length===0){console.log(g.dim(" No local tasks found. Nothing to push."));return}console.log(g.cyan(` Found ${a.length} local task(s). Pushing to SaaS...`));let c=be(),p=r.workspace;if(!p){let t=await A();t&&(p=t.id,console.log(g.dim(` Using board: ${t.icon??""} ${t.name}`)))}let y={tasks:a};p&&(y.workspaceId=p);let l;try{let t=await fetch(`${c}/api/cli/import`,{method:"POST",headers:{"Content-Type":"application/json",Authorization:`Bearer ${n}`},body:JSON.stringify(y)});if(!t.ok){let u=await t.json().catch(()=>({}));console.error(g.red(` Import failed: ${t.status} ${u.error??t.statusText}`)),process.exitCode=w.GENERAL;return}l=await t.json()}catch(t){let u=t instanceof Error?t.message:String(t);console.error(g.red(` Network error: ${u}`)),process.exitCode=w.GENERAL;return}console.log(g.green(` \u2713 Pushed ${l.imported} task(s) to SaaS`)),l.skipped&&l.skipped>0&&console.log(g.dim(` Skipped ${l.skipped} already-imported task(s).`));let h=(await A())?.name??l.workspaceId;console.log(g.dim(` Board: ${h}`));let s=l.idMap??{},f=a.filter(t=>t.id&&s[t.id]).map(t=>({localId:t.id,remoteId:s[t.id]})),{uploaded:m,failed:d,failedFiles:k}=await Te(c,n,o,f);if(m>0&&console.log(g.green(` \u2713 Uploaded ${m} file(s) to storage`)),d>0){console.log(g.yellow(` \u26A0 ${d} file(s) failed to upload`));for(let t of k)console.log(g.dim(` - ${t.name}: ${t.reason}`))}if(r.keepLocalFiles){console.log(g.dim(" Local task files kept (--keep-local-files)."));return}let S=0;for(let t of a)try{ye(t.filePath),S++}catch{}console.log(g.dim(` Deleted ${S} local task file(s).`))}export{b as a,Ae as b,se as c,Ne as d,Ve as e,X as f,Ie as g,Z as h,it as i};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ var d=(a=>typeof require<"u"?require:typeof Proxy<"u"?new Proxy(a,{get:(b,c)=>(typeof require<"u"?require:b)[c]}):a)(function(a){if(typeof require<"u")return require.apply(this,arguments);throw Error('Dynamic require of "'+a+'" is not supported')});export{d as a};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ var i=["backlog","todo","in-progress","review","done"];function s(e){let t=(e??"Medium").trim().toLowerCase();return t==="critical"?0:t==="high"?1:t==="low"?3:2}function o(e,t){let r=s(e.priority),n=s(t.priority);return r!==n?r-n:new Date(e.created).getTime()-new Date(t.created).getTime()}var a=".vibeflow",g="tasks",c="tasks/files",l="tasks/screenshots",m="config.json";export{i as a,s as b,o as c,a as d,g as e,c as f,l as g,m as h};