specweave 0.28.67 → 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.
Files changed (239) hide show
  1. package/CLAUDE.md +3 -2
  2. package/README.md +19 -2
  3. package/dist/src/cli/commands/discrepancies.d.ts +89 -0
  4. package/dist/src/cli/commands/discrepancies.d.ts.map +1 -0
  5. package/dist/src/cli/commands/discrepancies.js +385 -0
  6. package/dist/src/cli/commands/discrepancies.js.map +1 -0
  7. package/dist/src/cli/commands/notifications.d.ts +70 -0
  8. package/dist/src/cli/commands/notifications.d.ts.map +1 -0
  9. package/dist/src/cli/commands/notifications.js +236 -0
  10. package/dist/src/cli/commands/notifications.js.map +1 -0
  11. package/dist/src/cli/commands/sync-logs.d.ts +54 -0
  12. package/dist/src/cli/commands/sync-logs.d.ts.map +1 -0
  13. package/dist/src/cli/commands/sync-logs.js +240 -0
  14. package/dist/src/cli/commands/sync-logs.js.map +1 -0
  15. package/dist/src/cli/commands/sync-monitor.d.ts +42 -0
  16. package/dist/src/cli/commands/sync-monitor.d.ts.map +1 -0
  17. package/dist/src/cli/commands/sync-monitor.js +191 -0
  18. package/dist/src/cli/commands/sync-monitor.js.map +1 -0
  19. package/dist/src/cli/helpers/init/brownfield-analysis.d.ts +45 -0
  20. package/dist/src/cli/helpers/init/brownfield-analysis.d.ts.map +1 -0
  21. package/dist/src/cli/helpers/init/brownfield-analysis.js +431 -0
  22. package/dist/src/cli/helpers/init/brownfield-analysis.js.map +1 -0
  23. package/dist/src/cli/helpers/init/index.d.ts +1 -0
  24. package/dist/src/cli/helpers/init/index.d.ts.map +1 -1
  25. package/dist/src/cli/helpers/init/index.js +2 -0
  26. package/dist/src/cli/helpers/init/index.js.map +1 -1
  27. package/dist/src/cli/helpers/issue-tracker/ado.d.ts.map +1 -1
  28. package/dist/src/cli/helpers/issue-tracker/ado.js +14 -5
  29. package/dist/src/cli/helpers/issue-tracker/ado.js.map +1 -1
  30. package/dist/src/cli/workers/brownfield-worker.d.ts +66 -0
  31. package/dist/src/cli/workers/brownfield-worker.d.ts.map +1 -0
  32. package/dist/src/cli/workers/brownfield-worker.js +417 -0
  33. package/dist/src/cli/workers/brownfield-worker.js.map +1 -0
  34. package/dist/src/core/background/brownfield-launcher.d.ts +86 -0
  35. package/dist/src/core/background/brownfield-launcher.d.ts.map +1 -0
  36. package/dist/src/core/background/brownfield-launcher.js +295 -0
  37. package/dist/src/core/background/brownfield-launcher.js.map +1 -0
  38. package/dist/src/core/background/index.d.ts +2 -0
  39. package/dist/src/core/background/index.d.ts.map +1 -1
  40. package/dist/src/core/background/index.js +2 -0
  41. package/dist/src/core/background/index.js.map +1 -1
  42. package/dist/src/core/background/types.d.ts +23 -2
  43. package/dist/src/core/background/types.d.ts.map +1 -1
  44. package/dist/src/core/config/index.d.ts +1 -0
  45. package/dist/src/core/config/index.d.ts.map +1 -1
  46. package/dist/src/core/config/index.js +1 -0
  47. package/dist/src/core/config/index.js.map +1 -1
  48. package/dist/src/core/config/types.d.ts +6 -0
  49. package/dist/src/core/config/types.d.ts.map +1 -1
  50. package/dist/src/core/config/types.js.map +1 -1
  51. package/dist/src/core/dashboard/dashboard-data.d.ts +156 -0
  52. package/dist/src/core/dashboard/dashboard-data.d.ts.map +1 -0
  53. package/dist/src/core/dashboard/dashboard-data.js +191 -0
  54. package/dist/src/core/dashboard/dashboard-data.js.map +1 -0
  55. package/dist/src/core/dashboard/index.d.ts +9 -0
  56. package/dist/src/core/dashboard/index.d.ts.map +1 -0
  57. package/dist/src/core/dashboard/index.js +9 -0
  58. package/dist/src/core/dashboard/index.js.map +1 -0
  59. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts +77 -0
  60. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.d.ts.map +1 -0
  61. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js +286 -0
  62. package/dist/src/core/discrepancy/analyzers/api-route-analyzer.js.map +1 -0
  63. package/dist/src/core/discrepancy/analyzers/index.d.ts +8 -0
  64. package/dist/src/core/discrepancy/analyzers/index.d.ts.map +1 -0
  65. package/dist/src/core/discrepancy/analyzers/index.js +8 -0
  66. package/dist/src/core/discrepancy/analyzers/index.js.map +1 -0
  67. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts +96 -0
  68. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.d.ts.map +1 -0
  69. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js +247 -0
  70. package/dist/src/core/discrepancy/analyzers/typescript-analyzer.js.map +1 -0
  71. package/dist/src/core/discrepancy/brownfield-manager.d.ts +88 -0
  72. package/dist/src/core/discrepancy/brownfield-manager.d.ts.map +1 -0
  73. package/dist/src/core/discrepancy/brownfield-manager.js +520 -0
  74. package/dist/src/core/discrepancy/brownfield-manager.js.map +1 -0
  75. package/dist/src/core/discrepancy/brownfield-types.d.ts +174 -0
  76. package/dist/src/core/discrepancy/brownfield-types.d.ts.map +1 -0
  77. package/dist/src/core/discrepancy/brownfield-types.js +11 -0
  78. package/dist/src/core/discrepancy/brownfield-types.js.map +1 -0
  79. package/dist/src/core/discrepancy/detector.d.ts +92 -0
  80. package/dist/src/core/discrepancy/detector.d.ts.map +1 -0
  81. package/dist/src/core/discrepancy/detector.js +346 -0
  82. package/dist/src/core/discrepancy/detector.js.map +1 -0
  83. package/dist/src/core/discrepancy/increment-generator.d.ts +51 -0
  84. package/dist/src/core/discrepancy/increment-generator.d.ts.map +1 -0
  85. package/dist/src/core/discrepancy/increment-generator.js +234 -0
  86. package/dist/src/core/discrepancy/increment-generator.js.map +1 -0
  87. package/dist/src/core/discrepancy/index.d.ts +18 -0
  88. package/dist/src/core/discrepancy/index.d.ts.map +1 -0
  89. package/dist/src/core/discrepancy/index.js +24 -0
  90. package/dist/src/core/discrepancy/index.js.map +1 -0
  91. package/dist/src/core/discrepancy/severity-classifier.d.ts +81 -0
  92. package/dist/src/core/discrepancy/severity-classifier.d.ts.map +1 -0
  93. package/dist/src/core/discrepancy/severity-classifier.js +289 -0
  94. package/dist/src/core/discrepancy/severity-classifier.js.map +1 -0
  95. package/dist/src/core/discrepancy/spec-parser.d.ts +74 -0
  96. package/dist/src/core/discrepancy/spec-parser.d.ts.map +1 -0
  97. package/dist/src/core/discrepancy/spec-parser.js +213 -0
  98. package/dist/src/core/discrepancy/spec-parser.js.map +1 -0
  99. package/dist/src/core/discrepancy/update-recommender.d.ts +77 -0
  100. package/dist/src/core/discrepancy/update-recommender.d.ts.map +1 -0
  101. package/dist/src/core/discrepancy/update-recommender.js +323 -0
  102. package/dist/src/core/discrepancy/update-recommender.js.map +1 -0
  103. package/dist/src/core/living-docs/living-docs-sync.d.ts +13 -16
  104. package/dist/src/core/living-docs/living-docs-sync.d.ts.map +1 -1
  105. package/dist/src/core/living-docs/living-docs-sync.js +31 -112
  106. package/dist/src/core/living-docs/living-docs-sync.js.map +1 -1
  107. package/dist/src/core/logs/index.d.ts +10 -0
  108. package/dist/src/core/logs/index.d.ts.map +1 -0
  109. package/dist/src/core/logs/index.js +10 -0
  110. package/dist/src/core/logs/index.js.map +1 -0
  111. package/dist/src/core/logs/log-aggregator.d.ts +130 -0
  112. package/dist/src/core/logs/log-aggregator.d.ts.map +1 -0
  113. package/dist/src/core/logs/log-aggregator.js +206 -0
  114. package/dist/src/core/logs/log-aggregator.js.map +1 -0
  115. package/dist/src/core/logs/log-exporter.d.ts +81 -0
  116. package/dist/src/core/logs/log-exporter.d.ts.map +1 -0
  117. package/dist/src/core/logs/log-exporter.js +141 -0
  118. package/dist/src/core/logs/log-exporter.js.map +1 -0
  119. package/dist/src/core/notifications/command-integration.d.ts +82 -0
  120. package/dist/src/core/notifications/command-integration.d.ts.map +1 -0
  121. package/dist/src/core/notifications/command-integration.js +80 -0
  122. package/dist/src/core/notifications/command-integration.js.map +1 -0
  123. package/dist/src/core/notifications/index.d.ts +12 -0
  124. package/dist/src/core/notifications/index.d.ts.map +1 -0
  125. package/dist/src/core/notifications/index.js +12 -0
  126. package/dist/src/core/notifications/index.js.map +1 -0
  127. package/dist/src/core/notifications/notification-display.d.ts +70 -0
  128. package/dist/src/core/notifications/notification-display.d.ts.map +1 -0
  129. package/dist/src/core/notifications/notification-display.js +177 -0
  130. package/dist/src/core/notifications/notification-display.js.map +1 -0
  131. package/dist/src/core/notifications/notification-manager.d.ts +126 -0
  132. package/dist/src/core/notifications/notification-manager.d.ts.map +1 -0
  133. package/dist/src/core/notifications/notification-manager.js +287 -0
  134. package/dist/src/core/notifications/notification-manager.js.map +1 -0
  135. package/dist/src/core/notifications/notification-types.d.ts +159 -0
  136. package/dist/src/core/notifications/notification-types.d.ts.map +1 -0
  137. package/dist/src/core/notifications/notification-types.js +93 -0
  138. package/dist/src/core/notifications/notification-types.js.map +1 -0
  139. package/dist/src/core/scheduler/index.d.ts +11 -0
  140. package/dist/src/core/scheduler/index.d.ts.map +1 -0
  141. package/dist/src/core/scheduler/index.js +11 -0
  142. package/dist/src/core/scheduler/index.js.map +1 -0
  143. package/dist/src/core/scheduler/job-scheduler.d.ts +179 -0
  144. package/dist/src/core/scheduler/job-scheduler.d.ts.map +1 -0
  145. package/dist/src/core/scheduler/job-scheduler.js +282 -0
  146. package/dist/src/core/scheduler/job-scheduler.js.map +1 -0
  147. package/dist/src/core/scheduler/schedule-persistence.d.ts +83 -0
  148. package/dist/src/core/scheduler/schedule-persistence.d.ts.map +1 -0
  149. package/dist/src/core/scheduler/schedule-persistence.js +180 -0
  150. package/dist/src/core/scheduler/schedule-persistence.js.map +1 -0
  151. package/dist/src/core/scheduler/scheduled-job.d.ts +188 -0
  152. package/dist/src/core/scheduler/scheduled-job.d.ts.map +1 -0
  153. package/dist/src/core/scheduler/scheduled-job.js +182 -0
  154. package/dist/src/core/scheduler/scheduled-job.js.map +1 -0
  155. package/dist/src/core/sync/permission-enforcer.d.ts +206 -0
  156. package/dist/src/core/sync/permission-enforcer.d.ts.map +1 -0
  157. package/dist/src/core/sync/permission-enforcer.js +268 -0
  158. package/dist/src/core/sync/permission-enforcer.js.map +1 -0
  159. package/dist/src/core/sync/sync-audit-logger.d.ts +217 -0
  160. package/dist/src/core/sync/sync-audit-logger.d.ts.map +1 -0
  161. package/dist/src/core/sync/sync-audit-logger.js +327 -0
  162. package/dist/src/core/sync/sync-audit-logger.js.map +1 -0
  163. package/dist/src/core/sync/sync-interceptor.d.ts +190 -0
  164. package/dist/src/core/sync/sync-interceptor.d.ts.map +1 -0
  165. package/dist/src/core/sync/sync-interceptor.js +224 -0
  166. package/dist/src/core/sync/sync-interceptor.js.map +1 -0
  167. package/dist/src/core/types/increment-metadata.d.ts +5 -2
  168. package/dist/src/core/types/increment-metadata.d.ts.map +1 -1
  169. package/dist/src/core/types/sync-config.d.ts +267 -0
  170. package/dist/src/core/types/sync-config.d.ts.map +1 -0
  171. package/dist/src/core/types/sync-config.js +304 -0
  172. package/dist/src/core/types/sync-config.js.map +1 -0
  173. package/dist/src/hooks/index.d.ts +11 -0
  174. package/dist/src/hooks/index.d.ts.map +1 -0
  175. package/dist/src/hooks/index.js +11 -0
  176. package/dist/src/hooks/index.js.map +1 -0
  177. package/dist/src/hooks/platform.d.ts +125 -0
  178. package/dist/src/hooks/platform.d.ts.map +1 -0
  179. package/dist/src/hooks/platform.js +325 -0
  180. package/dist/src/hooks/platform.js.map +1 -0
  181. package/dist/src/hooks/processor.d.ts +20 -0
  182. package/dist/src/hooks/processor.d.ts.map +1 -0
  183. package/dist/src/hooks/processor.js +317 -0
  184. package/dist/src/hooks/processor.js.map +1 -0
  185. package/dist/src/hooks/scheduler-startup.d.ts +19 -0
  186. package/dist/src/hooks/scheduler-startup.d.ts.map +1 -0
  187. package/dist/src/hooks/scheduler-startup.js +92 -0
  188. package/dist/src/hooks/scheduler-startup.js.map +1 -0
  189. package/dist/src/hooks/session-start.d.ts +16 -0
  190. package/dist/src/hooks/session-start.d.ts.map +1 -0
  191. package/dist/src/hooks/session-start.js +92 -0
  192. package/dist/src/hooks/session-start.js.map +1 -0
  193. package/dist/src/importers/duplicate-detector.d.ts +13 -2
  194. package/dist/src/importers/duplicate-detector.d.ts.map +1 -1
  195. package/dist/src/importers/duplicate-detector.js +21 -2
  196. package/dist/src/importers/duplicate-detector.js.map +1 -1
  197. package/dist/src/importers/item-converter.d.ts +41 -2
  198. package/dist/src/importers/item-converter.d.ts.map +1 -1
  199. package/dist/src/importers/item-converter.js +231 -45
  200. package/dist/src/importers/item-converter.js.map +1 -1
  201. package/dist/src/living-docs/fs-id-allocator.d.ts +7 -0
  202. package/dist/src/living-docs/fs-id-allocator.d.ts.map +1 -1
  203. package/dist/src/living-docs/fs-id-allocator.js +30 -4
  204. package/dist/src/living-docs/fs-id-allocator.js.map +1 -1
  205. package/dist/src/sync/ado-sync-wrapper.d.ts +137 -0
  206. package/dist/src/sync/ado-sync-wrapper.d.ts.map +1 -0
  207. package/dist/src/sync/ado-sync-wrapper.js +148 -0
  208. package/dist/src/sync/ado-sync-wrapper.js.map +1 -0
  209. package/dist/src/sync/github-sync-wrapper.d.ts +195 -0
  210. package/dist/src/sync/github-sync-wrapper.d.ts.map +1 -0
  211. package/dist/src/sync/github-sync-wrapper.js +220 -0
  212. package/dist/src/sync/github-sync-wrapper.js.map +1 -0
  213. package/dist/src/sync/jira-sync-wrapper.d.ts +155 -0
  214. package/dist/src/sync/jira-sync-wrapper.d.ts.map +1 -0
  215. package/dist/src/sync/jira-sync-wrapper.js +175 -0
  216. package/dist/src/sync/jira-sync-wrapper.js.map +1 -0
  217. package/dist/src/utils/feature-id-derivation.d.ts +58 -0
  218. package/dist/src/utils/feature-id-derivation.d.ts.map +1 -0
  219. package/dist/src/utils/feature-id-derivation.js +77 -0
  220. package/dist/src/utils/feature-id-derivation.js.map +1 -0
  221. package/package.json +1 -1
  222. package/plugins/specweave/commands/specweave-discrepancies.md +141 -0
  223. package/plugins/specweave/commands/specweave-discrepancy-to-increment.md +160 -0
  224. package/plugins/specweave/commands/specweave-jobs.md +45 -2
  225. package/plugins/specweave/commands/specweave-notifications.md +92 -0
  226. package/plugins/specweave/commands/specweave-sync-logs.md +131 -0
  227. package/plugins/specweave/commands/specweave-sync-monitor.md +57 -0
  228. package/plugins/specweave/hooks/hooks.json +3 -3
  229. package/plugins/specweave/hooks/lib/scheduler-startup.sh +72 -0
  230. package/plugins/specweave/hooks/universal/dispatcher.mjs +246 -0
  231. package/plugins/specweave/hooks/universal/session-start.cmd +16 -0
  232. package/plugins/specweave/hooks/universal/session-start.ps1 +16 -0
  233. package/plugins/specweave/hooks/v2/dispatchers/session-start.sh +14 -5
  234. package/plugins/specweave/lib/vendor/core/types/increment-metadata.d.ts +5 -2
  235. package/plugins/specweave/skills/discrepancy-viewer.md +154 -0
  236. package/plugins/specweave-ado/lib/ado-project-detector.js +11 -5
  237. package/plugins/specweave-ado/lib/ado-project-detector.ts +16 -5
  238. package/plugins/specweave-github/hooks/.specweave/logs/hooks-debug.log +34 -0
  239. 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":"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"}