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,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
- }