@boshu2/vibe-check 2.0.0 → 2.2.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 (61) hide show
  1. package/.agents/plans/2025-12-27-vibe-check-evolution-plan.md +383 -0
  2. package/.agents/research/2025-12-27-vibe-check-evolution.md +352 -0
  3. package/.claude/settings.local.json +8 -2
  4. package/CHANGELOG.md +33 -0
  5. package/CLAUDE.md +201 -26
  6. package/README.md +95 -0
  7. package/dist/analyzers/eldritch.d.ts +40 -0
  8. package/dist/analyzers/eldritch.d.ts.map +1 -0
  9. package/dist/analyzers/eldritch.js +202 -0
  10. package/dist/analyzers/eldritch.js.map +1 -0
  11. package/dist/analyzers/modularity.d.ts +67 -0
  12. package/dist/analyzers/modularity.d.ts.map +1 -0
  13. package/dist/analyzers/modularity.js +254 -0
  14. package/dist/analyzers/modularity.js.map +1 -0
  15. package/dist/cli.js +2 -1
  16. package/dist/cli.js.map +1 -1
  17. package/dist/commands/analyze.d.ts.map +1 -1
  18. package/dist/commands/analyze.js +11 -1
  19. package/dist/commands/analyze.js.map +1 -1
  20. package/dist/commands/audit.d.ts.map +1 -1
  21. package/dist/commands/audit.js +25 -0
  22. package/dist/commands/audit.js.map +1 -1
  23. package/dist/commands/forensics.d.ts +8 -0
  24. package/dist/commands/forensics.d.ts.map +1 -1
  25. package/dist/commands/forensics.js +51 -4
  26. package/dist/commands/forensics.js.map +1 -1
  27. package/dist/commands/index.d.ts +1 -0
  28. package/dist/commands/index.d.ts.map +1 -1
  29. package/dist/commands/index.js +1 -0
  30. package/dist/commands/index.js.map +1 -1
  31. package/dist/commands/modularity.d.ts +27 -0
  32. package/dist/commands/modularity.d.ts.map +1 -0
  33. package/dist/commands/modularity.js +182 -0
  34. package/dist/commands/modularity.js.map +1 -0
  35. package/dist/git.d.ts.map +1 -1
  36. package/dist/git.js +8 -2
  37. package/dist/git.js.map +1 -1
  38. package/dist/metrics/cohesion.d.ts +27 -0
  39. package/dist/metrics/cohesion.d.ts.map +1 -0
  40. package/dist/metrics/cohesion.js +134 -0
  41. package/dist/metrics/cohesion.js.map +1 -0
  42. package/dist/metrics/index.d.ts +8 -0
  43. package/dist/metrics/index.d.ts.map +1 -1
  44. package/dist/metrics/index.js +36 -0
  45. package/dist/metrics/index.js.map +1 -1
  46. package/dist/metrics/investigation.d.ts +25 -0
  47. package/dist/metrics/investigation.d.ts.map +1 -0
  48. package/dist/metrics/investigation.js +115 -0
  49. package/dist/metrics/investigation.js.map +1 -0
  50. package/dist/metrics/tracers.d.ts +28 -0
  51. package/dist/metrics/tracers.d.ts.map +1 -0
  52. package/dist/metrics/tracers.js +117 -0
  53. package/dist/metrics/tracers.js.map +1 -0
  54. package/dist/output/terminal.d.ts.map +1 -1
  55. package/dist/output/terminal.js +34 -1
  56. package/dist/output/terminal.js.map +1 -1
  57. package/dist/types.d.ts +36 -1
  58. package/dist/types.d.ts.map +1 -1
  59. package/docs/ENHANCEMENT-PLAN.md +32 -14
  60. package/package.json +1 -1
  61. package/.claude/skills/typescript-review.md +0 -152
package/README.md CHANGED
@@ -187,6 +187,15 @@ vibe-check profile # XP and achievements
187
187
  vibe-check insights # Your spiral patterns
