@buoy-design/cli 0.1.1 → 0.1.2

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 (119) hide show
  1. package/dist/commands/audit.d.ts +3 -0
  2. package/dist/commands/audit.d.ts.map +1 -0
  3. package/dist/commands/audit.js +235 -0
  4. package/dist/commands/audit.js.map +1 -0
  5. package/dist/commands/check.d.ts +16 -0
  6. package/dist/commands/check.d.ts.map +1 -0
  7. package/dist/commands/check.js +168 -0
  8. package/dist/commands/check.js.map +1 -0
  9. package/dist/commands/ci.d.ts.map +1 -1
  10. package/dist/commands/ci.js +85 -81
  11. package/dist/commands/ci.js.map +1 -1
  12. package/dist/commands/compare.d.ts +3 -0
  13. package/dist/commands/compare.d.ts.map +1 -0
  14. package/dist/commands/compare.js +170 -0
  15. package/dist/commands/compare.js.map +1 -0
  16. package/dist/commands/drift.d.ts.map +1 -1
  17. package/dist/commands/drift.js +40 -55
  18. package/dist/commands/drift.js.map +1 -1
  19. package/dist/commands/explain.d.ts +3 -0
  20. package/dist/commands/explain.d.ts.map +1 -0
  21. package/dist/commands/explain.js +212 -0
  22. package/dist/commands/explain.js.map +1 -0
  23. package/dist/commands/graph.d.ts +3 -0
  24. package/dist/commands/graph.d.ts.map +1 -0
  25. package/dist/commands/graph.js +430 -0
  26. package/dist/commands/graph.js.map +1 -0
  27. package/dist/commands/index.d.ts +6 -1
  28. package/dist/commands/index.d.ts.map +1 -1
  29. package/dist/commands/index.js +6 -1
  30. package/dist/commands/index.js.map +1 -1
  31. package/dist/commands/init.d.ts +1 -1
  32. package/dist/commands/init.d.ts.map +1 -1
  33. package/dist/commands/init.js +368 -176
  34. package/dist/commands/init.js.map +1 -1
  35. package/dist/commands/scan.d.ts.map +1 -1
  36. package/dist/commands/scan.js +56 -16
  37. package/dist/commands/scan.js.map +1 -1
  38. package/dist/commands/status.d.ts.map +1 -1
  39. package/dist/commands/status.js +40 -11
  40. package/dist/commands/status.js.map +1 -1
  41. package/dist/commands/tokens.d.ts +3 -0
  42. package/dist/commands/tokens.d.ts.map +1 -0
  43. package/dist/commands/tokens.js +261 -0
  44. package/dist/commands/tokens.js.map +1 -0
  45. package/dist/config/auto-detect.d.ts +21 -0
  46. package/dist/config/auto-detect.d.ts.map +1 -0
  47. package/dist/config/auto-detect.js +278 -0
  48. package/dist/config/auto-detect.js.map +1 -0
  49. package/dist/config/loader.d.ts.map +1 -1
  50. package/dist/config/loader.js +17 -0
  51. package/dist/config/loader.js.map +1 -1
  52. package/dist/config/schema.d.ts +63 -63
  53. package/dist/config/schema.d.ts.map +1 -1
  54. package/dist/config/schema.js +20 -2
  55. package/dist/config/schema.js.map +1 -1
  56. package/dist/constants.d.ts +36 -0
  57. package/dist/constants.d.ts.map +1 -0
  58. package/dist/constants.js +37 -0
  59. package/dist/constants.js.map +1 -0
  60. package/dist/detect/frameworks.d.ts +5 -1
  61. package/dist/detect/frameworks.d.ts.map +1 -1
  62. package/dist/detect/frameworks.js +35 -9
  63. package/dist/detect/frameworks.js.map +1 -1
  64. package/dist/detect/index.d.ts +1 -0
  65. package/dist/detect/index.d.ts.map +1 -1
  66. package/dist/detect/index.js +3 -0
  67. package/dist/detect/index.js.map +1 -1
  68. package/dist/detect/monorepo-patterns.d.ts +54 -0
  69. package/dist/detect/monorepo-patterns.d.ts.map +1 -0
  70. package/dist/detect/monorepo-patterns.js +209 -0
  71. package/dist/detect/monorepo-patterns.js.map +1 -0
  72. package/dist/detect/project-detector.d.ts +1 -1
  73. package/dist/detect/project-detector.d.ts.map +1 -1
  74. package/dist/detect/project-detector.js +132 -0
  75. package/dist/detect/project-detector.js.map +1 -1
  76. package/dist/explain/agents.d.ts +31 -0
  77. package/dist/explain/agents.d.ts.map +1 -0
  78. package/dist/explain/agents.js +507 -0
  79. package/dist/explain/agents.js.map +1 -0
  80. package/dist/hooks/index.d.ts +26 -0
  81. package/dist/hooks/index.d.ts.map +1 -0
  82. package/dist/hooks/index.js +283 -0
  83. package/dist/hooks/index.js.map +1 -0
  84. package/dist/index.d.ts.map +1 -1
  85. package/dist/index.js +7 -2
  86. package/dist/index.js.map +1 -1
  87. package/dist/integrations/github-formatter.d.ts +54 -2
  88. package/dist/integrations/github-formatter.d.ts.map +1 -1
  89. package/dist/integrations/github-formatter.js +369 -47
  90. package/dist/integrations/github-formatter.js.map +1 -1
  91. package/dist/integrations/github.d.ts +75 -0
  92. package/dist/integrations/github.d.ts.map +1 -1
  93. package/dist/integrations/github.js +212 -0
  94. package/dist/integrations/github.js.map +1 -1
  95. package/dist/integrations/index.d.ts +3 -3
  96. package/dist/integrations/index.d.ts.map +1 -1
  97. package/dist/integrations/index.js +2 -2
  98. package/dist/integrations/index.js.map +1 -1
  99. package/dist/output/formatters.d.ts.map +1 -1
  100. package/dist/output/formatters.js +5 -10
  101. package/dist/output/formatters.js.map +1 -1
  102. package/dist/services/ai-analysis.d.ts +54 -0
  103. package/dist/services/ai-analysis.d.ts.map +1 -0
  104. package/dist/services/ai-analysis.js +239 -0
  105. package/dist/services/ai-analysis.js.map +1 -0
  106. package/dist/services/drift-analysis.d.ts +77 -0
  107. package/dist/services/drift-analysis.d.ts.map +1 -0
  108. package/dist/services/drift-analysis.js +145 -0
  109. package/dist/services/drift-analysis.js.map +1 -0
  110. package/package.json +16 -13
  111. package/LICENSE +0 -21
  112. package/dist/commands/__tests__/ci.test.d.ts +0 -2
  113. package/dist/commands/__tests__/ci.test.d.ts.map +0 -1
  114. package/dist/commands/__tests__/ci.test.js +0 -33
  115. package/dist/commands/__tests__/ci.test.js.map +0 -1
  116. package/dist/commands/bootstrap.d.ts +0 -3
  117. package/dist/commands/bootstrap.d.ts.map +0 -1
  118. package/dist/commands/bootstrap.js +0 -458
  119. package/dist/commands/bootstrap.js.map +0 -1
