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.
- package/dist/api.js +49 -0
- package/dist/cli.js +135 -0
- package/dist/ui/index-gnk6rhxs.js +9 -0
- package/dist/ui/index.html +10 -0
- package/dist/ui/index.js +2 -0
- package/package.json +10 -80
- package/README.md +0 -12
- package/dist/index.js +0 -114
- package/dist/runtime/api/.tsbuildinfo +0 -1
- package/dist/runtime/api/agent/agent-service.d.ts +0 -225
- package/dist/runtime/api/agent/agent-service.js +0 -904
- package/dist/runtime/api/agent/ai-providers/claude-code-adapter.d.ts +0 -61
- package/dist/runtime/api/agent/ai-providers/claude-code-adapter.js +0 -362
- package/dist/runtime/api/agent/ai-providers/codex-cli-provider.d.ts +0 -36
- package/dist/runtime/api/agent/ai-providers/codex-cli-provider.js +0 -347
- package/dist/runtime/api/agent/ai-providers/index.d.ts +0 -9
- package/dist/runtime/api/agent/ai-providers/index.js +0 -7
- package/dist/runtime/api/agent/ai-providers/types.d.ts +0 -182
- package/dist/runtime/api/agent/ai-providers/types.js +0 -5
- package/dist/runtime/api/agent/codex-cli-provider.test.d.ts +0 -1
- package/dist/runtime/api/agent/codex-cli-provider.test.js +0 -170
- package/dist/runtime/api/agent/core-agent-service.d.ts +0 -119
- package/dist/runtime/api/agent/core-agent-service.js +0 -267
- package/dist/runtime/api/agent/parsers.d.ts +0 -16
- package/dist/runtime/api/agent/parsers.js +0 -308
- package/dist/runtime/api/agent/prompt-service.d.ts +0 -30
- package/dist/runtime/api/agent/prompt-service.js +0 -449
- package/dist/runtime/api/agent/prompt-service.test.d.ts +0 -1
- package/dist/runtime/api/agent/prompt-service.test.js +0 -230
- package/dist/runtime/api/agent/routing-policy.d.ts +0 -171
- package/dist/runtime/api/agent/routing-policy.js +0 -196
- package/dist/runtime/api/agent/routing-policy.test.d.ts +0 -1
- package/dist/runtime/api/agent/routing-policy.test.js +0 -63
- package/dist/runtime/api/api/router-helpers.d.ts +0 -32
- package/dist/runtime/api/api/router-helpers.js +0 -31
- package/dist/runtime/api/api/routers/ai.d.ts +0 -200
- package/dist/runtime/api/api/routers/ai.js +0 -396
- package/dist/runtime/api/api/routers/executions.d.ts +0 -98
- package/dist/runtime/api/api/routers/executions.js +0 -94
- package/dist/runtime/api/api/routers/git.d.ts +0 -45
- package/dist/runtime/api/api/routers/git.js +0 -35
- package/dist/runtime/api/api/routers/provider-config.d.ts +0 -165
- package/dist/runtime/api/api/routers/provider-config.js +0 -252
- package/dist/runtime/api/api/routers/settings.d.ts +0 -139
- package/dist/runtime/api/api/routers/settings.js +0 -113
- package/dist/runtime/api/api/routers/tasks.d.ts +0 -141
- package/dist/runtime/api/api/routers/tasks.js +0 -238
- package/dist/runtime/api/api/routers/workflows.d.ts +0 -275
- package/dist/runtime/api/api/routers/workflows.js +0 -311
- package/dist/runtime/api/api/routers/worktrees.d.ts +0 -101
- package/dist/runtime/api/api/routers/worktrees.js +0 -80
- package/dist/runtime/api/api/trpc.d.ts +0 -118
- package/dist/runtime/api/api/trpc.js +0 -34
- package/dist/runtime/api/index.d.ts +0 -9
- package/dist/runtime/api/index.js +0 -117
- package/dist/runtime/api/lib/id-generator.d.ts +0 -70
- package/dist/runtime/api/lib/id-generator.js +0 -123
- package/dist/runtime/api/lib/local-config.d.ts +0 -245
- package/dist/runtime/api/lib/local-config.js +0 -288
- package/dist/runtime/api/lib/logger.d.ts +0 -11
- package/dist/runtime/api/lib/logger.js +0 -188
- package/dist/runtime/api/lib/provider-detection.d.ts +0 -59
- package/dist/runtime/api/lib/provider-detection.js +0 -244
- package/dist/runtime/api/lib/server/agent-service-singleton.d.ts +0 -6
- package/dist/runtime/api/lib/server/agent-service-singleton.js +0 -27
- package/dist/runtime/api/lib/server/bootstrap.d.ts +0 -38
- package/dist/runtime/api/lib/server/bootstrap.js +0 -197
- package/dist/runtime/api/lib/server/git-service-singleton.d.ts +0 -6
- package/dist/runtime/api/lib/server/git-service-singleton.js +0 -47
- package/dist/runtime/api/lib/server/project-root.d.ts +0 -2
- package/dist/runtime/api/lib/server/project-root.js +0 -61
- package/dist/runtime/api/lib/server/task-service-singleton.d.ts +0 -7
- package/dist/runtime/api/lib/server/task-service-singleton.js +0 -58
- package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.d.ts +0 -7
- package/dist/runtime/api/lib/server/vibing-orchestrator-singleton.js +0 -57
- package/dist/runtime/api/lib/trpc/client.d.ts +0 -1
- package/dist/runtime/api/lib/trpc/client.js +0 -5
- package/dist/runtime/api/lib/trpc/server.d.ts +0 -935
- package/dist/runtime/api/lib/trpc/server.js +0 -11
- package/dist/runtime/api/lib/trpc/ws-server.d.ts +0 -8
- package/dist/runtime/api/lib/trpc/ws-server.js +0 -33
- package/dist/runtime/api/persistence/database-service.d.ts +0 -14
- package/dist/runtime/api/persistence/database-service.js +0 -74
- package/dist/runtime/api/persistence/execution-log-persistence.d.ts +0 -90
- package/dist/runtime/api/persistence/execution-log-persistence.js +0 -410
- package/dist/runtime/api/persistence/execution-log-persistence.test.d.ts +0 -1
- package/dist/runtime/api/persistence/execution-log-persistence.test.js +0 -170
- package/dist/runtime/api/router.d.ts +0 -938
- package/dist/runtime/api/router.js +0 -34
- package/dist/runtime/api/settings-service.d.ts +0 -110
- package/dist/runtime/api/settings-service.js +0 -661
- package/dist/runtime/api/tasks/file-watcher.d.ts +0 -23
- package/dist/runtime/api/tasks/file-watcher.js +0 -88
- package/dist/runtime/api/tasks/task-file-parser.d.ts +0 -13
- package/dist/runtime/api/tasks/task-file-parser.js +0 -161
- package/dist/runtime/api/tasks/task-service.d.ts +0 -36
- package/dist/runtime/api/tasks/task-service.js +0 -173
- package/dist/runtime/api/types/index.d.ts +0 -186
- package/dist/runtime/api/types/index.js +0 -1
- package/dist/runtime/api/types/settings.d.ts +0 -94
- package/dist/runtime/api/types/settings.js +0 -2
- package/dist/runtime/api/types.d.ts +0 -2
- package/dist/runtime/api/types.js +0 -1
- package/dist/runtime/api/utils/env.d.ts +0 -6
- package/dist/runtime/api/utils/env.js +0 -12
- package/dist/runtime/api/utils/stripNextEnv.d.ts +0 -7
- package/dist/runtime/api/utils/stripNextEnv.js +0 -22
- package/dist/runtime/api/utils/title-slug.d.ts +0 -6
- package/dist/runtime/api/utils/title-slug.js +0 -77
- package/dist/runtime/api/utils/url.d.ts +0 -2
- package/dist/runtime/api/utils/url.js +0 -19
- package/dist/runtime/api/vcs/git-history-service.d.ts +0 -57
- package/dist/runtime/api/vcs/git-history-service.js +0 -228
- package/dist/runtime/api/vcs/git-service.d.ts +0 -127
- package/dist/runtime/api/vcs/git-service.js +0 -284
- package/dist/runtime/api/vcs/worktree-service.d.ts +0 -93
- package/dist/runtime/api/vcs/worktree-service.js +0 -506
- package/dist/runtime/api/vcs/worktree-service.test.d.ts +0 -1
- package/dist/runtime/api/vcs/worktree-service.test.js +0 -20
- package/dist/runtime/api/workflows/quality-pipeline.d.ts +0 -58
- package/dist/runtime/api/workflows/quality-pipeline.js +0 -400
- package/dist/runtime/api/workflows/vibing-orchestrator.d.ts +0 -318
- package/dist/runtime/api/workflows/vibing-orchestrator.js +0 -1891
- package/dist/runtime/web/.next/BUILD_ID +0 -1
- package/dist/runtime/web/.next/app-build-manifest.json +0 -66
- package/dist/runtime/web/.next/app-path-routes-manifest.json +0 -8
- package/dist/runtime/web/.next/build-manifest.json +0 -33
- package/dist/runtime/web/.next/package.json +0 -1
- package/dist/runtime/web/.next/prerender-manifest.json +0 -61
- package/dist/runtime/web/.next/react-loadable-manifest.json +0 -39
- package/dist/runtime/web/.next/required-server-files.json +0 -334
- package/dist/runtime/web/.next/routes-manifest.json +0 -70
- package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js +0 -1
- package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/.vibeman/assets/images/[...path]/route_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app/_not-found/page.js +0 -2
- package/dist/runtime/web/.next/server/app/_not-found/page.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/_not-found/page_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app/_not-found.html +0 -7
- package/dist/runtime/web/.next/server/app/_not-found.meta +0 -8
- package/dist/runtime/web/.next/server/app/_not-found.rsc +0 -22
- package/dist/runtime/web/.next/server/app/api/health/route.js +0 -1
- package/dist/runtime/web/.next/server/app/api/health/route.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/api/health/route_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js +0 -1
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/api/images/[...path]/route_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app/api/upload/route.js +0 -1
- package/dist/runtime/web/.next/server/app/api/upload/route.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/api/upload/route_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app/index.html +0 -7
- package/dist/runtime/web/.next/server/app/index.meta +0 -7
- package/dist/runtime/web/.next/server/app/index.rsc +0 -27
- package/dist/runtime/web/.next/server/app/page.js +0 -147
- package/dist/runtime/web/.next/server/app/page.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/app/page_client-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/app-paths-manifest.json +0 -8
- package/dist/runtime/web/.next/server/chunks/217.js +0 -1
- package/dist/runtime/web/.next/server/chunks/383.js +0 -6
- package/dist/runtime/web/.next/server/chunks/458.js +0 -1
- package/dist/runtime/web/.next/server/chunks/576.js +0 -18
- package/dist/runtime/web/.next/server/chunks/635.js +0 -22
- package/dist/runtime/web/.next/server/chunks/761.js +0 -1
- package/dist/runtime/web/.next/server/chunks/777.js +0 -3
- package/dist/runtime/web/.next/server/chunks/825.js +0 -1
- package/dist/runtime/web/.next/server/chunks/838.js +0 -1
- package/dist/runtime/web/.next/server/chunks/973.js +0 -15
- package/dist/runtime/web/.next/server/functions-config-manifest.json +0 -4
- package/dist/runtime/web/.next/server/middleware-build-manifest.js +0 -1
- package/dist/runtime/web/.next/server/middleware-manifest.json +0 -6
- package/dist/runtime/web/.next/server/middleware-react-loadable-manifest.js +0 -1
- package/dist/runtime/web/.next/server/next-font-manifest.js +0 -1
- package/dist/runtime/web/.next/server/next-font-manifest.json +0 -1
- package/dist/runtime/web/.next/server/pages/404.html +0 -7
- package/dist/runtime/web/.next/server/pages/500.html +0 -1
- package/dist/runtime/web/.next/server/pages/_app.js +0 -1
- package/dist/runtime/web/.next/server/pages/_app.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/pages/_document.js +0 -1
- package/dist/runtime/web/.next/server/pages/_document.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/pages/_error.js +0 -19
- package/dist/runtime/web/.next/server/pages/_error.js.nft.json +0 -1
- package/dist/runtime/web/.next/server/pages-manifest.json +0 -6
- package/dist/runtime/web/.next/server/server-reference-manifest.js +0 -1
- package/dist/runtime/web/.next/server/server-reference-manifest.json +0 -1
- package/dist/runtime/web/.next/server/webpack-runtime.js +0 -1
- package/dist/runtime/web/.next/static/5_15u1WQCxN1_eHZpldCv/_buildManifest.js +0 -1
- package/dist/runtime/web/.next/static/5_15u1WQCxN1_eHZpldCv/_ssgManifest.js +0 -1
- package/dist/runtime/web/.next/static/chunks/18-15c10d3288afef2e.js +0 -1
- package/dist/runtime/web/.next/static/chunks/1c0ca389.537bbe362e3ffbd9.js +0 -3
- package/dist/runtime/web/.next/static/chunks/22747d63-ad5da0c19f4cfe41.js +0 -71
- package/dist/runtime/web/.next/static/chunks/355.056c2645878a799a.js +0 -1
- package/dist/runtime/web/.next/static/chunks/420.a5ccf151c9e2b2f1.js +0 -1
- package/dist/runtime/web/.next/static/chunks/439.1be0c6242fd248d5.js +0 -15
- package/dist/runtime/web/.next/static/chunks/440.c52e7c0f797e22b2.js +0 -1
- package/dist/runtime/web/.next/static/chunks/575-e2478287c27da87b.js +0 -1
- package/dist/runtime/web/.next/static/chunks/691.920d88c115087314.js +0 -1
- package/dist/runtime/web/.next/static/chunks/765-e838910065b50c3d.js +0 -1
- package/dist/runtime/web/.next/static/chunks/823-6f371a6e829adbba.js +0 -63
- package/dist/runtime/web/.next/static/chunks/87c73c54-09e1ba5c70e60a51.js +0 -1
- package/dist/runtime/web/.next/static/chunks/891cff7f.0f71fc028f87e683.js +0 -1
- package/dist/runtime/web/.next/static/chunks/8bb4d8db-3e2aa02b0a2384b9.js +0 -1
- package/dist/runtime/web/.next/static/chunks/9af238c7-271a911d4e99ab18.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/.vibeman/assets/images/[...path]/route-751c9265a65409e5.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/_not-found/page-1cb74d1cba27d0ab.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/api/health/route-751c9265a65409e5.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/api/images/[...path]/route-751c9265a65409e5.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/api/upload/route-751c9265a65409e5.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/layout-8435322f09fd0975.js +0 -1
- package/dist/runtime/web/.next/static/chunks/app/page-9fe7d75095b4ccec.js +0 -1
- package/dist/runtime/web/.next/static/chunks/cac567b0-5b77dd12911823cd.js +0 -1
- package/dist/runtime/web/.next/static/chunks/framework-2518f1345b5b2806.js +0 -1
- package/dist/runtime/web/.next/static/chunks/main-17665e5e39de9a8a.js +0 -1
- package/dist/runtime/web/.next/static/chunks/main-app-c0b0f5ba4f7f9d75.js +0 -1
- package/dist/runtime/web/.next/static/chunks/pages/_app-d6f6b3bbc3d81ee1.js +0 -1
- package/dist/runtime/web/.next/static/chunks/pages/_error-75a96cf1997cc3b9.js +0 -1
- package/dist/runtime/web/.next/static/chunks/polyfills-42372ed130431b0a.js +0 -1
- package/dist/runtime/web/.next/static/chunks/webpack-c8de37305b4635cf.js +0 -1
- package/dist/runtime/web/.next/static/css/08c950681f1a9a92.css +0 -1
- package/dist/runtime/web/.next/static/css/2728291c68f99cb1.css +0 -3
- package/dist/runtime/web/.next/static/css/521bd69cc298cd1a.css +0 -1
- package/dist/runtime/web/.next/static/css/537e22821e101b87.css +0 -1
- package/dist/runtime/web/.next/static/media/19cfc7226ec3afaa-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/21350d82a1f187e9-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/8e9860b6e62d6359-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/ba9851c3c22cd980-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/c5fe6dc8356a8c31-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/df0a9ae256c0569c-s.woff2 +0 -0
- package/dist/runtime/web/.next/static/media/e4af272ccee01ff0-s.p.woff2 +0 -0
- package/dist/runtime/web/package.json +0 -65
- package/dist/runtime/web/server.js +0 -44
- 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
|
-
}
|