specweave 0.28.68 → 0.29.0
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.md +3 -2
- package/README.md +19 -2
- package/dist/src/cli/commands/discrepancies.d.ts +89 -0
- package/dist/src/cli/commands/discrepancies.d.ts.map +1 -0
- package/dist/src/cli/commands/discrepancies.js +385 -0
- package/dist/src/cli/commands/discrepancies.js.map +1 -0
- package/dist/src/cli/commands/notifications.d.ts +70 -0
- package/dist/src/cli/commands/notifications.d.ts.map +1 -0
- package/dist/src/cli/commands/notifications.js +236 -0
- package/dist/src/cli/commands/notifications.js.map +1 -0
- package/dist/src/cli/commands/sync-logs.d.ts +54 -0
- package/dist/src/cli/commands/sync-logs.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-logs.js +240 -0
- package/dist/src/cli/commands/sync-logs.js.map +1 -0
- package/dist/src/cli/commands/sync-monitor.d.ts +42 -0
- package/dist/src/cli/commands/sync-monitor.d.ts.map +1 -0
- package/dist/src/cli/commands/sync-monitor.js +191 -0
- package/dist/src/cli/commands/sync-monitor.js.map +1 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.d.ts +45 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.d.ts.map +1 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.js +431 -0
- package/dist/src/cli/helpers/init/brownfield-analysis.js.map +1 -0
- package/dist/src/cli/helpers/init/index.d.ts +1 -0
- package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
- package/dist/src/cli/helpers/init/index.js +2 -0
- package/dist/src/cli/helpers/init/index.js.map +1 -1
- package/dist/src/cli/workers/brownfield-worker.d.ts +66 -0
- package/dist/src/cli/workers/brownfield-worker.d.ts.map +1 -0
- package/dist/src/cli/workers/brownfield-worker.js +417 -0
- package/dist/src/cli/workers/brownfield-worker.js.map +1 -0
- package/dist/src/core/background/brownfield-launcher.d.ts +86 -0
- package/dist/src/core/background/brownfield-launcher.d.ts.map +1 -0
- package/dist/src/core/background/brownfield-launcher.js +295 -0
- package/dist/src/core/background/brownfield-launcher.js.map +1 -0
- package/dist/src/core/background/index.d.ts +2 -0
- package/dist/src/core/background/index.d.ts.map +1 -1
- package/dist/src/core/background/index.js +2 -0
- package/dist/src/core/background/index.js.map +1 -1
- package/dist/src/core/background/types.d.ts +23 -2
- package/dist/src/core/background/types.d.ts.map +1 -1
- package/dist/src/core/config/index.d.ts +1 -0
- package/dist/src/core/config/index.d.ts.map +1 -1
- package/dist/src/core/config/index.js +1 -0
- package/dist/src/core/config/index.js.map +1 -1
- package/dist/src/core/config/types.d.ts +6 -0
- package/dist/src/core/config/types.d.ts.map +1 -1
- package/dist/src/core/config/types.js.map +1 -1
- package/dist/src/core/dashboard/dashboard-data.d.ts +156 -0
- package/dist/src/core/dashboard/dashboard-data.d.ts.map +1 -0
- package/dist/src/core/dashboard/dashboard-data.js +191 -0
- package/dist/src/core/dashboard/dashboard-data.js.map +1 -0
- package/dist/src/core/dashboard/index.d.ts +9 -0
- package/dist/src/core/dashboard/index.d.ts.map +1 -0
- package/dist/src/core/dashboard/index.js +9 -0
- package/dist/src/core/dashboard/index.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts +77 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js +286 -0
- package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/index.d.ts +8 -0
- package/dist/src/core/discrepancy/analyzers/index.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/index.js +8 -0
- package/dist/src/core/discrepancy/analyzers/index.js.map +1 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts +96 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts.map +1 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js +247 -0
- package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js.map +1 -0
- package/dist/src/core/discrepancy/brownfield-manager.d.ts +88 -0
- package/dist/src/core/discrepancy/brownfield-manager.d.ts.map +1 -0
- package/dist/src/core/discrepancy/brownfield-manager.js +520 -0
- package/dist/src/core/discrepancy/brownfield-manager.js.map +1 -0
- package/dist/src/core/discrepancy/brownfield-types.d.ts +174 -0
- package/dist/src/core/discrepancy/brownfield-types.d.ts.map +1 -0
- package/dist/src/core/discrepancy/brownfield-types.js +11 -0
- package/dist/src/core/discrepancy/brownfield-types.js.map +1 -0
- package/dist/src/core/discrepancy/detector.d.ts +92 -0
- package/dist/src/core/discrepancy/detector.d.ts.map +1 -0
- package/dist/src/core/discrepancy/detector.js +346 -0
- package/dist/src/core/discrepancy/detector.js.map +1 -0
- package/dist/src/core/discrepancy/increment-generator.d.ts +51 -0
- package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -0
- package/dist/src/core/discrepancy/increment-generator.js +234 -0
- package/dist/src/core/discrepancy/increment-generator.js.map +1 -0
- package/dist/src/core/discrepancy/index.d.ts +18 -0
- package/dist/src/core/discrepancy/index.d.ts.map +1 -0
- package/dist/src/core/discrepancy/index.js +24 -0
- package/dist/src/core/discrepancy/index.js.map +1 -0
- package/dist/src/core/discrepancy/severity-classifier.d.ts +81 -0
- package/dist/src/core/discrepancy/severity-classifier.d.ts.map +1 -0
- package/dist/src/core/discrepancy/severity-classifier.js +289 -0
- package/dist/src/core/discrepancy/severity-classifier.js.map +1 -0
- package/dist/src/core/discrepancy/spec-parser.d.ts +74 -0
- package/dist/src/core/discrepancy/spec-parser.d.ts.map +1 -0
- package/dist/src/core/discrepancy/spec-parser.js +213 -0
- package/dist/src/core/discrepancy/spec-parser.js.map +1 -0
- package/dist/src/core/discrepancy/update-recommender.d.ts +77 -0
- package/dist/src/core/discrepancy/update-recommender.d.ts.map +1 -0
- package/dist/src/core/discrepancy/update-recommender.js +323 -0
- package/dist/src/core/discrepancy/update-recommender.js.map +1 -0
- package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -16
- package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
- package/dist/src/core/living-docs/living-docs-sync.js +31 -112
- package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
- package/dist/src/core/logs/index.d.ts +10 -0
- package/dist/src/core/logs/index.d.ts.map +1 -0
- package/dist/src/core/logs/index.js +10 -0
- package/dist/src/core/logs/index.js.map +1 -0
- package/dist/src/core/logs/log-aggregator.d.ts +130 -0
- package/dist/src/core/logs/log-aggregator.d.ts.map +1 -0
- package/dist/src/core/logs/log-aggregator.js +206 -0
- package/dist/src/core/logs/log-aggregator.js.map +1 -0
- package/dist/src/core/logs/log-exporter.d.ts +81 -0
- package/dist/src/core/logs/log-exporter.d.ts.map +1 -0
- package/dist/src/core/logs/log-exporter.js +141 -0
- package/dist/src/core/logs/log-exporter.js.map +1 -0
- package/dist/src/core/notifications/command-integration.d.ts +82 -0
- package/dist/src/core/notifications/command-integration.d.ts.map +1 -0
- package/dist/src/core/notifications/command-integration.js +80 -0
- package/dist/src/core/notifications/command-integration.js.map +1 -0
- package/dist/src/core/notifications/index.d.ts +12 -0
- package/dist/src/core/notifications/index.d.ts.map +1 -0
- package/dist/src/core/notifications/index.js +12 -0
- package/dist/src/core/notifications/index.js.map +1 -0
- package/dist/src/core/notifications/notification-display.d.ts +70 -0
- package/dist/src/core/notifications/notification-display.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-display.js +177 -0
- package/dist/src/core/notifications/notification-display.js.map +1 -0
- package/dist/src/core/notifications/notification-manager.d.ts +126 -0
- package/dist/src/core/notifications/notification-manager.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-manager.js +287 -0
- package/dist/src/core/notifications/notification-manager.js.map +1 -0
- package/dist/src/core/notifications/notification-types.d.ts +159 -0
- package/dist/src/core/notifications/notification-types.d.ts.map +1 -0
- package/dist/src/core/notifications/notification-types.js +93 -0
- package/dist/src/core/notifications/notification-types.js.map +1 -0
- package/dist/src/core/scheduler/index.d.ts +11 -0
- package/dist/src/core/scheduler/index.d.ts.map +1 -0
- package/dist/src/core/scheduler/index.js +11 -0
- package/dist/src/core/scheduler/index.js.map +1 -0
- package/dist/src/core/scheduler/job-scheduler.d.ts +179 -0
- package/dist/src/core/scheduler/job-scheduler.d.ts.map +1 -0
- package/dist/src/core/scheduler/job-scheduler.js +282 -0
- package/dist/src/core/scheduler/job-scheduler.js.map +1 -0
- package/dist/src/core/scheduler/schedule-persistence.d.ts +83 -0
- package/dist/src/core/scheduler/schedule-persistence.d.ts.map +1 -0
- package/dist/src/core/scheduler/schedule-persistence.js +180 -0
- package/dist/src/core/scheduler/schedule-persistence.js.map +1 -0
- package/dist/src/core/scheduler/scheduled-job.d.ts +188 -0
- package/dist/src/core/scheduler/scheduled-job.d.ts.map +1 -0
- package/dist/src/core/scheduler/scheduled-job.js +182 -0
- package/dist/src/core/scheduler/scheduled-job.js.map +1 -0
- package/dist/src/core/sync/permission-enforcer.d.ts +206 -0
- package/dist/src/core/sync/permission-enforcer.d.ts.map +1 -0
- package/dist/src/core/sync/permission-enforcer.js +268 -0
- package/dist/src/core/sync/permission-enforcer.js.map +1 -0
- package/dist/src/core/sync/sync-audit-logger.d.ts +217 -0
- package/dist/src/core/sync/sync-audit-logger.d.ts.map +1 -0
- package/dist/src/core/sync/sync-audit-logger.js +327 -0
- package/dist/src/core/sync/sync-audit-logger.js.map +1 -0
- package/dist/src/core/sync/sync-interceptor.d.ts +190 -0
- package/dist/src/core/sync/sync-interceptor.d.ts.map +1 -0
- package/dist/src/core/sync/sync-interceptor.js +224 -0
- package/dist/src/core/sync/sync-interceptor.js.map +1 -0
- package/dist/src/core/types/increment-metadata.d.ts +5 -2
- package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
- package/dist/src/core/types/sync-config.d.ts +267 -0
- package/dist/src/core/types/sync-config.d.ts.map +1 -0
- package/dist/src/core/types/sync-config.js +304 -0
- package/dist/src/core/types/sync-config.js.map +1 -0
- package/dist/src/hooks/index.d.ts +11 -0
- package/dist/src/hooks/index.d.ts.map +1 -0
- package/dist/src/hooks/index.js +11 -0
- package/dist/src/hooks/index.js.map +1 -0
- package/dist/src/hooks/platform.d.ts +125 -0
- package/dist/src/hooks/platform.d.ts.map +1 -0
- package/dist/src/hooks/platform.js +325 -0
- package/dist/src/hooks/platform.js.map +1 -0
- package/dist/src/hooks/processor.d.ts +20 -0
- package/dist/src/hooks/processor.d.ts.map +1 -0
- package/dist/src/hooks/processor.js +317 -0
- package/dist/src/hooks/processor.js.map +1 -0
- package/dist/src/hooks/scheduler-startup.d.ts +19 -0
- package/dist/src/hooks/scheduler-startup.d.ts.map +1 -0
- package/dist/src/hooks/scheduler-startup.js +92 -0
- package/dist/src/hooks/scheduler-startup.js.map +1 -0
- package/dist/src/hooks/session-start.d.ts +16 -0
- package/dist/src/hooks/session-start.d.ts.map +1 -0
- package/dist/src/hooks/session-start.js +92 -0
- package/dist/src/hooks/session-start.js.map +1 -0
- package/dist/src/importers/duplicate-detector.d.ts +13 -2
- package/dist/src/importers/duplicate-detector.d.ts.map +1 -1
- package/dist/src/importers/duplicate-detector.js +21 -2
- package/dist/src/importers/duplicate-detector.js.map +1 -1
- package/dist/src/importers/item-converter.d.ts +41 -2
- package/dist/src/importers/item-converter.d.ts.map +1 -1
- package/dist/src/importers/item-converter.js +225 -38
- package/dist/src/importers/item-converter.js.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.d.ts +7 -0
- package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
- package/dist/src/living-docs/fs-id-allocator.js +30 -4
- package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
- package/dist/src/sync/ado-sync-wrapper.d.ts +137 -0
- package/dist/src/sync/ado-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/ado-sync-wrapper.js +148 -0
- package/dist/src/sync/ado-sync-wrapper.js.map +1 -0
- package/dist/src/sync/github-sync-wrapper.d.ts +195 -0
- package/dist/src/sync/github-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/github-sync-wrapper.js +220 -0
- package/dist/src/sync/github-sync-wrapper.js.map +1 -0
- package/dist/src/sync/jira-sync-wrapper.d.ts +155 -0
- package/dist/src/sync/jira-sync-wrapper.d.ts.map +1 -0
- package/dist/src/sync/jira-sync-wrapper.js +175 -0
- package/dist/src/sync/jira-sync-wrapper.js.map +1 -0
- package/dist/src/utils/feature-id-derivation.d.ts +58 -0
- package/dist/src/utils/feature-id-derivation.d.ts.map +1 -0
- package/dist/src/utils/feature-id-derivation.js +77 -0
- package/dist/src/utils/feature-id-derivation.js.map +1 -0
- package/package.json +1 -1
- package/plugins/specweave/commands/specweave-discrepancies.md +141 -0
- package/plugins/specweave/commands/specweave-discrepancy-to-increment.md +160 -0
- package/plugins/specweave/commands/specweave-jobs.md +45 -2
- package/plugins/specweave/commands/specweave-notifications.md +92 -0
- package/plugins/specweave/commands/specweave-sync-logs.md +131 -0
- package/plugins/specweave/commands/specweave-sync-monitor.md +57 -0
- package/plugins/specweave/hooks/hooks.json +3 -3
- package/plugins/specweave/hooks/lib/scheduler-startup.sh +72 -0
- package/plugins/specweave/hooks/universal/dispatcher.mjs +246 -0
- package/plugins/specweave/hooks/universal/session-start.cmd +16 -0
- package/plugins/specweave/hooks/universal/session-start.ps1 +16 -0
- package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +14 -5
- package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +5 -2
- package/plugins/specweave/skills/discrepancy-viewer.md +154 -0
- package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +34 -0
- package/plugins/specweave-release/hooks/.specweave/logs/dora-tracking.log +51 -0
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Severity Classifier
|
|
3
|
+
*
|
|
4
|
+
* Classifies discrepancy severity to determine appropriate action.
|
|
5
|
+
* Conservative by default: when uncertain, classify higher severity.
|
|
6
|
+
*
|
|
7
|
+
* @module core/discrepancy/severity-classifier
|
|
8
|
+
*/
|
|
9
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
10
|
+
/**
|
|
11
|
+
* Classifies discrepancy severity based on change type and details.
|
|
12
|
+
*/
|
|
13
|
+
export class SeverityClassifier {
|
|
14
|
+
constructor(options = {}) {
|
|
15
|
+
this.logger = options.logger ?? consoleLogger;
|
|
16
|
+
this.config = {
|
|
17
|
+
conservative: options.config?.conservative ?? true,
|
|
18
|
+
strictRemovals: options.config?.strictRemovals ?? true,
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Classify the severity of a discrepancy.
|
|
23
|
+
*/
|
|
24
|
+
classify(change) {
|
|
25
|
+
// Removal = breaking (might break consumers)
|
|
26
|
+
if (change.category === 'removed') {
|
|
27
|
+
return this.classifyRemoval(change);
|
|
28
|
+
}
|
|
29
|
+
// Addition = major (new undocumented functionality)
|
|
30
|
+
if (change.category === 'added') {
|
|
31
|
+
return this.classifyAddition(change);
|
|
32
|
+
}
|
|
33
|
+
// Modification = depends on what changed
|
|
34
|
+
return this.classifyModification(change);
|
|
35
|
+
}
|
|
36
|
+
classifyRemoval(change) {
|
|
37
|
+
if (this.config.strictRemovals) {
|
|
38
|
+
return {
|
|
39
|
+
severity: 'breaking',
|
|
40
|
+
reason: `${change.itemType} removed: ${change.specValue}`,
|
|
41
|
+
confidence: 'high',
|
|
42
|
+
};
|
|
43
|
+
}
|
|
44
|
+
// Check if it's a significant removal
|
|
45
|
+
if (change.itemType === 'api-route') {
|
|
46
|
+
return {
|
|
47
|
+
severity: 'breaking',
|
|
48
|
+
reason: `API route removed: ${change.specValue}`,
|
|
49
|
+
confidence: 'high',
|
|
50
|
+
};
|
|
51
|
+
}
|
|
52
|
+
if (change.itemType === 'function-signature') {
|
|
53
|
+
return {
|
|
54
|
+
severity: 'breaking',
|
|
55
|
+
reason: `Exported function removed: ${change.specValue}`,
|
|
56
|
+
confidence: 'high',
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
if (change.itemType === 'type-definition') {
|
|
60
|
+
return {
|
|
61
|
+
severity: 'major',
|
|
62
|
+
reason: `Type definition removed: ${change.specValue}`,
|
|
63
|
+
confidence: 'medium',
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
return {
|
|
67
|
+
severity: 'major',
|
|
68
|
+
reason: 'Item removed from codebase',
|
|
69
|
+
confidence: 'low',
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
classifyAddition(change) {
|
|
73
|
+
// New API routes are major (new functionality)
|
|
74
|
+
if (change.itemType === 'api-route') {
|
|
75
|
+
return {
|
|
76
|
+
severity: 'major',
|
|
77
|
+
reason: `New API route not documented: ${change.codeValue}`,
|
|
78
|
+
confidence: 'high',
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
// New exported functions are major
|
|
82
|
+
if (change.itemType === 'function-signature') {
|
|
83
|
+
return {
|
|
84
|
+
severity: 'major',
|
|
85
|
+
reason: `New exported function not documented: ${change.codeValue}`,
|
|
86
|
+
confidence: 'high',
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
// New types are minor (usually supporting types)
|
|
90
|
+
if (change.itemType === 'type-definition') {
|
|
91
|
+
return {
|
|
92
|
+
severity: 'minor',
|
|
93
|
+
reason: `New type definition not documented: ${change.codeValue}`,
|
|
94
|
+
confidence: 'medium',
|
|
95
|
+
};
|
|
96
|
+
}
|
|
97
|
+
return {
|
|
98
|
+
severity: 'minor',
|
|
99
|
+
reason: 'New item added to codebase',
|
|
100
|
+
confidence: 'low',
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
classifyModification(change) {
|
|
104
|
+
const description = change.description?.toLowerCase() ?? '';
|
|
105
|
+
// Check for trivial changes
|
|
106
|
+
if (this.isTrivialChange(change.specValue, change.codeValue, description)) {
|
|
107
|
+
return {
|
|
108
|
+
severity: 'trivial',
|
|
109
|
+
reason: 'Minor formatting or documentation change',
|
|
110
|
+
confidence: 'high',
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
// Check for breaking signature changes
|
|
114
|
+
if (this.isBreakingSignatureChange(change)) {
|
|
115
|
+
return {
|
|
116
|
+
severity: 'breaking',
|
|
117
|
+
reason: this.getBreakingChangeReason(change),
|
|
118
|
+
confidence: 'high',
|
|
119
|
+
};
|
|
120
|
+
}
|
|
121
|
+
// API route path changes
|
|
122
|
+
if (change.itemType === 'api-route') {
|
|
123
|
+
return this.classifyApiRouteChange(change);
|
|
124
|
+
}
|
|
125
|
+
// Function signature changes
|
|
126
|
+
if (change.itemType === 'function-signature') {
|
|
127
|
+
return this.classifyFunctionChange(change);
|
|
128
|
+
}
|
|
129
|
+
// Default to minor for modifications
|
|
130
|
+
return {
|
|
131
|
+
severity: this.config.conservative ? 'minor' : 'trivial',
|
|
132
|
+
reason: 'Modification detected',
|
|
133
|
+
confidence: 'low',
|
|
134
|
+
};
|
|
135
|
+
}
|
|
136
|
+
isTrivialChange(specValue, codeValue, description) {
|
|
137
|
+
// Normalize and compare
|
|
138
|
+
const normalizedSpec = this.normalize(specValue);
|
|
139
|
+
const normalizedCode = this.normalize(codeValue);
|
|
140
|
+
// If normalized values are same, it's just formatting
|
|
141
|
+
if (normalizedSpec === normalizedCode) {
|
|
142
|
+
return true;
|
|
143
|
+
}
|
|
144
|
+
// Check for typo indicators in description
|
|
145
|
+
if (description.includes('typo') || description.includes('whitespace')) {
|
|
146
|
+
return true;
|
|
147
|
+
}
|
|
148
|
+
return false;
|
|
149
|
+
}
|
|
150
|
+
normalize(value) {
|
|
151
|
+
return value
|
|
152
|
+
.toLowerCase()
|
|
153
|
+
.replace(/\s+/g, ' ')
|
|
154
|
+
.replace(/['"]/g, '')
|
|
155
|
+
.trim();
|
|
156
|
+
}
|
|
157
|
+
isBreakingSignatureChange(change) {
|
|
158
|
+
const description = change.description?.toLowerCase() ?? '';
|
|
159
|
+
// Return type changes are breaking
|
|
160
|
+
if (description.includes('return type')) {
|
|
161
|
+
return true;
|
|
162
|
+
}
|
|
163
|
+
// Required parameter additions are breaking
|
|
164
|
+
if (description.includes('required param')) {
|
|
165
|
+
return true;
|
|
166
|
+
}
|
|
167
|
+
// Parameter removal is breaking
|
|
168
|
+
if (description.includes('parameter count') && this.hasFewerParams(change)) {
|
|
169
|
+
return true;
|
|
170
|
+
}
|
|
171
|
+
return false;
|
|
172
|
+
}
|
|
173
|
+
hasFewerParams(change) {
|
|
174
|
+
// Extract param counts from description
|
|
175
|
+
const match = change.description?.match(/spec has (\d+), code has (\d+)/);
|
|
176
|
+
if (match) {
|
|
177
|
+
const specCount = parseInt(match[1], 10);
|
|
178
|
+
const codeCount = parseInt(match[2], 10);
|
|
179
|
+
return codeCount < specCount;
|
|
180
|
+
}
|
|
181
|
+
return false;
|
|
182
|
+
}
|
|
183
|
+
getBreakingChangeReason(change) {
|
|
184
|
+
const description = change.description ?? '';
|
|
185
|
+
if (description.includes('return type')) {
|
|
186
|
+
return `Breaking: ${description}`;
|
|
187
|
+
}
|
|
188
|
+
if (description.includes('required param')) {
|
|
189
|
+
return `Breaking: New required parameter added`;
|
|
190
|
+
}
|
|
191
|
+
if (description.includes('parameter count')) {
|
|
192
|
+
return `Breaking: ${description}`;
|
|
193
|
+
}
|
|
194
|
+
return 'Breaking signature change detected';
|
|
195
|
+
}
|
|
196
|
+
classifyApiRouteChange(change) {
|
|
197
|
+
const specPath = this.extractPath(change.specValue);
|
|
198
|
+
const codePath = this.extractPath(change.codeValue);
|
|
199
|
+
// Version change (v1 -> v2) is major
|
|
200
|
+
if (this.isVersionChange(specPath, codePath)) {
|
|
201
|
+
return {
|
|
202
|
+
severity: 'major',
|
|
203
|
+
reason: `API version changed: ${specPath} → ${codePath}`,
|
|
204
|
+
confidence: 'high',
|
|
205
|
+
};
|
|
206
|
+
}
|
|
207
|
+
// Path structure change is major
|
|
208
|
+
if (this.isPathStructureChange(specPath, codePath)) {
|
|
209
|
+
return {
|
|
210
|
+
severity: 'major',
|
|
211
|
+
reason: `API path structure changed: ${specPath} → ${codePath}`,
|
|
212
|
+
confidence: 'medium',
|
|
213
|
+
};
|
|
214
|
+
}
|
|
215
|
+
// Param name change is minor
|
|
216
|
+
return {
|
|
217
|
+
severity: 'minor',
|
|
218
|
+
reason: `API route modified: ${change.description ?? 'path changed'}`,
|
|
219
|
+
confidence: 'medium',
|
|
220
|
+
};
|
|
221
|
+
}
|
|
222
|
+
classifyFunctionChange(change) {
|
|
223
|
+
const description = change.description?.toLowerCase() ?? '';
|
|
224
|
+
// Parameter type changes are minor (TypeScript will catch issues)
|
|
225
|
+
if (description.includes('parameter') && !description.includes('count')) {
|
|
226
|
+
return {
|
|
227
|
+
severity: 'minor',
|
|
228
|
+
reason: 'Parameter type or name changed',
|
|
229
|
+
confidence: 'medium',
|
|
230
|
+
};
|
|
231
|
+
}
|
|
232
|
+
// Optional parameter additions are minor
|
|
233
|
+
if (description.includes('optional')) {
|
|
234
|
+
return {
|
|
235
|
+
severity: 'minor',
|
|
236
|
+
reason: 'Optional parameter added',
|
|
237
|
+
confidence: 'high',
|
|
238
|
+
};
|
|
239
|
+
}
|
|
240
|
+
return {
|
|
241
|
+
severity: this.config.conservative ? 'minor' : 'trivial',
|
|
242
|
+
reason: 'Function signature modified',
|
|
243
|
+
confidence: 'low',
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
extractPath(value) {
|
|
247
|
+
// Extract path from "METHOD /path" format
|
|
248
|
+
const match = value.match(/(?:GET|POST|PUT|DELETE|PATCH)\s+(\S+)/i);
|
|
249
|
+
return match ? match[1] : value;
|
|
250
|
+
}
|
|
251
|
+
isVersionChange(specPath, codePath) {
|
|
252
|
+
const versionPattern = /\/v(\d+)\//;
|
|
253
|
+
const specVersion = specPath.match(versionPattern);
|
|
254
|
+
const codeVersion = codePath.match(versionPattern);
|
|
255
|
+
if (specVersion && codeVersion) {
|
|
256
|
+
return specVersion[1] !== codeVersion[1];
|
|
257
|
+
}
|
|
258
|
+
// New version added where none existed
|
|
259
|
+
if (!specVersion && codeVersion) {
|
|
260
|
+
return true;
|
|
261
|
+
}
|
|
262
|
+
return false;
|
|
263
|
+
}
|
|
264
|
+
isPathStructureChange(specPath, codePath) {
|
|
265
|
+
// Normalize paths for comparison
|
|
266
|
+
const specParts = specPath.split('/').filter(Boolean);
|
|
267
|
+
const codeParts = codePath.split('/').filter(Boolean);
|
|
268
|
+
// Different segment count (excluding params)
|
|
269
|
+
const specSegments = specParts.filter(p => !p.startsWith(':'));
|
|
270
|
+
const codeSegments = codeParts.filter(p => !p.startsWith(':'));
|
|
271
|
+
return specSegments.length !== codeSegments.length;
|
|
272
|
+
}
|
|
273
|
+
/**
|
|
274
|
+
* Map severity to recommended action.
|
|
275
|
+
*/
|
|
276
|
+
getRecommendation(severity) {
|
|
277
|
+
switch (severity) {
|
|
278
|
+
case 'trivial':
|
|
279
|
+
return 'auto-update';
|
|
280
|
+
case 'minor':
|
|
281
|
+
return 'review-required';
|
|
282
|
+
case 'major':
|
|
283
|
+
return 'notify';
|
|
284
|
+
case 'breaking':
|
|
285
|
+
return 'alert';
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
//# sourceMappingURL=severity-classifier.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"severity-classifier.js","sourceRoot":"","sources":["../../../../src/core/discrepancy/severity-classifier.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses living docs to extract documented API endpoints and function signatures.
|
|
5
|
+
*
|
|
6
|
+
* @module core/discrepancy/spec-parser
|
|
7
|
+
*/
|
|
8
|
+
import { Logger } from '../../utils/logger.js';
|
|
9
|
+
/**
|
|
10
|
+
* Type of specification (API route or function).
|
|
11
|
+
*/
|
|
12
|
+
export type SpecType = 'api' | 'function' | 'type';
|
|
13
|
+
/**
|
|
14
|
+
* Represents a parsed specification from living docs.
|
|
15
|
+
*/
|
|
16
|
+
export interface ParsedSpec {
|
|
17
|
+
type: SpecType;
|
|
18
|
+
source: string;
|
|
19
|
+
lineNumber: number;
|
|
20
|
+
identifier: string;
|
|
21
|
+
description: string;
|
|
22
|
+
method?: string;
|
|
23
|
+
params?: string[];
|
|
24
|
+
returnType?: string;
|
|
25
|
+
metadata?: Record<string, unknown>;
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* Configuration for the spec parser.
|
|
29
|
+
*/
|
|
30
|
+
export interface SpecParserConfig {
|
|
31
|
+
/** Base path for living docs */
|
|
32
|
+
docsPath?: string;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Result of spec parsing.
|
|
36
|
+
*/
|
|
37
|
+
export interface SpecParseResult {
|
|
38
|
+
specs: ParsedSpec[];
|
|
39
|
+
errors: string[];
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* Parses living docs to extract documented behavior.
|
|
43
|
+
*/
|
|
44
|
+
export declare class SpecParser {
|
|
45
|
+
private readonly logger;
|
|
46
|
+
private readonly config;
|
|
47
|
+
constructor(options?: {
|
|
48
|
+
logger?: Logger;
|
|
49
|
+
config?: SpecParserConfig;
|
|
50
|
+
});
|
|
51
|
+
/**
|
|
52
|
+
* Parse all specs from the living docs directory.
|
|
53
|
+
*/
|
|
54
|
+
parseAll(docsPath?: string): Promise<SpecParseResult>;
|
|
55
|
+
/**
|
|
56
|
+
* Parse a single markdown file for specs.
|
|
57
|
+
*/
|
|
58
|
+
parseFile(filePath: string): Promise<SpecParseResult>;
|
|
59
|
+
/**
|
|
60
|
+
* Parse API specs from a docs path.
|
|
61
|
+
*/
|
|
62
|
+
parseApiSpecs(docsPath: string): Promise<ParsedSpec[]>;
|
|
63
|
+
/**
|
|
64
|
+
* Parse function specs from a docs path.
|
|
65
|
+
*/
|
|
66
|
+
parseFunctionSpecs(docsPath: string): Promise<ParsedSpec[]>;
|
|
67
|
+
private parseApiLine;
|
|
68
|
+
private parseFunctionLine;
|
|
69
|
+
private parseTypeLine;
|
|
70
|
+
private extractDescription;
|
|
71
|
+
private extractRouteParams;
|
|
72
|
+
private findMarkdownFiles;
|
|
73
|
+
}
|
|
74
|
+
//# sourceMappingURL=spec-parser.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-parser.d.ts","sourceRoot":"","sources":["../../../../src/core/discrepancy/spec-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAIH,OAAO,EAAE,MAAM,EAAiB,MAAM,uBAAuB,CAAC;AAE9D;;GAEG;AACH,MAAM,MAAM,QAAQ,GAAG,KAAK,GAAG,UAAU,GAAG,MAAM,CAAC;AAEnD;;GAEG;AACH,MAAM,WAAW,UAAU;IACzB,IAAI,EAAE,QAAQ,CAAC;IACf,MAAM,EAAE,MAAM,CAAC;IACf,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,MAAM,CAAC;IACpB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,EAAE,CAAC;IAClB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,QAAQ,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;CACpC;AAED;;GAEG;AACH,MAAM,WAAW,gBAAgB;IAC/B,gCAAgC;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED;;GAEG;AACH,MAAM,WAAW,eAAe;IAC9B,KAAK,EAAE,UAAU,EAAE,CAAC;IACpB,MAAM,EAAE,MAAM,EAAE,CAAC;CAClB;AAED;;GAEG;AACH,qBAAa,UAAU;IACrB,OAAO,CAAC,QAAQ,CAAC,MAAM,CAAS;IAChC,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA6B;gBAExC,OAAO,GAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,gBAAgB,CAAA;KAAO;IAOxE;;OAEG;IACG,QAAQ,CAAC,QAAQ,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IA2B3D;;OAEG;IACG,SAAS,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,eAAe,CAAC;IAyC3D;;OAEG;IACG,aAAa,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAK5D;;OAEG;IACG,kBAAkB,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,UAAU,EAAE,CAAC;IAKjE,OAAO,CAAC,YAAY;IAsBpB,OAAO,CAAC,iBAAiB;IA6BzB,OAAO,CAAC,aAAa;IAoBrB,OAAO,CAAC,kBAAkB;IA2B1B,OAAO,CAAC,kBAAkB;IAW1B,OAAO,CAAC,iBAAiB;CAwB1B"}
|
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Spec Parser
|
|
3
|
+
*
|
|
4
|
+
* Parses living docs to extract documented API endpoints and function signatures.
|
|
5
|
+
*
|
|
6
|
+
* @module core/discrepancy/spec-parser
|
|
7
|
+
*/
|
|
8
|
+
import * as fs from 'fs';
|
|
9
|
+
import * as path from 'path';
|
|
10
|
+
import { consoleLogger } from '../../utils/logger.js';
|
|
11
|
+
/**
|
|
12
|
+
* Parses living docs to extract documented behavior.
|
|
13
|
+
*/
|
|
14
|
+
export class SpecParser {
|
|
15
|
+
constructor(options = {}) {
|
|
16
|
+
this.logger = options.logger ?? consoleLogger;
|
|
17
|
+
this.config = {
|
|
18
|
+
docsPath: options.config?.docsPath ?? '.specweave/docs',
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* Parse all specs from the living docs directory.
|
|
23
|
+
*/
|
|
24
|
+
async parseAll(docsPath) {
|
|
25
|
+
const basePath = docsPath ?? this.config.docsPath;
|
|
26
|
+
const specs = [];
|
|
27
|
+
const errors = [];
|
|
28
|
+
if (!fs.existsSync(basePath)) {
|
|
29
|
+
errors.push(`Docs path not found: ${basePath}`);
|
|
30
|
+
return { specs, errors };
|
|
31
|
+
}
|
|
32
|
+
// Scan for markdown files
|
|
33
|
+
const files = this.findMarkdownFiles(basePath);
|
|
34
|
+
for (const file of files) {
|
|
35
|
+
try {
|
|
36
|
+
const result = await this.parseFile(file);
|
|
37
|
+
specs.push(...result.specs);
|
|
38
|
+
errors.push(...result.errors);
|
|
39
|
+
}
|
|
40
|
+
catch (error) {
|
|
41
|
+
const message = error instanceof Error ? error.message : String(error);
|
|
42
|
+
errors.push(`Failed to parse ${file}: ${message}`);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
return { specs, errors };
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Parse a single markdown file for specs.
|
|
49
|
+
*/
|
|
50
|
+
async parseFile(filePath) {
|
|
51
|
+
const specs = [];
|
|
52
|
+
const errors = [];
|
|
53
|
+
if (!fs.existsSync(filePath)) {
|
|
54
|
+
errors.push(`File not found: ${filePath}`);
|
|
55
|
+
return { specs, errors };
|
|
56
|
+
}
|
|
57
|
+
const content = fs.readFileSync(filePath, 'utf-8');
|
|
58
|
+
const lines = content.split('\n');
|
|
59
|
+
for (let i = 0; i < lines.length; i++) {
|
|
60
|
+
const line = lines[i];
|
|
61
|
+
// Parse API route documentation
|
|
62
|
+
const apiSpec = this.parseApiLine(line, i + 1, filePath);
|
|
63
|
+
if (apiSpec) {
|
|
64
|
+
// Look for description in following lines
|
|
65
|
+
apiSpec.description = this.extractDescription(lines, i + 1);
|
|
66
|
+
specs.push(apiSpec);
|
|
67
|
+
}
|
|
68
|
+
// Parse function documentation
|
|
69
|
+
const funcSpec = this.parseFunctionLine(line, i + 1, filePath);
|
|
70
|
+
if (funcSpec) {
|
|
71
|
+
funcSpec.description = this.extractDescription(lines, i + 1);
|
|
72
|
+
specs.push(funcSpec);
|
|
73
|
+
}
|
|
74
|
+
// Parse type documentation
|
|
75
|
+
const typeSpec = this.parseTypeLine(line, i + 1, filePath);
|
|
76
|
+
if (typeSpec) {
|
|
77
|
+
typeSpec.description = this.extractDescription(lines, i + 1);
|
|
78
|
+
specs.push(typeSpec);
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
return { specs, errors };
|
|
82
|
+
}
|
|
83
|
+
/**
|
|
84
|
+
* Parse API specs from a docs path.
|
|
85
|
+
*/
|
|
86
|
+
async parseApiSpecs(docsPath) {
|
|
87
|
+
const result = await this.parseAll(docsPath);
|
|
88
|
+
return result.specs.filter(s => s.type === 'api');
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Parse function specs from a docs path.
|
|
92
|
+
*/
|
|
93
|
+
async parseFunctionSpecs(docsPath) {
|
|
94
|
+
const result = await this.parseAll(docsPath);
|
|
95
|
+
return result.specs.filter(s => s.type === 'function');
|
|
96
|
+
}
|
|
97
|
+
parseApiLine(line, lineNumber, filePath) {
|
|
98
|
+
// Pattern: ## GET /users or ### POST /api/users
|
|
99
|
+
const apiPattern = /^#{2,4}\s+(GET|POST|PUT|DELETE|PATCH|HEAD|OPTIONS)\s+(\S+)/i;
|
|
100
|
+
const match = line.match(apiPattern);
|
|
101
|
+
if (!match)
|
|
102
|
+
return null;
|
|
103
|
+
const method = match[1].toUpperCase();
|
|
104
|
+
const routePath = match[2];
|
|
105
|
+
const params = this.extractRouteParams(routePath);
|
|
106
|
+
return {
|
|
107
|
+
type: 'api',
|
|
108
|
+
source: filePath,
|
|
109
|
+
lineNumber,
|
|
110
|
+
identifier: routePath,
|
|
111
|
+
description: '',
|
|
112
|
+
method,
|
|
113
|
+
params,
|
|
114
|
+
};
|
|
115
|
+
}
|
|
116
|
+
parseFunctionLine(line, lineNumber, filePath) {
|
|
117
|
+
// Pattern: ### functionName(param1: type, param2: type): returnType
|
|
118
|
+
// Or: ### `functionName(param1, param2)`
|
|
119
|
+
const funcPattern = /^#{2,4}\s+`?(\w+)\s*\(([^)]*)\)\s*(?::\s*(\w+))?`?/;
|
|
120
|
+
const match = line.match(funcPattern);
|
|
121
|
+
if (!match)
|
|
122
|
+
return null;
|
|
123
|
+
const name = match[1];
|
|
124
|
+
const paramsStr = match[2];
|
|
125
|
+
const returnType = match[3];
|
|
126
|
+
// Parse parameters
|
|
127
|
+
const params = paramsStr
|
|
128
|
+
.split(',')
|
|
129
|
+
.map(p => p.trim())
|
|
130
|
+
.filter(p => p.length > 0);
|
|
131
|
+
return {
|
|
132
|
+
type: 'function',
|
|
133
|
+
source: filePath,
|
|
134
|
+
lineNumber,
|
|
135
|
+
identifier: name,
|
|
136
|
+
description: '',
|
|
137
|
+
params,
|
|
138
|
+
returnType,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
parseTypeLine(line, lineNumber, filePath) {
|
|
142
|
+
// Pattern: ### interface TypeName or ### type TypeName
|
|
143
|
+
const typePattern = /^#{2,4}\s+(interface|type|class)\s+(\w+)/i;
|
|
144
|
+
const match = line.match(typePattern);
|
|
145
|
+
if (!match)
|
|
146
|
+
return null;
|
|
147
|
+
const kind = match[1].toLowerCase();
|
|
148
|
+
const name = match[2];
|
|
149
|
+
return {
|
|
150
|
+
type: 'type',
|
|
151
|
+
source: filePath,
|
|
152
|
+
lineNumber,
|
|
153
|
+
identifier: name,
|
|
154
|
+
description: '',
|
|
155
|
+
metadata: { kind },
|
|
156
|
+
};
|
|
157
|
+
}
|
|
158
|
+
extractDescription(lines, startIndex) {
|
|
159
|
+
const descriptionLines = [];
|
|
160
|
+
for (let i = startIndex; i < lines.length; i++) {
|
|
161
|
+
const line = lines[i];
|
|
162
|
+
// Stop at next heading
|
|
163
|
+
if (/^#{1,6}\s/.test(line))
|
|
164
|
+
break;
|
|
165
|
+
// Stop at empty line followed by heading
|
|
166
|
+
if (line.trim() === '' && i + 1 < lines.length && /^#{1,6}\s/.test(lines[i + 1]))
|
|
167
|
+
break;
|
|
168
|
+
// Skip empty lines at the start
|
|
169
|
+
if (descriptionLines.length === 0 && line.trim() === '')
|
|
170
|
+
continue;
|
|
171
|
+
// Add non-empty content
|
|
172
|
+
if (line.trim()) {
|
|
173
|
+
descriptionLines.push(line.trim());
|
|
174
|
+
}
|
|
175
|
+
// Stop after a few lines of description
|
|
176
|
+
if (descriptionLines.length >= 3)
|
|
177
|
+
break;
|
|
178
|
+
}
|
|
179
|
+
return descriptionLines.join(' ').slice(0, 500);
|
|
180
|
+
}
|
|
181
|
+
extractRouteParams(routePath) {
|
|
182
|
+
// Extract :param or {param} from path
|
|
183
|
+
const colonParams = routePath.match(/:([^/]+)/g) || [];
|
|
184
|
+
const braceParams = routePath.match(/\{([^}]+)\}/g) || [];
|
|
185
|
+
return [
|
|
186
|
+
...colonParams.map(p => p.slice(1)),
|
|
187
|
+
...braceParams.map(p => p.slice(1, -1)),
|
|
188
|
+
];
|
|
189
|
+
}
|
|
190
|
+
findMarkdownFiles(dir) {
|
|
191
|
+
const files = [];
|
|
192
|
+
const scan = (currentDir) => {
|
|
193
|
+
if (!fs.existsSync(currentDir))
|
|
194
|
+
return;
|
|
195
|
+
const entries = fs.readdirSync(currentDir, { withFileTypes: true });
|
|
196
|
+
for (const entry of entries) {
|
|
197
|
+
const fullPath = path.join(currentDir, entry.name);
|
|
198
|
+
if (entry.isDirectory()) {
|
|
199
|
+
// Skip common non-doc directories
|
|
200
|
+
if (['node_modules', '.git', 'dist', '_archive'].includes(entry.name))
|
|
201
|
+
continue;
|
|
202
|
+
scan(fullPath);
|
|
203
|
+
}
|
|
204
|
+
else if (entry.isFile() && entry.name.endsWith('.md')) {
|
|
205
|
+
files.push(fullPath);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
scan(dir);
|
|
210
|
+
return files;
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
//# sourceMappingURL=spec-parser.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"spec-parser.js","sourceRoot":"","sources":["../../../../src/core/discrepancy/spec-parser.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,MAAM,IAAI,CAAC;AACzB,OAAO,KAAK,IAAI,MAAM,MAAM,CAAC;AAC7B,OAAO,EAAU,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAsC9D;;GAEG;AACH,MAAM,OAAO,UAAU;IAIrB,YAAY,UAA0D,EAAE;QACtE,IAAI,CAAC,MAAM,GAAG,OAAO,CAAC,MAAM,IAAI,aAAa,CAAC;QAC9C,IAAI,CAAC,MAAM,GAAG;YACZ,QAAQ,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,IAAI,iBAAiB;SACxD,CAAC;IACJ,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,QAAQ,CAAC,QAAiB;QAC9B,MAAM,QAAQ,GAAG,QAAQ,IAAI,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC;QAClD,MAAM,KAAK,GAAiB,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,wBAAwB,QAAQ,EAAE,CAAC,CAAC;YAChD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC3B,CAAC;QAED,0BAA0B;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,iBAAiB,CAAC,QAAQ,CAAC,CAAC;QAE/C,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE,CAAC;YACzB,IAAI,CAAC;gBACH,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;gBAC1C,KAAK,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;gBAC5B,MAAM,CAAC,IAAI,CAAC,GAAG,MAAM,CAAC,MAAM,CAAC,CAAC;YAChC,CAAC;YAAC,OAAO,KAAK,EAAE,CAAC;gBACf,MAAM,OAAO,GAAG,KAAK,YAAY,KAAK,CAAC,CAAC,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;gBACvE,MAAM,CAAC,IAAI,CAAC,mBAAmB,IAAI,KAAK,OAAO,EAAE,CAAC,CAAC;YACrD,CAAC;QACH,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,SAAS,CAAC,QAAgB;QAC9B,MAAM,KAAK,GAAiB,EAAE,CAAC;QAC/B,MAAM,MAAM,GAAa,EAAE,CAAC;QAE5B,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,EAAE,CAAC;YAC7B,MAAM,CAAC,IAAI,CAAC,mBAAmB,QAAQ,EAAE,CAAC,CAAC;YAC3C,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;QAC3B,CAAC;QAED,MAAM,OAAO,GAAG,EAAE,CAAC,YAAY,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;QACnD,MAAM,KAAK,GAAG,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QAElC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YACtC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,gCAAgC;YAChC,MAAM,OAAO,GAAG,IAAI,CAAC,YAAY,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YACzD,IAAI,OAAO,EAAE,CAAC;gBACZ,0CAA0C;gBAC1C,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC5D,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;YACtB,CAAC;YAED,+BAA+B;YAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,iBAAiB,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC/D,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;YAED,2BAA2B;YAC3B,MAAM,QAAQ,GAAG,IAAI,CAAC,aAAa,CAAC,IAAI,EAAE,CAAC,GAAG,CAAC,EAAE,QAAQ,CAAC,CAAC;YAC3D,IAAI,QAAQ,EAAE,CAAC;gBACb,QAAQ,CAAC,WAAW,GAAG,IAAI,CAAC,kBAAkB,CAAC,KAAK,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC;gBAC7D,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACvB,CAAC;QACH,CAAC;QAED,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC;IAC3B,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,aAAa,CAAC,QAAgB;QAClC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,CAAC;IACpD,CAAC;IAED;;OAEG;IACH,KAAK,CAAC,kBAAkB,CAAC,QAAgB;QACvC,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC;QAC7C,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,UAAU,CAAC,CAAC;IACzD,CAAC;IAEO,YAAY,CAAC,IAAY,EAAE,UAAkB,EAAE,QAAgB;QACrE,gDAAgD;QAChD,MAAM,UAAU,GAAG,6DAA6D,CAAC;QACjF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC;QAErC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,MAAM,MAAM,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACtC,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,MAAM,GAAG,IAAI,CAAC,kBAAkB,CAAC,SAAS,CAAC,CAAC;QAElD,OAAO;YACL,IAAI,EAAE,KAAK;YACX,MAAM,EAAE,QAAQ;YAChB,UAAU;YACV,UAAU,EAAE,SAAS;YACrB,WAAW,EAAE,EAAE;YACf,MAAM;YACN,MAAM;SACP,CAAC;IACJ,CAAC;IAEO,iBAAiB,CAAC,IAAY,EAAE,UAAkB,EAAE,QAAgB;QAC1E,oEAAoE;QACpE,yCAAyC;QACzC,MAAM,WAAW,GAAG,oDAAoD,CAAC;QACzE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QACtB,MAAM,SAAS,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAC3B,MAAM,UAAU,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAE5B,mBAAmB;QACnB,MAAM,MAAM,GAAG,SAAS;aACrB,KAAK,CAAC,GAAG,CAAC;aACV,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;aAClB,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC;QAE7B,OAAO;YACL,IAAI,EAAE,UAAU;YAChB,MAAM,EAAE,QAAQ;YAChB,UAAU;YACV,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,EAAE;YACf,MAAM;YACN,UAAU;SACX,CAAC;IACJ,CAAC;IAEO,aAAa,CAAC,IAAY,EAAE,UAAkB,EAAE,QAAgB;QACtE,uDAAuD;QACvD,MAAM,WAAW,GAAG,2CAA2C,CAAC;QAChE,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,WAAW,CAAC,CAAC;QAEtC,IAAI,CAAC,KAAK;YAAE,OAAO,IAAI,CAAC;QAExB,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC;QACpC,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAEtB,OAAO;YACL,IAAI,EAAE,MAAM;YACZ,MAAM,EAAE,QAAQ;YAChB,UAAU;YACV,UAAU,EAAE,IAAI;YAChB,WAAW,EAAE,EAAE;YACf,QAAQ,EAAE,EAAE,IAAI,EAAE;SACnB,CAAC;IACJ,CAAC;IAEO,kBAAkB,CAAC,KAAe,EAAE,UAAkB;QAC5D,MAAM,gBAAgB,GAAa,EAAE,CAAC;QAEtC,KAAK,IAAI,CAAC,GAAG,UAAU,EAAE,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE,CAAC;YAC/C,MAAM,IAAI,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;YAEtB,uBAAuB;YACvB,IAAI,WAAW,CAAC,IAAI,CAAC,IAAI,CAAC;gBAAE,MAAM;YAElC,yCAAyC;YACzC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,GAAG,CAAC,GAAG,KAAK,CAAC,MAAM,IAAI,WAAW,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;gBAAE,MAAM;YAExF,gCAAgC;YAChC,IAAI,gBAAgB,CAAC,MAAM,KAAK,CAAC,IAAI,IAAI,CAAC,IAAI,EAAE,KAAK,EAAE;gBAAE,SAAS;YAElE,wBAAwB;YACxB,IAAI,IAAI,CAAC,IAAI,EAAE,EAAE,CAAC;gBAChB,gBAAgB,CAAC,IAAI,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC;YACrC,CAAC;YAED,wCAAwC;YACxC,IAAI,gBAAgB,CAAC,MAAM,IAAI,CAAC;gBAAE,MAAM;QAC1C,CAAC;QAED,OAAO,gBAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;IAClD,CAAC;IAEO,kBAAkB,CAAC,SAAiB;QAC1C,sCAAsC;QACtC,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,CAAC;QACvD,MAAM,WAAW,GAAG,SAAS,CAAC,KAAK,CAAC,cAAc,CAAC,IAAI,EAAE,CAAC;QAE1D,OAAO;YACL,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;YACnC,GAAG,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;SACxC,CAAC;IACJ,CAAC;IAEO,iBAAiB,CAAC,GAAW;QACnC,MAAM,KAAK,GAAa,EAAE,CAAC;QAE3B,MAAM,IAAI,GAAG,CAAC,UAAkB,EAAQ,EAAE;YACxC,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,UAAU,CAAC;gBAAE,OAAO;YAEvC,MAAM,OAAO,GAAG,EAAE,CAAC,WAAW,CAAC,UAAU,EAAE,EAAE,aAAa,EAAE,IAAI,EAAE,CAAC,CAAC;YAEpE,KAAK,MAAM,KAAK,IAAI,OAAO,EAAE,CAAC;gBAC5B,MAAM,QAAQ,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,KAAK,CAAC,IAAI,CAAC,CAAC;gBAEnD,IAAI,KAAK,CAAC,WAAW,EAAE,EAAE,CAAC;oBACxB,kCAAkC;oBAClC,IAAI,CAAC,cAAc,EAAE,MAAM,EAAE,MAAM,EAAE,UAAU,CAAC,CAAC,QAAQ,CAAC,KAAK,CAAC,IAAI,CAAC;wBAAE,SAAS;oBAChF,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACjB,CAAC;qBAAM,IAAI,KAAK,CAAC,MAAM,EAAE,IAAI,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,KAAK,CAAC,EAAE,CAAC;oBACxD,KAAK,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gBACvB,CAAC;YACH,CAAC;QACH,CAAC,CAAC;QAEF,IAAI,CAAC,GAAG,CAAC,CAAC;QACV,OAAO,KAAK,CAAC;IACf,CAAC;CACF"}
|