vibeman 0.0.5 → 0.0.7

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 (239) hide show
  1. package/dist/api.js +43 -0
  2. package/dist/index.js +227 -104
  3. package/dist/ui/assets/index-C_kQPI1m.js +9 -0
  4. package/dist/ui/index.html +12 -0
  5. package/package.json +13 -46
  6. package/README.md +0 -12
  7. package/dist/runtime/api/.tsbuildinfo +0 -1
  8. package/dist/runtime/api/agent/agent-service.d.ts +0 -229
  9. package/dist/runtime/api/agent/agent-service.js +0 -963
  10. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.d.ts +0 -38
  11. package/dist/runtime/api/agent/ai-providers/amp-cli-provider.js +0 -268
  12. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +0 -61
  13. package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +0 -362
  14. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +0 -36
  15. package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +0 -375
  16. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.d.ts +0 -24
  17. package/dist/runtime/api/agent/ai-providers/gemini-cli-provider.js +0 -291
  18. package/dist/runtime/api/agent/ai-providers/index.d.ts +0 -9
  19. package/dist/runtime/api/agent/ai-providers/index.js +0 -9
  20. package/dist/runtime/api/agent/ai-providers/types.d.ts +0 -185
  21. package/dist/runtime/api/agent/ai-providers/types.js +0 -5
  22. package/dist/runtime/api/agent/amp-cli-provider.test.d.ts +0 -1
  23. package/dist/runtime/api/agent/amp-cli-provider.test.js +0 -99
  24. package/dist/runtime/api/agent/codex-cli-provider.test.d.ts +0 -1
  25. package/dist/runtime/api/agent/codex-cli-provider.test.js +0 -172
  26. package/dist/runtime/api/agent/core-agent-service.d.ts +0 -119
  27. package/dist/runtime/api/agent/core-agent-service.js +0 -267
  28. package/dist/runtime/api/agent/parsers.d.ts +0 -16
  29. package/dist/runtime/api/agent/parsers.js +0 -308
  30. package/dist/runtime/api/agent/prompt-service.d.ts +0 -30
  31. package/dist/runtime/api/agent/prompt-service.js +0 -452
  32. package/dist/runtime/api/agent/prompt-service.test.d.ts +0 -1
  33. package/dist/runtime/api/agent/prompt-service.test.js +0 -265
  34. package/dist/runtime/api/agent/routing-policy.d.ts +0 -171
  35. package/dist/runtime/api/agent/routing-policy.js +0 -196
  36. package/dist/runtime/api/agent/routing-policy.test.d.ts +0 -1
  37. package/dist/runtime/api/agent/routing-policy.test.js +0 -63
  38. package/dist/runtime/api/api/router-helpers.d.ts +0 -32
  39. package/dist/runtime/api/api/router-helpers.js +0 -31
  40. package/dist/runtime/api/api/routers/ai.d.ts +0 -200
  41. package/dist/runtime/api/api/routers/ai.js +0 -396
  42. package/dist/runtime/api/api/routers/executions.d.ts +0 -93
  43. package/dist/runtime/api/api/routers/executions.js +0 -94
  44. package/dist/runtime/api/api/routers/git.d.ts +0 -45
  45. package/dist/runtime/api/api/routers/git.js +0 -35
  46. package/dist/runtime/api/api/routers/provider-config.d.ts +0 -199
  47. package/dist/runtime/api/api/routers/provider-config.js +0 -252
  48. package/dist/runtime/api/api/routers/settings.d.ts +0 -158
  49. package/dist/runtime/api/api/routers/settings.js +0 -129
  50. package/dist/runtime/api/api/routers/tasks.d.ts +0 -141
  51. package/dist/runtime/api/api/routers/tasks.js +0 -238
  52. package/dist/runtime/api/api/routers/workflows.d.ts +0 -275
  53. package/dist/runtime/api/api/routers/workflows.js +0 -311
  54. package/dist/runtime/api/api/routers/worktrees.d.ts +0 -101
  55. package/dist/runtime/api/api/routers/worktrees.js +0 -80
  56. package/dist/runtime/api/api/trpc.d.ts +0 -118
  57. package/dist/runtime/api/api/trpc.js +0 -34
  58. package/dist/runtime/api/index.d.ts +0 -9
  59. package/dist/runtime/api/index.js +0 -117
  60. package/dist/runtime/api/lib/id-generator.d.ts +0 -70
  61. package/dist/runtime/api/lib/id-generator.js +0 -123
  62. package/dist/runtime/api/lib/local-config.d.ts +0 -335
  63. package/dist/runtime/api/lib/local-config.js +0 -304
  64. package/dist/runtime/api/lib/logger.d.ts +0 -11
  65. package/dist/runtime/api/lib/logger.js +0 -188
  66. package/dist/runtime/api/lib/provider-detection.d.ts +0 -61
  67. package/dist/runtime/api/lib/provider-detection.js +0 -326
  68. package/dist/runtime/api/lib/server/agent-service-singleton.d.ts +0 -6
  69. package/dist/runtime/api/lib/server/agent-service-singleton.js +0 -27
  70. package/dist/runtime/api/lib/server/bootstrap.d.ts +0 -38
  71. package/dist/runtime/api/lib/server/bootstrap.js +0 -197
  72. package/dist/runtime/api/lib/server/git-service-singleton.d.ts +0 -6
  73. package/dist/runtime/api/lib/server/git-service-singleton.js +0 -47
  74. package/dist/runtime/api/lib/server/project-root.d.ts +0 -2
  75. package/dist/runtime/api/lib/server/project-root.js +0 -61
  76. package/dist/runtime/api/lib/server/task-service-singleton.d.ts +0 -7
  77. package/dist/runtime/api/lib/server/task-service-singleton.js +0 -58
  78. package/dist/runtime/api/lib/server/vibeman-info.d.ts +0 -5
  79. package/dist/runtime/api/lib/server/vibeman-info.js +0 -85
  80. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.d.ts +0 -7
  81. package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.js +0 -57
  82. package/dist/runtime/api/lib/trpc/server.d.ts +0 -965
  83. package/dist/runtime/api/lib/trpc/server.js +0 -11
  84. package/dist/runtime/api/lib/trpc/ws-server.d.ts +0 -8
  85. package/dist/runtime/api/lib/trpc/ws-server.js +0 -33
  86. package/dist/runtime/api/persistence/database-service.d.ts +0 -14
  87. package/dist/runtime/api/persistence/database-service.js +0 -74
  88. package/dist/runtime/api/persistence/execution-log-persistence.d.ts +0 -90
  89. package/dist/runtime/api/persistence/execution-log-persistence.js +0 -426
  90. package/dist/runtime/api/persistence/execution-log-persistence.test.d.ts +0 -1
  91. package/dist/runtime/api/persistence/execution-log-persistence.test.js +0 -170
  92. package/dist/runtime/api/router.d.ts +0 -968
  93. package/dist/runtime/api/router.js +0 -34
  94. package/dist/runtime/api/settings-service.d.ts +0 -110
  95. package/dist/runtime/api/settings-service.js +0 -678
  96. package/dist/runtime/api/tasks/file-watcher.d.ts +0 -23
  97. package/dist/runtime/api/tasks/file-watcher.js +0 -88
  98. package/dist/runtime/api/tasks/task-file-parser.d.ts +0 -14
  99. package/dist/runtime/api/tasks/task-file-parser.js +0 -180
  100. package/dist/runtime/api/tasks/task-service.d.ts +0 -36
  101. package/dist/runtime/api/tasks/task-service.js +0 -173
  102. package/dist/runtime/api/tasks/task-updater.d.ts +0 -62
  103. package/dist/runtime/api/tasks/task-updater.js +0 -260
  104. package/dist/runtime/api/tasks/task-updater.test.d.ts +0 -1
  105. package/dist/runtime/api/tasks/task-updater.test.js +0 -303
  106. package/dist/runtime/api/types/index.d.ts +0 -186
  107. package/dist/runtime/api/types/index.js +0 -1
  108. package/dist/runtime/api/types/settings.d.ts +0 -105
  109. package/dist/runtime/api/types/settings.js +0 -2
  110. package/dist/runtime/api/types.d.ts +0 -2
  111. package/dist/runtime/api/types.js +0 -1
  112. package/dist/runtime/api/utils/env.d.ts +0 -6
  113. package/dist/runtime/api/utils/env.js +0 -12
  114. package/dist/runtime/api/utils/stripNextEnv.d.ts +0 -7
  115. package/dist/runtime/api/utils/stripNextEnv.js +0 -22
  116. package/dist/runtime/api/utils/title-slug.d.ts +0 -6
  117. package/dist/runtime/api/utils/title-slug.js +0 -77
  118. package/dist/runtime/api/utils/url.d.ts +0 -2
  119. package/dist/runtime/api/utils/url.js +0 -19
  120. package/dist/runtime/api/vcs/git-history-service.d.ts +0 -57
  121. package/dist/runtime/api/vcs/git-history-service.js +0 -228
  122. package/dist/runtime/api/vcs/git-service.d.ts +0 -136
  123. package/dist/runtime/api/vcs/git-service.js +0 -307
  124. package/dist/runtime/api/vcs/worktree-service.d.ts +0 -93
  125. package/dist/runtime/api/vcs/worktree-service.js +0 -518
  126. package/dist/runtime/api/vcs/worktree-service.test.d.ts +0 -1
  127. package/dist/runtime/api/vcs/worktree-service.test.js +0 -20
  128. package/dist/runtime/api/workflows/quality-pipeline.d.ts +0 -58
  129. package/dist/runtime/api/workflows/quality-pipeline.js +0 -401
  130. package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +0 -406
  131. package/dist/runtime/api/workflows/vibing-orchestrator.js +0 -2462
  132. package/dist/runtime/api/workflows/workflow-effects.d.ts +0 -45
  133. package/dist/runtime/api/workflows/workflow-effects.js +0 -49
  134. package/dist/runtime/api/workflows/workflow-reconciler.d.ts +0 -65
  135. package/dist/runtime/api/workflows/workflow-reconciler.js +0 -226
  136. package/dist/runtime/api/workflows/workflow-reducer.d.ts +0 -26
  137. package/dist/runtime/api/workflows/workflow-reducer.js +0 -288
  138. package/dist/runtime/api/workflows/workflow-reducer.test.d.ts +0 -1
  139. package/dist/runtime/api/workflows/workflow-reducer.test.js +0 -247
  140. package/dist/runtime/api/workflows/workflow-schema.d.ts +0 -546
  141. package/dist/runtime/api/workflows/workflow-schema.js +0 -256
  142. package/dist/runtime/web/.next/BUILD_ID +0 -1
  143. package/dist/runtime/web/.next/app-build-manifest.json +0 -66
  144. package/dist/runtime/web/.next/app-path-routes-manifest.json +0 -8
  145. package/dist/runtime/web/.next/build-manifest.json +0 -33
  146. package/dist/runtime/web/.next/package.json +0 -1
  147. package/dist/runtime/web/.next/prerender-manifest.json +0 -61
  148. package/dist/runtime/web/.next/react-loadable-manifest.json +0 -8
  149. package/dist/runtime/web/.next/required-server-files.json +0 -334
  150. package/dist/runtime/web/.next/routes-manifest.json +0 -70
  151. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +0 -1
  152. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +0 -1
  153. package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +0 -1
  154. package/dist/runtime/web/.next/server/app/_not-found/page.js +0 -2
  155. package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +0 -1
  156. package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
  157. package/dist/runtime/web/.next/server/app/_not-found.html +0 -7
  158. package/dist/runtime/web/.next/server/app/_not-found.meta +0 -8
  159. package/dist/runtime/web/.next/server/app/_not-found.rsc +0 -22
  160. package/dist/runtime/web/.next/server/app/api/health/route.js +0 -1
  161. package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +0 -1
  162. package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +0 -1
  163. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +0 -1
  164. package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +0 -1
  165. package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +0 -1
  166. package/dist/runtime/web/.next/server/app/api/upload/route.js +0 -1
  167. package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +0 -1
  168. package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +0 -1
  169. package/dist/runtime/web/.next/server/app/index.html +0 -7
  170. package/dist/runtime/web/.next/server/app/index.meta +0 -7
  171. package/dist/runtime/web/.next/server/app/index.rsc +0 -27
  172. package/dist/runtime/web/.next/server/app/page.js +0 -112
  173. package/dist/runtime/web/.next/server/app/page.js.nft.json +0 -1
  174. package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +0 -1
  175. package/dist/runtime/web/.next/server/app-paths-manifest.json +0 -8
  176. package/dist/runtime/web/.next/server/chunks/210.js +0 -1
  177. package/dist/runtime/web/.next/server/chunks/291.js +0 -18
  178. package/dist/runtime/web/.next/server/chunks/552.js +0 -22
  179. package/dist/runtime/web/.next/server/chunks/780.js +0 -1
  180. package/dist/runtime/web/.next/server/chunks/905.js +0 -6
  181. package/dist/runtime/web/.next/server/chunks/98.js +0 -1
  182. package/dist/runtime/web/.next/server/functions-config-manifest.json +0 -4
  183. package/dist/runtime/web/.next/server/middleware-build-manifest.js +0 -1
  184. package/dist/runtime/web/.next/server/middleware-manifest.json +0 -6
  185. package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +0 -1
  186. package/dist/runtime/web/.next/server/next-font-manifest.js +0 -1
  187. package/dist/runtime/web/.next/server/next-font-manifest.json +0 -1
  188. package/dist/runtime/web/.next/server/pages/404.html +0 -7
  189. package/dist/runtime/web/.next/server/pages/500.html +0 -1
  190. package/dist/runtime/web/.next/server/pages/_app.js +0 -1
  191. package/dist/runtime/web/.next/server/pages/_app.js.nft.json +0 -1
  192. package/dist/runtime/web/.next/server/pages/_document.js +0 -1
  193. package/dist/runtime/web/.next/server/pages/_document.js.nft.json +0 -1
  194. package/dist/runtime/web/.next/server/pages/_error.js +0 -19
  195. package/dist/runtime/web/.next/server/pages/_error.js.nft.json +0 -1
  196. package/dist/runtime/web/.next/server/pages-manifest.json +0 -6
  197. package/dist/runtime/web/.next/server/server-reference-manifest.js +0 -1
  198. package/dist/runtime/web/.next/server/server-reference-manifest.json +0 -1
  199. package/dist/runtime/web/.next/server/webpack-runtime.js +0 -1
  200. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_buildManifest.js +0 -1
  201. package/dist/runtime/web/.next/static/LJFZk_8tvKFN_Ee4HqUuM/_ssgManifest.js +0 -1
  202. package/dist/runtime/web/.next/static/chunks/05c91ade-7d09b2b280adffd1.js +0 -1
  203. package/dist/runtime/web/.next/static/chunks/201-51bef3fa8c832e2e.js +0 -1
  204. package/dist/runtime/web/.next/static/chunks/524-89747ed9b0294f8a.js +0 -1
  205. package/dist/runtime/web/.next/static/chunks/554-8bec6e9cca6acc67.js +0 -1
  206. package/dist/runtime/web/.next/static/chunks/764.86e9503a69d45a85.js +0 -1
  207. package/dist/runtime/web/.next/static/chunks/7ab4dc20-239138e0ae7af24a.js +0 -1
  208. package/dist/runtime/web/.next/static/chunks/905-342391e3d3a3678f.js +0 -20
  209. package/dist/runtime/web/.next/static/chunks/a8a5ce16-4edea7df2d9b544a.js +0 -79
  210. package/dist/runtime/web/.next/static/chunks/ad74d572-4c1b162e2c15acaa.js +0 -1
  211. package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  212. package/dist/runtime/web/.next/static/chunks/app/_not-found/page-34e66b251c2b5044.js +0 -1
  213. package/dist/runtime/web/.next/static/chunks/app/api/health/route-7b752a8641f96c1f.js +0 -1
  214. package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-7b752a8641f96c1f.js +0 -1
  215. package/dist/runtime/web/.next/static/chunks/app/api/upload/route-7b752a8641f96c1f.js +0 -1
  216. package/dist/runtime/web/.next/static/chunks/app/layout-df9ac93cb02b2385.js +0 -1
  217. package/dist/runtime/web/.next/static/chunks/app/page-6610743f7de5f92a.js +0 -1
  218. package/dist/runtime/web/.next/static/chunks/c25e0690-e9b798b8de667da1.js +0 -1
  219. package/dist/runtime/web/.next/static/chunks/framework-57157ec4d37f64aa.js +0 -1
  220. package/dist/runtime/web/.next/static/chunks/main-app-156cc0c60371bd78.js +0 -1
  221. package/dist/runtime/web/.next/static/chunks/main-df25d367c47b1fec.js +0 -1
  222. package/dist/runtime/web/.next/static/chunks/pages/_app-9f629a5e1131d19f.js +0 -1
  223. package/dist/runtime/web/.next/static/chunks/pages/_error-9238238274c7efcd.js +0 -1
  224. package/dist/runtime/web/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
  225. package/dist/runtime/web/.next/static/chunks/webpack-cd50e39b423d1808.js +0 -1
  226. package/dist/runtime/web/.next/static/css/2728291c68f99cb1.css +0 -3
  227. package/dist/runtime/web/.next/static/css/4fbf378a264bd4ea.css +0 -1
  228. package/dist/runtime/web/.next/static/css/521bd69cc298cd1a.css +0 -1
  229. package/dist/runtime/web/.next/static/css/537e22821e101b87.css +0 -1
  230. package/dist/runtime/web/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
  231. package/dist/runtime/web/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
  232. package/dist/runtime/web/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
  233. package/dist/runtime/web/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
  234. package/dist/runtime/web/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
  235. package/dist/runtime/web/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
  236. package/dist/runtime/web/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
  237. package/dist/runtime/web/package.json +0 -65
  238. package/dist/runtime/web/server.js +0 -44
  239. package/dist/tsconfig.tsbuildinfo +0 -1