@@ -0,0 +1,239 @@
1
+ /**
2
+ * AI Analysis Service
3
+ *
4
+ * Uses Claude + the knowledge graph to provide intelligent drift analysis.
5
+ * The graph provides context, Claude provides understanding.
6
+ */
7
+ import Anthropic from '@anthropic-ai/sdk';
8
+ import { GraphBuilder, collectGitHistory, findRepeatOffenders, } from '@buoy-design/core';
9
+ export class AIAnalysisService {
10
+ client = null;
11
+ graph = null;
12
+ constructor(apiKey) {
13
+ const key = apiKey || process.env.ANTHROPIC_API_KEY;
14
+ if (key) {
15
+ this.client = new Anthropic({ apiKey: key });
16
+ }
17
+ }
18
+ get isEnabled() {
19
+ return this.client !== null;
20
+ }
21
+ /**
22
+ * Build the knowledge graph for context
23
+ */
24
+ async buildGraph(projectRoot) {
25
+ const builder = new GraphBuilder({ projectId: 'default' });
26
+ // Collect git history for context
27
+ const gitResult = await collectGitHistory(projectRoot, { maxCount: 500 });
28
+ for (const commit of gitResult.commits) {
29
+ const commitId = builder.addCommit(commit.sha, commit.message, commit.author, commit.authorEmail, commit.timestamp);
30
+ for (const file of commit.filesChanged) {
31
+ const fileId = builder.addFile(file.path, file.path);
32
+ builder.addEdge('CHANGED', commitId, fileId, {
33
+ createdAt: commit.timestamp,
34
+ });
35
+ }
36
+ }
37
+ for (const dev of gitResult.developers) {
38
+ builder.addDeveloper(dev.id, dev.name, dev.email, undefined, dev.commitCount);
39
+ }
40
+ this.graph = builder.build();
41
+ }
42
+ /**
43
+ * Get context from the graph for a specific file
44
+ */
45
+ getFileContext(filePath) {
46
+ const context = [];
47
+ if (!this.graph)
48
+ return context;
49
+ // Find repeat offenders
50
+ const offenders = findRepeatOffenders(this.graph);
51
+ const isRepeatOffender = offenders.some(o => o.file === filePath);
52
+ if (isRepeatOffender) {
53
+ const offender = offenders.find(o => o.file === filePath);
54
+ context.push(`This file has ${offender?.driftCount || 0} previous drift signals (repeat offender)`);
55
+ }
56
+ return context;
57
+ }
58
+ /**
59
+ * Analyze a single drift signal with AI
60
+ */
61
+ async analyzeDrift(signal, context) {
62
+ if (!this.client) {
63
+ // Fallback without AI
64
+ return {
65
+ signal,
66
+ analysis: signal.message,
67
+ isLikelyIntentional: false,
68
+ confidence: 0.5,
69
+ suggestedAction: signal.severity === 'critical' ? 'fix' : 'discuss',
70
+ relatedHistory: [],
71
+ };
72
+ }
73
+ // Get graph context
74
+ const fileContext = signal.source.location
75
+ ? this.getFileContext(signal.source.location.split(':')[0] || '')
76
+ : [];
77
+ const prompt = `You are a design system expert analyzing code drift. Be concise.
78
+
79
+ Drift Signal:
80
+ - Type: ${signal.type}
81
+ - Severity: ${signal.severity}
82
+ - Component: ${signal.source.entityName}
83
+ - File: ${signal.source.location || 'unknown'}
84
+ - Message: ${signal.message}
85
+ - Found: ${signal.details.actual || 'N/A'}
86
+ - Expected: ${signal.details.expected || 'N/A'}
87
+
88
+ Context:
89
+ - PR Author: ${context.prAuthor || 'unknown'}
90
+ - Files in PR: ${context.filesChanged?.length || 0}
91
+ ${fileContext.map(c => `- ${c}`).join('\n')}
92
+
93
+ Analyze this drift signal:
94
+ 1. Is this likely intentional or accidental? (one sentence why)
95
+ 2. What's the risk if merged? (low/medium/high + one sentence)
96
+ 3. Recommended action: fix, approve, or discuss?
97
+
98
+ Be direct and practical. No fluff.`;
99
+ try {
100
+ const response = await this.client.messages.create({
101
+ model: 'claude-sonnet-4-20250514',
102
+ max_tokens: 300,
103
+ messages: [{ role: 'user', content: prompt }],
104
+ });
105
+ const analysisText = response.content[0]?.type === 'text'
106
+ ? response.content[0].text
107
+ : '';
108
+ // Parse the response
109
+ const isIntentional = analysisText.toLowerCase().includes('intentional') &&
110
+ !analysisText.toLowerCase().includes('not intentional') &&
111
+ !analysisText.toLowerCase().includes('unintentional');
112
+ const suggestedAction = analysisText.toLowerCase().includes('fix') ? 'fix'
113
+ : analysisText.toLowerCase().includes('approve') ? 'approve'
114
+ : 'discuss';
115
+ return {
116
+ signal,
117
+ analysis: analysisText,
118
+ isLikelyIntentional: isIntentional,
119
+ confidence: 0.8,
120
+ suggestedAction,
121
+ relatedHistory: fileContext,
122
+ };
123
+ }
124
+ catch (error) {
125
+ // Fallback on error
126
+ return {
127
+ signal,
128
+ analysis: `Analysis unavailable: ${error instanceof Error ? error.message : 'Unknown error'}`,
129
+ isLikelyIntentional: false,
130
+ confidence: 0,
131
+ suggestedAction: 'discuss',
132
+ relatedHistory: fileContext,
133
+ };
134
+ }
135
+ }
136
+ /**
137
+ * Analyze all drift signals and produce a PR summary
138
+ */
139
+ async analyzePR(signals, context) {
140
+ // Build graph if not already built
141
+ if (!this.graph) {
142
+ await this.buildGraph(context.projectRoot);
143
+ }
144
+ // Analyze critical and warning signals
145
+ const criticals = signals.filter(s => s.severity === 'critical');
146
+ const warnings = signals.filter(s => s.severity === 'warning');
147
+ const criticalAnalyses = [];
148
+ const warningAnalyses = [];
149
+ // Analyze criticals (all of them)
150
+ for (const signal of criticals) {
151
+ const analysis = await this.analyzeDrift(signal, context);
152
+ criticalAnalyses.push(analysis);
153
+ }
154
+ // Analyze warnings (limit to top 5)
155
+ for (const signal of warnings.slice(0, 5)) {
156
+ const analysis = await this.analyzeDrift(signal, context);
157
+ warningAnalyses.push(analysis);
158
+ }
159
+ // Generate overall summary
160
+ const overview = await this.generateOverview(signals, context, criticalAnalyses);
161
+ // Determine risk level
162
+ const riskLevel = criticals.length > 0 ? 'high'
163
+ : warnings.length > 5 ? 'medium'
164
+ : 'low';
165
+ // Generate recommendations
166
+ const recommendations = this.generateRecommendations(criticalAnalyses, warningAnalyses);
167
+ return {
168
+ overview,
169
+ criticalIssues: criticalAnalyses,
170
+ warnings: warningAnalyses,
171
+ recommendations,
172
+ riskLevel,
173
+ };
174
+ }
175
+ async generateOverview(signals, context, criticalAnalyses) {
176
+ if (!this.client) {
177
+ const { critical, warning, info } = this.countBySeverity(signals);
178
+ return `Found ${signals.length} drift signals: ${critical} critical, ${warning} warnings, ${info} info.`;
179
+ }
180
+ const prompt = `Summarize this PR's design system impact in 2-3 sentences:
181
+
182
+ - Total signals: ${signals.length}
183
+ - Critical: ${signals.filter(s => s.severity === 'critical').length}
184
+ - Warnings: ${signals.filter(s => s.severity === 'warning').length}
185
+ - Files affected: ${new Set(signals.map(s => s.source.location?.split(':')[0])).size}
186
+ - PR Author: ${context.prAuthor || 'unknown'}
187
+
188
+ Critical issues:
189
+ ${criticalAnalyses.map(a => `- ${a.signal.message}`).join('\n') || 'None'}
190
+
191
+ Be direct. Focus on what matters for the reviewer.`;
192
+ try {
193
+ const response = await this.client.messages.create({
194
+ model: 'claude-sonnet-4-20250514',
195
+ max_tokens: 150,
196
+ messages: [{ role: 'user', content: prompt }],
197
+ });
198
+ return response.content[0]?.type === 'text'
199
+ ? response.content[0].text
200
+ : 'Unable to generate overview.';
201
+ }
202
+ catch {
203
+ const { critical, warning, info } = this.countBySeverity(signals);
204
+ return `Found ${signals.length} drift signals: ${critical} critical, ${warning} warnings, ${info} info.`;
205
+ }
206
+ }
207
+ countBySeverity(signals) {
208
+ return {
209
+ critical: signals.filter(s => s.severity === 'critical').length,
210
+ warning: signals.filter(s => s.severity === 'warning').length,
211
+ info: signals.filter(s => s.severity === 'info').length,
212
+ };
213
+ }
214
+ generateRecommendations(criticals, warnings) {
215
+ const recommendations = [];
216
+ // Check for patterns
217
+ const needsFix = [...criticals, ...warnings].filter(a => a.suggestedAction === 'fix');
218
+ const canApprove = [...criticals, ...warnings].filter(a => a.suggestedAction === 'approve');
219
+ const needsDiscussion = [...criticals, ...warnings].filter(a => a.suggestedAction === 'discuss');
220
+ if (needsFix.length > 0) {
221
+ recommendations.push(`Fix ${needsFix.length} issue${needsFix.length === 1 ? '' : 's'} before merging`);
222
+ }
223
+ if (canApprove.length > 0) {
224
+ recommendations.push(`${canApprove.length} issue${canApprove.length === 1 ? ' appears' : 's appear'} intentional - consider approving with 👍`);
225
+ }
226
+ if (needsDiscussion.length > 0) {
227
+ recommendations.push(`${needsDiscussion.length} issue${needsDiscussion.length === 1 ? ' needs' : 's need'} team discussion`);
228
+ }
229
+ // Check for repeat offenders
230
+ const repeatFiles = new Set([...criticals, ...warnings]
231
+ .filter(a => a.relatedHistory.some(h => h.includes('repeat offender')))
232
+ .map(a => a.signal.source.location?.split(':')[0]));
233
+ if (repeatFiles.size > 0) {
234
+ recommendations.push(`Consider refactoring ${repeatFiles.size} file${repeatFiles.size === 1 ? '' : 's'} with recurring drift`);
235
+ }
236
+ return recommendations;
237
+ }
238
+ }
239
+ //# sourceMappingURL=ai-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ai-analysis.js","sourceRoot":"","sources":["../../src/services/ai-analysis.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,77 @@
1
+ /**
2
+ * DriftAnalysisService - Consolidated drift detection workflow
3
+ *
4
+ * Handles the common pattern of:
5
+ * 1. Scanning components via ScanOrchestrator
6
+ * 2. Running SemanticDiffEngine analysis
7
+ * 3. Applying ignore rules from config
8
+ * 4. Filtering against baseline
9
+ */
10
+ import type { DriftSignal, Severity, Component } from "@buoy-design/core";
11
+ import type { BuoyConfig } from "../config/schema.js";
12
+ export interface DriftAnalysisOptions {
13
+ /** Callback for progress updates */
14
+ onProgress?: (message: string) => void;
15
+ /** Include baselined drifts (default: false) */
16
+ includeBaseline?: boolean;
17
+ /** Filter by minimum severity */
18
+ minSeverity?: Severity;
19
+ /** Filter by drift type */
20
+ filterType?: string;
21
+ }
22
+ export interface DriftAnalysisResult {
23
+ /** All drifts after filtering */
24
+ drifts: DriftSignal[];
25
+ /** Components that were scanned */
26
+ components: Component[];
27
+ /** Number of drifts filtered out by baseline */
28
+ baselinedCount: number;
29
+ /** Summary counts by severity */
30
+ summary: {
31
+ total: number;
32
+ critical: number;
33
+ warning: number;
34
+ info: number;
35
+ };
36
+ }
37
+ /**
38
+ * Calculate summary counts for drift signals
39
+ */
40
+ export declare function calculateDriftSummary(drifts: DriftSignal[]): {
41
+ total: number;
42
+ critical: number;
43
+ warning: number;
44
+ info: number;
45
+ };
46
+ /**
47
+ * Determine if drifts exceed a severity threshold
48
+ */
49
+ export declare function hasDriftsAboveThreshold(drifts: DriftSignal[], failOn: Severity | "none"): boolean;
50
+ /**
51
+ * Sort drifts by severity (critical first)
52
+ */
53
+ export declare function sortDriftsBySeverity(drifts: DriftSignal[]): DriftSignal[];
54
+ /**
55
+ * Apply ignore rules from config to filter out matching drifts
56
+ */
57
+ export declare function applyIgnoreRules(drifts: DriftSignal[], ignoreRules: BuoyConfig["drift"]["ignore"], onWarning?: (message: string) => void): DriftSignal[];
58
+ /**
59
+ * Apply severity filter to drifts
60
+ */
61
+ export declare function filterBySeverity(drifts: DriftSignal[], minSeverity: Severity): DriftSignal[];
62
+ /**
63
+ * Apply type filter to drifts
64
+ */
65
+ export declare function filterByType(drifts: DriftSignal[], type: string): DriftSignal[];
66
+ /**
67
+ * DriftAnalysisService - Main entry point for drift detection
68
+ */
69
+ export declare class DriftAnalysisService {
70
+ private config;
71
+ constructor(config: BuoyConfig);
72
+ /**
73
+ * Run full drift analysis pipeline
74
+ */
75
+ analyze(options?: DriftAnalysisOptions): Promise<DriftAnalysisResult>;
76
+ }
77
+ //# sourceMappingURL=drift-analysis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-analysis.d.ts","sourceRoot":"","sources":["../../src/services/drift-analysis.ts"],"names":[],"mappings":"AACA;;;;;;;;GAQG;AAEH,OAAO,KAAK,EAAE,WAAW,EAAE,QAAQ,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC1E,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,qBAAqB,CAAC;AAItD,MAAM,WAAW,oBAAoB;IACnC,oCAAoC;IACpC,UAAU,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,CAAC;IACvC,gDAAgD;IAChD,eAAe,CAAC,EAAE,OAAO,CAAC;IAC1B,iCAAiC;IACjC,WAAW,CAAC,EAAE,QAAQ,CAAC;IACvB,2BAA2B;IAC3B,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,mBAAmB;IAClC,iCAAiC;IACjC,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,mCAAmC;IACnC,UAAU,EAAE,SAAS,EAAE,CAAC;IACxB,gDAAgD;IAChD,cAAc,EAAE,MAAM,CAAC;IACvB,iCAAiC;IACjC,OAAO,EAAE;QACP,KAAK,EAAE,MAAM,CAAC;QACd,QAAQ,EAAE,MAAM,CAAC;QACjB,OAAO,EAAE,MAAM,CAAC;QAChB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;CACH;AAYD;;GAEG;AACH,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG;IAC5D,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,CAAC;IAChB,IAAI,EAAE,MAAM,CAAC;CACd,CAOA;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,MAAM,EAAE,WAAW,EAAE,EACrB,MAAM,EAAE,QAAQ,GAAG,MAAM,GACxB,OAAO,CAIT;AAED;;GAEG;AACH,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,WAAW,EAAE,GAAG,WAAW,EAAE,CAIzE;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,UAAU,CAAC,OAAO,CAAC,CAAC,QAAQ,CAAC,EAC1C,SAAS,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GACpC,WAAW,EAAE,CAqBf;AAED;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,MAAM,EAAE,WAAW,EAAE,EACrB,WAAW,EAAE,QAAQ,GACpB,WAAW,EAAE,CAGf;AAED;;GAEG;AACH,wBAAgB,YAAY,CAC1B,MAAM,EAAE,WAAW,EAAE,EACrB,IAAI,EAAE,MAAM,GACX,WAAW,EAAE,CAEf;AAED;;GAEG;AACH,qBAAa,oBAAoB;IACnB,OAAO,CAAC,MAAM;gBAAN,MAAM,EAAE,UAAU;IAEtC;;OAEG;IACG,OAAO,CAAC,OAAO,GAAE,oBAAyB,GAAG,OAAO,CAAC,mBAAmB,CAAC;CA4DhF"}
@@ -0,0 +1,145 @@
1
+ // apps/cli/src/services/drift-analysis.ts
2
+ /**
3
+ * DriftAnalysisService - Consolidated drift detection workflow
4
+ *
5
+ * Handles the common pattern of:
6
+ * 1. Scanning components via ScanOrchestrator
7
+ * 2. Running SemanticDiffEngine analysis
8
+ * 3. Applying ignore rules from config
9
+ * 4. Filtering against baseline
10
+ */
11
+ import { ScanOrchestrator } from "../scan/orchestrator.js";
12
+ import { getSeverityWeight } from "@buoy-design/core";
13
+ /**
14
+ * Severity order for filtering and sorting (0 = lowest, 2 = highest)
15
+ * Use getSeverityWeight from @buoy-design/core for consistent ordering
16
+ */
17
+ const SEVERITY_ORDER = {
18
+ info: 0,
19
+ warning: 1,
20
+ critical: 2,
21
+ };
22
+ /**
23
+ * Calculate summary counts for drift signals
24
+ */
25
+ export function calculateDriftSummary(drifts) {
26
+ return {
27
+ total: drifts.length,
28
+ critical: drifts.filter((d) => d.severity === "critical").length,
29
+ warning: drifts.filter((d) => d.severity === "warning").length,
30
+ info: drifts.filter((d) => d.severity === "info").length,
31
+ };
32
+ }
33
+ /**
34
+ * Determine if drifts exceed a severity threshold
35
+ */
36
+ export function hasDriftsAboveThreshold(drifts, failOn) {
37
+ if (failOn === "none")
38
+ return false;
39
+ const threshold = SEVERITY_ORDER[failOn] ?? SEVERITY_ORDER.critical;
40
+ return drifts.some((d) => SEVERITY_ORDER[d.severity] >= threshold);
41
+ }
42
+ /**
43
+ * Sort drifts by severity (critical first)
44
+ */
45
+ export function sortDriftsBySeverity(drifts) {
46
+ return [...drifts].sort((a, b) => getSeverityWeight(b.severity) - getSeverityWeight(a.severity));
47
+ }
48
+ /**
49
+ * Apply ignore rules from config to filter out matching drifts
50
+ */
51
+ export function applyIgnoreRules(drifts, ignoreRules, onWarning) {
52
+ let filtered = drifts;
53
+ for (const rule of ignoreRules) {
54
+ filtered = filtered.filter((d) => {
55
+ if (d.type !== rule.type)
56
+ return true;
57
+ if (!rule.pattern)
58
+ return false;
59
+ try {
60
+ const regex = new RegExp(rule.pattern);
61
+ return !regex.test(d.source.entityName);
62
+ }
63
+ catch {
64
+ onWarning?.(`Invalid regex pattern "${rule.pattern}" in ignore rule, skipping`);
65
+ return true;
66
+ }
67
+ });
68
+ }
69
+ return filtered;
70
+ }
71
+ /**
72
+ * Apply severity filter to drifts
73
+ */
74
+ export function filterBySeverity(drifts, minSeverity) {
75
+ const minLevel = SEVERITY_ORDER[minSeverity] ?? 0;
76
+ return drifts.filter((d) => SEVERITY_ORDER[d.severity] >= minLevel);
77
+ }
78
+ /**
79
+ * Apply type filter to drifts
80
+ */
81
+ export function filterByType(drifts, type) {
82
+ return drifts.filter((d) => d.type === type);
83
+ }
84
+ /**
85
+ * DriftAnalysisService - Main entry point for drift detection
86
+ */
87
+ export class DriftAnalysisService {
88
+ config;
89
+ constructor(config) {
90
+ this.config = config;
91
+ }
92
+ /**
93
+ * Run full drift analysis pipeline
94
+ */
95
+ async analyze(options = {}) {
96
+ const { onProgress, includeBaseline, minSeverity, filterType } = options;
97
+ // Step 1: Scan components
98
+ onProgress?.("Scanning components...");
99
+ const orchestrator = new ScanOrchestrator(this.config);
100
+ const { components } = await orchestrator.scanComponents({
101
+ onProgress,
102
+ });
103
+ // Step 2: Run semantic diff analysis
104
+ onProgress?.("Analyzing drift...");
105
+ const { SemanticDiffEngine } = await import("@buoy-design/core/analysis");
106
+ const engine = new SemanticDiffEngine();
107
+ const diffResult = engine.analyzeComponents(components, {
108
+ checkDeprecated: true,
109
+ checkNaming: true,
110
+ checkDocumentation: true,
111
+ });
112
+ let drifts = diffResult.drifts;
113
+ // Step 3: Apply severity filter (before other filters for efficiency)
114
+ if (minSeverity) {
115
+ drifts = filterBySeverity(drifts, minSeverity);
116
+ }
117
+ // Step 4: Apply type filter
118
+ if (filterType) {
119
+ drifts = filterByType(drifts, filterType);
120
+ }
121
+ // Step 5: Apply ignore rules from config
122
+ drifts = applyIgnoreRules(drifts, this.config.drift.ignore, (msg) => {
123
+ onProgress?.(`Warning: ${msg}`);
124
+ });
125
+ // Step 6: Apply baseline filtering
126
+ let baselinedCount = 0;
127
+ if (!includeBaseline) {
128
+ const { loadBaseline, filterBaseline } = await import("../commands/baseline.js");
129
+ const baseline = await loadBaseline();
130
+ const filtered = filterBaseline(drifts, baseline);
131
+ drifts = filtered.newDrifts;
132
+ baselinedCount = filtered.baselinedCount;
133
+ if (baselinedCount > 0) {
134
+ onProgress?.(`Filtered out ${baselinedCount} baselined drift signals.`);
135
+ }
136
+ }
137
+ return {
138
+ drifts,
139
+ components,
140
+ baselinedCount,
141
+ summary: calculateDriftSummary(drifts),
142
+ };
143
+ }
144
+ }
145
+ //# sourceMappingURL=drift-analysis.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"drift-analysis.js","sourceRoot":"","sources":["../../src/services/drift-analysis.ts"],"names":[],"mappings":"AAAA,0CAA0C;AAC1C;;;;;;;;GAQG;AAIH,OAAO,EAAE,gBAAgB,EAAE,MAAM,yBAAyB,CAAC;AAC3D,OAAO,EAAE,iBAAiB,EAAE,MAAM,mBAAmB,CAAC;AA6BtD;;;GAGG;AACH,MAAM,cAAc,GAA6B;IAC/C,IAAI,EAAE,CAAC;IACP,OAAO,EAAE,CAAC;IACV,QAAQ,EAAE,CAAC;CACZ,CAAC;AAEF;;GAEG;AACH,MAAM,UAAU,qBAAqB,CAAC,MAAqB;IAMzD,OAAO;QACL,KAAK,EAAE,MAAM,CAAC,MAAM;QACpB,QAAQ,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,UAAU,CAAC,CAAC,MAAM;QAChE,OAAO,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,SAAS,CAAC,CAAC,MAAM;QAC9D,IAAI,EAAE,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,MAAM;KACzD,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,uBAAuB,CACrC,MAAqB,EACrB,MAAyB;IAEzB,IAAI,MAAM,KAAK,MAAM;QAAE,OAAO,KAAK,CAAC;IACpC,MAAM,SAAS,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC;IACpE,OAAO,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,SAAS,CAAC,CAAC;AACrE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,oBAAoB,CAAC,MAAqB;IACxD,OAAO,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,CACrB,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,GAAG,iBAAiB,CAAC,CAAC,CAAC,QAAQ,CAAC,CACxE,CAAC;AACJ,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAqB,EACrB,WAA0C,EAC1C,SAAqC;IAErC,IAAI,QAAQ,GAAG,MAAM,CAAC;IAEtB,KAAK,MAAM,IAAI,IAAI,WAAW,EAAE,CAAC;QAC/B,QAAQ,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE;YAC/B,IAAI,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,IAAI;gBAAE,OAAO,IAAI,CAAC;YACtC,IAAI,CAAC,IAAI,CAAC,OAAO;gBAAE,OAAO,KAAK,CAAC;YAEhC,IAAI,CAAC;gBACH,MAAM,KAAK,GAAG,IAAI,MAAM,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC;gBACvC,OAAO,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;YAC1C,CAAC;YAAC,MAAM,CAAC;gBACP,SAAS,EAAE,CACT,0BAA0B,IAAI,CAAC,OAAO,4BAA4B,CACnE,CAAC;gBACF,OAAO,IAAI,CAAC;YACd,CAAC;QACH,CAAC,CAAC,CAAC;IACL,CAAC;IAED,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB,CAC9B,MAAqB,EACrB,WAAqB;IAErB,MAAM,QAAQ,GAAG,cAAc,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;IAClD,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,cAAc,CAAC,CAAC,CAAC,QAAQ,CAAC,IAAI,QAAQ,CAAC,CAAC;AACtE,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,YAAY,CAC1B,MAAqB,EACrB,IAAY;IAEZ,OAAO,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED;;GAEG;AACH,MAAM,OAAO,oBAAoB;IACX;IAApB,YAAoB,MAAkB;QAAlB,WAAM,GAAN,MAAM,CAAY;IAAG,CAAC;IAE1C;;OAEG;IACH,KAAK,CAAC,OAAO,CAAC,UAAgC,EAAE;QAC9C,MAAM,EAAE,UAAU,EAAE,eAAe,EAAE,WAAW,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;QAEzE,0BAA0B;QAC1B,UAAU,EAAE,CAAC,wBAAwB,CAAC,CAAC;QACvC,MAAM,YAAY,GAAG,IAAI,gBAAgB,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QACvD,MAAM,EAAE,UAAU,EAAE,GAAG,MAAM,YAAY,CAAC,cAAc,CAAC;YACvD,UAAU;SACX,CAAC,CAAC;QAEH,qCAAqC;QACrC,UAAU,EAAE,CAAC,oBAAoB,CAAC,CAAC;QACnC,MAAM,EAAE,kBAAkB,EAAE,GAAG,MAAM,MAAM,CAAC,4BAA4B,CAAC,CAAC;QAC1E,MAAM,MAAM,GAAG,IAAI,kBAAkB,EAAE,CAAC;QACxC,MAAM,UAAU,GAAG,MAAM,CAAC,iBAAiB,CAAC,UAAU,EAAE;YACtD,eAAe,EAAE,IAAI;YACrB,WAAW,EAAE,IAAI;YACjB,kBAAkB,EAAE,IAAI;SACzB,CAAC,CAAC;QAEH,IAAI,MAAM,GAAkB,UAAU,CAAC,MAAM,CAAC;QAE9C,sEAAsE;QACtE,IAAI,WAAW,EAAE,CAAC;YAChB,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,WAAW,CAAC,CAAC;QACjD,CAAC;QAED,4BAA4B;QAC5B,IAAI,UAAU,EAAE,CAAC;YACf,MAAM,GAAG,YAAY,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAC5C,CAAC;QAED,yCAAyC;QACzC,MAAM,GAAG,gBAAgB,CAAC,MAAM,EAAE,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,EAAE,CAAC,GAAG,EAAE,EAAE;YAClE,UAAU,EAAE,CAAC,YAAY,GAAG,EAAE,CAAC,CAAC;QAClC,CAAC,CAAC,CAAC;QAEH,mCAAmC;QACnC,IAAI,cAAc,GAAG,CAAC,CAAC;QACvB,IAAI,CAAC,eAAe,EAAE,CAAC;YACrB,MAAM,EAAE,YAAY,EAAE,cAAc,EAAE,GAAG,MAAM,MAAM,CACnD,yBAAyB,CAC1B,CAAC;YACF,MAAM,QAAQ,GAAG,MAAM,YAAY,EAAE,CAAC;YACtC,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAC;YAClD,MAAM,GAAG,QAAQ,CAAC,SAAS,CAAC;YAC5B,cAAc,GAAG,QAAQ,CAAC,cAAc,CAAC;YAEzC,IAAI,cAAc,GAAG,CAAC,EAAE,CAAC;gBACvB,UAAU,EAAE,CAAC,gBAAgB,cAAc,2BAA2B,CAAC,CAAC;YAC1E,CAAC;QACH,CAAC;QAED,OAAO;YACL,MAAM;YACN,UAAU;YACV,cAAc;YACd,OAAO,EAAE,qBAAqB,CAAC,MAAM,CAAC;SACvC,CAAC;IACJ,CAAC;CACF"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buoy-design/cli",
3
- "version": "0.1.1",
3
+ "version": "0.1.2",
4
4
  "description": "Buoy CLI - Design drift detection for the AI era",
