@vibeflow-tools/cli 0.5.0 → 0.6.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 (115) hide show
  1. package/CHANGELOG.md +53 -0
  2. package/dist/chunk-GEQ64RVF.js +7 -0
  3. package/dist/chunk-IUZWZWMW.js +7 -0
  4. package/dist/chunk-NRMCK2HM.js +7 -0
  5. package/dist/chunk-PCPVP4ZD.js +7 -0
  6. package/dist/chunk-XO547RIH.js +7 -0
  7. package/dist/cli/chunk-GEQ64RVF.js +7 -0
  8. package/dist/cli/chunk-IUZWZWMW.js +7 -0
  9. package/dist/cli/chunk-NRMCK2HM.js +7 -0
  10. package/dist/cli/chunk-PCPVP4ZD.js +7 -0
  11. package/dist/cli/chunk-XO547RIH.js +7 -0
  12. package/dist/cli/files-GOVXPMB5.js +2 -0
  13. package/dist/cli/files-LTK2TDC2.js +2 -0
  14. package/dist/cli/files-MEEV7E6V.js +2 -0
  15. package/dist/cli/files-R6YCYMTI.js +2 -0
  16. package/dist/cli/files-SUCOSQAO.js +2 -0
  17. package/dist/cli/index.js +384 -197
  18. package/dist/client/kanban-browser.js +23 -12
  19. package/dist/client/kanban.css +1 -1
  20. package/dist/client/overlay-browser.js +5 -4
  21. package/dist/files-GOVXPMB5.js +2 -0
  22. package/dist/files-LTK2TDC2.js +2 -0
  23. package/dist/files-MEEV7E6V.js +2 -0
  24. package/dist/files-R6YCYMTI.js +2 -0
  25. package/dist/files-SUCOSQAO.js +2 -0
  26. package/dist/index.js +384 -197
  27. package/package.json +7 -2
  28. package/dist/chunk-252RNKHM.js +0 -2
  29. package/dist/chunk-43MUGU6Z.js +0 -67
  30. package/dist/chunk-4Y62J4KR.js +0 -438
  31. package/dist/chunk-6ABTC7IA.js +0 -482
  32. package/dist/chunk-7K2VHAWF.js +0 -569
  33. package/dist/chunk-BKTZSHJS.js +0 -2
  34. package/dist/chunk-BQLZVQ4E.js +0 -2
  35. package/dist/chunk-F57OXWVU.js +0 -33
  36. package/dist/chunk-I2OSZY66.js +0 -803
  37. package/dist/chunk-JKC6MUZ4.js +0 -558
  38. package/dist/chunk-KKBXVPTJ.js +0 -2
  39. package/dist/chunk-LK3IGDR6.js +0 -438
  40. package/dist/chunk-MKOKIWTN.js +0 -569
  41. package/dist/chunk-MW4OS3IK.js +0 -438
  42. package/dist/chunk-NRPOXSY6.js +0 -568
  43. package/dist/chunk-NUM3G22J.js +0 -569
  44. package/dist/chunk-O564QSMS.js +0 -569
  45. package/dist/chunk-OAGEPYIT.js +0 -535
  46. package/dist/chunk-PHBHAIHA.js +0 -33
  47. package/dist/chunk-PK737AKV.js +0 -560
  48. package/dist/chunk-TWAAPROG.js +0 -822
  49. package/dist/chunk-XF2CNPE4.js +0 -803
  50. package/dist/cli/chunk-252RNKHM.js +0 -2
  51. package/dist/cli/chunk-43MUGU6Z.js +0 -67
  52. package/dist/cli/chunk-4Y62J4KR.js +0 -438
  53. package/dist/cli/chunk-6ABTC7IA.js +0 -482
  54. package/dist/cli/chunk-7K2VHAWF.js +0 -569
  55. package/dist/cli/chunk-BKTZSHJS.js +0 -2
  56. package/dist/cli/chunk-BQLZVQ4E.js +0 -2
  57. package/dist/cli/chunk-F57OXWVU.js +0 -33
  58. package/dist/cli/chunk-I2OSZY66.js +0 -803
  59. package/dist/cli/chunk-JKC6MUZ4.js +0 -558
  60. package/dist/cli/chunk-KKBXVPTJ.js +0 -2
  61. package/dist/cli/chunk-LK3IGDR6.js +0 -438
  62. package/dist/cli/chunk-MKOKIWTN.js +0 -569
  63. package/dist/cli/chunk-MW4OS3IK.js +0 -438
  64. package/dist/cli/chunk-NRPOXSY6.js +0 -568
  65. package/dist/cli/chunk-NUM3G22J.js +0 -569
  66. package/dist/cli/chunk-O564QSMS.js +0 -569
  67. package/dist/cli/chunk-OAGEPYIT.js +0 -535
  68. package/dist/cli/chunk-PHBHAIHA.js +0 -33
  69. package/dist/cli/chunk-PK737AKV.js +0 -560
  70. package/dist/cli/chunk-TWAAPROG.js +0 -822
  71. package/dist/cli/chunk-XF2CNPE4.js +0 -803
  72. package/dist/cli/files-27OYPA7W.js +0 -20
  73. package/dist/cli/files-2TK74THO.js +0 -22
  74. package/dist/cli/files-3RDDXUOS.js +0 -2
  75. package/dist/cli/files-7275M2PW.js +0 -20
  76. package/dist/cli/files-D3YPV7QT.js +0 -20
  77. package/dist/cli/files-FER4UZ4X.js +0 -22
  78. package/dist/cli/files-H4FRDKJV.js +0 -22
  79. package/dist/cli/files-IJZVMROA.js +0 -22
  80. package/dist/cli/files-IX5QZQHC.js +0 -2
  81. package/dist/cli/files-KH3UEFN7.js +0 -20
  82. package/dist/cli/files-LTDT5ZFT.js +0 -22
  83. package/dist/cli/files-O4WJLFMU.js +0 -2
  84. package/dist/cli/files-OYO6A6MZ.js +0 -22
  85. package/dist/cli/files-R6QHQBH4.js +0 -22
  86. package/dist/cli/files-UCALOYWZ.js +0 -22
  87. package/dist/cli/files-UWZP7P6B.js +0 -2
  88. package/dist/cli/files-VIDLQM7Y.js +0 -20
  89. package/dist/cli/files-X2RDLF3W.js +0 -22
  90. package/dist/cli/files-XVDNOAZB.js +0 -22
  91. package/dist/cli/workspace-NB6BACZA.js +0 -12
  92. package/dist/cli/workspace-X2NGGGTQ.js +0 -12
  93. package/dist/cli/workspace-X4QXECQQ.js +0 -12
  94. package/dist/files-27OYPA7W.js +0 -20
  95. package/dist/files-2TK74THO.js +0 -22
  96. package/dist/files-3RDDXUOS.js +0 -2
  97. package/dist/files-7275M2PW.js +0 -20
  98. package/dist/files-D3YPV7QT.js +0 -20
  99. package/dist/files-FER4UZ4X.js +0 -22
  100. package/dist/files-H4FRDKJV.js +0 -22
  101. package/dist/files-IJZVMROA.js +0 -22
  102. package/dist/files-IX5QZQHC.js +0 -2
  103. package/dist/files-KH3UEFN7.js +0 -20
  104. package/dist/files-LTDT5ZFT.js +0 -22
  105. package/dist/files-O4WJLFMU.js +0 -2
  106. package/dist/files-OYO6A6MZ.js +0 -22
  107. package/dist/files-R6QHQBH4.js +0 -22
  108. package/dist/files-UCALOYWZ.js +0 -22
  109. package/dist/files-UWZP7P6B.js +0 -2
  110. package/dist/files-VIDLQM7Y.js +0 -20
  111. package/dist/files-X2RDLF3W.js +0 -22
  112. package/dist/files-XVDNOAZB.js +0 -22
  113. package/dist/workspace-NB6BACZA.js +0 -12
  114. package/dist/workspace-X2NGGGTQ.js +0 -12
  115. package/dist/workspace-X4QXECQQ.js +0 -12
