@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,410 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Bootspring Context Manager
|
|
3
|
+
* Handles project context for AI assistants
|
|
4
|
+
*
|
|
5
|
+
* @package bootspring
|
|
6
|
+
* @module core/context
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import * as configModule from './config';
|
|
11
|
+
import * as utils from './utils';
|
|
12
|
+
import type { LoadedConfig, ConfigInput } from './config';
|
|
13
|
+
|
|
14
|
+
// =============================================================================
|
|
15
|
+
// Types
|
|
16
|
+
// =============================================================================
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* Enabled plugin info
|
|
20
|
+
*/
|
|
21
|
+
export interface EnabledPlugin {
|
|
22
|
+
provider: string;
|
|
23
|
+
features: string[];
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Enabled plugins map
|
|
28
|
+
*/
|
|
29
|
+
export interface EnabledPlugins {
|
|
30
|
+
[name: string]: EnabledPlugin;
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* Project file structure info
|
|
35
|
+
*/
|
|
36
|
+
export interface ProjectFiles {
|
|
37
|
+
hasPackageJson: boolean;
|
|
38
|
+
hasTsConfig: boolean;
|
|
39
|
+
hasClaudeMd: boolean;
|
|
40
|
+
hasBootspringConfig: boolean;
|
|
41
|
+
hasTodoMd: boolean;
|
|
42
|
+
hasGit: boolean;
|
|
43
|
+
hasSrcDir: boolean;
|
|
44
|
+
hasAppDir: boolean;
|
|
45
|
+
hasPagesDir: boolean;
|
|
46
|
+
structure: 'app-router' | 'pages-router' | 'src-based' | 'flat';
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Git repository info
|
|
51
|
+
*/
|
|
52
|
+
export interface GitInfo {
|
|
53
|
+
initialized: boolean;
|
|
54
|
+
branch?: string | undefined;
|
|
55
|
+
hasRemote?: boolean | undefined;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
/**
|
|
59
|
+
* Project state info
|
|
60
|
+
*/
|
|
61
|
+
export interface ProjectState {
|
|
62
|
+
phase: 'unknown' | 'uninitialized' | 'initialized' | 'active';
|
|
63
|
+
health: 'unknown' | 'good' | 'fair' | 'needs-attention';
|
|
64
|
+
todos: number;
|
|
65
|
+
lastGenerated: Date | null;
|
|
66
|
+
issues?: string[] | undefined;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Full project context
|
|
71
|
+
*/
|
|
72
|
+
export interface ProjectContext {
|
|
73
|
+
project: ConfigInput['project'];
|
|
74
|
+
stack: ConfigInput['stack'];
|
|
75
|
+
plugins: EnabledPlugins;
|
|
76
|
+
files: ProjectFiles;
|
|
77
|
+
git: GitInfo;
|
|
78
|
+
state: ProjectState;
|
|
79
|
+
timestamp: string;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Validation check result
|
|
84
|
+
*/
|
|
85
|
+
export interface ValidationCheck {
|
|
86
|
+
name: string;
|
|
87
|
+
status: 'pass' | 'fail' | 'warn';
|
|
88
|
+
message: string;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* Context validation result
|
|
93
|
+
*/
|
|
94
|
+
export interface ContextValidationResult {
|
|
95
|
+
valid: boolean;
|
|
96
|
+
score: number;
|
|
97
|
+
maxScore: number;
|
|
98
|
+
percentage: number;
|
|
99
|
+
checks: ValidationCheck[];
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
/**
|
|
103
|
+
* Options for get/validate functions
|
|
104
|
+
*/
|
|
105
|
+
export interface ContextOptions {
|
|
106
|
+
config?: LoadedConfig | undefined;
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
// =============================================================================
|
|
110
|
+
// Functions
|
|
111
|
+
// =============================================================================
|
|
112
|
+
|
|
113
|
+
/**
|
|
114
|
+
* Get current project context
|
|
115
|
+
*/
|
|
116
|
+
export function get(options: ContextOptions = {}): ProjectContext {
|
|
117
|
+
const cfg = options.config ?? configModule.load();
|
|
118
|
+
const projectRoot = cfg._projectRoot ?? process.cwd();
|
|
119
|
+
|
|
120
|
+
const context: ProjectContext = {
|
|
121
|
+
project: cfg.project,
|
|
122
|
+
stack: cfg.stack,
|
|
123
|
+
plugins: getEnabledPlugins(cfg),
|
|
124
|
+
files: getProjectFiles(projectRoot),
|
|
125
|
+
git: getGitInfo(projectRoot),
|
|
126
|
+
state: getProjectState(projectRoot, cfg),
|
|
127
|
+
timestamp: new Date().toISOString()
|
|
128
|
+
};
|
|
129
|
+
|
|
130
|
+
return context;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/**
|
|
134
|
+
* Get enabled plugins from config
|
|
135
|
+
*/
|
|
136
|
+
export function getEnabledPlugins(cfg: LoadedConfig | ConfigInput): EnabledPlugins {
|
|
137
|
+
const enabled: EnabledPlugins = {};
|
|
138
|
+
|
|
139
|
+
const plugins = cfg.plugins ?? {};
|
|
140
|
+
for (const [name, plugin] of Object.entries(plugins)) {
|
|
141
|
+
if (plugin && plugin.enabled !== false) {
|
|
142
|
+
enabled[name] = {
|
|
143
|
+
provider: (plugin as { provider?: string }).provider ?? 'default',
|
|
144
|
+
features: (plugin as { features?: string[] }).features ?? []
|
|
145
|
+
};
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
return enabled;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
/**
|
|
153
|
+
* Get project file structure summary
|
|
154
|
+
*/
|
|
155
|
+
export function getProjectFiles(projectRoot: string): ProjectFiles {
|
|
156
|
+
const files: ProjectFiles = {
|
|
157
|
+
hasPackageJson: utils.fileExists(path.join(projectRoot, 'package.json')),
|
|
158
|
+
hasTsConfig: utils.fileExists(path.join(projectRoot, 'tsconfig.json')),
|
|
159
|
+
hasClaudeMd: utils.fileExists(path.join(projectRoot, 'CLAUDE.md')),
|
|
160
|
+
hasBootspringConfig: utils.fileExists(path.join(projectRoot, 'bootspring.config.js')),
|
|
161
|
+
hasTodoMd: utils.fileExists(path.join(projectRoot, 'todo.md')),
|
|
162
|
+
hasGit: utils.fileExists(path.join(projectRoot, '.git')),
|
|
163
|
+
hasSrcDir: utils.fileExists(path.join(projectRoot, 'src')),
|
|
164
|
+
hasAppDir: utils.fileExists(path.join(projectRoot, 'app')),
|
|
165
|
+
hasPagesDir: utils.fileExists(path.join(projectRoot, 'pages')),
|
|
166
|
+
structure: 'flat'
|
|
167
|
+
};
|
|
168
|
+
|
|
169
|
+
// Detect framework structure
|
|
170
|
+
if (files.hasAppDir) {
|
|
171
|
+
files.structure = 'app-router';
|
|
172
|
+
} else if (files.hasPagesDir) {
|
|
173
|
+
files.structure = 'pages-router';
|
|
174
|
+
} else if (files.hasSrcDir) {
|
|
175
|
+
files.structure = 'src-based';
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
return files;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
/**
|
|
182
|
+
* Get git information
|
|
183
|
+
*/
|
|
184
|
+
export function getGitInfo(projectRoot: string): GitInfo {
|
|
185
|
+
const gitDir = path.join(projectRoot, '.git');
|
|
186
|
+
|
|
187
|
+
if (!utils.fileExists(gitDir)) {
|
|
188
|
+
return { initialized: false };
|
|
189
|
+
}
|
|
190
|
+
|
|
191
|
+
const info: GitInfo = { initialized: true };
|
|
192
|
+
|
|
193
|
+
// Get current branch
|
|
194
|
+
const headPath = path.join(gitDir, 'HEAD');
|
|
195
|
+
if (utils.fileExists(headPath)) {
|
|
196
|
+
const head = utils.readFile(headPath);
|
|
197
|
+
if (head) {
|
|
198
|
+
const trimmedHead = head.trim();
|
|
199
|
+
if (trimmedHead.startsWith('ref: refs/heads/')) {
|
|
200
|
+
info.branch = trimmedHead.replace('ref: refs/heads/', '');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
// Check for remote
|
|
206
|
+
const configPath = path.join(gitDir, 'config');
|
|
207
|
+
if (utils.fileExists(configPath)) {
|
|
208
|
+
const gitConfig = utils.readFile(configPath);
|
|
209
|
+
if (gitConfig) {
|
|
210
|
+
info.hasRemote = gitConfig.includes('[remote "origin"]');
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
return info;
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Get project state
|
|
219
|
+
*/
|
|
220
|
+
export function getProjectState(projectRoot: string, cfg: LoadedConfig | ConfigInput): ProjectState {
|
|
221
|
+
const state: ProjectState = {
|
|
222
|
+
phase: 'unknown',
|
|
223
|
+
health: 'unknown',
|
|
224
|
+
todos: 0,
|
|
225
|
+
lastGenerated: null
|
|
226
|
+
};
|
|
227
|
+
|
|
228
|
+
// Count todos
|
|
229
|
+
const todoPath = path.join(projectRoot, cfg.paths?.todo ?? 'todo.md');
|
|
230
|
+
if (utils.fileExists(todoPath)) {
|
|
231
|
+
const content = utils.readFile(todoPath);
|
|
232
|
+
if (content) {
|
|
233
|
+
const todoMatches = content.match(/- \[ \]/g);
|
|
234
|
+
state.todos = todoMatches ? todoMatches.length : 0;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
|
|
238
|
+
// Check CLAUDE.md generation time
|
|
239
|
+
const claudePath = path.join(projectRoot, cfg.paths?.context ?? 'CLAUDE.md');
|
|
240
|
+
if (utils.fileExists(claudePath)) {
|
|
241
|
+
state.lastGenerated = utils.getFileTime(claudePath);
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
// Determine phase
|
|
245
|
+
const loadedCfg = cfg as LoadedConfig;
|
|
246
|
+
if (!loadedCfg._configPath) {
|
|
247
|
+
state.phase = 'uninitialized';
|
|
248
|
+
} else if (!state.lastGenerated) {
|
|
249
|
+
state.phase = 'initialized';
|
|
250
|
+
} else {
|
|
251
|
+
state.phase = 'active';
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
// Determine health
|
|
255
|
+
const issues: string[] = [];
|
|
256
|
+
if (!utils.fileExists(path.join(projectRoot, 'package.json'))) {
|
|
257
|
+
issues.push('missing-package-json');
|
|
258
|
+
}
|
|
259
|
+
if (!loadedCfg._configPath) {
|
|
260
|
+
issues.push('missing-config');
|
|
261
|
+
}
|
|
262
|
+
if (!state.lastGenerated) {
|
|
263
|
+
issues.push('missing-context');
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
if (issues.length === 0) {
|
|
267
|
+
state.health = 'good';
|
|
268
|
+
} else if (issues.length <= 2) {
|
|
269
|
+
state.health = 'fair';
|
|
270
|
+
} else {
|
|
271
|
+
state.health = 'needs-attention';
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
state.issues = issues;
|
|
275
|
+
|
|
276
|
+
return state;
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Validate project context
|
|
281
|
+
*/
|
|
282
|
+
export function validate(options: ContextOptions = {}): ContextValidationResult {
|
|
283
|
+
const cfg = options.config ?? configModule.load();
|
|
284
|
+
const projectRoot = cfg._projectRoot ?? process.cwd();
|
|
285
|
+
|
|
286
|
+
const checks: ValidationCheck[] = [];
|
|
287
|
+
let score = 0;
|
|
288
|
+
const maxScore = 10;
|
|
289
|
+
|
|
290
|
+
// Check 1: Config exists
|
|
291
|
+
if (cfg._configPath) {
|
|
292
|
+
checks.push({ name: 'Configuration', status: 'pass', message: 'bootspring.config.js found' });
|
|
293
|
+
score += 2;
|
|
294
|
+
} else {
|
|
295
|
+
checks.push({ name: 'Configuration', status: 'fail', message: 'bootspring.config.js missing' });
|
|
296
|
+
}
|
|
297
|
+
|
|
298
|
+
// Check 2: CLAUDE.md exists
|
|
299
|
+
const claudePath = path.join(projectRoot, cfg.paths?.context ?? 'CLAUDE.md');
|
|
300
|
+
if (utils.fileExists(claudePath)) {
|
|
301
|
+
checks.push({ name: 'AI Context', status: 'pass', message: 'CLAUDE.md exists' });
|
|
302
|
+
score += 2;
|
|
303
|
+
} else {
|
|
304
|
+
checks.push({ name: 'AI Context', status: 'fail', message: 'CLAUDE.md missing - run bootspring generate' });
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Check 3: package.json exists
|
|
308
|
+
if (utils.fileExists(path.join(projectRoot, 'package.json'))) {
|
|
309
|
+
checks.push({ name: 'Package', status: 'pass', message: 'package.json found' });
|
|
310
|
+
score += 1;
|
|
311
|
+
} else {
|
|
312
|
+
checks.push({ name: 'Package', status: 'warn', message: 'package.json missing' });
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
// Check 4: Git initialized
|
|
316
|
+
if (utils.fileExists(path.join(projectRoot, '.git'))) {
|
|
317
|
+
checks.push({ name: 'Git', status: 'pass', message: 'Git repository initialized' });
|
|
318
|
+
score += 1;
|
|
319
|
+
} else {
|
|
320
|
+
checks.push({ name: 'Git', status: 'warn', message: 'Git not initialized' });
|
|
321
|
+
}
|
|
322
|
+
|
|
323
|
+
// Check 5: TypeScript config (if using TS)
|
|
324
|
+
if (cfg.stack?.language === 'typescript') {
|
|
325
|
+
if (utils.fileExists(path.join(projectRoot, 'tsconfig.json'))) {
|
|
326
|
+
checks.push({ name: 'TypeScript', status: 'pass', message: 'tsconfig.json found' });
|
|
327
|
+
score += 1;
|
|
328
|
+
} else {
|
|
329
|
+
checks.push({ name: 'TypeScript', status: 'fail', message: 'tsconfig.json missing for TypeScript project' });
|
|
330
|
+
}
|
|
331
|
+
} else {
|
|
332
|
+
score += 1;
|
|
333
|
+
}
|
|
334
|
+
|
|
335
|
+
// Check 6: Config validation
|
|
336
|
+
const configValidation = configModule.validate(cfg);
|
|
337
|
+
if (configValidation.valid) {
|
|
338
|
+
checks.push({ name: 'Config Validation', status: 'pass', message: 'Configuration is valid' });
|
|
339
|
+
score += 2;
|
|
340
|
+
} else {
|
|
341
|
+
checks.push({ name: 'Config Validation', status: 'fail', message: configValidation.errors.join(', ') });
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
// Check 7: Todo file
|
|
345
|
+
if (utils.fileExists(path.join(projectRoot, cfg.paths?.todo ?? 'todo.md'))) {
|
|
346
|
+
checks.push({ name: 'Todo Tracking', status: 'pass', message: 'todo.md exists' });
|
|
347
|
+
score += 1;
|
|
348
|
+
} else {
|
|
349
|
+
checks.push({ name: 'Todo Tracking', status: 'fail', message: 'todo.md not found' });
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
return {
|
|
353
|
+
valid: score >= maxScore * 0.6,
|
|
354
|
+
score,
|
|
355
|
+
maxScore,
|
|
356
|
+
percentage: Math.round((score / maxScore) * 100),
|
|
357
|
+
checks
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
/**
|
|
362
|
+
* Generate context summary for AI
|
|
363
|
+
*/
|
|
364
|
+
export function generateSummary(options: ContextOptions = {}): string {
|
|
365
|
+
const ctx = get(options);
|
|
366
|
+
|
|
367
|
+
const lines: string[] = [
|
|
368
|
+
'# Project Context',
|
|
369
|
+
'',
|
|
370
|
+
`**Project**: ${ctx.project?.name ?? 'Unknown'}`,
|
|
371
|
+
`**Generated**: ${ctx.timestamp}`,
|
|
372
|
+
'',
|
|
373
|
+
'## Stack',
|
|
374
|
+
`- Framework: ${ctx.stack?.framework ?? 'unknown'}`,
|
|
375
|
+
`- Language: ${ctx.stack?.language ?? 'unknown'}`,
|
|
376
|
+
`- Database: ${ctx.stack?.database ?? 'unknown'}`,
|
|
377
|
+
`- Hosting: ${ctx.stack?.hosting ?? 'unknown'}`,
|
|
378
|
+
''
|
|
379
|
+
];
|
|
380
|
+
|
|
381
|
+
// Plugins
|
|
382
|
+
const enabledPlugins = Object.keys(ctx.plugins);
|
|
383
|
+
if (enabledPlugins.length > 0) {
|
|
384
|
+
lines.push('## Enabled Plugins');
|
|
385
|
+
for (const [name, plugin] of Object.entries(ctx.plugins)) {
|
|
386
|
+
lines.push(`- **${name}**: ${plugin.provider}`);
|
|
387
|
+
}
|
|
388
|
+
lines.push('');
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
// State
|
|
392
|
+
lines.push('## Project State');
|
|
393
|
+
lines.push(`- Phase: ${ctx.state.phase}`);
|
|
394
|
+
lines.push(`- Health: ${ctx.state.health}`);
|
|
395
|
+
lines.push(`- Open Todos: ${ctx.state.todos}`);
|
|
396
|
+
if (ctx.state.lastGenerated) {
|
|
397
|
+
lines.push(`- Context Last Generated: ${utils.formatRelativeTime(ctx.state.lastGenerated)}`);
|
|
398
|
+
}
|
|
399
|
+
lines.push('');
|
|
400
|
+
|
|
401
|
+
// Git
|
|
402
|
+
if (ctx.git.initialized) {
|
|
403
|
+
lines.push('## Git');
|
|
404
|
+
lines.push(`- Branch: ${ctx.git.branch ?? 'unknown'}`);
|
|
405
|
+
lines.push(`- Remote: ${ctx.git.hasRemote ? 'configured' : 'not configured'}`);
|
|
406
|
+
lines.push('');
|
|
407
|
+
}
|
|
408
|
+
|
|
409
|
+
return lines.join('\n');
|
|
410
|
+
}
|