specweave 0.28.3 → 0.28.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.
Files changed (33) hide show
  1. package/README.md +36 -93
  2. package/dist/src/core/living-docs/feature-consistency-validator.d.ts +129 -0
  3. package/dist/src/core/living-docs/feature-consistency-validator.d.ts.map +1 -0
  4. package/dist/src/core/living-docs/feature-consistency-validator.js +445 -0
  5. package/dist/src/core/living-docs/feature-consistency-validator.js.map +1 -0
  6. package/dist/src/core/living-docs/index.d.ts +1 -0
  7. package/dist/src/core/living-docs/index.d.ts.map +1 -1
  8. package/dist/src/core/living-docs/index.js +1 -0
  9. package/dist/src/core/living-docs/index.js.map +1 -1
  10. package/dist/src/core/living-docs/living-docs-sync.d.ts +30 -2
  11. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  12. package/dist/src/core/living-docs/living-docs-sync.js +74 -4
  13. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  14. package/dist/src/core/repo-structure/prompt-consolidator.js +6 -6
  15. package/dist/src/core/repo-structure/prompt-consolidator.js.map +1 -1
  16. package/dist/src/sync/frontmatter-updater.d.ts +8 -0
  17. package/dist/src/sync/frontmatter-updater.d.ts.map +1 -1
  18. package/dist/src/sync/frontmatter-updater.js +27 -2
  19. package/dist/src/sync/frontmatter-updater.js.map +1 -1
  20. package/dist/src/sync/sync-coordinator.d.ts +1 -0
  21. package/dist/src/sync/sync-coordinator.d.ts.map +1 -1
  22. package/dist/src/sync/sync-coordinator.js +6 -3
  23. package/dist/src/sync/sync-coordinator.js.map +1 -1
  24. package/package.json +1 -1
  25. package/plugins/specweave/commands/specweave-sync-specs.md +14 -5
  26. package/plugins/specweave/commands/specweave-validate-features.md +203 -0
  27. package/plugins/specweave/commands/specweave-workflow.md +483 -0
  28. package/plugins/specweave-jira/skills/jira-sync/SKILL.md +4 -4
  29. package/plugins/specweave-jira/skills/specweave-jira-mapper/SKILL.md +3 -3
  30. package/plugins/specweave-kafka/skills/kafka-mcp-integration/SKILL.md +17 -0
  31. package/plugins/specweave-plugin-dev/skills/claude-sdk/SKILL.md +3 -1
  32. package/plugins/specweave-ui/commands/ui-automate.md +5 -28
  33. package/src/templates/AGENTS.md.template +92 -9
