@vibeflow-tools/cli 0.9.1 → 0.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +143 -23
- package/dist/chunk-2L7GDWKA.js +8 -0
- package/dist/chunk-D4FZTZHO.js +8 -0
- package/dist/chunk-ES3JTCZ7.js +8 -0
- package/dist/chunk-I3WFKPN7.js +8 -0
- package/dist/chunk-PYMUW2HM.js +8 -0
- package/dist/chunk-TCTUG3QV.js +8 -0
- package/dist/chunk-XYZECVJ4.js +8 -0
- package/dist/cli/chunk-2L7GDWKA.js +8 -0
- package/dist/cli/chunk-D4FZTZHO.js +8 -0
- package/dist/cli/chunk-ES3JTCZ7.js +8 -0
- package/dist/cli/chunk-I3WFKPN7.js +8 -0
- package/dist/cli/chunk-PYMUW2HM.js +8 -0
- package/dist/cli/chunk-TCTUG3QV.js +8 -0
- package/dist/cli/chunk-XYZECVJ4.js +8 -0
- package/dist/cli/files-4O3JKNKY.js +2 -0
- package/dist/cli/files-BMMCSJZ3.js +2 -0
- package/dist/cli/files-CZEVX3KX.js +2 -0
- package/dist/cli/files-F2EISWAF.js +2 -0
- package/dist/cli/files-FW2FWYFX.js +2 -0
- package/dist/cli/files-RNEVXCMZ.js +2 -0
- package/dist/cli/files-TGBQRRBH.js +2 -0
- package/dist/cli/index.js +81 -60
- package/dist/client/kanban-browser.js +17 -22
- package/dist/client/kanban.css +1 -1
- package/dist/client/overlay-browser.js +9 -9
- package/dist/files-4O3JKNKY.js +2 -0
- package/dist/files-BMMCSJZ3.js +2 -0
- package/dist/files-CZEVX3KX.js +2 -0
- package/dist/files-F2EISWAF.js +2 -0
- package/dist/files-FW2FWYFX.js +2 -0
- package/dist/files-RNEVXCMZ.js +2 -0
- package/dist/files-TGBQRRBH.js +2 -0
- package/dist/index.js +81 -60
- package/package.json +4 -4
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,128 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.11.0
|
|
4
|
+
|
|
5
|
+
### Minor Changes
|
|
6
|
+
|
|
7
|
+
- abbda12: feat(cli): startup banner always shows a localhost URL alongside the LAN IP
|
|
8
|
+
|
|
9
|
+
When the server is bound to 0.0.0.0, every user-facing URL in the serve and
|
|
10
|
+
kanban startup banners (Kanban board, Task API, /inject guide, overlay script
|
|
11
|
+
tag, File lines, "Kanban board ready") now prints an aligned localhost
|
|
12
|
+
continuation line. Fixes kanban "request timeouts" when the displayed LAN IP
|
|
13
|
+
is unreachable from the local browser. Output is unchanged when bound to a
|
|
14
|
+
single host.
|
|
15
|
+
|
|
16
|
+
- 76d664c: feat(verify): page-wide baseline capture and diff
|
|
17
|
+
|
|
18
|
+
> ⚠️ The `verify` command is experimental and may change without notice.
|
|
19
|
+
|
|
20
|
+
- Capture page-wide baseline at annotation time, store as baseline-page.json
|
|
21
|
+
- Remove baseline from task.json (too large), use file reference instead
|
|
22
|
+
- Enable page-wide diff at verify time (verify-page-diff.json)
|
|
23
|
+
- Add html_query tool for structural HTML changes
|
|
24
|
+
- Back-fill baseline values in verify-all-styles.json for accurate diffs
|
|
25
|
+
|
|
26
|
+
- c3c3fd7: Show the changelog after updates and add a `vibeflow changelog` command.
|
|
27
|
+
|
|
28
|
+
- The update notice in `vibeflow kanban` now prints the newest CHANGELOG section below it; suppress with `--no-changelog`.
|
|
29
|
+
- New `vibeflow changelog [--all]` command prints the latest (or full) changelog to the terminal.
|
|
30
|
+
- Kanban board shows a one-time "What's New" modal after a CLI update and a header **Changelog** button to browse the full changelog at any time.
|
|
31
|
+
|
|
32
|
+
- adac672: feat(verify): page-wide query system with progressive exploration
|
|
33
|
+
|
|
34
|
+
> ⚠️ The `verify` command is experimental and may change without notice.
|
|
35
|
+
|
|
36
|
+
Adds page-wide element capture and query tools for agents to explore verify evidence:
|
|
37
|
+
|
|
38
|
+
- `vibeflow verify style_diff <id>` — summary of all style changes across the page
|
|
39
|
+
- `vibeflow verify style_query <id> <prop>` — ALL elements where a property changed
|
|
40
|
+
- `vibeflow verify html_query <id> children|text|attributes` — structural changes
|
|
41
|
+
- `vibeflow verify element_info <id>` — element details
|
|
42
|
+
|
|
43
|
+
Captures `verify-all-styles.json` with element tree, styles, and structure for every element with classes or data-attributes.
|
|
44
|
+
|
|
45
|
+
### Patch Changes
|
|
46
|
+
|
|
47
|
+
- 5881018: Add verified property to tasks with green VERIFIED badge in kanban UI.
|
|
48
|
+
- 857d597: feat(verify): add agent evidence tools for targeted style/HTML queries
|
|
49
|
+
|
|
50
|
+
> ⚠️ The `verify` command is experimental and may change without notice.
|
|
51
|
+
|
|
52
|
+
Adds four new CLI tools that agents can call to explore verify evidence
|
|
53
|
+
without reading all files (~34K tokens → ~7K tokens):
|
|
54
|
+
|
|
55
|
+
- `vibeflow verify style_query <task-id> <property>` — query specific CSS property
|
|
56
|
+
- `vibeflow verify style_diff <task-id> [--filter <pattern>]` — get changed properties
|
|
57
|
+
- `vibeflow verify element_info <task-id>` — get element details
|
|
58
|
+
- `vibeflow verify html_diff <task-id>` — get HTML changes
|
|
59
|
+
|
|
60
|
+
Also adds tool hints in verify output so agents know what's available.
|
|
61
|
+
|
|
62
|
+
- d0eceb5: fix(kanban): add vertical scrollbar to lanes except Done
|
|
63
|
+
|
|
64
|
+
Lanes now have `overflow-y: auto` so tasks are scrollable when they exceed the viewport height. The Done lane keeps `overflow-y: hidden` since it already limits visible cards to 20.
|
|
65
|
+
|
|
66
|
+
- fix(kanban): What's New changelog modal scrollbar not working
|
|
67
|
+
|
|
68
|
+
The full changelog view (8000+ pixels of content) overflowed the modal without a scrollbar because the scrollable child wasn't constrained by the modal's maxHeight. Fixed by making modal-box a flex column container so children shrink within bounds.
|
|
69
|
+
|
|
70
|
+
- 9085faf: Add Playwright page HTML, screenshot, and element HTML to verify evidence artifacts.
|
|
71
|
+
|
|
72
|
+
> ⚠️ The `verify` command is experimental and may change without notice.
|
|
73
|
+
|
|
74
|
+
- fix(cli): security hardening — XSS, SSRF, open redirects, config crash protection
|
|
75
|
+
|
|
76
|
+
- Sanitize all user data in kanban-template.html with `esc()` and `safeHttpUrl()` helpers; replace `innerHTML=''` clears with `replaceChildren()`
|
|
77
|
+
- Add same-origin guard on kanban file preview to prevent open redirects
|
|
78
|
+
- Validate outbound URL scheme (http/https only) in SaaS client to prevent SSRF
|
|
79
|
+
- Wrap config JSON.parse in try/catch to prevent CLI crash on corrupted config
|
|
80
|
+
- Add SAFETY comments on verified-safe innerHTML usages (renderMarkdown, SVG namespaces)
|
|
81
|
+
|
|
82
|
+
- 3405e3b: Improve verify command output: show evidence file paths and agent instructions instead of generic "Verification passed". Add verify step to agent workflow instructions.
|
|
83
|
+
|
|
84
|
+
> ⚠️ The `verify` command is experimental and may change without notice.
|
|
85
|
+
|
|
86
|
+
## 0.10.0
|
|
87
|
+
|
|
88
|
+
### Minor Changes
|
|
89
|
+
|
|
90
|
+
- 2929354: Add a `vibeflow watch` command that watches the local task store and prints full ticket details whenever a task is newly created or moved back to `todo`.
|
|
91
|
+
|
|
92
|
+
Also includes several hardening and consistency fixes:
|
|
93
|
+
|
|
94
|
+
- tRPC task-ID inputs now enforce the 30-char hex shape, matching the REST API's `isValidTaskId` guard and blocking path-traversal IDs in file/comment endpoints.
|
|
95
|
+
- `tasks --edit` now resolves a unique partial task-ID prefix to the full ID, consistent with `--get` and `--commit`.
|
|
96
|
+
- The login push preview now handles legacy flat `.json` task files in addition to date-based subdirectories.
|
|
97
|
+
|
|
98
|
+
- 98ea6a6: Remove the experimental agent-run feature and its supporting packages.
|
|
99
|
+
|
|
100
|
+
- Delete the `opencode-telegram-bridge` package.
|
|
101
|
+
- Remove the agent-run API endpoints (`/api/agent/run`, `/api/agent/stop`, `/api/agent/agents`, `/api/agent/models`) and the `models` tRPC procedure from the CLI server.
|
|
102
|
+
- Remove the Agent tab, model/agent pickers, agent queue panel, and multi-select (long-press) mode from the kanban UI.
|
|
103
|
+
- Remove agent/model-related settings keys (`defaultModel`, `perTypeModels`, `defaultModelBug/Research/Task`, `defaultAgent`, `experimentalAgents`).
|
|
104
|
+
- Remove `AgentStatus`/`AgentRun` types and the `getModels`/`getAgents` API methods from `@vibeflow-tools/ui`.
|
|
105
|
+
|
|
106
|
+
### Patch Changes
|
|
107
|
+
|
|
108
|
+
- c4b85d4: Add next_actions hints to mutation command JSON output
|
|
109
|
+
|
|
110
|
+
- `tasks --add`: returns next_actions with hints to set status and add description
|
|
111
|
+
- `tasks --next`: returns next_actions with implementation workflow hints
|
|
112
|
+
- `tasks --edit --set-status`: returns context-appropriate next_actions
|
|
113
|
+
- `tasks --commit`: returns next_actions to set review status
|
|
114
|
+
|
|
115
|
+
Human-readable output shows concise → Next: hint lines.
|
|
116
|
+
|
|
117
|
+
- 7c49b56: Add semantic exit codes to the CLI. Instead of always exiting with code 1, the CLI now uses purpose-specific codes: 2 for usage/argument errors, 3 for not-found, 4 for auth failures, and 5 for conflicts. Exit code 1 is reserved for general/unexpected errors.
|
|
118
|
+
- b03bdc7: Add --dry-run, --fields, and structured JSON error output for agent-friendly CLI
|
|
119
|
+
- 9b600ac: Fix the file-upload endpoint documented in `vibeflow --help` and used by the legacy kanban template: the correct route is `POST /api/tasks/<id>/files/<filename>` (path segment), not `?filename=` (query parameter).
|
|
120
|
+
|
|
121
|
+
Also document the `vibeflow watch` command and `vibeflow tasks --next` in the CLI help quick reference and README.
|
|
122
|
+
|
|
123
|
+
- 4a2d8c0: Harden REST API input validation for comments and file uploads to match tRPC validation: add `isValidCommentId` (16-char hex) for all comment endpoints, `isValidFilename` rejecting traversal/control chars for file endpoints, and whitespace-only rejection on comment text.
|
|
124
|
+
- d402441: Harden watch command error handling and tRPC input validation
|
|
125
|
+
|
|
3
126
|
## 0.9.1
|
|
4
127
|
|
|
5
128
|
### Patch Changes
|
|
@@ -168,29 +291,26 @@
|
|
|
168
291
|
|
|
169
292
|
### Patch Changes
|
|
170
293
|
|
|
171
|
-
-
|
|
172
|
-
-
|
|
173
|
-
-
|
|
174
|
-
-
|
|
175
|
-
-
|
|
176
|
-
-
|
|
177
|
-
-
|
|
178
|
-
-
|
|
179
|
-
-
|
|
180
|
-
-
|
|
181
|
-
-
|
|
182
|
-
-
|
|
183
|
-
-
|
|
184
|
-
-
|
|
185
|
-
-
|
|
186
|
-
-
|
|
187
|
-
-
|
|
188
|
-
-
|
|
189
|
-
-
|
|
190
|
-
-
|
|
191
|
-
- 9cd0d82: Validate workspace URL against an allowlist of production domains before using it as the SaaS API base URL, preventing SSRF (SEC-08).
|
|
192
|
-
- 9cd0d82: Serve screenshots through a route handler that validates task ID format instead of an unauthenticated static directory (SEC-05).
|
|
193
|
-
- 9cd0d82: Only trust X-Forwarded-For header for rate limiting when TRUSTED_PROXY=1 env var is set, preventing IP spoofing (SEC-01).
|
|
294
|
+
- Fix task file corruption when multiple processes write simultaneously.
|
|
295
|
+
- Fix potential HTML injection via malformed workspace ID.
|
|
296
|
+
- Fix soft-deleted comments being permanently lost when edited.
|
|
297
|
+
- Fix copilot auth failing silently on some systems.
|
|
298
|
+
- Fix logout not fully clearing workspace data.
|
|
299
|
+
- Reject invalid task status values instead of silently accepting.
|
|
300
|
+
- Fix push command reading tasks from wrong directory in some cases.
|
|
301
|
+
- Fix commit hash display showing wrong commits when multiple projects are open.
|
|
302
|
+
- Fix stale commit data persisting in task objects.
|
|
303
|
+
- Reject unknown settings keys to prevent accidental config corruption.
|
|
304
|
+
- Fix XSS vulnerability in markdown link rendering.
|
|
305
|
+
- Fix comment ID collisions when multiple users comment simultaneously.
|
|
306
|
+
- Fix CLI not running cleanup handlers on login errors.
|
|
307
|
+
- Faster task listing by computing counts from memory instead of disk.
|
|
308
|
+
- Fix copilot config file readable by other users on shared systems.
|
|
309
|
+
- Reject unsupported file types on upload.
|
|
310
|
+
- Block cross-origin mutation requests for security.
|
|
311
|
+
- Fix potential SSRF via malformed workspace URL.
|
|
312
|
+
- Fix screenshots accessible without authentication.
|
|
313
|
+
- Fix rate limiting bypass via spoofed X-Forwarded-For header.
|
|
194
314
|
|
|
195
315
|
## 0.4.1
|
|
196
316
|
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as F,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(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:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type: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=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,i),i}function y(e){try{let s=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:J(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 r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:s})=>s)}function le(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),i&&i!==U(e,s,t.created))try{w(i)}catch{}return t}function me(e,s){let n=T(e,s);return n?(w(n),!0):!1}function fe(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 de(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];s&&a.push('--commit-message "<one-line summary>"'),i&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];i&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var $=".linked.json";function d(e,s){return m(e,g,S,s)}function Q(e,s){Y(d(e,s),{recursive:!0})}function X(e,s){let n=m(d(e,s),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(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=Z(e,s),i=m(d(e,s),$);if(!l(i))return n;let r=X(e,s);if(r.length===0){try{b(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,s,t);try{b(i)}catch{}return t}function ee(e,s){let n=d(e,s),i=x(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,s,n,i){let r=R(n);Q(e,s),V(m(d(e,s),r),i);let t=x(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=x(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if(C(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&b(c)}return!0}let o=m(d(e,s),i);return l(o)?(b(o),!0):!1}function ve(e,s,n){let i=R(n),r=x(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function Ae(e,s){return ee(e,s).length}export{g as a,P as b,S as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Ae as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as F,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",$="tasks",k="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function S(e){return u(e,g,$)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,k),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function ae(e){H(e),p(S(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=S(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=S(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(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:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line!=null?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type: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=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,s){let n=u(S(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,i),i}function y(e){try{let s=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let s=S(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:s})=>s)}function le(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),i&&i!==U(e,s,t.created))try{w(i)}catch{}return t}function me(e,s){let n=T(e,s);return n?(w(n),!0):!1}function fe(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 de(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line!=null?`:${e.line}`:""}${e.col!=null?`:${e.col}`:""}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var C=".linked.json";function d(e,s){return m(e,g,k,s)}function Q(e,s){Y(d(e,s),{recursive:!0})}function X(e,s){let n=m(d(e,s),C);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function P(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Z(e,s),i=m(d(e,s),C);if(!l(i))return n;let r=X(e,s);if(r.length===0){try{b(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&P(e,s,t);try{b(i)}catch{}return t}function ee(e,s){let n=d(e,s),i=x(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===C||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,s,n,i){let r=R(n);Q(e,s),V(m(d(e,s),r),i);let t=x(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),P(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=x(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if(P(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&b(c)}return!0}let o=m(d(e,s),i);return l(o)?(b(o),!0):!1}function ve(e,s,n){let i=R(n),r=x(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function Ae(e,s){return ee(e,s).length}export{g as a,$ as b,k as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Ae as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as J,writeFileSync as q,readFileSync as V,unlinkSync as x,statSync as F,mkdirSync as G,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",S="tasks/files",v="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as E,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,C)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function oe(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){let s=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line!=null?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type:s,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>({...n,text:n.text??n.content??""})):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0}}function L(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ae(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ue(e){return N(e).map(({task:s})=>s)}function ce(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{E(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(E(n),!0):!1}function me(e,s,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...s&&s.length>0&&{structuredComments:s},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function fe(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line!=null?`:${e.line}`:""}${e.col!=null?`:${e.col}`:""}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function de(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var P=".linked.json";function d(e,s){return m(e,g,S,s)}function Y(e,s){G(d(e,s),{recursive:!0})}function Q(e,s){let n=m(d(e,s),P);if(!l(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function X(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function $(e,s,n){B(e,s,{files:n})}function b(e,s){let n=X(e,s),i=m(d(e,s),P);if(!l(i))return n;let r=Q(e,s);if(r.length===0){try{x(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,s,t);try{x(i)}catch{}return t}function Z(e,s){let n=d(e,s),i=b(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function Te(e,s,n,i){let r=R(n);Y(e,s),q(m(d(e,s),r),i);let t=b(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),$(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=b(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if($(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&x(c)}return!0}let o=m(d(e,s),i);return l(o)?(x(o),!0):!1}function be(e,s,n){let i=R(n),r=b(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function ve(e,s){return Z(e,s).length}export{g as a,C as b,S as c,v as d,ee as e,M as f,oe as g,U as h,T as i,O as j,ae as k,y as l,ue as m,ce as n,B as o,le as p,me as q,fe as r,de as s,d as t,Y as u,Z as v,Te as w,xe as x,be as y,ve as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as F,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let i=u(e,g),n=u(i,"files"),s=u(i,S),r=u(i,"screenshots"),t=u(i,v);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(s,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,i,n){let s=k(e);return n?u(s,D(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=k(e);if(!f(n))return null;for(let s of h(n,{withFileTypes:!0}))if(s.isDirectory()){let r=u(n,s.name,`${i}.json`);if(f(r))return r}else if(s.name===`${i}.json`)return u(n,s.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,i){let n=u(k(e),D(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),r=s+".tmp";z(r,JSON.stringify(i,null,2),"utf-8"),A(r,s)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,i){let n=(()=>{let r=(i.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),s={...i,title:O(i.title??"").trim(),description:O(i.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,s),s}function y(e){try{let i=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let i=k(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let r=u(i,s.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(s.name)===".json"){let r=u(i,s.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:i})=>i)}function le(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function B(e,i,n){let s=T(e,i),r=s?y(s):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),s&&s!==U(e,i,t.created))try{w(s)}catch{}return t}function me(e,i){let n=T(e,i);return n?(w(n),!0):!1}function fe(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function de(e,i,n,s,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let o of s){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:i,autoPush:n,autoComment:s,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),i){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),s&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),s&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var $=".linked.json";function d(e,i){return m(e,g,S,i)}function Q(e,i){Y(d(e,i),{recursive:!0})}function X(e,i){let n=m(d(e,i),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function C(e,i,n){B(e,i,{files:n})}function x(e,i){let n=Z(e,i),s=m(d(e,i),$);if(!l(s))return n;let r=X(e,i);if(r.length===0){try{b(s)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,i,t);try{b(s)}catch{}return t}function ee(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,i,n,s){let r=R(n);Q(e,i),V(m(d(e,i),r),s);let t=x(e,i);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function xe(e,i,n){let s=R(n),r=x(e,i),t=r.findIndex(a=>a.name===s);if(t!==-1){let[a]=r.splice(t,1);if(C(e,i,r),a&&!a.linkedPath){let c=m(d(e,i),s);l(c)&&b(c)}return!0}let o=m(d(e,i),s);return l(o)?(b(o),!0):!1}function ve(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return l(t)?t:null}function Ae(e,i){return ee(e,i).length}export{g as a,P as b,S as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Ae as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as A,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as F}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let i=u(e,g),n=u(i,"files"),s=u(i,S),r=u(i,"screenshots"),t=u(i,v);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(s,o);if(!f(c))try{F(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{F(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,i,n){let s=k(e);return n?u(s,D(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=k(e);if(!f(n))return null;for(let s of h(n,{withFileTypes:!0}))if(s.isDirectory()){let r=u(n,s.name,`${i}.json`);if(f(r))return r}else if(s.name===`${i}.json`)return u(n,s.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,i){let n=u(k(e),D(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),r=s+".tmp";z(r,JSON.stringify(i,null,2),"utf-8"),F(r,s)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,i){let n=(()=>{let r=(i.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),s={...i,title:O(i.title??"").trim(),description:O(i.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,s),s}function y(e){try{let i=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let i=k(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let r=u(i,s.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(s.name)===".json"){let r=u(i,s.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:i})=>i)}function le(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function B(e,i,n){let s=T(e,i),r=s?y(s):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),s&&s!==U(e,i,t.created))try{w(s)}catch{}return t}function me(e,i){let n=T(e,i);return n?(w(n),!0):!1}function fe(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function de(e,i,n,s,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let o of s){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:i,autoPush:n,autoComment:s,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),i){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),s&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),s&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var $=".linked.json";function d(e,i){return m(e,g,S,i)}function Q(e,i){Y(d(e,i),{recursive:!0})}function X(e,i){let n=m(d(e,i),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function C(e,i,n){B(e,i,{files:n})}function x(e,i){let n=Z(e,i),s=m(d(e,i),$);if(!l(s))return n;let r=X(e,i);if(r.length===0){try{b(s)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,i,t);try{b(s)}catch{}return t}function ee(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&l(t.linkedPath)){let a=A(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,i,n,s){let r=R(n);Q(e,i),V(m(d(e,i),r),s);let t=x(e,i);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function xe(e,i,n){let s=R(n),r=x(e,i),t=r.findIndex(a=>a.name===s);if(t!==-1){let[a]=r.splice(t,1);if(C(e,i,r),a&&!a.linkedPath){let c=m(d(e,i),s);l(c)&&b(c)}return!0}let o=m(d(e,i),s);return l(o)?(b(o),!0):!1}function ve(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return l(t)?t:null}function Fe(e,i){return ee(e,i).length}export{g as a,P as b,S as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Fe as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as A,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as F}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let i=u(e,g),n=u(i,"files"),s=u(i,S),r=u(i,"screenshots"),t=u(i,v);if(f(n)){p(s,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(s,o);if(!f(c))try{F(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{F(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,i,n){let s=k(e);return n?u(s,D(n),`${i}.json`):u(s,`${i}.json`)}function T(e,i){let n=k(e);if(!f(n))return null;for(let s of h(n,{withFileTypes:!0}))if(s.isDirectory()){let r=u(n,s.name,`${i}.json`);if(f(r))return r}else if(s.name===`${i}.json`)return u(n,s.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(e){let i=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type:i,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,verified:e.verified===!0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,i){let n=u(k(e),D(i.created));p(n,{recursive:!0});let s=u(n,`${i.id}.json`),r=s+".tmp";z(r,JSON.stringify(i,null,2),"utf-8"),F(r,s)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(i,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,i){let n=(()=>{let r=(i.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),s={...i,title:O(i.title??"").trim(),description:O(i.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,s),s}function y(e){try{let i=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(i);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let i=k(e);if(!f(i))return[];let n=[];for(let s of h(i,{withFileTypes:!0}))if(s.isDirectory()){let r=u(i,s.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(s.name)===".json"){let r=u(i,s.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:i})=>i)}function le(e){return L(e).map(({task:i,filePath:n})=>({...i,filePath:n}))}function B(e,i,n){let s=T(e,i),r=s?y(s):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),s&&s!==U(e,i,t.created))try{w(s)}catch{}return t}function me(e,i){let n=T(e,i);return n?(w(n),!0):!1}function fe(e,i,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...i&&i.length>0&&{structuredComments:i},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function de(e,i,n,s,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${i}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(s.length>0){t.push(` linked files (${s.length}):`);for(let o of s){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:i,autoPush:n,autoComment:s,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),i){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];i&&a.push('--commit-message "<one-line summary>"'),s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];s&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),s&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),i&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),s&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var $=".linked.json";function d(e,i){return m(e,g,S,i)}function Q(e,i){Y(d(e,i),{recursive:!0})}function X(e,i){let n=m(d(e,i),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,i){let n=T(e,i),s=n?y(n):null;return!s?.files||s.files.length===0?[]:s.files}function C(e,i,n){B(e,i,{files:n})}function x(e,i){let n=Z(e,i),s=m(d(e,i),$);if(!l(s))return n;let r=X(e,i);if(r.length===0){try{b(s)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,i,t);try{b(s)}catch{}return t}function ee(e,i){let n=d(e,i),s=x(e,i),r=new Map;for(let t of s){if(t.linkedPath&&l(t.linkedPath)){let a=A(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=A(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${i}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,i,n,s){let r=R(n);Q(e,i),V(m(d(e,i),r),s);let t=x(e,i);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,i,t)),{name:r,size:s.length,url:`/api/tasks/${i}/files/${encodeURIComponent(r)}`}}function xe(e,i,n){let s=R(n),r=x(e,i),t=r.findIndex(a=>a.name===s);if(t!==-1){let[a]=r.splice(t,1);if(C(e,i,r),a&&!a.linkedPath){let c=m(d(e,i),s);l(c)&&b(c)}return!0}let o=m(d(e,i),s);return l(o)?(b(o),!0):!1}function ve(e,i,n){let s=R(n),r=x(e,i).find(o=>o.name===s&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,i),s);return l(t)?t:null}function Fe(e,i){return ee(e,i).length}export{g as a,P as b,v as c,te as d,M as e,ae as f,U as g,T as h,O as i,ue as j,y as k,ce as l,le as m,B as n,me as o,fe as p,de as q,ge as r,d as s,Q as t,ee as u,be as v,xe as w,ve as x,Fe as y};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as J,writeFileSync as q,readFileSync as V,unlinkSync as x,statSync as F,mkdirSync as G,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",C="tasks",S="tasks/files",v="tasks/screenshots",ee="config.json";import{existsSync as f,readFileSync as w,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as E,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as K}from"crypto";var j=["backlog","todo","in-progress","review","done"];function M(){return K(15).toString("hex")}function k(e){return u(e,g,C)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function oe(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){let s=(()=>{if(typeof e.type!="string")return;let n=e.type.trim();if(!(!n||n==="[object Object]"))return n})();return{id:String(e.id??""),title:String(e.title??"Untitled"),description:String(e.description??""),status:j.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line!=null?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type:s,priority:e.priority?String(e.priority):void 0,...e.reportBack===!0&&{reportBack:!0},agent:e.agent?String(e.agent):void 0,model:e.model?String(e.model):void 0,author:e.author?String(e.author):void 0,commits:Array.isArray(e.commits)?e.commits.map(n=>({sha:String(n.sha??""),message:String(n.message??""),timestamp:String(n.timestamp??new Date().toISOString())})):void 0,created:String(e.created??new Date().toISOString()),updated:e.updated?String(e.updated):void 0,comments:Array.isArray(e.comments)?e.comments.map(n=>({...n,text:n.text??n.content??""})):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0}}function L(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ae(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return L(e,i),i}function y(e){try{let s=w(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:W(n)}return null}catch{return null}}function N(e){let s=k(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ue(e){return N(e).map(({task:s})=>s)}function ce(e){return N(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(L(e,t),i&&i!==U(e,s,t.created))try{E(i)}catch{}return t}function le(e,s){let n=T(e,s);return n?(E(n),!0):!1}function me(e,s,n){return{id:e.id,status:e.status,title:e.title,description:e.description,...e.url&&{url:e.url},selector:e.selector,...e.file&&{file:e.file},...e.line!=null&&{line:e.line},...e.col!=null&&{col:e.col},...e.component&&{component:e.component},...e.type&&{type:e.type},...e.priority&&{priority:e.priority},...s&&s.length>0&&{structuredComments:s},...n&&n.length>0&&{linkedFiles:n},...e.reportBack&&{reportBack:!0},created:e.created}}function fe(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line!=null?`:${e.line}`:""}${e.col!=null?`:${e.col}`:""}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=w(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function de(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var P=".linked.json";function d(e,s){return m(e,g,S,s)}function Y(e,s){G(d(e,s),{recursive:!0})}function Q(e,s){let n=m(d(e,s),P);if(!l(n))return[];try{return JSON.parse(V(n,"utf-8"))}catch{return[]}}function X(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function $(e,s,n){B(e,s,{files:n})}function b(e,s){let n=X(e,s),i=m(d(e,s),P);if(!l(i))return n;let r=Q(e,s);if(r.length===0){try{x(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&$(e,s,t);try{x(i)}catch{}return t}function Z(e,s){let n=d(e,s),i=b(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of J(n,{withFileTypes:!0})){if(!t.isFile()||t.name===P||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function Te(e,s,n,i){let r=R(n);Y(e,s),q(m(d(e,s),r),i);let t=b(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),$(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=b(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if($(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&x(c)}return!0}let o=m(d(e,s),i);return l(o)?(x(o),!0):!1}function be(e,s,n){let i=R(n),r=b(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function ve(e,s){return Z(e,s).length}export{g as a,C as b,S as c,v as d,ee as e,M as f,oe as g,U as h,T as i,O as j,ae as k,y as l,ue as m,ce as n,B as o,le as p,me as q,fe as r,de as s,d as t,Y as u,Z as v,Te as w,xe as x,be as y,ve as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as F,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",P="tasks",S="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function k(e){return u(e,g,P)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,S),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function ae(e){H(e),p(k(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=k(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=k(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(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:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line==null?void 0:Number(e.line),col:e.col==null?void 0:Number(e.col),component:e.component?String(e.component):void 0,type: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=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,s){let n=u(k(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,i),i}function y(e){try{let s=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:J(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 r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:s})=>s)}function le(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),i&&i!==U(e,s,t.created))try{w(i)}catch{}return t}function me(e,s){let n=T(e,s);return n?(w(n),!0):!1}function fe(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 de(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line==null?"":`:${e.line}`}${e.col==null?"":`:${e.col}`}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let a=["--set-status review"];s&&a.push('--commit-message "<one-line summary>"'),i&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let a=["--set-status review"];i&&a.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${a.join(" ")}`)}let o=r?"6":"5";return t.push(` ${o}. vibeflow verify <id> (verify the fix \u2014 check the evidences it produces)`),t.push(" If verification fails, set task back to in-progress and fix."),i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var $=".linked.json";function d(e,s){return m(e,g,S,s)}function Q(e,s){Y(d(e,s),{recursive:!0})}function X(e,s){let n=m(d(e,s),$);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(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=Z(e,s),i=m(d(e,s),$);if(!l(i))return n;let r=X(e,s);if(r.length===0){try{b(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&C(e,s,t);try{b(i)}catch{}return t}function ee(e,s){let n=d(e,s),i=x(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===$||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,s,n,i){let r=R(n);Q(e,s),V(m(d(e,s),r),i);let t=x(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),C(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=x(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if(C(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&b(c)}return!0}let o=m(d(e,s),i);return l(o)?(b(o),!0):!1}function ve(e,s,n){let i=R(n),r=x(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function Ae(e,s){return ee(e,s).length}export{g as a,P as b,S as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Ae as z};
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
import{readdirSync as q,writeFileSync as V,readFileSync as G,unlinkSync as b,statSync as F,mkdirSync as Y,existsSync as l}from"fs";import{join as m,basename as R}from"path";var g=".vibeflow",$="tasks",k="tasks/files",v="tasks/screenshots",te="config.json";import{existsSync as f,readFileSync as E,writeFileSync as z,mkdirSync as p,readdirSync as h,unlinkSync as w,renameSync as A}from"fs";import{join as u,extname as I}from"path";import{randomBytes as j}from"crypto";var K=["backlog","todo","in-progress","review","done"];function M(){return j(15).toString("hex")}function S(e){return u(e,g,$)}function H(e){let s=u(e,g),n=u(s,"files"),i=u(s,k),r=u(s,"screenshots"),t=u(s,v);if(f(n)){p(i,{recursive:!0});for(let o of h(n)){let a=u(n,o),c=u(i,o);if(!f(c))try{A(a,c)}catch{}}}if(f(r)){p(t,{recursive:!0});for(let o of h(r)){let a=u(r,o),c=u(t,o);if(!f(c))try{A(a,c)}catch{}}}}function ae(e){H(e),p(S(e),{recursive:!0}),p(u(e,g,v),{recursive:!0})}function D(e){return e.slice(0,10)}function U(e,s,n){let i=S(e);return n?u(i,D(n),`${s}.json`):u(i,`${s}.json`)}function T(e,s){let n=S(e);if(!f(n))return null;for(let i of h(n,{withFileTypes:!0}))if(i.isDirectory()){let r=u(n,i.name,`${s}.json`);if(f(r))return r}else if(i.name===`${s}.json`)return u(n,i.name);return null}function W(e){return{...e,text:e.text??e.content??""}}function J(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:K.includes(e.status)?e.status:"todo",url:e.url?String(e.url):void 0,selector:(()=>{let n=String(e.selector??"/");return e.file&&!e.cssSelector&&n.startsWith(String(e.file))?e.url?String(e.url):"/":n})(),cssSelector:e.cssSelector&&String(e.cssSelector)!==String(e.selector??"/")?String(e.cssSelector):void 0,file:e.file?String(e.file):void 0,line:e.line!=null?Number(e.line):void 0,col:e.col!=null?Number(e.col):void 0,component:e.component?String(e.component):void 0,type: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=>W(n)):[],files:Array.isArray(e.files)?e.files.map(n=>typeof n=="string"?{name:n,addedAt:new Date().toISOString()}:{name:String(n.name??""),addedAt:String(n.addedAt??new Date().toISOString()),linkedPath:n.linkedPath?String(n.linkedPath):void 0,mimeType:n.mimeType?String(n.mimeType):void 0}).filter(n=>n.name):[],screenshot:e.screenshot?String(e.screenshot):void 0,annotatedElementText:e.annotatedElementText?String(e.annotatedElementText):void 0,tags:Array.isArray(e.tags)?e.tags.filter(n=>typeof n=="string"&&n.length>0):void 0,sortKey:e.sortKey?String(e.sortKey):void 0,branchName:e.branchName?String(e.branchName):void 0,baseline:e.baseline&&typeof e.baseline=="object"?e.baseline:void 0,authStateEnc:e.authStateEnc?String(e.authStateEnc):void 0}}function N(e,s){let n=u(S(e),D(s.created));p(n,{recursive:!0});let i=u(n,`${s.id}.json`),r=i+".tmp";z(r,JSON.stringify(s,null,2),"utf-8"),A(r,i)}function O(e){return e.replace(/\\(n|t|r|\\)/g,(s,n)=>{switch(n){case"n":return`
|
|
3
|
+
`;case"t":return" ";case"r":return"\r";case"\\":return"\\";default:return n}})}function ue(e,s){let n=(()=>{let r=(s.priority??"").trim().toLowerCase();return r==="critical"?"Critical":r==="high"?"High":r==="low"?"Low":"Medium"})(),i={...s,title:O(s.title??"").trim(),description:O(s.description??"").trim(),priority:n,id:M(),created:new Date().toISOString(),comments:[],files:[]};return N(e,i),i}function y(e){try{let s=E(e,"utf-8");if(e.endsWith(".json")){let n=JSON.parse(s);return!n||typeof n!="object"||!("id"in n)?null:J(n)}return null}catch{return null}}function L(e){let s=S(e);if(!f(s))return[];let n=[];for(let i of h(s,{withFileTypes:!0}))if(i.isDirectory()){let r=u(s,i.name);for(let t of h(r))if(I(t)===".json"){let o=u(r,t),a=y(o);a&&n.push({task:a,filePath:o})}}else if(I(i.name)===".json"){let r=u(s,i.name),t=y(r);t&&n.push({task:t,filePath:r})}return n}function ce(e){return L(e).map(({task:s})=>s)}function le(e){return L(e).map(({task:s,filePath:n})=>({...s,filePath:n}))}function B(e,s,n){let i=T(e,s),r=i?y(i):null;if(!r)return null;let t={...r,...n,updated:new Date().toISOString()};if(N(e,t),i&&i!==U(e,s,t.created))try{w(i)}catch{}return t}function me(e,s){let n=T(e,s);return n?(w(n),!0):!1}function fe(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 de(e,s,n,i,r){let t=[];if(t.push(`[${e.status}] ${e.title}`),t.push(` id: ${e.id}`),t.push(` file: ${s}`),e.file&&t.push(` source: ${e.file}${e.line!=null?`:${e.line}`:""}${e.col!=null?`:${e.col}`:""}`),e.component&&t.push(` component: ${e.component}`),t.push(` selector: ${e.selector??"/"}`),e.cssSelector&&t.push(` css: ${e.cssSelector}`),e.url&&t.push(` url: ${e.url}`),e.commits&&e.commits.length>0)if(e.commits.length===1)t.push(` commit: ${e.commits[0].sha}`);else{t.push(` commits (${e.commits.length}):`);for(let o of e.commits)t.push(` ${o.sha.slice(0,8)} ${o.timestamp} ${o.message.slice(0,60)}`)}if(t.push(` created: ${e.created}`),e.type&&t.push(` type: ${e.type}`),e.priority&&t.push(` priority: ${e.priority}`),e.author&&t.push(` author: ${e.author}`),e.description){t.push(" description:");for(let o of e.description.split(`
|
|
4
|
+
`))t.push(` ${o}`)}if(e.annotatedElementText&&t.push(` element text: ${e.annotatedElementText}`),n.length>0){t.push(` comments (${n.length}):`);for(let o of n){let a=o.updatedAt?` (edited ${o.updatedAt})`:"";t.push(` [${o.author??"user"}] ${o.createdAt}${a}`);for(let c of o.text.split(`
|
|
5
|
+
`))t.push(` ${c}`)}}if(i.length>0){t.push(` linked files (${i.length}):`);for(let o of i){t.push(` - ${o.name} ${o.url}`);let a=o.linkedPath??u(r,".vibeflow","files",e.id,o.name);if(/\.(md|txt)$/i.test(o.name)&&o.size<1e5&&f(a))try{let c=E(a,"utf-8");t.push(" \u250C\u2500\u2500 content \u2500\u2500");for(let _ of c.split(`
|
|
6
|
+
`))t.push(` \u2502 ${_}`);t.push(" \u2514\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500")}catch{}}}return t.join(`
|
|
7
|
+
`)}function ge(e){let{autoCommit:s,autoPush:n,autoComment:i,createBranch:r}=e,t=[];if(t.push("Agent instructions (concise):"),t.push(" Discover: vibeflow tasks --status todo | vibeflow tasks --type Research | vibeflow tasks --user <email> | vibeflow tasks --tag <tag>"),t.push(" Auto-claim: vibeflow tasks --next (picks highest-priority todo task and sets it in-progress automatically)"),t.push(" Details: vibeflow tasks --get <id> (full task info with comments and files)"),t.push(' Create: vibeflow tasks --add --title "..." --description "..."'),t.push(""),t.push(" Workflow:"),r?(t.push(" \u26A0 Create a branch FIRST, before any implementation:"),t.push(" 1. git checkout -b <short-name> (e.g. fix/annotation-errors, feat/eye-toggle, chore/cleanup-extension)"),t.push(" Branch name rules: lowercase, kebab-case, 2-5 words, prefix fix/feat/chore/docs."),t.push(" Describe the WORK done (not dates). Bad: agent/2026-04-16. Good: fix/bug-errors-visibility."),t.push(" 2. vibeflow tasks --edit <id> --set-status in-progress \u2190 CLAIM TASK"),t.push(" 3. <implement the change>")):(t.push(" \u26A0 IMMEDIATELY set in-progress BEFORE any implementation work:"),t.push(" 1. vibeflow tasks --edit <id> --set-status in-progress \u2190 DO THIS FIRST"),t.push(" (if you used --next: task is already in-progress \u2014 skip to step 2)"),t.push(" 2. <implement the change>")),s){t.push(r?" 4. git add <files> (stage your changes first)":" 3. git add <files> (stage your changes first)");let o=["--set-status review"];s&&o.push('--commit-message "<one-line summary>"'),i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`),t.push(" CLI will commit staged changes and link the commit SHA automatically.")}else{t.push(r?' 4. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"':' 3. git add <files> && vibeflow tasks --commit --task <id> --message "<one-line summary>"');let o=["--set-status review"];i&&o.push('--comment "<report>"'),t.push(` ${r?"5":"4"}. vibeflow tasks --edit <id> ${o.join(" ")}`)}return i&&(t.push(""),t.push(" Comment format (--comment):"),t.push(" \xB7 Plain text for concise one-liners."),t.push(" \xB7 Markdown for multi-section reports. Use **bold**, bullet lists, code fences."),t.push(" \xB7 Must cover: what changed, why, key decisions, anything future agents should know."),t.push(" \xB7 For long reports, attach a .md file and reference it in the comment.")),t.push(""),s&&t.push(" [setting] Auto-commit ON: provide --commit-message when setting status to review; CLI commits."),n&&t.push(" [setting] Auto-push ON: CLI pushes after the commit automatically."),i&&t.push(" [setting] Auto-comment ON: --comment is required when setting status to review."),r&&t.push(" [setting] Create branch ON: all work goes on a dedicated branch created before implementation."),e.hasResearchTasks&&(t.push(" Research tasks: NEVER generate code \u2014 research only."),t.push(" Attach a .md report before marking Research tasks as review."),t.push(" CLI ENFORCES: cannot mark Research as review without an attached .md report."),t.push(" Create the report file locally first, then upload when marking as review:"),t.push(' vibeflow tasks --edit <id> --set-status review --report-file ./report.md --comment "..."'),t.push(" The file is saved next to the task and deleted from the original path automatically."),t.push(" Report must include: findings, options considered (with pros/cons), recommendation, sources.")),e.hasBugTasks&&(t.push(" Bug tasks: Reproduce the bug first, then include in the comment:"),t.push(" \xB7 Symptom: what the user sees"),t.push(" \xB7 Trigger: exact steps to reproduce"),t.push(" \xB7 Root cause: the specific code/logic that caused it"),t.push(" \xB7 Fix: what was changed and why it works"),t.push(" \xB7 Evidence: paste the relevant error message or stack trace")),t.push(" BLOCKED? If a task is unclear or missing context:"),t.push(' vibeflow tasks --edit <id> --comment "Blocked: <reason>. Need: <what is needed>."'),t.push(" Then pick the next task: vibeflow tasks --next"),t.push(" Do not guess at unclear requirements \u2014 leave a comment and move on."),t.push(" CRITICAL: NEVER edit .vibeflow/ task files directly."),t.push(" All task operations (status, comments, commits) must go through CLI commands."),t.push(" CRITICAL: Set in-progress BEFORE reading/planning. Other agents may pick the same task."),t.push(" The in-progress transition signals ownership. Skip it and another agent may duplicate your work."),t.push(" Sequence: discover tasks \u2192 pick one \u2192 set in-progress \u2192 THEN read details and implement."),t.push(' CRITICAL: NEVER set a task status to "done".'),t.push(' When your implementation is complete, set the status to "review" \u2014 not "done".'),t.push(" Only humans can mark tasks as done after reviewing the work."),t.push(" The CLI will warn you and still allow the change \u2014 but agents must not use it."),t.push(""),t.join(`
|
|
8
|
+
`)}var C=".linked.json";function d(e,s){return m(e,g,k,s)}function Q(e,s){Y(d(e,s),{recursive:!0})}function X(e,s){let n=m(d(e,s),C);if(!l(n))return[];try{return JSON.parse(G(n,"utf-8"))}catch{return[]}}function Z(e,s){let n=T(e,s),i=n?y(n):null;return!i?.files||i.files.length===0?[]:i.files}function P(e,s,n){B(e,s,{files:n})}function x(e,s){let n=Z(e,s),i=m(d(e,s),C);if(!l(i))return n;let r=X(e,s);if(r.length===0){try{b(i)}catch{}return n}let t=n.slice(),o=!1;for(let a of r)t.find(c=>c.linkedPath===a.path||c.name===a.name&&c.linkedPath)||(t.push({name:a.name,linkedPath:a.path,addedAt:new Date().toISOString()}),o=!0);o&&P(e,s,t);try{b(i)}catch{}return t}function ee(e,s){let n=d(e,s),i=x(e,s),r=new Map;for(let t of i){if(t.linkedPath&&l(t.linkedPath)){let a=F(t.linkedPath);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,linkedPath:t.linkedPath,createdAt:a.mtime.toISOString()});continue}let o=m(n,t.name);if(l(o)){let a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}}if(l(n))for(let t of q(n,{withFileTypes:!0})){if(!t.isFile()||t.name===C||r.has(t.name))continue;let o=m(n,t.name),a=F(o);r.set(t.name,{name:t.name,size:a.size,url:`/api/tasks/${s}/files/${encodeURIComponent(t.name)}`,createdAt:a.mtime.toISOString()})}return Array.from(r.values())}function be(e,s,n,i){let r=R(n);Q(e,s),V(m(d(e,s),r),i);let t=x(e,s);return t.find(o=>o.name===r&&!o.linkedPath)||(t.push({name:r,addedAt:new Date().toISOString()}),P(e,s,t)),{name:r,size:i.length,url:`/api/tasks/${s}/files/${encodeURIComponent(r)}`}}function xe(e,s,n){let i=R(n),r=x(e,s),t=r.findIndex(a=>a.name===i);if(t!==-1){let[a]=r.splice(t,1);if(P(e,s,r),a&&!a.linkedPath){let c=m(d(e,s),i);l(c)&&b(c)}return!0}let o=m(d(e,s),i);return l(o)?(b(o),!0):!1}function ve(e,s,n){let i=R(n),r=x(e,s).find(o=>o.name===i&&o.linkedPath);if(r?.linkedPath&&l(r.linkedPath))return r.linkedPath;let t=m(d(e,s),i);return l(t)?t:null}function Ae(e,s){return ee(e,s).length}export{g as a,$ as b,k as c,v as d,te as e,M as f,ae as g,U as h,T as i,O as j,ue as k,y as l,ce as m,le as n,B as o,me as p,fe as q,de as r,ge as s,d as t,Q as u,ee as v,be as w,xe as x,ve as y,Ae as z};
|