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