@@ -0,0 +1,445 @@
1
+ /**
2
+ * Feature Consistency Validator
3
+ *
4
+ * Validates and repairs consistency between:
5
+ * - .specweave/docs/internal/specs/_features/FS-XXX/
6
+ * - .specweave/docs/internal/specs/{project}/FS-XXX/
7
+ *
8
+ * PROBLEM SOLVED:
9
+ * Living docs sync creates _features/ and {project}/ folders sequentially.
10
+ * If sync fails midway or increment is deleted, folders can get out of sync.
11
+ *
12
+ * SOLUTION:
13
+ * 1. Detect discrepancies (orphaned _features without project folders)
14
+ * 2. Auto-repair by creating missing project folders
15
+ * 3. Report issues for manual intervention when auto-repair not possible
16
+ *
17
+ * @see ADR-0142 (if created) for architectural decision
18
+ */
19
+ import { existsSync, promises as fs } from 'fs';
20
+ import path from 'path';
21
+ import yaml from 'yaml';
22
+ import { consoleLogger } from '../../utils/logger.js';
23
+ export class FeatureConsistencyValidator {
24
+ constructor(projectRoot, options = {}) {
25
+ this.projectRoot = projectRoot;
26
+ this.specsPath = path.join(projectRoot, '.specweave/docs/internal/specs');
27
+ this.incrementsPath = path.join(projectRoot, '.specweave/increments');
28
+ this.logger = options.logger ?? consoleLogger;
29
+ this.defaultProject = options.defaultProject ?? 'specweave';
30
+ this.includeArchived = options.includeArchived ?? false;
31
+ }
32
+ /**
33
+ * Validate consistency between _features and project folders
34
+ *
35
+ * @param autoRepair - If true, attempt to auto-repair discrepancies
36
+ * @returns Validation result with discrepancies and repair results
37
+ */
38
+ async validate(autoRepair = false) {
39
+ const result = {
40
+ totalFeatures: 0,
41
+ consistentCount: 0,
42
+ discrepancies: [],
43
+ repairs: autoRepair ? [] : undefined
44
+ };
45
+ this.logger.log('🔍 Validating feature folder consistency...');
46
+ // Step 1: Get all features from _features folder
47
+ const featuresDir = path.join(this.specsPath, '_features');
48
+ if (!existsSync(featuresDir)) {
49
+ this.logger.log(' â„šī¸ No _features folder found, nothing to validate');
50
+ return result;
51
+ }
52
+ const featureFolders = await this.getFeatureFolders(featuresDir);
53
+ result.totalFeatures = featureFolders.length;
54
+ // Step 2: Get all project folders
55
+ const projectFolders = await this.getProjectFolders();
56
+ // Step 3: Check each feature for consistency
57
+ for (const featureId of featureFolders) {
58
+ const discrepancy = await this.checkFeatureConsistency(featureId, projectFolders);
59
+ if (discrepancy) {
60
+ result.discrepancies.push(discrepancy);
61
+ // Attempt auto-repair if enabled
62
+ if (autoRepair && discrepancy.autoRepairable) {
63
+ const repairResult = await this.repairDiscrepancy(discrepancy);
64
+ result.repairs.push(repairResult);
65
+ if (repairResult.success) {
66
+ result.consistentCount++; // Count as consistent after repair
67
+ }
68
+ }
69
+ }
70
+ else {
71
+ result.consistentCount++;
72
+ }
73
+ }
74
+ // Step 4: Log summary
75
+ this.logValidationSummary(result);
76
+ return result;
77
+ }
78
+ /**
79
+ * Get all feature folder IDs from _features directory
80
+ */
81
+ async getFeatureFolders(featuresDir) {
82
+ const entries = await fs.readdir(featuresDir, { withFileTypes: true });
83
+ const folders = [];
84
+ for (const entry of entries) {
85
+ if (!entry.isDirectory())
86
+ continue;
87
+ // Skip _archive unless includeArchived is true
88
+ if (entry.name === '_archive' && !this.includeArchived)
89
+ continue;
90
+ // Only include FS-XXX pattern folders
91
+ if (entry.name.startsWith('FS-')) {
92
+ folders.push(entry.name);
93
+ }
94
+ }
95
+ return folders.sort();
96
+ }
97
+ /**
98
+ * Get all project folder names (excluding _features, _epics, _archive)
99
+ */
100
+ async getProjectFolders() {
101
+ if (!existsSync(this.specsPath)) {
102
+ return [];
103
+ }
104
+ const entries = await fs.readdir(this.specsPath, { withFileTypes: true });
105
+ const projects = [];
106
+ for (const entry of entries) {
107
+ if (!entry.isDirectory())
108
+ continue;
109
+ // Skip special folders
110
+ if (entry.name.startsWith('_'))
111
+ continue;
112
+ projects.push(entry.name);
113
+ }
114
+ return projects;
115
+ }
116
+ /**
117
+ * Check if a feature has consistent folders across _features and projects
118
+ */
119
+ async checkFeatureConsistency(featureId, projectFolders) {
120
+ const featuresPath = path.join(this.specsPath, '_features', featureId);
121
+ const featureFilePath = path.join(featuresPath, 'FEATURE.md');
122
+ // Check if FEATURE.md exists
123
+ if (!existsSync(featureFilePath)) {
124
+ return {
125
+ featureId,
126
+ type: 'orphaned_feature',
127
+ description: `_features/${featureId}/ exists but has no FEATURE.md`,
128
+ autoRepairable: false,
129
+ featuresPath
130
+ };
131
+ }
132
+ // Parse FEATURE.md to find linked increment
133
+ const linkedIncrement = await this.extractLinkedIncrement(featureFilePath);
134
+ const incrementExists = linkedIncrement
135
+ ? this.checkIncrementExists(linkedIncrement)
136
+ : false;
137
+ // Check if feature exists in any project folder
138
+ let foundInProjects = [];
139
+ for (const project of projectFolders) {
140
+ const projectFeaturePath = path.join(this.specsPath, project, featureId);
141
+ if (existsSync(projectFeaturePath)) {
142
+ foundInProjects.push(project);
143
+ }
144
+ }
145
+ if (foundInProjects.length === 0) {
146
+ // Check if this is an orphaned feature (increment deleted, not external)
147
+ const isExternalFeature = await this.isExternalFeature(featureFilePath);
148
+ if (!incrementExists && !isExternalFeature && linkedIncrement) {
149
+ // ORPHANED: Increment was deleted, feature is not external - should be archived
150
+ // This prevents creating project folders for features whose increments no longer exist
151
+ return {
152
+ featureId,
153
+ type: 'orphaned_feature',
154
+ description: `Feature ${featureId} references deleted increment ${linkedIncrement} - should be archived`,
155
+ autoRepairable: true, // Can auto-repair via archiver
156
+ featuresPath,
157
+ linkedIncrementId: linkedIncrement,
158
+ incrementExists: false
159
+ };
160
+ }
161
+ // Normal case: increment exists OR external feature OR no linked increment
162
+ // Create missing project folder
163
+ return {
164
+ featureId,
165
+ type: 'missing_project_folder',
166
+ description: `Feature ${featureId} exists in _features/ but not in any project folder`,
167
+ autoRepairable: true, // We can create the missing folder
168
+ featuresPath,
169
+ projectPath: path.join(this.specsPath, this.defaultProject, featureId),
170
+ linkedIncrementId: linkedIncrement,
171
+ incrementExists
172
+ };
173
+ }
174
+ // Feature is consistent
175
+ return null;
176
+ }
177
+ /**
178
+ * Check if a feature is from an external source (GitHub, JIRA, ADO)
179
+ * External features should NOT be considered orphaned even if local increment is missing
180
+ */
181
+ async isExternalFeature(featureFilePath) {
182
+ try {
183
+ const content = await fs.readFile(featureFilePath, 'utf-8');
184
+ // Check frontmatter for external indicators
185
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
186
+ if (frontmatterMatch) {
187
+ try {
188
+ const frontmatter = yaml.parse(frontmatterMatch[1]);
189
+ if (frontmatter.origin === 'external' ||
190
+ frontmatter.external_source ||
191
+ frontmatter.external_id) {
192
+ return true;
193
+ }
194
+ }
195
+ catch {
196
+ // Ignore YAML parse errors
197
+ }
198
+ }
199
+ // Check for external badges/markers in content
200
+ // 🔗 = GitHub, đŸŽĢ = JIRA, 📋 = ADO
201
+ if (content.includes('origin: external') ||
202
+ content.includes('external_source:') ||
203
+ content.includes('external_id:')) {
204
+ return true;
205
+ }
206
+ return false;
207
+ }
208
+ catch {
209
+ return false;
210
+ }
211
+ }
212
+ /**
213
+ * Extract linked increment ID from FEATURE.md
214
+ */
215
+ async extractLinkedIncrement(featureFilePath) {
216
+ try {
217
+ const content = await fs.readFile(featureFilePath, 'utf-8');
218
+ // Look for increment link pattern: [0062-test-living-docs-auto-sync](...)
219
+ const incrementMatch = content.match(/\[(\d{4}-[^\]]+)\]\([^)]+\)/);
220
+ if (incrementMatch) {
221
+ return incrementMatch[1];
222
+ }
223
+ // Also check frontmatter
224
+ const frontmatterMatch = content.match(/^---\n([\s\S]*?)\n---/);
225
+ if (frontmatterMatch) {
226
+ try {
227
+ const frontmatter = yaml.parse(frontmatterMatch[1]);
228
+ if (frontmatter.increment) {
229
+ return frontmatter.increment;
230
+ }
231
+ }
232
+ catch {
233
+ // Ignore YAML parse errors
234
+ }
235
+ }
236
+ return null;
237
+ }
238
+ catch {
239
+ return null;
240
+ }
241
+ }
242
+ /**
243
+ * Check if an increment exists (in active or archive folder)
244
+ */
245
+ checkIncrementExists(incrementId) {
246
+ const activePath = path.join(this.incrementsPath, incrementId);
247
+ const archivePath = path.join(this.incrementsPath, '_archive', incrementId);
248
+ return existsSync(activePath) || existsSync(archivePath);
249
+ }
250
+ /**
251
+ * Attempt to repair a discrepancy
252
+ */
253
+ async repairDiscrepancy(discrepancy) {
254
+ const result = {
255
+ featureId: discrepancy.featureId,
256
+ success: false,
257
+ action: ''
258
+ };
259
+ try {
260
+ switch (discrepancy.type) {
261
+ case 'missing_project_folder':
262
+ result.action = await this.repairMissingProjectFolder(discrepancy);
263
+ result.success = true;
264
+ break;
265
+ case 'orphaned_feature':
266
+ // Auto-archive orphaned features (increment was deleted)
267
+ if (discrepancy.autoRepairable) {
268
+ result.action = await this.archiveOrphanedFeature(discrepancy);
269
+ result.success = true;
270
+ }
271
+ else {
272
+ // No FEATURE.md or other issue - needs manual intervention
273
+ result.action = 'Skipped - requires manual intervention (no FEATURE.md)';
274
+ result.success = false;
275
+ }
276
+ break;
277
+ default:
278
+ result.action = 'Unknown discrepancy type';
279
+ result.success = false;
280
+ }
281
+ }
282
+ catch (error) {
283
+ result.error = String(error);
284
+ result.action = `Failed: ${error}`;
285
+ }
286
+ return result;
287
+ }
288
+ /**
289
+ * Archive an orphaned feature (increment was deleted)
290
+ * Delegates to FeatureArchiver for consistent archiving behavior
291
+ */
292
+ async archiveOrphanedFeature(discrepancy) {
293
+ // Dynamic import to avoid circular dependency
294
+ const { FeatureArchiver } = await import('./feature-archiver.js');
295
+ const archiver = new FeatureArchiver(this.projectRoot);
296
+ this.logger.log(` đŸ—‚ī¸ Archiving orphaned feature ${discrepancy.featureId} (increment deleted)...`);
297
+ const archiveResult = await archiver.archiveFeatures({
298
+ archiveOrphanedFeatures: true,
299
+ archiveOrphanedEpics: false, // Be conservative - only archive features
300
+ dryRun: false,
301
+ updateLinks: true,
302
+ customReason: `Increment ${discrepancy.linkedIncrementId || 'unknown'} was deleted`
303
+ });
304
+ if (archiveResult.archivedFeatures.includes(discrepancy.featureId)) {
305
+ this.logger.log(` ✅ Archived ${discrepancy.featureId} to _archive/`);
306
+ return `Archived orphaned feature ${discrepancy.featureId} (increment ${discrepancy.linkedIncrementId} deleted)`;
307
+ }
308
+ else if (archiveResult.errors.length > 0) {
309
+ throw new Error(archiveResult.errors.join(', '));
310
+ }
311
+ else {
312
+ // Feature might have been archived by another process or already in archive
313
+ return `Feature ${discrepancy.featureId} already archived or cleaned up`;
314
+ }
315
+ }
316
+ /**
317
+ * Create missing project folder for a feature
318
+ */
319
+ async repairMissingProjectFolder(discrepancy) {
320
+ const projectPath = discrepancy.projectPath;
321
+ const featuresPath = discrepancy.featuresPath;
322
+ // Create project folder
323
+ await fs.mkdir(projectPath, { recursive: true });
324
+ // Extract info from FEATURE.md to create README.md
325
+ const featureFilePath = path.join(featuresPath, 'FEATURE.md');
326
+ const featureContent = await fs.readFile(featureFilePath, 'utf-8');
327
+ // Extract title from FEATURE.md
328
+ let title = discrepancy.featureId;
329
+ const titleMatch = featureContent.match(/^#\s+(.+)$/m);
330
+ if (titleMatch) {
331
+ title = titleMatch[1];
332
+ }
333
+ // Extract frontmatter
334
+ let status = 'in-progress';
335
+ const frontmatterMatch = featureContent.match(/^---\n([\s\S]*?)\n---/);
336
+ if (frontmatterMatch) {
337
+ try {
338
+ const frontmatter = yaml.parse(frontmatterMatch[1]);
339
+ status = frontmatter.status || status;
340
+ }
341
+ catch {
342
+ // Ignore YAML parse errors
343
+ }
344
+ }
345
+ // Create README.md in project folder
346
+ const readmeContent = `---
347
+ id: ${discrepancy.featureId}-${this.defaultProject}
348
+ title: "${title} - ${this.defaultProject.charAt(0).toUpperCase() + this.defaultProject.slice(1)} Implementation"
349
+ feature: ${discrepancy.featureId}
350
+ project: ${this.defaultProject}
351
+ type: feature-context
352
+ status: ${status}
353
+ auto_repaired: true
354
+ repaired_at: ${new Date().toISOString()}
355
+ ---
356
+
357
+ # ${title}
358
+
359
+ **Feature**: [${discrepancy.featureId}](../../_features/${discrepancy.featureId}/FEATURE.md)
360
+
361
+ ## Overview
362
+
363
+ This project context was auto-created by consistency validator.
364
+
365
+ ## User Stories
366
+
367
+ See user story files in this directory.
368
+
369
+ ## Note
370
+
371
+ This folder was auto-created because _features/${discrepancy.featureId}/ existed
372
+ but ${this.defaultProject}/${discrepancy.featureId}/ was missing.
373
+
374
+ ${discrepancy.linkedIncrementId
375
+ ? `**Linked Increment**: ${discrepancy.linkedIncrementId} (${discrepancy.incrementExists ? 'exists' : 'not found'})`
376
+ : '**Linked Increment**: Not found in FEATURE.md'}
377
+ `;
378
+ const readmePath = path.join(projectPath, 'README.md');
379
+ await fs.writeFile(readmePath, readmeContent, 'utf-8');
380
+ this.logger.log(` ✅ Created ${this.defaultProject}/${discrepancy.featureId}/README.md`);
381
+ return `Created ${projectPath}/README.md`;
382
+ }
383
+ /**
384
+ * Log validation summary
385
+ */
386
+ logValidationSummary(result) {
387
+ this.logger.log('');
388
+ this.logger.log('═══════════════════════════════════════════════════════');
389
+ this.logger.log('📊 FEATURE CONSISTENCY VALIDATION REPORT');
390
+ this.logger.log('═══════════════════════════════════════════════════════');
391
+ this.logger.log('');
392
+ this.logger.log(`Total features scanned: ${result.totalFeatures}`);
393
+ this.logger.log(`Consistent: ${result.consistentCount}`);
394
+ this.logger.log(`Discrepancies found: ${result.discrepancies.length}`);
395
+ this.logger.log('');
396
+ if (result.discrepancies.length > 0) {
397
+ this.logger.log('───────────────────────────────────────────────────────');
398
+ this.logger.log('âš ī¸ DISCREPANCIES');
399
+ this.logger.log('───────────────────────────────────────────────────────');
400
+ for (const disc of result.discrepancies) {
401
+ this.logger.log('');
402
+ this.logger.log(`Feature: ${disc.featureId}`);
403
+ this.logger.log(`Type: ${disc.type}`);
404
+ this.logger.log(`Description: ${disc.description}`);
405
+ this.logger.log(`Auto-repairable: ${disc.autoRepairable ? 'Yes' : 'No'}`);
406
+ if (disc.linkedIncrementId) {
407
+ this.logger.log(`Linked increment: ${disc.linkedIncrementId} (${disc.incrementExists ? '✅ exists' : '❌ not found'})`);
408
+ }
409
+ }
410
+ }
411
+ if (result.repairs && result.repairs.length > 0) {
412
+ this.logger.log('');
413
+ this.logger.log('───────────────────────────────────────────────────────');
414
+ this.logger.log('🔧 REPAIR RESULTS');
415
+ this.logger.log('───────────────────────────────────────────────────────');
416
+ for (const repair of result.repairs) {
417
+ const icon = repair.success ? '✅' : '❌';
418
+ this.logger.log(`${icon} ${repair.featureId}: ${repair.action}`);
419
+ if (repair.error) {
420
+ this.logger.log(` Error: ${repair.error}`);
421
+ }
422
+ }
423
+ }
424
+ this.logger.log('');
425
+ this.logger.log('═══════════════════════════════════════════════════════');
426
+ }
427
+ /**
428
+ * Quick check: Are there any discrepancies?
429
+ * Use this for fast validation without full report
430
+ */
431
+ async hasDiscrepancies() {
432
+ const result = await this.validate(false);
433
+ return result.discrepancies.length > 0;
434
+ }
435
+ /**
436
+ * Get list of orphaned features (features in _features without corresponding project folder)
437
+ */
438
+ async getOrphanedFeatures() {
439
+ const result = await this.validate(false);
440
+ return result.discrepancies
441
+ .filter(d => d.type === 'missing_project_folder')
442
+ .map(d => d.featureId);
443
+ }
444
+ }
445
+ //# sourceMappingURL=feature-consistency-validator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"feature-consistency-validator.js","sourceRoot":"","sources":["../../../../src/core/living-docs/feature-consistency-validator.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,OAAO,EAAE,UAAU,EAAE,QAAQ,IAAI,EAAE,EAAE,MAAM,IAAI,CAAC;AAChD,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,IAAI,MAAM,MAAM,CAAC;AACxB,OAAO,EAAU,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAgD9D,MAAM,OAAO,2BAA2B;IAQtC,YAAY,WAAmB,EAAE,UAA4B,EAAE;QAC7D,IAAI,CAAC,WAAW,GAAG,WAAW,CAAC;QAC/B,IAAI,CAAC,SAAS,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,gCAAgC,CAAC,CAAC;QAC1E,IAAI,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,uBAAuB,CAAC,CAAC;QACtE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;QAC9C,IAAI,CAAC,cAAc,GAAG,OAAO,CAAC,cAAc,IAAI,WAAW,CAAC;QAC5D,IAAI,CAAC,eAAe,GAAG,OAAO,CAAC,eAAe,IAAI,KAAK,CAAC;IAC1D,CAAC;IAED;;;;;OAKG;IACH,KAAK,CAAC,QAAQ,CAAC,aAAsB,KAAK;QACxC,MAAM,MAAM,GAAqB;YAC/B,aAAa,EAAE,CAAC;YAChB,eAAe,EAAE,CAAC;YAClB,aAAa,EAAE,EAAE;YACjB,OAAO,EAAE,UAAU,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS;SACrC,CAAC;QAEF,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;QAE/D,iDAAiD;QACjD,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,CAAC,CAAC;QAC3D,IAAI,CAAC,UAAU,CAAC,WAAW,CAAC,EAAE,CAAC;YAC7B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,uDAAuD,CAAC,CAAC;YACzE,OAAO,MAAM,CAAC;QAChB,CAAC;QAED,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;QACjE,MAAM,CAAC,aAAa,GAAG,cAAc,CAAC,MAAM,CAAC;QAE7C,kCAAkC;QAClC,MAAM,cAAc,GAAG,MAAM,IAAI,CAAC,iBAAiB,EAAE,CAAC;QAEtD,6CAA6C;QAC7C,KAAK,MAAM,SAAS,IAAI,cAAc,EAAE,CAAC;YACvC,MAAM,WAAW,GAAG,MAAM,IAAI,CAAC,uBAAuB,CACpD,SAAS,EACT,cAAc,CACf,CAAC;YAEF,IAAI,WAAW,EAAE,CAAC;gBAChB,MAAM,CAAC,aAAa,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;gBAEvC,iCAAiC;gBACjC,IAAI,UAAU,IAAI,WAAW,CAAC,cAAc,EAAE,CAAC;oBAC7C,MAAM,YAAY,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,WAAW,CAAC,CAAC;oBAC/D,MAAM,CAAC,OAAQ,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;oBAEnC,IAAI,YAAY,CAAC,OAAO,EAAE,CAAC;wBACzB,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC,mCAAmC;oBAC/D,CAAC;gBACH,CAAC;YACH,CAAC;iBAAM,CAAC;gBACN,MAAM,CAAC,eAAe,EAAE,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,sBAAsB;QACtB,IAAI,CAAC,oBAAoB,CAAC,MAAM,CAAC,CAAC;QAElC,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,WAAmB;QACjD,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,WAAW,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QACvE,MAAM,OAAO,GAAa,EAAE,CAAC;QAE7B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YAEnC,+CAA+C;YAC/C,IAAI,KAAK,CAAC,IAAI,KAAK,UAAU,IAAI,CAAC,IAAI,CAAC,eAAe;gBAAE,SAAS;YAEjE,sCAAsC;YACtC,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,EAAE,CAAC;gBACjC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;QACH,CAAC;QAED,OAAO,OAAO,CAAC,IAAI,EAAE,CAAC;IACxB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB;QAC7B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,SAAS,CAAC,EAAE,CAAC;YAChC,OAAO,EAAE,CAAC;QACZ,CAAC;QAED,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,OAAO,CAAC,IAAI,CAAC,SAAS,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;QAC1E,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;YAC5B,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;gBAAE,SAAS;YAEnC,uBAAuB;YACvB,IAAI,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC;gBAAE,SAAS;YAEzC,QAAQ,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;QAED,OAAO,QAAQ,CAAC;IAClB,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,uBAAuB,CACnC,SAAiB,EACjB,cAAwB;QAExB,MAAM,YAAY,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,CAAC,CAAC;QACvE,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAE9D,6BAA6B;QAC7B,IAAI,CAAC,UAAU,CAAC,eAAe,CAAC,EAAE,CAAC;YACjC,OAAO;gBACL,SAAS;gBACT,IAAI,EAAE,kBAAkB;gBACxB,WAAW,EAAE,aAAa,SAAS,gCAAgC;gBACnE,cAAc,EAAE,KAAK;gBACrB,YAAY;aACb,CAAC;QACJ,CAAC;QAED,4CAA4C;QAC5C,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,eAAe,CAAC,CAAC;QAC3E,MAAM,eAAe,GAAG,eAAe;YACrC,CAAC,CAAC,IAAI,CAAC,oBAAoB,CAAC,eAAe,CAAC;YAC5C,CAAC,CAAC,KAAK,CAAC;QAEV,gDAAgD;QAChD,IAAI,eAAe,GAAa,EAAE,CAAC;QACnC,KAAK,MAAM,OAAO,IAAI,cAAc,EAAE,CAAC;YACrC,MAAM,kBAAkB,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,OAAO,EAAE,SAAS,CAAC,CAAC;YACzE,IAAI,UAAU,CAAC,kBAAkB,CAAC,EAAE,CAAC;gBACnC,eAAe,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YAChC,CAAC;QACH,CAAC;QAED,IAAI,eAAe,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACjC,yEAAyE;YACzE,MAAM,iBAAiB,GAAG,MAAM,IAAI,CAAC,iBAAiB,CAAC,eAAe,CAAC,CAAC;YAExE,IAAI,CAAC,eAAe,IAAI,CAAC,iBAAiB,IAAI,eAAe,EAAE,CAAC;gBAC9D,gFAAgF;gBAChF,uFAAuF;gBACvF,OAAO;oBACL,SAAS;oBACT,IAAI,EAAE,kBAAkB;oBACxB,WAAW,EAAE,WAAW,SAAS,iCAAiC,eAAe,uBAAuB;oBACxG,cAAc,EAAE,IAAI,EAAE,+BAA+B;oBACrD,YAAY;oBACZ,iBAAiB,EAAE,eAAe;oBAClC,eAAe,EAAE,KAAK;iBACvB,CAAC;YACJ,CAAC;YAED,2EAA2E;YAC3E,gCAAgC;YAChC,OAAO;gBACL,SAAS;gBACT,IAAI,EAAE,wBAAwB;gBAC9B,WAAW,EAAE,WAAW,SAAS,qDAAqD;gBACtF,cAAc,EAAE,IAAI,EAAE,mCAAmC;gBACzD,YAAY;gBACZ,WAAW,EAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,SAAS,EAAE,IAAI,CAAC,cAAc,EAAE,SAAS,CAAC;gBACtE,iBAAiB,EAAE,eAAe;gBAClC,eAAe;aAChB,CAAC;QACJ,CAAC;QAED,wBAAwB;QACxB,OAAO,IAAI,CAAC;IACd,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,iBAAiB,CAAC,eAAuB;QACrD,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAE5D,4CAA4C;YAC5C,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAChE,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,CAAC;oBACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpD,IAAI,WAAW,CAAC,MAAM,KAAK,UAAU;wBACjC,WAAW,CAAC,eAAe;wBAC3B,WAAW,CAAC,WAAW,EAAE,CAAC;wBAC5B,OAAO,IAAI,CAAC;oBACd,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,2BAA2B;gBAC7B,CAAC;YACH,CAAC;YAED,+CAA+C;YAC/C,mCAAmC;YACnC,IAAI,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;gBACpC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAAC;gBACpC,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAC,EAAE,CAAC;gBACrC,OAAO,IAAI,CAAC;YACd,CAAC;YAED,OAAO,KAAK,CAAC;QACf,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,sBAAsB,CAAC,eAAuB;QAC1D,IAAI,CAAC;YACH,MAAM,OAAO,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;YAE5D,0EAA0E;YAC1E,MAAM,cAAc,GAAG,OAAO,CAAC,KAAK,CAAC,6BAA6B,CAAC,CAAC;YACpE,IAAI,cAAc,EAAE,CAAC;gBACnB,OAAO,cAAc,CAAC,CAAC,CAAC,CAAC;YAC3B,CAAC;YAED,yBAAyB;YACzB,MAAM,gBAAgB,GAAG,OAAO,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;YAChE,IAAI,gBAAgB,EAAE,CAAC;gBACrB,IAAI,CAAC;oBACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;oBACpD,IAAI,WAAW,CAAC,SAAS,EAAE,CAAC;wBAC1B,OAAO,WAAW,CAAC,SAAS,CAAC;oBAC/B,CAAC;gBACH,CAAC;gBAAC,MAAM,CAAC;oBACP,2BAA2B;gBAC7B,CAAC;YACH,CAAC;YAED,OAAO,IAAI,CAAC;QACd,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,IAAI,CAAC;QACd,CAAC;IACH,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,WAAmB;QAC9C,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,WAAW,CAAC,CAAC;QAC/D,MAAM,WAAW,GAAG,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,cAAc,EAAE,UAAU,EAAE,WAAW,CAAC,CAAC;QAC5E,OAAO,UAAU,CAAC,UAAU,CAAC,IAAI,UAAU,CAAC,WAAW,CAAC,CAAC;IAC3D,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,iBAAiB,CAAC,WAA8B;QAC5D,MAAM,MAAM,GAAiB;YAC3B,SAAS,EAAE,WAAW,CAAC,SAAS;YAChC,OAAO,EAAE,KAAK;YACd,MAAM,EAAE,EAAE;SACX,CAAC;QAEF,IAAI,CAAC;YACH,QAAQ,WAAW,CAAC,IAAI,EAAE,CAAC;gBACzB,KAAK,wBAAwB;oBAC3B,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,0BAA0B,CAAC,WAAW,CAAC,CAAC;oBACnE,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;oBACtB,MAAM;gBAER,KAAK,kBAAkB;oBACrB,yDAAyD;oBACzD,IAAI,WAAW,CAAC,cAAc,EAAE,CAAC;wBAC/B,MAAM,CAAC,MAAM,GAAG,MAAM,IAAI,CAAC,sBAAsB,CAAC,WAAW,CAAC,CAAC;wBAC/D,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC;oBACxB,CAAC;yBAAM,CAAC;wBACN,2DAA2D;wBAC3D,MAAM,CAAC,MAAM,GAAG,wDAAwD,CAAC;wBACzE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;oBACzB,CAAC;oBACD,MAAM;gBAER;oBACE,MAAM,CAAC,MAAM,GAAG,0BAA0B,CAAC;oBAC3C,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;YAC3B,CAAC;QACH,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,MAAM,CAAC,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;YAC7B,MAAM,CAAC,MAAM,GAAG,WAAW,KAAK,EAAE,CAAC;QACrC,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED;;;OAGG;IACK,KAAK,CAAC,sBAAsB,CAAC,WAA8B;QACjE,8CAA8C;QAC9C,MAAM,EAAE,eAAe,EAAE,GAAG,MAAM,MAAM,CAAC,uBAAuB,CAAC,CAAC;QAClE,MAAM,QAAQ,GAAG,IAAI,eAAe,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;QAEvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,sCAAsC,WAAW,CAAC,SAAS,yBAAyB,CAAC,CAAC;QAEtG,MAAM,aAAa,GAAG,MAAM,QAAQ,CAAC,eAAe,CAAC;YACnD,uBAAuB,EAAE,IAAI;YAC7B,oBAAoB,EAAE,KAAK,EAAE,0CAA0C;YACvE,MAAM,EAAE,KAAK;YACb,WAAW,EAAE,IAAI;YACjB,YAAY,EAAE,aAAa,WAAW,CAAC,iBAAiB,IAAI,SAAS,cAAc;SACpF,CAAC,CAAC;QAEH,IAAI,aAAa,CAAC,gBAAgB,CAAC,QAAQ,CAAC,WAAW,CAAC,SAAS,CAAC,EAAE,CAAC;YACnE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,iBAAiB,WAAW,CAAC,SAAS,eAAe,CAAC,CAAC;YACvE,OAAO,6BAA6B,WAAW,CAAC,SAAS,eAAe,WAAW,CAAC,iBAAiB,WAAW,CAAC;QACnH,CAAC;aAAM,IAAI,aAAa,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAC3C,MAAM,IAAI,KAAK,CAAC,aAAa,CAAC,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,CAAC;QACnD,CAAC;aAAM,CAAC;YACN,4EAA4E;YAC5E,OAAO,WAAW,WAAW,CAAC,SAAS,iCAAiC,CAAC;QAC3E,CAAC;IACH,CAAC;IAED;;OAEG;IACK,KAAK,CAAC,0BAA0B,CAAC,WAA8B;QACrE,MAAM,WAAW,GAAG,WAAW,CAAC,WAAY,CAAC;QAC7C,MAAM,YAAY,GAAG,WAAW,CAAC,YAAa,CAAC;QAE/C,wBAAwB;QACxB,MAAM,EAAE,CAAC,KAAK,CAAC,WAAW,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;QAEjD,mDAAmD;QACnD,MAAM,eAAe,GAAG,IAAI,CAAC,IAAI,CAAC,YAAY,EAAE,YAAY,CAAC,CAAC;QAC9D,MAAM,cAAc,GAAG,MAAM,EAAE,CAAC,QAAQ,CAAC,eAAe,EAAE,OAAO,CAAC,CAAC;QAEnE,gCAAgC;QAChC,IAAI,KAAK,GAAG,WAAW,CAAC,SAAS,CAAC;QAClC,MAAM,UAAU,GAAG,cAAc,CAAC,KAAK,CAAC,aAAa,CAAC,CAAC;QACvD,IAAI,UAAU,EAAE,CAAC;YACf,KAAK,GAAG,UAAU,CAAC,CAAC,CAAC,CAAC;QACxB,CAAC;QAED,sBAAsB;QACtB,IAAI,MAAM,GAAG,aAAa,CAAC;QAC3B,MAAM,gBAAgB,GAAG,cAAc,CAAC,KAAK,CAAC,uBAAuB,CAAC,CAAC;QACvE,IAAI,gBAAgB,EAAE,CAAC;YACrB,IAAI,CAAC;gBACH,MAAM,WAAW,GAAG,IAAI,CAAC,KAAK,CAAC,gBAAgB,CAAC,CAAC,CAAC,CAAC,CAAC;gBACpD,MAAM,GAAG,WAAW,CAAC,MAAM,IAAI,MAAM,CAAC;YACxC,CAAC;YAAC,MAAM,CAAC;gBACP,2BAA2B;YAC7B,CAAC;QACH,CAAC;QAED,qCAAqC;QACrC,MAAM,aAAa,GAAG;MACpB,WAAW,CAAC,SAAS,IAAI,IAAI,CAAC,cAAc;UACxC,KAAK,MAAM,IAAI,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,GAAG,IAAI,CAAC,cAAc,CAAC,KAAK,CAAC,CAAC,CAAC;WACpF,WAAW,CAAC,SAAS;WACrB,IAAI,CAAC,cAAc;;UAEpB,MAAM;;eAED,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;;;IAGnC,KAAK;;gBAEO,WAAW,CAAC,SAAS,qBAAqB,WAAW,CAAC,SAAS;;;;;;;;;;;;iDAY9B,WAAW,CAAC,SAAS;MAChE,IAAI,CAAC,cAAc,IAAI,WAAW,CAAC,SAAS;;EAEhD,WAAW,CAAC,iBAAiB;YAC7B,CAAC,CAAC,yBAAyB,WAAW,CAAC,iBAAiB,KAAK,WAAW,CAAC,eAAe,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,WAAW,GAAG;YACpH,CAAC,CAAC,+CAA+C;CAClD,CAAC;QAEE,MAAM,UAAU,GAAG,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,WAAW,CAAC,CAAC;QACvD,MAAM,EAAE,CAAC,SAAS,CAAC,UAAU,EAAE,aAAa,EAAE,OAAO,CAAC,CAAC;QAEvD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,cAAc,IAAI,WAAW,CAAC,SAAS,YAAY,CAAC,CAAC;QAE1F,OAAO,WAAW,WAAW,YAAY,CAAC;IAC5C,CAAC;IAED;;OAEG;IACK,oBAAoB,CAAC,MAAwB;QACnD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,0CAA0C,CAAC,CAAC;QAC5D,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;QAC3E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,2BAA2B,MAAM,CAAC,aAAa,EAAE,CAAC,CAAC;QACnE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,eAAe,EAAE,CAAC,CAAC;QACzD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,wBAAwB,MAAM,CAAC,aAAa,CAAC,MAAM,EAAE,CAAC,CAAC;QACvE,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QAEpB,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YAC3E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YAE3E,KAAK,MAAM,IAAI,IAAI,MAAM,CAAC,aAAa,EAAE,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;gBACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,YAAY,IAAI,CAAC,SAAS,EAAE,CAAC,CAAC;gBAC9C,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,SAAS,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;gBACtC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,gBAAgB,IAAI,CAAC,WAAW,EAAE,CAAC,CAAC;gBACpD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,oBAAoB,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBAC1E,IAAI,IAAI,CAAC,iBAAiB,EAAE,CAAC;oBAC3B,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,qBAAqB,IAAI,CAAC,iBAAiB,KAAK,IAAI,CAAC,eAAe,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,aAAa,GAAG,CAAC,CAAC;gBACxH,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,MAAM,CAAC,OAAO,IAAI,MAAM,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YAChD,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;YACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YAC3E,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC;YACrC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;YAE3E,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;gBACpC,MAAM,IAAI,GAAG,MAAM,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC;gBACxC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,IAAI,IAAI,MAAM,CAAC,SAAS,KAAK,MAAM,CAAC,MAAM,EAAE,CAAC,CAAC;gBACjE,IAAI,MAAM,CAAC,KAAK,EAAE,CAAC;oBACjB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,aAAa,MAAM,CAAC,KAAK,EAAE,CAAC,CAAC;gBAC/C,CAAC;YACH,CAAC;QACH,CAAC;QAED,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC;QACpB,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,yDAAyD,CAAC,CAAC;IAC7E,CAAC;IAED;;;OAGG;IACH,KAAK,CAAC,gBAAgB;QACpB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC;IACzC,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,mBAAmB;QACvB,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,CAAC;QAC1C,OAAO,MAAM,CAAC,aAAa;aACxB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,wBAAwB,CAAC;aAChD,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC;IAC3B,CAAC;CACF"}
@@ -17,5 +17,6 @@ export { ContentClassifier } from './content-classifier.js';
17
17
  export { ProjectDetector } from './project-detector.js';