188
188
  ```
189
189
 
190
+ ### Code Quality
191
+
192
+ ```bash
193
+ vibe-check audit # Scan for monoliths, test gaps, TODOs
194
+ vibe-check modularity # Pattern-aware modularity analysis
195
+ vibe-check modularity --verbose # Detailed breakdown with metrics
196
+ vibe-check modularity -f json # JSON output for CI integration
197
+ ```
198
+
190
199
  ### Tools
191
200
 
192
201
  ```bash
@@ -241,6 +250,92 @@ When inner loop issues are detected:
241
250
 
242
251
  ---
243
252
 
253
+ ## Modularity Analysis
254
+
255
+ Goes beyond simple LOC counting to assess whether large files are well-organized or problematic.
256
+
257
+ ```bash
258
+ vibe-check modularity
259
+ ```
260
+
261
+ ```
262
+ 📐 Modularity Analysis
263
+ ────────────────────────────────────────────────────────────
264
+
265
+ Analyzed 584 files (195,345 lines)
266
+ Average modularity score: 9.5/10
267
+
268
+ Score Distribution:
269
+ Elite (9-10): ████████████████░░░░ 82%
270
+ Good (7-8): ███░░░░░░░░░░░░░░░░░ 15%
271
+ Acceptable (5-6): ░░░░░░░░░░░░░░░░░░░░ 2%
272
+ Needs Work (3-4): ░░░░░░░░░░░░░░░░░░░░ 1%
273
+ Poor (0-2): ░░░░░░░░░░░░░░░░░░░░ 0%
274
+
275
+ ⚠️ Files Needing Attention (8):
276
+
277
+ 6/10 stores/network.js 1023 lines [state-machine]
278
+ ⚠ no sections/organization
279
+ 5/10 server/WebSocketGateway.ts 702 lines
280
+ ⚠ no sections/organization
281
+ 4/10 client/App.tsx 568 lines [component]
282
+ ⚠ no sections/organization, ⚠ high coupling
283
+
284
+ 👍 Good modularity. Minor improvements possible.
285
+ ```
286
+
287
+ ### Pattern-Aware Scoring
288
+
289
+ A 2,500-line file can score **10/10** if well-organized. A 300-line file can score **4/10** if it's a mess.
290
+
291
+ | Factor | Impact | What It Checks |
292
+ |--------|--------|----------------|
293
+ | **Pattern Match** | +1 | Is it a controller/store/routes/state-machine? |
294
+ | **Internal Sections** | +1/-2 | Does it use `// ====` dividers or nested classes? |
295
+ | **Single Responsibility** | +2/-2 | Can purpose be described in one sentence? |
296
+ | **Coupling** | -1/-2 | >15 imports = high coupling warning |
297
+ | **Export Surface** | -1 | >20 exports = bloated API |
298
+
299
+ ### Pattern-Specific Thresholds
300
+
301
+ Different file types have different acceptable sizes:
302
+
303
+ | Pattern | Yellow | Red | Why |
304
+ |---------|--------|-----|-----|
305
+ | `store` | 1,500 | 2,500 | Data layer naturally groups many methods |
306
+ | `controller` | 800 | 1,200 | K8s-style with reconciliation loops |
307
+ | `routes` | 1,000 | 1,500 | Vertical slice entry points |
308
+ | `component` | 250 | 400 | React components should stay focused |
309
+ | `utility` | 150 | 250 | Utilities should be smallest |
310
+
311
+ ### Automatic Exemptions
312
+
313
+ These patterns skip modularity checks:
314
+ - `*.test.ts` — Tests can be comprehensive
315
+ - `*.generated.ts` — Generated files
316
+ - Type definition files — Central types are OK to be large
317
+
318
+ ### Forensics Integration
319
+
320
+ Modularity is also included in `vibe-check forensics` for complete code health analysis:
321
+
322
+ ```bash
323
+ vibe-check forensics
324
+ ```
325
+
326
+ ```
327
+ Modularity Health:
328
+ Average Score: 9.5/10 (303 files analyzed)
329
+ ⚠️ 8 files need attention:
330
+ 6/10 stores/network.js 1023 lines (no-internal-structure)
331
+ 5/10 server/WebSocketGateway.ts 702 lines
332
+ ...
333
+ ```
334
+
335
+ Poor modularity (score <5) triggers the **SWEEP** recommendation alongside commit pattern issues.
336
+
337
+ ---
338
+
244
339
  ## For Autonomous Agents
