vibepro 0.1.0-alpha.0
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/LICENSE +201 -0
- package/NOTICE +9 -0
- package/README.ja.md +448 -0
- package/README.md +520 -0
- package/agent-instructions/codex/AGENTS.vibepro.md +45 -0
- package/bin/vibepro.js +9 -0
- package/docs/assets/vibepro-header.png +0 -0
- package/package.json +51 -0
- package/skills/vibepro-diagnosis-packages/SKILL.md +133 -0
- package/skills/vibepro-human-review/SKILL.md +73 -0
- package/skills/vibepro-story-refactor/SKILL.md +89 -0
- package/skills/vibepro-workflow/SKILL.md +139 -0
- package/src/agent-harness-map.js +230 -0
- package/src/agent-harness-scanner.js +337 -0
- package/src/agent-review.js +2180 -0
- package/src/api-boundary-scanner.js +452 -0
- package/src/architecture-profiler.js +423 -0
- package/src/authorization-scoring.js +149 -0
- package/src/brainbase-importer.js +534 -0
- package/src/change-risk-classifier.js +195 -0
- package/src/check-packs.js +605 -0
- package/src/checkpoint-manager.js +233 -0
- package/src/cli.js +2213 -0
- package/src/code-quality-scanner.js +310 -0
- package/src/codex-manager.js +143 -0
- package/src/component-style-scanner.js +336 -0
- package/src/coverage-report.js +99 -0
- package/src/database-access-scanner.js +163 -0
- package/src/decision-records.js +315 -0
- package/src/design-modernize.js +1435 -0
- package/src/design-system.js +1732 -0
- package/src/diagnostic-engine.js +1945 -0
- package/src/diagram-requirement-resolver.js +194 -0
- package/src/doctor.js +677 -0
- package/src/environment-graph.js +424 -0
- package/src/execution-state.js +849 -0
- package/src/explore-evidence.js +425 -0
- package/src/flow-design-scanner.js +896 -0
- package/src/flow-verifier.js +887 -0
- package/src/gesture-interaction-scanner.js +330 -0
- package/src/graph-context.js +263 -0
- package/src/graphify-adapter.js +189 -0
- package/src/html-report.js +1035 -0
- package/src/journey-map.js +1299 -0
- package/src/language.js +48 -0
- package/src/lazy-pattern-detector.js +182 -0
- package/src/local-dev-scanner.js +135 -0
- package/src/managed-worktree-gate.js +187 -0
- package/src/managed-worktree.js +766 -0
- package/src/merge-manager.js +501 -0
- package/src/network-contract-scanner.js +442 -0
- package/src/nocodb-story-sync.js +386 -0
- package/src/oss-readiness-scanner.js +417 -0
- package/src/performance-evidence.js +756 -0
- package/src/performance-measurer.js +591 -0
- package/src/pr-manager.js +8220 -0
- package/src/presets.js +682 -0
- package/src/public-discovery-scanner.js +519 -0
- package/src/refactoring-delta-reporter.js +367 -0
- package/src/refactoring-opportunity-generator.js +797 -0
- package/src/regression-risk-scanner.js +146 -0
- package/src/repo-status.js +266 -0
- package/src/report-fingerprint.js +188 -0
- package/src/report-pr-body-prompt-template.md +108 -0
- package/src/report-pr-body-schema.json +95 -0
- package/src/report-store.js +135 -0
- package/src/report-validator.js +192 -0
- package/src/requirement-consistency.js +1066 -0
- package/src/runtime-info.js +134 -0
- package/src/self-dogfood-scanner.js +476 -0
- package/src/session-learning.js +164 -0
- package/src/skills-manager.js +157 -0
- package/src/spec-drift.js +378 -0
- package/src/spec-fingerprint.js +445 -0
- package/src/spec-prompt-template.md +155 -0
- package/src/spec-schema.json +219 -0
- package/src/spec-store.js +258 -0
- package/src/spec-validator.js +459 -0
- package/src/static-site-scanner.js +316 -0
- package/src/story-candidate-generator.js +85 -0
- package/src/story-catalog-generator.js +2813 -0
- package/src/story-html.js +156 -0
- package/src/story-manager.js +2144 -0
- package/src/story-task-generator.js +522 -0
- package/src/task-manager.js +1029 -0
- package/src/terminal-link-scanner.js +238 -0
- package/src/usage-report.js +417 -0
- package/src/verification-evidence.js +284 -0
- package/src/workspace.js +126 -0
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
const WORKFLOW_KEYWORDS = [
|
|
2
|
+
/workflow/i,
|
|
3
|
+
/preflight/i,
|
|
4
|
+
/poll(?:ing)?/i,
|
|
5
|
+
/retry/i,
|
|
6
|
+
/queue/i,
|
|
7
|
+
/worker/i,
|
|
8
|
+
/\bstate\b/i,
|
|
9
|
+
/\bstatus\b/i,
|
|
10
|
+
/resume/i,
|
|
11
|
+
/legacy/i,
|
|
12
|
+
/\bv1\b/i,
|
|
13
|
+
/auth/i,
|
|
14
|
+
/認証/,
|
|
15
|
+
/状態/,
|
|
16
|
+
/再開/,
|
|
17
|
+
/検出/,
|
|
18
|
+
/キュー/
|
|
19
|
+
];
|
|
20
|
+
|
|
21
|
+
export function classifyChangeRisk({ fileGroups = {}, storySource = {}, networkContracts = null, regressionRisk = null } = {}) {
|
|
22
|
+
const sourceFiles = fileGroups.source?.files ?? [];
|
|
23
|
+
const testFiles = fileGroups.tests?.files ?? [];
|
|
24
|
+
const allFiles = [
|
|
25
|
+
...sourceFiles,
|
|
26
|
+
...testFiles,
|
|
27
|
+
...(fileGroups.repo_control?.files ?? []),
|
|
28
|
+
...(fileGroups.story_docs?.files ?? []),
|
|
29
|
+
...(fileGroups.specifications?.files ?? [])
|
|
30
|
+
];
|
|
31
|
+
const storyText = [
|
|
32
|
+
storySource?.title,
|
|
33
|
+
storySource?.requirement_title,
|
|
34
|
+
storySource?.background,
|
|
35
|
+
storySource?.policy,
|
|
36
|
+
...(storySource?.acceptance_criteria ?? [])
|
|
37
|
+
].filter(Boolean).join(' ');
|
|
38
|
+
// Regression-risk hotspots that the diff actually touches. A changed module
|
|
39
|
+
// with a large call-graph blast radius (and, when coverage is known, a thin
|
|
40
|
+
// safety net) warrants heavier gates than its file paths alone would suggest.
|
|
41
|
+
const regressionHits = resolveRegressionHits({ sourceFiles, regressionRisk });
|
|
42
|
+
const criticalRegressionHits = regressionHits.filter((hit) => hit.priority === 'critical');
|
|
43
|
+
const highRegressionHits = regressionHits.filter((hit) => hit.risk_tier === 'high' || hit.priority === 'critical');
|
|
44
|
+
const riskSurfaces = detectRiskSurfaces({
|
|
45
|
+
sourceFiles,
|
|
46
|
+
allFiles,
|
|
47
|
+
storyText,
|
|
48
|
+
networkContracts,
|
|
49
|
+
hasRegressionBlastRadius: highRegressionHits.length > 0
|
|
50
|
+
});
|
|
51
|
+
const reasons = buildReasons({ riskSurfaces, sourceFiles, allFiles, storyText, networkContracts });
|
|
52
|
+
appendRegressionReasons(reasons, { criticalRegressionHits, highRegressionHits });
|
|
53
|
+
const hasWorkflowSignal = WORKFLOW_KEYWORDS.some((pattern) => pattern.test(storyText) || allFiles.some((file) => pattern.test(file)));
|
|
54
|
+
const crossSurface = riskSurfaces.filter((surface) => surface !== 'test_coverage').length >= 3;
|
|
55
|
+
const coreWorkflowHeavy = riskSurfaces.includes('core_workflow_state') && hasWorkflowSignal;
|
|
56
|
+
const baseProfile = (crossSurface && hasWorkflowSignal) || coreWorkflowHeavy
|
|
57
|
+
? 'workflow_heavy'
|
|
58
|
+
: riskSurfaces.includes('frontend_interaction')
|
|
59
|
+
? 'ui_interaction'
|
|
60
|
+
: (riskSurfaces.includes('server_api') || riskSurfaces.includes('auth_boundary') || riskSurfaces.includes('legacy_v1_compatibility'))
|
|
61
|
+
? 'api_contract'
|
|
62
|
+
: 'light';
|
|
63
|
+
// A changed critical hotspot (large blast radius + low coverage) is the
|
|
64
|
+
// genuine regression trap, so it forces the heaviest gate profile outright.
|
|
65
|
+
const profile = criticalRegressionHits.length > 0 ? 'workflow_heavy' : baseProfile;
|
|
66
|
+
const changeType = profile === 'workflow_heavy'
|
|
67
|
+
? 'cross_surface_workflow_change'
|
|
68
|
+
: profile === 'ui_interaction'
|
|
69
|
+
? 'ui_interaction_change'
|
|
70
|
+
: profile === 'api_contract'
|
|
71
|
+
? 'api_contract_change'
|
|
72
|
+
: 'simple_code_change';
|
|
73
|
+
return {
|
|
74
|
+
schema_version: '0.1.0',
|
|
75
|
+
profile,
|
|
76
|
+
change_type: changeType,
|
|
77
|
+
risk_surfaces: riskSurfaces,
|
|
78
|
+
reasons,
|
|
79
|
+
required_gate_profile: profile,
|
|
80
|
+
regression_hotspots: regressionHits,
|
|
81
|
+
regression_escalated: criticalRegressionHits.length > 0
|
|
82
|
+
};
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function resolveRegressionHits({ sourceFiles, regressionRisk }) {
|
|
86
|
+
const hotspots = regressionRisk?.hotspots ?? [];
|
|
87
|
+
if (!Array.isArray(hotspots) || hotspots.length === 0) return [];
|
|
88
|
+
const changedSource = new Set(sourceFiles);
|
|
89
|
+
return hotspots
|
|
90
|
+
.filter((hotspot) => hotspot && changedSource.has(hotspot.file))
|
|
91
|
+
.map((hotspot) => ({
|
|
92
|
+
file: hotspot.file,
|
|
93
|
+
fan_in: hotspot.fan_in,
|
|
94
|
+
coverage_pct: hotspot.coverage_pct ?? null,
|
|
95
|
+
risk_tier: hotspot.risk_tier,
|
|
96
|
+
priority: hotspot.priority ?? hotspot.risk_tier
|
|
97
|
+
}));
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
function appendRegressionReasons(reasons, { criticalRegressionHits, highRegressionHits }) {
|
|
101
|
+
if (criticalRegressionHits.length > 0) {
|
|
102
|
+
const files = criticalRegressionHits.map((hit) => hit.file).join(', ');
|
|
103
|
+
reasons.push(`critical regression hotspot changed (large blast radius + low coverage): ${files}`);
|
|
104
|
+
} else if (highRegressionHits.length > 0) {
|
|
105
|
+
const files = highRegressionHits.map((hit) => hit.file).join(', ');
|
|
106
|
+
reasons.push(`high blast-radius module changed (many call-graph dependents): ${files}`);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function detectRiskSurfaces({ sourceFiles, allFiles, storyText, networkContracts, hasRegressionBlastRadius = false }) {
|
|
111
|
+
const surfaces = new Set();
|
|
112
|
+
if (hasRegressionBlastRadius) surfaces.add('regression_blast_radius');
|
|
113
|
+
if (sourceFiles.some(isUiPath)) surfaces.add('frontend_interaction');
|
|
114
|
+
if (sourceFiles.some(isApiPath) || (networkContracts?.introduced_api_client_call_count ?? 0) > 0) surfaces.add('server_api');
|
|
115
|
+
if (sourceFiles.some(isServicePath)) surfaces.add('service_orchestration');
|
|
116
|
+
if (sourceFiles.some(isCoreWorkflowPath)) surfaces.add('core_workflow_state');
|
|
117
|
+
if (sourceFiles.some(isGateOrchestrationPath)) surfaces.add('gate_orchestration');
|
|
118
|
+
if (sourceFiles.some(isVerificationEvidencePath)) surfaces.add('verification_evidence');
|
|
119
|
+
if (sourceFiles.some(isReviewLifecyclePath)) surfaces.add('review_lifecycle');
|
|
120
|
+
if (sourceFiles.some(isDatabasePath)) surfaces.add('database_state');
|
|
121
|
+
if (sourceFiles.some((file) => !isUiPath(file) && isQueueWorkerPath(file))) surfaces.add('queue_worker');
|
|
122
|
+
if (sourceFiles.some((file) => !isUiPath(file) && /retry|poll|status|state/i.test(file))) {
|
|
123
|
+
surfaces.add('polling_retry');
|
|
124
|
+
}
|
|
125
|
+
if (sourceFiles.some((file) => /auth|session|permission|middleware/i.test(file))) {
|
|
126
|
+
surfaces.add('auth_boundary');
|
|
127
|
+
}
|
|
128
|
+
if (sourceFiles.some((file) => /\/v1\/|legacy/i.test(file))) surfaces.add('legacy_v1_compatibility');
|
|
129
|
+
if (allFiles.some((file) => /\.(test|spec)\.[cm]?[jt]sx?$/.test(file))) surfaces.add('test_coverage');
|
|
130
|
+
return [...surfaces].sort();
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
function buildReasons({ riskSurfaces, sourceFiles, allFiles, storyText, networkContracts }) {
|
|
134
|
+
const reasons = [];
|
|
135
|
+
if (riskSurfaces.includes('regression_blast_radius')) reasons.push('changed module has a large call-graph blast radius');
|
|
136
|
+
if (riskSurfaces.includes('frontend_interaction')) reasons.push('UI-facing source files changed');
|
|
137
|
+
if (riskSurfaces.includes('server_api')) reasons.push('API/server boundary changed');
|
|
138
|
+
if (riskSurfaces.includes('service_orchestration')) reasons.push('service/orchestration layer changed');
|
|
139
|
+
if (riskSurfaces.includes('core_workflow_state')) reasons.push('core workflow/state orchestration source changed');
|
|
140
|
+
if (riskSurfaces.includes('gate_orchestration')) reasons.push('PR/gate orchestration source changed');
|
|
141
|
+
if (riskSurfaces.includes('verification_evidence')) reasons.push('verification evidence binding source changed');
|
|
142
|
+
if (riskSurfaces.includes('review_lifecycle')) reasons.push('agent review lifecycle source changed');
|
|
143
|
+
if (riskSurfaces.includes('database_state')) reasons.push('database/state persistence surface detected');
|
|
144
|
+
if (riskSurfaces.includes('queue_worker')) reasons.push('queue/worker/job surface detected');
|
|
145
|
+
if (riskSurfaces.includes('polling_retry')) reasons.push('polling/retry/status workflow signal detected');
|
|
146
|
+
if (riskSurfaces.includes('auth_boundary')) reasons.push('auth/permission boundary signal detected');
|
|
147
|
+
if (riskSurfaces.includes('legacy_v1_compatibility')) reasons.push('legacy/v1 compatibility surface detected');
|
|
148
|
+
if ((networkContracts?.introduced_api_client_call_count ?? 0) > 0) reasons.push('new API client calls detected by network contract scanner');
|
|
149
|
+
if (WORKFLOW_KEYWORDS.some((pattern) => pattern.test(storyText) || allFiles.some((file) => pattern.test(file)))) {
|
|
150
|
+
reasons.push('Story or diff contains workflow/state transition keywords');
|
|
151
|
+
}
|
|
152
|
+
if (sourceFiles.length === 0) reasons.push('no runtime source files changed');
|
|
153
|
+
return reasons;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
function isUiPath(file) {
|
|
157
|
+
if (/\/api\//.test(file) || file.startsWith('api/')) return false;
|
|
158
|
+
return file.startsWith('src/app/')
|
|
159
|
+
|| file.startsWith('src/pages/')
|
|
160
|
+
|| file.startsWith('src/components/')
|
|
161
|
+
|| file.startsWith('components/')
|
|
162
|
+
|| /\.(tsx|jsx|css|scss|sass|less|vue|svelte)$/.test(file);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
function isApiPath(file) {
|
|
166
|
+
return /\/api\//.test(file) || file.startsWith('api/') || file.startsWith('server/');
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
function isServicePath(file) {
|
|
170
|
+
return /\/services?\//.test(file) || /\/actions?\//.test(file) || /orchestr/i.test(file);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
function isDatabasePath(file) {
|
|
174
|
+
return /prisma|db|database|repository|model|schema/i.test(file);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
function isQueueWorkerPath(file) {
|
|
178
|
+
return /queue|worker|job|scheduled-task|background-task/i.test(file);
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
function isCoreWorkflowPath(file) {
|
|
182
|
+
return /workflow|preflight|orchestrat|state-machine|statemachine|execution-state|transition|resume|replay/i.test(file);
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
function isGateOrchestrationPath(file) {
|
|
186
|
+
return /(^|\/)(pr-manager|change-risk-classifier)\.[cm]?js$/.test(file);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
function isVerificationEvidencePath(file) {
|
|
190
|
+
return /(^|\/)(verification-evidence|flow-verifier)\.[cm]?js$/.test(file);
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
function isReviewLifecyclePath(file) {
|
|
194
|
+
return /(^|\/)agent-review\.[cm]?js$/.test(file);
|
|
195
|
+
}
|