@vibeflow-tools/cli 0.8.0 → 0.9.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.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,50 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.9.0
4
+
5
+ ### Minor Changes
6
+
7
+ - 4dc1975: Add "🎨 Prototyping" option to the overlay page-level right-click context menu when `@vibeflow-tools/prototyping` is installed. Clicking the option opens the variant switcher panel via the `__vf_prototyping` API.
8
+
9
+ ### Patch Changes
10
+
11
+ - 3e4b441: Add "Hide Vibeflow" and "Disable Vibeflow" to the page-level right-click context menu.
12
+
13
+ - "Hide Vibeflow" now appears in the page context menu when the badge is visible (mirrors the badge's own context menu)
14
+ - "Disable Vibeflow" completely removes all overlay activity for the current page session (resets on page refresh)
15
+
16
+ - ba09800: Cancel multiselect mode when a task is dragged on the Kanban board.
17
+ - f4cf385: Add "Disable Vibeflow" option to the corner trigger right-click menu.
18
+
19
+ The bottom-right Vibeflow icon button's context menu now shows both "Hide Vibeflow" and "Disable Vibeflow", matching the options already available in the page-level right-click menu. Clicking "Disable Vibeflow" removes the overlay completely for the current session (resets on page refresh).
20
+
21
+ - a1c2b76: Fix overlay button (corner trigger) not visible on fresh injection after "Hide Vibeflow" was previously used. The hidden state now resets on every fresh page load / bookmarklet injection so the button always appears when the overlay is first mounted.
22
+ - 8db8f88: Fix overlay corner trigger rendering off-screen when a position saved on a larger monitor is restored from localStorage. The saved coordinates are now clamped to the current viewport bounds on load, so the button is always visible regardless of screen size changes.
23
+ - e015fdc: Improve agent instructions: add --next auto-claim, blocked task escape hatch, structured bug format, and richer research task guidance.
24
+ - 38c3da6: Normalize literal `\n`, `\t`, `\r` escape sequences in task titles and descriptions at creation time. This fixes agent-created tasks that pass descriptions via CLI args (e.g. `--description "Line 1\nLine 2"`) which previously stored literal backslash-n instead of real newlines.
25
+ - 4e191ff: feat: add Show Vibeflow option to page context menu when badge is hidden
26
+
27
+ When the Vibeflow badge is hidden via the corner trigger's right-click menu,
28
+ it was previously impossible to restore it. Now, right-clicking any page element
29
+ shows a "Show Vibeflow" option in the context menu, allowing users to bring the
30
+ badge back.
31
+
32
+ The hidden state is also persisted to localStorage so it survives page reloads.
33
+
34
+ - 4bbe370: fix: silence opencode stderr when not installed
35
+
36
+ Add `stdio: "pipe"` to all `execSync` calls for opencode commands in
37
+ `server.ts` and `trpc.ts`. Without this option, the OS "command not found"
38
+ error was written to the terminal each time the Kanban board started and
39
+ fetched models/agents — even though the errors were caught and handled.
40
+ Users who don't have opencode installed should see no output about it.
41
+
42
+ ## 0.8.1
43
+
44
+ ### Patch Changes
45
+
46
+ - c917033: Increase kanban multi-select long-press timeout to 750ms with drag cancellation
47
+
3
48
  ## 0.8.0
4
49
 
5
50
  ### Minor Changes
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as V,readFileSync as q,unlinkSync as b,statSync as v,mkdirSync as G,existsSync as c}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as D,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 S(e){return u(e,g,C)}function U(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),r=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),l=u(s,o);if(!f(l))try{F(a,l)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),l=u(t,o);if(!f(l))try{F(a,l)}catch{}}}}function oe(e){U(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function H(e,i,n){let s=S(e);return n?u(s,E(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=S(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){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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,i){let n=u(S(e),E(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}}).trim()}function ae(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??""),description:O(i.description??""),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,s),s}function y(e){try{let i=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let i=S(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 ue(e){return N(e).map(({task:i})=>i)}function le(e){return N(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(L(e,t),s&&s!==H(e,i,t.created))try{D(s)}catch{}return t}function ce(e,i){let n=T(e,i);return n?(D(n),!0):!1}function me(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 fe(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 l of o.text.split(`
5
+ `))t.push(` ${l}`)}}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 l=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.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 de(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(" 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(" 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 o=["--set-status review"];i&&o.push('--commit-message "<one-line summary>"'),s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return 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(" Use --report-file <path> to upload your .md report when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is uploaded to the task and deleted from the local filesystem automatically.")),e.hasBugTasks&&(t.push(" Bug tasks: Include error logs / stack traces in the commit comment."),t.push(" Describe: the symptom, the console error, what triggered it, and how it was fixed.")),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 P=".linked.json";function d(e,i){return m(e,g,k,i)}function Y(e,i){G(d(e,i),{recursive:!0})}function Q(e,i){let n=m(d(e,i),P);if(!c(n))return[];try{return JSON.parse(q(n,"utf-8"))}catch{return[]}}function X(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function $(e,i,n){B(e,i,{files:n})}function x(e,i){let n=X(e,i),s=m(d(e,i),P);if(!c(s))return n;let r=Q(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(l=>l.linkedPath===a.path||l.name===a.name&&l.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,i,t);try{b(s)}catch{}return t}function Z(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(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(c(o)){let a=v(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=v(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 Te(e,i,n,s){let r=R(n);Y(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()}),$(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function be(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($(e,i,r),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&b(l)}return!0}let o=m(d(e,i),s);return c(o)?(b(o),!0):!1}function xe(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&c(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function Ae(e,i){return Z(e,i).length}export{g as a,C as b,A as c,ee as d,M as e,oe as f,H as g,T as h,ae as i,y as j,ue as k,le as l,B as m,ce as n,me as o,fe as p,de as q,d as r,Y as s,Z as t,Te as u,be as v,xe as w,Ae as x};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as V,readFileSync as q,unlinkSync as b,statSync as v,mkdirSync as G,existsSync as c}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as D,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 S(e){return u(e,g,C)}function U(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),r=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),l=u(s,o);if(!f(l))try{F(a,l)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),l=u(t,o);if(!f(l))try{F(a,l)}catch{}}}}function oe(e){U(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function H(e,i,n){let s=S(e);return n?u(s,E(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=S(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){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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,i){let n=u(S(e),E(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 ae(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 L(e,s),s}function y(e){try{let i=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let i=S(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 ue(e){return N(e).map(({task:i})=>i)}function le(e){return N(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(L(e,t),s&&s!==H(e,i,t.created))try{D(s)}catch{}return t}function ce(e,i){let n=T(e,i);return n?(D(n),!0):!1}function me(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 fe(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 l of o.text.split(`
5
+ `))t.push(` ${l}`)}}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 l=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.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 de(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(" 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(" 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 o=["--set-status review"];i&&o.push('--commit-message "<one-line summary>"'),s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return 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(" Use --report-file <path> to upload your .md report when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is uploaded to the task and deleted from the local filesystem automatically.")),e.hasBugTasks&&(t.push(" Bug tasks: Include error logs / stack traces in the commit comment."),t.push(" Describe: the symptom, the console error, what triggered it, and how it was fixed.")),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 P=".linked.json";function d(e,i){return m(e,g,k,i)}function Y(e,i){G(d(e,i),{recursive:!0})}function Q(e,i){let n=m(d(e,i),P);if(!c(n))return[];try{return JSON.parse(q(n,"utf-8"))}catch{return[]}}function X(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function $(e,i,n){B(e,i,{files:n})}function x(e,i){let n=X(e,i),s=m(d(e,i),P);if(!c(s))return n;let r=Q(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(l=>l.linkedPath===a.path||l.name===a.name&&l.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,i,t);try{b(s)}catch{}return t}function Z(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(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(c(o)){let a=v(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=v(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 Te(e,i,n,s){let r=R(n);Y(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()}),$(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function be(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($(e,i,r),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&b(l)}return!0}let o=m(d(e,i),s);return c(o)?(b(o),!0):!1}function xe(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&c(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function Ae(e,i){return Z(e,i).length}export{g as a,C as b,A as c,ee as d,M as e,oe as f,H as g,T as h,O as i,ae as j,y as k,ue as l,le as m,B as n,ce as o,me as p,fe as q,de as r,d as s,Y as t,Z as u,Te as v,be as w,xe as x,Ae as y};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as q,readFileSync as V,unlinkSync as x,statSync as F,mkdirSync as G,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",S="tasks/files",v="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as E,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as K}from"crypto";var j=["backlog","todo","in-progress","review","done"];function M(){return K(15).toString("hex")}function k(e){return u(e,g,C)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(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{A(a,c)}catch{}}}}function oe(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,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){let s=(()=>{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:j.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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type:s,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ae(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.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(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ue(e){return N(e).map(({task:s})=>s)}function ce(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{E(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(E(n),!0):!1}function me(e,s,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},...s&&s.length>0&&{structuredComments:s},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function fe(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),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(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){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=w(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 de(e){let{autoCommit:s,autoPush:n,autoComment:i,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>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(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(""),s&&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."),i&&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 P=".linked.json";function d(e,s){return m(e,g,S,s)}function Y(e,s){G(d(e,s),{recursive:!0})}function Q(e,s){let n=m(d(e,s),P);if(!l(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function X(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function $(e,s,n){B(e,s,{files:n})}function b(e,s){let n=X(e,s),i=m(d(e,s),P);if(!l(i))return n;let r=Q(e,s);if(r.length===0){try{x(i)}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&&$(e,s,t);try{x(i)}catch{}return t}function Z(e,s){let n=d(e,s),i=b(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function Te(e,s,n,i){let r=R(n);Y(e,s),q(m(d(e,s),r),i);let t=b(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),$(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=b(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if($(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&x(c)}return!0}let o=m(d(e,s),i);return l(o)?(x(o),!0):!1}function be(e,s,n){let i=R(n),r=b(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function ve(e,s){return Z(e,s).length}export{g as a,C as b,v as c,ee as d,M as e,oe as f,U as g,T as h,O as i,ae as j,y as k,ue as l,ce as m,B as n,le as o,me as p,fe as q,de as r,d as s,Y as t,Z as u,Te as v,xe as w,be as x,ve as y};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as V,readFileSync as q,unlinkSync as b,statSync as v,mkdirSync as G,existsSync as c}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as D,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 S(e){return u(e,g,C)}function U(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),r=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),l=u(s,o);if(!f(l))try{F(a,l)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),l=u(t,o);if(!f(l))try{F(a,l)}catch{}}}}function oe(e){U(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function H(e,i,n){let s=S(e);return n?u(s,E(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=S(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){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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,i){let n=u(S(e),E(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}}).trim()}function ae(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??""),description:O(i.description??""),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,s),s}function y(e){try{let i=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let i=S(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 ue(e){return N(e).map(({task:i})=>i)}function le(e){return N(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(L(e,t),s&&s!==H(e,i,t.created))try{D(s)}catch{}return t}function ce(e,i){let n=T(e,i);return n?(D(n),!0):!1}function me(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 fe(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 l of o.text.split(`
5
+ `))t.push(` ${l}`)}}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 l=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.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 de(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(" 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(" 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 o=["--set-status review"];i&&o.push('--commit-message "<one-line summary>"'),s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return 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(" Use --report-file <path> to upload your .md report when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is uploaded to the task and deleted from the local filesystem automatically.")),e.hasBugTasks&&(t.push(" Bug tasks: Include error logs / stack traces in the commit comment."),t.push(" Describe: the symptom, the console error, what triggered it, and how it was fixed.")),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 P=".linked.json";function d(e,i){return m(e,g,k,i)}function Y(e,i){G(d(e,i),{recursive:!0})}function Q(e,i){let n=m(d(e,i),P);if(!c(n))return[];try{return JSON.parse(q(n,"utf-8"))}catch{return[]}}function X(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function $(e,i,n){B(e,i,{files:n})}function x(e,i){let n=X(e,i),s=m(d(e,i),P);if(!c(s))return n;let r=Q(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(l=>l.linkedPath===a.path||l.name===a.name&&l.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,i,t);try{b(s)}catch{}return t}function Z(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(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(c(o)){let a=v(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=v(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 Te(e,i,n,s){let r=R(n);Y(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()}),$(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function be(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($(e,i,r),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&b(l)}return!0}let o=m(d(e,i),s);return c(o)?(b(o),!0):!1}function xe(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&c(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function Ae(e,i){return Z(e,i).length}export{g as a,C as b,A as c,ee as d,M as e,oe as f,H as g,T as h,ae as i,y as j,ue as k,le as l,B as m,ce as n,me as o,fe as p,de as q,d as r,Y as s,Z as t,Te as u,be as v,xe as w,Ae as x};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as V,readFileSync as q,unlinkSync as b,statSync as v,mkdirSync as G,existsSync as c}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as D,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 S(e){return u(e,g,C)}function U(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),r=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),l=u(s,o);if(!f(l))try{F(a,l)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),l=u(t,o);if(!f(l))try{F(a,l)}catch{}}}}function oe(e){U(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function H(e,i,n){let s=S(e);return n?u(s,E(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=S(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){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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,i){let n=u(S(e),E(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 ae(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 L(e,s),s}function y(e){try{let i=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let i=S(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 ue(e){return N(e).map(({task:i})=>i)}function le(e){return N(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(L(e,t),s&&s!==H(e,i,t.created))try{D(s)}catch{}return t}function ce(e,i){let n=T(e,i);return n?(D(n),!0):!1}function me(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 fe(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 l of o.text.split(`
5
+ `))t.push(` ${l}`)}}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 l=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.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 de(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(" 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(" 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 o=["--set-status review"];i&&o.push('--commit-message "<one-line summary>"'),s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];s&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return 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(" Use --report-file <path> to upload your .md report when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is uploaded to the task and deleted from the local filesystem automatically.")),e.hasBugTasks&&(t.push(" Bug tasks: Include error logs / stack traces in the commit comment."),t.push(" Describe: the symptom, the console error, what triggered it, and how it was fixed.")),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 P=".linked.json";function d(e,i){return m(e,g,k,i)}function Y(e,i){G(d(e,i),{recursive:!0})}function Q(e,i){let n=m(d(e,i),P);if(!c(n))return[];try{return JSON.parse(q(n,"utf-8"))}catch{return[]}}function X(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function $(e,i,n){B(e,i,{files:n})}function x(e,i){let n=X(e,i),s=m(d(e,i),P);if(!c(s))return n;let r=Q(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(l=>l.linkedPath===a.path||l.name===a.name&&l.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,i,t);try{b(s)}catch{}return t}function Z(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(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(c(o)){let a=v(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=v(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 Te(e,i,n,s){let r=R(n);Y(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()}),$(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function be(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($(e,i,r),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&b(l)}return!0}let o=m(d(e,i),s);return c(o)?(b(o),!0):!1}function xe(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&c(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function Ae(e,i){return Z(e,i).length}export{g as a,C as b,A as c,ee as d,M as e,oe as f,H as g,T as h,O as i,ae as j,y as k,ue as l,le as m,B as n,ce as o,me as p,fe as q,de as r,d as s,Y as t,Z as u,Te as v,be as w,xe as x,Ae as y};
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as J,writeFileSync as q,readFileSync as V,unlinkSync as x,statSync as F,mkdirSync as G,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",S="tasks/files",v="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as E,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as K}from"crypto";var j=["backlog","todo","in-progress","review","done"];function M(){return K(15).toString("hex")}function k(e){return u(e,g,C)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(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{A(a,c)}catch{}}}}function oe(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,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){let s=(()=>{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:j.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?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type:s,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=>({...n,text:n.text??n.content??""})):[],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}}function L(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
3
+ `;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ae(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.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(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ue(e){return N(e).map(({task:s})=>s)}function ce(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{E(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(E(n),!0):!1}function me(e,s,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},...s&&s.length>0&&{structuredComments:s},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function fe(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),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(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){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=w(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 de(e){let{autoCommit:s,autoPush:n,autoComment:i,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>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.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 o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(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(""),s&&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."),i&&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 P=".linked.json";function d(e,s){return m(e,g,S,s)}function Y(e,s){G(d(e,s),{recursive:!0})}function Q(e,s){let n=m(d(e,s),P);if(!l(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function X(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function $(e,s,n){B(e,s,{files:n})}function b(e,s){let n=X(e,s),i=m(d(e,s),P);if(!l(i))return n;let r=Q(e,s);if(r.length===0){try{x(i)}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&&$(e,s,t);try{x(i)}catch{}return t}function Z(e,s){let n=d(e,s),i=b(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function Te(e,s,n,i){let r=R(n);Y(e,s),q(m(d(e,s),r),i);let t=b(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),$(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=b(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if($(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&x(c)}return!0}let o=m(d(e,s),i);return l(o)?(x(o),!0):!1}function be(e,s,n){let i=R(n),r=b(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function ve(e,s){return Z(e,s).length}export{g as a,C as b,v as c,ee as d,M as e,oe as f,U as g,T as h,O as i,ae as j,y as k,ue as l,ce as m,B as n,le as o,me as p,fe as q,de as r,d as s,Y as t,Z as u,Te as v,xe as w,be as x,ve as y};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{s as a,t as b,u as c,v as d,w as e,x as f,y as g}from"./chunk-Y5ZURUI5.js";export{e as deleteFile,b as ensureFilesDir,g as getFileCount,f as getFilePath,a as getFilesDir,c as listFiles,d as saveFile};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{s as a,t as b,u as c,v as d,w as e,x as f,y as g}from"./chunk-TPL7JWD7.js";export{e as deleteFile,b as ensureFilesDir,g as getFileCount,f as getFilePath,a as getFilesDir,c as listFiles,d as saveFile};
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ import{r as a,s as b,t as c,u as d,v as e,w as f,x as g}from"./chunk-7BJ7ARAD.js";export{e as deleteFile,b as ensureFilesDir,g as getFileCount,f as getFilePath,a as getFilesDir,c as listFiles,d as saveFile};