vibeman 0.0.5 → 0.0.6

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (241) hide show
  1. package/dist/api.js +49 -0
  2. package/dist/cli.js +135 -0
  3. package/dist/ui/index-gnk6rhxs.js +9 -0
  4. package/dist/ui/index.html +10 -0
  5. package/dist/ui/index.js +2 -0
  6. package/package.json +10 -46
  7. package/README.md +0 -12
  8. package/dist/index.js +0 -114
  9. package/dist/runtime/api/.tsbuildinfo +0 -1
  10. package/dist/runtime/api/agent/agent-service.d.ts +0 -229
  11. package/dist/runtime/api/agent/agent-service.js +0 -963
  12. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.d.ts +0 -38
  13. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.js +0 -268
  14. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +0 -61
  15. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +0 -362
  16. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +0 -36
  17. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +0 -375
  18. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.d.ts +0 -24
  19. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.js +0 -291
  20. package/dist/runtime/api/agent/ai-providers/index.d.ts +0 -9
  21. package/dist/runtime/api/agent/ai-providers/index.js +0 -9
  22. package/dist/runtime/api/agent/ai-providers/types.d.ts +0 -185
  23. package/dist/runtime/api/agent/ai-providers/types.js +0 -5
  24. package/dist/runtime/api/agent/amp-cli-provider.test.d.ts +0 -1
  25. package/dist/runtime/api/agent/amp-cli-provider.test.js +0 -99
  26. package/dist/runtime/api/agent/codex-cli-provider.test.d.ts +0 -1
  27. package/dist/runtime/api/agent/codex-cli-provider.test.js +0 -172
  28. package/dist/runtime/api/agent/core-agent-service.d.ts +0 -119
  29. package/dist/runtime/api/agent/core-agent-service.js +0 -267
  30. package/dist/runtime/api/agent/parsers.d.ts +0 -16
  31. package/dist/runtime/api/agent/parsers.js +0 -308
  32. package/dist/runtime/api/agent/prompt-service.d.ts +0 -30
  33. package/dist/runtime/api/agent/prompt-service.js +0 -452
  34. package/dist/runtime/api/agent/prompt-service.test.d.ts +0 -1
  35. package/dist/runtime/api/agent/prompt-service.test.js +0 -265
  36. package/dist/runtime/api/agent/routing-policy.d.ts +0 -171
  37. package/dist/runtime/api/agent/routing-policy.js +0 -196
  38. package/dist/runtime/api/agent/routing-policy.test.d.ts +0 -1
  39. package/dist/runtime/api/agent/routing-policy.test.js +0 -63
  40. package/dist/runtime/api/api/router-helpers.d.ts +0 -32
  41. package/dist/runtime/api/api/router-helpers.js +0 -31
  42. package/dist/runtime/api/api/routers/ai.d.ts +0 -200
  43. package/dist/runtime/api/api/routers/ai.js +0 -396
  44. package/dist/runtime/api/api/routers/executions.d.ts +0 -93
  45. package/dist/runtime/api/api/routers/executions.js +0 -94
  46. package/dist/runtime/api/api/routers/git.d.ts +0 -45
  47. package/dist/runtime/api/api/routers/git.js +0 -35
  48. package/dist/runtime/api/api/routers/provider-config.d.ts +0 -199
  49. package/dist/runtime/api/api/routers/provider-config.js +0 -252
  50. package/dist/runtime/api/api/routers/settings.d.ts +0 -158
  51. package/dist/runtime/api/api/routers/settings.js +0 -129
  52. package/dist/runtime/api/api/routers/tasks.d.ts +0 -141
  53. package/dist/runtime/api/api/routers/tasks.js +0 -238
  54. package/dist/runtime/api/api/routers/workflows.d.ts +0 -275
  55. package/dist/runtime/api/api/routers/workflows.js +0 -311
  56. package/dist/runtime/api/api/routers/worktrees.d.ts +0 -101
  57. package/dist/runtime/api/api/routers/worktrees.js +0 -80
  58. package/dist/runtime/api/api/trpc.d.ts +0 -118
  59. package/dist/runtime/api/api/trpc.js +0 -34
  60. package/dist/runtime/api/index.d.ts +0 -9
  61. package/dist/runtime/api/index.js +0 -117
  62. package/dist/runtime/api/lib/id-generator.d.ts +0 -70
  63. package/dist/runtime/api/lib/id-generator.js +0 -123
  64. package/dist/runtime/api/lib/local-config.d.ts +0 -335
  65. package/dist/runtime/api/lib/local-config.js +0 -304
  66. package/dist/runtime/api/lib/logger.d.ts +0 -11
  67. package/dist/runtime/api/lib/logger.js +0 -188
  68. package/dist/runtime/api/lib/provider-detection.d.ts +0 -61
  69. package/dist/runtime/api/lib/provider-detection.js +0 -326
  70. package/dist/runtime/api/lib/server/agent-service-singleton.d.ts +0 -6
  71. package/dist/runtime/api/lib/server/agent-service-singleton.js +0 -27
  72. package/dist/runtime/api/lib/server/bootstrap.d.ts +0 -38
  73. package/dist/runtime/api/lib/server/bootstrap.js +0 -197
  74. package/dist/runtime/api/lib/server/git-service-singleton.d.ts +0 -6
  75. package/dist/runtime/api/lib/server/git-service-singleton.js +0 -47
  76. package/dist/runtime/api/lib/server/project-root.d.ts +0 -2
  77. package/dist/runtime/api/lib/server/project-root.js +0 -61
  78. package/dist/runtime/api/lib/server/task-service-singleton.d.ts +0 -7
  79. package/dist/runtime/api/lib/server/task-service-singleton.js +0 -58
  80. package/dist/runtime/api/lib/server/vibeman-info.d.ts +0 -5
  81. package/dist/runtime/api/lib/server/vibeman-info.js +0 -85
  82. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.d.ts +0 -7
  83. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.js +0 -57
  84. package/dist/runtime/api/lib/trpc/server.d.ts +0 -965
  85. package/dist/runtime/api/lib/trpc/server.js +0 -11
  86. package/dist/runtime/api/lib/trpc/ws-server.d.ts +0 -8
  87. package/dist/runtime/api/lib/trpc/ws-server.js +0 -33
  88. package/dist/runtime/api/persistence/database-service.d.ts +0 -14
  89. package/dist/runtime/api/persistence/database-service.js +0 -74
  90. package/dist/runtime/api/persistence/execution-log-persistence.d.ts +0 -90
  91. package/dist/runtime/api/persistence/execution-log-persistence.js +0 -426
  92. package/dist/runtime/api/persistence/execution-log-persistence.test.d.ts +0 -1
  93. package/dist/runtime/api/persistence/execution-log-persistence.test.js +0 -170
  94. package/dist/runtime/api/router.d.ts +0 -968
  95. package/dist/runtime/api/router.js +0 -34
  96. package/dist/runtime/api/settings-service.d.ts +0 -110
  97. package/dist/runtime/api/settings-service.js +0 -678
  98. package/dist/runtime/api/tasks/file-watcher.d.ts +0 -23
  99. package/dist/runtime/api/tasks/file-watcher.js +0 -88
  100. package/dist/runtime/api/tasks/task-file-parser.d.ts +0 -14
  101. package/dist/runtime/api/tasks/task-file-parser.js +0 -180
  102. package/dist/runtime/api/tasks/task-service.d.ts +0 -36
  103. package/dist/runtime/api/tasks/task-service.js +0 -173
  104. package/dist/runtime/api/tasks/task-updater.d.ts +0 -62
  105. package/dist/runtime/api/tasks/task-updater.js +0 -260
  106. package/dist/runtime/api/tasks/task-updater.test.d.ts +0 -1
  107. package/dist/runtime/api/tasks/task-updater.test.js +0 -303
  108. package/dist/runtime/api/types/index.d.ts +0 -186
  109. package/dist/runtime/api/types/index.js +0 -1
  110. package/dist/runtime/api/types/settings.d.ts +0 -105
  111. package/dist/runtime/api/types/settings.js +0 -2
  112. package/dist/runtime/api/types.d.ts +0 -2
  113. package/dist/runtime/api/types.js +0 -1
  114. package/dist/runtime/api/utils/env.d.ts +0 -6
  115. package/dist/runtime/api/utils/env.js +0 -12
  116. package/dist/runtime/api/utils/stripNextEnv.d.ts +0 -7
  117. package/dist/runtime/api/utils/stripNextEnv.js +0 -22
  118. package/dist/runtime/api/utils/title-slug.d.ts +0 -6
  119. package/dist/runtime/api/utils/title-slug.js +0 -77
  120. package/dist/runtime/api/utils/url.d.ts +0 -2
  121. package/dist/runtime/api/utils/url.js +0 -19
  122. package/dist/runtime/api/vcs/git-history-service.d.ts +0 -57
  123. package/dist/runtime/api/vcs/git-history-service.js +0 -228
  124. package/dist/runtime/api/vcs/git-service.d.ts +0 -136
  125. package/dist/runtime/api/vcs/git-service.js +0 -307
  126. package/dist/runtime/api/vcs/worktree-service.d.ts +0 -93
  127. package/dist/runtime/api/vcs/worktree-service.js +0 -518
  128. package/dist/runtime/api/vcs/worktree-service.test.d.ts +0 -1
  129. package/dist/runtime/api/vcs/worktree-service.test.js +0 -20
  130. package/dist/runtime/api/workflows/quality-pipeline.d.ts +0 -58
  131. package/dist/runtime/api/workflows/quality-pipeline.js +0 -401
  132. package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +0 -406
  133. package/dist/runtime/api/workflows/vibing-orchestrator.js +0 -2462
  134. package/dist/runtime/api/workflows/workflow-effects.d.ts +0 -45
  135. package/dist/runtime/api/workflows/workflow-effects.js +0 -49
  136. package/dist/runtime/api/workflows/workflow-reconciler.d.ts +0 -65
  137. package/dist/runtime/api/workflows/workflow-reconciler.js +0 -226
  138. package/dist/runtime/api/workflows/workflow-reducer.d.ts +0 -26
  139. package/dist/runtime/api/workflows/workflow-reducer.js +0 -288
  140. package/dist/runtime/api/workflows/workflow-reducer.test.d.ts +0 -1
  141. package/dist/runtime/api/workflows/workflow-reducer.test.js +0 -247
  142. package/dist/runtime/api/workflows/workflow-schema.d.ts +0 -546
  143. package/dist/runtime/api/workflows/workflow-schema.js +0 -256
  144. package/dist/runtime/web/.next/BUILD_ID +0 -1
  145. package/dist/runtime/web/.next/app-build-manifest.json +0 -66
  146. package/dist/runtime/web/.next/app-path-routes-manifest.json +0 -8
  147. package/dist/runtime/web/.next/build-manifest.json +0 -33
  148. package/dist/runtime/web/.next/package.json +0 -1
  149. package/dist/runtime/web/.next/prerender-manifest.json +0 -61
  150. package/dist/runtime/web/.next/react-loadable-manifest.json +0 -8
  151. package/dist/runtime/web/.next/required-server-files.json +0 -334
  152. package/dist/runtime/web/.next/routes-manifest.json +0 -70
  153. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +0 -1
  154. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +0 -1
  155. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +0 -1
  156. package/dist/runtime/web/.next/server/app/_not-found/page.js +0 -2
  157. package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +0 -1
  158. package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  159. package/dist/runtime/web/.next/server/app/_not-found.html +0 -7
  160. package/dist/runtime/web/.next/server/app/_not-found.meta +0 -8
  161. package/dist/runtime/web/.next/server/app/_not-found.rsc +0 -22
  162. package/dist/runtime/web/.next/server/app/api/health/route.js +0 -1
  163. package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +0 -1
  164. package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +0 -1
  165. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +0 -1
  166. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +0 -1
  167. package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +0 -1
  168. package/dist/runtime/web/.next/server/app/api/upload/route.js +0 -1
  169. package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +0 -1
  170. package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +0 -1
  171. package/dist/runtime/web/.next/server/app/index.html +0 -7
  172. package/dist/runtime/web/.next/server/app/index.meta +0 -7
  173. package/dist/runtime/web/.next/server/app/index.rsc +0 -27
  174. package/dist/runtime/web/.next/server/app/page.js +0 -112
  175. package/dist/runtime/web/.next/server/app/page.js.nft.json +0 -1
  176. package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +0 -1
  177. package/dist/runtime/web/.next/server/app-paths-manifest.json +0 -8
  178. package/dist/runtime/web/.next/server/chunks/210.js +0 -1
  179. package/dist/runtime/web/.next/server/chunks/291.js +0 -18
  180. package/dist/runtime/web/.next/server/chunks/552.js +0 -22
  181. package/dist/runtime/web/.next/server/chunks/780.js +0 -1
  182. package/dist/runtime/web/.next/server/chunks/905.js +0 -6
  183. package/dist/runtime/web/.next/server/chunks/98.js +0 -1
  184. package/dist/runtime/web/.next/server/functions-config-manifest.json +0 -4
  185. package/dist/runtime/web/.next/server/middleware-build-manifest.js +0 -1
  186. package/dist/runtime/web/.next/server/middleware-manifest.json +0 -6
  187. package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +0 -1
  188. package/dist/runtime/web/.next/server/next-font-manifest.js +0 -1
  189. package/dist/runtime/web/.next/server/next-font-manifest.json +0 -1
  190. package/dist/runtime/web/.next/server/pages/404.html +0 -7
  191. package/dist/runtime/web/.next/server/pages/500.html +0 -1
  192. package/dist/runtime/web/.next/server/pages/_app.js +0 -1
  193. package/dist/runtime/web/.next/server/pages/_app.js.nft.json +0 -1
  194. package/dist/runtime/web/.next/server/pages/_document.js +0 -1
  195. package/dist/runtime/web/.next/server/pages/_document.js.nft.json +0 -1
  196. package/dist/runtime/web/.next/server/pages/_error.js +0 -19
  197. package/dist/runtime/web/.next/server/pages/_error.js.nft.json +0 -1
  198. package/dist/runtime/web/.next/server/pages-manifest.json +0 -6
  199. package/dist/runtime/web/.next/server/server-reference-manifest.js +0 -1
  200. package/dist/runtime/web/.next/server/server-reference-manifest.json +0 -1
  201. package/dist/runtime/web/.next/server/webpack-runtime.js +0 -1
  202. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_buildManifest.js +0 -1
  203. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_ssgManifest.js +0 -1
  204. package/dist/runtime/web/.next/static/chunks/05c91ade-7d09b2b280adffd1.js +0 -1
  205. package/dist/runtime/web/.next/static/chunks/201-51bef3fa8c832e2e.js +0 -1
  206. package/dist/runtime/web/.next/static/chunks/524-89747ed9b0294f8a.js +0 -1
  207. package/dist/runtime/web/.next/static/chunks/554-8bec6e9cca6acc67.js +0 -1
  208. package/dist/runtime/web/.next/static/chunks/764.86e9503a69d45a85.js +0 -1
  209. package/dist/runtime/web/.next/static/chunks/7ab4dc20-239138e0ae7af24a.js +0 -1
  210. package/dist/runtime/web/.next/static/chunks/905-342391e3d3a3678f.js +0 -20
  211. package/dist/runtime/web/.next/static/chunks/a8a5ce16-4edea7df2d9b544a.js +0 -79
  212. package/dist/runtime/web/.next/static/chunks/ad74d572-4c1b162e2c15acaa.js +0 -1
  213. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  214. package/dist/runtime/web/.next/static/chunks/app/_not-found/page-34e66b251c2b5044.js +0 -1
  215. package/dist/runtime/web/.next/static/chunks/app/api/health/route-7b752a8641f96c1f.js +0 -1
  216. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  217. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-7b752a8641f96c1f.js +0 -1
  218. package/dist/runtime/web/.next/static/chunks/app/layout-df9ac93cb02b2385.js +0 -1
  219. package/dist/runtime/web/.next/static/chunks/app/page-6610743f7de5f92a.js +0 -1
  220. package/dist/runtime/web/.next/static/chunks/c25e0690-e9b798b8de667da1.js +0 -1
  221. package/dist/runtime/web/.next/static/chunks/framework-57157ec4d37f64aa.js +0 -1
  222. package/dist/runtime/web/.next/static/chunks/main-app-156cc0c60371bd78.js +0 -1
  223. package/dist/runtime/web/.next/static/chunks/main-df25d367c47b1fec.js +0 -1
  224. package/dist/runtime/web/.next/static/chunks/pages/_app-9f629a5e1131d19f.js +0 -1
  225. package/dist/runtime/web/.next/static/chunks/pages/_error-9238238274c7efcd.js +0 -1
  226. package/dist/runtime/web/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  227. package/dist/runtime/web/.next/static/chunks/webpack-cd50e39b423d1808.js +0 -1
  228. package/dist/runtime/web/.next/static/css/2728291c68f99cb1.css +0 -3
  229. package/dist/runtime/web/.next/static/css/4fbf378a264bd4ea.css +0 -1
  230. package/dist/runtime/web/.next/static/css/521bd69cc298cd1a.css +0 -1
  231. package/dist/runtime/web/.next/static/css/537e22821e101b87.css +0 -1
  232. package/dist/runtime/web/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
  233. package/dist/runtime/web/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
  234. package/dist/runtime/web/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  235. package/dist/runtime/web/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
  236. package/dist/runtime/web/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
  237. package/dist/runtime/web/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  238. package/dist/runtime/web/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  239. package/dist/runtime/web/package.json +0 -65
  240. package/dist/runtime/web/server.js +0 -44
  241. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,88 +0,0 @@
