specweave 1.0.31 → 1.0.33
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/.claude-plugin/marketplace.json +1 -1
- package/CLAUDE.md +205 -148
- package/README.md +0 -2
- package/bin/specweave.js +11 -0
- package/dist/src/cli/commands/init.js +1 -1
- package/dist/src/cli/commands/init.js.map +1 -1
- package/dist/src/cli/commands/update-instructions.d.ts +16 -0
- package/dist/src/cli/commands/update-instructions.d.ts.map +1 -0
- package/dist/src/cli/commands/update-instructions.js +134 -0
- package/dist/src/cli/commands/update-instructions.js.map +1 -0
- package/dist/src/cli/helpers/init/directory-structure.d.ts +28 -1
- package/dist/src/cli/helpers/init/directory-structure.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/directory-structure.js +163 -33
- package/dist/src/cli/helpers/init/directory-structure.js.map +1 -1
- package/dist/src/cli/helpers/init/index.d.ts +2 -1
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/index.js +3 -1
- package/dist/src/cli/helpers/init/index.js.map +1 -1
- package/dist/src/cli/helpers/init/instruction-file-merger.d.ts +23 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.js +243 -0
- package/dist/src/cli/helpers/init/instruction-file-merger.js.map +1 -0
- package/dist/src/cli/helpers/init/plugin-installer.js +49 -0
- package/dist/src/cli/helpers/init/plugin-installer.js.map +1 -1
- package/dist/src/config/types.d.ts +2 -2
- package/dist/src/core/living-docs/external-sync-orchestrator.d.ts +26 -0
- package/dist/src/core/living-docs/external-sync-orchestrator.d.ts.map +1 -1
- package/dist/src/core/living-docs/external-sync-orchestrator.js +61 -0
- package/dist/src/core/living-docs/external-sync-orchestrator.js.map +1 -1
- package/dist/src/core/living-docs/scaffolding/index.d.ts +12 -0
- package/dist/src/core/living-docs/scaffolding/index.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/index.js +15 -0
- package/dist/src/core/living-docs/scaffolding/index.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/merger.d.ts +183 -0
- package/dist/src/core/living-docs/scaffolding/merger.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/merger.js +523 -0
- package/dist/src/core/living-docs/scaffolding/merger.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.d.ts +102 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.js +346 -0
- package/dist/src/core/living-docs/scaffolding/scaffold.js.map +1 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.d.ts +108 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.d.ts.map +1 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.js +204 -0
- package/dist/src/core/living-docs/scaffolding/template-engine.js.map +1 -0
- package/dist/src/core/living-docs/sync-helpers/generators.d.ts +38 -2
- package/dist/src/core/living-docs/sync-helpers/generators.d.ts.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/generators.js +65 -10
- package/dist/src/core/living-docs/sync-helpers/generators.js.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.d.ts +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.d.ts.map +1 -1
- package/dist/src/core/living-docs/sync-helpers/index.js.map +1 -1
- package/dist/src/core/tools/index.d.ts +11 -0
- package/dist/src/core/tools/index.d.ts.map +1 -0
- package/dist/src/core/tools/index.js +10 -0
- package/dist/src/core/tools/index.js.map +1 -0
- package/dist/src/core/tools/tool-event-bus.d.ts +33 -0
- package/dist/src/core/tools/tool-event-bus.d.ts.map +1 -0
- package/dist/src/core/tools/tool-event-bus.js +84 -0
- package/dist/src/core/tools/tool-event-bus.js.map +1 -0
- package/dist/src/core/tools/tool-index-builder.d.ts +27 -0
- package/dist/src/core/tools/tool-index-builder.d.ts.map +1 -0
- package/dist/src/core/tools/tool-index-builder.js +289 -0
- package/dist/src/core/tools/tool-index-builder.js.map +1 -0
- package/dist/src/core/tools/tool-registry.d.ts +51 -0
- package/dist/src/core/tools/tool-registry.d.ts.map +1 -0
- package/dist/src/core/tools/tool-registry.js +224 -0
- package/dist/src/core/tools/tool-registry.js.map +1 -0
- package/dist/src/core/tools/tool-search-engine.d.ts +22 -0
- package/dist/src/core/tools/tool-search-engine.d.ts.map +1 -0
- package/dist/src/core/tools/tool-search-engine.js +174 -0
- package/dist/src/core/tools/tool-search-engine.js.map +1 -0
- package/dist/src/core/tools/types/tool-registry-types.d.ts +112 -0
- package/dist/src/core/tools/types/tool-registry-types.d.ts.map +1 -0
- package/dist/src/core/tools/types/tool-registry-types.js +7 -0
- package/dist/src/core/tools/types/tool-registry-types.js.map +1 -0
- package/dist/src/init/compliance/types.d.ts +1 -1
- package/package.json +1 -1
- package/plugins/specweave/hooks/hooks.json +3 -13
- package/plugins/specweave/hooks/lib/common-setup.sh +47 -321
- package/plugins/specweave/hooks/lib/migrate-increment-work.sh +5 -5
- package/plugins/specweave/hooks/lib/sync-spec-content.sh +5 -5
- package/plugins/specweave/hooks/universal/dispatcher.mjs +4 -5
- package/plugins/specweave/hooks/universal/fail-fast-wrapper.sh +43 -296
- package/plugins/specweave/hooks/universal/hook-wrapper.sh +3 -1
- package/plugins/specweave/hooks/user-prompt-submit.sh +1 -1
- package/plugins/specweave/hooks/v2/dispatchers/post-tool-use.sh +2 -2
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +1 -10
- package/plugins/specweave/hooks/v2/guards/completion-guard.sh +12 -29
- package/plugins/specweave/hooks/v2/guards/increment-duplicate-guard.sh +27 -29
- package/plugins/specweave/hooks/v2/guards/metadata-json-guard.sh +10 -4
- package/plugins/specweave/hooks/v2/guards/spec-validation-guard.sh +139 -0
- package/plugins/specweave/hooks/v2/guards/task-ac-sync-guard.sh +4 -2
- package/plugins/specweave/hooks/v2/session-end.sh +3 -1
- package/plugins/specweave/hooks/v2/session-start.sh +3 -1
- package/plugins/specweave/skills/increment-planner/templates/plan.md +14 -0
- package/plugins/specweave/skills/update-instructions/SKILL.md +80 -0
- package/plugins/specweave-ado/hooks/post-living-docs-update.sh +1 -1
- package/plugins/specweave-mobile/README.md +55 -35
- package/plugins/specweave-mobile/agents/mobile-architect/AGENT.md +805 -329
- package/plugins/specweave-mobile/skills/expo-workflow/SKILL.md +226 -9
- package/plugins/specweave-mobile/skills/native-modules/SKILL.md +221 -20
- package/plugins/specweave-mobile/skills/performance-optimization/SKILL.md +186 -14
- package/plugins/specweave-mobile/skills/react-native-setup/SKILL.md +151 -54
- package/plugins/specweave-release/commands/npm.md +61 -17
- package/plugins/specweave-release/hooks/post-task-completion.sh +2 -3
- package/src/templates/AGENTS.md.template +34 -0
- package/src/templates/CLAUDE.md.template +121 -155
- package/plugins/specweave/hooks/config-env-separator.sh +0 -99
- package/plugins/specweave/hooks/github-metadata-guard.sh +0 -73
- package/plugins/specweave/hooks/lib/circuit-breaker.sh +0 -381
- package/plugins/specweave/hooks/lib/crash-prevention.sh +0 -336
- package/plugins/specweave/hooks/lib/logging.sh +0 -231
- package/plugins/specweave/hooks/lib/metrics.sh +0 -347
- package/plugins/specweave/hooks/lib/semaphore.sh +0 -216
- package/plugins/specweave/hooks/project-folder-guard.sh +0 -274
- package/plugins/specweave/hooks/spec-project-validator.sh +0 -210
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.sh +0 -212
- package/plugins/specweave/hooks/v2/guards/bash-file-guard.test.sh +0 -163
- package/plugins/specweave/hooks/v2/guards/features-folder-guard.sh +0 -51
- package/plugins/specweave/hooks/v2/guards/increment-root-guard.sh +0 -63
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.sh +0 -335
- package/plugins/specweave/hooks/v2/guards/per-us-project-validator.test.sh +0 -406
|
@@ -0,0 +1,523 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Living Docs Merger - Intelligently merges existing documentation
|
|
3
|
+
*
|
|
4
|
+
* This module scans for existing documentation in a user project and
|
|
5
|
+
* offers to merge/import it into the living docs structure.
|
|
6
|
+
*
|
|
7
|
+
* Smart features:
|
|
8
|
+
* - Detects documentation type (README, API docs, guides, etc.)
|
|
9
|
+
* - Suggests appropriate target folders
|
|
10
|
+
* - Detects similar/duplicate content
|
|
11
|
+
* - Preserves original files (copies, doesn't move)
|
|
12
|
+
*
|
|
13
|
+
* @module core/living-docs/scaffolding/merger
|
|
14
|
+
*/
|
|
15
|
+
import * as fs from 'fs';
|
|
16
|
+
import * as path from 'path';
|
|
17
|
+
import { consoleLogger } from '../../../utils/logger.js';
|
|
18
|
+
/**
|
|
19
|
+
* Common documentation folder patterns
|
|
20
|
+
*/
|
|
21
|
+
const DOC_FOLDER_PATTERNS = [
|
|
22
|
+
'docs',
|
|
23
|
+
'doc',
|
|
24
|
+
'documentation',
|
|
25
|
+
'wiki',
|
|
26
|
+
'guides',
|
|
27
|
+
'tutorials',
|
|
28
|
+
'api-docs',
|
|
29
|
+
'notion-export',
|
|
30
|
+
'confluence-export',
|
|
31
|
+
];
|
|
32
|
+
/**
|
|
33
|
+
* File patterns for document types
|
|
34
|
+
*/
|
|
35
|
+
const DOC_TYPE_PATTERNS = {
|
|
36
|
+
readme: [/^readme/i, /^index\.md$/i],
|
|
37
|
+
api: [/api/i, /endpoint/i, /swagger/i, /openapi/i],
|
|
38
|
+
guide: [/guide/i, /tutorial/i, /how-to/i, /getting-started/i],
|
|
39
|
+
architecture: [/architecture/i, /design/i, /system/i, /diagram/i],
|
|
40
|
+
adr: [/^adr-/i, /^\d{4}-/i, /decision/i],
|
|
41
|
+
runbook: [/runbook/i, /playbook/i, /incident/i, /sop/i],
|
|
42
|
+
contributing: [/contributing/i, /contribution/i],
|
|
43
|
+
changelog: [/changelog/i, /changes/i, /history/i, /release/i],
|
|
44
|
+
spec: [/spec/i, /requirement/i, /prd/i, /rfc/i],
|
|
45
|
+
other: [/.*/],
|
|
46
|
+
};
|
|
47
|
+
/**
|
|
48
|
+
* Target folder mapping
|
|
49
|
+
*/
|
|
50
|
+
const TYPE_TO_TARGET = {
|
|
51
|
+
readme: 'public/overview',
|
|
52
|
+
api: 'public/api',
|
|
53
|
+
guide: 'public/guides',
|
|
54
|
+
architecture: 'internal/architecture',
|
|
55
|
+
adr: 'internal/architecture/adr',
|
|
56
|
+
runbook: 'internal/operations',
|
|
57
|
+
contributing: 'public/overview',
|
|
58
|
+
changelog: 'internal/delivery',
|
|
59
|
+
spec: 'internal/specs',
|
|
60
|
+
other: 'internal/modules',
|
|
61
|
+
};
|
|
62
|
+
/**
|
|
63
|
+
* Living Docs Merger class
|
|
64
|
+
*/
|
|
65
|
+
export class LivingDocsMerger {
|
|
66
|
+
constructor(options) {
|
|
67
|
+
this.projectPath = options.projectPath;
|
|
68
|
+
this.logger = options.logger ?? consoleLogger;
|
|
69
|
+
this.recursive = options.recursive ?? true;
|
|
70
|
+
this.maxDepth = options.maxDepth ?? 5;
|
|
71
|
+
this.minConfidence = options.minConfidence ?? 0.3;
|
|
72
|
+
this.additionalFolders = options.additionalFolders ?? [];
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* Scan for existing documentation
|
|
76
|
+
*/
|
|
77
|
+
async scan() {
|
|
78
|
+
const detected = [];
|
|
79
|
+
this.logger.info('Scanning for existing documentation...');
|
|
80
|
+
// Scan root-level markdown files
|
|
81
|
+
await this.scanDirectory(this.projectPath, detected, 0, false);
|
|
82
|
+
// Scan common doc folders
|
|
83
|
+
for (const folder of DOC_FOLDER_PATTERNS) {
|
|
84
|
+
const folderPath = path.join(this.projectPath, folder);
|
|
85
|
+
if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
|
|
86
|
+
this.logger.info(' Found: ' + folder + '/');
|
|
87
|
+
await this.scanDirectory(folderPath, detected, 0, true);
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Scan additional folders
|
|
91
|
+
for (const folder of this.additionalFolders) {
|
|
92
|
+
const folderPath = path.isAbsolute(folder)
|
|
93
|
+
? folder
|
|
94
|
+
: path.join(this.projectPath, folder);
|
|
95
|
+
if (fs.existsSync(folderPath) && fs.statSync(folderPath).isDirectory()) {
|
|
96
|
+
this.logger.info(' Scanning additional: ' + folder);
|
|
97
|
+
await this.scanDirectory(folderPath, detected, 0, true);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
// Filter by confidence
|
|
101
|
+
const filtered = detected.filter(d => d.confidence >= this.minConfidence);
|
|
102
|
+
this.logger.info('Found ' + filtered.length + ' documentation files');
|
|
103
|
+
return filtered;
|
|
104
|
+
}
|
|
105
|
+
/**
|
|
106
|
+
* Scan a directory for markdown files
|
|
107
|
+
*/
|
|
108
|
+
async scanDirectory(dirPath, results, depth, recursive) {
|
|
109
|
+
if (depth > this.maxDepth)
|
|
110
|
+
return;
|
|
111
|
+
// Skip certain directories
|
|
112
|
+
const dirName = path.basename(dirPath);
|
|
113
|
+
if (this.shouldSkipDir(dirName))
|
|
114
|
+
return;
|
|
115
|
+
try {
|
|
116
|
+
const entries = fs.readdirSync(dirPath, { withFileTypes: true });
|
|
117
|
+
for (const entry of entries) {
|
|
118
|
+
const fullPath = path.join(dirPath, entry.name);
|
|
119
|
+
if (entry.isDirectory() && recursive && this.recursive) {
|
|
120
|
+
await this.scanDirectory(fullPath, results, depth + 1, recursive);
|
|
121
|
+
}
|
|
122
|
+
else if (entry.isFile() && this.isDocFile(entry.name)) {
|
|
123
|
+
const doc = this.analyzeFile(fullPath);
|
|
124
|
+
if (doc) {
|
|
125
|
+
results.push(doc);
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
catch (error) {
|
|
131
|
+
this.logger.warn('Could not scan ' + dirPath + ': ' + error);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Check if directory should be skipped
|
|
136
|
+
*/
|
|
137
|
+
shouldSkipDir(name) {
|
|
138
|
+
const skipDirs = [
|
|
139
|
+
'node_modules',
|
|
140
|
+
'.git',
|
|
141
|
+
'.specweave',
|
|
142
|
+
'dist',
|
|
143
|
+
'build',
|
|
144
|
+
'coverage',
|
|
145
|
+
'.next',
|
|
146
|
+
'.nuxt',
|
|
147
|
+
'vendor',
|
|
148
|
+
'__pycache__',
|
|
149
|
+
];
|
|
150
|
+
return skipDirs.includes(name) || name.startsWith('.');
|
|
151
|
+
}
|
|
152
|
+
/**
|
|
153
|
+
* Check if file is a documentation file
|
|
154
|
+
*/
|
|
155
|
+
isDocFile(fileName) {
|
|
156
|
+
return /\.(md|mdx|rst|txt)$/i.test(fileName);
|
|
157
|
+
}
|
|
158
|
+
/**
|
|
159
|
+
* Analyze a documentation file
|
|
160
|
+
*/
|
|
161
|
+
analyzeFile(filePath) {
|
|
162
|
+
try {
|
|
163
|
+
const stats = fs.statSync(filePath);
|
|
164
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
165
|
+
const fileName = path.basename(filePath);
|
|
166
|
+
const relativePath = path.relative(this.projectPath, filePath);
|
|
167
|
+
// Detect type
|
|
168
|
+
const { type, confidence } = this.detectType(fileName, content);
|
|
169
|
+
// Extract themes
|
|
170
|
+
const themes = this.extractThemes(content);
|
|
171
|
+
// Get preview
|
|
172
|
+
const preview = content.slice(0, 500).trim();
|
|
173
|
+
return {
|
|
174
|
+
sourcePath: relativePath,
|
|
175
|
+
absolutePath: filePath,
|
|
176
|
+
fileName,
|
|
177
|
+
type,
|
|
178
|
+
confidence,
|
|
179
|
+
suggestedTarget: TYPE_TO_TARGET[type],
|
|
180
|
+
size: stats.size,
|
|
181
|
+
preview,
|
|
182
|
+
themes,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
catch (error) {
|
|
186
|
+
this.logger.warn('Could not analyze ' + filePath + ': ' + error);
|
|
187
|
+
return null;
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Detect document type from filename and content
|
|
192
|
+
*/
|
|
193
|
+
detectType(fileName, content) {
|
|
194
|
+
let bestType = 'other';
|
|
195
|
+
let bestConfidence = 0;
|
|
196
|
+
const lowerFileName = fileName.toLowerCase();
|
|
197
|
+
const lowerContent = content.toLowerCase();
|
|
198
|
+
for (const [type, patterns] of Object.entries(DOC_TYPE_PATTERNS)) {
|
|
199
|
+
if (type === 'other')
|
|
200
|
+
continue;
|
|
201
|
+
for (const pattern of patterns) {
|
|
202
|
+
// Check filename
|
|
203
|
+
if (pattern.test(lowerFileName)) {
|
|
204
|
+
const confidence = 0.8;
|
|
205
|
+
if (confidence > bestConfidence) {
|
|
206
|
+
bestType = type;
|
|
207
|
+
bestConfidence = confidence;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Check content (lower confidence)
|
|
211
|
+
if (pattern.test(lowerContent)) {
|
|
212
|
+
const confidence = 0.5;
|
|
213
|
+
if (confidence > bestConfidence) {
|
|
214
|
+
bestType = type;
|
|
215
|
+
bestConfidence = confidence;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
// Default confidence for 'other'
|
|
221
|
+
if (bestType === 'other') {
|
|
222
|
+
bestConfidence = 0.3;
|
|
223
|
+
}
|
|
224
|
+
return { type: bestType, confidence: bestConfidence };
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Extract themes/keywords from content
|
|
228
|
+
*/
|
|
229
|
+
extractThemes(content) {
|
|
230
|
+
const themes = new Set();
|
|
231
|
+
const lowerContent = content.toLowerCase();
|
|
232
|
+
const themeKeywords = {
|
|
233
|
+
auth: ['authentication', 'authorization', 'login', 'oauth', 'jwt'],
|
|
234
|
+
api: ['api', 'endpoint', 'rest', 'graphql', 'grpc'],
|
|
235
|
+
database: ['database', 'sql', 'postgres', 'mysql', 'mongodb', 'redis'],
|
|
236
|
+
testing: ['test', 'spec', 'jest', 'vitest', 'playwright', 'cypress'],
|
|
237
|
+
deployment: ['deploy', 'docker', 'kubernetes', 'k8s', 'ci/cd', 'pipeline'],
|
|
238
|
+
security: ['security', 'encryption', 'secret', 'password', 'https'],
|
|
239
|
+
performance: ['performance', 'cache', 'optimization', 'lazy', 'bundle'],
|
|
240
|
+
};
|
|
241
|
+
for (const [theme, keywords] of Object.entries(themeKeywords)) {
|
|
242
|
+
for (const keyword of keywords) {
|
|
243
|
+
if (lowerContent.includes(keyword)) {
|
|
244
|
+
themes.add(theme);
|
|
245
|
+
break;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
}
|
|
249
|
+
return Array.from(themes);
|
|
250
|
+
}
|
|
251
|
+
/**
|
|
252
|
+
* Check similarity between two files using TF-IDF weighted cosine similarity
|
|
253
|
+
*
|
|
254
|
+
* TF-IDF (Term Frequency-Inverse Document Frequency) weights terms by:
|
|
255
|
+
* - How often they appear in a document (TF - more = more important)
|
|
256
|
+
* - How rare they are across all documents (IDF - rarer = more distinctive)
|
|
257
|
+
*/
|
|
258
|
+
checkSimilarity(doc1, doc2) {
|
|
259
|
+
// Theme similarity (Jaccard index)
|
|
260
|
+
const sharedThemes = doc1.themes.filter(t => doc2.themes.includes(t));
|
|
261
|
+
const unionThemes = new Set([...doc1.themes, ...doc2.themes]);
|
|
262
|
+
const themeScore = unionThemes.size > 0 ? sharedThemes.length / unionThemes.size : 0;
|
|
263
|
+
// Size similarity (logarithmic scale for better large file handling)
|
|
264
|
+
const logSize1 = Math.log(doc1.size + 1);
|
|
265
|
+
const logSize2 = Math.log(doc2.size + 1);
|
|
266
|
+
const sizeScore = 1 - Math.abs(logSize1 - logSize2) / Math.max(logSize1, logSize2, 1);
|
|
267
|
+
// TF-IDF weighted content similarity
|
|
268
|
+
const contentScore = this.computeTfIdfSimilarity(doc1.preview, doc2.preview);
|
|
269
|
+
// Filename similarity (Levenshtein-based)
|
|
270
|
+
const filenameScore = this.computeFilenameSimilarity(doc1.fileName, doc2.fileName);
|
|
271
|
+
// Weighted combination (TF-IDF content is most important)
|
|
272
|
+
const score = (contentScore * 0.45) +
|
|
273
|
+
(themeScore * 0.25) +
|
|
274
|
+
(filenameScore * 0.15) +
|
|
275
|
+
(sizeScore * 0.15);
|
|
276
|
+
// Determine reason based on highest contributing factor
|
|
277
|
+
let reason;
|
|
278
|
+
if (score > 0.6) {
|
|
279
|
+
const reasons = [];
|
|
280
|
+
if (contentScore > 0.5)
|
|
281
|
+
reasons.push('similar content');
|
|
282
|
+
if (themeScore > 0.5)
|
|
283
|
+
reasons.push('shared themes');
|
|
284
|
+
if (filenameScore > 0.6)
|
|
285
|
+
reasons.push('similar filename');
|
|
286
|
+
reason = reasons.length > 0 ? reasons.join(', ') : 'overall similarity';
|
|
287
|
+
}
|
|
288
|
+
return {
|
|
289
|
+
isSimilar: score > 0.6,
|
|
290
|
+
score,
|
|
291
|
+
reason,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Compute TF-IDF weighted cosine similarity between two texts
|
|
296
|
+
*
|
|
297
|
+
* This is a simplified but effective TF-IDF implementation:
|
|
298
|
+
* - TF: term frequency in document (normalized)
|
|
299
|
+
* - IDF: inverse document frequency (approximated using both documents as corpus)
|
|
300
|
+
*/
|
|
301
|
+
computeTfIdfSimilarity(text1, text2) {
|
|
302
|
+
const tokens1 = this.tokenize(text1);
|
|
303
|
+
const tokens2 = this.tokenize(text2);
|
|
304
|
+
if (tokens1.length === 0 || tokens2.length === 0)
|
|
305
|
+
return 0;
|
|
306
|
+
// Build term frequency maps
|
|
307
|
+
const tf1 = this.computeTermFrequency(tokens1);
|
|
308
|
+
const tf2 = this.computeTermFrequency(tokens2);
|
|
309
|
+
// Build IDF using both documents as mini-corpus
|
|
310
|
+
const allTerms = new Set([...tf1.keys(), ...tf2.keys()]);
|
|
311
|
+
const idf = new Map();
|
|
312
|
+
const numDocs = 2; // We have 2 documents
|
|
313
|
+
for (const term of allTerms) {
|
|
314
|
+
const docsWithTerm = (tf1.has(term) ? 1 : 0) + (tf2.has(term) ? 1 : 0);
|
|
315
|
+
// IDF = log(N / df) where N = total docs, df = docs containing term
|
|
316
|
+
idf.set(term, Math.log(numDocs / docsWithTerm) + 1); // +1 to avoid log(1)=0
|
|
317
|
+
}
|
|
318
|
+
// Compute TF-IDF vectors
|
|
319
|
+
const tfidf1 = new Map();
|
|
320
|
+
const tfidf2 = new Map();
|
|
321
|
+
for (const [term, freq] of tf1) {
|
|
322
|
+
tfidf1.set(term, freq * (idf.get(term) || 1));
|
|
323
|
+
}
|
|
324
|
+
for (const [term, freq] of tf2) {
|
|
325
|
+
tfidf2.set(term, freq * (idf.get(term) || 1));
|
|
326
|
+
}
|
|
327
|
+
// Compute cosine similarity
|
|
328
|
+
return this.cosineSimilarity(tfidf1, tfidf2);
|
|
329
|
+
}
|
|
330
|
+
/**
|
|
331
|
+
* Tokenize text into meaningful terms
|
|
332
|
+
* Filters out common stop words and short tokens
|
|
333
|
+
*/
|
|
334
|
+
tokenize(text) {
|
|
335
|
+
const stopWords = new Set([
|
|
336
|
+
'the', 'a', 'an', 'and', 'or', 'but', 'in', 'on', 'at', 'to', 'for',
|
|
337
|
+
'of', 'with', 'by', 'from', 'as', 'is', 'was', 'are', 'were', 'been',
|
|
338
|
+
'be', 'have', 'has', 'had', 'do', 'does', 'did', 'will', 'would',
|
|
339
|
+
'could', 'should', 'may', 'might', 'must', 'this', 'that', 'these',
|
|
340
|
+
'those', 'it', 'its', 'you', 'your', 'we', 'our', 'they', 'their',
|
|
341
|
+
'i', 'me', 'my', 'he', 'she', 'him', 'her', 'his', 'hers',
|
|
342
|
+
]);
|
|
343
|
+
return text
|
|
344
|
+
.toLowerCase()
|
|
345
|
+
.replace(/[^a-z0-9\s]/g, ' ') // Remove punctuation
|
|
346
|
+
.split(/\s+/) // Split on whitespace
|
|
347
|
+
.filter(token => token.length > 2 && // Min 3 chars
|
|
348
|
+
!stopWords.has(token) && // Not a stop word
|
|
349
|
+
!/^\d+$/.test(token) // Not pure numbers
|
|
350
|
+
);
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* Compute normalized term frequency
|
|
354
|
+
*/
|
|
355
|
+
computeTermFrequency(tokens) {
|
|
356
|
+
const tf = new Map();
|
|
357
|
+
for (const token of tokens) {
|
|
358
|
+
tf.set(token, (tf.get(token) || 0) + 1);
|
|
359
|
+
}
|
|
360
|
+
// Normalize by document length
|
|
361
|
+
const maxFreq = Math.max(...tf.values());
|
|
362
|
+
for (const [term, freq] of tf) {
|
|
363
|
+
tf.set(term, freq / maxFreq);
|
|
364
|
+
}
|
|
365
|
+
return tf;
|
|
366
|
+
}
|
|
367
|
+
/**
|
|
368
|
+
* Compute cosine similarity between two TF-IDF vectors
|
|
369
|
+
*/
|
|
370
|
+
cosineSimilarity(vec1, vec2) {
|
|
371
|
+
let dotProduct = 0;
|
|
372
|
+
let norm1 = 0;
|
|
373
|
+
let norm2 = 0;
|
|
374
|
+
// Compute dot product for shared terms
|
|
375
|
+
for (const [term, weight1] of vec1) {
|
|
376
|
+
const weight2 = vec2.get(term) || 0;
|
|
377
|
+
dotProduct += weight1 * weight2;
|
|
378
|
+
norm1 += weight1 * weight1;
|
|
379
|
+
}
|
|
380
|
+
// Add remaining terms from vec2 to norm2
|
|
381
|
+
for (const [term, weight2] of vec2) {
|
|
382
|
+
norm2 += weight2 * weight2;
|
|
383
|
+
if (!vec1.has(term)) {
|
|
384
|
+
// Already counted in dot product loop
|
|
385
|
+
}
|
|
386
|
+
}
|
|
387
|
+
norm1 = Math.sqrt(norm1);
|
|
388
|
+
norm2 = Math.sqrt(norm2);
|
|
389
|
+
if (norm1 === 0 || norm2 === 0)
|
|
390
|
+
return 0;
|
|
391
|
+
return dotProduct / (norm1 * norm2);
|
|
392
|
+
}
|
|
393
|
+
/**
|
|
394
|
+
* Compute filename similarity using normalized Levenshtein distance
|
|
395
|
+
*/
|
|
396
|
+
computeFilenameSimilarity(name1, name2) {
|
|
397
|
+
// Remove extension for comparison
|
|
398
|
+
const base1 = name1.replace(/\.[^.]+$/, '').toLowerCase();
|
|
399
|
+
const base2 = name2.replace(/\.[^.]+$/, '').toLowerCase();
|
|
400
|
+
if (base1 === base2)
|
|
401
|
+
return 1;
|
|
402
|
+
const distance = this.levenshteinDistance(base1, base2);
|
|
403
|
+
const maxLen = Math.max(base1.length, base2.length);
|
|
404
|
+
return maxLen === 0 ? 1 : 1 - (distance / maxLen);
|
|
405
|
+
}
|
|
406
|
+
/**
|
|
407
|
+
* Compute Levenshtein edit distance between two strings
|
|
408
|
+
*/
|
|
409
|
+
levenshteinDistance(s1, s2) {
|
|
410
|
+
const m = s1.length;
|
|
411
|
+
const n = s2.length;
|
|
412
|
+
// Create DP matrix
|
|
413
|
+
const dp = Array(m + 1).fill(null).map(() => Array(n + 1).fill(0));
|
|
414
|
+
// Initialize base cases
|
|
415
|
+
for (let i = 0; i <= m; i++)
|
|
416
|
+
dp[i][0] = i;
|
|
417
|
+
for (let j = 0; j <= n; j++)
|
|
418
|
+
dp[0][j] = j;
|
|
419
|
+
// Fill the matrix
|
|
420
|
+
for (let i = 1; i <= m; i++) {
|
|
421
|
+
for (let j = 1; j <= n; j++) {
|
|
422
|
+
if (s1[i - 1] === s2[j - 1]) {
|
|
423
|
+
dp[i][j] = dp[i - 1][j - 1];
|
|
424
|
+
}
|
|
425
|
+
else {
|
|
426
|
+
dp[i][j] = 1 + Math.min(dp[i - 1][j], // deletion
|
|
427
|
+
dp[i][j - 1], // insertion
|
|
428
|
+
dp[i - 1][j - 1] // substitution
|
|
429
|
+
);
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
}
|
|
433
|
+
return dp[m][n];
|
|
434
|
+
}
|
|
435
|
+
/**
|
|
436
|
+
* Generate merge suggestions grouped by target folder
|
|
437
|
+
*/
|
|
438
|
+
generateSuggestions(detected) {
|
|
439
|
+
const suggestions = new Map();
|
|
440
|
+
for (const doc of detected) {
|
|
441
|
+
const target = doc.suggestedTarget;
|
|
442
|
+
if (!suggestions.has(target)) {
|
|
443
|
+
suggestions.set(target, []);
|
|
444
|
+
}
|
|
445
|
+
suggestions.get(target).push(doc);
|
|
446
|
+
}
|
|
447
|
+
return suggestions;
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Merge a detected document into living docs
|
|
451
|
+
*/
|
|
452
|
+
async mergeDoc(doc, targetFolder) {
|
|
453
|
+
const target = targetFolder || doc.suggestedTarget;
|
|
454
|
+
const targetDir = path.join(this.projectPath, '.specweave', 'docs', target);
|
|
455
|
+
const targetPath = path.join(targetDir, doc.fileName);
|
|
456
|
+
try {
|
|
457
|
+
// Ensure target directory exists
|
|
458
|
+
if (!fs.existsSync(targetDir)) {
|
|
459
|
+
fs.mkdirSync(targetDir, { recursive: true });
|
|
460
|
+
}
|
|
461
|
+
// Check if target already exists
|
|
462
|
+
if (fs.existsSync(targetPath)) {
|
|
463
|
+
return {
|
|
464
|
+
success: false,
|
|
465
|
+
targetPath,
|
|
466
|
+
error: 'Target file already exists',
|
|
467
|
+
};
|
|
468
|
+
}
|
|
469
|
+
// Copy file
|
|
470
|
+
fs.copyFileSync(doc.absolutePath, targetPath);
|
|
471
|
+
this.logger.info('Merged: ' + doc.sourcePath + ' -> ' + target + '/' + doc.fileName);
|
|
472
|
+
return { success: true, targetPath };
|
|
473
|
+
}
|
|
474
|
+
catch (error) {
|
|
475
|
+
return {
|
|
476
|
+
success: false,
|
|
477
|
+
targetPath,
|
|
478
|
+
error: String(error),
|
|
479
|
+
};
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
}
|
|
483
|
+
/**
|
|
484
|
+
* Scan for existing documentation (convenience function)
|
|
485
|
+
*/
|
|
486
|
+
export async function scanExistingDocs(options) {
|
|
487
|
+
const merger = new LivingDocsMerger(options);
|
|
488
|
+
return merger.scan();
|
|
489
|
+
}
|
|
490
|
+
/**
|
|
491
|
+
* Find similar documentation folders
|
|
492
|
+
*/
|
|
493
|
+
export function findSimilarFolders(projectPath, existingDocs) {
|
|
494
|
+
const folderThemes = new Map();
|
|
495
|
+
// Group themes by parent folder
|
|
496
|
+
for (const doc of existingDocs) {
|
|
497
|
+
const folder = path.dirname(doc.sourcePath);
|
|
498
|
+
if (!folderThemes.has(folder)) {
|
|
499
|
+
folderThemes.set(folder, new Set());
|
|
500
|
+
}
|
|
501
|
+
for (const theme of doc.themes) {
|
|
502
|
+
folderThemes.get(folder).add(theme);
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
// Find folders with overlapping themes
|
|
506
|
+
const similar = new Map();
|
|
507
|
+
const folders = Array.from(folderThemes.keys());
|
|
508
|
+
for (let i = 0; i < folders.length; i++) {
|
|
509
|
+
for (let j = i + 1; j < folders.length; j++) {
|
|
510
|
+
const themes1 = folderThemes.get(folders[i]);
|
|
511
|
+
const themes2 = folderThemes.get(folders[j]);
|
|
512
|
+
const shared = [...themes1].filter(t => themes2.has(t));
|
|
513
|
+
if (shared.length >= 2) {
|
|
514
|
+
if (!similar.has(folders[i])) {
|
|
515
|
+
similar.set(folders[i], []);
|
|
516
|
+
}
|
|
517
|
+
similar.get(folders[i]).push(folders[j]);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
}
|
|
521
|
+
return similar;
|
|
522
|
+
}
|
|
523
|
+
//# sourceMappingURL=merger.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"merger.js","sourceRoot":"","sources":["../../../../../src/core/living-docs/scaffolding/merger.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Living Docs Scaffold - Creates documentation structure for user projects
|
|
3
|
+
*
|
|
4
|
+
* This module creates the .specweave/docs/ directory structure for ANY user project.
|
|
5
|
+
* It's project-agnostic and uses templates with variable substitution.
|
|
6
|
+
*
|
|
7
|
+
* CRITICAL: This runs during `specweave init` to set up the docs structure.
|
|
8
|
+
*
|
|
9
|
+
* @module core/living-docs/scaffolding/scaffold
|
|
10
|
+
*/
|
|
11
|
+
import { Logger } from '../../../utils/logger.js';
|
|
12
|
+
import { type TemplateContext } from './template-engine.js';
|
|
13
|
+
/**
|
|
14
|
+
* Scaffold options
|
|
15
|
+
*/
|
|
16
|
+
export interface ScaffoldOptions {
|
|
17
|
+
/** Project root path */
|
|
18
|
+
projectPath: string;
|
|
19
|
+
/** Project ID (e.g., "my-app") - auto-detected if not provided */
|
|
20
|
+
projectId?: string;
|
|
21
|
+
/** Project display name (e.g., "My Application") */
|
|
22
|
+
projectName?: string;
|
|
23
|
+
/** Whether to overwrite existing files */
|
|
24
|
+
overwrite?: boolean;
|
|
25
|
+
/** Dry run - don't create files, just report what would be created */
|
|
26
|
+
dryRun?: boolean;
|
|
27
|
+
/** Logger instance */
|
|
28
|
+
logger?: Logger;
|
|
29
|
+
/** Additional template context variables */
|
|
30
|
+
additionalContext?: Record<string, unknown>;
|
|
31
|
+
}
|
|
32
|
+
/**
|
|
33
|
+
* Scaffold result
|
|
34
|
+
*/
|
|
35
|
+
export interface ScaffoldResult {
|
|
36
|
+
/** Whether scaffolding was successful */
|
|
37
|
+
success: boolean;
|
|
38
|
+
/** Files that were created */
|
|
39
|
+
filesCreated: string[];
|
|
40
|
+
/** Files that were skipped (already exist) */
|
|
41
|
+
filesSkipped: string[];
|
|
42
|
+
/** Directories that were created */
|
|
43
|
+
dirsCreated: string[];
|
|
44
|
+
/** Any errors that occurred */
|
|
45
|
+
errors: string[];
|
|
46
|
+
/** Project context used for scaffolding */
|
|
47
|
+
context: TemplateContext;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Scaffold class - creates living docs structure
|
|
51
|
+
*/
|
|
52
|
+
export declare class LivingDocsScaffold {
|
|
53
|
+
private projectPath;
|
|
54
|
+
private projectId;
|
|
55
|
+
private logger;
|
|
56
|
+
private templateEngine;
|
|
57
|
+
private overwrite;
|
|
58
|
+
private dryRun;
|
|
59
|
+
private context;
|
|
60
|
+
constructor(options: ScaffoldOptions);
|
|
61
|
+
/**
|
|
62
|
+
* Detect project ID from git remote or directory name
|
|
63
|
+
*/
|
|
64
|
+
private detectProjectId;
|
|
65
|
+
/**
|
|
66
|
+
* Create the full living docs structure
|
|
67
|
+
*/
|
|
68
|
+
scaffold(): Promise<ScaffoldResult>;
|
|
69
|
+
/**
|
|
70
|
+
* Create directory structure recursively
|
|
71
|
+
*/
|
|
72
|
+
private createStructure;
|
|
73
|
+
/**
|
|
74
|
+
* Create root README.md
|
|
75
|
+
*/
|
|
76
|
+
private createRootReadme;
|
|
77
|
+
/**
|
|
78
|
+
* Create project-specific specs folder
|
|
79
|
+
*/
|
|
80
|
+
private createProjectSpecsFolder;
|
|
81
|
+
/**
|
|
82
|
+
* Create SUGGESTIONS.md placeholder
|
|
83
|
+
*/
|
|
84
|
+
private createSuggestionsFile;
|
|
85
|
+
/**
|
|
86
|
+
* Ensure directory exists
|
|
87
|
+
*/
|
|
88
|
+
private ensureDir;
|
|
89
|
+
/**
|
|
90
|
+
* Create a file with content
|
|
91
|
+
*/
|
|
92
|
+
private createFile;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* Scaffold living docs structure (convenience function)
|
|
96
|
+
*/
|
|
97
|
+
export declare function scaffoldLivingDocs(options: ScaffoldOptions): Promise<ScaffoldResult>;
|
|
98
|
+
/**
|
|
99
|
+
* Check if living docs structure exists
|
|
100
|
+
*/
|
|
101
|
+
export declare function hasLivingDocsStructure(projectPath: string): boolean;
|
|
102
|
+
//# sourceMappingURL=scaffold.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"scaffold.d.ts","sourceRoot":"","sources":["../../../../../src/core/living-docs/scaffolding/scaffold.ts"],"names":[],"mappings":"AAAA;;;;;;;;;GASG;AAIH,OAAO,EAAE,MAAM,EAAiB,MAAM,0BAA0B,CAAC;AACjE,OAAO,EAAwC,KAAK,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAElG;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,wBAAwB;IACxB,WAAW,EAAE,MAAM,CAAC;IAEpB,kEAAkE;IAClE,SAAS,CAAC,EAAE,MAAM,CAAC;IAEnB,oDAAoD;IACpD,WAAW,CAAC,EAAE,MAAM,CAAC;IAErB,0CAA0C;IAC1C,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,sEAAsE;IACtE,MAAM,CAAC,EAAE,OAAO,CAAC;IAEjB,sBAAsB;IACtB,MAAM,CAAC,EAAE,MAAM,CAAC;IAEhB,4CAA4C;IAC5C,iBAAiB,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CAC7C;AAED;;GAEG;AACH,MAAM,WAAW,cAAc;IAC7B,yCAAyC;IACzC,OAAO,EAAE,OAAO,CAAC;IAEjB,8BAA8B;IAC9B,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,8CAA8C;IAC9C,YAAY,EAAE,MAAM,EAAE,CAAC;IAEvB,oCAAoC;IACpC,WAAW,EAAE,MAAM,EAAE,CAAC;IAEtB,+BAA+B;IAC/B,MAAM,EAAE,MAAM,EAAE,CAAC;IAEjB,2CAA2C;IAC3C,OAAO,EAAE,eAAe,CAAC;CAC1B;AA8FD;;GAEG;AACH,qBAAa,kBAAkB;IAC7B,OAAO,CAAC,WAAW,CAAS;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;IACvB,OAAO,CAAC,cAAc,CAAiB;IACvC,OAAO,CAAC,SAAS,CAAU;IAC3B,OAAO,CAAC,MAAM,CAAU;IACxB,OAAO,CAAC,OAAO,CAAkB;gBAErB,OAAO,EAAE,eAAe;IAgBpC;;OAEG;IACH,OAAO,CAAC,eAAe;IAmBvB;;OAEG;IACG,QAAQ,IAAI,OAAO,CAAC,cAAc,CAAC;IA8CzC;;OAEG;YACW,eAAe;IAwB7B;;OAEG;YACW,gBAAgB;IAoC9B;;OAEG;YACW,wBAAwB;IAsCtC;;OAEG;YACW,qBAAqB;IAkCnC;;OAEG;YACW,SAAS;IAcvB;;OAEG;YACW,UAAU;CAqBzB;AAED;;GAEG;AACH,wBAAsB,kBAAkB,CAAC,OAAO,EAAE,eAAe,GAAG,OAAO,CAAC,cAAc,CAAC,CAG1F;AAED;;GAEG;AACH,wBAAgB,sBAAsB,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAGnE"}
|