@codebakers/mcp 5.4.3 ā 5.5.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/INSTALL.md +221 -221
- package/LICENSE +21 -21
- package/README.md +412 -412
- package/dist/cli.js +29 -29
- package/dist/cli.js.map +1 -1
- package/dist/index.js +11 -0
- package/dist/index.js.map +1 -1
- package/dist/tools/analyze-mockups.js +37 -37
- package/dist/tools/autonomous-build.d.ts +18 -18
- package/dist/tools/autonomous-build.js +286 -286
- package/dist/tools/check-gate.js +6 -6
- package/dist/tools/check-scope.js +10 -10
- package/dist/tools/enforce-feature.js +15 -15
- package/dist/tools/fix-commit.js +18 -18
- package/dist/tools/fix-mockups.js +191 -191
- package/dist/tools/generate-api-route.js +155 -155
- package/dist/tools/generate-chatbot.js +306 -306
- package/dist/tools/generate-component.js +117 -117
- package/dist/tools/generate-docs.js +525 -525
- package/dist/tools/generate-e2e-tests.js +19 -19
- package/dist/tools/generate-migration.js +22 -22
- package/dist/tools/generate-schema.js +37 -37
- package/dist/tools/generate-spec.js +38 -38
- package/dist/tools/generate-store-contracts.js +42 -42
- package/dist/tools/generate-store.js +109 -109
- package/dist/tools/generate-unit-tests.js +57 -57
- package/dist/tools/map-dependencies.js +45 -45
- package/dist/tools/run-interview.js +142 -142
- package/dist/tools/setup-github.js +8 -8
- package/dist/tools/setup-supabase.js +8 -8
- package/dist/tools/setup-vercel.js +8 -8
- package/dist/tools/start.d.ts +12 -0
- package/dist/tools/start.d.ts.map +1 -0
- package/dist/tools/start.js +220 -0
- package/dist/tools/start.js.map +1 -0
- package/dist/tools/validate-mockups.js +19 -19
- package/package.json +50 -50
|
@@ -1,287 +1,287 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* codebakers_autonomous_build
|
|
3
|
-
*
|
|
4
|
-
* Full Autonomous Build Orchestrator
|
|
5
|
-
*
|
|
6
|
-
* Builds entire application from FLOWS.md with zero human intervention.
|
|
7
|
-
* Executes all features sequentially with full atomic unit protocol.
|
|
8
|
-
*/
|
|
9
|
-
import * as fs from 'fs/promises';
|
|
10
|
-
import * as path from 'path';
|
|
11
|
-
import { executeAtomicUnit } from './execute-atomic-unit';
|
|
12
|
-
import { verifyCompleteness } from './verify-completeness';
|
|
13
|
-
import { validateAccessibility } from './validate-accessibility';
|
|
14
|
-
import { optimizePerformance } from './optimize-performance';
|
|
15
|
-
import { scanSecurity } from './scan-security';
|
|
16
|
-
import { deployVercel } from './deploy-vercel';
|
|
17
|
-
import { generateDocs } from './generate-docs';
|
|
18
|
-
import { generateChatbot } from './generate-chatbot';
|
|
19
|
-
export async function autonomousBuild(args) {
|
|
20
|
-
const cwd = process.cwd();
|
|
21
|
-
const { mode, stop_on_error = false, skip_quality_gates = false, skip_deploy = false, skip_docs = false, skip_chatbot = false } = args;
|
|
22
|
-
console.error('š CodeBakers: Autonomous Build Starting');
|
|
23
|
-
try {
|
|
24
|
-
// Load FLOWS.md
|
|
25
|
-
const flowsPath = path.join(cwd, 'FLOWS.md');
|
|
26
|
-
const flowsExist = await fs.access(flowsPath).then(() => true).catch(() => false);
|
|
27
|
-
if (!flowsExist) {
|
|
28
|
-
return `š CodeBakers: Autonomous Build BLOCKED
|
|
29
|
-
|
|
30
|
-
ā FLOWS.md not found
|
|
31
|
-
|
|
32
|
-
Run codebakers_run_interview first to generate flows.`;
|
|
33
|
-
}
|
|
34
|
-
const flowsContent = await fs.readFile(flowsPath, 'utf-8');
|
|
35
|
-
// Extract features (simple parsing)
|
|
36
|
-
const features = extractFeatures(flowsContent, mode);
|
|
37
|
-
if (features.length === 0) {
|
|
38
|
-
return `š CodeBakers: No features to build
|
|
39
|
-
|
|
40
|
-
${mode === 'full' ? 'All features already complete' : 'No pending features found'}
|
|
41
|
-
|
|
42
|
-
Check FLOWS.md for status.`;
|
|
43
|
-
}
|
|
44
|
-
console.error(`Found ${features.length} features to build`);
|
|
45
|
-
const results = [];
|
|
46
|
-
// Build each feature sequentially
|
|
47
|
-
for (let i = 0; i < features.length; i++) {
|
|
48
|
-
const feature = features[i];
|
|
49
|
-
console.error(`\n[${i + 1}/${features.length}] Building: ${feature.name}`);
|
|
50
|
-
try {
|
|
51
|
-
// Execute atomic unit
|
|
52
|
-
const result = await executeAtomicUnit({
|
|
53
|
-
feature_name: feature.name,
|
|
54
|
-
entity: feature.entity || 'Item',
|
|
55
|
-
operations: feature.operations || ['list', 'create', 'update', 'delete'],
|
|
56
|
-
});
|
|
57
|
-
console.error(result);
|
|
58
|
-
// Verify completeness
|
|
59
|
-
const verification = await verifyCompleteness({ feature_name: feature.name });
|
|
60
|
-
console.error(verification);
|
|
61
|
-
results.push({ feature: feature.name, status: 'success' });
|
|
62
|
-
// Update FLOWS.md to mark complete
|
|
63
|
-
await markFlowComplete(cwd, feature.name);
|
|
64
|
-
}
|
|
65
|
-
catch (error) {
|
|
66
|
-
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
67
|
-
console.error(`ā Failed: ${errorMsg}`);
|
|
68
|
-
results.push({ feature: feature.name, status: 'failed', error: errorMsg });
|
|
69
|
-
if (stop_on_error) {
|
|
70
|
-
break;
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
// Quality Gates (after all features complete)
|
|
75
|
-
let qualityGates = null;
|
|
76
|
-
if (!skip_quality_gates && results.filter(r => r.status === 'success').length > 0) {
|
|
77
|
-
console.error('\nš Running Quality Gates...\n');
|
|
78
|
-
qualityGates = await runQualityGates(cwd, skip_deploy, skip_docs, skip_chatbot);
|
|
79
|
-
}
|
|
80
|
-
// Generate final report
|
|
81
|
-
const report = generateBuildReport(results, features.length, qualityGates);
|
|
82
|
-
return report;
|
|
83
|
-
}
|
|
84
|
-
catch (error) {
|
|
85
|
-
return `š CodeBakers: Autonomous Build Failed
|
|
86
|
-
|
|
87
|
-
Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
88
|
-
}
|
|
89
|
-
}
|
|
90
|
-
function extractFeatures(flowsContent, mode) {
|
|
91
|
-
const features = [];
|
|
92
|
-
// Simple extraction: look for flow headings
|
|
93
|
-
const flowMatches = flowsContent.matchAll(/## (\d+)\. (.+?) \((.+?)\)/g);
|
|
94
|
-
for (const match of flowMatches) {
|
|
95
|
-
const name = match[2];
|
|
96
|
-
const priority = match[3];
|
|
97
|
-
const status = flowsContent.includes(`${name}`) && flowsContent.includes('complete') ? 'complete' : 'pending';
|
|
98
|
-
if (mode === 'full' || (mode === 'remaining' && status === 'pending')) {
|
|
99
|
-
// Infer entity from flow name
|
|
100
|
-
let entity = 'Item';
|
|
101
|
-
if (name.toLowerCase().includes('message'))
|
|
102
|
-
entity = 'Message';
|
|
103
|
-
if (name.toLowerCase().includes('user'))
|
|
104
|
-
entity = 'User';
|
|
105
|
-
if (name.toLowerCase().includes('inbox'))
|
|
106
|
-
entity = 'Message';
|
|
107
|
-
features.push({
|
|
108
|
-
name,
|
|
109
|
-
entity,
|
|
110
|
-
priority,
|
|
111
|
-
operations: ['list', 'create', 'update', 'delete'],
|
|
112
|
-
});
|
|
113
|
-
}
|
|
114
|
-
}
|
|
115
|
-
return features;
|
|
116
|
-
}
|
|
117
|
-
async function markFlowComplete(cwd, featureName) {
|
|
118
|
-
const flowsPath = path.join(cwd, 'FLOWS.md');
|
|
119
|
-
let content = await fs.readFile(flowsPath, 'utf-8');
|
|
120
|
-
// Find the flow section and mark as complete
|
|
121
|
-
const regex = new RegExp(`(## \\d+\\. ${featureName}.+?\\*\\*Status:\\*\\*) pending`, 'g');
|
|
122
|
-
content = content.replace(regex, '$1 complete');
|
|
123
|
-
await fs.writeFile(flowsPath, content, 'utf-8');
|
|
124
|
-
}
|
|
125
|
-
async function runQualityGates(cwd, skipDeploy, skipDocs, skipChatbot) {
|
|
126
|
-
const gates = {
|
|
127
|
-
accessibility: null,
|
|
128
|
-
performance: null,
|
|
129
|
-
security: null,
|
|
130
|
-
deployment: null,
|
|
131
|
-
documentation: null,
|
|
132
|
-
chatbot: null
|
|
133
|
-
};
|
|
134
|
-
try {
|
|
135
|
-
// Gate 1: Accessibility
|
|
136
|
-
console.error('[1/6] Accessibility validation...');
|
|
137
|
-
const a11yResult = await validateAccessibility({ threshold: 90 });
|
|
138
|
-
gates.accessibility = a11yResult.includes('ā
') ? 'pass' : 'fail';
|
|
139
|
-
console.error(a11yResult.split('\n').slice(0, 5).join('\n')); // Show summary
|
|
140
|
-
// Gate 2: Performance
|
|
141
|
-
console.error('[2/6] Performance optimization...');
|
|
142
|
-
const perfResult = await optimizePerformance({ auto_fix: true });
|
|
143
|
-
gates.performance = 'pass'; // Always passes, just applies optimizations
|
|
144
|
-
console.error(perfResult.split('\n').slice(0, 5).join('\n'));
|
|
145
|
-
// Gate 3: Security
|
|
146
|
-
console.error('[3/6] Security scan...');
|
|
147
|
-
const secResult = await scanSecurity({ block_on_critical: true });
|
|
148
|
-
gates.security = secResult.includes('ā
PASS') ? 'pass' : secResult.includes('ā BLOCKED') ? 'blocked' : 'warnings';
|
|
149
|
-
console.error(secResult.split('\n').slice(0, 8).join('\n'));
|
|
150
|
-
// If security blocked, stop here
|
|
151
|
-
if (gates.security === 'blocked') {
|
|
152
|
-
console.error('\nā Security gate BLOCKED - fix critical issues before deployment');
|
|
153
|
-
return gates;
|
|
154
|
-
}
|
|
155
|
-
// Gate 4: Documentation
|
|
156
|
-
if (!skipDocs) {
|
|
157
|
-
console.error('[4/6] Generating documentation...');
|
|
158
|
-
const docsResult = await generateDocs({});
|
|
159
|
-
gates.documentation = docsResult.includes('ā
') ? 'generated' : 'failed';
|
|
160
|
-
console.error(docsResult.split('\n').slice(0, 5).join('\n'));
|
|
161
|
-
}
|
|
162
|
-
else {
|
|
163
|
-
gates.documentation = 'skipped';
|
|
164
|
-
}
|
|
165
|
-
// Gate 5: AI Chatbot
|
|
166
|
-
if (!skipChatbot) {
|
|
167
|
-
console.error('[5/6] Generating AI chatbot...');
|
|
168
|
-
const chatbotResult = await generateChatbot({});
|
|
169
|
-
gates.chatbot = chatbotResult.includes('ā
') ? 'generated' : 'failed';
|
|
170
|
-
console.error(chatbotResult.split('\n').slice(0, 5).join('\n'));
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
gates.chatbot = 'skipped';
|
|
174
|
-
}
|
|
175
|
-
// Gate 6: Deployment
|
|
176
|
-
if (!skipDeploy && gates.security !== 'blocked') {
|
|
177
|
-
console.error('[6/6] Deploying to Vercel...');
|
|
178
|
-
try {
|
|
179
|
-
const deployResult = await deployVercel({ production: true });
|
|
180
|
-
gates.deployment = deployResult.includes('ā
') ? 'deployed' : 'failed';
|
|
181
|
-
gates.deployment_url = deployResult.match(/https:\/\/[^\s]+/)?.[0];
|
|
182
|
-
console.error(deployResult.split('\n').slice(0, 5).join('\n'));
|
|
183
|
-
}
|
|
184
|
-
catch (error) {
|
|
185
|
-
gates.deployment = 'failed';
|
|
186
|
-
gates.deployment_error = error instanceof Error ? error.message : String(error);
|
|
187
|
-
console.error(`Deployment failed: ${gates.deployment_error}`);
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
else {
|
|
191
|
-
gates.deployment = 'skipped';
|
|
192
|
-
}
|
|
193
|
-
}
|
|
194
|
-
catch (error) {
|
|
195
|
-
console.error(`Quality gate error: ${error}`);
|
|
196
|
-
}
|
|
197
|
-
return gates;
|
|
198
|
-
}
|
|
199
|
-
function generateBuildReport(results, total, qualityGates = null) {
|
|
200
|
-
const successful = results.filter(r => r.status === 'success').length;
|
|
201
|
-
const failed = results.filter(r => r.status === 'failed').length;
|
|
202
|
-
let report = `š CodeBakers: Autonomous Build Complete\n\n`;
|
|
203
|
-
report += `## Build Summary\n\n`;
|
|
204
|
-
report += `**Features requested:** ${total}\n`;
|
|
205
|
-
report += `**Features completed:** ${successful} ā
\n`;
|
|
206
|
-
report += `**Features failed:** ${failed} ${failed > 0 ? 'ā' : ''}\n\n`;
|
|
207
|
-
if (successful > 0) {
|
|
208
|
-
report += `## ā
Successful Builds\n\n`;
|
|
209
|
-
for (const result of results.filter(r => r.status === 'success')) {
|
|
210
|
-
report += `- ${result.feature}\n`;
|
|
211
|
-
}
|
|
212
|
-
report += `\n`;
|
|
213
|
-
}
|
|
214
|
-
if (failed > 0) {
|
|
215
|
-
report += `## ā Failed Builds\n\n`;
|
|
216
|
-
for (const result of results.filter(r => r.status === 'failed')) {
|
|
217
|
-
report += `- ${result.feature}\n`;
|
|
218
|
-
if (result.error) {
|
|
219
|
-
report += ` Error: ${result.error}\n`;
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
report += `\n`;
|
|
223
|
-
}
|
|
224
|
-
// Quality Gates Section
|
|
225
|
-
if (qualityGates) {
|
|
226
|
-
report += `---\n\n`;
|
|
227
|
-
report += `## š Quality Gates\n\n`;
|
|
228
|
-
const gates = [
|
|
229
|
-
{ name: 'Accessibility', status: qualityGates.accessibility },
|
|
230
|
-
{ name: 'Performance', status: qualityGates.performance },
|
|
231
|
-
{ name: 'Security', status: qualityGates.security },
|
|
232
|
-
{ name: 'Documentation', status: qualityGates.documentation },
|
|
233
|
-
{ name: 'AI Chatbot', status: qualityGates.chatbot },
|
|
234
|
-
{ name: 'Deployment', status: qualityGates.deployment }
|
|
235
|
-
];
|
|
236
|
-
for (const gate of gates) {
|
|
237
|
-
const emoji = gate.status === 'pass' || gate.status === 'generated' || gate.status === 'deployed'
|
|
238
|
-
? 'ā
'
|
|
239
|
-
: gate.status === 'fail' || gate.status === 'blocked'
|
|
240
|
-
? 'ā'
|
|
241
|
-
: gate.status === 'warnings'
|
|
242
|
-
? 'ā ļø'
|
|
243
|
-
: 'āļø';
|
|
244
|
-
report += `- ${emoji} **${gate.name}:** ${gate.status}\n`;
|
|
245
|
-
}
|
|
246
|
-
report += `\n`;
|
|
247
|
-
// Deployment URL if available
|
|
248
|
-
if (qualityGates.deployment_url) {
|
|
249
|
-
report += `š **Live URL:** ${qualityGates.deployment_url}\n\n`;
|
|
250
|
-
}
|
|
251
|
-
// Security blocked warning
|
|
252
|
-
if (qualityGates.security === 'blocked') {
|
|
253
|
-
report += `ā ļø **Security gate BLOCKED** - Fix critical vulnerabilities before deployment\n\n`;
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
report += `---\n\n`;
|
|
257
|
-
if (failed === 0 && qualityGates && qualityGates.deployment === 'deployed') {
|
|
258
|
-
report += `## š BUILD COMPLETE - PRODUCTION READY\n\n`;
|
|
259
|
-
report += `**Your app is live!**\n\n`;
|
|
260
|
-
if (qualityGates.deployment_url) {
|
|
261
|
-
report += `**URL:** ${qualityGates.deployment_url}\n\n`;
|
|
262
|
-
}
|
|
263
|
-
report += `**Quality Scores:**\n`;
|
|
264
|
-
report += `- Accessibility: ${qualityGates.accessibility === 'pass' ? 'ā
Compliant' : 'ā ļø Issues found'}\n`;
|
|
265
|
-
report += `- Performance: ā
Optimized\n`;
|
|
266
|
-
report += `- Security: ${qualityGates.security === 'pass' ? 'ā
Secure' : qualityGates.security === 'warnings' ? 'ā ļø Warnings' : 'ā Critical issues'}\n`;
|
|
267
|
-
report += `- Documentation: ${qualityGates.documentation === 'generated' ? 'ā
Generated' : 'Not generated'}\n`;
|
|
268
|
-
report += `- AI Chatbot: ${qualityGates.chatbot === 'generated' ? 'ā
Integrated' : 'Not integrated'}\n\n`;
|
|
269
|
-
report += `**Time saved:** Entire app built autonomously from mockups to production\n`;
|
|
270
|
-
}
|
|
271
|
-
else if (failed === 0) {
|
|
272
|
-
report += `## š All Features Complete!\n\n`;
|
|
273
|
-
report += `**Next steps:**\n`;
|
|
274
|
-
report += `1. Run tests: codebakers_run_tests { test_type: "all" }\n`;
|
|
275
|
-
report += `2. Review quality gates above\n`;
|
|
276
|
-
report += `3. Deploy: codebakers_deploy_vercel { production: true }\n`;
|
|
277
|
-
}
|
|
278
|
-
else {
|
|
279
|
-
report += `## ā ļø Some Features Failed\n\n`;
|
|
280
|
-
report += `**Next steps:**\n`;
|
|
281
|
-
report += `1. Review error messages above\n`;
|
|
282
|
-
report += `2. Fix issues manually\n`;
|
|
283
|
-
report += `3. Re-run: codebakers_autonomous_build { mode: "remaining" }\n`;
|
|
284
|
-
}
|
|
285
|
-
return report;
|
|
286
|
-
}
|
|
1
|
+
/**
|
|
2
|
+
* codebakers_autonomous_build
|
|
3
|
+
*
|
|
4
|
+
* Full Autonomous Build Orchestrator
|
|
5
|
+
*
|
|
6
|
+
* Builds entire application from FLOWS.md with zero human intervention.
|
|
7
|
+
* Executes all features sequentially with full atomic unit protocol.
|
|
8
|
+
*/
|
|
9
|
+
import * as fs from 'fs/promises';
|
|
10
|
+
import * as path from 'path';
|
|
11
|
+
import { executeAtomicUnit } from './execute-atomic-unit';
|
|
12
|
+
import { verifyCompleteness } from './verify-completeness';
|
|
13
|
+
import { validateAccessibility } from './validate-accessibility';
|
|
14
|
+
import { optimizePerformance } from './optimize-performance';
|
|
15
|
+
import { scanSecurity } from './scan-security';
|
|
16
|
+
import { deployVercel } from './deploy-vercel';
|
|
17
|
+
import { generateDocs } from './generate-docs';
|
|
18
|
+
import { generateChatbot } from './generate-chatbot';
|
|
19
|
+
export async function autonomousBuild(args) {
|
|
20
|
+
const cwd = process.cwd();
|
|
21
|
+
const { mode, stop_on_error = false, skip_quality_gates = false, skip_deploy = false, skip_docs = false, skip_chatbot = false } = args;
|
|
22
|
+
console.error('š CodeBakers: Autonomous Build Starting');
|
|
23
|
+
try {
|
|
24
|
+
// Load FLOWS.md
|
|
25
|
+
const flowsPath = path.join(cwd, 'FLOWS.md');
|
|
26
|
+
const flowsExist = await fs.access(flowsPath).then(() => true).catch(() => false);
|
|
27
|
+
if (!flowsExist) {
|
|
28
|
+
return `š CodeBakers: Autonomous Build BLOCKED
|
|
29
|
+
|
|
30
|
+
ā FLOWS.md not found
|
|
31
|
+
|
|
32
|
+
Run codebakers_run_interview first to generate flows.`;
|
|
33
|
+
}
|
|
34
|
+
const flowsContent = await fs.readFile(flowsPath, 'utf-8');
|
|
35
|
+
// Extract features (simple parsing)
|
|
36
|
+
const features = extractFeatures(flowsContent, mode);
|
|
37
|
+
if (features.length === 0) {
|
|
38
|
+
return `š CodeBakers: No features to build
|
|
39
|
+
|
|
40
|
+
${mode === 'full' ? 'All features already complete' : 'No pending features found'}
|
|
41
|
+
|
|
42
|
+
Check FLOWS.md for status.`;
|
|
43
|
+
}
|
|
44
|
+
console.error(`Found ${features.length} features to build`);
|
|
45
|
+
const results = [];
|
|
46
|
+
// Build each feature sequentially
|
|
47
|
+
for (let i = 0; i < features.length; i++) {
|
|
48
|
+
const feature = features[i];
|
|
49
|
+
console.error(`\n[${i + 1}/${features.length}] Building: ${feature.name}`);
|
|
50
|
+
try {
|
|
51
|
+
// Execute atomic unit
|
|
52
|
+
const result = await executeAtomicUnit({
|
|
53
|
+
feature_name: feature.name,
|
|
54
|
+
entity: feature.entity || 'Item',
|
|
55
|
+
operations: feature.operations || ['list', 'create', 'update', 'delete'],
|
|
56
|
+
});
|
|
57
|
+
console.error(result);
|
|
58
|
+
// Verify completeness
|
|
59
|
+
const verification = await verifyCompleteness({ feature_name: feature.name });
|
|
60
|
+
console.error(verification);
|
|
61
|
+
results.push({ feature: feature.name, status: 'success' });
|
|
62
|
+
// Update FLOWS.md to mark complete
|
|
63
|
+
await markFlowComplete(cwd, feature.name);
|
|
64
|
+
}
|
|
65
|
+
catch (error) {
|
|
66
|
+
const errorMsg = error instanceof Error ? error.message : String(error);
|
|
67
|
+
console.error(`ā Failed: ${errorMsg}`);
|
|
68
|
+
results.push({ feature: feature.name, status: 'failed', error: errorMsg });
|
|
69
|
+
if (stop_on_error) {
|
|
70
|
+
break;
|
|
71
|
+
}
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
// Quality Gates (after all features complete)
|
|
75
|
+
let qualityGates = null;
|
|
76
|
+
if (!skip_quality_gates && results.filter(r => r.status === 'success').length > 0) {
|
|
77
|
+
console.error('\nš Running Quality Gates...\n');
|
|
78
|
+
qualityGates = await runQualityGates(cwd, skip_deploy, skip_docs, skip_chatbot);
|
|
79
|
+
}
|
|
80
|
+
// Generate final report
|
|
81
|
+
const report = generateBuildReport(results, features.length, qualityGates);
|
|
82
|
+
return report;
|
|
83
|
+
}
|
|
84
|
+
catch (error) {
|
|
85
|
+
return `š CodeBakers: Autonomous Build Failed
|
|
86
|
+
|
|
87
|
+
Error: ${error instanceof Error ? error.message : String(error)}`;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
function extractFeatures(flowsContent, mode) {
|
|
91
|
+
const features = [];
|
|
92
|
+
// Simple extraction: look for flow headings
|
|
93
|
+
const flowMatches = flowsContent.matchAll(/## (\d+)\. (.+?) \((.+?)\)/g);
|
|
94
|
+
for (const match of flowMatches) {
|
|
95
|
+
const name = match[2];
|
|
96
|
+
const priority = match[3];
|
|
97
|
+
const status = flowsContent.includes(`${name}`) && flowsContent.includes('complete') ? 'complete' : 'pending';
|
|
98
|
+
if (mode === 'full' || (mode === 'remaining' && status === 'pending')) {
|
|
99
|
+
// Infer entity from flow name
|
|
100
|
+
let entity = 'Item';
|
|
101
|
+
if (name.toLowerCase().includes('message'))
|
|
102
|
+
entity = 'Message';
|
|
103
|
+
if (name.toLowerCase().includes('user'))
|
|
104
|
+
entity = 'User';
|
|
105
|
+
if (name.toLowerCase().includes('inbox'))
|
|
106
|
+
entity = 'Message';
|
|
107
|
+
features.push({
|
|
108
|
+
name,
|
|
109
|
+
entity,
|
|
110
|
+
priority,
|
|
111
|
+
operations: ['list', 'create', 'update', 'delete'],
|
|
112
|
+
});
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return features;
|
|
116
|
+
}
|
|
117
|
+
async function markFlowComplete(cwd, featureName) {
|
|
118
|
+
const flowsPath = path.join(cwd, 'FLOWS.md');
|
|
119
|
+
let content = await fs.readFile(flowsPath, 'utf-8');
|
|
120
|
+
// Find the flow section and mark as complete
|
|
121
|
+
const regex = new RegExp(`(## \\d+\\. ${featureName}.+?\\*\\*Status:\\*\\*) pending`, 'g');
|
|
122
|
+
content = content.replace(regex, '$1 complete');
|
|
123
|
+
await fs.writeFile(flowsPath, content, 'utf-8');
|
|
124
|
+
}
|
|
125
|
+
async function runQualityGates(cwd, skipDeploy, skipDocs, skipChatbot) {
|
|
126
|
+
const gates = {
|
|
127
|
+
accessibility: null,
|
|
128
|
+
performance: null,
|
|
129
|
+
security: null,
|
|
130
|
+
deployment: null,
|
|
131
|
+
documentation: null,
|
|
132
|
+
chatbot: null
|
|
133
|
+
};
|
|
134
|
+
try {
|
|
135
|
+
// Gate 1: Accessibility
|
|
136
|
+
console.error('[1/6] Accessibility validation...');
|
|
137
|
+
const a11yResult = await validateAccessibility({ threshold: 90 });
|
|
138
|
+
gates.accessibility = a11yResult.includes('ā
') ? 'pass' : 'fail';
|
|
139
|
+
console.error(a11yResult.split('\n').slice(0, 5).join('\n')); // Show summary
|
|
140
|
+
// Gate 2: Performance
|
|
141
|
+
console.error('[2/6] Performance optimization...');
|
|
142
|
+
const perfResult = await optimizePerformance({ auto_fix: true });
|
|
143
|
+
gates.performance = 'pass'; // Always passes, just applies optimizations
|
|
144
|
+
console.error(perfResult.split('\n').slice(0, 5).join('\n'));
|
|
145
|
+
// Gate 3: Security
|
|
146
|
+
console.error('[3/6] Security scan...');
|
|
147
|
+
const secResult = await scanSecurity({ block_on_critical: true });
|
|
148
|
+
gates.security = secResult.includes('ā
PASS') ? 'pass' : secResult.includes('ā BLOCKED') ? 'blocked' : 'warnings';
|
|
149
|
+
console.error(secResult.split('\n').slice(0, 8).join('\n'));
|
|
150
|
+
// If security blocked, stop here
|
|
151
|
+
if (gates.security === 'blocked') {
|
|
152
|
+
console.error('\nā Security gate BLOCKED - fix critical issues before deployment');
|
|
153
|
+
return gates;
|
|
154
|
+
}
|
|
155
|
+
// Gate 4: Documentation
|
|
156
|
+
if (!skipDocs) {
|
|
157
|
+
console.error('[4/6] Generating documentation...');
|
|
158
|
+
const docsResult = await generateDocs({});
|
|
159
|
+
gates.documentation = docsResult.includes('ā
') ? 'generated' : 'failed';
|
|
160
|
+
console.error(docsResult.split('\n').slice(0, 5).join('\n'));
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
gates.documentation = 'skipped';
|
|
164
|
+
}
|
|
165
|
+
// Gate 5: AI Chatbot
|
|
166
|
+
if (!skipChatbot) {
|
|
167
|
+
console.error('[5/6] Generating AI chatbot...');
|
|
168
|
+
const chatbotResult = await generateChatbot({});
|
|
169
|
+
gates.chatbot = chatbotResult.includes('ā
') ? 'generated' : 'failed';
|
|
170
|
+
console.error(chatbotResult.split('\n').slice(0, 5).join('\n'));
|
|
171
|
+
}
|
|
172
|
+
else {
|
|
173
|
+
gates.chatbot = 'skipped';
|
|
174
|
+
}
|
|
175
|
+
// Gate 6: Deployment
|
|
176
|
+
if (!skipDeploy && gates.security !== 'blocked') {
|
|
177
|
+
console.error('[6/6] Deploying to Vercel...');
|
|
178
|
+
try {
|
|
179
|
+
const deployResult = await deployVercel({ production: true });
|
|
180
|
+
gates.deployment = deployResult.includes('ā
') ? 'deployed' : 'failed';
|
|
181
|
+
gates.deployment_url = deployResult.match(/https:\/\/[^\s]+/)?.[0];
|
|
182
|
+
console.error(deployResult.split('\n').slice(0, 5).join('\n'));
|
|
183
|
+
}
|
|
184
|
+
catch (error) {
|
|
185
|
+
gates.deployment = 'failed';
|
|
186
|
+
gates.deployment_error = error instanceof Error ? error.message : String(error);
|
|
187
|
+
console.error(`Deployment failed: ${gates.deployment_error}`);
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
else {
|
|
191
|
+
gates.deployment = 'skipped';
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
catch (error) {
|
|
195
|
+
console.error(`Quality gate error: ${error}`);
|
|
196
|
+
}
|
|
197
|
+
return gates;
|
|
198
|
+
}
|
|
199
|
+
function generateBuildReport(results, total, qualityGates = null) {
|
|
200
|
+
const successful = results.filter(r => r.status === 'success').length;
|
|
201
|
+
const failed = results.filter(r => r.status === 'failed').length;
|
|
202
|
+
let report = `š CodeBakers: Autonomous Build Complete\n\n`;
|
|
203
|
+
report += `## Build Summary\n\n`;
|
|
204
|
+
report += `**Features requested:** ${total}\n`;
|
|
205
|
+
report += `**Features completed:** ${successful} ā
\n`;
|
|
206
|
+
report += `**Features failed:** ${failed} ${failed > 0 ? 'ā' : ''}\n\n`;
|
|
207
|
+
if (successful > 0) {
|
|
208
|
+
report += `## ā
Successful Builds\n\n`;
|
|
209
|
+
for (const result of results.filter(r => r.status === 'success')) {
|
|
210
|
+
report += `- ${result.feature}\n`;
|
|
211
|
+
}
|
|
212
|
+
report += `\n`;
|
|
213
|
+
}
|
|
214
|
+
if (failed > 0) {
|
|
215
|
+
report += `## ā Failed Builds\n\n`;
|
|
216
|
+
for (const result of results.filter(r => r.status === 'failed')) {
|
|
217
|
+
report += `- ${result.feature}\n`;
|
|
218
|
+
if (result.error) {
|
|
219
|
+
report += ` Error: ${result.error}\n`;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
report += `\n`;
|
|
223
|
+
}
|
|
224
|
+
// Quality Gates Section
|
|
225
|
+
if (qualityGates) {
|
|
226
|
+
report += `---\n\n`;
|
|
227
|
+
report += `## š Quality Gates\n\n`;
|
|
228
|
+
const gates = [
|
|
229
|
+
{ name: 'Accessibility', status: qualityGates.accessibility },
|
|
230
|
+
{ name: 'Performance', status: qualityGates.performance },
|
|
231
|
+
{ name: 'Security', status: qualityGates.security },
|
|
232
|
+
{ name: 'Documentation', status: qualityGates.documentation },
|
|
233
|
+
{ name: 'AI Chatbot', status: qualityGates.chatbot },
|
|
234
|
+
{ name: 'Deployment', status: qualityGates.deployment }
|
|
235
|
+
];
|
|
236
|
+
for (const gate of gates) {
|
|
237
|
+
const emoji = gate.status === 'pass' || gate.status === 'generated' || gate.status === 'deployed'
|
|
238
|
+
? 'ā
'
|
|
239
|
+
: gate.status === 'fail' || gate.status === 'blocked'
|
|
240
|
+
? 'ā'
|
|
241
|
+
: gate.status === 'warnings'
|
|
242
|
+
? 'ā ļø'
|
|
243
|
+
: 'āļø';
|
|
244
|
+
report += `- ${emoji} **${gate.name}:** ${gate.status}\n`;
|
|
245
|
+
}
|
|
246
|
+
report += `\n`;
|
|
247
|
+
// Deployment URL if available
|
|
248
|
+
if (qualityGates.deployment_url) {
|
|
249
|
+
report += `š **Live URL:** ${qualityGates.deployment_url}\n\n`;
|
|
250
|
+
}
|
|
251
|
+
// Security blocked warning
|
|
252
|
+
if (qualityGates.security === 'blocked') {
|
|
253
|
+
report += `ā ļø **Security gate BLOCKED** - Fix critical vulnerabilities before deployment\n\n`;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
report += `---\n\n`;
|
|
257
|
+
if (failed === 0 && qualityGates && qualityGates.deployment === 'deployed') {
|
|
258
|
+
report += `## š BUILD COMPLETE - PRODUCTION READY\n\n`;
|
|
259
|
+
report += `**Your app is live!**\n\n`;
|
|
260
|
+
if (qualityGates.deployment_url) {
|
|
261
|
+
report += `**URL:** ${qualityGates.deployment_url}\n\n`;
|
|
262
|
+
}
|
|
263
|
+
report += `**Quality Scores:**\n`;
|
|
264
|
+
report += `- Accessibility: ${qualityGates.accessibility === 'pass' ? 'ā
Compliant' : 'ā ļø Issues found'}\n`;
|
|
265
|
+
report += `- Performance: ā
Optimized\n`;
|
|
266
|
+
report += `- Security: ${qualityGates.security === 'pass' ? 'ā
Secure' : qualityGates.security === 'warnings' ? 'ā ļø Warnings' : 'ā Critical issues'}\n`;
|
|
267
|
+
report += `- Documentation: ${qualityGates.documentation === 'generated' ? 'ā
Generated' : 'Not generated'}\n`;
|
|
268
|
+
report += `- AI Chatbot: ${qualityGates.chatbot === 'generated' ? 'ā
Integrated' : 'Not integrated'}\n\n`;
|
|
269
|
+
report += `**Time saved:** Entire app built autonomously from mockups to production\n`;
|
|
270
|
+
}
|
|
271
|
+
else if (failed === 0) {
|
|
272
|
+
report += `## š All Features Complete!\n\n`;
|
|
273
|
+
report += `**Next steps:**\n`;
|
|
274
|
+
report += `1. Run tests: codebakers_run_tests { test_type: "all" }\n`;
|
|
275
|
+
report += `2. Review quality gates above\n`;
|
|
276
|
+
report += `3. Deploy: codebakers_deploy_vercel { production: true }\n`;
|
|
277
|
+
}
|
|
278
|
+
else {
|
|
279
|
+
report += `## ā ļø Some Features Failed\n\n`;
|
|
280
|
+
report += `**Next steps:**\n`;
|
|
281
|
+
report += `1. Review error messages above\n`;
|
|
282
|
+
report += `2. Fix issues manually\n`;
|
|
283
|
+
report += `3. Re-run: codebakers_autonomous_build { mode: "remaining" }\n`;
|
|
284
|
+
}
|
|
285
|
+
return report;
|
|
286
|
+
}
|
|
287
287
|
//# sourceMappingURL=autonomous-build.js.map
|
package/dist/tools/check-gate.js
CHANGED
|
@@ -47,8 +47,8 @@ export async function checkGate(args) {
|
|
|
47
47
|
result = await checkPhase6Gate(cwd);
|
|
48
48
|
break;
|
|
49
49
|
default:
|
|
50
|
-
return `š CodeBakers: Invalid Phase
|
|
51
|
-
|
|
50
|
+
return `š CodeBakers: Invalid Phase
|
|
51
|
+
|
|
52
52
|
Phase ${phase} is not valid. Valid phases: 0-6.`;
|
|
53
53
|
}
|
|
54
54
|
// Generate report
|
|
@@ -57,10 +57,10 @@ Phase ${phase} is not valid. Valid phases: 0-6.`;
|
|
|
57
57
|
}
|
|
58
58
|
catch (error) {
|
|
59
59
|
console.error('Error during gate check:', error);
|
|
60
|
-
return `š CodeBakers: Gate Check Failed
|
|
61
|
-
|
|
62
|
-
Error: ${error instanceof Error ? error.message : String(error)}
|
|
63
|
-
|
|
60
|
+
return `š CodeBakers: Gate Check Failed
|
|
61
|
+
|
|
62
|
+
Error: ${error instanceof Error ? error.message : String(error)}
|
|
63
|
+
|
|
64
64
|
Please verify project directory and file permissions.`;
|
|
65
65
|
}
|
|
66
66
|
}
|
|
@@ -28,12 +28,12 @@ export async function checkScope(args) {
|
|
|
28
28
|
const specPath = path.join(cwd, '.codebakers', 'PROJECT-SPEC.md');
|
|
29
29
|
const specExists = await fs.access(specPath).then(() => true).catch(() => false);
|
|
30
30
|
if (!specExists) {
|
|
31
|
-
return `š CodeBakers: Scope Check BLOCKED
|
|
32
|
-
|
|
33
|
-
ā PROJECT-SPEC.md not found
|
|
34
|
-
|
|
35
|
-
Cannot verify scope without specification.
|
|
36
|
-
|
|
31
|
+
return `š CodeBakers: Scope Check BLOCKED
|
|
32
|
+
|
|
33
|
+
ā PROJECT-SPEC.md not found
|
|
34
|
+
|
|
35
|
+
Cannot verify scope without specification.
|
|
36
|
+
|
|
37
37
|
Next step: Run Phase 0 first (codebakers_generate_spec)`;
|
|
38
38
|
}
|
|
39
39
|
const specContent = await fs.readFile(specPath, 'utf-8');
|
|
@@ -51,10 +51,10 @@ Next step: Run Phase 0 first (codebakers_generate_spec)`;
|
|
|
51
51
|
}
|
|
52
52
|
catch (error) {
|
|
53
53
|
console.error('Error during scope check:', error);
|
|
54
|
-
return `š CodeBakers: Scope Check Failed
|
|
55
|
-
|
|
56
|
-
Error: ${error instanceof Error ? error.message : String(error)}
|
|
57
|
-
|
|
54
|
+
return `š CodeBakers: Scope Check Failed
|
|
55
|
+
|
|
56
|
+
Error: ${error instanceof Error ? error.message : String(error)}
|
|
57
|
+
|
|
58
58
|
Please verify PROJECT-SPEC.md exists and is readable.`;
|
|
59
59
|
}
|
|
60
60
|
}
|