@@ -1,401 +0,0 @@
1
- import { spawn } from 'child_process';
2
- import { stripNextInjectedEnv } from '../utils/stripNextEnv.js';
3
- import { log } from '../lib/logger.js';
4
- import { getSettingsService } from '../settings-service.js';
5
- import { CoreAgentService } from '../agent/core-agent-service.js';
6
- import { ClaudeCodeAdapter, CodexCliProvider, GeminiCliProvider, } from '../agent/ai-providers/index.js';
7
- import { getQualityChecksDetectionPrompt } from '../agent/prompt-service.js';
8
- export class QualityPipeline {
9
- // Expose configured checks for external orchestration/streaming
10
- async getChecksFor() {
11
- return await this.getChecks();
12
- }
13
- // Load checks from settings only. If none are configured, return an empty list
14
- // so validation is skipped by default. Auto-detection should be an explicit user action
15
- // (via Settings → Detect Quality Checks) rather than an implicit fallback.
16
- async getChecks() {
17
- const settingsService = getSettingsService();
18
- await settingsService.initialize();
19
- const settings = settingsService.getSettings();
20
- const configured = settings.quality?.checks || [];
21
- if (configured.length === 0)
22
- return [];
23
- return configured
24
- .filter((c) => c.enabled !== false)
25
- .map((c) => ({
26
- name: c.name,
27
- command: c.command,
28
- args: c.args ?? [],
29
- timeout: c.timeout ?? 30000,
30
- }));
31
- }
32
- async detectQualityChecks(cwd) {
33
- // AI-only detection. If AI fails or returns nothing, we skip validation.
34
- try {
35
- const aiChecks = await this.aiDetectQualityChecks(cwd);
36
- return Array.isArray(aiChecks) ? aiChecks : [];
37
- }
38
- catch (e) {
39
- log.error('AI detection failed; no quality checks will be used', e, 'quality-pipeline:detect');
40
- return [];
41
- }
42
- }
43
- async aiDetectQualityChecks(cwd) {
44
- const prompt = getQualityChecksDetectionPrompt();
45
- const core = new CoreAgentService({ defaultProvider: this.getDefaultProviderName() });
46
- core.registerProvider('claude-code', new ClaudeCodeAdapter({
47
- defaultWorkingDirectory: cwd,
48
- defaultModel: 'claude-sonnet-4-20250514',
49
- }));
50
- core.registerProvider('codex', new CodexCliProvider({ defaultWorkingDirectory: cwd }));
51
- core.registerProvider('gemini', new GeminiCliProvider({ defaultWorkingDirectory: cwd }));
52
- const tools = ['Read', 'Grep', 'Glob'];
53
- const result = await core.execute({
54
- prompt,
55
- options: {
56
- workingDirectory: cwd,
57
- tools,
58
- maxTokens: 2000,
59
- },
60
- });
61
- const jsonStart = result.indexOf('{');
62
- const jsonEnd = result.lastIndexOf('}');
63
- if (jsonStart === -1 || jsonEnd === -1)
64
- throw new Error('No JSON in AI output');
65
- const text = result.slice(jsonStart, jsonEnd + 1);
66
- const parsed = JSON.parse(text);
67
- const items = (parsed.checks || []).filter((c) => c && c.name && c.command);
68
- return items.map((c) => ({
69
- name: c.name,
70
- command: c.command,
71
- args: Array.isArray(c.args) ? c.args : [],
72
- timeout: typeof c.timeout === 'number' ? c.timeout : 30000,
73
- }));
74
- }
75
- getDefaultProviderName() {
76
- try {
77
- const s = getSettingsService().getSettings();
78
- return s.agents?.defaultProvider || 'claude-code';
79
- }
80
- catch {
81
- return 'claude-code';
82
- }
83
- }
84
- /**
85
- * Public: Detect quality checks (AI-only) and persist to settings if found.
86
- * Does not execute any checks.
87
- */
88
- async detectAndPersistChecks(workingDirectory) {
89
- const settingsService = getSettingsService();
90
- await settingsService.initialize();
91
- const detected = await this.detectQualityChecks(workingDirectory);
92
- const result = detected.map((d) => ({ ...d, enabled: true }));
93
- if (result.length > 0) {
94
- try {
95
- await settingsService.updateSettings([{ path: ['quality', 'checks'], value: result }]);
96
- }
97
- catch (err) {
98
- log.warn('Failed to persist detected quality checks', err, 'quality-pipeline:detectPersist');
99
- }
100
- }
101
- return result;
102
- }
103
- /**
104
- * Run all quality checks in the specified directory
105
- */
106
- async runChecks(workingDirectory) {
107
- log.info(`Running quality checks in ${workingDirectory}`, { workingDirectory }, 'quality-pipeline:runChecks');
108
- const startTime = Date.now();
109
- // Run checks sequentially to avoid race conditions between tools
110
- const details = {};
111
- const outputs = {};
112
- let overall = true;
113
- const checks = await this.getChecks();
114
- if (!checks || checks.length === 0) {
115
- log.info('No quality checks detected; skipping validation', { workingDirectory }, 'quality-pipeline:runChecks');
116
- return {
117
- overall: true,
118
- timestamp: new Date().toISOString(),
119
- details: {},
120
- outputs: { skipped: 'No quality checks configured or detected. Skipping validation.' },
121
- };
122
- }
123
- for (const check of checks) {
124
- const result = await this.runCheck(check, workingDirectory);
125
- details[check.name] = result.passed;
126
- outputs[check.name] = result.output;
127
- if (!result.passed)
128
- overall = false;
129
- }
130
- const results = {
131
- overall,
132
- timestamp: new Date().toISOString(),
133
- details,
134
- outputs,
135
- };
136
- const duration = Date.now() - startTime;
137
- log.info(`Quality checks completed in ${duration}ms`, {
138
- workingDirectory,
139
- duration,
140
- overall,
141
- status: overall ? 'PASSED' : 'FAILED',
142
- results: results.details,
143
- }, 'quality-pipeline:runChecks');
144
- return results;
145
- }
146
- /**
147
- * Run checks with streaming logs via callback.
148
- */
149
- async runChecksStreaming(workingDirectory, onLog) {
150
- const startTime = Date.now();
151
- const details = {};
152
- const outputs = {};
153
- let overall = true;
154
- const checks = await this.getChecks();
155
- if (!checks || checks.length === 0) {
156
- onLog?.('[validation] No quality checks configured or detected. Skipping validation.');
157
- return {
158
- overall: true,
159
- timestamp: new Date().toISOString(),
160
- details: {},
161
- outputs: { skipped: 'No quality checks configured or detected. Skipping validation.' },
162
- };
163
- }
164
- for (const check of checks) {
165
- if (onLog)
166
- await onLog(`== ${check.name.toUpperCase()}: START ==`);
167
- try {
168
- const output = await this.runCommandStreaming(check.command, check.args, workingDirectory, check.timeout, (chunk) => onLog?.(String(chunk)));
169
- details[check.name] = true;
170
- outputs[check.name] = output.trim();
171
- if (onLog)
172
- await onLog(`== ${check.name.toUpperCase()}: PASSED ==`);
173
- }
174
- catch (error) {
175
- const msg = error instanceof Error ? error.message : String(error);
176
- const isMissing = this.isMissingCommandError(msg);
177
- if (isMissing) {
178
- details[check.name] = true;
179
- outputs[check.name] = `Skipped: command unavailable. ${msg}`;
180
- if (onLog)
181
- await onLog(`== ${check.name.toUpperCase()}: SKIPPED (missing command) ==`);
182
- }
183
- else {
184
- details[check.name] = false;
185
- outputs[check.name] = msg;
186
- overall = false;
187
- if (onLog)
188
- await onLog(`== ${check.name.toUpperCase()}: FAILED ==`);
189
- }
190
- }
191
- }
192
- const duration = Date.now() - startTime;
193
- if (onLog)
194
- await onLog(`[validation] Completed in ${duration}ms. Status: ${overall ? 'PASSED' : 'FAILED'}`);
195
- return {
196
- overall,
197
- timestamp: new Date().toISOString(),
198
- details,
199
- outputs,
200
- };
201
- }
202
- /**
203
- * Run a single quality check
204
- */
205
- async runCheck(check, workingDirectory) {
206
- try {
207
- const output = await this.runCommand(check.command, check.args, workingDirectory, check.timeout);
208
- return {
209
- passed: true,
210
- output: output.trim(),
211
- };
212
- }
213
- catch (error) {
214
- const msg = error instanceof Error ? error.message : String(error);
215
- const isMissing = this.isMissingCommandError(msg);
216
- if (isMissing) {
217
- return {
218
- passed: true,
219
- output: `Skipped: command unavailable. ${msg}`,
220
- };
221
- }
222
- return { passed: false, output: msg };
223
- }
224
- }
225
- /**
226
- * Run a command and return its output
227
- */
228
- runCommand(command, args, cwd, timeoutMs = 30000) {
229
- return new Promise((resolve, reject) => {
230
- const childProcess = spawn(command, args, {
231
- cwd,
232
- stdio: ['pipe', 'pipe', 'pipe'],
233
- shell: true,
234
- env: {
235
- ...stripNextInjectedEnv(process.env),
236
- NODE_ENV: 'production',
237
- },
238
- });
239
- let stdout = '';
240
- let stderr = '';
241
- let settled = false;
242
- const cleanup = () => {
243
- if (settled)
244
- return;
245
- settled = true;
246
- clearTimeout(timer);
247
- clearTimeout(killTimer);
248
- };
249
- let killTimer;
250
- const timer = setTimeout(() => {
251
- if (settled)
252
- return;
253
- // First try SIGTERM
254
- childProcess.kill('SIGTERM');
255
- // If process doesn't exit within 5 seconds, force kill with SIGKILL
256
- killTimer = setTimeout(() => {
257
- if (!settled) {
258
- childProcess.kill('SIGKILL');
259
- cleanup();
260
- reject(new Error(`Command "${command} ${args.join(' ')}" timed out after ${timeoutMs}ms and was force killed`));
261
- }
262
- }, 5000);
263
- // Set timeout error
264
- setTimeout(() => {
265
- if (!settled) {
266
- cleanup();
267
- reject(new Error(`Command "${command} ${args.join(' ')}" timed out after ${timeoutMs}ms`));
268
- }
269
- }, 100);
270
- }, timeoutMs);
271
- childProcess.stdout?.on('data', (data) => {
272
- stdout += data.toString();
273
- });
274
- childProcess.stderr?.on('data', (data) => {
275
- stderr += data.toString();
276
- });
277
- childProcess.on('close', (code) => {
278
- cleanup();
279
- const output = stdout + (stderr ? `\n--- STDERR ---\n${stderr}` : '');
280
- if (code === 0) {
281
- resolve(output);
282
- }
283
- else {
284
- reject(new Error(`Command "${command} ${args.join(' ')}" failed with code ${code}\n${output}`));
285
- }
286
- });
287
- childProcess.on('error', (error) => {
288
- cleanup();
289
- reject(error);
290
- });
291
- });
292
- }
293
- runCommandStreaming(command, args, cwd, timeoutMs = 30000, onChunk) {
294
- return new Promise((resolve, reject) => {
295
- const childProcess = spawn(command, args, {
296
- cwd,
297
- stdio: ['pipe', 'pipe', 'pipe'],
298
- shell: true,
299
- env: {
300
- ...stripNextInjectedEnv(process.env),
301
- NODE_ENV: 'production',
302
- },
303
- });
304
- let stdout = '';
305
- let stderr = '';
306
- let settled = false;
307
- const pending = [];
308
- const cleanup = () => {
309
- if (settled)
310
- return;
311
- settled = true;
312
- clearTimeout(timer);
313
- clearTimeout(killTimer);
314
- };
315
- let killTimer;
316
- const timer = setTimeout(() => {
317
- if (settled)
318
- return;
319
- childProcess.kill('SIGTERM');
320
- killTimer = setTimeout(() => {
321
- if (!settled) {
322
- childProcess.kill('SIGKILL');
323
- cleanup();
324
- reject(new Error(`Command "${command} ${args.join(' ')}" timed out after ${timeoutMs}ms and was force killed`));
325
- }
326
- }, 5000);
327
- setTimeout(() => {
328
- if (!settled) {
329
- cleanup();
330
- reject(new Error(`Command "${command} ${args.join(' ')}" timed out after ${timeoutMs}ms`));
331
- }
332
- }, 100);
333
- }, timeoutMs);
334
- const handleData = (buff, isErr = false) => {
335
- const str = String(buff);
336
- if (isErr)
337
- stderr += str;
338
- else
339
- stdout += str;
340
- try {
341
- const maybe = onChunk?.(str);
342
- if (maybe && typeof maybe.then === 'function') {
343
- pending.push(maybe);
344
- }
345
- }
346
- catch (e) {
347
- log.error('Error handling data', e, 'quality-pipeline:runCommandStreaming');
348
- }
349
- };
350
- childProcess.stdout?.on('data', (data) => handleData(data, false));
351
- childProcess.stderr?.on('data', (data) => handleData(data, true));
352
- childProcess.on('close', async (code) => {
353
- cleanup();
354
- // Ensure all async log writes are flushed before resolving
355
- try {
356
- if (pending.length)
357
- await Promise.allSettled(pending);
358
- }
359
- catch (e) {
360
- log.error('Error setting pending', e, 'quality-pipeline:runCommandStreaming');
361
- }
362
- const output = stdout + (stderr ? `\n--- STDERR ---\n${stderr}` : '');
363
- if (code === 0)
364
- resolve(output);
365
- else
366
- reject(new Error(`Command "${command} ${args.join(' ')}" failed with code ${code}\n${output}`));
367
- });
368
- childProcess.on('error', (error) => {
369
- cleanup();
370
- reject(error);
371
- });
372
- });
373
- }
374
- isMissingCommandError(message) {
375
- const m = message.toLowerCase();
376
- return (m.includes('enoent') ||
377
- m.includes('command not found') ||
378
- m.includes('not recognized as an internal or external command') ||
379
- m.includes('missing script'));
380
- }
381
- /**
382
- * Run individual quality check by name
383
- */
384
- async runSingleCheck(checkName, workingDirectory) {
385
- const checks = await this.getChecks();
386
- const check = checks.find((c) => c.name === checkName);
387
- if (!check) {
388
- throw new Error(`Unknown check: ${checkName}`);
389
- }
390
- return this.runCheck(check, workingDirectory);
391
- }
392
- /**
393
- * Get quality pipeline configuration
394
- */
395
- getConfig() {
396
- return {
397
- checks: [],
398
- parallel: false,
399
- };
400
- }
401
- }