@girardmedia/bootspring 2.0.37 → 2.0.38
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/cli/analyze.js +312 -0
- package/cli/generate.js +182 -1
- package/cli/visualize.js +171 -1
- package/core/coherence/index.js +15 -1
- package/core/coherence/semantic-analyzer.js +836 -0
- package/generators/visual-doc-generator.js +910 -0
- package/intelligence/index.js +14 -1
- package/intelligence/model-context-optimizer.js +704 -0
- package/mcp/contracts/mcp-contract.v1.json +1 -1
- package/package.json +1 -1
package/cli/analyze.js
CHANGED
|
@@ -21,6 +21,32 @@ function getContinuousAnalyzer() {
|
|
|
21
21
|
return ContinuousAnalyzer;
|
|
22
22
|
}
|
|
23
23
|
|
|
24
|
+
// Lazy load Phase 3 modules
|
|
25
|
+
let DeepArchitectureAnalyzer = null;
|
|
26
|
+
let ContinuousSecurityAnalyzer = null;
|
|
27
|
+
let SemanticDocumentAnalyzer = null;
|
|
28
|
+
|
|
29
|
+
function getDeepArchitectureAnalyzer() {
|
|
30
|
+
if (!DeepArchitectureAnalyzer) {
|
|
31
|
+
DeepArchitectureAnalyzer = require('../analyzers').DeepArchitectureAnalyzer;
|
|
32
|
+
}
|
|
33
|
+
return DeepArchitectureAnalyzer;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
function getContinuousSecurityAnalyzer() {
|
|
37
|
+
if (!ContinuousSecurityAnalyzer) {
|
|
38
|
+
ContinuousSecurityAnalyzer = require('../analyzers').ContinuousSecurityAnalyzer;
|
|
39
|
+
}
|
|
40
|
+
return ContinuousSecurityAnalyzer;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
function getSemanticDocumentAnalyzer() {
|
|
44
|
+
if (!SemanticDocumentAnalyzer) {
|
|
45
|
+
SemanticDocumentAnalyzer = require('../core/coherence').SemanticDocumentAnalyzer;
|
|
46
|
+
}
|
|
47
|
+
return SemanticDocumentAnalyzer;
|
|
48
|
+
}
|
|
49
|
+
|
|
24
50
|
// Get project root
|
|
25
51
|
const projectRoot = process.cwd();
|
|
26
52
|
|
|
@@ -39,12 +65,16 @@ ${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
|
39
65
|
bootspring analyze reset Reset workflow
|
|
40
66
|
bootspring analyze watch Watch mode - continuous analysis
|
|
41
67
|
bootspring analyze drift Detect documentation drift
|
|
68
|
+
bootspring analyze deep Deep architecture analysis
|
|
69
|
+
bootspring analyze security Continuous security analysis
|
|
70
|
+
bootspring analyze semantic Semantic document analysis
|
|
42
71
|
|
|
43
72
|
${utils.COLORS.bold}Options:${utils.COLORS.reset}
|
|
44
73
|
--depth=<level> Analysis depth: shallow, standard, deep
|
|
45
74
|
--phase=<phase> Run specific phase only
|
|
46
75
|
--include=<glob> Include pattern (e.g., "src/**")
|
|
47
76
|
--exclude=<glob> Exclude pattern
|
|
77
|
+
--json Output results as JSON
|
|
48
78
|
|
|
49
79
|
${utils.COLORS.bold}Watch Mode:${utils.COLORS.reset}
|
|
50
80
|
--watch Start file watcher for continuous analysis
|
|
@@ -55,6 +85,14 @@ ${utils.COLORS.bold}Depth Levels:${utils.COLORS.reset}
|
|
|
55
85
|
standard Standard analysis with patterns and dependencies
|
|
56
86
|
deep Comprehensive with flow tracing and components
|
|
57
87
|
|
|
88
|
+
${utils.COLORS.bold}Advanced Analysis (Phase 3):${utils.COLORS.reset}
|
|
89
|
+
deep Comprehensive architecture analysis with data flow,
|
|
90
|
+
dependencies, components, and quality indicators
|
|
91
|
+
security Continuous security analysis with auth, data protection,
|
|
92
|
+
compliance, and vulnerability scanning
|
|
93
|
+
semantic AI-powered document understanding with concept extraction,
|
|
94
|
+
terminology analysis, and contradiction detection
|
|
95
|
+
|
|
58
96
|
${utils.COLORS.bold}Notes:${utils.COLORS.reset}
|
|
59
97
|
Large codebases (500+ files) automatically skip heavy dependency
|
|
60
98
|
analysis for performance. Use --depth=deep to force full analysis.
|
|
@@ -66,6 +104,9 @@ ${utils.COLORS.bold}Examples:${utils.COLORS.reset}
|
|
|
66
104
|
bootspring analyze status
|
|
67
105
|
bootspring analyze watch Continuous file watching
|
|
68
106
|
bootspring analyze drift Check documentation alignment
|
|
107
|
+
bootspring analyze deep Deep architecture analysis
|
|
108
|
+
bootspring analyze security Security posture analysis
|
|
109
|
+
bootspring analyze semantic Document semantic analysis
|
|
69
110
|
`);
|
|
70
111
|
}
|
|
71
112
|
|
|
@@ -626,6 +667,268 @@ async function analyzeDrift() {
|
|
|
626
667
|
}
|
|
627
668
|
}
|
|
628
669
|
|
|
670
|
+
/**
|
|
671
|
+
* Run deep architecture analysis
|
|
672
|
+
*/
|
|
673
|
+
async function analyzeDeepArchitecture(args) {
|
|
674
|
+
const Analyzer = getDeepArchitectureAnalyzer();
|
|
675
|
+
const analyzer = new Analyzer(projectRoot);
|
|
676
|
+
|
|
677
|
+
utils.print.header('Deep Architecture Analysis');
|
|
678
|
+
console.log('');
|
|
679
|
+
|
|
680
|
+
const spinner = utils.createSpinner('Analyzing architecture in depth...').start();
|
|
681
|
+
|
|
682
|
+
try {
|
|
683
|
+
const result = await analyzer.analyze();
|
|
684
|
+
|
|
685
|
+
spinner.succeed('Deep architecture analysis complete');
|
|
686
|
+
console.log('');
|
|
687
|
+
|
|
688
|
+
if (args.json) {
|
|
689
|
+
console.log(JSON.stringify(result, null, 2));
|
|
690
|
+
return;
|
|
691
|
+
}
|
|
692
|
+
|
|
693
|
+
// Display results
|
|
694
|
+
if (result.structure) {
|
|
695
|
+
console.log(`${utils.COLORS.cyan}Structure:${utils.COLORS.reset}`);
|
|
696
|
+
console.log(` Layers: ${result.structure.layers?.length || 0}`);
|
|
697
|
+
console.log(` Modules: ${result.structure.modules?.length || 0}`);
|
|
698
|
+
console.log(` Entry Points: ${result.structure.entryPoints?.length || 0}`);
|
|
699
|
+
console.log('');
|
|
700
|
+
}
|
|
701
|
+
|
|
702
|
+
if (result.dataFlow) {
|
|
703
|
+
console.log(`${utils.COLORS.cyan}Data Flow:${utils.COLORS.reset}`);
|
|
704
|
+
console.log(` Sources: ${result.dataFlow.sources?.length || 0}`);
|
|
705
|
+
console.log(` Processors: ${result.dataFlow.processors?.length || 0}`);
|
|
706
|
+
console.log(` Outputs: ${result.dataFlow.outputs?.length || 0}`);
|
|
707
|
+
console.log('');
|
|
708
|
+
}
|
|
709
|
+
|
|
710
|
+
if (result.dependencies) {
|
|
711
|
+
console.log(`${utils.COLORS.cyan}Dependencies:${utils.COLORS.reset}`);
|
|
712
|
+
console.log(` External: ${result.dependencies.external?.length || 0}`);
|
|
713
|
+
console.log(` Internal: ${result.dependencies.internal?.length || 0}`);
|
|
714
|
+
if (result.dependencies.circular?.length > 0) {
|
|
715
|
+
console.log(` ${utils.COLORS.yellow}Circular: ${result.dependencies.circular.length}${utils.COLORS.reset}`);
|
|
716
|
+
}
|
|
717
|
+
console.log('');
|
|
718
|
+
}
|
|
719
|
+
|
|
720
|
+
if (result.quality) {
|
|
721
|
+
console.log(`${utils.COLORS.cyan}Quality Indicators:${utils.COLORS.reset}`);
|
|
722
|
+
console.log(` Modularity: ${result.quality.modularity || 'N/A'}`);
|
|
723
|
+
console.log(` Coupling: ${result.quality.coupling || 'N/A'}`);
|
|
724
|
+
console.log(` Cohesion: ${result.quality.cohesion || 'N/A'}`);
|
|
725
|
+
console.log('');
|
|
726
|
+
}
|
|
727
|
+
|
|
728
|
+
if (result.recommendations?.length > 0) {
|
|
729
|
+
console.log(`${utils.COLORS.cyan}Recommendations:${utils.COLORS.reset}`);
|
|
730
|
+
for (const rec of result.recommendations.slice(0, 5)) {
|
|
731
|
+
console.log(` ${utils.COLORS.yellow}→${utils.COLORS.reset} ${rec.message || rec}`);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
|
|
735
|
+
} catch (error) {
|
|
736
|
+
spinner.fail(`Analysis failed: ${error.message}`);
|
|
737
|
+
}
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
/**
|
|
741
|
+
* Run continuous security analysis
|
|
742
|
+
*/
|
|
743
|
+
async function analyzeSecurityContinuous(args) {
|
|
744
|
+
const Analyzer = getContinuousSecurityAnalyzer();
|
|
745
|
+
const analyzer = new Analyzer(projectRoot);
|
|
746
|
+
|
|
747
|
+
utils.print.header('Continuous Security Analysis');
|
|
748
|
+
console.log('');
|
|
749
|
+
|
|
750
|
+
const spinner = utils.createSpinner('Analyzing security posture...').start();
|
|
751
|
+
|
|
752
|
+
try {
|
|
753
|
+
const result = await analyzer.analyze();
|
|
754
|
+
|
|
755
|
+
spinner.succeed('Security analysis complete');
|
|
756
|
+
console.log('');
|
|
757
|
+
|
|
758
|
+
if (args.json) {
|
|
759
|
+
console.log(JSON.stringify(result, null, 2));
|
|
760
|
+
return;
|
|
761
|
+
}
|
|
762
|
+
|
|
763
|
+
// Risk score
|
|
764
|
+
const scoreColor = result.riskScore < 30 ? utils.COLORS.green :
|
|
765
|
+
result.riskScore < 60 ? utils.COLORS.yellow :
|
|
766
|
+
utils.COLORS.red;
|
|
767
|
+
console.log(`Risk Score: ${scoreColor}${result.riskScore || 0}${utils.COLORS.reset}/100`);
|
|
768
|
+
console.log('');
|
|
769
|
+
|
|
770
|
+
// Authentication
|
|
771
|
+
if (result.authentication) {
|
|
772
|
+
console.log(`${utils.COLORS.cyan}Authentication:${utils.COLORS.reset}`);
|
|
773
|
+
console.log(` Mechanisms: ${result.authentication.mechanisms?.join(', ') || 'None detected'}`);
|
|
774
|
+
console.log(` Issues: ${result.authentication.issues?.length || 0}`);
|
|
775
|
+
console.log('');
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
// Authorization
|
|
779
|
+
if (result.authorization) {
|
|
780
|
+
console.log(`${utils.COLORS.cyan}Authorization:${utils.COLORS.reset}`);
|
|
781
|
+
console.log(` Patterns: ${result.authorization.patterns?.join(', ') || 'None detected'}`);
|
|
782
|
+
console.log(` Issues: ${result.authorization.issues?.length || 0}`);
|
|
783
|
+
console.log('');
|
|
784
|
+
}
|
|
785
|
+
|
|
786
|
+
// Data Protection
|
|
787
|
+
if (result.dataProtection) {
|
|
788
|
+
console.log(`${utils.COLORS.cyan}Data Protection:${utils.COLORS.reset}`);
|
|
789
|
+
console.log(` Encryption: ${result.dataProtection.encryption ? 'Detected' : 'Not detected'}`);
|
|
790
|
+
console.log(` PII Handling: ${result.dataProtection.piiDetected ? 'Detected' : 'Not detected'}`);
|
|
791
|
+
console.log('');
|
|
792
|
+
}
|
|
793
|
+
|
|
794
|
+
// Compliance
|
|
795
|
+
if (result.compliance) {
|
|
796
|
+
console.log(`${utils.COLORS.cyan}Compliance:${utils.COLORS.reset}`);
|
|
797
|
+
for (const [standard, status] of Object.entries(result.compliance)) {
|
|
798
|
+
const icon = status.compliant ? `${utils.COLORS.green}✓${utils.COLORS.reset}` : `${utils.COLORS.yellow}○${utils.COLORS.reset}`;
|
|
799
|
+
console.log(` ${icon} ${standard}: ${status.compliant ? 'Compliant' : 'Needs review'}`);
|
|
800
|
+
}
|
|
801
|
+
console.log('');
|
|
802
|
+
}
|
|
803
|
+
|
|
804
|
+
// Recommendations
|
|
805
|
+
if (result.recommendations?.length > 0) {
|
|
806
|
+
console.log(`${utils.COLORS.cyan}Recommendations:${utils.COLORS.reset}`);
|
|
807
|
+
for (const rec of result.recommendations.slice(0, 5)) {
|
|
808
|
+
const priority = rec.priority || 'medium';
|
|
809
|
+
const icon = priority === 'high' ? `${utils.COLORS.red}!${utils.COLORS.reset}` :
|
|
810
|
+
priority === 'medium' ? `${utils.COLORS.yellow}→${utils.COLORS.reset}` :
|
|
811
|
+
`${utils.COLORS.dim}○${utils.COLORS.reset}`;
|
|
812
|
+
console.log(` ${icon} ${rec.message || rec}`);
|
|
813
|
+
}
|
|
814
|
+
}
|
|
815
|
+
|
|
816
|
+
} catch (error) {
|
|
817
|
+
spinner.fail(`Analysis failed: ${error.message}`);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
|
|
821
|
+
/**
|
|
822
|
+
* Run semantic document analysis
|
|
823
|
+
*/
|
|
824
|
+
async function analyzeSemanticDocuments(args) {
|
|
825
|
+
const Analyzer = getSemanticDocumentAnalyzer();
|
|
826
|
+
const analyzer = new Analyzer();
|
|
827
|
+
|
|
828
|
+
utils.print.header('Semantic Document Analysis');
|
|
829
|
+
console.log('');
|
|
830
|
+
|
|
831
|
+
// Collect documents to analyze
|
|
832
|
+
const fs = require('fs');
|
|
833
|
+
const documents = [];
|
|
834
|
+
|
|
835
|
+
const docFiles = [
|
|
836
|
+
path.join(projectRoot, 'CLAUDE.md'),
|
|
837
|
+
path.join(projectRoot, 'README.md'),
|
|
838
|
+
path.join(projectRoot, 'docs', 'README.md'),
|
|
839
|
+
path.join(projectRoot, 'docs', 'architecture.md'),
|
|
840
|
+
path.join(projectRoot, 'docs', 'api.md')
|
|
841
|
+
];
|
|
842
|
+
|
|
843
|
+
for (const file of docFiles) {
|
|
844
|
+
if (fs.existsSync(file)) {
|
|
845
|
+
const content = fs.readFileSync(file, 'utf-8');
|
|
846
|
+
documents.push({
|
|
847
|
+
path: file,
|
|
848
|
+
name: path.basename(file),
|
|
849
|
+
content
|
|
850
|
+
});
|
|
851
|
+
}
|
|
852
|
+
}
|
|
853
|
+
|
|
854
|
+
if (documents.length === 0) {
|
|
855
|
+
utils.print.warn('No documentation files found to analyze');
|
|
856
|
+
return;
|
|
857
|
+
}
|
|
858
|
+
|
|
859
|
+
const spinner = utils.createSpinner(`Analyzing ${documents.length} documents...`).start();
|
|
860
|
+
|
|
861
|
+
try {
|
|
862
|
+
const result = await analyzer.analyze(documents);
|
|
863
|
+
|
|
864
|
+
spinner.succeed('Semantic analysis complete');
|
|
865
|
+
console.log('');
|
|
866
|
+
|
|
867
|
+
if (args.json) {
|
|
868
|
+
console.log(JSON.stringify(result, null, 2));
|
|
869
|
+
return;
|
|
870
|
+
}
|
|
871
|
+
|
|
872
|
+
// Concepts
|
|
873
|
+
if (result.concepts) {
|
|
874
|
+
console.log(`${utils.COLORS.cyan}Concepts Extracted:${utils.COLORS.reset}`);
|
|
875
|
+
const topConcepts = Object.entries(result.concepts)
|
|
876
|
+
.sort((a, b) => b[1].frequency - a[1].frequency)
|
|
877
|
+
.slice(0, 10);
|
|
878
|
+
for (const [concept, data] of topConcepts) {
|
|
879
|
+
console.log(` ${concept}: ${data.frequency} occurrences`);
|
|
880
|
+
}
|
|
881
|
+
console.log('');
|
|
882
|
+
}
|
|
883
|
+
|
|
884
|
+
// Terminology
|
|
885
|
+
if (result.terminology) {
|
|
886
|
+
console.log(`${utils.COLORS.cyan}Terminology:${utils.COLORS.reset}`);
|
|
887
|
+
console.log(` Unique terms: ${result.terminology.uniqueTerms || 0}`);
|
|
888
|
+
console.log(` Technical density: ${result.terminology.technicalDensity || 'N/A'}`);
|
|
889
|
+
if (result.terminology.inconsistencies?.length > 0) {
|
|
890
|
+
console.log(` ${utils.COLORS.yellow}Inconsistencies: ${result.terminology.inconsistencies.length}${utils.COLORS.reset}`);
|
|
891
|
+
}
|
|
892
|
+
console.log('');
|
|
893
|
+
}
|
|
894
|
+
|
|
895
|
+
// Contradictions
|
|
896
|
+
if (result.contradictions?.length > 0) {
|
|
897
|
+
console.log(`${utils.COLORS.cyan}Potential Contradictions:${utils.COLORS.reset}`);
|
|
898
|
+
for (const contradiction of result.contradictions.slice(0, 3)) {
|
|
899
|
+
console.log(` ${utils.COLORS.yellow}!${utils.COLORS.reset} ${contradiction.description || contradiction}`);
|
|
900
|
+
}
|
|
901
|
+
console.log('');
|
|
902
|
+
}
|
|
903
|
+
|
|
904
|
+
// Specificity
|
|
905
|
+
if (result.specificity) {
|
|
906
|
+
console.log(`${utils.COLORS.cyan}Specificity:${utils.COLORS.reset}`);
|
|
907
|
+
console.log(` Overall: ${result.specificity.overall || 'N/A'}`);
|
|
908
|
+
console.log(` Vague sections: ${result.specificity.vagueSections?.length || 0}`);
|
|
909
|
+
console.log('');
|
|
910
|
+
}
|
|
911
|
+
|
|
912
|
+
// Gaps
|
|
913
|
+
if (result.gaps?.length > 0) {
|
|
914
|
+
console.log(`${utils.COLORS.cyan}Documentation Gaps:${utils.COLORS.reset}`);
|
|
915
|
+
for (const gap of result.gaps.slice(0, 5)) {
|
|
916
|
+
console.log(` ${utils.COLORS.yellow}○${utils.COLORS.reset} ${gap.description || gap}`);
|
|
917
|
+
}
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
// Summary
|
|
921
|
+
if (result.summary) {
|
|
922
|
+
console.log('');
|
|
923
|
+
console.log(`${utils.COLORS.cyan}Summary:${utils.COLORS.reset}`);
|
|
924
|
+
console.log(` ${result.summary.overview || 'Analysis complete'}`);
|
|
925
|
+
}
|
|
926
|
+
|
|
927
|
+
} catch (error) {
|
|
928
|
+
spinner.fail(`Analysis failed: ${error.message}`);
|
|
929
|
+
}
|
|
930
|
+
}
|
|
931
|
+
|
|
629
932
|
/**
|
|
630
933
|
* Main entry point
|
|
631
934
|
*/
|
|
@@ -659,6 +962,15 @@ async function run(args) {
|
|
|
659
962
|
case 'drift':
|
|
660
963
|
return analyzeDrift();
|
|
661
964
|
|
|
965
|
+
case 'deep':
|
|
966
|
+
return analyzeDeepArchitecture(parsedArgs);
|
|
967
|
+
|
|
968
|
+
case 'security':
|
|
969
|
+
return analyzeSecurityContinuous(parsedArgs);
|
|
970
|
+
|
|
971
|
+
case 'semantic':
|
|
972
|
+
return analyzeSemanticDocuments(parsedArgs);
|
|
973
|
+
|
|
662
974
|
case 'help':
|
|
663
975
|
case '--help':
|
|
664
976
|
case '-h':
|
package/cli/generate.js
CHANGED
|
@@ -7,12 +7,25 @@
|
|
|
7
7
|
*/
|
|
8
8
|
|
|
9
9
|
const path = require('path');
|
|
10
|
+
const fs = require('fs');
|
|
10
11
|
const config = require('../core/config');
|
|
11
12
|
const context = require('../core/context');
|
|
12
13
|
const utils = require('../core/utils');
|
|
13
14
|
const gitMemory = require('../intelligence/git-memory');
|
|
14
15
|
const agentsTemplate = require('../generators/templates/agents.template');
|
|
15
16
|
|
|
17
|
+
// Lazy load Phase 3 module
|
|
18
|
+
let ModelContextOptimizer = null;
|
|
19
|
+
let listSupportedModels = null;
|
|
20
|
+
function getModelContextOptimizer() {
|
|
21
|
+
if (!ModelContextOptimizer) {
|
|
22
|
+
const module = require('../intelligence/model-context-optimizer');
|
|
23
|
+
ModelContextOptimizer = module.ModelContextOptimizer;
|
|
24
|
+
listSupportedModels = module.listSupportedModels;
|
|
25
|
+
}
|
|
26
|
+
return { ModelContextOptimizer, listSupportedModels };
|
|
27
|
+
}
|
|
28
|
+
|
|
16
29
|
/**
|
|
17
30
|
* Generate CLAUDE.md content from config and project state
|
|
18
31
|
*/
|
|
@@ -186,6 +199,19 @@ ${cfg.customInstructions}
|
|
|
186
199
|
*/
|
|
187
200
|
async function run(args) {
|
|
188
201
|
const parsedArgs = utils.parseArgs(args);
|
|
202
|
+
const subcommand = parsedArgs._[0];
|
|
203
|
+
|
|
204
|
+
// Handle help
|
|
205
|
+
if (subcommand === 'help' || parsedArgs.help || parsedArgs.h) {
|
|
206
|
+
showHelp();
|
|
207
|
+
return;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
// Handle multimodel subcommand
|
|
211
|
+
if (subcommand === 'multimodel' || subcommand === 'multi') {
|
|
212
|
+
return generateMultiModel(parsedArgs);
|
|
213
|
+
}
|
|
214
|
+
|
|
189
215
|
const full = parsedArgs.full || parsedArgs.f;
|
|
190
216
|
|
|
191
217
|
console.log(`
|
|
@@ -303,4 +329,159 @@ ${utils.COLORS.dim}Tip: Run 'bootspring generate --full' to regenerate all files
|
|
|
303
329
|
`);
|
|
304
330
|
}
|
|
305
331
|
|
|
306
|
-
|
|
332
|
+
/**
|
|
333
|
+
* Generate multi-model context files
|
|
334
|
+
*/
|
|
335
|
+
async function generateMultiModel(args) {
|
|
336
|
+
const { ModelContextOptimizer, listSupportedModels } = getModelContextOptimizer();
|
|
337
|
+
|
|
338
|
+
console.log(`
|
|
339
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Multi-Model Context Generation${utils.COLORS.reset}
|
|
340
|
+
${utils.COLORS.dim}Generating optimized context for multiple AI models...${utils.COLORS.reset}
|
|
341
|
+
`);
|
|
342
|
+
|
|
343
|
+
const cfg = config.load();
|
|
344
|
+
|
|
345
|
+
if (!cfg._configPath) {
|
|
346
|
+
utils.print.error('No bootspring.config.js found');
|
|
347
|
+
utils.print.dim('Run "bootspring init" first to initialize your project');
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
|
|
351
|
+
// Check for existing CLAUDE.md
|
|
352
|
+
const claudePath = path.join(cfg._projectRoot, 'CLAUDE.md');
|
|
353
|
+
if (!fs.existsSync(claudePath)) {
|
|
354
|
+
utils.print.error('CLAUDE.md not found');
|
|
355
|
+
utils.print.dim('Run "bootspring generate" first to create the base context');
|
|
356
|
+
return;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
const sourceContent = fs.readFileSync(claudePath, 'utf-8');
|
|
360
|
+
|
|
361
|
+
// List models if requested
|
|
362
|
+
if (args.list) {
|
|
363
|
+
const models = listSupportedModels();
|
|
364
|
+
console.log(`${utils.COLORS.bold}Supported Models:${utils.COLORS.reset}\n`);
|
|
365
|
+
for (const model of models) {
|
|
366
|
+
console.log(` ${utils.COLORS.cyan}${model.family}${utils.COLORS.reset} (${model.provider})`);
|
|
367
|
+
console.log(` Variants: ${model.variants.join(', ')}`);
|
|
368
|
+
console.log(` Context file: ${model.contextFile}`);
|
|
369
|
+
console.log('');
|
|
370
|
+
}
|
|
371
|
+
return;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Determine which models to generate for
|
|
375
|
+
let targetModels = ['claude', 'openai', 'gemini'];
|
|
376
|
+
if (args.models) {
|
|
377
|
+
targetModels = args.models.split(',').map(m => m.trim().toLowerCase());
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
// Compare across models
|
|
381
|
+
if (args.compare) {
|
|
382
|
+
const optimizer = new ModelContextOptimizer({ projectRoot: cfg._projectRoot });
|
|
383
|
+
const comparison = optimizer.compareAcrossModels(sourceContent);
|
|
384
|
+
|
|
385
|
+
console.log(`${utils.COLORS.bold}Context Comparison Across Models:${utils.COLORS.reset}\n`);
|
|
386
|
+
console.log(`Source tokens: ~${optimizer.estimateTokens(sourceContent).toLocaleString()}\n`);
|
|
387
|
+
|
|
388
|
+
for (const result of comparison) {
|
|
389
|
+
const statusIcon = result.fitsWithinBudget
|
|
390
|
+
? `${utils.COLORS.green}✓${utils.COLORS.reset}`
|
|
391
|
+
: `${utils.COLORS.yellow}⚠${utils.COLORS.reset}`;
|
|
392
|
+
|
|
393
|
+
console.log(` ${statusIcon} ${result.model} (${result.variant})`);
|
|
394
|
+
console.log(` ${utils.COLORS.dim}Context window: ${result.contextWindow.toLocaleString()} tokens${utils.COLORS.reset}`);
|
|
395
|
+
console.log(` ${utils.COLORS.dim}Utilization: ${result.utilizationPercent}%${utils.COLORS.reset}`);
|
|
396
|
+
}
|
|
397
|
+
console.log('');
|
|
398
|
+
return;
|
|
399
|
+
}
|
|
400
|
+
|
|
401
|
+
// Generate context files
|
|
402
|
+
const generated = [];
|
|
403
|
+
|
|
404
|
+
for (const model of targetModels) {
|
|
405
|
+
try {
|
|
406
|
+
const optimizer = new ModelContextOptimizer({
|
|
407
|
+
projectRoot: cfg._projectRoot,
|
|
408
|
+
model
|
|
409
|
+
});
|
|
410
|
+
|
|
411
|
+
const spinner = utils.createSpinner(`Generating ${optimizer.config.contextFile}`).start();
|
|
412
|
+
|
|
413
|
+
const result = optimizer.generateContextFile(sourceContent);
|
|
414
|
+
|
|
415
|
+
// Write the file
|
|
416
|
+
fs.writeFileSync(result.filepath, result.content, 'utf-8');
|
|
417
|
+
|
|
418
|
+
const savings = result.optimization.originalTokens - result.optimization.optimizedTokens;
|
|
419
|
+
const savingsPercent = Math.round((savings / result.optimization.originalTokens) * 100);
|
|
420
|
+
|
|
421
|
+
spinner.succeed(`Generated ${result.filename}`);
|
|
422
|
+
|
|
423
|
+
if (result.optimization.sectionsDropped > 0) {
|
|
424
|
+
console.log(` ${utils.COLORS.dim}Optimized: ${result.optimization.optimizedTokens.toLocaleString()} tokens (${savingsPercent}% reduction)${utils.COLORS.reset}`);
|
|
425
|
+
console.log(` ${utils.COLORS.dim}Dropped ${result.optimization.sectionsDropped} low-priority sections${utils.COLORS.reset}`);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
generated.push({
|
|
429
|
+
model,
|
|
430
|
+
filename: result.filename,
|
|
431
|
+
tokens: result.optimization.optimizedTokens
|
|
432
|
+
});
|
|
433
|
+
|
|
434
|
+
} catch (error) {
|
|
435
|
+
utils.print.error(`Failed to generate for ${model}: ${error.message}`);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if (generated.length > 0) {
|
|
440
|
+
console.log(`
|
|
441
|
+
${utils.COLORS.bold}Summary:${utils.COLORS.reset}
|
|
442
|
+
Generated ${generated.length} context file(s):
|
|
443
|
+
${generated.map(g => ` ${utils.COLORS.green}✓${utils.COLORS.reset} ${g.filename} (~${g.tokens.toLocaleString()} tokens)`).join('\n')}
|
|
444
|
+
|
|
445
|
+
${utils.COLORS.dim}These files are optimized for each AI model's context window and formatting preferences.${utils.COLORS.reset}
|
|
446
|
+
`);
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
|
|
450
|
+
/**
|
|
451
|
+
* Show help
|
|
452
|
+
*/
|
|
453
|
+
function showHelp() {
|
|
454
|
+
console.log(`
|
|
455
|
+
${utils.COLORS.cyan}${utils.COLORS.bold}⚡ Bootspring Generate${utils.COLORS.reset}
|
|
456
|
+
${utils.COLORS.dim}Generate AI context files${utils.COLORS.reset}
|
|
457
|
+
|
|
458
|
+
${utils.COLORS.bold}Usage:${utils.COLORS.reset}
|
|
459
|
+
bootspring generate Generate CLAUDE.md
|
|
460
|
+
bootspring generate --full Generate all context files
|
|
461
|
+
bootspring generate multimodel Generate for multiple AI models
|
|
462
|
+
bootspring generate multimodel --list List supported models
|
|
463
|
+
bootspring generate multimodel --compare Compare context across models
|
|
464
|
+
|
|
465
|
+
${utils.COLORS.bold}Options:${utils.COLORS.reset}
|
|
466
|
+
--full, -f Generate all files (CLAUDE.md, AGENTS.md, .mcp.json)
|
|
467
|
+
--models <list> Comma-separated list of models (default: claude,openai,gemini)
|
|
468
|
+
--list List all supported AI models
|
|
469
|
+
--compare Compare context requirements across models
|
|
470
|
+
|
|
471
|
+
${utils.COLORS.bold}Supported Models:${utils.COLORS.reset}
|
|
472
|
+
claude Claude (Anthropic) - CLAUDE.md
|
|
473
|
+
openai GPT (OpenAI) - OPENAI.md
|
|
474
|
+
gemini Gemini (Google) - GEMINI.md
|
|
475
|
+
mistral Mistral (Mistral AI) - MISTRAL.md
|
|
476
|
+
llama Llama (Meta) - LLAMA.md
|
|
477
|
+
|
|
478
|
+
${utils.COLORS.bold}Examples:${utils.COLORS.reset}
|
|
479
|
+
bootspring generate # Generate CLAUDE.md
|
|
480
|
+
bootspring generate --full # Generate all files
|
|
481
|
+
bootspring generate multimodel # Generate for all default models
|
|
482
|
+
bootspring generate multimodel --models claude,openai
|
|
483
|
+
bootspring generate multimodel --compare
|
|
484
|
+
`);
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
module.exports = { run, generateClaudeMd, generateMultiModel };
|