package/CHANGELOG.md CHANGED
@@ -1,5 +1,58 @@
1
1
  # Changelog
2
2
 
3
+ ## 0.6.0
4
+
5
+ ### Minor Changes
6
+
7
+ - Add agent queue side panel with button in header
8
+ - Fix agent run: use positional message instead of invalid --task flag, add agent picker, list agents/models endpoints, align Run Agent button right, sync model/agent live updates
9
+ - Implement real agent execution: Run Agent button now spawns opencode with task context via server endpoint. Output streams via WebSocket to the UI. Replaced simulated agent runs with actual opencode process spawning.
10
+
11
+ ### Patch Changes
12
+
13
+ - Add agent session metadata display: capture tokens, cost, and duration from opencode JSON output and show in AgentTab footer.
14
+ - Add minimal agent badge to kanban task cards and detail panel.
15
+
16
+ - TaskCard footer now shows a purple "Agent" pill with Bot icon when `task.agent` is set.
17
+ - KanbanListView rows also display the agent badge inline with the title.
18
+ - TaskDetailsTab metadata section includes an "Agent" tile when present.
19
+ - All styles blend with existing badge sizing (font-size 10, compact padding, purple tint).
20
+
21
+ - Parse opencode JSON events into human-readable text in the agent streaming output.
22
+ - Auto-move task to in-progress status when agent run is started
23
+ - Auto-select default model in Agent tab so "Run Agent" works without user interaction.
24
+ - Add `experimentalAgents` feature flag to gate all agent-related UI features. When disabled (default), the agent tab, agent queue, agent status badges, "Run Agents" multi-select toolbar, and agent settings are hidden from the kanban UI. The flag can be toggled in Settings > Agent.
25
+ - Fix agent run: pass full task context, fix model picker dropdown clicks, and sync default model selection between UI and API request.
26
+ - Fix agent run: replace fake model IDs with real opencode models, add integration test with WebSocket event verification.
27
+ - Fix commit hash display in detail panel: show commit tile when commits array is present even if commit string is absent.
28
+ - Fix experimentalAgents flag to properly hide agent UI by default. Changed all gating conditions from `experimentalAgents !== false` (which evaluated to true when undefined) to `experimentalAgents === true`, ensuring agent features are hidden unless explicitly enabled.
29
+ - Fix model picker dropdown closing detail panel when selecting a model
30
+ - Two fixes for model pickers in the kanban UI:
31
+
32
+ 1. **CLI kanban now parses tRPC response correctly** — the `/trpc/models` endpoint returns `{ result: { data: { models: [...] } } }` but the CLI API client was expecting the inner shape directly. Now unwraps the tRPC envelope.
33
+
34
+ 2. **ModelPicker dropdown no longer clipped by modal** — replaced absolute positioning with a `createPortal` that renders the dropdown at `position: fixed` using measured button coordinates. The dropdown now expands upward above the button and escapes any parent overflow clipping.
35
+
36
+ - Fix sortKey not being accepted when creating tasks via POST /api/tasks, enabling multi-select drag-to-reorder to work correctly.
37
+ - Fix web tRPC models endpoint path: `/api/trpc/settings.models` not `/api/trpc/models`
38
+ - Move "Press Ctrl+C to stop" hint to the end of kanban startup output so it appears after the agent prompt block.
39
+ - Kanban web app now loads models dynamically from OpenCode CLI via tRPC `settings.models` endpoint
40
+ - Move agent action buttons from agent tab body to detail panel footer
41
+ - Fix multi-select drag to compute sort keys incrementally, preserving relative order of selected tasks.
42
+ - Add multi-select drag support: dragging a selected task in select mode moves all selected tasks together.
43
+ - Remove AgentQueueBar from kanban UI — the bottom queue bar is no longer shown.
44
+ - Settings modal Agent tab now uses the same searchable ModelPicker as the AgentTab task agent picker
45
+ - Share agent task formatting between CLI --get and server agent-run endpoint via new `renderTaskForAgent` function.
46
+ - Use default model from settings as initial selection in agent tab
47
+ - Use default model from settings in Agent tab when no model is explicitly chosen. Fixed state disconnect where "Run Agent" passed empty string instead of the displayed default model. CLI kanban now passes defaultModel to DetailPanel.
48
+
49
+ ## 0.5.1
50
+
51
+ ### Patch Changes
52
+
53
+ - de759ff: Include agent workflow instructions in agent run context. Previously, `vibeflow tasks --get` printed CLI instructions but the server agent-run endpoint did not include them in the prompt sent to opencode. Now both entry points share the same `renderAgentInstructions()` formatter, ensuring agents always receive workflow rules, settings flags, and critical constraints.
54
+ - defc6cf: Fix multi-select drag & drop to preserve relative order of selected tasks. Previously, all selected tasks were appended to the column bottom. Now they are inserted at the drop position with correct sort keys computed from the final arrangement. Added e2e Playwright test verifying the behavior.
55
+
3
56
  ## 0.5.0