245
340
 
246
341
  vibe-check measures **human-AI collaboration sessions**—the inner loop where you're working with an AI assistant.
@@ -0,0 +1,40 @@
1
+ /**
2
+ * Eldritch Horror Detector
3
+ *
4
+ * Detects oversized functions that are symptomatic of the "Eldritch Horror"
5
+ * middle loop failure pattern from vibe coding. This pattern occurs when
6
+ * AI generates monolithic functions that are impossible to understand.
7
+ *
8
+ * Thresholds:
9
+ * - Warning: Functions > 200 lines
10
+ * - Critical: Functions > 500 lines
11
+ *
12
+ * Detection is heuristic-based (not full AST parsing) to keep it fast
13
+ * and work across multiple languages.
14
+ */
15
+ export interface EldritchHorror {
16
+ file: string;
17
+ functionName: string;
18
+ lineStart: number;
19
+ lineCount: number;
20
+ severity: 'warning' | 'critical';
21
+ }
22
+ export interface EldritchHorrorResult {
23
+ detected: boolean;
24
+ horrors: EldritchHorror[];
25
+ totalCount: number;
26
+ criticalCount: number;
27
+ warningCount: number;
28
+ }
29
+ /**
30
+ * Detect oversized functions in source files.
31
+ *
32
+ * @param files - List of file paths to analyze
33
+ * @returns Detection result with list of horrors
34
+ */
35
+ export declare function detectEldritchHorrors(files: string[]): EldritchHorrorResult;
36
+ /**
37
+ * Run eldritch horror detection on a directory.
38
+ */
39
+ export declare function scanForHorrors(dir: string): EldritchHorrorResult;
40
+ //# sourceMappingURL=eldritch.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eldritch.d.ts","sourceRoot":"","sources":["../../src/analyzers/eldritch.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;GAaG;AAKH,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,YAAY,EAAE,MAAM,CAAC;IACrB,SAAS,EAAE,MAAM,CAAC;IAClB,SAAS,EAAE,MAAM,CAAC;IAClB,QAAQ,EAAE,SAAS,GAAG,UAAU,CAAC;CAClC;AAED,MAAM,WAAW,oBAAoB;IACnC,QAAQ,EAAE,OAAO,CAAC;IAClB,OAAO,EAAE,cAAc,EAAE,CAAC;IAC1B,UAAU,EAAE,MAAM,CAAC;IACnB,aAAa,EAAE,MAAM,CAAC;IACtB,YAAY,EAAE,MAAM,CAAC;CACtB;AAqBD;;;;;GAKG;AACH,wBAAgB,qBAAqB,CAAC,KAAK,EAAE,MAAM,EAAE,GAAG,oBAAoB,CAuB3E;AA8HD;;GAEG;AACH,wBAAgB,cAAc,CAAC,GAAG,EAAE,MAAM,GAAG,oBAAoB,CAGhE"}
@@ -0,0 +1,202 @@
1
+ /**
2
+ * Eldritch Horror Detector
3
+ *
4
+ * Detects oversized functions that are symptomatic of the "Eldritch Horror"
5
+ * middle loop failure pattern from vibe coding. This pattern occurs when
6
+ * AI generates monolithic functions that are impossible to understand.
7
+ *
8
+ * Thresholds:
9
+ * - Warning: Functions > 200 lines
10
+ * - Critical: Functions > 500 lines
11
+ *
12
+ * Detection is heuristic-based (not full AST parsing) to keep it fast
13
+ * and work across multiple languages.
14
+ */
15
+ import * as fs from 'fs';
16
+ import * as path from 'path';
17
+ const WARNING_THRESHOLD = 200;
18
+ const CRITICAL_THRESHOLD = 500;
19
+ // Pattern matchers for function declarations across languages
20
+ const FUNCTION_PATTERNS = {
21
+ // JavaScript/TypeScript
22
+ jsFunction: /^\s*(?:export\s+)?(?:async\s+)?function\s+(\w+)\s*\(/,
23
+ jsArrow: /^\s*(?:export\s+)?(?:const|let|var)\s+(\w+)\s*=\s*(?:async\s+)?\(/,
24
+ jsMethod: /^\s*(?:async\s+)?(\w+)\s*\([^)]*\)\s*{/,
25
+ jsClass: /^\s*(?:export\s+)?class\s+(\w+)/,
26
+ // Python
27
+ pyFunction: /^\s*(?:async\s+)?def\s+(\w+)\s*\(/,
28
+ pyClass: /^\s*class\s+(\w+)/,
29
+ // Go
30
+ goFunction: /^\s*func\s+(?:\([^)]+\)\s+)?(\w+)\s*\(/,
31
+ };
32
+ /**
33
+ * Detect oversized functions in source files.
34
+ *
35
+ * @param files - List of file paths to analyze
36
+ * @returns Detection result with list of horrors
37
+ */
38
+ export function detectEldritchHorrors(files) {
39
+ const horrors = [];
40
+ for (const file of files) {
41
+ try {
42
+ const content = fs.readFileSync(file, 'utf-8');
43
+ const fileHorrors = analyzeFile(file, content);
44
+ horrors.push(...fileHorrors);
45
+ }
46
+ catch {
47
+ // Skip files that can't be read
48
+ }
49
+ }
50
+ const criticalCount = horrors.filter((h) => h.severity === 'critical').length;
51
+ const warningCount = horrors.filter((h) => h.severity === 'warning').length;
52
+ return {
53
+ detected: horrors.length > 0,
54
+ horrors: horrors.sort((a, b) => b.lineCount - a.lineCount),
55
+ totalCount: horrors.length,
56
+ criticalCount,
57
+ warningCount,
58
+ };
59
+ }
60
+ /**
61
+ * Analyze a single file for oversized functions.
62
+ */
63
+ function analyzeFile(filePath, content) {
64
+ const horrors = [];
65
+ const lines = content.split('\n');
66
+ const ext = path.extname(filePath).toLowerCase();
67
+ // Determine which patterns to use based on file extension
68
+ const patterns = getPatterns(ext);
69
+ let currentFunction = null;
70
+ for (let i = 0; i < lines.length; i++) {
71
+ const line = lines[i];
72
+ const lineNum = i + 1;
73
+ // Check if this line starts a new function
74
+ for (const pattern of patterns) {
75
+ const match = line.match(pattern);
76
+ if (match) {
77
+ // If we were tracking a function, close it out
78
+ if (currentFunction) {
79
+ const lineCount = lineNum - currentFunction.startLine;
80
+ if (lineCount >= WARNING_THRESHOLD) {
81
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
82
+ }
83
+ }
84
+ currentFunction = {
85
+ name: match[1] || 'anonymous',
86
+ startLine: lineNum,
87
+ braceDepth: countBraces(line),
88
+ };
89
+ break;
90
+ }
91
+ }
92
+ // Track brace depth
93
+ if (currentFunction && !line.match(/^\s*\/\//)) {
94
+ currentFunction.braceDepth += countBraces(line);
95
+ // Check for function end (Python uses indentation, others use braces)
96
+ if (ext === '.py') {
97
+ // For Python, check if we hit a line with less indentation
98
+ // This is a simplified heuristic
99
+ if (i + 1 < lines.length) {
100
+ const nextLine = lines[i + 1];
101
+ if (nextLine.match(/^(?:def|class|@|\S)/) && !nextLine.match(/^\s*#/)) {
102
+ const lineCount = lineNum - currentFunction.startLine + 1;
103
+ if (lineCount >= WARNING_THRESHOLD) {
104
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
105
+ }
106
+ currentFunction = null;
107
+ }
108
+ }
109
+ }
110
+ else if (currentFunction.braceDepth <= 0) {
111
+ // For brace-based languages, function ends when braces balance
112
+ const lineCount = lineNum - currentFunction.startLine + 1;
113
+ if (lineCount >= WARNING_THRESHOLD) {
114
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
115
+ }
116
+ currentFunction = null;
117
+ }
118
+ }
119
+ }
120
+ // Handle function that extends to end of file
121
+ if (currentFunction) {
122
+ const lineCount = lines.length - currentFunction.startLine + 1;
123
+ if (lineCount >= WARNING_THRESHOLD) {
124
+ horrors.push(createHorror(filePath, currentFunction.name, currentFunction.startLine, lineCount));
125
+ }
126
+ }
127
+ return horrors;
128
+ }
129
+ function getPatterns(ext) {
130
+ switch (ext) {
131
+ case '.ts':
132
+ case '.tsx':
133
+ case '.js':
134
+ case '.jsx':
135
+ return [
136
+ FUNCTION_PATTERNS.jsFunction,
137
+ FUNCTION_PATTERNS.jsArrow,
138
+ FUNCTION_PATTERNS.jsMethod,
139
+ ];
140
+ case '.py':
141
+ return [FUNCTION_PATTERNS.pyFunction];
142
+ case '.go':
143
+ return [FUNCTION_PATTERNS.goFunction];
144
+ default:
145
+ // Default to JS-like patterns
146
+ return [FUNCTION_PATTERNS.jsFunction, FUNCTION_PATTERNS.jsMethod];
147
+ }
148
+ }
149
+ function countBraces(line) {
150
+ // Simple brace counting (doesn't handle strings/comments perfectly)
151
+ let count = 0;
152
+ for (const char of line) {
153
+ if (char === '{')
154
+ count++;
155
+ if (char === '}')
156
+ count--;
157
+ }
158
+ return count;
159
+ }
160
+ function createHorror(file, functionName, lineStart, lineCount) {
161
+ return {
162
+ file,
163
+ functionName,
164
+ lineStart,
165
+ lineCount,
166
+ severity: lineCount >= CRITICAL_THRESHOLD ? 'critical' : 'warning',
167
+ };
168
+ }
169
+ /**
170
+ * Run eldritch horror detection on a directory.
171
+ */
172
+ export function scanForHorrors(dir) {
173
+ const files = scanDirectory(dir);
174
+ return detectEldritchHorrors(files);
175
+ }
176
+ // Utility to scan directory (matching audit.ts pattern)
177
+ const IGNORE_DIRS = ['node_modules', 'dist', 'coverage', '.git', '.vibe-check', '__pycache__'];
178
+ function scanDirectory(dir) {
179
+ const results = [];
180
+ try {
181
+ const list = fs.readdirSync(dir);
182
+ for (const file of list) {
183
+ const filePath = path.join(dir, file);
184
+ const stat = fs.statSync(filePath);
185
+ if (stat && stat.isDirectory()) {
186
+ if (!IGNORE_DIRS.includes(file) && !file.startsWith('.')) {
187
+ results.push(...scanDirectory(filePath));
188
+ }
189
+ }
190
+ else {
191
+ if (file.match(/\.(ts|js|jsx|tsx|py|go)$/)) {
192
+ results.push(filePath);
193
+ }
194
+ }
195
+ }
196
+ }
197
+ catch {
198
+ // Silently skip unreadable directories
199
+ }
200
+ return results;
201
+ }
202
+ //# sourceMappingURL=eldritch.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"eldritch.js","sourceRoot":"","sources":["../../src/analyzers/eldritch.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * Modularity Analyzer
3
+ *
4
+ * Pattern-aware modularity assessment that goes beyond simple LOC counting.
5
+ * Recognizes that a well-organized 2,500-line file can be more maintainable
6
+ * than a poorly-structured 300-line file.
7
+ *
8
+ * Based on research into:
9
+ * - K8s-style controller patterns
10
+ * - Cohesion metrics (LCOM)
11
+ * - Coupling analysis (CBO, fan-in/fan-out)
12
+ * - Single Responsibility Principle indicators
13
+ */
14
+ export interface ModularityResult {
15
+ files: FileModularity[];
16
+ summary: ModularitySummary;
17
+ exempted: ExemptedFile[];
18
+ }
19
+ export interface FileModularity {
20
+ file: string;
21
+ lines: number;
22
+ pattern: FilePattern | null;
23
+ score: number;
24
+ rating: ModularityRating;
25
+ flags: ModularityFlag[];
26
+ details: ModularityDetails;
27
+ }
28
+ export interface ModularityDetails {
29
+ hasSections: boolean;
30
+ sectionCount: number;
31
+ exportCount: number;
32
+ importCount: number;
33
+ hasNestedClasses: boolean;
34
+ methodCount: number;
35
+ }
36
+ export interface ModularitySummary {
37
+ totalFiles: number;
38
+ totalLines: number;
39
+ avgScore: number;
40
+ distribution: {
41
+ elite: number;
42
+ good: number;
43
+ acceptable: number;
44
+ needsWork: number;
45
+ poor: number;
46
+ };
47
+ largestFiles: {
48
+ file: string;
49
+ lines: number;
50
+ score: number;
51
+ }[];
52
+ }
53
+ export interface ExemptedFile {
54
+ file: string;
55
+ lines: number;
56
+ reason: string;
57
+ }
58
+ export type ModularityRating = 'elite' | 'good' | 'acceptable' | 'needs-work' | 'poor';
59
+ export type ModularityFlag = 'no-single-responsibility' | 'no-internal-structure' | 'high-coupling' | 'low-cohesion' | 'missing-tests' | 'god-class' | 'utility-grab-bag';
60
+ export type FilePattern = 'controller' | 'store' | 'routes' | 'types' | 'state-machine' | 'test' | 'generated' | 'component' | 'middleware' | 'utility';
61
+ export interface ModularityOptions {
62
+ minLines?: number;
63
+ includeAll?: boolean;
64
+ patterns?: FilePattern[];
65
+ }
66
+ export declare function analyzeModularity(rootDir: string, options?: ModularityOptions): ModularityResult;
67
+ //# sourceMappingURL=modularity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"modularity.d.ts","sourceRoot":"","sources":["../../src/analyzers/modularity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAUH,MAAM,WAAW,gBAAgB;IAC/B,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,iBAAiB,CAAC;IAC3B,QAAQ,EAAE,YAAY,EAAE,CAAC;CAC1B;AAED,MAAM,WAAW,cAAc;IAC7B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,OAAO,EAAE,WAAW,GAAG,IAAI,CAAC;IAC5B,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,gBAAgB,CAAC;IACzB,KAAK,EAAE,cAAc,EAAE,CAAC;IACxB,OAAO,EAAE,iBAAiB,CAAC;CAC5B;AAED,MAAM,WAAW,iBAAiB;IAChC,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,CAAC;IACpB,WAAW,EAAE,MAAM,CAAC;IACpB,gBAAgB,EAAE,OAAO,CAAC;IAC1B,WAAW,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,iBAAiB;IAChC,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE;QACZ,KAAK,EAAE,MAAM,CAAC;QACd,IAAI,EAAE,MAAM,CAAC;QACb,UAAU,EAAE,MAAM,CAAC;QACnB,SAAS,EAAE,MAAM,CAAC;QAClB,IAAI,EAAE,MAAM,CAAC;KACd,CAAC;IACF,YAAY,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAC;QAAC,KAAK,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAChE;AAED,MAAM,WAAW,YAAY;IAC3B,IAAI,EAAE,MAAM,CAAC;IACb,KAAK,EAAE,MAAM,CAAC;IACd,MAAM,EAAE,MAAM,CAAC;CAChB;AAED,MAAM,MAAM,gBAAgB,GAAG,OAAO,GAAG,MAAM,GAAG,YAAY,GAAG,YAAY,GAAG,MAAM,CAAC;AAEvF,MAAM,MAAM,cAAc,GACtB,0BAA0B,GAC1B,uBAAuB,GACvB,eAAe,GACf,cAAc,GACd,eAAe,GACf,WAAW,GACX,kBAAkB,CAAC;AAEvB,MAAM,MAAM,WAAW,GACnB,YAAY,GACZ,OAAO,GACP,QAAQ,GACR,OAAO,GACP,eAAe,GACf,MAAM,GACN,WAAW,GACX,WAAW,GACX,YAAY,GACZ,SAAS,CAAC;AAyMd,MAAM,WAAW,iBAAiB;IAChC,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,UAAU,CAAC,EAAE,OAAO,CAAC;IACrB,QAAQ,CAAC,EAAE,WAAW,EAAE,CAAC;CAC1B;AAED,wBAAgB,iBAAiB,CAC/B,OAAO,EAAE,MAAM,EACf,OAAO,GAAE,iBAAsB,GAC9B,gBAAgB,CAoClB"}