5
5
  "type": "module",
6
6
  "license": "MIT",
@@ -30,28 +30,31 @@
30
30
  },
31
31
  "main": "./dist/index.js",
32
32
  "types": "./dist/index.d.ts",
33
+ "scripts": {
34
+ "build": "tsc",
35
+ "dev": "tsc --watch",
36
+ "typecheck": "tsc --noEmit",
37
+ "clean": "rm -rf dist",
38
+ "start": "node ./dist/bin/buoy.js",
39
+ "test": "vitest run",
40
+ "test:watch": "vitest"
41
+ },
33
42
  "dependencies": {
43
+ "@anthropic-ai/sdk": "^0.71.2",
44
+ "@buoy-design/core": "workspace:*",
45
+ "@buoy-design/scanners": "workspace:*",
34
46
  "@octokit/rest": "^21.0.0",
35
47
  "chalk": "^5.3.0",
36
48
  "cli-table3": "^0.6.5",
37
49
  "commander": "^12.1.0",
38
50
  "glob": "^11.0.0",
39
51
  "ora": "^8.1.1",
52
+ "yaml": "^2.7.0",
40
53
  "zod": "^3.24.1",
41
- "@buoy-design/core": "0.1.1",
42
- "@buoy-design/scanners": "0.1.1"
54
+ "zod-validation-error": "^5.0.0"
43
55
  },