4
57
 
5
58
  ### Minor Changes
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as U,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as c}from"fs";import{join as m,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as f,readFileSync as O,writeFileSync as _,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 z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(f(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!f(l))try{A(a,l)}catch{}}}if(f(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!f(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0})}function D(e){return e.slice(0,10)}function H(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 o=u(n,i.name,`${s}.json`);if(f(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function K(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:V.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 w(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";_(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return w(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:K(n)}return null}catch{return null}}function L(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return L(e).map(({task:s})=>s)}function ue(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function N(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(w(e,t),i&&i!==H(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 ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&f(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let B of l.split(`
5
+ `))t.push(` \u2502 ${B}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return m(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=m(d(e,s),P);if(!c(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){N(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=m(d(e,s),P);if(!c(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&c(t.linkedPath)){let a=F(t.linkedPath);o.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 r=m(n,t.name);if(c(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of U(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=m(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(m(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=m(d(e,s),i);c(l)&&b(l)}return!0}let r=m(d(e,s),i);return c(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&c(o.linkedPath))return o.linkedPath;let t=m(d(e,s),i);return c(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,H as g,T as h,oe as i,y as j,ae as k,ue as l,N as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as H,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function K(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function U(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:V.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),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:U(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==K(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of H(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,K as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as W,writeFileSync as J,readFileSync as V,unlinkSync as x,statSync as v,mkdirSync as q,existsSync as c}from"fs";import{join as m,basename as P}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",Z="config.json";import{existsSync as f,readFileSync as O,writeFileSync as _,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 z}from"crypto";var j=["backlog","todo","in-progress","review","done"];function H(){return z(15).toString("hex")}function S(e){return u(e,g,C)}function K(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),o=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(s,r);if(!f(l))try{F(a,l)}catch{}}}if(f(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!f(l))try{F(a,l)}catch{}}}}function re(e){K(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function U(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 o=u(n,s.name,`${i}.json`);if(f(o))return o}else if(s.name===`${i}.json`)return u(n,s.name);return null}function M(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: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: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 w(e,i){let n=u(S(e),E(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),o=s+".tmp";_(o,JSON.stringify(i,null,2),"utf-8"),F(o,s)}function oe(e,i){let n=(()=>{let o=(i.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),s={...i,priority:n,id:H(),created:new Date().toISOString(),comments:[],files:[]};return w(e,s),s}function y(e){try{let i=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:M(n)}return null}catch{return null}}function L(e){let i=S(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let o=u(i,s.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(s.name)===".json"){let o=u(i,s.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return L(e).map(({task:i})=>i)}function ue(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function N(e,i,n){let s=T(e,i),o=s?y(s):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(w(e,t),s&&s!==U(e,i,t.created))try{D(s)}catch{}return t}function le(e,i){let n=T(e,i);return n?(D(n),!0):!1}function ce(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 me(e,i,n,s,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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let r of s){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&f(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let B of l.split(`
5
+ `))t.push(` \u2502 ${B}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:i,autoPush:n,autoComment:s,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(" 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:"),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(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];i&&r.push('--commit-message "<one-line summary>"'),s&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];s&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var R=".linked.json";function d(e,i){return m(e,g,k,i)}function G(e,i){q(d(e,i),{recursive:!0})}function Y(e,i){let n=m(d(e,i),R);if(!c(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function Q(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){N(e,i,{files:n})}function b(e,i){let n=Q(e,i),s=m(d(e,i),R);if(!c(s))return n;let o=Y(e,i);if(o.length===0){try{x(s)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&$(e,i,t);try{x(s)}catch{}return t}function X(e,i){let n=d(e,i),s=b(e,i),o=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(t.linkedPath);o.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 r=m(n,t.name);if(c(r)){let a=v(r);o.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 W(n,{withFileTypes:!0})){if(!t.isFile()||t.name===R||o.has(t.name))continue;let r=m(n,t.name),a=v(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function ke(e,i,n,s){let o=P(n);G(e,i),J(m(d(e,i),o),s);let t=b(e,i);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),$(e,i,t)),{name:o,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(o)}`}}function Te(e,i,n){let s=P(n),o=b(e,i),t=o.findIndex(a=>a.name===s);if(t!==-1){let[a]=o.splice(t,1);if($(e,i,o),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&x(l)}return!0}let r=m(d(e,i),s);return c(r)?(x(r),!0):!1}function xe(e,i,n){let s=P(n),o=b(e,i).find(r=>r.name===s&&r.linkedPath);if(o?.linkedPath&&c(o.linkedPath))return o.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function be(e,i){return X(e,i).length}export{g as a,C as b,A as c,Z as d,H as e,re as f,U as g,T as h,oe as i,y as j,ae as k,ue as l,N as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,ke as u,Te as v,xe as w,be as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as U,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function H(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function K(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:V.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),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:K(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==H(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of U(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,H as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as M,writeFileSync as J,readFileSync as K,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function H(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:V.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}}function L(e,s){let n=u(k(e),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:H(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(K(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of M(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),J(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,U as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as U,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as c}from"fs";import{join as m,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as f,readFileSync as O,writeFileSync as _,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 z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(f(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!f(l))try{A(a,l)}catch{}}}if(f(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!f(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0})}function D(e){return e.slice(0,10)}function H(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 o=u(n,i.name,`${s}.json`);if(f(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function K(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:V.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 w(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";_(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return w(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:K(n)}return null}catch{return null}}function L(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return L(e).map(({task:s})=>s)}function ue(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function N(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(w(e,t),i&&i!==H(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 ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&f(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let B of l.split(`
5
+ `))t.push(` \u2502 ${B}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return m(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=m(d(e,s),P);if(!c(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){N(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=m(d(e,s),P);if(!c(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&c(t.linkedPath)){let a=F(t.linkedPath);o.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 r=m(n,t.name);if(c(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(c(n))for(let t of U(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=m(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(m(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=m(d(e,s),i);c(l)&&b(l)}return!0}let r=m(d(e,s),i);return c(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&c(o.linkedPath))return o.linkedPath;let t=m(d(e,s),i);return c(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,H as g,T as h,oe as i,y as j,ae as k,ue as l,N as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as H,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function K(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function U(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:V.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),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:U(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==K(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of H(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,K as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as W,writeFileSync as J,readFileSync as V,unlinkSync as x,statSync as v,mkdirSync as q,existsSync as c}from"fs";import{join as m,basename as P}from"path";var g=".vibeflow",C="tasks",k="tasks/files",A="tasks/screenshots",Z="config.json";import{existsSync as f,readFileSync as O,writeFileSync as _,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 z}from"crypto";var j=["backlog","todo","in-progress","review","done"];function H(){return z(15).toString("hex")}function S(e){return u(e,g,C)}function K(e){let i=u(e,g),n=u(i,"files"),s=u(i,k),o=u(i,"screenshots"),t=u(i,A);if(f(n)){p(s,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(s,r);if(!f(l))try{F(a,l)}catch{}}}if(f(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!f(l))try{F(a,l)}catch{}}}}function re(e){K(e),p(S(e),{recursive:!0}),p(u(e,g,A),{recursive:!0})}function E(e){return e.slice(0,10)}function U(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 o=u(n,s.name,`${i}.json`);if(f(o))return o}else if(s.name===`${i}.json`)return u(n,s.name);return null}function M(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: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: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 w(e,i){let n=u(S(e),E(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),o=s+".tmp";_(o,JSON.stringify(i,null,2),"utf-8"),F(o,s)}function oe(e,i){let n=(()=>{let o=(i.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),s={...i,priority:n,id:H(),created:new Date().toISOString(),comments:[],files:[]};return w(e,s),s}function y(e){try{let i=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:M(n)}return null}catch{return null}}function L(e){let i=S(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let o=u(i,s.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(s.name)===".json"){let o=u(i,s.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return L(e).map(({task:i})=>i)}function ue(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function N(e,i,n){let s=T(e,i),o=s?y(s):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(w(e,t),s&&s!==U(e,i,t.created))try{D(s)}catch{}return t}function le(e,i){let n=T(e,i);return n?(D(n),!0):!1}function ce(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 me(e,i,n,s,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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let r of s){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&f(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let B of l.split(`
5
+ `))t.push(` \u2502 ${B}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:i,autoPush:n,autoComment:s,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(" 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:"),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(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];i&&r.push('--commit-message "<one-line summary>"'),s&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];s&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var R=".linked.json";function d(e,i){return m(e,g,k,i)}function G(e,i){q(d(e,i),{recursive:!0})}function Y(e,i){let n=m(d(e,i),R);if(!c(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function Q(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){N(e,i,{files:n})}function b(e,i){let n=Q(e,i),s=m(d(e,i),R);if(!c(s))return n;let o=Y(e,i);if(o.length===0){try{x(s)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&$(e,i,t);try{x(s)}catch{}return t}function X(e,i){let n=d(e,i),s=b(e,i),o=new Map;for(let t of s){if(t.linkedPath&&c(t.linkedPath)){let a=v(t.linkedPath);o.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 r=m(n,t.name);if(c(r)){let a=v(r);o.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 W(n,{withFileTypes:!0})){if(!t.isFile()||t.name===R||o.has(t.name))continue;let r=m(n,t.name),a=v(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function ke(e,i,n,s){let o=P(n);G(e,i),J(m(d(e,i),o),s);let t=b(e,i);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),$(e,i,t)),{name:o,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(o)}`}}function Te(e,i,n){let s=P(n),o=b(e,i),t=o.findIndex(a=>a.name===s);if(t!==-1){let[a]=o.splice(t,1);if($(e,i,o),a&&!a.linkedPath){let l=m(d(e,i),s);c(l)&&x(l)}return!0}let r=m(d(e,i),s);return c(r)?(x(r),!0):!1}function xe(e,i,n){let s=P(n),o=b(e,i).find(r=>r.name===s&&r.linkedPath);if(o?.linkedPath&&c(o.linkedPath))return o.linkedPath;let t=m(d(e,i),s);return c(t)?t:null}function be(e,i){return X(e,i).length}export{g as a,C as b,A as c,Z as d,H as e,re as f,U as g,T as h,oe as i,y as j,ae as k,ue as l,N as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,ke as u,Te as v,xe as w,be as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as U,writeFileSync as M,readFileSync as J,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function H(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function K(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:V.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),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:K(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==H(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(J(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of U(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),M(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,H as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -0,0 +1,7 @@
1
+ #!/usr/bin/env node
2
+ import{readdirSync as M,writeFileSync as J,readFileSync as K,unlinkSync as b,statSync as F,mkdirSync as q,existsSync as m}from"fs";import{join as f,basename as v}from"path";var g=".vibeflow",$="tasks",S="tasks/files",R="tasks/screenshots",Z="config.json";import{existsSync as c,readFileSync as O,writeFileSync as E,mkdirSync as p,readdirSync as h,unlinkSync as D,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as z}from"crypto";var V=["backlog","todo","in-progress","review","done"];function W(){return z(15).toString("hex")}function k(e){return u(e,g,$)}function j(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),o=u(s,"screenshots"),t=u(s,R);if(c(n)){p(i,{recursive:!0});for(let r of h(n)){let a=u(n,r),l=u(i,r);if(!c(l))try{A(a,l)}catch{}}}if(c(o)){p(t,{recursive:!0});for(let r of h(o)){let a=u(o,r),l=u(t,r);if(!c(l))try{A(a,l)}catch{}}}}function re(e){j(e),p(k(e),{recursive:!0}),p(u(e,g,R),{recursive:!0});let s=u(e,".opencode"),n=u(s,"opencode.json");c(n)||(p(s,{recursive:!0}),E(n,JSON.stringify({$schema:"https://opencode.ai/config.json",plugin:[]},null,2),"utf-8"))}function w(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,w(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!c(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let o=u(n,i.name,`${s}.json`);if(c(o))return o}else if(i.name===`${s}.json`)return u(n,i.name);return null}function H(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:V.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}}function L(e,s){let n=u(k(e),w(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),o=i+".tmp";E(o,JSON.stringify(s,null,2),"utf-8"),A(o,i)}function oe(e,s){let n=(()=>{let o=(s.priority??"").trim().toLowerCase();return o==="critical"?"Critical":o==="high"?"High":o==="low"?"Low":"Medium"})(),i={...s,priority:n,id:W(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=O(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:H(n)}return null}catch{return null}}function N(e){let s=k(e);if(!c(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let o=u(s,i.name);for(let t of h(o))if(I(t)===".json"){let r=u(o,t),a=y(r);a&&n.push({task:a,filePath:r})}}else if(I(i.name)===".json"){let o=u(s,i.name),t=y(o);t&&n.push({task:t,filePath:o})}return n}function ae(e){return N(e).map(({task:s})=>s)}function ue(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),o=i?y(i):null;if(!o)return null;let t={...o,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{D(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(D(n),!0):!1}function ce(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 me(e,s,n,i,o){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 r of e.commits)t.push(` ${r.sha.slice(0,8)} ${r.timestamp} ${r.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 r of e.description.split(`
3
+ `))t.push(` ${r}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let r of n){let a=r.updatedAt?` (edited ${r.updatedAt})`:"";t.push(` [${r.author??"user"}] ${r.createdAt}${a}`);for(let l of r.text.split(`
4
+ `))t.push(` ${l}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let r of i){t.push(` - ${r.name} ${r.url}`);let a=r.linkedPath??u(o,".vibeflow","files",e.id,r.name);if(/\.(md|txt)$/i.test(r.name)&&r.size<1e5&&c(a))try{let l=O(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of l.split(`
5
+ `))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
6
+ `)}function fe(e){let{autoCommit:s,autoPush:n,autoComment:i,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(" 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:"),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>"),s){t.push(" 3. git add <files> (stage your changes first)");let r=["--set-status review"];s&&r.push('--commit-message "<one-line summary>"'),i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let r=["--set-status review"];i&&r.push('--comment "<report>"'),t.push(` 4. vibeflow tasks --edit <id> ${r.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."),o&&(t.push(" [setting] Create branch ON: after ALL tasks in this session are done, create and push a descriptive branch:"),t.push(" git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" git push -u origin HEAD"),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.")),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(`
7
+ `)}var P=".linked.json";function d(e,s){return f(e,g,S,s)}function G(e,s){q(d(e,s),{recursive:!0})}function Y(e,s){let n=f(d(e,s),P);if(!m(n))return[];try{return JSON.parse(K(n,"utf-8"))}catch{return[]}}function Q(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function C(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Q(e,s),i=f(d(e,s),P);if(!m(i))return n;let o=Y(e,s);if(o.length===0){try{b(i)}catch{}return n}let t=n.slice(),r=!1;for(let a of o)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()}),r=!0);r&&C(e,s,t);try{b(i)}catch{}return t}function X(e,s){let n=d(e,s),i=x(e,s),o=new Map;for(let t of i){if(t.linkedPath&&m(t.linkedPath)){let a=F(t.linkedPath);o.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 r=f(n,t.name);if(m(r)){let a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(m(n))for(let t of M(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||o.has(t.name))continue;let r=f(n,t.name),a=F(r);o.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(o.values())}function Se(e,s,n,i){let o=v(n);G(e,s),J(f(d(e,s),o),i);let t=x(e,s);return t.find(r=>r.name===o&&!r.linkedPath)||(t.push({name:o,addedAt:new Date().toISOString()}),C(e,s,t)),{name:o,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(o)}`}}function Te(e,s,n){let i=v(n),o=x(e,s),t=o.findIndex(a=>a.name===i);if(t!==-1){let[a]=o.splice(t,1);if(C(e,s,o),a&&!a.linkedPath){let l=f(d(e,s),i);m(l)&&b(l)}return!0}let r=f(d(e,s),i);return m(r)?(b(r),!0):!1}function be(e,s,n){let i=v(n),o=x(e,s).find(r=>r.name===i&&r.linkedPath);if(o?.linkedPath&&m(o.linkedPath))return o.linkedPath;let t=f(d(e,s),i);return m(t)?t:null}function xe(e,s){return X(e,s).length}export{g as a,$ as b,R as c,Z as d,W as e,re as f,U as g,T as h,oe as i,y as j,ae as k,ue as l,B as m,le as n,ce as o,me as p,fe as q,d as r,G as s,X as t,Se as u,Te as v,be as w,xe as x};
@@ -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-NRMCK2HM.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-XO547RIH.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-IUZWZWMW.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-GEQ64RVF.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-PCPVP4ZD.js";export{e as deleteFile,b as ensureFilesDir,g as getFileCount,f as getFilePath,a as getFilesDir,c as listFiles,d as saveFile};