1
- import path from 'path';
2
- import fs from 'fs';
3
- import { EventEmitter } from 'events';
4
- import { log } from '../lib/logger.js';
5
- export class FileWatcher extends EventEmitter {
6
- constructor(watchDir, options = {}) {
7
- super();
8
- this.watcher = null;
9
- this.pendingChanges = new Map();
10
- this.watchDir = path.resolve(watchDir);
11
- this.options = {
12
- recursive: false,
13
- debounceMs: 100,
14
- fileFilter: () => true,
15
- ...options,
16
- };
17
- }
18
- start() {
19
- if (this.watcher) {
20
- return;
21
- }
22
- // Check if directory exists
23
- if (!fs.existsSync(this.watchDir)) {
24
- const error = new Error(`Watch directory does not exist: ${this.watchDir}`);
25
- log.error('FileWatcher start failed', error, 'file-watcher');
26
- this.emit('error', error);
27
- return;
28
- }
29
- this.watcher = fs.watch(this.watchDir, { recursive: this.options.recursive }, (eventType, filename) => {
30
- if (filename && this.options.fileFilter(filename)) {
31
- this.debounceFileChange(filename);
32
- }
33
- });
34
- log.debug('FileWatcher started', { watchDir: this.watchDir }, 'file-watcher');
35
- }
36
- stop() {
37
- if (this.watcher) {
38
- this.watcher.close();
39
- this.watcher = null;
40
- // Clear all pending timeouts
41
- for (const timeout of this.pendingChanges.values()) {
42
- clearTimeout(timeout);
43
- }
44
- this.pendingChanges.clear();
45
- log.info('FileWatcher stopped', { watchDir: this.watchDir }, 'file-watcher');
46
- }
47
- }
48
- debounceFileChange(filename) {
49
- // Clear any existing timeout for this file
50
- const existingTimeout = this.pendingChanges.get(filename);
51
- if (existingTimeout) {
52
- clearTimeout(existingTimeout);
53
- }
54
- // Set a new timeout to handle the change after a short delay
55
- const timeout = setTimeout(() => {
56
- this.handleFileChange(filename);
57
- this.pendingChanges.delete(filename);
58
- }, this.options.debounceMs);
59
- this.pendingChanges.set(filename, timeout);
60
- }
61
- async handleFileChange(filename) {
62
- const fullPath = path.join(this.watchDir, filename);
63
- try {
64
- const fileExists = await this.fileExists(fullPath);
65
- const changeType = fileExists ? 'updated' : 'deleted';
66
- const event = {
67
- type: changeType,
68
- filename,
69
- fullPath,
70
- };
71
- this.emit('fileChanged', event);
72
- log.debug(`File ${changeType}: ${filename}`, { filename, fullPath, type: changeType }, 'file-watcher');
73
- }
74
- catch (error) {
75
- log.error(`Error processing file change for ${filename}`, error, 'file-watcher');
76
- this.emit('error', error);
77
- }
78
- }
79
- async fileExists(filePath) {
80
- try {
81
- await fs.promises.access(filePath);
82
- return true;
83
- }
84
- catch {
85
- return false;
86
- }
87
- }
88
- }
@@ -1,14 +0,0 @@
1
- import { Task } from '../types/index.js';
2
- export declare class TaskFileParser {
3
- private baseDir;
4
- constructor(baseDir: string);
5
- parseFile(filePath: string): Promise<Task | null>;
6
- parseDirectory(dirPath?: string): Promise<Task[]>;
7
- parseContent(content: string, filePath?: string): Promise<Task | null>;
8
- private getFileStats;
9
- private normalizeStatus;
10
- writeTask(task: Task): Promise<void>;
11
- deleteTask(taskId: string): Promise<void>;
12
- generateFilePath(task: Task): string;
13
- generateFilePathFromId(taskId: string): string;
14
- }
@@ -1,180 +0,0 @@
1
- import fs from 'fs/promises';
2
- import path from 'path';
3
- import matter from 'gray-matter';
4
- import { log } from '../lib/logger.js';
5
- export class TaskFileParser {
6
- constructor(baseDir) {
7
- this.baseDir = baseDir;
8
- }
9
- async parseFile(filePath) {
10
- try {
11
- const content = await fs.readFile(filePath, 'utf-8');
12
- return await this.parseContent(content, filePath);
13
- }
14
- catch (error) {
15
- log.error(`Error reading file ${filePath}`, error, 'task-file-parser:parseFile');
16
- return null;
17
- }
18
- }
19
- async parseDirectory(dirPath) {
20
- const targetDir = dirPath || this.baseDir;
21
- try {
22
- const files = await fs.readdir(targetDir);
23
- const markdownFiles = files.filter((file) => file.endsWith('.md'));
24
- const tasks = [];
25
- for (const file of markdownFiles) {
26
- const filePath = path.join(targetDir, file);
27
- const task = await this.parseFile(filePath);
28
- if (task) {
29
- tasks.push(task);
30
- }
31
- }
32
- // Sort by ID for consistent ordering
33
- return tasks.sort((a, b) => a.id.localeCompare(b.id));
34
- }
35
- catch (error) {
36
- log.error(`Error reading directory ${targetDir}`, error, 'task-file-parser:parseDirectory');
37
- return [];
38
- }
39
- }
40
- async parseContent(content, filePath) {
41
- try {
42
- const parsed = matter(content);
43
- const metadata = parsed.data;
44
- const normalizedStatus = this.normalizeStatus(metadata.status);
45
- if (normalizedStatus !== null) {
46
- metadata.status = normalizedStatus;
47
- }
48
- // Validate required fields
49
- if (!metadata.id || !metadata.title || !metadata.type || !metadata.status) {
50
- log.error(`Invalid task metadata in ${filePath}`, { metadata, filePath }, 'task-file-parser:parseContent');
51
- return null;
52
- }
53
- // Validate enum values
54
- const validTypes = ['feature', 'bug', 'chore', 'refactor', 'test', 'doc'];
55
- const validStatuses = ['backlog', 'in-progress', 'review', 'done'];
56
- const validPriorities = ['low', 'medium', 'high'];
57
- if (!validTypes.includes(metadata.type)) {
58
- log.error(`Invalid task type '${metadata.type}' in ${filePath}`, { type: metadata.type, filePath, validTypes }, 'task-file-parser:parseContent');
59
- return null;
60
- }
61
- if (!validStatuses.includes(metadata.status)) {
62
- log.error(`Invalid task status '${metadata.status}' in ${filePath}`, { status: metadata.status, filePath, validStatuses }, 'task-file-parser:parseContent');
63
- metadata.status = 'backlog';
64
- }
65
- if (metadata.priority && !validPriorities.includes(metadata.priority)) {
66
- log.error(`Invalid task priority '${metadata.priority}' in ${filePath}`, { priority: metadata.priority, filePath, validPriorities }, 'task-file-parser:parseContent');
67
- return null;
68
- }
69
- const now = new Date().toISOString();
70
- const stats = filePath ? await this.getFileStats(filePath) : null;
71
- const task = {
72
- id: metadata.id,
73
- title: metadata.title,
74
- type: metadata.type,
75
- status: metadata.status,
76
- tags: Array.isArray(metadata.tags) ? metadata.tags : [],
77
- due_date: metadata.due_date
78
- ? metadata.due_date instanceof Date
79
- ? metadata.due_date.toISOString().split('T')[0]
80
- : String(metadata.due_date)
81
- : undefined,
82
- assignee: Array.isArray(metadata.assignee)
83
- ? metadata.assignee
84
- : metadata.assignee
85
- ? [metadata.assignee]
86
- : [],
87
- priority: metadata.priority || 'medium',
88
- comments: Array.isArray(metadata.comments)
89
- ? metadata.comments
90
- : metadata.comments
91
- ? [metadata.comments]
92
- : [],
93
- deleted_at: metadata.deleted_at ? String(metadata.deleted_at) : undefined,
94
- content: parsed.content.trim(),
95
- created_at: stats?.birthtime && !isNaN(stats.birthtime.getTime())
96
- ? stats.birthtime.toISOString()
97
- : now,
98
- updated_at: stats?.mtime && !isNaN(stats.mtime.getTime()) ? stats.mtime.toISOString() : now,
99
- };
100
- return task;
101
- }
102
- catch (error) {
103
- log.error(`Error parsing task content from ${filePath}`, error, 'task-file-parser:parseContent');
104
- return null;
105
- }
106
- }
107
- async getFileStats(filePath) {
108
- try {
109
- return await fs.stat(filePath);
110
- }
111
- catch {
112
- return null;
113
- }
114
- }
115
- normalizeStatus(status) {
116
- if (typeof status !== 'string') {
117
- return null;
118
- }
119
- const normalized = status
120
- .trim()
121
- .toLowerCase()
122
- .replace(/[_\s]+/g, '-')
123
- .replace(/-+/g, '-');
124
- const validStatuses = ['backlog', 'in-progress', 'review', 'done'];
125
- if (validStatuses.includes(normalized)) {
126
- return normalized;
127
- }
128
- return null;
129
- }
130
- async writeTask(task) {
131
- const filePath = this.generateFilePath(task);
132
- const frontMatter = {
133
- id: task.id,
134
- title: task.title,
135
- type: task.type,
136
- status: task.status,
137
- tags: task.tags.join(', ') || '',
138
- due_date: task.due_date || '',
139
- assignee: task.assignee?.join(', ') || '',
140
- priority: task.priority,
141
- comments: task.comments?.join(', ') || '',
142
- deleted_at: task.deleted_at || '',
143
- };
144
- // Compose the file so there is always exactly one blank line
145
- // between the front matter and the content body.
146
- // 1) Build only front matter
147
- let fmOnly = matter.stringify('', frontMatter);
148
- // 2) Normalize trailing newlines on FM to exactly one
149
- fmOnly = fmOnly.replace(/\n*$/, '\n');
150
- // 3) Normalize leading newlines on body
151
- const body = (task.content || '').replace(/^[\r\n]+/, '');
152
- // 4) Join with exactly one extra newline to create a single blank line
153
- const fileContent = body ? fmOnly + '\n' + body : fmOnly;
154
- try {
155
- await fs.writeFile(filePath, fileContent, 'utf-8');
156
- }
157
- catch (error) {
158
- log.error(`Error writing task file ${filePath}`, error, 'task-file-parser:writeTask');
159
- throw error;
160
- }
161
- }
162
- async deleteTask(taskId) {
163
- const filePath = this.generateFilePathFromId(taskId);
164
- try {
165
- await fs.unlink(filePath);
166
- }
167
- catch (error) {
168
- log.error(`Error deleting task file ${filePath}`, error, 'task-file-parser:deleteTask');
169
- throw error;
170
- }
171
- }
172
- generateFilePath(task) {
173
- const fileName = `${task.id}.md`;
174
- return path.join(this.baseDir, fileName);
175
- }
176
- generateFilePathFromId(taskId) {
177
- const fileName = `${taskId}.md`;
178
- return path.join(this.baseDir, fileName);
179
- }
180
- }
@@ -1,36 +0,0 @@
1
- import { EventEmitter } from 'events';
2
- import { Task } from '../types/index.js';
3
- export declare class TaskService extends EventEmitter {
4
- private tasks;
5
- private fileWatcher;
6
- private taskParser;
7
- private tasksDir;
8
- private initialized;
9
- constructor(vibeDir: string);
10
- private handleFileChange;
11
- private extractTaskIdFromFilename;
12
- initialize(): Promise<void>;
13
- ensureInitialized(): Promise<void>;
14
- stop(): void;
15
- getAllTasks(): Task[];
16
- getActiveTasks(): Task[];
17
- getTask(id: string): Task | undefined;
18
- getTasksByStatus(status: Task['status']): Task[];
19
- getTasksByType(type: Task['type']): Task[];
20
- searchTasks(query: string): Task[];
21
- createTask(taskData: Omit<Task, 'id' | 'created_at' | 'updated_at'> & {
22
- id?: string;
23
- }): Promise<Task>;
24
- updateTask(id: string, updates: Partial<Task>): Promise<Task>;
25
- deleteTask(id: string): Promise<void>;
26
- moveTask(id: string, newStatus: Task['status']): Promise<Task>;
27
- getTaskStats(): {
28
- total: number;
29
- backlog: number;
30
- 'in-progress': number;
31
- review: number;
32
- done: number;
33
- byType: Record<Task["type"], number>;
34
- byPriority: Record<Task["priority"], number>;
35
- };
36
- }
@@ -1,173 +0,0 @@
1
- import { EventEmitter } from 'events';
2
- import { FileWatcher } from './file-watcher.js';
3
- import { TaskFileParser } from './task-file-parser.js';
4
- import { generateHumanTaskId } from '../utils/title-slug.js';
5
- import { log } from '../lib/logger.js';
6
- import fs from 'fs/promises';
7
- export class TaskService extends EventEmitter {
8
- constructor(vibeDir) {
9
- super();
10
- this.tasks = new Map();
11
- this.initialized = false;
12
- this.tasksDir = `${vibeDir}/tasks`;
13
- this.fileWatcher = new FileWatcher(this.tasksDir, {
14
- fileFilter: (filename) => filename.endsWith('.md'),
15
- });
16
- this.taskParser = new TaskFileParser(this.tasksDir);
17
- this.fileWatcher.on('fileChanged', async (event) => {
18
- try {
19
- await this.handleFileChange(event);
20
- }
21
- catch (error) {
22
- log.error('Error handling file change', error, 'task-service');
23
- this.emit('error', error);
24
- }
25
- });
26
- this.fileWatcher.on('error', (error) => {
27
- log.error('FileWatcher error', error, 'task-service');
28
- this.emit('error', error);
29
- });
30
- }
31
- async handleFileChange(event) {
32
- const { type, filename, fullPath } = event;
33
- if (type === 'deleted') {
34
- const taskId = this.extractTaskIdFromFilename(filename);
35
- if (taskId && this.tasks.has(taskId)) {
36
- this.tasks.delete(taskId);
37
- this.emit('taskDeleted', taskId);
38
- log.info('Task deleted', { taskId }, 'task-service');
39
- }
40
- }
41
- else {
42
- // File exists, parse and update
43
- const task = await this.taskParser.parseFile(fullPath);
44
- if (task) {
45
- this.tasks.set(task.id, task);
46
- this.emit('taskUpdated', task);
47
- log.info(`Task updated from file change: ${task.id}`, { taskId: task.id, filename }, 'task-service');
48
- }
49
- else {
50
- log.warn(`Failed to parse task from ${filename}`, { filename }, 'task-service');
51
- }
52
- }
53
- }
54
- extractTaskIdFromFilename(filename) {
55
- // Use the basename (without extension) as ID, supports multi-hyphen IDs
56
- return filename.endsWith('.md') ? filename.slice(0, -3) : null;
57
- }
58
- async initialize() {
59
- if (this.initialized) {
60
- return;
61
- }
62
- // Ensure directories exist
63
- await fs.mkdir(this.tasksDir, { recursive: true });
64
- // Load existing tasks
65
- const tasks = await this.taskParser.parseDirectory();
66
- for (const task of tasks) {
67
- this.tasks.set(task.id, task);
68
- }
69
- // Start file watcher
70
- this.fileWatcher.start();
71
- this.initialized = true;
72
- }
73
- async ensureInitialized() {
74
- if (!this.initialized) {
75
- await this.initialize();
76
- }
77
- }
78
- stop() {
79
- this.fileWatcher.stop();
80
- this.tasks.clear();
81
- this.initialized = false;
82
- log.info('Task Service stopped', undefined, 'task-service');
83
- }
84
- // Task CRUD operations
85
- getAllTasks() {
86
- return Array.from(this.tasks.values());
87
- }
88
- // Get all non-deleted tasks (excludes soft-deleted tasks)
89
- getActiveTasks() {
90
- return Array.from(this.tasks.values()).filter((task) => !task.deleted_at);
91
- }
92
- getTask(id) {
93
- return this.tasks.get(id);
94
- }
95
- getTasksByStatus(status) {
96
- return this.getAllTasks().filter((task) => task.status === status);
97
- }
98
- getTasksByType(type) {
99
- return this.getAllTasks().filter((task) => task.type === type);
100
- }
101
- searchTasks(query) {
102
- const searchTerm = query.toLowerCase();
103
- return this.getAllTasks().filter((task) => task.title.toLowerCase().includes(searchTerm) ||
104
- task.content.toLowerCase().includes(searchTerm) ||
105
- task.tags.some((tag) => tag.toLowerCase().includes(searchTerm)));
106
- }
107
- async createTask(taskData) {
108
- const now = new Date().toISOString();
109
- // Generate human-readable ID if not provided
110
- const id = taskData.id ||
111
- generateHumanTaskId(taskData.type, taskData.title, Array.from(this.tasks.keys()));
112
- const task = {
113
- ...taskData,
114
- id,
115
- created_at: now,
116
- updated_at: now,
117
- };
118
- // Write to file system (watcher will update memory)
119
- await this.taskParser.writeTask(task);
120
- return task;
121
- }
122
- async updateTask(id, updates) {
123
- const existingTask = this.tasks.get(id);
124
- if (!existingTask) {
125
- throw new Error(`Task ${id} not found`);
126
- }
127
- const updatedTask = {
128
- ...existingTask,
129
- ...updates,
130
- id, // Ensure ID cannot be changed
131
- updated_at: new Date().toISOString(),
132
- };
133
- // Write to file system (watcher will update memory)
134
- await this.taskParser.writeTask(updatedTask);
135
- return updatedTask;
136
- }
137
- async deleteTask(id) {
138
- const existingTask = this.tasks.get(id);
139
- if (!existingTask) {
140
- throw new Error(`Task ${id} not found`);
141
- }
142
- // Soft delete: mark deleted_at and write file
143
- const softDeleted = {
144
- ...existingTask,
145
- deleted_at: new Date().toISOString(),
146
- };
147
- await this.taskParser.writeTask(softDeleted);
148
- // Update in-memory map and emit update event for subscribers
149
- this.tasks.set(id, softDeleted);
150
- this.emit('taskUpdated', softDeleted);
151
- }
152
- async moveTask(id, newStatus) {
153
- return this.updateTask(id, { status: newStatus });
154
- }
155
- getTaskStats() {
156
- const tasks = this.getAllTasks();
157
- const stats = {
158
- total: tasks.length,
159
- backlog: 0,
160
- 'in-progress': 0,
161
- review: 0,
162
- done: 0,
163
- byType: {},
164
- byPriority: {},
165
- };
166
- for (const task of tasks) {
167
- stats[task.status]++;
168
- stats.byType[task.type] = (stats.byType[task.type] || 0) + 1;
169
- stats.byPriority[task.priority] = (stats.byPriority[task.priority] || 0) + 1;
170
- }
171
- return stats;
172
- }
173
- }
@@ -1,62 +0,0 @@
1
- export interface TaskUpdateContext {
2
- filesModified?: string[];
3
- keyChanges?: string[];
4
- testsAdded?: boolean;
5
- testsPassed?: boolean;
6
- buildPassed?: boolean;
7
- qualityChecksPassed?: boolean;
8
- aiReviewScore?: number;
9
- workflowId?: string;
10
- phase?: string;
11
- }
12
- export interface TaskUpdateSummary {
13
- filesChanged: string[];
14
- keyLogic: string[];
15
- testsInfo: string;
16
- qualityNotes: string;
17
- remainingRisks: string[];
18
- }
19
- /**
20
- * Updates task markdown files when workflows reach review readiness.
21
- * Handles status updates, todo marking, and implementation summary generation.
22
- */
23
- export declare class TaskUpdater {
24
- private tasksDir;
25
- constructor(vibeDir?: string);
26
- /**
27
- * Main entry point: Update task for review readiness
28
- */
29
- updateTaskForReviewReadiness(taskId: string, context?: TaskUpdateContext): Promise<void>;
30
- /**
31
- * Update YAML front-matter to set status to 'review'
32
- */
33
- private updateStatusToReview;
34
- /**
35
- * Process markdown content: mark todos and add/update implementation summary
36
- */
37
- private processMarkdownContent;
38
- /**
39
- * Mark implementation-related todos as completed
40
- */
41
- private markImplementationTodos;
42
- /**
43
- * Check if a section is eligible for todo marking
44
- */
45
- private isEligibleTodoSection;
46
- /**
47
- * Add or update the implementation summary section
48
- */
49
- private upsertImplementationSummary;
50
- /**
51
- * Generate implementation summary from context
52
- */
53
- private generateImplementationSummary;
54
- /**
55
- * Build the implementation summary markdown section
56
- */
57
- private buildImplementationSummarySection;
58
- /**
59
- * Write task file atomically using temporary file
60
- */
61
- private writeTaskFileAtomically;
62
- }