18
18
  export { ContentDistributor } from './content-distributor.js';
19
19
  export { CrossLinker } from './cross-linker.js';
20
+ export { FeatureConsistencyValidator } from './feature-consistency-validator.js';
20
21
  export * from './types.js';
21
22
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/living-docs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/core/living-docs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAOH,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,cAAc,YAAY,CAAC"}
@@ -21,5 +21,6 @@ export { ContentClassifier } from './content-classifier.js';
21
21
  export { ProjectDetector } from './project-detector.js';
22
22
  export { ContentDistributor } from './content-distributor.js';
23
23
  export { CrossLinker } from './cross-linker.js';
24
+ export { FeatureConsistencyValidator } from './feature-consistency-validator.js';
24
25
  export * from './types.js';
25
26
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/living-docs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gEAAgE;AAChE,kDAAkD;AAClD,2DAA2D;AAE3D,0DAA0D;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,cAAc,YAAY,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/core/living-docs/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;GAWG;AAEH,gEAAgE;AAChE,kDAAkD;AAClD,2DAA2D;AAE3D,0DAA0D;AAC1D,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAsB,CAAC;AAEvD,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,aAAa,EAAE,MAAM,qBAAqB,CAAC;AACpD,OAAO,EAAE,iBAAiB,EAAE,MAAM,yBAAyB,CAAC;AAC5D,OAAO,EAAE,eAAe,EAAE,MAAM,uBAAuB,CAAC;AACxD,OAAO,EAAE,kBAAkB,EAAE,MAAM,0BAA0B,CAAC;AAC9D,OAAO,EAAE,WAAW,EAAE,MAAM,mBAAmB,CAAC;AAChD,OAAO,EAAE,2BAA2B,EAAE,MAAM,oCAAoC,CAAC;AACjF,cAAc,YAAY,CAAC"}
@@ -3,8 +3,13 @@
3
3
  *