44
56
  "devDependencies": {
45
57
  "@types/node": "^22.10.2",
46
58
  "typescript": "^5.7.2"
47
- },
48
- "scripts": {
49
- "build": "tsc",
50
- "dev": "tsc --watch",
51
- "typecheck": "tsc --noEmit",
52
- "clean": "rm -rf dist",
53
- "start": "node ./dist/bin/buoy.js",
54
- "test": "vitest run",
55
- "test:watch": "vitest"
56
59
  }
57
- }
60
+ }
package/LICENSE DELETED
@@ -1,21 +0,0 @@
1
- MIT License
2
-
3
- Copyright (c) 2024 Buoy
4
-
5
- Permission is hereby granted, free of charge, to any person obtaining a copy
6
- of this software and associated documentation files (the "Software"), to deal
7
- in the Software without restriction, including without limitation the rights
8
- to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
- copies of the Software, and to permit persons to whom the Software is
10
- furnished to do so, subject to the following conditions:
11
-
12
- The above copyright notice and this permission notice shall be included in all
13
- copies or substantial portions of the Software.
14
-
15
- THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
- IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
- FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
- AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
- LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
- OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
- SOFTWARE.
@@ -1,2 +0,0 @@
1
- export {};
2
- //# sourceMappingURL=ci.test.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ci.test.d.ts","sourceRoot":"","sources":["../../../src/commands/__tests__/ci.test.ts"],"names":[],"mappings":""}
@@ -1,33 +0,0 @@
1
- // apps/cli/src/commands/__tests__/ci.test.ts
2
- import { describe, it, expect } from 'vitest';
3
- // Import the function we want to test
4
- // Note: We'll need to export buildCIOutput for testing
5
- // For now, test the output structure
6
- describe('buoy ci', () => {
7
- describe('exit codes', () => {
8
- it('should exit 0 when no drift found', () => {
9
- // Placeholder - would need to mock config and scanners
10
- expect(true).toBe(true);
11
- });
12
- it('should exit 1 when critical drift found and fail-on=critical', () => {
13
- expect(true).toBe(true);
14
- });
15
- it('should exit 0 when warning drift found and fail-on=critical', () => {
16
- expect(true).toBe(true);
17
- });
18
- it('should exit 1 when warning drift found and fail-on=warning', () => {
19
- expect(true).toBe(true);
20
- });
21
- it('should exit 0 when fail-on=none regardless of drift', () => {
22
- expect(true).toBe(true);
23
- });
24
- });
25
- describe('output format', () => {
26
- it('should output valid JSON with required fields', () => {
27
- const expectedFields = ['version', 'timestamp', 'summary', 'topIssues', 'exitCode'];
28
- // Placeholder
29
- expect(expectedFields.length).toBe(5);
30
- });
31
- });
32
- });
33
- //# sourceMappingURL=ci.test.js.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"ci.test.js","sourceRoot":"","sources":["../../../src/commands/__tests__/ci.test.ts"],"names":[],"mappings":"AAAA,6CAA6C;AAC7C,OAAO,EAAE,QAAQ,EAAE,EAAE,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AAE9C,sCAAsC;AACtC,uDAAuD;AACvD,qCAAqC;AAErC,QAAQ,CAAC,SAAS,EAAE,GAAG,EAAE;IACvB,QAAQ,CAAC,YAAY,EAAE,GAAG,EAAE;QAC1B,EAAE,CAAC,mCAAmC,EAAE,GAAG,EAAE;YAC3C,uDAAuD;YACvD,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,8DAA8D,EAAE,GAAG,EAAE;YACtE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,6DAA6D,EAAE,GAAG,EAAE;YACrE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,4DAA4D,EAAE,GAAG,EAAE;YACpE,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;QAEH,EAAE,CAAC,qDAAqD,EAAE,GAAG,EAAE;YAC7D,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAC1B,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IAEH,QAAQ,CAAC,eAAe,EAAE,GAAG,EAAE;QAC7B,EAAE,CAAC,+CAA+C,EAAE,GAAG,EAAE;YACvD,MAAM,cAAc,GAAG,CAAC,SAAS,EAAE,WAAW,EAAE,SAAS,EAAE,WAAW,EAAE,UAAU,CAAC,CAAC;YACpF,cAAc;YACd,MAAM,CAAC,cAAc,CAAC,MAAM,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACxC,CAAC,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;AACL,CAAC,CAAC,CAAC"}
@@ -1,3 +0,0 @@
1
- import { Command } from 'commander';
2
- export declare function createBootstrapCommand(): Command;
3
- //# sourceMappingURL=bootstrap.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"bootstrap.d.ts","sourceRoot":"","sources":["../../src/commands/bootstrap.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAqCpC,wBAAgB,sBAAsB,IAAI,OAAO,CA4KhD"}