@girardmedia/bootspring 2.0.21 → 2.0.23
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/bin/bootspring.js +5 -0
- package/cli/org.js +474 -0
- package/cli/preseed/index.js +16 -0
- package/cli/preseed/interactive.js +143 -0
- package/cli/preseed/templates.js +227 -0
- package/cli/preseed.js +9 -301
- package/cli/seed/builders/ai-context-builder.js +85 -0
- package/cli/seed/builders/index.js +13 -0
- package/cli/seed/builders/seed-builder.js +272 -0
- package/cli/seed/extractors/content-extractors.js +383 -0
- package/cli/seed/extractors/index.js +47 -0
- package/cli/seed/extractors/metadata-extractors.js +167 -0
- package/cli/seed/extractors/section-extractor.js +54 -0
- package/cli/seed/extractors/stack-extractors.js +228 -0
- package/cli/seed/index.js +18 -0
- package/cli/seed/utils/folder-structure.js +84 -0
- package/cli/seed/utils/index.js +11 -0
- package/cli/seed.js +23 -1074
- package/core/api-client.js +77 -0
- package/core/entitlements.js +36 -0
- package/core/organizations.js +223 -0
- package/core/policies.js +51 -6
- package/core/policy-matrix.js +303 -0
- package/core/project-context.js +1 -0
- package/dist/cli/index.d.ts +3 -0
- package/dist/cli/index.js +3220 -0
- package/dist/cli/index.js.map +1 -0
- package/dist/context-McpJQa_2.d.ts +5710 -0
- package/dist/core/index.d.ts +635 -0
- package/dist/core/index.js +2593 -0
- package/dist/core/index.js.map +1 -0
- package/dist/index-QqbeEiDm.d.ts +857 -0
- package/dist/index-UiYCgwiH.d.ts +174 -0
- package/dist/index.d.ts +453 -0
- package/dist/index.js +44228 -0
- package/dist/index.js.map +1 -0
- package/dist/mcp/index.d.ts +1 -0
- package/dist/mcp/index.js +41173 -0
- package/dist/mcp/index.js.map +1 -0
- package/generators/index.ts +82 -0
- package/intelligence/orchestrator/config/failure-signatures.js +48 -0
- package/intelligence/orchestrator/config/index.js +23 -0
- package/intelligence/orchestrator/config/pack-lifecycle.js +262 -0
- package/intelligence/orchestrator/config/phases.js +111 -0
- package/intelligence/orchestrator/config/remediation.js +150 -0
- package/intelligence/orchestrator/config/workflows.js +168 -0
- package/intelligence/orchestrator/core/index.js +16 -0
- package/intelligence/orchestrator/core/state-manager.js +88 -0
- package/intelligence/orchestrator/core/telemetry.js +24 -0
- package/intelligence/orchestrator/index.js +17 -0
- package/intelligence/orchestrator.js +17 -512
- package/mcp/contracts/mcp-contract.v1.json +1 -1
- package/package.json +16 -3
- package/src/cli/agent.ts +703 -0
- package/src/cli/analyze.ts +640 -0
- package/src/cli/audit.ts +707 -0
- package/src/cli/auth.ts +930 -0
- package/src/cli/billing.ts +364 -0
- package/src/cli/build.ts +1089 -0
- package/src/cli/business.ts +508 -0
- package/src/cli/checkpoint-utils.ts +236 -0
- package/src/cli/checkpoint.ts +757 -0
- package/src/cli/cloud-sync.ts +534 -0
- package/src/cli/content.ts +273 -0
- package/src/cli/context.ts +667 -0
- package/src/cli/dashboard.ts +133 -0
- package/src/cli/deploy.ts +704 -0
- package/src/cli/doctor.ts +480 -0
- package/src/cli/fundraise.ts +494 -0
- package/src/cli/generate.ts +346 -0
- package/src/cli/github-cmd.ts +566 -0
- package/src/cli/health.ts +599 -0
- package/src/cli/index.ts +113 -0
- package/src/cli/init.ts +838 -0
- package/src/cli/legal.ts +495 -0
- package/src/cli/log.ts +316 -0
- package/src/cli/loop.ts +1660 -0
- package/src/cli/manager.ts +878 -0
- package/src/cli/mcp.ts +275 -0
- package/src/cli/memory.ts +346 -0
- package/src/cli/metrics.ts +590 -0
- package/src/cli/monitor.ts +960 -0
- package/src/cli/mvp.ts +662 -0
- package/src/cli/onboard.ts +663 -0
- package/src/cli/orchestrator.ts +622 -0
- package/src/cli/plugin.ts +483 -0
- package/src/cli/prd.ts +671 -0
- package/src/cli/preseed-start.ts +1633 -0
- package/src/cli/preseed.ts +2434 -0
- package/src/cli/project.ts +526 -0
- package/src/cli/quality.ts +885 -0
- package/src/cli/security.ts +1079 -0
- package/src/cli/seed.ts +1224 -0
- package/src/cli/skill.ts +537 -0
- package/src/cli/suggest.ts +1225 -0
- package/src/cli/switch.ts +518 -0
- package/src/cli/task.ts +780 -0
- package/src/cli/telemetry.ts +172 -0
- package/src/cli/todo.ts +627 -0
- package/src/cli/types.ts +15 -0
- package/src/cli/update.ts +334 -0
- package/src/cli/visualize.ts +609 -0
- package/src/cli/watch.ts +895 -0
- package/src/cli/workspace.ts +709 -0
- package/src/core/action-recorder.ts +673 -0
- package/src/core/analyze-workflow.ts +1453 -0
- package/src/core/api-client.ts +1120 -0
- package/src/core/audit-workflow.ts +1681 -0
- package/src/core/auth.ts +471 -0
- package/src/core/build-orchestrator.ts +509 -0
- package/src/core/build-state.ts +621 -0
- package/src/core/checkpoint-engine.ts +482 -0
- package/src/core/config.ts +1285 -0
- package/src/core/context-loader.ts +694 -0
- package/src/core/context.ts +410 -0
- package/src/core/deploy-workflow.ts +1085 -0
- package/src/core/entitlements.ts +322 -0
- package/src/core/github-sync.ts +720 -0
- package/src/core/index.ts +981 -0
- package/src/core/ingest.ts +1186 -0
- package/src/core/metrics-engine.ts +886 -0
- package/src/core/mvp.ts +847 -0
- package/src/core/onboard-workflow.ts +1293 -0
- package/src/core/policies.ts +81 -0
- package/src/core/preseed-workflow.ts +1163 -0
- package/src/core/preseed.ts +1826 -0
- package/src/core/project-context.ts +380 -0
- package/src/core/project-state.ts +699 -0
- package/src/core/r2-sync.ts +691 -0
- package/src/core/scaffold.ts +1715 -0
- package/src/core/session.ts +286 -0
- package/src/core/task-extractor.ts +799 -0
- package/src/core/telemetry.ts +371 -0
- package/src/core/tier-enforcement.ts +737 -0
- package/src/core/utils.ts +437 -0
- package/src/index.ts +29 -0
- package/src/intelligence/agent-collab.ts +2376 -0
- package/src/intelligence/auto-suggest.ts +713 -0
- package/src/intelligence/content-gen.ts +1351 -0
- package/src/intelligence/cross-project.ts +1692 -0
- package/src/intelligence/git-memory.ts +529 -0
- package/src/intelligence/index.ts +318 -0
- package/src/intelligence/orchestrator.ts +534 -0
- package/src/intelligence/prd.ts +466 -0
- package/src/intelligence/recommendations.ts +982 -0
- package/src/intelligence/workflow-composer.ts +1472 -0
- package/src/mcp/capabilities.ts +233 -0
- package/src/mcp/index.ts +37 -0
- package/src/mcp/registry.ts +1268 -0
- package/src/mcp/response-formatter.ts +797 -0
- package/src/mcp/server.ts +240 -0
- package/src/types/agent.ts +69 -0
- package/src/types/config.ts +86 -0
- package/src/types/context.ts +77 -0
- package/src/types/index.ts +53 -0
- package/src/types/mcp.ts +91 -0
- package/src/types/skills.ts +47 -0
- package/src/types/workflow.ts +155 -0
- package/generators/index.js +0 -18
|
@@ -0,0 +1,667 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Context Command
|
|
3
|
+
* View, search, and manage project context files
|
|
4
|
+
*
|
|
5
|
+
* Commands:
|
|
6
|
+
* show Show context summary (default)
|
|
7
|
+
* validate Validate project setup
|
|
8
|
+
* refresh Regenerate context files
|
|
9
|
+
* list List all context files
|
|
10
|
+
* read <type> Read a context file
|
|
11
|
+
* search <query> Search across context files
|
|
12
|
+
* agent <name> Show context for an agent
|
|
13
|
+
* index Rebuild context index
|
|
14
|
+
* types Show available context types
|
|
15
|
+
* agents Show agent to context mapping
|
|
16
|
+
*
|
|
17
|
+
* @package bootspring
|
|
18
|
+
* @module cli/context
|
|
19
|
+
*/
|
|
20
|
+
|
|
21
|
+
// Import JS modules with type interfaces
|
|
22
|
+
interface Config {
|
|
23
|
+
_projectRoot: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
interface ConfigModule {
|
|
27
|
+
load(): Config;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
interface ContextProject {
|
|
31
|
+
name: string;
|
|
32
|
+
version: string;
|
|
33
|
+
description?: string;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
interface ContextStack {
|
|
37
|
+
framework: string;
|
|
38
|
+
language: string;
|
|
39
|
+
database: string;
|
|
40
|
+
hosting: string;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
interface ContextPlugin {
|
|
44
|
+
provider: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
interface ContextState {
|
|
48
|
+
phase: string;
|
|
49
|
+
health: string;
|
|
50
|
+
todos: number;
|
|
51
|
+
lastGenerated?: string;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
interface ContextGit {
|
|
55
|
+
initialized: boolean;
|
|
56
|
+
branch?: string;
|
|
57
|
+
hasRemote: boolean;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
interface Context {
|
|
61
|
+
project: ContextProject;
|
|
62
|
+
stack: ContextStack;
|
|
63
|
+
plugins: Record<string, ContextPlugin>;
|
|
64
|
+
state: ContextState;
|
|
65
|
+
git: ContextGit;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
interface ValidationCheck {
|
|
69
|
+
status: 'pass' | 'fail' | 'warn' | 'info';
|
|
70
|
+
name: string;
|
|
71
|
+
message: string;
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
interface ValidationResult {
|
|
75
|
+
checks: ValidationCheck[];
|
|
76
|
+
percentage: number;
|
|
77
|
+
score: number;
|
|
78
|
+
maxScore: number;
|
|
79
|
+
valid: boolean;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
interface ContextModule {
|
|
83
|
+
get(options: { config: Config }): Context;
|
|
84
|
+
validate(options: { config: Config }): ValidationResult;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
interface ContextFile {
|
|
88
|
+
type: string;
|
|
89
|
+
exists: boolean;
|
|
90
|
+
path: string;
|
|
91
|
+
isDirectory?: boolean;
|
|
92
|
+
fileCount?: number;
|
|
93
|
+
size?: number;
|
|
94
|
+
modifiedRelative?: string;
|
|
95
|
+
content?: string;
|
|
96
|
+
metadata?: {
|
|
97
|
+
size: number;
|
|
98
|
+
modifiedRelative: string;
|
|
99
|
+
};
|
|
100
|
+
files?: Array<{ path: string; size: number }>;
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
interface SearchMatch {
|
|
104
|
+
line: number;
|
|
105
|
+
preview: string;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
interface SearchResult {
|
|
109
|
+
type: string;
|
|
110
|
+
file: string;
|
|
111
|
+
matches?: SearchMatch[];
|
|
112
|
+
matchType?: string;
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
interface AgentContext {
|
|
116
|
+
files: Array<ContextFile & { files?: Array<{ path: string }> }>;
|
|
117
|
+
summary: string[];
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
interface ContextIndex {
|
|
121
|
+
files: unknown[];
|
|
122
|
+
agents: Record<string, unknown>;
|
|
123
|
+
lastUpdated: string;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
interface ContextLoaderModule {
|
|
127
|
+
list(options: { config: Config }): ContextFile[];
|
|
128
|
+
load(type: string): ContextFile & { error?: string };
|
|
129
|
+
search(query: string, options: { limit?: number }): SearchResult[];
|
|
130
|
+
getAgentContext(agentName: string): AgentContext;
|
|
131
|
+
getAgentMap(): Record<string, string[]>;
|
|
132
|
+
buildIndex(): ContextIndex;
|
|
133
|
+
getLocations(): Record<string, string>;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
interface GenerateModule {
|
|
137
|
+
run(args: string[]): void;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
interface ParsedArgs {
|
|
141
|
+
_: string[];
|
|
142
|
+
all?: boolean;
|
|
143
|
+
limit?: string;
|
|
144
|
+
metadata?: boolean;
|
|
145
|
+
full?: boolean;
|
|
146
|
+
agent?: string;
|
|
147
|
+
preview?: boolean;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
151
|
+
const config = require('../../core/config') as ConfigModule;
|
|
152
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
153
|
+
const context = require('../../core/context') as ContextModule;
|
|
154
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
155
|
+
const contextLoader = require('../../core/context-loader') as ContextLoaderModule;
|
|
156
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
157
|
+
const utils = require('../../core/utils') as typeof import('../core/utils');
|
|
158
|
+
|
|
159
|
+
/**
|
|
160
|
+
* Show project context summary
|
|
161
|
+
*/
|
|
162
|
+
export function showContext(): void {
|
|
163
|
+
const cfg = config.load();
|
|
164
|
+
const ctx = context.get({ config: cfg });
|
|
165
|
+
|
|
166
|
+
console.log(`
|
|
167
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context${utils.COLORS.reset}
|
|
168
|
+
${utils.COLORS.dim}Project: ${cfg._projectRoot}${utils.COLORS.reset}
|
|
169
|
+
`);
|
|
170
|
+
|
|
171
|
+
// Project Info
|
|
172
|
+
console.log(`${utils.COLORS.bold}Project${utils.COLORS.reset}`);
|
|
173
|
+
console.log(` Name: ${ctx.project.name}`);
|
|
174
|
+
console.log(` Version: ${ctx.project.version}`);
|
|
175
|
+
if (ctx.project.description) {
|
|
176
|
+
console.log(` Description: ${ctx.project.description}`);
|
|
177
|
+
}
|
|
178
|
+
console.log();
|
|
179
|
+
|
|
180
|
+
// Stack
|
|
181
|
+
console.log(`${utils.COLORS.bold}Stack${utils.COLORS.reset}`);
|
|
182
|
+
console.log(` Framework: ${utils.COLORS.cyan}${ctx.stack.framework}${utils.COLORS.reset}`);
|
|
183
|
+
console.log(` Language: ${ctx.stack.language}`);
|
|
184
|
+
console.log(` Database: ${ctx.stack.database}`);
|
|
185
|
+
console.log(` Hosting: ${ctx.stack.hosting}`);
|
|
186
|
+
console.log();
|
|
187
|
+
|
|
188
|
+
// Plugins
|
|
189
|
+
const plugins = Object.keys(ctx.plugins);
|
|
190
|
+
if (plugins.length > 0) {
|
|
191
|
+
console.log(`${utils.COLORS.bold}Enabled Plugins${utils.COLORS.reset}`);
|
|
192
|
+
for (const [name, plugin] of Object.entries(ctx.plugins)) {
|
|
193
|
+
console.log(` ${utils.COLORS.green}●${utils.COLORS.reset} ${name} (${plugin.provider})`);
|
|
194
|
+
}
|
|
195
|
+
console.log();
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
// State
|
|
199
|
+
const healthColor = ctx.state.health === 'good' ? utils.COLORS.green :
|
|
200
|
+
ctx.state.health === 'fair' ? utils.COLORS.yellow :
|
|
201
|
+
utils.COLORS.red;
|
|
202
|
+
|
|
203
|
+
console.log(`${utils.COLORS.bold}State${utils.COLORS.reset}`);
|
|
204
|
+
console.log(` Phase: ${ctx.state.phase}`);
|
|
205
|
+
console.log(` Health: ${healthColor}${ctx.state.health}${utils.COLORS.reset}`);
|
|
206
|
+
console.log(` Open Todos: ${ctx.state.todos}`);
|
|
207
|
+
if (ctx.state.lastGenerated) {
|
|
208
|
+
console.log(` Context Updated: ${utils.formatRelativeTime(new Date(ctx.state.lastGenerated))}`);
|
|
209
|
+
}
|
|
210
|
+
console.log();
|
|
211
|
+
|
|
212
|
+
// Git
|
|
213
|
+
if (ctx.git.initialized) {
|
|
214
|
+
console.log(`${utils.COLORS.bold}Git${utils.COLORS.reset}`);
|
|
215
|
+
console.log(` Branch: ${ctx.git.branch || 'unknown'}`);
|
|
216
|
+
console.log(` Remote: ${ctx.git.hasRemote ? 'configured' : 'not configured'}`);
|
|
217
|
+
console.log();
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
/**
|
|
222
|
+
* Validate project context
|
|
223
|
+
*/
|
|
224
|
+
export function validateContext(): void {
|
|
225
|
+
const cfg = config.load();
|
|
226
|
+
const validation = context.validate({ config: cfg });
|
|
227
|
+
|
|
228
|
+
console.log(`
|
|
229
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context Validation${utils.COLORS.reset}
|
|
230
|
+
`);
|
|
231
|
+
|
|
232
|
+
for (const check of validation.checks) {
|
|
233
|
+
const icon = check.status === 'pass' ? utils.COLORS.green + '✓' :
|
|
234
|
+
check.status === 'fail' ? utils.COLORS.red + '✗' :
|
|
235
|
+
check.status === 'warn' ? utils.COLORS.yellow + '⚠' :
|
|
236
|
+
utils.COLORS.dim + 'ℹ';
|
|
237
|
+
console.log(` ${icon}${utils.COLORS.reset} ${check.name}`);
|
|
238
|
+
console.log(` ${utils.COLORS.dim}${check.message}${utils.COLORS.reset}`);
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
console.log();
|
|
242
|
+
|
|
243
|
+
// Score bar
|
|
244
|
+
const barWidth = 30;
|
|
245
|
+
const filled = Math.round((validation.percentage / 100) * barWidth);
|
|
246
|
+
const empty = barWidth - filled;
|
|
247
|
+
const scoreColor = validation.percentage >= 80 ? utils.COLORS.green :
|
|
248
|
+
validation.percentage >= 50 ? utils.COLORS.yellow :
|
|
249
|
+
utils.COLORS.red;
|
|
250
|
+
|
|
251
|
+
console.log(`${utils.COLORS.bold}Score${utils.COLORS.reset}`);
|
|
252
|
+
console.log(` ${scoreColor}${'█'.repeat(filled)}${utils.COLORS.dim}${'░'.repeat(empty)}${utils.COLORS.reset} ${validation.percentage}%`);
|
|
253
|
+
console.log(` ${validation.score}/${validation.maxScore} checks passed`);
|
|
254
|
+
console.log();
|
|
255
|
+
|
|
256
|
+
if (validation.valid) {
|
|
257
|
+
utils.print.success('Context validation passed');
|
|
258
|
+
} else {
|
|
259
|
+
utils.print.warning('Context needs attention - fix the issues above');
|
|
260
|
+
utils.print.dim('Run "bootspring generate" to regenerate context');
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* Refresh project context
|
|
266
|
+
*/
|
|
267
|
+
export function refreshContext(): void {
|
|
268
|
+
console.log(`
|
|
269
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context Refresh${utils.COLORS.reset}
|
|
270
|
+
`);
|
|
271
|
+
|
|
272
|
+
utils.print.info('Refreshing context...');
|
|
273
|
+
|
|
274
|
+
// This triggers a regeneration
|
|
275
|
+
// eslint-disable-next-line @typescript-eslint/no-require-imports
|
|
276
|
+
const generateModule = require('./generate') as GenerateModule;
|
|
277
|
+
generateModule.run([]);
|
|
278
|
+
}
|
|
279
|
+
|
|
280
|
+
/**
|
|
281
|
+
* List all context files
|
|
282
|
+
*/
|
|
283
|
+
export function listContext(args: string[]): void {
|
|
284
|
+
const parsedArgs = utils.parseArgs(args) as ParsedArgs;
|
|
285
|
+
utils.print.header('Project Context Files');
|
|
286
|
+
|
|
287
|
+
const cfg = config.load();
|
|
288
|
+
const contextList = contextLoader.list({ config: cfg });
|
|
289
|
+
|
|
290
|
+
// Group by category
|
|
291
|
+
const categories: Record<string, string[]> = {
|
|
292
|
+
'Root Files': ['seed', 'claude', 'todo', 'readme', 'changelog'],
|
|
293
|
+
'Planning': ['plan', 'prd', 'architecture', 'decisions', 'roadmap'],
|
|
294
|
+
'Business': ['business_plan', 'pitch_deck', 'competitive', 'market', 'financial'],
|
|
295
|
+
'Legal': ['terms', 'privacy', 'legal_checklist'],
|
|
296
|
+
'Code Context': ['mvp_source', 'mvp_references'],
|
|
297
|
+
'System': ['logs', 'context_index']
|
|
298
|
+
};
|
|
299
|
+
|
|
300
|
+
for (const [category, types] of Object.entries(categories)) {
|
|
301
|
+
const categoryItems = contextList.filter(c => types.includes(c.type));
|
|
302
|
+
const existingCount = categoryItems.filter(c => c.exists).length;
|
|
303
|
+
|
|
304
|
+
if (existingCount > 0 || parsedArgs.all) {
|
|
305
|
+
console.log(`\n${utils.COLORS.bold}${category}${utils.COLORS.reset}`);
|
|
306
|
+
|
|
307
|
+
for (const item of categoryItems) {
|
|
308
|
+
if (item.exists) {
|
|
309
|
+
const icon = item.isDirectory ? '📁' : '📄';
|
|
310
|
+
const size = item.isDirectory
|
|
311
|
+
? `${item.fileCount} files`
|
|
312
|
+
: formatSize(item.size || 0);
|
|
313
|
+
const modified = item.modifiedRelative || '';
|
|
314
|
+
|
|
315
|
+
console.log(` ${utils.COLORS.green}${icon}${utils.COLORS.reset} ${item.type.padEnd(20)} ${item.path}`);
|
|
316
|
+
console.log(` ${utils.COLORS.dim}${size}${modified ? ` • ${modified}` : ''}${utils.COLORS.reset}`);
|
|
317
|
+
} else if (parsedArgs.all) {
|
|
318
|
+
console.log(` ${utils.COLORS.dim}○ ${item.type.padEnd(20)} ${item.path} (not found)${utils.COLORS.reset}`);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
|
|
324
|
+
// Summary
|
|
325
|
+
const total = contextList.length;
|
|
326
|
+
const existing = contextList.filter(c => c.exists).length;
|
|
327
|
+
console.log(`\n${utils.COLORS.dim}Found ${existing}/${total} context files${utils.COLORS.reset}`);
|
|
328
|
+
|
|
329
|
+
if (!parsedArgs.all) {
|
|
330
|
+
utils.print.dim('Use --all to show missing files');
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
|
|
334
|
+
/**
|
|
335
|
+
* Read a specific context file
|
|
336
|
+
*/
|
|
337
|
+
export function readContext(args: string[]): void {
|
|
338
|
+
const parsedArgs = utils.parseArgs(args) as ParsedArgs;
|
|
339
|
+
const contextType = parsedArgs._[0];
|
|
340
|
+
|
|
341
|
+
if (!contextType) {
|
|
342
|
+
utils.print.error('Please specify a context type');
|
|
343
|
+
utils.print.dim('Example: bootspring context read seed');
|
|
344
|
+
utils.print.dim('Run "bootspring context types" to see available types');
|
|
345
|
+
return;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
const loaded = contextLoader.load(contextType);
|
|
349
|
+
|
|
350
|
+
if (!loaded.exists) {
|
|
351
|
+
if (loaded.error) {
|
|
352
|
+
utils.print.error(loaded.error);
|
|
353
|
+
} else {
|
|
354
|
+
utils.print.warning(`Context "${contextType}" not found at: ${loaded.path}`);
|
|
355
|
+
}
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
utils.print.header(`Context: ${contextType}`);
|
|
360
|
+
console.log(`${utils.COLORS.dim}Path: ${loaded.path}${utils.COLORS.reset}\n`);
|
|
361
|
+
|
|
362
|
+
if (loaded.files) {
|
|
363
|
+
// Directory listing
|
|
364
|
+
console.log(`${utils.COLORS.bold}Files (${loaded.fileCount}):${utils.COLORS.reset}\n`);
|
|
365
|
+
|
|
366
|
+
const limit = parsedArgs.limit ? parseInt(parsedArgs.limit, 10) : 20;
|
|
367
|
+
const files = loaded.files.slice(0, limit);
|
|
368
|
+
|
|
369
|
+
for (const file of files) {
|
|
370
|
+
console.log(` ${file.path} ${utils.COLORS.dim}(${formatSize(file.size)})${utils.COLORS.reset}`);
|
|
371
|
+
}
|
|
372
|
+
|
|
373
|
+
if (loaded.fileCount && loaded.fileCount > limit) {
|
|
374
|
+
utils.print.dim(`\n... and ${loaded.fileCount - limit} more files`);
|
|
375
|
+
}
|
|
376
|
+
} else {
|
|
377
|
+
// File content
|
|
378
|
+
if (parsedArgs.metadata && loaded.metadata) {
|
|
379
|
+
console.log(`${utils.COLORS.bold}Metadata:${utils.COLORS.reset}`);
|
|
380
|
+
console.log(` Size: ${formatSize(loaded.metadata.size)}`);
|
|
381
|
+
console.log(` Modified: ${loaded.metadata.modifiedRelative}`);
|
|
382
|
+
console.log('');
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
// Print content (truncate if very long unless --full is passed)
|
|
386
|
+
const content = loaded.content || '';
|
|
387
|
+
const maxLines = parsedArgs.full ? Infinity : 100;
|
|
388
|
+
const lines = content.split('\n');
|
|
389
|
+
|
|
390
|
+
if (lines.length > maxLines) {
|
|
391
|
+
console.log(lines.slice(0, maxLines).join('\n'));
|
|
392
|
+
utils.print.dim(`\n... truncated (${lines.length - maxLines} more lines)`);
|
|
393
|
+
utils.print.dim('Use --full to see entire file');
|
|
394
|
+
} else {
|
|
395
|
+
console.log(content);
|
|
396
|
+
}
|
|
397
|
+
}
|
|
398
|
+
}
|
|
399
|
+
|
|
400
|
+
/**
|
|
401
|
+
* Search across context files
|
|
402
|
+
*/
|
|
403
|
+
export function searchContext(args: string[]): void {
|
|
404
|
+
const parsedArgs = utils.parseArgs(args) as ParsedArgs;
|
|
405
|
+
const query = parsedArgs._[0];
|
|
406
|
+
|
|
407
|
+
if (!query) {
|
|
408
|
+
utils.print.error('Please specify a search query');
|
|
409
|
+
utils.print.dim('Example: bootspring context search "authentication"');
|
|
410
|
+
return;
|
|
411
|
+
}
|
|
412
|
+
|
|
413
|
+
utils.print.header(`Searching for: ${query}`);
|
|
414
|
+
|
|
415
|
+
const limit = parsedArgs.limit ? parseInt(parsedArgs.limit, 10) : 20;
|
|
416
|
+
const results = contextLoader.search(query, { limit });
|
|
417
|
+
|
|
418
|
+
if (results.length === 0) {
|
|
419
|
+
utils.print.warning('No results found');
|
|
420
|
+
return;
|
|
421
|
+
}
|
|
422
|
+
|
|
423
|
+
console.log(`${utils.COLORS.dim}Found ${results.length} result(s)${utils.COLORS.reset}\n`);
|
|
424
|
+
|
|
425
|
+
for (const result of results) {
|
|
426
|
+
console.log(`${utils.COLORS.bold}${result.type}${utils.COLORS.reset}: ${result.file}`);
|
|
427
|
+
|
|
428
|
+
if (result.matches) {
|
|
429
|
+
for (const match of result.matches) {
|
|
430
|
+
console.log(` ${utils.COLORS.dim}L${match.line}:${utils.COLORS.reset} ${highlightMatch(match.preview, query)}`);
|
|
431
|
+
}
|
|
432
|
+
} else if (result.matchType === 'filename') {
|
|
433
|
+
console.log(` ${utils.COLORS.dim}(filename match)${utils.COLORS.reset}`);
|
|
434
|
+
}
|
|
435
|
+
console.log('');
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
/**
|
|
440
|
+
* Show context for a specific agent
|
|
441
|
+
*/
|
|
442
|
+
export function showAgentContext(args: string[]): void {
|
|
443
|
+
const parsedArgs = utils.parseArgs(args) as ParsedArgs;
|
|
444
|
+
const agentName = parsedArgs.agent || parsedArgs._[0];
|
|
445
|
+
|
|
446
|
+
if (!agentName) {
|
|
447
|
+
utils.print.error('Please specify an agent name');
|
|
448
|
+
utils.print.dim('Example: bootspring context agent frontend-expert');
|
|
449
|
+
utils.print.dim('Run "bootspring context agents" to see agent mappings');
|
|
450
|
+
return;
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
const agentContext = contextLoader.getAgentContext(agentName);
|
|
454
|
+
|
|
455
|
+
if (agentContext.files.length === 0) {
|
|
456
|
+
utils.print.warning(`No context available for agent: ${agentName}`);
|
|
457
|
+
|
|
458
|
+
const agentMap = contextLoader.getAgentMap();
|
|
459
|
+
if (!agentMap[agentName]) {
|
|
460
|
+
utils.print.dim('This agent is not in the context mapping.');
|
|
461
|
+
} else {
|
|
462
|
+
utils.print.dim('The mapped context files do not exist yet.');
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
|
|
467
|
+
utils.print.header(`Context for: ${agentName}`);
|
|
468
|
+
console.log(`${utils.COLORS.dim}${agentContext.summary.join(' | ')}${utils.COLORS.reset}\n`);
|
|
469
|
+
|
|
470
|
+
for (const file of agentContext.files) {
|
|
471
|
+
if (file.isDirectory) {
|
|
472
|
+
console.log(`${utils.COLORS.bold}📁 ${file.type}${utils.COLORS.reset} (${file.fileCount} files)`);
|
|
473
|
+
if (file.files && file.files.length > 0) {
|
|
474
|
+
for (const f of file.files.slice(0, 5)) {
|
|
475
|
+
console.log(` ${utils.COLORS.dim}${f.path}${utils.COLORS.reset}`);
|
|
476
|
+
}
|
|
477
|
+
if (file.fileCount && file.fileCount > 5) {
|
|
478
|
+
console.log(` ${utils.COLORS.dim}... and ${file.fileCount - 5} more${utils.COLORS.reset}`);
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
} else {
|
|
482
|
+
console.log(`${utils.COLORS.bold}📄 ${file.type}${utils.COLORS.reset}: ${file.path}`);
|
|
483
|
+
if (file.metadata) {
|
|
484
|
+
console.log(` ${utils.COLORS.dim}${formatSize(file.metadata.size)} • ${file.metadata.modifiedRelative}${utils.COLORS.reset}`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
// Show preview
|
|
488
|
+
if (parsedArgs.preview && file.content) {
|
|
489
|
+
const preview = file.content.split('\n').slice(0, 5).join('\n');
|
|
490
|
+
console.log(` ${utils.COLORS.dim}---${utils.COLORS.reset}`);
|
|
491
|
+
console.log(` ${preview.split('\n').map(l => utils.COLORS.dim + l + utils.COLORS.reset).join('\n ')}`);
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
console.log('');
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
|
|
498
|
+
/**
|
|
499
|
+
* Build/rebuild context index
|
|
500
|
+
*/
|
|
501
|
+
export function buildIndex(): void {
|
|
502
|
+
const spinner = utils.createSpinner('Building context index...').start();
|
|
503
|
+
|
|
504
|
+
try {
|
|
505
|
+
const index = contextLoader.buildIndex();
|
|
506
|
+
|
|
507
|
+
spinner.succeed('Context index built');
|
|
508
|
+
|
|
509
|
+
console.log(`\n${utils.COLORS.bold}Index Summary:${utils.COLORS.reset}`);
|
|
510
|
+
console.log(` Files indexed: ${index.files.length}`);
|
|
511
|
+
console.log(` Agents mapped: ${Object.keys(index.agents).length}`);
|
|
512
|
+
console.log(` Last updated: ${index.lastUpdated}`);
|
|
513
|
+
} catch (error) {
|
|
514
|
+
spinner.fail(`Failed to build index: ${(error as Error).message}`);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
|
|
518
|
+
/**
|
|
519
|
+
* Show available context types
|
|
520
|
+
*/
|
|
521
|
+
export function showTypes(): void {
|
|
522
|
+
utils.print.header('Available Context Types');
|
|
523
|
+
|
|
524
|
+
const locations = contextLoader.getLocations();
|
|
525
|
+
|
|
526
|
+
const headers = ['Type', 'Path'];
|
|
527
|
+
const rows = Object.entries(locations).map(([type, path]) => [type, path]);
|
|
528
|
+
|
|
529
|
+
console.log(utils.createTable(headers, rows));
|
|
530
|
+
}
|
|
531
|
+
|
|
532
|
+
/**
|
|
533
|
+
* Show agent to context mapping
|
|
534
|
+
*/
|
|
535
|
+
export function showAgentMap(): void {
|
|
536
|
+
utils.print.header('Agent Context Mapping');
|
|
537
|
+
|
|
538
|
+
const agentMap = contextLoader.getAgentMap();
|
|
539
|
+
|
|
540
|
+
for (const [agent, types] of Object.entries(agentMap)) {
|
|
541
|
+
console.log(`${utils.COLORS.bold}${agent}${utils.COLORS.reset}`);
|
|
542
|
+
console.log(` ${utils.COLORS.dim}${types.join(', ')}${utils.COLORS.reset}`);
|
|
543
|
+
}
|
|
544
|
+
}
|
|
545
|
+
|
|
546
|
+
/**
|
|
547
|
+
* Format file size
|
|
548
|
+
*/
|
|
549
|
+
function formatSize(bytes: number): string {
|
|
550
|
+
if (bytes < 1024) return `${bytes}B`;
|
|
551
|
+
if (bytes < 1024 * 1024) return `${(bytes / 1024).toFixed(1)}KB`;
|
|
552
|
+
return `${(bytes / 1024 / 1024).toFixed(1)}MB`;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
/**
|
|
556
|
+
* Highlight search match in text
|
|
557
|
+
*/
|
|
558
|
+
function highlightMatch(text: string, query: string): string {
|
|
559
|
+
const regex = new RegExp(`(${query})`, 'gi');
|
|
560
|
+
return text.replace(regex, `${utils.COLORS.yellow}$1${utils.COLORS.reset}`);
|
|
561
|
+
}
|
|
562
|
+
|
|
563
|
+
/**
|
|
564
|
+
* Show context help
|
|
565
|
+
*/
|
|
566
|
+
function showHelp(): void {
|
|
567
|
+
console.log(`
|
|
568
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Context${utils.COLORS.reset}
|
|
569
|
+
${utils.COLORS.dim}View, search, and manage project context${utils.COLORS.reset}
|
|
570
|
+
|
|
571
|
+
${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
572
|
+
bootspring context <command> [options]
|
|
573
|
+
|
|
574
|
+
${utils.COLORS.bold}Commands:${utils.COLORS.reset}
|
|
575
|
+
${utils.COLORS.cyan}show${utils.COLORS.reset} Show context summary (default)
|
|
576
|
+
${utils.COLORS.cyan}validate${utils.COLORS.reset} Validate project setup
|
|
577
|
+
${utils.COLORS.cyan}refresh${utils.COLORS.reset} Regenerate context files
|
|
578
|
+
${utils.COLORS.cyan}list${utils.COLORS.reset} List all context files
|
|
579
|
+
${utils.COLORS.cyan}read <type>${utils.COLORS.reset} Read a context file
|
|
580
|
+
${utils.COLORS.cyan}search <query>${utils.COLORS.reset} Search across context files
|
|
581
|
+
${utils.COLORS.cyan}agent <name>${utils.COLORS.reset} Show context for an agent
|
|
582
|
+
${utils.COLORS.cyan}index${utils.COLORS.reset} Rebuild context index
|
|
583
|
+
${utils.COLORS.cyan}types${utils.COLORS.reset} Show available context types
|
|
584
|
+
${utils.COLORS.cyan}agents${utils.COLORS.reset} Show agent to context mapping
|
|
585
|
+
|
|
586
|
+
${utils.COLORS.bold}Options:${utils.COLORS.reset}
|
|
587
|
+
--all Show all files (including missing)
|
|
588
|
+
--full Show full file content (no truncation)
|
|
589
|
+
--preview Show content preview
|
|
590
|
+
--limit=<n> Limit results
|
|
591
|
+
--metadata Show file metadata
|
|
592
|
+
|
|
593
|
+
${utils.COLORS.bold}Examples:${utils.COLORS.reset}
|
|
594
|
+
bootspring context
|
|
595
|
+
bootspring context list --all
|
|
596
|
+
bootspring context read seed
|
|
597
|
+
bootspring context search "authentication"
|
|
598
|
+
bootspring context agent frontend-expert
|
|
599
|
+
`);
|
|
600
|
+
}
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Run context command
|
|
604
|
+
*/
|
|
605
|
+
export async function run(args: string[]): Promise<void> {
|
|
606
|
+
const subcommand = args[0] || 'show';
|
|
607
|
+
const subArgs = args.slice(1);
|
|
608
|
+
|
|
609
|
+
switch (subcommand) {
|
|
610
|
+
case 'show':
|
|
611
|
+
showContext();
|
|
612
|
+
break;
|
|
613
|
+
|
|
614
|
+
case 'validate':
|
|
615
|
+
case 'check':
|
|
616
|
+
validateContext();
|
|
617
|
+
break;
|
|
618
|
+
|
|
619
|
+
case 'refresh':
|
|
620
|
+
case 'regenerate':
|
|
621
|
+
refreshContext();
|
|
622
|
+
break;
|
|
623
|
+
|
|
624
|
+
case 'list':
|
|
625
|
+
case 'ls':
|
|
626
|
+
listContext(subArgs);
|
|
627
|
+
break;
|
|
628
|
+
|
|
629
|
+
case 'read':
|
|
630
|
+
case 'cat':
|
|
631
|
+
case 'get':
|
|
632
|
+
readContext(subArgs);
|
|
633
|
+
break;
|
|
634
|
+
|
|
635
|
+
case 'search':
|
|
636
|
+
case 'find':
|
|
637
|
+
searchContext(subArgs);
|
|
638
|
+
break;
|
|
639
|
+
|
|
640
|
+
case 'agent':
|
|
641
|
+
showAgentContext(subArgs);
|
|
642
|
+
break;
|
|
643
|
+
|
|
644
|
+
case 'index':
|
|
645
|
+
case 'reindex':
|
|
646
|
+
buildIndex();
|
|
647
|
+
break;
|
|
648
|
+
|
|
649
|
+
case 'types':
|
|
650
|
+
showTypes();
|
|
651
|
+
break;
|
|
652
|
+
|
|
653
|
+
case 'agents':
|
|
654
|
+
showAgentMap();
|
|
655
|
+
break;
|
|
656
|
+
|
|
657
|
+
case 'help':
|
|
658
|
+
case '-h':
|
|
659
|
+
case '--help':
|
|
660
|
+
showHelp();
|
|
661
|
+
break;
|
|
662
|
+
|
|
663
|
+
default:
|
|
664
|
+
utils.print.error(`Unknown subcommand: ${subcommand}`);
|
|
665
|
+
showHelp();
|
|
666
|
+
}
|
|
667
|
+
}
|