specweave 0.34.4 → 0.34.6
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/fix-marketplace-errors.sh +55 -7
- package/dist/plugins/specweave-github/lib/github-feature-sync.d.ts.map +1 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js +3 -1
- package/dist/plugins/specweave-github/lib/github-feature-sync.js.map +1 -1
- package/dist/src/cli/commands/init.d.ts.map +1 -1
- package/dist/src/cli/commands/init.js +11 -2
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/living-docs.js +4 -4
- package/dist/src/cli/commands/living-docs.js.map +1 -1
- package/dist/src/cli/helpers/init/brownfield-analysis.js +15 -15
- package/dist/src/cli/helpers/init/brownfield-analysis.js.map +1 -1
- package/dist/src/cli/helpers/init/living-docs-preflight.js +7 -7
- package/dist/src/cli/helpers/init/living-docs-preflight.js.map +1 -1
- package/dist/src/cli/helpers/init/plugin-installer.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/plugin-installer.js +61 -9
- package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -1
- package/dist/src/core/background/types.d.ts +3 -0
- package/dist/src/core/background/types.d.ts.map +1 -1
- package/dist/src/core/living-docs/delivery/delivery-generator.d.ts +58 -0
- package/dist/src/core/living-docs/delivery/delivery-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/delivery/delivery-generator.js +501 -0
- package/dist/src/core/living-docs/delivery/delivery-generator.js.map +1 -0
- package/dist/src/core/living-docs/delivery/index.d.ts +8 -0
- package/dist/src/core/living-docs/delivery/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/delivery/index.js +7 -0
- package/dist/src/core/living-docs/delivery/index.js.map +1 -0
- package/dist/src/core/living-docs/diagrams/index.d.ts +8 -0
- package/dist/src/core/living-docs/diagrams/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/diagrams/index.js +7 -0
- package/dist/src/core/living-docs/diagrams/index.js.map +1 -0
- package/dist/src/core/living-docs/diagrams/mermaid-generator.d.ts +103 -0
- package/dist/src/core/living-docs/diagrams/mermaid-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/diagrams/mermaid-generator.js +515 -0
- package/dist/src/core/living-docs/diagrams/mermaid-generator.js.map +1 -0
- package/dist/src/core/living-docs/enterprise/enterprise-generator.d.ts +85 -0
- package/dist/src/core/living-docs/enterprise/enterprise-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/enterprise/enterprise-generator.js +556 -0
- package/dist/src/core/living-docs/enterprise/enterprise-generator.js.map +1 -0
- package/dist/src/core/living-docs/enterprise/history-analyzer.d.ts +91 -0
- package/dist/src/core/living-docs/enterprise/history-analyzer.d.ts.map +1 -0
- package/dist/src/core/living-docs/enterprise/history-analyzer.js +321 -0
- package/dist/src/core/living-docs/enterprise/history-analyzer.js.map +1 -0
- package/dist/src/core/living-docs/enterprise/index.d.ts +18 -0
- package/dist/src/core/living-docs/enterprise/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/enterprise/index.js +14 -0
- package/dist/src/core/living-docs/enterprise/index.js.map +1 -0
- package/dist/src/core/living-docs/enterprise/relationship-mapper.d.ts +58 -0
- package/dist/src/core/living-docs/enterprise/relationship-mapper.d.ts.map +1 -0
- package/dist/src/core/living-docs/enterprise/relationship-mapper.js +227 -0
- package/dist/src/core/living-docs/enterprise/relationship-mapper.js.map +1 -0
- package/dist/src/core/living-docs/enterprise/spec-loader.d.ts +161 -0
- package/dist/src/core/living-docs/enterprise/spec-loader.d.ts.map +1 -0
- package/dist/src/core/living-docs/enterprise/spec-loader.js +470 -0
- package/dist/src/core/living-docs/enterprise/spec-loader.js.map +1 -0
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts +31 -1
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.d.ts.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js +626 -14
- package/dist/src/core/living-docs/intelligent-analyzer/inconsistency-detector.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts +8 -0
- package/dist/src/core/living-docs/intelligent-analyzer/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/index.js +87 -4
- package/dist/src/core/living-docs/intelligent-analyzer/index.js.map +1 -1
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts +3 -1
- package/dist/src/core/living-docs/intelligent-analyzer/types.d.ts.map +1 -1
- package/dist/src/core/living-docs/operations/index.d.ts +8 -0
- package/dist/src/core/living-docs/operations/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/operations/index.js +7 -0
- package/dist/src/core/living-docs/operations/index.js.map +1 -0
- package/dist/src/core/living-docs/operations/ops-generator.d.ts +53 -0
- package/dist/src/core/living-docs/operations/ops-generator.d.ts.map +1 -0
- package/dist/src/core/living-docs/operations/ops-generator.js +462 -0
- package/dist/src/core/living-docs/operations/ops-generator.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/commands/living-docs.md +168 -39
- package/plugins/specweave-github/lib/github-feature-sync.js +1 -1
- package/plugins/specweave-github/lib/github-feature-sync.ts +3 -1
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Knowledge Base Generator
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator that generates comprehensive enterprise documentation:
|
|
5
|
+
* - Company history and timeline
|
|
6
|
+
* - Feature catalog with ownership
|
|
7
|
+
* - Team directory with expertise
|
|
8
|
+
* - Cross-references and relationships
|
|
9
|
+
* - Mermaid diagrams for visualization
|
|
10
|
+
*/
|
|
11
|
+
import { Logger } from '../../../utils/logger.js';
|
|
12
|
+
import type { RepoAnalysis, LLMProvider, ProgressCallback } from '../intelligent-analyzer/types.js';
|
|
13
|
+
import type { OrganizationSynthesisResult } from '../intelligent-analyzer/organization-synthesizer.js';
|
|
14
|
+
export interface EnterpriseGeneratorOptions {
|
|
15
|
+
projectPath: string;
|
|
16
|
+
projectName?: string;
|
|
17
|
+
logger?: Logger;
|
|
18
|
+
llmProvider?: LLMProvider;
|
|
19
|
+
repoAnalyses?: Map<string, RepoAnalysis>;
|
|
20
|
+
orgResult?: OrganizationSynthesisResult;
|
|
21
|
+
teams?: Array<{
|
|
22
|
+
name: string;
|
|
23
|
+
repos: string[];
|
|
24
|
+
members?: string[];
|
|
25
|
+
}>;
|
|
26
|
+
}
|
|
27
|
+
export interface EnterpriseGenerationResult {
|
|
28
|
+
filesCreated: string[];
|
|
29
|
+
savedFiles: string[];
|
|
30
|
+
metrics: EnterpriseMetrics;
|
|
31
|
+
}
|
|
32
|
+
export interface EnterpriseMetrics {
|
|
33
|
+
totalFeatures: number;
|
|
34
|
+
activeFeatures: number;
|
|
35
|
+
completedFeatures: number;
|
|
36
|
+
totalUserStories: number;
|
|
37
|
+
totalTeams: number;
|
|
38
|
+
totalModules: number;
|
|
39
|
+
overallCompletion: number;
|
|
40
|
+
timelineEvents: number;
|
|
41
|
+
relationships: number;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Enterprise documentation generator
|
|
45
|
+
*/
|
|
46
|
+
export declare class EnterpriseGenerator {
|
|
47
|
+
private projectPath;
|
|
48
|
+
private logger;
|
|
49
|
+
private llmProvider?;
|
|
50
|
+
private repoAnalyses?;
|
|
51
|
+
private orgResult?;
|
|
52
|
+
private enterprisePath;
|
|
53
|
+
constructor(options: EnterpriseGeneratorOptions);
|
|
54
|
+
/**
|
|
55
|
+
* Generate all enterprise documentation
|
|
56
|
+
*/
|
|
57
|
+
generate(onProgress?: ProgressCallback): Promise<EnterpriseGenerationResult>;
|
|
58
|
+
/**
|
|
59
|
+
* Generate COMPANY-HISTORY.md with timeline
|
|
60
|
+
*/
|
|
61
|
+
private generateHistory;
|
|
62
|
+
/**
|
|
63
|
+
* Generate FEATURE-CATALOG.md
|
|
64
|
+
*/
|
|
65
|
+
private generateFeatureCatalog;
|
|
66
|
+
/**
|
|
67
|
+
* Generate TEAM-DIRECTORY.md
|
|
68
|
+
*/
|
|
69
|
+
private generateTeamDirectory;
|
|
70
|
+
/**
|
|
71
|
+
* Generate ARCHITECTURE-MAP.md with C4 diagrams
|
|
72
|
+
*/
|
|
73
|
+
private generateArchitectureMap;
|
|
74
|
+
/**
|
|
75
|
+
* Generate relationship documentation files
|
|
76
|
+
*/
|
|
77
|
+
private generateRelationshipDocs;
|
|
78
|
+
/**
|
|
79
|
+
* Get project name from config or folder
|
|
80
|
+
*/
|
|
81
|
+
private getProjectName;
|
|
82
|
+
private getStatusEmoji;
|
|
83
|
+
private getEventEmoji;
|
|
84
|
+
}
|
|
85
|
+
//# sourceMappingURL=enterprise-generator.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"enterprise-generator.d.ts","sourceRoot":"","sources":["../../../../../src/core/living-docs/enterprise/enterprise-generator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAiB,MAAM,0BAA0B,CAAC;AAIjE,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,gBAAgB,EAAgB,MAAM,kCAAkC,CAAC;AAClH,OAAO,KAAK,EAAE,2BAA2B,EAAE,MAAM,qDAAqD,CAAC;AAEvG,MAAM,WAAW,0BAA0B;IACzC,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,WAAW,CAAC,EAAE,WAAW,CAAC;IAC1B,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,EAAE,YAAY,CAAC,CAAC;IACzC,SAAS,CAAC,EAAE,2BAA2B,CAAC;IACxC,KAAK,CAAC,EAAE,KAAK,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,EAAE,CAAC;QAAC,OAAO,CAAC,EAAE,MAAM,EAAE,CAAA;KAAE,CAAC,CAAC;CACtE;AAED,MAAM,WAAW,0BAA0B;IACzC,YAAY,EAAE,MAAM,EAAE,CAAC;IACvB,UAAU,EAAE,MAAM,EAAE,CAAC;IACrB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,aAAa,EAAE,MAAM,CAAC;IACtB,cAAc,EAAE,MAAM,CAAC;IACvB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,gBAAgB,EAAE,MAAM,CAAC;IACzB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,iBAAiB,EAAE,MAAM,CAAC;IAC1B,cAAc,EAAE,MAAM,CAAC;IACvB,aAAa,EAAE,MAAM,CAAC;CACvB;AAED;;GAEG;AACH,qBAAa,mBAAmB;IAC9B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,WAAW,CAAC,CAAc;IAClC,OAAO,CAAC,YAAY,CAAC,CAA4B;IACjD,OAAO,CAAC,SAAS,CAAC,CAA8B;IAChD,OAAO,CAAC,cAAc,CAAS;gBAEnB,OAAO,EAAE,0BAA0B;IAS/C;;OAEG;IACG,QAAQ,CACZ,UAAU,CAAC,EAAE,gBAAgB,GAC5B,OAAO,CAAC,0BAA0B,CAAC;IAuGtC;;OAEG;YACW,eAAe;IA+D7B;;OAEG;YACW,sBAAsB;IA0FpC;;OAEG;YACW,qBAAqB;IAyGnC;;OAEG;YACW,uBAAuB;IA4FrC;;OAEG;YACW,wBAAwB;IAyHtC;;OAEG;IACH,OAAO,CAAC,cAAc;IAWtB,OAAO,CAAC,cAAc;IAYtB,OAAO,CAAC,aAAa;CAYtB"}
|
|
@@ -0,0 +1,556 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Enterprise Knowledge Base Generator
|
|
3
|
+
*
|
|
4
|
+
* Main orchestrator that generates comprehensive enterprise documentation:
|
|
5
|
+
* - Company history and timeline
|
|
6
|
+
* - Feature catalog with ownership
|
|
7
|
+
* - Team directory with expertise
|
|
8
|
+
* - Cross-references and relationships
|
|
9
|
+
* - Mermaid diagrams for visualization
|
|
10
|
+
*/
|
|
11
|
+
import * as fs from 'fs';
|
|
12
|
+
import * as path from 'path';
|
|
13
|
+
import { consoleLogger } from '../../../utils/logger.js';
|
|
14
|
+
import { EnhancedSpecLoader } from './spec-loader.js';
|
|
15
|
+
import { HistoryAnalyzer } from './history-analyzer.js';
|
|
16
|
+
import { RelationshipMapper } from './relationship-mapper.js';
|
|
17
|
+
/**
|
|
18
|
+
* Enterprise documentation generator
|
|
19
|
+
*/
|
|
20
|
+
export class EnterpriseGenerator {
|
|
21
|
+
constructor(options) {
|
|
22
|
+
this.projectPath = options.projectPath;
|
|
23
|
+
this.logger = options.logger ?? consoleLogger;
|
|
24
|
+
this.llmProvider = options.llmProvider;
|
|
25
|
+
this.repoAnalyses = options.repoAnalyses;
|
|
26
|
+
this.orgResult = options.orgResult;
|
|
27
|
+
this.enterprisePath = path.join(this.projectPath, '.specweave/docs/internal/enterprise');
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* Generate all enterprise documentation
|
|
31
|
+
*/
|
|
32
|
+
async generate(onProgress) {
|
|
33
|
+
const progress = onProgress ?? (() => { });
|
|
34
|
+
const filesCreated = [];
|
|
35
|
+
this.logger.info('ENTERPRISE KNOWLEDGE BASE GENERATION');
|
|
36
|
+
this.logger.info('═══════════════════════════════════════════════════════════');
|
|
37
|
+
// Ensure enterprise directory exists
|
|
38
|
+
fs.mkdirSync(this.enterprisePath, { recursive: true });
|
|
39
|
+
// Phase 1: Load all specs
|
|
40
|
+
progress('enterprise', 0, 100, 'Loading specifications');
|
|
41
|
+
this.logger.info('');
|
|
42
|
+
this.logger.info('📚 Loading all specifications...');
|
|
43
|
+
const specLoader = new EnhancedSpecLoader({
|
|
44
|
+
projectPath: this.projectPath,
|
|
45
|
+
logger: this.logger,
|
|
46
|
+
includeArchived: true,
|
|
47
|
+
});
|
|
48
|
+
const specsCatalog = await specLoader.loadAllSpecs();
|
|
49
|
+
this.logger.info(` Loaded ${specsCatalog.totalFeatures} features, ${specsCatalog.totalUserStories} user stories`);
|
|
50
|
+
// Phase 2: Analyze history
|
|
51
|
+
progress('enterprise', 20, 100, 'Analyzing project history');
|
|
52
|
+
this.logger.info('');
|
|
53
|
+
this.logger.info('📅 Analyzing project history...');
|
|
54
|
+
const historyAnalyzer = new HistoryAnalyzer({
|
|
55
|
+
projectPath: this.projectPath,
|
|
56
|
+
logger: this.logger,
|
|
57
|
+
});
|
|
58
|
+
const timeline = await historyAnalyzer.analyze(specsCatalog);
|
|
59
|
+
this.logger.info(` Found ${timeline.events.length} timeline events`);
|
|
60
|
+
// Phase 3: Map relationships
|
|
61
|
+
progress('enterprise', 40, 100, 'Mapping relationships');
|
|
62
|
+
this.logger.info('');
|
|
63
|
+
this.logger.info('🔗 Mapping relationships...');
|
|
64
|
+
const relationshipMapper = new RelationshipMapper({
|
|
65
|
+
projectPath: this.projectPath,
|
|
66
|
+
logger: this.logger,
|
|
67
|
+
repoAnalyses: this.repoAnalyses,
|
|
68
|
+
});
|
|
69
|
+
const relationships = await relationshipMapper.map(specsCatalog, this.orgResult);
|
|
70
|
+
this.logger.info(` Mapped ${relationships.totalRelationships} relationships`);
|
|
71
|
+
// Phase 4: Generate documentation files
|
|
72
|
+
progress('enterprise', 60, 100, 'Generating documentation');
|
|
73
|
+
this.logger.info('');
|
|
74
|
+
this.logger.info('📝 Generating enterprise documentation...');
|
|
75
|
+
// Generate COMPANY-HISTORY.md
|
|
76
|
+
const historyFile = await this.generateHistory(timeline, specsCatalog);
|
|
77
|
+
filesCreated.push(historyFile);
|
|
78
|
+
this.logger.info(' ✓ COMPANY-HISTORY.md');
|
|
79
|
+
// Generate FEATURE-CATALOG.md
|
|
80
|
+
const catalogFile = await this.generateFeatureCatalog(specsCatalog, relationships);
|
|
81
|
+
filesCreated.push(catalogFile);
|
|
82
|
+
this.logger.info(' ✓ FEATURE-CATALOG.md');
|
|
83
|
+
// Generate TEAM-DIRECTORY.md
|
|
84
|
+
const teamFile = await this.generateTeamDirectory(specsCatalog, relationships);
|
|
85
|
+
filesCreated.push(teamFile);
|
|
86
|
+
this.logger.info(' ✓ TEAM-DIRECTORY.md');
|
|
87
|
+
// Generate ARCHITECTURE-MAP.md with Mermaid
|
|
88
|
+
const archFile = await this.generateArchitectureMap(specsCatalog, relationships);
|
|
89
|
+
filesCreated.push(archFile);
|
|
90
|
+
this.logger.info(' ✓ ARCHITECTURE-MAP.md');
|
|
91
|
+
// Generate relationships folder
|
|
92
|
+
progress('enterprise', 80, 100, 'Generating relationship docs');
|
|
93
|
+
this.logger.info('');
|
|
94
|
+
this.logger.info('🔗 Generating relationship documentation...');
|
|
95
|
+
const relFiles = await this.generateRelationshipDocs(relationships, specsCatalog);
|
|
96
|
+
filesCreated.push(...relFiles);
|
|
97
|
+
this.logger.info(` ✓ ${relFiles.length} relationship files`);
|
|
98
|
+
progress('enterprise', 100, 100, 'Complete');
|
|
99
|
+
const metrics = {
|
|
100
|
+
totalFeatures: specsCatalog.totalFeatures,
|
|
101
|
+
activeFeatures: specsCatalog.activeFeatures,
|
|
102
|
+
completedFeatures: specsCatalog.completedFeatures,
|
|
103
|
+
totalUserStories: specsCatalog.totalUserStories,
|
|
104
|
+
totalTeams: this.orgResult?.enhancedTeams.length ?? 0,
|
|
105
|
+
totalModules: this.repoAnalyses?.size ?? 0,
|
|
106
|
+
overallCompletion: specsCatalog.overallCompletion,
|
|
107
|
+
timelineEvents: timeline.events.length,
|
|
108
|
+
relationships: relationships.totalRelationships,
|
|
109
|
+
};
|
|
110
|
+
this.logger.info('');
|
|
111
|
+
this.logger.info('═══════════════════════════════════════════════════════════');
|
|
112
|
+
this.logger.info(`✅ Enterprise documentation complete: ${filesCreated.length} files`);
|
|
113
|
+
return { filesCreated, savedFiles: filesCreated, metrics };
|
|
114
|
+
}
|
|
115
|
+
/**
|
|
116
|
+
* Generate COMPANY-HISTORY.md with timeline
|
|
117
|
+
*/
|
|
118
|
+
async generateHistory(timeline, catalog) {
|
|
119
|
+
const lines = [
|
|
120
|
+
'# Project History & Timeline',
|
|
121
|
+
'',
|
|
122
|
+
`*Generated: ${new Date().toLocaleDateString()} | Project: ${timeline.projectName}*`,
|
|
123
|
+
'',
|
|
124
|
+
'## Overview',
|
|
125
|
+
'',
|
|
126
|
+
`- **Started**: ${timeline.startDate}`,
|
|
127
|
+
`- **Current Version**: ${timeline.currentVersion}`,
|
|
128
|
+
`- **Total Features**: ${catalog.totalFeatures}`,
|
|
129
|
+
`- **Completion Rate**: ${catalog.overallCompletion}%`,
|
|
130
|
+
'',
|
|
131
|
+
'## Timeline',
|
|
132
|
+
'',
|
|
133
|
+
'```mermaid',
|
|
134
|
+
'timeline',
|
|
135
|
+
` title ${timeline.projectName} Evolution`,
|
|
136
|
+
];
|
|
137
|
+
// Group events by month
|
|
138
|
+
const eventsByMonth = new Map();
|
|
139
|
+
for (const event of timeline.events.slice(-50)) { // Last 50 events
|
|
140
|
+
const month = event.date.substring(0, 7); // YYYY-MM
|
|
141
|
+
if (!eventsByMonth.has(month)) {
|
|
142
|
+
eventsByMonth.set(month, []);
|
|
143
|
+
}
|
|
144
|
+
eventsByMonth.get(month).push(event);
|
|
145
|
+
}
|
|
146
|
+
for (const [month, events] of eventsByMonth) {
|
|
147
|
+
const [year, monthNum] = month.split('-');
|
|
148
|
+
const monthName = new Date(parseInt(year), parseInt(monthNum) - 1).toLocaleString('default', { month: 'short' });
|
|
149
|
+
lines.push(` section ${monthName} ${year}`);
|
|
150
|
+
for (const event of events.slice(0, 3)) { // Max 3 per month
|
|
151
|
+
const escapedTitle = event.title.replace(/:/g, ' ').substring(0, 40);
|
|
152
|
+
lines.push(` ${escapedTitle}`);
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
lines.push('```', '');
|
|
156
|
+
// Detailed event list
|
|
157
|
+
lines.push('## Detailed Events', '');
|
|
158
|
+
lines.push('| Date | Type | Event | Related |');
|
|
159
|
+
lines.push('|------|------|-------|---------|');
|
|
160
|
+
for (const event of timeline.events.slice(-100)) { // Last 100
|
|
161
|
+
const typeEmoji = this.getEventEmoji(event.type);
|
|
162
|
+
const related = event.relatedEntities.slice(0, 2).join(', ');
|
|
163
|
+
lines.push(`| ${event.date} | ${typeEmoji} ${event.type} | ${event.title} | ${related} |`);
|
|
164
|
+
}
|
|
165
|
+
lines.push('', '---', `*Last updated: ${new Date().toISOString()}*`);
|
|
166
|
+
const filePath = path.join(this.enterprisePath, 'COMPANY-HISTORY.md');
|
|
167
|
+
fs.writeFileSync(filePath, lines.join('\n'));
|
|
168
|
+
return filePath;
|
|
169
|
+
}
|
|
170
|
+
/**
|
|
171
|
+
* Generate FEATURE-CATALOG.md
|
|
172
|
+
*/
|
|
173
|
+
async generateFeatureCatalog(catalog, relationships) {
|
|
174
|
+
const lines = [
|
|
175
|
+
'# Feature Catalog',
|
|
176
|
+
'',
|
|
177
|
+
`*Generated: ${new Date().toLocaleDateString()} | Total: ${catalog.totalFeatures} features*`,
|
|
178
|
+
'',
|
|
179
|
+
'## Summary',
|
|
180
|
+
'',
|
|
181
|
+
'| Status | Count | Completion |',
|
|
182
|
+
'|--------|-------|------------|',
|
|
183
|
+
`| 🟢 Active | ${catalog.activeFeatures} | - |`,
|
|
184
|
+
`| ✅ Completed | ${catalog.completedFeatures} | 100% |`,
|
|
185
|
+
`| 📦 Archived | ${catalog.archivedFeatures} | - |`,
|
|
186
|
+
'',
|
|
187
|
+
`**Overall Completion**: ${catalog.overallCompletion}% (${catalog.completedACs}/${catalog.totalACs} ACs)`,
|
|
188
|
+
'',
|
|
189
|
+
'## Feature Status Diagram',
|
|
190
|
+
'',
|
|
191
|
+
'```mermaid',
|
|
192
|
+
'pie showData',
|
|
193
|
+
' title Feature Status Distribution',
|
|
194
|
+
` "Active" : ${catalog.activeFeatures}`,
|
|
195
|
+
` "Completed" : ${catalog.completedFeatures}`,
|
|
196
|
+
` "Archived" : ${catalog.archivedFeatures}`,
|
|
197
|
+
'```',
|
|
198
|
+
'',
|
|
199
|
+
];
|
|
200
|
+
// Features by project
|
|
201
|
+
if (catalog.byProject.size > 1) {
|
|
202
|
+
lines.push('## By Project', '');
|
|
203
|
+
for (const [project, features] of catalog.byProject) {
|
|
204
|
+
lines.push(`### ${project}`, '');
|
|
205
|
+
lines.push('| Feature | Status | User Stories | Completion | Owner |');
|
|
206
|
+
lines.push('|---------|--------|--------------|------------|-------|');
|
|
207
|
+
for (const f of features.slice(0, 20)) {
|
|
208
|
+
const owner = relationships.featureToTeam.get(f.featureId) || '-';
|
|
209
|
+
const status = this.getStatusEmoji(f.status);
|
|
210
|
+
lines.push(`| [${f.featureId}](#${f.featureId.toLowerCase()}) | ${status} | ${f.userStories.length} | ${f.completionPercentage}% | ${owner} |`);
|
|
211
|
+
}
|
|
212
|
+
if (features.length > 20) {
|
|
213
|
+
lines.push(`| ... | | | | *${features.length - 20} more* |`);
|
|
214
|
+
}
|
|
215
|
+
lines.push('');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
// All features detail
|
|
219
|
+
lines.push('## Feature Details', '');
|
|
220
|
+
for (const feature of catalog.features.slice(0, 50)) { // Limit for file size
|
|
221
|
+
lines.push(`### ${feature.featureId}: ${feature.featureName}`, '');
|
|
222
|
+
lines.push(`**Status**: ${this.getStatusEmoji(feature.status)} ${feature.status}`);
|
|
223
|
+
lines.push(`**Completion**: ${feature.completionPercentage}%`);
|
|
224
|
+
if (feature.project) {
|
|
225
|
+
lines.push(`**Project**: ${feature.project}`);
|
|
226
|
+
}
|
|
227
|
+
if (feature.relatedIncrements.length > 0) {
|
|
228
|
+
lines.push(`**Related Increments**: ${feature.relatedIncrements.slice(0, 5).join(', ')}`);
|
|
229
|
+
}
|
|
230
|
+
lines.push('', '**User Stories**:', '');
|
|
231
|
+
for (const us of feature.userStories.slice(0, 10)) {
|
|
232
|
+
const usStatus = this.getStatusEmoji(us.status);
|
|
233
|
+
const acComplete = us.acceptanceCriteria.filter(ac => ac.completed).length;
|
|
234
|
+
lines.push(`- ${usStatus} **${us.id}**: ${us.title} (${acComplete}/${us.acceptanceCriteria.length} ACs)`);
|
|
235
|
+
}
|
|
236
|
+
if (feature.userStories.length > 10) {
|
|
237
|
+
lines.push(`- *... ${feature.userStories.length - 10} more user stories*`);
|
|
238
|
+
}
|
|
239
|
+
lines.push('');
|
|
240
|
+
}
|
|
241
|
+
if (catalog.features.length > 50) {
|
|
242
|
+
lines.push(`*Showing 50 of ${catalog.features.length} features. See individual project folders for complete list.*`);
|
|
243
|
+
}
|
|
244
|
+
lines.push('', '---', `*Last updated: ${new Date().toISOString()}*`);
|
|
245
|
+
const filePath = path.join(this.enterprisePath, 'FEATURE-CATALOG.md');
|
|
246
|
+
fs.writeFileSync(filePath, lines.join('\n'));
|
|
247
|
+
return filePath;
|
|
248
|
+
}
|
|
249
|
+
/**
|
|
250
|
+
* Generate TEAM-DIRECTORY.md
|
|
251
|
+
*/
|
|
252
|
+
async generateTeamDirectory(catalog, relationships) {
|
|
253
|
+
const teams = this.orgResult?.enhancedTeams ?? [];
|
|
254
|
+
const lines = [
|
|
255
|
+
'# Team Directory',
|
|
256
|
+
'',
|
|
257
|
+
`*Generated: ${new Date().toLocaleDateString()} | Total: ${teams.length} teams*`,
|
|
258
|
+
'',
|
|
259
|
+
'## Organization Chart',
|
|
260
|
+
'',
|
|
261
|
+
'```mermaid',
|
|
262
|
+
'graph TD',
|
|
263
|
+
];
|
|
264
|
+
// Build org chart
|
|
265
|
+
if (teams.length > 0) {
|
|
266
|
+
lines.push(' org[Organization]');
|
|
267
|
+
for (const team of teams) {
|
|
268
|
+
const teamId = team.name.replace(/\s+/g, '_').replace(/[^a-zA-Z0-9_]/g, '');
|
|
269
|
+
lines.push(` org --> ${teamId}["${team.name}"]`);
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
else {
|
|
273
|
+
lines.push(' org[No teams detected]');
|
|
274
|
+
}
|
|
275
|
+
lines.push('```', '');
|
|
276
|
+
// Team summary table
|
|
277
|
+
lines.push('## Teams Overview', '');
|
|
278
|
+
lines.push('| Team | Modules | Features | Tech Stack |');
|
|
279
|
+
lines.push('|------|---------|----------|------------|');
|
|
280
|
+
for (const team of teams) {
|
|
281
|
+
const moduleCount = team.repos.length;
|
|
282
|
+
const featureCount = relationships.teamToFeatures.get(team.name)?.length ?? 0;
|
|
283
|
+
const techStack = team.techStack.slice(0, 3).join(', ');
|
|
284
|
+
lines.push(`| [${team.name}](#${team.name.toLowerCase().replace(/\s+/g, '-')}) | ${moduleCount} | ${featureCount} | ${techStack} |`);
|
|
285
|
+
}
|
|
286
|
+
lines.push('');
|
|
287
|
+
// Team details
|
|
288
|
+
lines.push('## Team Details', '');
|
|
289
|
+
for (const team of teams) {
|
|
290
|
+
lines.push(`### ${team.name}`, '');
|
|
291
|
+
lines.push(team.description, '');
|
|
292
|
+
if (team.responsibilities.length > 0) {
|
|
293
|
+
lines.push('**Responsibilities**:', '');
|
|
294
|
+
for (const r of team.responsibilities) {
|
|
295
|
+
lines.push(`- ${r}`);
|
|
296
|
+
}
|
|
297
|
+
lines.push('');
|
|
298
|
+
}
|
|
299
|
+
if (team.domainExpertise.length > 0) {
|
|
300
|
+
lines.push('**Domain Expertise**:', '');
|
|
301
|
+
for (const e of team.domainExpertise) {
|
|
302
|
+
lines.push(`- ${e}`);
|
|
303
|
+
}
|
|
304
|
+
lines.push('');
|
|
305
|
+
}
|
|
306
|
+
if (team.techStack.length > 0) {
|
|
307
|
+
lines.push(`**Tech Stack**: ${team.techStack.join(', ')}`, '');
|
|
308
|
+
}
|
|
309
|
+
if (team.repos.length > 0) {
|
|
310
|
+
lines.push('**Owned Modules**:', '');
|
|
311
|
+
for (const repo of team.repos) {
|
|
312
|
+
lines.push(`- [${repo}](../modules/${repo}.md)`);
|
|
313
|
+
}
|
|
314
|
+
lines.push('');
|
|
315
|
+
}
|
|
316
|
+
const features = relationships.teamToFeatures.get(team.name) ?? [];
|
|
317
|
+
if (features.length > 0) {
|
|
318
|
+
lines.push('**Owned Features**:', '');
|
|
319
|
+
for (const f of features.slice(0, 10)) {
|
|
320
|
+
lines.push(`- ${f}`);
|
|
321
|
+
}
|
|
322
|
+
if (features.length > 10) {
|
|
323
|
+
lines.push(`- *... ${features.length - 10} more*`);
|
|
324
|
+
}
|
|
325
|
+
lines.push('');
|
|
326
|
+
}
|
|
327
|
+
if (team.externalUrl) {
|
|
328
|
+
lines.push(`**External Link**: [View in ${team.externalProvider}](${team.externalUrl})`, '');
|
|
329
|
+
}
|
|
330
|
+
lines.push('---', '');
|
|
331
|
+
}
|
|
332
|
+
lines.push(`*Last updated: ${new Date().toISOString()}*`);
|
|
333
|
+
const filePath = path.join(this.enterprisePath, 'TEAM-DIRECTORY.md');
|
|
334
|
+
fs.writeFileSync(filePath, lines.join('\n'));
|
|
335
|
+
return filePath;
|
|
336
|
+
}
|
|
337
|
+
/**
|
|
338
|
+
* Generate ARCHITECTURE-MAP.md with C4 diagrams
|
|
339
|
+
*/
|
|
340
|
+
async generateArchitectureMap(catalog, relationships) {
|
|
341
|
+
const lines = [
|
|
342
|
+
'# Architecture Map',
|
|
343
|
+
'',
|
|
344
|
+
`*Generated: ${new Date().toLocaleDateString()}*`,
|
|
345
|
+
'',
|
|
346
|
+
'## System Context',
|
|
347
|
+
'',
|
|
348
|
+
'```mermaid',
|
|
349
|
+
'C4Context',
|
|
350
|
+
' title System Context Diagram',
|
|
351
|
+
'',
|
|
352
|
+
];
|
|
353
|
+
// Add main system
|
|
354
|
+
const projectName = this.getProjectName();
|
|
355
|
+
lines.push(` System(main, "${projectName}", "Main application")`);
|
|
356
|
+
// Add external systems from external refs
|
|
357
|
+
const externalSystems = new Set();
|
|
358
|
+
for (const feature of catalog.features) {
|
|
359
|
+
for (const ref of feature.externalRefs) {
|
|
360
|
+
externalSystems.add(ref.provider);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
for (const ext of externalSystems) {
|
|
364
|
+
const label = ext === 'github' ? 'GitHub' : ext === 'jira' ? 'JIRA' : 'Azure DevOps';
|
|
365
|
+
lines.push(` System_Ext(${ext}, "${label}", "External tracking")`);
|
|
366
|
+
}
|
|
367
|
+
// Add relationships
|
|
368
|
+
for (const ext of externalSystems) {
|
|
369
|
+
lines.push(` Rel(main, ${ext}, "Syncs with")`);
|
|
370
|
+
}
|
|
371
|
+
lines.push('```', '');
|
|
372
|
+
// Module dependency diagram
|
|
373
|
+
lines.push('## Module Dependencies', '');
|
|
374
|
+
lines.push('```mermaid', 'graph LR');
|
|
375
|
+
if (this.repoAnalyses && this.repoAnalyses.size > 0) {
|
|
376
|
+
const modules = Array.from(this.repoAnalyses.keys()).slice(0, 20);
|
|
377
|
+
for (const mod of modules) {
|
|
378
|
+
const deps = relationships.moduleDependencies.get(mod) ?? [];
|
|
379
|
+
if (deps.length > 0) {
|
|
380
|
+
for (const dep of deps.slice(0, 5)) {
|
|
381
|
+
if (modules.includes(dep)) {
|
|
382
|
+
lines.push(` ${mod.replace(/[^a-zA-Z0-9]/g, '_')} --> ${dep.replace(/[^a-zA-Z0-9]/g, '_')}`);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
}
|
|
388
|
+
else {
|
|
389
|
+
lines.push(' no_modules[No modules analyzed]');
|
|
390
|
+
}
|
|
391
|
+
lines.push('```', '');
|
|
392
|
+
// Feature hierarchy
|
|
393
|
+
lines.push('## Feature Hierarchy', '');
|
|
394
|
+
lines.push('```mermaid', 'graph TD');
|
|
395
|
+
const activeFeatures = catalog.byStatus.get('active') ?? [];
|
|
396
|
+
for (const feature of activeFeatures.slice(0, 15)) {
|
|
397
|
+
const fId = feature.featureId.replace(/[^a-zA-Z0-9]/g, '_');
|
|
398
|
+
lines.push(` ${fId}["${feature.featureId}<br/>${feature.completionPercentage}%"]`);
|
|
399
|
+
for (const us of feature.userStories.slice(0, 3)) {
|
|
400
|
+
const usId = us.id.replace(/[^a-zA-Z0-9]/g, '_');
|
|
401
|
+
const acComplete = us.acceptanceCriteria.filter(ac => ac.completed).length;
|
|
402
|
+
const acTotal = us.acceptanceCriteria.length;
|
|
403
|
+
lines.push(` ${fId} --> ${usId}["${us.id}<br/>${acComplete}/${acTotal}"]`);
|
|
404
|
+
}
|
|
405
|
+
if (feature.userStories.length > 3) {
|
|
406
|
+
lines.push(` ${fId} --> ${fId}_more["...${feature.userStories.length - 3} more"]`);
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
lines.push('```', '');
|
|
410
|
+
lines.push('---', `*Last updated: ${new Date().toISOString()}*`);
|
|
411
|
+
const filePath = path.join(this.enterprisePath, 'ARCHITECTURE-MAP.md');
|
|
412
|
+
fs.writeFileSync(filePath, lines.join('\n'));
|
|
413
|
+
return filePath;
|
|
414
|
+
}
|
|
415
|
+
/**
|
|
416
|
+
* Generate relationship documentation files
|
|
417
|
+
*/
|
|
418
|
+
async generateRelationshipDocs(relationships, catalog) {
|
|
419
|
+
const filesCreated = [];
|
|
420
|
+
const relPath = path.join(this.projectPath, '.specweave/docs/internal/relationships');
|
|
421
|
+
fs.mkdirSync(relPath, { recursive: true });
|
|
422
|
+
// FEATURE-TO-CODE.md
|
|
423
|
+
const ftcLines = [
|
|
424
|
+
'# Feature to Code Mapping',
|
|
425
|
+
'',
|
|
426
|
+
`*Generated: ${new Date().toLocaleDateString()}*`,
|
|
427
|
+
'',
|
|
428
|
+
'## Mappings',
|
|
429
|
+
'',
|
|
430
|
+
'| Feature | Files | Coverage |',
|
|
431
|
+
'|---------|-------|----------|',
|
|
432
|
+
];
|
|
433
|
+
for (const [featureId, files] of relationships.featureToCode) {
|
|
434
|
+
const coverage = files.length > 0 ? '✅' : '❌';
|
|
435
|
+
ftcLines.push(`| ${featureId} | ${files.length} | ${coverage} |`);
|
|
436
|
+
}
|
|
437
|
+
const ftcPath = path.join(relPath, 'FEATURE-TO-CODE.md');
|
|
438
|
+
fs.writeFileSync(ftcPath, ftcLines.join('\n'));
|
|
439
|
+
filesCreated.push(ftcPath);
|
|
440
|
+
// TEAM-TO-FEATURES.md
|
|
441
|
+
const ttfLines = [
|
|
442
|
+
'# Team to Features Mapping',
|
|
443
|
+
'',
|
|
444
|
+
`*Generated: ${new Date().toLocaleDateString()}*`,
|
|
445
|
+
'',
|
|
446
|
+
];
|
|
447
|
+
for (const [team, features] of relationships.teamToFeatures) {
|
|
448
|
+
ttfLines.push(`## ${team}`, '');
|
|
449
|
+
for (const f of features) {
|
|
450
|
+
ttfLines.push(`- ${f}`);
|
|
451
|
+
}
|
|
452
|
+
ttfLines.push('');
|
|
453
|
+
}
|
|
454
|
+
const ttfPath = path.join(relPath, 'TEAM-TO-FEATURES.md');
|
|
455
|
+
fs.writeFileSync(ttfPath, ttfLines.join('\n'));
|
|
456
|
+
filesCreated.push(ttfPath);
|
|
457
|
+
// MODULE-DEPENDENCIES.md
|
|
458
|
+
const mdLines = [
|
|
459
|
+
'# Module Dependencies',
|
|
460
|
+
'',
|
|
461
|
+
`*Generated: ${new Date().toLocaleDateString()}*`,
|
|
462
|
+
'',
|
|
463
|
+
'## Dependency Matrix',
|
|
464
|
+
'',
|
|
465
|
+
];
|
|
466
|
+
for (const [mod, deps] of relationships.moduleDependencies) {
|
|
467
|
+
if (deps.length > 0) {
|
|
468
|
+
mdLines.push(`### ${mod}`, '');
|
|
469
|
+
mdLines.push('**Depends on**:', '');
|
|
470
|
+
for (const dep of deps) {
|
|
471
|
+
mdLines.push(`- ${dep}`);
|
|
472
|
+
}
|
|
473
|
+
mdLines.push('');
|
|
474
|
+
}
|
|
475
|
+
}
|
|
476
|
+
const mdPath = path.join(relPath, 'MODULE-DEPENDENCIES.md');
|
|
477
|
+
fs.writeFileSync(mdPath, mdLines.join('\n'));
|
|
478
|
+
filesCreated.push(mdPath);
|
|
479
|
+
// EXTERNAL-REFS.md
|
|
480
|
+
const erLines = [
|
|
481
|
+
'# External References',
|
|
482
|
+
'',
|
|
483
|
+
`*Generated: ${new Date().toLocaleDateString()}*`,
|
|
484
|
+
'',
|
|
485
|
+
'## GitHub Issues',
|
|
486
|
+
'',
|
|
487
|
+
'| Feature | Issue | Status |',
|
|
488
|
+
'|---------|-------|--------|',
|
|
489
|
+
];
|
|
490
|
+
for (const feature of catalog.features) {
|
|
491
|
+
for (const ref of feature.externalRefs) {
|
|
492
|
+
if (ref.provider === 'github') {
|
|
493
|
+
erLines.push(`| ${feature.featureId} | #${ref.id} | ${ref.status || '-'} |`);
|
|
494
|
+
}
|
|
495
|
+
}
|
|
496
|
+
}
|
|
497
|
+
erLines.push('', '## JIRA Issues', '', '| Feature | Key | Status |', '|---------|-----|--------|');
|
|
498
|
+
for (const feature of catalog.features) {
|
|
499
|
+
for (const ref of feature.externalRefs) {
|
|
500
|
+
if (ref.provider === 'jira') {
|
|
501
|
+
erLines.push(`| ${feature.featureId} | ${ref.id} | ${ref.status || '-'} |`);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
erLines.push('', '## Azure DevOps', '', '| Feature | Work Item | Status |', '|---------|-----------|--------|');
|
|
506
|
+
for (const feature of catalog.features) {
|
|
507
|
+
for (const ref of feature.externalRefs) {
|
|
508
|
+
if (ref.provider === 'ado') {
|
|
509
|
+
erLines.push(`| ${feature.featureId} | ${ref.id} | ${ref.status || '-'} |`);
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
}
|
|
513
|
+
const erPath = path.join(relPath, 'EXTERNAL-REFS.md');
|
|
514
|
+
fs.writeFileSync(erPath, erLines.join('\n'));
|
|
515
|
+
filesCreated.push(erPath);
|
|
516
|
+
return filesCreated;
|
|
517
|
+
}
|
|
518
|
+
/**
|
|
519
|
+
* Get project name from config or folder
|
|
520
|
+
*/
|
|
521
|
+
getProjectName() {
|
|
522
|
+
const configPath = path.join(this.projectPath, '.specweave/config.json');
|
|
523
|
+
if (fs.existsSync(configPath)) {
|
|
524
|
+
try {
|
|
525
|
+
const config = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
|
|
526
|
+
return config.project?.name || config.name || path.basename(this.projectPath);
|
|
527
|
+
}
|
|
528
|
+
catch { /* ignore */ }
|
|
529
|
+
}
|
|
530
|
+
return path.basename(this.projectPath);
|
|
531
|
+
}
|
|
532
|
+
getStatusEmoji(status) {
|
|
533
|
+
switch (status) {
|
|
534
|
+
case 'active': return '🟢';
|
|
535
|
+
case 'completed': return '✅';
|
|
536
|
+
case 'archived': return '📦';
|
|
537
|
+
case 'in_progress': return '🔄';
|
|
538
|
+
case 'draft': return '📝';
|
|
539
|
+
case 'ready': return '🎯';
|
|
540
|
+
default: return '⚪';
|
|
541
|
+
}
|
|
542
|
+
}
|
|
543
|
+
getEventEmoji(type) {
|
|
544
|
+
switch (type) {
|
|
545
|
+
case 'feature_started': return '🚀';
|
|
546
|
+
case 'feature_completed': return '✅';
|
|
547
|
+
case 'release': return '📦';
|
|
548
|
+
case 'team_change': return '👥';
|
|
549
|
+
case 'incident': return '🚨';
|
|
550
|
+
case 'increment_started': return '📋';
|
|
551
|
+
case 'increment_completed': return '🎉';
|
|
552
|
+
default: return '📌';
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
}
|
|
556
|
+
//# sourceMappingURL=enterprise-generator.js.map
|