@girardmedia/bootspring 1.1.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 +21 -0
- package/README.md +255 -0
- package/agents/README.md +93 -0
- package/agents/api-expert/context.md +416 -0
- package/agents/architecture-expert/context.md +454 -0
- package/agents/backend-expert/context.md +483 -0
- package/agents/code-review-expert/context.md +365 -0
- package/agents/database-expert/context.md +250 -0
- package/agents/devops-expert/context.md +446 -0
- package/agents/frontend-expert/context.md +364 -0
- package/agents/index.js +140 -0
- package/agents/performance-expert/context.md +377 -0
- package/agents/security-expert/context.md +343 -0
- package/agents/testing-expert/context.md +414 -0
- package/agents/ui-ux-expert/context.md +448 -0
- package/agents/vercel-expert/context.md +426 -0
- package/bin/bootspring.js +310 -0
- package/cli/agent.js +337 -0
- package/cli/context.js +194 -0
- package/cli/dashboard.js +150 -0
- package/cli/generate.js +294 -0
- package/cli/init.js +410 -0
- package/cli/loop.js +421 -0
- package/cli/mcp.js +241 -0
- package/cli/memory.js +303 -0
- package/cli/orchestrator.js +400 -0
- package/cli/plugin.js +451 -0
- package/cli/quality.js +332 -0
- package/cli/skill.js +369 -0
- package/cli/task.js +628 -0
- package/cli/telemetry.js +114 -0
- package/cli/todo.js +614 -0
- package/cli/update.js +312 -0
- package/core/config.js +245 -0
- package/core/context.js +329 -0
- package/core/entitlements.js +209 -0
- package/core/index.js +43 -0
- package/core/policies.js +68 -0
- package/core/telemetry.js +247 -0
- package/core/utils.js +380 -0
- package/dashboard/server.js +818 -0
- package/docs/integrations/claude-code.md +42 -0
- package/docs/integrations/codex.md +42 -0
- package/docs/mcp-api-platform.md +102 -0
- package/generators/generate.js +598 -0
- package/generators/index.js +18 -0
- package/hooks/context-detector.js +177 -0
- package/hooks/index.js +35 -0
- package/hooks/prompt-enhancer.js +289 -0
- package/intelligence/git-memory.js +551 -0
- package/intelligence/index.js +59 -0
- package/intelligence/orchestrator.js +964 -0
- package/intelligence/prd.js +447 -0
- package/intelligence/recommendation-weights.json +18 -0
- package/intelligence/recommendations.js +234 -0
- package/mcp/capabilities.js +71 -0
- package/mcp/contracts/mcp-contract.v1.json +497 -0
- package/mcp/registry.js +213 -0
- package/mcp/response-formatter.js +462 -0
- package/mcp/server.js +99 -0
- package/mcp/tools/agent-tool.js +137 -0
- package/mcp/tools/capabilities-tool.js +54 -0
- package/mcp/tools/context-tool.js +49 -0
- package/mcp/tools/dashboard-tool.js +58 -0
- package/mcp/tools/generate-tool.js +46 -0
- package/mcp/tools/loop-tool.js +134 -0
- package/mcp/tools/memory-tool.js +180 -0
- package/mcp/tools/orchestrator-tool.js +232 -0
- package/mcp/tools/plugin-tool.js +76 -0
- package/mcp/tools/quality-tool.js +47 -0
- package/mcp/tools/skill-tool.js +233 -0
- package/mcp/tools/telemetry-tool.js +95 -0
- package/mcp/tools/todo-tool.js +133 -0
- package/package.json +98 -0
- package/plugins/index.js +141 -0
- package/quality/index.js +380 -0
- package/quality/lint-budgets.json +19 -0
- package/skills/index.js +787 -0
- package/skills/patterns/README.md +163 -0
- package/skills/patterns/api/route-handler.md +217 -0
- package/skills/patterns/api/server-action.md +249 -0
- package/skills/patterns/auth/clerk.md +132 -0
- package/skills/patterns/database/prisma.md +180 -0
- package/skills/patterns/payments/stripe.md +272 -0
- package/skills/patterns/security/validation.md +268 -0
- package/skills/patterns/testing/vitest.md +307 -0
- package/templates/bootspring.config.js +83 -0
- package/templates/mcp.json +9 -0
package/cli/context.js
ADDED
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Context Command
|
|
3
|
+
* View and manage project context
|
|
4
|
+
*
|
|
5
|
+
* @package bootspring
|
|
6
|
+
* @command context
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const config = require('../core/config');
|
|
11
|
+
const context = require('../core/context');
|
|
12
|
+
const utils = require('../core/utils');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Show project context summary
|
|
16
|
+
*/
|
|
17
|
+
function showContext() {
|
|
18
|
+
const cfg = config.load();
|
|
19
|
+
const ctx = context.get({ config: cfg });
|
|
20
|
+
|
|
21
|
+
console.log(`
|
|
22
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context${utils.COLORS.reset}
|
|
23
|
+
${utils.COLORS.dim}Project: ${cfg._projectRoot}${utils.COLORS.reset}
|
|
24
|
+
`);
|
|
25
|
+
|
|
26
|
+
// Project Info
|
|
27
|
+
console.log(`${utils.COLORS.bold}Project${utils.COLORS.reset}`);
|
|
28
|
+
console.log(` Name: ${ctx.project.name}`);
|
|
29
|
+
console.log(` Version: ${ctx.project.version}`);
|
|
30
|
+
if (ctx.project.description) {
|
|
31
|
+
console.log(` Description: ${ctx.project.description}`);
|
|
32
|
+
}
|
|
33
|
+
console.log();
|
|
34
|
+
|
|
35
|
+
// Stack
|
|
36
|
+
console.log(`${utils.COLORS.bold}Stack${utils.COLORS.reset}`);
|
|
37
|
+
console.log(` Framework: ${utils.COLORS.cyan}${ctx.stack.framework}${utils.COLORS.reset}`);
|
|
38
|
+
console.log(` Language: ${ctx.stack.language}`);
|
|
39
|
+
console.log(` Database: ${ctx.stack.database}`);
|
|
40
|
+
console.log(` Hosting: ${ctx.stack.hosting}`);
|
|
41
|
+
console.log();
|
|
42
|
+
|
|
43
|
+
// Plugins
|
|
44
|
+
const plugins = Object.keys(ctx.plugins);
|
|
45
|
+
if (plugins.length > 0) {
|
|
46
|
+
console.log(`${utils.COLORS.bold}Enabled Plugins${utils.COLORS.reset}`);
|
|
47
|
+
for (const [name, plugin] of Object.entries(ctx.plugins)) {
|
|
48
|
+
console.log(` ${utils.COLORS.green}●${utils.COLORS.reset} ${name} (${plugin.provider})`);
|
|
49
|
+
}
|
|
50
|
+
console.log();
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// State
|
|
54
|
+
const healthColor = ctx.state.health === 'good' ? utils.COLORS.green :
|
|
55
|
+
ctx.state.health === 'fair' ? utils.COLORS.yellow :
|
|
56
|
+
utils.COLORS.red;
|
|
57
|
+
|
|
58
|
+
console.log(`${utils.COLORS.bold}State${utils.COLORS.reset}`);
|
|
59
|
+
console.log(` Phase: ${ctx.state.phase}`);
|
|
60
|
+
console.log(` Health: ${healthColor}${ctx.state.health}${utils.COLORS.reset}`);
|
|
61
|
+
console.log(` Open Todos: ${ctx.state.todos}`);
|
|
62
|
+
if (ctx.state.lastGenerated) {
|
|
63
|
+
console.log(` Context Updated: ${utils.formatRelativeTime(ctx.state.lastGenerated)}`);
|
|
64
|
+
}
|
|
65
|
+
console.log();
|
|
66
|
+
|
|
67
|
+
// Git
|
|
68
|
+
if (ctx.git.initialized) {
|
|
69
|
+
console.log(`${utils.COLORS.bold}Git${utils.COLORS.reset}`);
|
|
70
|
+
console.log(` Branch: ${ctx.git.branch || 'unknown'}`);
|
|
71
|
+
console.log(` Remote: ${ctx.git.hasRemote ? 'configured' : 'not configured'}`);
|
|
72
|
+
console.log();
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* Validate project context
|
|
78
|
+
*/
|
|
79
|
+
function validateContext() {
|
|
80
|
+
const cfg = config.load();
|
|
81
|
+
const validation = context.validate({ config: cfg });
|
|
82
|
+
|
|
83
|
+
console.log(`
|
|
84
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context Validation${utils.COLORS.reset}
|
|
85
|
+
`);
|
|
86
|
+
|
|
87
|
+
for (const check of validation.checks) {
|
|
88
|
+
const icon = check.status === 'pass' ? utils.COLORS.green + '✓' :
|
|
89
|
+
check.status === 'fail' ? utils.COLORS.red + '✗' :
|
|
90
|
+
check.status === 'warn' ? utils.COLORS.yellow + '⚠' :
|
|
91
|
+
utils.COLORS.dim + 'ℹ';
|
|
92
|
+
const color = check.status === 'pass' ? '' :
|
|
93
|
+
check.status === 'fail' ? utils.COLORS.red :
|
|
94
|
+
check.status === 'warn' ? utils.COLORS.yellow :
|
|
95
|
+
utils.COLORS.dim;
|
|
96
|
+
console.log(` ${icon}${utils.COLORS.reset} ${check.name}`);
|
|
97
|
+
console.log(` ${utils.COLORS.dim}${check.message}${utils.COLORS.reset}`);
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
console.log();
|
|
101
|
+
|
|
102
|
+
// Score bar
|
|
103
|
+
const barWidth = 30;
|
|
104
|
+
const filled = Math.round((validation.percentage / 100) * barWidth);
|
|
105
|
+
const empty = barWidth - filled;
|
|
106
|
+
const scoreColor = validation.percentage >= 80 ? utils.COLORS.green :
|
|
107
|
+
validation.percentage >= 50 ? utils.COLORS.yellow :
|
|
108
|
+
utils.COLORS.red;
|
|
109
|
+
|
|
110
|
+
console.log(`${utils.COLORS.bold}Score${utils.COLORS.reset}`);
|
|
111
|
+
console.log(` ${scoreColor}${'█'.repeat(filled)}${utils.COLORS.dim}${'░'.repeat(empty)}${utils.COLORS.reset} ${validation.percentage}%`);
|
|
112
|
+
console.log(` ${validation.score}/${validation.maxScore} checks passed`);
|
|
113
|
+
console.log();
|
|
114
|
+
|
|
115
|
+
if (validation.valid) {
|
|
116
|
+
utils.print.success('Context validation passed');
|
|
117
|
+
} else {
|
|
118
|
+
utils.print.warning('Context needs attention - fix the issues above');
|
|
119
|
+
utils.print.dim('Run "bootspring generate" to regenerate context');
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Refresh project context
|
|
125
|
+
*/
|
|
126
|
+
function refreshContext() {
|
|
127
|
+
console.log(`
|
|
128
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context Refresh${utils.COLORS.reset}
|
|
129
|
+
`);
|
|
130
|
+
|
|
131
|
+
utils.print.info('Refreshing context...');
|
|
132
|
+
|
|
133
|
+
// This triggers a regeneration
|
|
134
|
+
const generateModule = require('./generate');
|
|
135
|
+
generateModule.run([]);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Show context help
|
|
140
|
+
*/
|
|
141
|
+
function showHelp() {
|
|
142
|
+
console.log(`
|
|
143
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context${utils.COLORS.reset}
|
|
144
|
+
${utils.COLORS.dim}View and manage project context${utils.COLORS.reset}
|
|
145
|
+
|
|
146
|
+
${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
147
|
+
bootspring context <command>
|
|
148
|
+
|
|
149
|
+
${utils.COLORS.bold}Commands:${utils.COLORS.reset}
|
|
150
|
+
${utils.COLORS.cyan}show${utils.COLORS.reset} Show context summary (default)
|
|
151
|
+
${utils.COLORS.cyan}validate${utils.COLORS.reset} Validate project setup
|
|
152
|
+
${utils.COLORS.cyan}refresh${utils.COLORS.reset} Regenerate context files
|
|
153
|
+
|
|
154
|
+
${utils.COLORS.bold}Examples:${utils.COLORS.reset}
|
|
155
|
+
bootspring context
|
|
156
|
+
bootspring context validate
|
|
157
|
+
bootspring context refresh
|
|
158
|
+
`);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* Run context command
|
|
163
|
+
*/
|
|
164
|
+
async function run(args) {
|
|
165
|
+
const subcommand = args[0] || 'show';
|
|
166
|
+
|
|
167
|
+
switch (subcommand) {
|
|
168
|
+
case 'show':
|
|
169
|
+
showContext();
|
|
170
|
+
break;
|
|
171
|
+
|
|
172
|
+
case 'validate':
|
|
173
|
+
case 'check':
|
|
174
|
+
validateContext();
|
|
175
|
+
break;
|
|
176
|
+
|
|
177
|
+
case 'refresh':
|
|
178
|
+
case 'regenerate':
|
|
179
|
+
refreshContext();
|
|
180
|
+
break;
|
|
181
|
+
|
|
182
|
+
case 'help':
|
|
183
|
+
case '-h':
|
|
184
|
+
case '--help':
|
|
185
|
+
showHelp();
|
|
186
|
+
break;
|
|
187
|
+
|
|
188
|
+
default:
|
|
189
|
+
utils.print.error(`Unknown subcommand: ${subcommand}`);
|
|
190
|
+
showHelp();
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
module.exports = { run, showContext, validateContext, refreshContext };
|
package/cli/dashboard.js
ADDED
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Dashboard Command
|
|
3
|
+
* Control the real-time dashboard
|
|
4
|
+
*
|
|
5
|
+
* @package bootspring
|
|
6
|
+
* @command dashboard
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const path = require('path');
|
|
10
|
+
const { spawn } = require('child_process');
|
|
11
|
+
const config = require('../core/config');
|
|
12
|
+
const utils = require('../core/utils');
|
|
13
|
+
|
|
14
|
+
/**
|
|
15
|
+
* Start the dashboard server
|
|
16
|
+
*/
|
|
17
|
+
function startDashboard(options = {}) {
|
|
18
|
+
const cfg = config.load();
|
|
19
|
+
const port = options.port || cfg.dashboard?.port || 3456;
|
|
20
|
+
|
|
21
|
+
const dashboardPath = path.resolve(__dirname, '../dashboard/server.js');
|
|
22
|
+
|
|
23
|
+
// Check if dashboard server exists
|
|
24
|
+
if (!utils.fileExists(dashboardPath)) {
|
|
25
|
+
utils.print.warning('Dashboard server not yet implemented');
|
|
26
|
+
utils.print.dim('Coming soon in a future release');
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
console.log(`
|
|
31
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Dashboard${utils.COLORS.reset}
|
|
32
|
+
${utils.COLORS.dim}Real-time project visibility${utils.COLORS.reset}
|
|
33
|
+
`);
|
|
34
|
+
|
|
35
|
+
utils.print.info(`Starting dashboard on port ${port}...`);
|
|
36
|
+
|
|
37
|
+
// Start the server
|
|
38
|
+
const server = spawn('node', [dashboardPath], {
|
|
39
|
+
env: {
|
|
40
|
+
...process.env,
|
|
41
|
+
PORT: port,
|
|
42
|
+
BOOTSPRING_ROOT: cfg._projectRoot
|
|
43
|
+
},
|
|
44
|
+
stdio: 'inherit'
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
server.on('error', (error) => {
|
|
48
|
+
utils.print.error(`Failed to start dashboard: ${error.message}`);
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
server.on('close', (code) => {
|
|
52
|
+
if (code !== 0) {
|
|
53
|
+
utils.print.error(`Dashboard exited with code ${code}`);
|
|
54
|
+
}
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Handle graceful shutdown
|
|
58
|
+
process.on('SIGINT', () => {
|
|
59
|
+
utils.print.info('Shutting down dashboard...');
|
|
60
|
+
server.kill('SIGINT');
|
|
61
|
+
process.exit(0);
|
|
62
|
+
});
|
|
63
|
+
|
|
64
|
+
process.on('SIGTERM', () => {
|
|
65
|
+
server.kill('SIGTERM');
|
|
66
|
+
process.exit(0);
|
|
67
|
+
});
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/**
|
|
71
|
+
* Show dashboard status
|
|
72
|
+
*/
|
|
73
|
+
function showStatus() {
|
|
74
|
+
const cfg = config.load();
|
|
75
|
+
const port = cfg.dashboard?.port || 3456;
|
|
76
|
+
|
|
77
|
+
console.log(`
|
|
78
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Dashboard Status${utils.COLORS.reset}
|
|
79
|
+
|
|
80
|
+
${utils.COLORS.bold}Configuration:${utils.COLORS.reset}
|
|
81
|
+
Port: ${port}
|
|
82
|
+
Auto-open: ${cfg.dashboard?.autoOpen ? 'yes' : 'no'}
|
|
83
|
+
|
|
84
|
+
${utils.COLORS.bold}To start:${utils.COLORS.reset}
|
|
85
|
+
bootspring dashboard
|
|
86
|
+
|
|
87
|
+
${utils.COLORS.bold}URL:${utils.COLORS.reset}
|
|
88
|
+
http://localhost:${port}
|
|
89
|
+
`);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
/**
|
|
93
|
+
* Show dashboard help
|
|
94
|
+
*/
|
|
95
|
+
function showHelp() {
|
|
96
|
+
console.log(`
|
|
97
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Dashboard${utils.COLORS.reset}
|
|
98
|
+
${utils.COLORS.dim}Real-time project visibility${utils.COLORS.reset}
|
|
99
|
+
|
|
100
|
+
${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
101
|
+
bootspring dashboard [command] [options]
|
|
102
|
+
|
|
103
|
+
${utils.COLORS.bold}Commands:${utils.COLORS.reset}
|
|
104
|
+
${utils.COLORS.cyan}start${utils.COLORS.reset} Start the dashboard (default)
|
|
105
|
+
${utils.COLORS.cyan}status${utils.COLORS.reset} Show dashboard status
|
|
106
|
+
|
|
107
|
+
${utils.COLORS.bold}Options:${utils.COLORS.reset}
|
|
108
|
+
--port <port> Use a specific port (default: 3456)
|
|
109
|
+
|
|
110
|
+
${utils.COLORS.bold}Examples:${utils.COLORS.reset}
|
|
111
|
+
bootspring dashboard
|
|
112
|
+
bootspring dashboard --port 8080
|
|
113
|
+
bootspring dashboard status
|
|
114
|
+
`);
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
/**
|
|
118
|
+
* Run dashboard command
|
|
119
|
+
*/
|
|
120
|
+
async function run(args) {
|
|
121
|
+
const parsedArgs = utils.parseArgs(args);
|
|
122
|
+
const subcommand = parsedArgs._[0] || 'start';
|
|
123
|
+
|
|
124
|
+
switch (subcommand) {
|
|
125
|
+
case 'start':
|
|
126
|
+
startDashboard({ port: parsedArgs.port });
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case 'status':
|
|
130
|
+
showStatus();
|
|
131
|
+
break;
|
|
132
|
+
|
|
133
|
+
case 'help':
|
|
134
|
+
case '-h':
|
|
135
|
+
case '--help':
|
|
136
|
+
showHelp();
|
|
137
|
+
break;
|
|
138
|
+
|
|
139
|
+
default:
|
|
140
|
+
// Treat unknown as start with possible port
|
|
141
|
+
if (!isNaN(parseInt(subcommand, 10))) {
|
|
142
|
+
startDashboard({ port: parseInt(subcommand, 10) });
|
|
143
|
+
} else {
|
|
144
|
+
utils.print.error(`Unknown subcommand: ${subcommand}`);
|
|
145
|
+
showHelp();
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
module.exports = { run, startDashboard, showStatus };
|
package/cli/generate.js
ADDED
|
@@ -0,0 +1,294 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Generate Command
|
|
3
|
+
* Generate and regenerate AI context files
|
|
4
|
+
*
|
|
5
|
+
* @package bootspring
|
|
6
|
+
* @command generate
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
const fs = require('fs');
|
|
10
|
+
const path = require('path');
|
|
11
|
+
const config = require('../core/config');
|
|
12
|
+
const context = require('../core/context');
|
|
13
|
+
const utils = require('../core/utils');
|
|
14
|
+
const gitMemory = require('../intelligence/git-memory');
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Generate CLAUDE.md content from config and project state
|
|
18
|
+
*/
|
|
19
|
+
function generateClaudeMd(cfg, ctx) {
|
|
20
|
+
const date = utils.formatDate();
|
|
21
|
+
|
|
22
|
+
const sections = [];
|
|
23
|
+
|
|
24
|
+
// Header
|
|
25
|
+
sections.push(`# ${cfg.project.name} - AI Context
|
|
26
|
+
|
|
27
|
+
**Generated by**: Bootspring v1.0.0
|
|
28
|
+
**Last Updated**: ${date}
|
|
29
|
+
**Status**: ${ctx.state.phase}
|
|
30
|
+
**Health**: ${ctx.state.health}
|
|
31
|
+
|
|
32
|
+
---`);
|
|
33
|
+
|
|
34
|
+
// Project Overview
|
|
35
|
+
sections.push(`## Project Overview
|
|
36
|
+
|
|
37
|
+
${cfg.project.description || 'A modern web application built with Bootspring.'}
|
|
38
|
+
|
|
39
|
+
---`);
|
|
40
|
+
|
|
41
|
+
// Tech Stack
|
|
42
|
+
sections.push(`## Tech Stack
|
|
43
|
+
|
|
44
|
+
| Component | Technology |
|
|
45
|
+
|-----------|------------|
|
|
46
|
+
| Framework | ${cfg.stack.framework} |
|
|
47
|
+
| Language | ${cfg.stack.language} |
|
|
48
|
+
| Database | ${cfg.stack.database} |
|
|
49
|
+
| Hosting | ${cfg.stack.hosting} |
|
|
50
|
+
|
|
51
|
+
---`);
|
|
52
|
+
|
|
53
|
+
// Enabled Plugins
|
|
54
|
+
const enabledPlugins = Object.entries(cfg.plugins)
|
|
55
|
+
.filter(([_, p]) => p.enabled !== false);
|
|
56
|
+
|
|
57
|
+
if (enabledPlugins.length > 0) {
|
|
58
|
+
sections.push(`## Enabled Plugins
|
|
59
|
+
|
|
60
|
+
${enabledPlugins.map(([name, plugin]) => `### ${name.charAt(0).toUpperCase() + name.slice(1)}
|
|
61
|
+
- **Provider**: ${plugin.provider || 'default'}
|
|
62
|
+
- **Features**: ${(plugin.features || []).join(', ') || 'default'}`).join('\n\n')}
|
|
63
|
+
|
|
64
|
+
---`);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Bootspring Commands
|
|
68
|
+
sections.push(`## Bootspring Commands
|
|
69
|
+
|
|
70
|
+
Quick commands for your AI assistant:
|
|
71
|
+
|
|
72
|
+
### Todo Management
|
|
73
|
+
\`\`\`bash
|
|
74
|
+
bootspring todo add "task" # Add a new todo
|
|
75
|
+
bootspring todo list # List all todos
|
|
76
|
+
bootspring todo done <id> # Mark as complete
|
|
77
|
+
bootspring todo clear # Clear completed
|
|
78
|
+
\`\`\`
|
|
79
|
+
|
|
80
|
+
### Agents & Skills
|
|
81
|
+
\`\`\`bash
|
|
82
|
+
bootspring agent list # List available agents
|
|
83
|
+
bootspring agent invoke <n> # Get specialized help
|
|
84
|
+
bootspring skill search <q> # Find code patterns
|
|
85
|
+
bootspring skill show <name> # View a skill
|
|
86
|
+
\`\`\`
|
|
87
|
+
|
|
88
|
+
### Project Tools
|
|
89
|
+
\`\`\`bash
|
|
90
|
+
bootspring dashboard # Start real-time dashboard
|
|
91
|
+
bootspring generate # Regenerate this context
|
|
92
|
+
bootspring quality pre-commit # Run quality checks
|
|
93
|
+
bootspring context validate # Validate project setup
|
|
94
|
+
\`\`\`
|
|
95
|
+
|
|
96
|
+
---`);
|
|
97
|
+
|
|
98
|
+
// Project State
|
|
99
|
+
sections.push(`## Current State
|
|
100
|
+
|
|
101
|
+
- **Phase**: ${ctx.state.phase}
|
|
102
|
+
- **Health**: ${ctx.state.health}
|
|
103
|
+
- **Open Todos**: ${ctx.state.todos}
|
|
104
|
+
${ctx.state.issues.length > 0 ? `- **Issues**: ${ctx.state.issues.join(', ')}` : ''}
|
|
105
|
+
|
|
106
|
+
---`);
|
|
107
|
+
|
|
108
|
+
// Git Info
|
|
109
|
+
if (ctx.git.initialized) {
|
|
110
|
+
sections.push(`## Git Repository
|
|
111
|
+
|
|
112
|
+
- **Branch**: ${ctx.git.branch || 'unknown'}
|
|
113
|
+
- **Remote**: ${ctx.git.hasRemote ? 'configured' : 'not configured'}
|
|
114
|
+
|
|
115
|
+
---`);
|
|
116
|
+
|
|
117
|
+
// Extract git learnings
|
|
118
|
+
try {
|
|
119
|
+
const { learnings } = gitMemory.extractLearnings({
|
|
120
|
+
limit: 30,
|
|
121
|
+
since: '2 months ago',
|
|
122
|
+
cwd: cfg._projectRoot
|
|
123
|
+
});
|
|
124
|
+
|
|
125
|
+
if (learnings && learnings.length > 0) {
|
|
126
|
+
const learningsSection = gitMemory.toCompactSummary(learnings, { maxItems: 12 });
|
|
127
|
+
sections.push(learningsSection + '\n---');
|
|
128
|
+
}
|
|
129
|
+
} catch (e) {
|
|
130
|
+
// Git memory extraction failed silently
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
// Project Structure
|
|
135
|
+
sections.push(`## Project Structure
|
|
136
|
+
|
|
137
|
+
- **Structure Type**: ${ctx.files.structure}
|
|
138
|
+
- **Has TypeScript**: ${ctx.files.hasTsConfig ? 'yes' : 'no'}
|
|
139
|
+
- **Has Package.json**: ${ctx.files.hasPackageJson ? 'yes' : 'no'}
|
|
140
|
+
|
|
141
|
+
---`);
|
|
142
|
+
|
|
143
|
+
// Development Guidelines
|
|
144
|
+
sections.push(`## Development Guidelines
|
|
145
|
+
|
|
146
|
+
### Code Style
|
|
147
|
+
- Use ${cfg.stack.language === 'typescript' ? 'TypeScript' : 'JavaScript'} for all new code
|
|
148
|
+
- Follow existing naming conventions in the codebase
|
|
149
|
+
- Keep files focused and under 300 lines when possible
|
|
150
|
+
|
|
151
|
+
### Best Practices
|
|
152
|
+
- Use Server Components by default (if Next.js)
|
|
153
|
+
- Prefer Server Actions over API routes for mutations
|
|
154
|
+
- Use Zod for all input validation
|
|
155
|
+
- Never expose API keys to client-side code
|
|
156
|
+
- Write tests for new features
|
|
157
|
+
|
|
158
|
+
### Git Commits
|
|
159
|
+
- Use conventional commit format: \`feat:\`, \`fix:\`, \`docs:\`, \`refactor:\`
|
|
160
|
+
- Keep commits focused and atomic
|
|
161
|
+
- Never commit sensitive data or API keys
|
|
162
|
+
|
|
163
|
+
---`);
|
|
164
|
+
|
|
165
|
+
// Custom Instructions
|
|
166
|
+
if (cfg.customInstructions) {
|
|
167
|
+
sections.push(`## Custom Instructions
|
|
168
|
+
|
|
169
|
+
${cfg.customInstructions}
|
|
170
|
+
|
|
171
|
+
---`);
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
// Footer
|
|
175
|
+
sections.push(`---
|
|
176
|
+
|
|
177
|
+
*Generated by [Bootspring](https://bootspring.com) - Development scaffolding with intelligence*
|
|
178
|
+
`);
|
|
179
|
+
|
|
180
|
+
return sections.join('\n\n');
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
/**
|
|
184
|
+
* Run generate command
|
|
185
|
+
*/
|
|
186
|
+
async function run(args) {
|
|
187
|
+
const parsedArgs = utils.parseArgs(args);
|
|
188
|
+
const full = parsedArgs.full || parsedArgs.f;
|
|
189
|
+
|
|
190
|
+
console.log(`
|
|
191
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Generate${utils.COLORS.reset}
|
|
192
|
+
${utils.COLORS.dim}Regenerating AI context...${utils.COLORS.reset}
|
|
193
|
+
`);
|
|
194
|
+
|
|
195
|
+
// Load config
|
|
196
|
+
const cfg = config.load();
|
|
197
|
+
|
|
198
|
+
if (!cfg._configPath) {
|
|
199
|
+
utils.print.error('No bootspring.config.js found');
|
|
200
|
+
utils.print.dim('Run "bootspring init" first to initialize your project');
|
|
201
|
+
return;
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
// Get context
|
|
205
|
+
const ctx = context.get({ config: cfg });
|
|
206
|
+
|
|
207
|
+
// Generate CLAUDE.md
|
|
208
|
+
const claudePath = path.join(cfg._projectRoot, cfg.paths?.context || 'CLAUDE.md');
|
|
209
|
+
const spinner = utils.createSpinner('Generating CLAUDE.md').start();
|
|
210
|
+
|
|
211
|
+
try {
|
|
212
|
+
const content = generateClaudeMd(cfg, ctx);
|
|
213
|
+
utils.writeFile(claudePath, content);
|
|
214
|
+
spinner.succeed('Generated CLAUDE.md');
|
|
215
|
+
} catch (error) {
|
|
216
|
+
spinner.fail(`Failed to generate CLAUDE.md: ${error.message}`);
|
|
217
|
+
return;
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
// Validate context
|
|
221
|
+
const validation = context.validate({ config: cfg });
|
|
222
|
+
|
|
223
|
+
console.log(`
|
|
224
|
+
${utils.COLORS.bold}Context Validation${utils.COLORS.reset}
|
|
225
|
+
`);
|
|
226
|
+
|
|
227
|
+
for (const check of validation.checks) {
|
|
228
|
+
const icon = check.status === 'pass' ? utils.COLORS.green + '✓' :
|
|
229
|
+
check.status === 'fail' ? utils.COLORS.red + '✗' :
|
|
230
|
+
check.status === 'warn' ? utils.COLORS.yellow + '⚠' :
|
|
231
|
+
utils.COLORS.dim + 'ℹ';
|
|
232
|
+
console.log(` ${icon}${utils.COLORS.reset} ${check.name}: ${utils.COLORS.dim}${check.message}${utils.COLORS.reset}`);
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
console.log(`
|
|
236
|
+
${utils.COLORS.bold}Score:${utils.COLORS.reset} ${validation.score}/${validation.maxScore} (${validation.percentage}%)
|
|
237
|
+
`);
|
|
238
|
+
|
|
239
|
+
if (validation.valid) {
|
|
240
|
+
utils.print.success('Context is valid and ready for AI assistants');
|
|
241
|
+
} else {
|
|
242
|
+
utils.print.warning('Context has some issues - review the checks above');
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
// Full generation includes additional files
|
|
246
|
+
if (full) {
|
|
247
|
+
console.log(`\n${utils.COLORS.bold}Full Generation${utils.COLORS.reset}\n`);
|
|
248
|
+
|
|
249
|
+
// Generate .mcp.json if missing
|
|
250
|
+
const mcpPath = path.join(cfg._projectRoot, '.mcp.json');
|
|
251
|
+
if (!utils.fileExists(mcpPath)) {
|
|
252
|
+
const mcpSpinner = utils.createSpinner('Generating .mcp.json').start();
|
|
253
|
+
const mcpConfig = {
|
|
254
|
+
mcpServers: {
|
|
255
|
+
bootspring: {
|
|
256
|
+
command: 'npx',
|
|
257
|
+
args: ['bootspring', 'mcp'],
|
|
258
|
+
env: {}
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
utils.writeFile(mcpPath, JSON.stringify(mcpConfig, null, 2));
|
|
263
|
+
mcpSpinner.succeed('Generated .mcp.json');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Generate todo.md if missing
|
|
267
|
+
const todoPath = path.join(cfg._projectRoot, cfg.paths?.todo || 'todo.md');
|
|
268
|
+
if (!utils.fileExists(todoPath)) {
|
|
269
|
+
const todoSpinner = utils.createSpinner('Generating todo.md').start();
|
|
270
|
+
const todoContent = `# ${cfg.project.name} - Todo List
|
|
271
|
+
|
|
272
|
+
> Last updated: ${utils.formatDate()}
|
|
273
|
+
|
|
274
|
+
## In Progress
|
|
275
|
+
|
|
276
|
+
## Pending
|
|
277
|
+
|
|
278
|
+
- [ ] Review generated context
|
|
279
|
+
- [ ] Configure environment variables
|
|
280
|
+
|
|
281
|
+
## Completed
|
|
282
|
+
|
|
283
|
+
`;
|
|
284
|
+
utils.writeFile(todoPath, todoContent);
|
|
285
|
+
todoSpinner.succeed('Generated todo.md');
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
console.log(`
|
|
290
|
+
${utils.COLORS.dim}Tip: Run 'bootspring generate --full' to regenerate all files${utils.COLORS.reset}
|
|
291
|
+
`);
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
module.exports = { run, generateClaudeMd };
|