4
4
  * Syncs increment specs to living docs structure:
5
5
  * - .specweave/docs/internal/specs/_features/FS-XXX/FEATURE.md
6
- * - .specweave/docs/internal/specs/specweave/FS-XXX/README.md
7
- * - .specweave/docs/internal/specs/specweave/FS-XXX/us-*.md
6
+ * - .specweave/docs/internal/specs/{project}/FS-XXX/README.md
7
+ * - .specweave/docs/internal/specs/{project}/FS-XXX/us-*.md
8
+ *
9
+ * Project folder is auto-detected from:
10
+ * 1. Git remote (GitHub repo name)
11
+ * 2. Sync configuration (JIRA/ADO project)
12
+ * 3. "default" (fallback)
8
13
  *
9
14
  * Uses FeatureIDManager for automatic feature ID assignment (greenfield vs brownfield)
10
15
  */
@@ -59,9 +64,19 @@ export declare class LivingDocsSync {
59
64
  private projectRoot;
60
65
  private featureIdManager;
61
66
  private logger;
67
+ private projectId;
62
68
  constructor(projectRoot: string, options?: {
63
69
  logger?: Logger;
64
70
  });
71
+ /**
72
+ * Get current project ID
73
+ *
74
+ * Priority:
75
+ * 1. Git remote (GitHub repo name)
76
+ * 2. Sync configuration (JIRA/ADO project)
77
+ * 3. "default" (fallback)
78
+ */
79
+ getProjectId(): string;
65
80
  /**
66
81
  * Check if increment is archived
67
82
  *
@@ -221,5 +236,18 @@ export declare class LivingDocsSync {
221
236
  * - Any other temporary files
222
237
  */
223
238
  private cleanupTempFiles;
239
+ /**
240
+ * Validate and repair consistency between _features and project folders
241
+ *
242
+ * CRITICAL FIX (2025-11-25): Post-sync validation to prevent orphaned folders
243
+ *
244
+ * This method:
245
+ * 1. Checks if the just-synced feature exists in both _features/ and project folder
246
+ * 2. Auto-repairs if discrepancy found (creates missing project folder)
247
+ * 3. Logs warnings for manual intervention if auto-repair not possible
248
+ *
249
+ * @param featureId - Feature ID that was just synced (e.g., "FS-062")
250
+ */
251
+ private validateAndRepairConsistency;
224
252
  }
225
253
  //# sourceMappingURL=living-docs-sync.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"living-docs-sync.d.ts","sourceRoot":"","sources":["../../../../src/core/living-docs/living-docs-sync.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"living-docs-sync.d.ts","sourceRoot":"","sources":["../../../../src/core/living-docs/living-docs-sync.ts"],"names":[],"mappings":"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"}