logicstamp-context 0.7.1 → 0.8.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/README.md +10 -1
- package/dist/cli/commands/clean.d.ts +2 -1
- package/dist/cli/commands/clean.d.ts.map +1 -1
- package/dist/cli/commands/clean.js +30 -2
- package/dist/cli/commands/clean.js.map +1 -1
- package/dist/cli/commands/compare/cleanup.d.ts +8 -0
- package/dist/cli/commands/compare/cleanup.d.ts.map +1 -0
- package/dist/cli/commands/compare/cleanup.js +27 -0
- package/dist/cli/commands/compare/cleanup.js.map +1 -0
- package/dist/cli/commands/compare/core.d.ts +29 -0
- package/dist/cli/commands/compare/core.d.ts.map +1 -0
- package/dist/cli/commands/compare/core.js +249 -0
- package/dist/cli/commands/compare/core.js.map +1 -0
- package/dist/cli/commands/compare/display.d.ts +9 -0
- package/dist/cli/commands/compare/display.d.ts.map +1 -0
- package/dist/cli/commands/compare/display.js +251 -0
- package/dist/cli/commands/compare/display.js.map +1 -0
- package/dist/cli/commands/compare/index.d.ts +26 -0
- package/dist/cli/commands/compare/index.d.ts.map +1 -0
- package/dist/cli/commands/compare/index.js +33 -0
- package/dist/cli/commands/compare/index.js.map +1 -0
- package/dist/cli/commands/compare/multiFile.d.ts +16 -0
- package/dist/cli/commands/compare/multiFile.d.ts.map +1 -0
- package/dist/cli/commands/compare/multiFile.js +113 -0
- package/dist/cli/commands/compare/multiFile.js.map +1 -0
- package/dist/cli/commands/compare/singleFile.d.ts +20 -0
- package/dist/cli/commands/compare/singleFile.d.ts.map +1 -0
- package/dist/cli/commands/compare/singleFile.js +341 -0
- package/dist/cli/commands/compare/singleFile.js.map +1 -0
- package/dist/cli/commands/{compare.d.ts → compare/types.d.ts} +21 -28
- package/dist/cli/commands/compare/types.d.ts.map +1 -0
- package/dist/cli/commands/compare/types.js +5 -0
- package/dist/cli/commands/compare/types.js.map +1 -0
- package/dist/cli/commands/compare/utils.d.ts +20 -0
- package/dist/cli/commands/compare/utils.d.ts.map +1 -0
- package/dist/cli/commands/compare/utils.js +94 -0
- package/dist/cli/commands/compare/utils.js.map +1 -0
- package/dist/cli/commands/context/watchMode/watchMode.d.ts.map +1 -1
- package/dist/cli/commands/context/watchMode/watchMode.js +2 -107
- package/dist/cli/commands/context/watchMode/watchMode.js.map +1 -1
- package/dist/cli/commands/context.d.ts +1 -0
- package/dist/cli/commands/context.d.ts.map +1 -1
- package/dist/cli/commands/context.js +3 -1
- package/dist/cli/commands/context.js.map +1 -1
- package/dist/cli/handlers/compareHandler.d.ts.map +1 -1
- package/dist/cli/handlers/compareHandler.js +297 -9
- package/dist/cli/handlers/compareHandler.js.map +1 -1
- package/dist/cli/index.js +1 -1
- package/dist/cli/index.js.map +1 -1
- package/dist/cli/parser/argumentParser.d.ts +2 -0
- package/dist/cli/parser/argumentParser.d.ts.map +1 -1
- package/dist/cli/parser/argumentParser.js +20 -2
- package/dist/cli/parser/argumentParser.js.map +1 -1
- package/dist/cli/parser/helpText.d.ts.map +1 -1
- package/dist/cli/parser/helpText.js +29 -0
- package/dist/cli/parser/helpText.js.map +1 -1
- package/dist/core/violations.d.ts +36 -0
- package/dist/core/violations.d.ts.map +1 -0
- package/dist/core/violations.js +292 -0
- package/dist/core/violations.js.map +1 -0
- package/dist/extractors/shared/propTypeNormalizer.d.ts.map +1 -1
- package/dist/extractors/shared/propTypeNormalizer.js +2 -1
- package/dist/extractors/shared/propTypeNormalizer.js.map +1 -1
- package/dist/index.d.ts +2 -2
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +1 -1
- package/dist/index.js.map +1 -1
- package/dist/utils/fileLock.d.ts.map +1 -1
- package/dist/utils/fileLock.js +79 -5
- package/dist/utils/fileLock.js.map +1 -1
- package/dist/utils/git.d.ts +135 -0
- package/dist/utils/git.d.ts.map +1 -0
- package/dist/utils/git.js +429 -0
- package/dist/utils/git.js.map +1 -0
- package/dist/utils/hash.d.ts.map +1 -1
- package/dist/utils/hash.js +20 -4
- package/dist/utils/hash.js.map +1 -1
- package/package.json +2 -1
- package/dist/cli/commands/compare.d.ts.map +0 -1
- package/dist/cli/commands/compare.js +0 -648
- package/dist/cli/commands/compare.js.map +0 -1
|
@@ -0,0 +1,251 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Display formatting for compare command results
|
|
3
|
+
*/
|
|
4
|
+
import { formatTokenCount } from '../../../utils/tokens.js';
|
|
5
|
+
/**
|
|
6
|
+
* Format and display multi-file comparison results
|
|
7
|
+
*/
|
|
8
|
+
export function displayMultiFileCompareResult(result, stats, quiet) {
|
|
9
|
+
// Skip status header in quiet mode unless there's drift
|
|
10
|
+
if (quiet && result.status === 'PASS') {
|
|
11
|
+
// Minimal output in quiet mode for PASS
|
|
12
|
+
process.stdout.write('✓\n');
|
|
13
|
+
}
|
|
14
|
+
else if (!quiet || result.status === 'DRIFT') {
|
|
15
|
+
console.log(`\n${result.status === 'PASS' ? '✅' : '⚠️'} ${result.status}\n`);
|
|
16
|
+
}
|
|
17
|
+
// Skip summaries in quiet mode
|
|
18
|
+
if (!quiet) {
|
|
19
|
+
// Display folder-level summary
|
|
20
|
+
console.log('📁 Folder Summary:');
|
|
21
|
+
console.log(` Total folders: ${result.summary.totalFolders}`);
|
|
22
|
+
if (result.summary.addedFolders > 0) {
|
|
23
|
+
console.log(` ➕ Added folders: ${result.summary.addedFolders}`);
|
|
24
|
+
}
|
|
25
|
+
if (result.summary.orphanedFolders > 0) {
|
|
26
|
+
console.log(` 🗑️ Orphaned folders: ${result.summary.orphanedFolders}`);
|
|
27
|
+
}
|
|
28
|
+
if (result.summary.driftFolders > 0) {
|
|
29
|
+
console.log(` ~ Changed folders: ${result.summary.driftFolders}`);
|
|
30
|
+
}
|
|
31
|
+
if (result.summary.passFolders > 0) {
|
|
32
|
+
console.log(` ✓ Unchanged folders: ${result.summary.passFolders}`);
|
|
33
|
+
}
|
|
34
|
+
console.log();
|
|
35
|
+
// Display component-level summary
|
|
36
|
+
if (result.status === 'DRIFT') {
|
|
37
|
+
console.log('📦 Component Summary:');
|
|
38
|
+
if (result.summary.totalComponentsAdded > 0) {
|
|
39
|
+
console.log(` + Added: ${result.summary.totalComponentsAdded}`);
|
|
40
|
+
}
|
|
41
|
+
if (result.summary.totalComponentsRemoved > 0) {
|
|
42
|
+
console.log(` - Removed: ${result.summary.totalComponentsRemoved}`);
|
|
43
|
+
}
|
|
44
|
+
if (result.summary.totalComponentsChanged > 0) {
|
|
45
|
+
console.log(` ~ Changed: ${result.summary.totalComponentsChanged}`);
|
|
46
|
+
}
|
|
47
|
+
console.log();
|
|
48
|
+
}
|
|
49
|
+
// Display detailed folder results
|
|
50
|
+
console.log('📂 Folder Details:');
|
|
51
|
+
if (stats) {
|
|
52
|
+
console.log(' ⚠️ Current mode = tokenizer-based.');
|
|
53
|
+
console.log(' Other modes / raw source = heuristic.');
|
|
54
|
+
console.log(' For precise per-mode breakdown, use "stamp context --compare-modes".');
|
|
55
|
+
}
|
|
56
|
+
console.log();
|
|
57
|
+
}
|
|
58
|
+
for (const folder of result.folders) {
|
|
59
|
+
if (folder.status === 'ADDED') {
|
|
60
|
+
console.log(` ➕ ADDED FILE: ${folder.contextFile}`);
|
|
61
|
+
console.log(` Path: ${folder.folderPath}`);
|
|
62
|
+
console.log();
|
|
63
|
+
}
|
|
64
|
+
else if (folder.status === 'ORPHANED') {
|
|
65
|
+
console.log(` 🗑️ ORPHANED FILE: ${folder.contextFile}`);
|
|
66
|
+
console.log(` Path: ${folder.folderPath}`);
|
|
67
|
+
console.log();
|
|
68
|
+
}
|
|
69
|
+
else if (folder.status === 'DRIFT') {
|
|
70
|
+
console.log(` ⚠️ DRIFT: ${folder.contextFile}`);
|
|
71
|
+
console.log(` Path: ${folder.folderPath}`);
|
|
72
|
+
if (folder.componentResult) {
|
|
73
|
+
const cr = folder.componentResult;
|
|
74
|
+
if (cr.added.length > 0) {
|
|
75
|
+
console.log(` + Added components (${cr.added.length}):`);
|
|
76
|
+
cr.added.forEach(id => console.log(` + ${id}`));
|
|
77
|
+
}
|
|
78
|
+
if (cr.removed.length > 0) {
|
|
79
|
+
console.log(` - Removed components (${cr.removed.length}):`);
|
|
80
|
+
cr.removed.forEach(id => console.log(` - ${id}`));
|
|
81
|
+
}
|
|
82
|
+
if (cr.changed.length > 0) {
|
|
83
|
+
console.log(` ~ Changed components (${cr.changed.length}):`);
|
|
84
|
+
cr.changed.forEach(({ id, deltas }) => {
|
|
85
|
+
console.log(` ~ ${id}`);
|
|
86
|
+
deltas.forEach(delta => {
|
|
87
|
+
console.log(` Δ ${delta.type}`);
|
|
88
|
+
if (delta.type === 'hash') {
|
|
89
|
+
console.log(` old: ${delta.old}`);
|
|
90
|
+
console.log(` new: ${delta.new}`);
|
|
91
|
+
}
|
|
92
|
+
else if (delta.type === 'props' || delta.type === 'emits') {
|
|
93
|
+
// props/emits are now full objects - compute diff on display
|
|
94
|
+
const oldObj = (delta.old && typeof delta.old === 'object') ? delta.old : {};
|
|
95
|
+
const newObj = (delta.new && typeof delta.new === 'object') ? delta.new : {};
|
|
96
|
+
const oldKeys = Object.keys(oldObj);
|
|
97
|
+
const newKeys = Object.keys(newObj);
|
|
98
|
+
const oldSet = new Set(oldKeys);
|
|
99
|
+
const newSet = new Set(newKeys);
|
|
100
|
+
const removed = oldKeys.filter((key) => !newSet.has(key));
|
|
101
|
+
const added = newKeys.filter((key) => !oldSet.has(key));
|
|
102
|
+
const changed = oldKeys.filter((key) => {
|
|
103
|
+
if (newSet.has(key)) {
|
|
104
|
+
return JSON.stringify(oldObj[key]) !== JSON.stringify(newObj[key]);
|
|
105
|
+
}
|
|
106
|
+
return false;
|
|
107
|
+
});
|
|
108
|
+
if (removed.length > 0) {
|
|
109
|
+
removed.forEach((key) => console.log(` - ${key}`));
|
|
110
|
+
}
|
|
111
|
+
if (added.length > 0) {
|
|
112
|
+
added.forEach((key) => console.log(` + ${key}`));
|
|
113
|
+
}
|
|
114
|
+
if (changed.length > 0) {
|
|
115
|
+
changed.forEach((key) => {
|
|
116
|
+
const oldStr = typeof oldObj[key] === 'string' ? oldObj[key] : JSON.stringify(oldObj[key]);
|
|
117
|
+
const newStr = typeof newObj[key] === 'string' ? newObj[key] : JSON.stringify(newObj[key]);
|
|
118
|
+
console.log(` ~ ${key}: ${oldStr} → ${newStr}`);
|
|
119
|
+
});
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
else if (delta.type === 'imports' || delta.type === 'hooks' || delta.type === 'functions' ||
|
|
123
|
+
delta.type === 'components' || delta.type === 'variables') {
|
|
124
|
+
const oldSet = new Set(delta.old);
|
|
125
|
+
const newSet = new Set(delta.new);
|
|
126
|
+
const removed = delta.old.filter((item) => !newSet.has(item));
|
|
127
|
+
const added = delta.new.filter((item) => !oldSet.has(item));
|
|
128
|
+
if (removed.length > 0) {
|
|
129
|
+
removed.forEach((item) => console.log(` - ${item}`));
|
|
130
|
+
}
|
|
131
|
+
if (added.length > 0) {
|
|
132
|
+
added.forEach((item) => console.log(` + ${item}`));
|
|
133
|
+
}
|
|
134
|
+
if (removed.length === 0 && added.length === 0) {
|
|
135
|
+
console.log(` (order changed)`);
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
else if (delta.type === 'state') {
|
|
139
|
+
const oldState = delta.old;
|
|
140
|
+
const newState = delta.new;
|
|
141
|
+
const oldKeys = Object.keys(oldState);
|
|
142
|
+
const newKeys = Object.keys(newState);
|
|
143
|
+
const oldSet = new Set(oldKeys);
|
|
144
|
+
const newSet = new Set(newKeys);
|
|
145
|
+
// Find removed state variables
|
|
146
|
+
const removed = oldKeys.filter((key) => !newSet.has(key));
|
|
147
|
+
// Find added state variables
|
|
148
|
+
const added = newKeys.filter((key) => !oldSet.has(key));
|
|
149
|
+
// Find changed state variables (type changed)
|
|
150
|
+
const changed = oldKeys.filter((key) => {
|
|
151
|
+
if (newSet.has(key)) {
|
|
152
|
+
return JSON.stringify(oldState[key]) !== JSON.stringify(newState[key]);
|
|
153
|
+
}
|
|
154
|
+
return false;
|
|
155
|
+
});
|
|
156
|
+
if (removed.length > 0) {
|
|
157
|
+
removed.forEach((key) => console.log(` - ${key}`));
|
|
158
|
+
}
|
|
159
|
+
if (added.length > 0) {
|
|
160
|
+
added.forEach((key) => console.log(` + ${key}`));
|
|
161
|
+
}
|
|
162
|
+
if (changed.length > 0) {
|
|
163
|
+
changed.forEach((key) => {
|
|
164
|
+
console.log(` ~ ${key}: ${JSON.stringify(oldState[key])} → ${JSON.stringify(newState[key])}`);
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
else if (delta.type === 'exports') {
|
|
169
|
+
console.log(` ${delta.old} → ${delta.new}`);
|
|
170
|
+
}
|
|
171
|
+
else if (delta.type === 'apiSignature') {
|
|
172
|
+
const oldSig = delta.old;
|
|
173
|
+
const newSig = delta.new;
|
|
174
|
+
// Handle null/undefined cases
|
|
175
|
+
if (!oldSig && newSig) {
|
|
176
|
+
console.log(` + Added API signature`);
|
|
177
|
+
if (newSig.parameters)
|
|
178
|
+
console.log(` parameters: ${JSON.stringify(newSig.parameters)}`);
|
|
179
|
+
if (newSig.returnType)
|
|
180
|
+
console.log(` returnType: ${newSig.returnType}`);
|
|
181
|
+
if (newSig.requestType)
|
|
182
|
+
console.log(` requestType: ${newSig.requestType}`);
|
|
183
|
+
if (newSig.responseType)
|
|
184
|
+
console.log(` responseType: ${newSig.responseType}`);
|
|
185
|
+
}
|
|
186
|
+
else if (oldSig && !newSig) {
|
|
187
|
+
console.log(` - Removed API signature`);
|
|
188
|
+
}
|
|
189
|
+
else if (oldSig && newSig) {
|
|
190
|
+
// Compare individual fields
|
|
191
|
+
const oldParams = oldSig.parameters ?? {};
|
|
192
|
+
const newParams = newSig.parameters ?? {};
|
|
193
|
+
const oldKeys = Object.keys(oldParams);
|
|
194
|
+
const newKeys = Object.keys(newParams);
|
|
195
|
+
const paramRemoved = oldKeys.filter(k => !(k in newParams));
|
|
196
|
+
const paramAdded = newKeys.filter(k => !(k in oldParams));
|
|
197
|
+
const paramChanged = oldKeys.filter(k => k in newParams && oldParams[k] !== newParams[k]);
|
|
198
|
+
if (paramRemoved.length > 0) {
|
|
199
|
+
paramRemoved.forEach(k => console.log(` - parameters.${k}: ${oldParams[k]}`));
|
|
200
|
+
}
|
|
201
|
+
if (paramAdded.length > 0) {
|
|
202
|
+
paramAdded.forEach(k => console.log(` + parameters.${k}: ${newParams[k]}`));
|
|
203
|
+
}
|
|
204
|
+
if (paramChanged.length > 0) {
|
|
205
|
+
paramChanged.forEach(k => console.log(` ~ parameters.${k}: ${oldParams[k]} → ${newParams[k]}`));
|
|
206
|
+
}
|
|
207
|
+
if (oldSig.returnType !== newSig.returnType) {
|
|
208
|
+
console.log(` ~ returnType: ${oldSig.returnType ?? '(none)'} → ${newSig.returnType ?? '(none)'}`);
|
|
209
|
+
}
|
|
210
|
+
if (oldSig.requestType !== newSig.requestType) {
|
|
211
|
+
console.log(` ~ requestType: ${oldSig.requestType ?? '(none)'} → ${newSig.requestType ?? '(none)'}`);
|
|
212
|
+
}
|
|
213
|
+
if (oldSig.responseType !== newSig.responseType) {
|
|
214
|
+
console.log(` ~ responseType: ${oldSig.responseType ?? '(none)'} → ${newSig.responseType ?? '(none)'}`);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
});
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
if (stats && !quiet && folder.tokenDelta) {
|
|
223
|
+
const sign = folder.tokenDelta.gpt4 > 0 ? '+' : '';
|
|
224
|
+
console.log(` Token Δ: ${sign}${formatTokenCount(folder.tokenDelta.gpt4)} (GPT-4) | ${sign}${formatTokenCount(folder.tokenDelta.claude)} (Claude)`);
|
|
225
|
+
}
|
|
226
|
+
console.log();
|
|
227
|
+
}
|
|
228
|
+
else if (folder.status === 'PASS') {
|
|
229
|
+
// Skip PASS folders in quiet mode
|
|
230
|
+
if (!quiet) {
|
|
231
|
+
console.log(` ✅ PASS: ${folder.contextFile}`);
|
|
232
|
+
console.log(` Path: ${folder.folderPath}`);
|
|
233
|
+
console.log();
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
// Display orphaned files on disk (only if not in quiet mode, or show as diff)
|
|
238
|
+
if (result.orphanedFiles && result.orphanedFiles.length > 0) {
|
|
239
|
+
if (!quiet) {
|
|
240
|
+
console.log('🗑️ Orphaned Files on Disk:');
|
|
241
|
+
console.log(' (These files exist on disk but are not in the new index)\n');
|
|
242
|
+
}
|
|
243
|
+
result.orphanedFiles.forEach(file => {
|
|
244
|
+
console.log(` 🗑️ ${file}`);
|
|
245
|
+
});
|
|
246
|
+
if (!quiet) {
|
|
247
|
+
console.log();
|
|
248
|
+
}
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
//# sourceMappingURL=display.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"display.js","sourceRoot":"","sources":["../../../../src/cli/commands/compare/display.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,EAAE,gBAAgB,EAAE,MAAM,0BAA0B,CAAC;AAG5D;;GAEG;AACH,MAAM,UAAU,6BAA6B,CAAC,MAA8B,EAAE,KAAc,EAAE,KAAe;IAC3G,wDAAwD;IACxD,IAAI,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;QACtC,wCAAwC;QACxC,OAAO,CAAC,MAAM,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;IAC9B,CAAC;SAAM,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC/C,OAAO,CAAC,GAAG,CAAC,KAAK,MAAM,CAAC,MAAM,KAAK,MAAM,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC;IAChF,CAAC;IAED,+BAA+B;IAC/B,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,+BAA+B;QAC/B,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,OAAO,CAAC,GAAG,CAAC,qBAAqB,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QAChE,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,uBAAuB,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACpE,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,eAAe,GAAG,CAAC,EAAE,CAAC;YACvC,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,OAAO,CAAC,eAAe,EAAE,CAAC,CAAC;QAC7E,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,GAAG,CAAC,EAAE,CAAC;YACpC,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,OAAO,CAAC,YAAY,EAAE,CAAC,CAAC;QACvE,CAAC;QACD,IAAI,MAAM,CAAC,OAAO,CAAC,WAAW,GAAG,CAAC,EAAE,CAAC;YACnC,OAAO,CAAC,GAAG,CAAC,4BAA4B,MAAM,CAAC,OAAO,CAAC,WAAW,EAAE,CAAC,CAAC;QACxE,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAEd,kCAAkC;QAClC,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,uBAAuB,CAAC,CAAC;YACrC,IAAI,MAAM,CAAC,OAAO,CAAC,oBAAoB,GAAG,CAAC,EAAE,CAAC;gBAC5C,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,OAAO,CAAC,oBAAoB,EAAE,CAAC,CAAC;YACpE,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC;YACxE,CAAC;YACD,IAAI,MAAM,CAAC,OAAO,CAAC,sBAAsB,GAAG,CAAC,EAAE,CAAC;gBAC9C,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,OAAO,CAAC,sBAAsB,EAAE,CAAC,CAAC;YACxE,CAAC;YACD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;QAED,kCAAkC;QAClC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;QAClC,IAAI,KAAK,EAAE,CAAC;YACV,OAAO,CAAC,GAAG,CAAC,wCAAwC,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,6CAA6C,CAAC,CAAC;YAC3D,OAAO,CAAC,GAAG,CAAC,4EAA4E,CAAC,CAAC;QAC5F,CAAC;QACD,OAAO,CAAC,GAAG,EAAE,CAAC;IAChB,CAAC;IAED,KAAK,MAAM,MAAM,IAAI,MAAM,CAAC,OAAO,EAAE,CAAC;QACpC,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YAC9B,OAAO,CAAC,GAAG,CAAC,oBAAoB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YACtD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,UAAU,EAAE,CAAC;YACxC,OAAO,CAAC,GAAG,CAAC,0BAA0B,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YAC5D,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YAChD,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;YACrC,OAAO,CAAC,GAAG,CAAC,iBAAiB,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;YACnD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;YAEhD,IAAI,MAAM,CAAC,eAAe,EAAE,CAAC;gBAC3B,MAAM,EAAE,GAAG,MAAM,CAAC,eAAe,CAAC;gBAClC,IAAI,EAAE,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBACxB,OAAO,CAAC,GAAG,CAAC,6BAA6B,EAAE,CAAC,KAAK,CAAC,MAAM,IAAI,CAAC,CAAC;oBAC9D,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;gBACzD,CAAC;gBACD,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;oBAClE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,EAAE,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC,CAAC;gBAC3D,CAAC;gBACD,IAAI,EAAE,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oBAC1B,OAAO,CAAC,GAAG,CAAC,+BAA+B,EAAE,CAAC,OAAO,CAAC,MAAM,IAAI,CAAC,CAAC;oBAClE,EAAE,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE,EAAE;wBACpC,OAAO,CAAC,GAAG,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;wBAC/B,MAAM,CAAC,OAAO,CAAC,KAAK,CAAC,EAAE;4BACrB,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,IAAI,EAAE,CAAC,CAAC;4BAEzC,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE,CAAC;gCAC1B,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;gCAC7C,OAAO,CAAC,GAAG,CAAC,oBAAoB,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;4BAC/C,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gCAC5D,6DAA6D;gCAC7D,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;gCACpG,MAAM,MAAM,GAAG,CAAC,KAAK,CAAC,GAAG,IAAI,OAAO,KAAK,CAAC,GAAG,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,GAA0B,CAAC,CAAC,CAAC,EAAE,CAAC;gCACpG,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gCACpC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;gCACpC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;gCAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;gCAEhC,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gCAClE,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gCAChE,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;oCAC7C,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wCACpB,OAAO,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;oCACrE,CAAC;oCACD,OAAO,KAAK,CAAC;gCACf,CAAC,CAAC,CAAC;gCAEH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC;gCACxE,CAAC;gCACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACrB,KAAK,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC;gCACtE,CAAC;gCACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE;wCAC9B,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;wCAC3F,MAAM,MAAM,GAAG,OAAO,MAAM,CAAC,GAAG,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;wCAC3F,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,KAAK,MAAM,MAAM,MAAM,EAAE,CAAC,CAAC;oCAC7D,CAAC,CAAC,CAAC;gCACL,CAAC;4BACH,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW;gCAChF,KAAK,CAAC,IAAI,KAAK,YAAY,IAAI,KAAK,CAAC,IAAI,KAAK,WAAW,EAAE,CAAC;gCACrE,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gCAClC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;gCAClC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gCACtE,MAAM,KAAK,GAAG,KAAK,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC;gCAEpE,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;gCAC1E,CAAC;gCACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACrB,KAAK,CAAC,OAAO,CAAC,CAAC,IAAY,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,IAAI,EAAE,CAAC,CAAC,CAAC;gCACxE,CAAC;gCACD,IAAI,OAAO,CAAC,MAAM,KAAK,CAAC,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;oCAC/C,OAAO,CAAC,GAAG,CAAC,6BAA6B,CAAC,CAAC;gCAC7C,CAAC;4BACH,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,OAAO,EAAE,CAAC;gCAClC,MAAM,QAAQ,GAAG,KAAK,CAAC,GAA0B,CAAC;gCAClD,MAAM,QAAQ,GAAG,KAAK,CAAC,GAA0B,CAAC;gCAClD,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gCACtC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;gCACtC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;gCAChC,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,OAAO,CAAC,CAAC;gCAEhC,+BAA+B;gCAC/B,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gCAClE,6BAA6B;gCAC7B,MAAM,KAAK,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC;gCAChE,8CAA8C;gCAC9C,MAAM,OAAO,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,GAAW,EAAE,EAAE;oCAC7C,IAAI,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,EAAE,CAAC;wCACpB,OAAO,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC;oCACzE,CAAC;oCACD,OAAO,KAAK,CAAC;gCACf,CAAC,CAAC,CAAC;gCAEH,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC;gCACxE,CAAC;gCACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACrB,KAAK,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,EAAE,CAAC,CAAC,CAAC;gCACtE,CAAC;gCACD,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;oCACvB,OAAO,CAAC,OAAO,CAAC,CAAC,GAAW,EAAE,EAAE;wCAC9B,OAAO,CAAC,GAAG,CAAC,iBAAiB,GAAG,KAAK,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,MAAM,IAAI,CAAC,SAAS,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC;oCAC3G,CAAC,CAAC,CAAC;gCACL,CAAC;4BACH,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,SAAS,EAAE,CAAC;gCACpC,OAAO,CAAC,GAAG,CAAC,eAAe,KAAK,CAAC,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE,CAAC,CAAC;4BACzD,CAAC;iCAAM,IAAI,KAAK,CAAC,IAAI,KAAK,cAAc,EAAE,CAAC;gCACzC,MAAM,MAAM,GAAG,KAAK,CAAC,GAAiC,CAAC;gCACvD,MAAM,MAAM,GAAG,KAAK,CAAC,GAAiC,CAAC;gCAEvD,8BAA8B;gCAC9B,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE,CAAC;oCACtB,OAAO,CAAC,GAAG,CAAC,mCAAmC,CAAC,CAAC;oCACjD,IAAI,MAAM,CAAC,UAAU;wCAAE,OAAO,CAAC,GAAG,CAAC,6BAA6B,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,UAAU,CAAC,EAAE,CAAC,CAAC;oCACrG,IAAI,MAAM,CAAC,UAAU;wCAAE,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;oCACrF,IAAI,MAAM,CAAC,WAAW;wCAAE,OAAO,CAAC,GAAG,CAAC,8BAA8B,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;oCACxF,IAAI,MAAM,CAAC,YAAY;wCAAE,OAAO,CAAC,GAAG,CAAC,+BAA+B,MAAM,CAAC,YAAY,EAAE,CAAC,CAAC;gCAC7F,CAAC;qCAAM,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE,CAAC;oCAC7B,OAAO,CAAC,GAAG,CAAC,qCAAqC,CAAC,CAAC;gCACrD,CAAC;qCAAM,IAAI,MAAM,IAAI,MAAM,EAAE,CAAC;oCAC5B,4BAA4B;oCAC5B,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;oCAC1C,MAAM,SAAS,GAAG,MAAM,CAAC,UAAU,IAAI,EAAE,CAAC;oCAC1C,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oCACvC,MAAM,OAAO,GAAG,MAAM,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;oCACvC,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;oCAC5D,MAAM,UAAU,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,IAAI,SAAS,CAAC,CAAC,CAAC;oCAC1D,MAAM,YAAY,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,SAAS,IAAI,SAAS,CAAC,CAAC,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;oCAE1F,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wCAC5B,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oCAC3F,CAAC;oCACD,IAAI,UAAU,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wCAC1B,UAAU,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oCACzF,CAAC;oCACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;wCAC5B,YAAY,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,OAAO,CAAC,GAAG,CAAC,4BAA4B,CAAC,KAAK,SAAS,CAAC,CAAC,CAAC,MAAM,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;oCAC7G,CAAC;oCAED,IAAI,MAAM,CAAC,UAAU,KAAK,MAAM,CAAC,UAAU,EAAE,CAAC;wCAC5C,OAAO,CAAC,GAAG,CAAC,6BAA6B,MAAM,CAAC,UAAU,IAAI,QAAQ,MAAM,MAAM,CAAC,UAAU,IAAI,QAAQ,EAAE,CAAC,CAAC;oCAC/G,CAAC;oCACD,IAAI,MAAM,CAAC,WAAW,KAAK,MAAM,CAAC,WAAW,EAAE,CAAC;wCAC9C,OAAO,CAAC,GAAG,CAAC,8BAA8B,MAAM,CAAC,WAAW,IAAI,QAAQ,MAAM,MAAM,CAAC,WAAW,IAAI,QAAQ,EAAE,CAAC,CAAC;oCAClH,CAAC;oCACD,IAAI,MAAM,CAAC,YAAY,KAAK,MAAM,CAAC,YAAY,EAAE,CAAC;wCAChD,OAAO,CAAC,GAAG,CAAC,+BAA+B,MAAM,CAAC,YAAY,IAAI,QAAQ,MAAM,MAAM,CAAC,YAAY,IAAI,QAAQ,EAAE,CAAC,CAAC;oCACrH,CAAC;gCACH,CAAC;4BACH,CAAC;wBACH,CAAC,CAAC,CAAC;oBACL,CAAC,CAAC,CAAC;gBACL,CAAC;YACH,CAAC;YAED,IAAI,KAAK,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,UAAU,EAAE,CAAC;gBACzC,MAAM,IAAI,GAAG,MAAM,CAAC,UAAU,CAAC,IAAI,GAAG,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC;gBACnD,OAAO,CAAC,GAAG,CAAC,kBAAkB,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,IAAI,CAAC,cAAc,IAAI,GAAG,gBAAgB,CAAC,MAAM,CAAC,UAAU,CAAC,MAAM,CAAC,WAAW,CAAC,CAAC;YAC3J,CAAC;YAED,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;aAAM,IAAI,MAAM,CAAC,MAAM,KAAK,MAAM,EAAE,CAAC;YACpC,kCAAkC;YAClC,IAAI,CAAC,KAAK,EAAE,CAAC;gBACX,OAAO,CAAC,GAAG,CAAC,cAAc,MAAM,CAAC,WAAW,EAAE,CAAC,CAAC;gBAChD,OAAO,CAAC,GAAG,CAAC,eAAe,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC;gBAChD,OAAO,CAAC,GAAG,EAAE,CAAC;YAChB,CAAC;QACH,CAAC;IACH,CAAC;IAED,8EAA8E;IAC9E,IAAI,MAAM,CAAC,aAAa,IAAI,MAAM,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5D,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,CAAC,8BAA8B,CAAC,CAAC;YAC5C,OAAO,CAAC,GAAG,CAAC,+DAA+D,CAAC,CAAC;QAC/E,CAAC;QACD,MAAM,CAAC,aAAa,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE;YAClC,OAAO,CAAC,GAAG,CAAC,WAAW,IAAI,EAAE,CAAC,CAAC;QACjC,CAAC,CAAC,CAAC;QACH,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO,CAAC,GAAG,EAAE,CAAC;QAChB,CAAC;IACH,CAAC;AACH,CAAC"}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare command - Main entry point
|
|
3
|
+
*
|
|
4
|
+
* Public API exports for the compare command module.
|
|
5
|
+
* These utilities are used by the main compare command and can be
|
|
6
|
+
* imported by external consumers for building custom tooling.
|
|
7
|
+
*
|
|
8
|
+
* @module compare
|
|
9
|
+
*
|
|
10
|
+
* Core modules:
|
|
11
|
+
* - types: Type definitions and interfaces
|
|
12
|
+
* - core: Core comparison logic (indexing, diffing, normalization)
|
|
13
|
+
* - utils: Utility functions (token calculation, index loading, orphaned file detection)
|
|
14
|
+
* - singleFile: Single file comparison logic
|
|
15
|
+
* - multiFile: Multi-file comparison logic
|
|
16
|
+
* - display: Display formatting for comparison results
|
|
17
|
+
* - cleanup: Cleanup functions for orphaned files
|
|
18
|
+
*/
|
|
19
|
+
export * from './types.js';
|
|
20
|
+
export * from './core.js';
|
|
21
|
+
export * from './utils.js';
|
|
22
|
+
export * from './singleFile.js';
|
|
23
|
+
export * from './multiFile.js';
|
|
24
|
+
export * from './display.js';
|
|
25
|
+
export * from './cleanup.js';
|
|
26
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/compare/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAGH,cAAc,YAAY,CAAC;AAG3B,cAAc,WAAW,CAAC;AAG1B,cAAc,YAAY,CAAC;AAG3B,cAAc,iBAAiB,CAAC;AAGhC,cAAc,gBAAgB,CAAC;AAG/B,cAAc,cAAc,CAAC;AAG7B,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compare command - Main entry point
|
|
3
|
+
*
|
|
4
|
+
* Public API exports for the compare command module.
|
|
5
|
+
* These utilities are used by the main compare command and can be
|
|
6
|
+
* imported by external consumers for building custom tooling.
|
|
7
|
+
*
|
|
8
|
+
* @module compare
|
|
9
|
+
*
|
|
10
|
+
* Core modules:
|
|
11
|
+
* - types: Type definitions and interfaces
|
|
12
|
+
* - core: Core comparison logic (indexing, diffing, normalization)
|
|
13
|
+
* - utils: Utility functions (token calculation, index loading, orphaned file detection)
|
|
14
|
+
* - singleFile: Single file comparison logic
|
|
15
|
+
* - multiFile: Multi-file comparison logic
|
|
16
|
+
* - display: Display formatting for comparison results
|
|
17
|
+
* - cleanup: Cleanup functions for orphaned files
|
|
18
|
+
*/
|
|
19
|
+
// Types
|
|
20
|
+
export * from './types.js';
|
|
21
|
+
// Core comparison logic
|
|
22
|
+
export * from './core.js';
|
|
23
|
+
// Utility functions
|
|
24
|
+
export * from './utils.js';
|
|
25
|
+
// Single file comparison
|
|
26
|
+
export * from './singleFile.js';
|
|
27
|
+
// Multi-file comparison
|
|
28
|
+
export * from './multiFile.js';
|
|
29
|
+
// Display formatting
|
|
30
|
+
export * from './display.js';
|
|
31
|
+
// Cleanup functions
|
|
32
|
+
export * from './cleanup.js';
|
|
33
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../../src/cli/commands/compare/index.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;GAiBG;AAEH,QAAQ;AACR,cAAc,YAAY,CAAC;AAE3B,wBAAwB;AACxB,cAAc,WAAW,CAAC;AAE1B,oBAAoB;AACpB,cAAc,YAAY,CAAC;AAE3B,yBAAyB;AACzB,cAAc,iBAAiB,CAAC;AAEhC,wBAAwB;AACxB,cAAc,gBAAgB,CAAC;AAE/B,qBAAqB;AACrB,cAAc,cAAc,CAAC;AAE7B,oBAAoB;AACpB,cAAc,cAAc,CAAC"}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-file comparison logic
|
|
3
|
+
*/
|
|
4
|
+
import type { MultiFileCompareOptions, MultiFileCompareResult } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Multi-file comparison - compares all context files using context_main.json indices
|
|
7
|
+
* This is the comprehensive comparison that handles:
|
|
8
|
+
* 1. context_main.json as root index
|
|
9
|
+
* 2. All folder context.json files
|
|
10
|
+
* 3. ADDED FILE detection (new folders)
|
|
11
|
+
* 4. ORPHANED FILE detection (deleted folders)
|
|
12
|
+
* 5. DRIFT detection (changed files)
|
|
13
|
+
* 6. PASS detection (unchanged files)
|
|
14
|
+
*/
|
|
15
|
+
export declare function multiFileCompare(options: MultiFileCompareOptions): Promise<MultiFileCompareResult>;
|
|
16
|
+
//# sourceMappingURL=multiFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiFile.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/compare/multiFile.ts"],"names":[],"mappings":"AAAA;;GAEG;AAGH,OAAO,KAAK,EAAE,uBAAuB,EAAE,sBAAsB,EAAsC,MAAM,YAAY,CAAC;AAItH;;;;;;;;;GASG;AACH,wBAAsB,gBAAgB,CAAC,OAAO,EAAE,uBAAuB,GAAG,OAAO,CAAC,sBAAsB,CAAC,CA0GxG"}
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Multi-file comparison logic
|
|
3
|
+
*/
|
|
4
|
+
import { dirname, join } from 'node:path';
|
|
5
|
+
import { loadIndex, findOrphanedFiles } from './utils.js';
|
|
6
|
+
import { compareFolderContext } from './singleFile.js';
|
|
7
|
+
/**
|
|
8
|
+
* Multi-file comparison - compares all context files using context_main.json indices
|
|
9
|
+
* This is the comprehensive comparison that handles:
|
|
10
|
+
* 1. context_main.json as root index
|
|
11
|
+
* 2. All folder context.json files
|
|
12
|
+
* 3. ADDED FILE detection (new folders)
|
|
13
|
+
* 4. ORPHANED FILE detection (deleted folders)
|
|
14
|
+
* 5. DRIFT detection (changed files)
|
|
15
|
+
* 6. PASS detection (unchanged files)
|
|
16
|
+
*/
|
|
17
|
+
export async function multiFileCompare(options) {
|
|
18
|
+
const oldBaseDir = dirname(options.oldIndexFile);
|
|
19
|
+
const newBaseDir = dirname(options.newIndexFile);
|
|
20
|
+
// Load both index files
|
|
21
|
+
const oldIndex = await loadIndex(options.oldIndexFile);
|
|
22
|
+
const newIndex = await loadIndex(options.newIndexFile);
|
|
23
|
+
// Create maps for quick lookup
|
|
24
|
+
const oldFolderMap = new Map(oldIndex.folders.map(f => [f.contextFile, f]));
|
|
25
|
+
const newFolderMap = new Map(newIndex.folders.map(f => [f.contextFile, f]));
|
|
26
|
+
const folderResults = [];
|
|
27
|
+
let totalComponentsAdded = 0;
|
|
28
|
+
let totalComponentsRemoved = 0;
|
|
29
|
+
let totalComponentsChanged = 0;
|
|
30
|
+
// Compare folders that exist in both old and new
|
|
31
|
+
const allContextFiles = new Set([
|
|
32
|
+
...oldIndex.folders.map(f => f.contextFile),
|
|
33
|
+
...newIndex.folders.map(f => f.contextFile),
|
|
34
|
+
]);
|
|
35
|
+
for (const contextFile of allContextFiles) {
|
|
36
|
+
const oldFolder = oldFolderMap.get(contextFile);
|
|
37
|
+
const newFolder = newFolderMap.get(contextFile);
|
|
38
|
+
if (oldFolder && newFolder) {
|
|
39
|
+
// Folder exists in both - compare context files
|
|
40
|
+
const oldPath = join(oldBaseDir, oldFolder.contextFile);
|
|
41
|
+
const newPath = join(newBaseDir, newFolder.contextFile);
|
|
42
|
+
try {
|
|
43
|
+
const { result, tokenDelta } = await compareFolderContext(oldPath, newPath, options.stats || false, options.quiet, options.gitBaseline ?? false);
|
|
44
|
+
folderResults.push({
|
|
45
|
+
folderPath: newFolder.path,
|
|
46
|
+
contextFile: newFolder.contextFile,
|
|
47
|
+
status: result.status,
|
|
48
|
+
componentResult: result,
|
|
49
|
+
tokenDelta,
|
|
50
|
+
});
|
|
51
|
+
if (result.status === 'DRIFT') {
|
|
52
|
+
totalComponentsAdded += result.added.length;
|
|
53
|
+
totalComponentsRemoved += result.removed.length;
|
|
54
|
+
totalComponentsChanged += result.changed.length;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
// If comparison fails, treat as drift
|
|
59
|
+
console.error(`⚠️ Failed to compare ${contextFile}: ${error.message}`);
|
|
60
|
+
folderResults.push({
|
|
61
|
+
folderPath: newFolder.path,
|
|
62
|
+
contextFile: newFolder.contextFile,
|
|
63
|
+
status: 'DRIFT',
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else if (!oldFolder && newFolder) {
|
|
68
|
+
// New folder - ADDED FILE
|
|
69
|
+
folderResults.push({
|
|
70
|
+
folderPath: newFolder.path,
|
|
71
|
+
contextFile: newFolder.contextFile,
|
|
72
|
+
status: 'ADDED',
|
|
73
|
+
});
|
|
74
|
+
totalComponentsAdded += newFolder.bundles;
|
|
75
|
+
}
|
|
76
|
+
else if (oldFolder && !newFolder) {
|
|
77
|
+
// Removed folder - ORPHANED FILE
|
|
78
|
+
folderResults.push({
|
|
79
|
+
folderPath: oldFolder.path,
|
|
80
|
+
contextFile: oldFolder.contextFile,
|
|
81
|
+
status: 'ORPHANED',
|
|
82
|
+
});
|
|
83
|
+
totalComponentsRemoved += oldFolder.bundles;
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
// Find orphaned files on disk
|
|
87
|
+
const orphanedFiles = await findOrphanedFiles(oldIndex, newIndex, oldBaseDir);
|
|
88
|
+
// Calculate summary
|
|
89
|
+
const addedFolders = folderResults.filter(f => f.status === 'ADDED').length;
|
|
90
|
+
const orphanedFolders = folderResults.filter(f => f.status === 'ORPHANED').length;
|
|
91
|
+
const driftFolders = folderResults.filter(f => f.status === 'DRIFT').length;
|
|
92
|
+
const passFolders = folderResults.filter(f => f.status === 'PASS').length;
|
|
93
|
+
// Only orphaned folders and drift folders qualify as drift; added folders are growth, not drift
|
|
94
|
+
const status = orphanedFolders > 0 || driftFolders > 0 ? 'DRIFT' : 'PASS';
|
|
95
|
+
// Sort folder results by path for consistent output
|
|
96
|
+
folderResults.sort((a, b) => a.folderPath.localeCompare(b.folderPath));
|
|
97
|
+
return {
|
|
98
|
+
status,
|
|
99
|
+
folders: folderResults,
|
|
100
|
+
summary: {
|
|
101
|
+
totalFolders: folderResults.length,
|
|
102
|
+
addedFolders,
|
|
103
|
+
orphanedFolders,
|
|
104
|
+
driftFolders,
|
|
105
|
+
passFolders,
|
|
106
|
+
totalComponentsAdded,
|
|
107
|
+
totalComponentsRemoved,
|
|
108
|
+
totalComponentsChanged,
|
|
109
|
+
},
|
|
110
|
+
orphanedFiles: orphanedFiles.length > 0 ? orphanedFiles : undefined,
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
//# sourceMappingURL=multiFile.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"multiFile.js","sourceRoot":"","sources":["../../../../src/cli/commands/compare/multiFile.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Single file comparison logic
|
|
3
|
+
*/
|
|
4
|
+
import type { CompareOptions, CompareResult } from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Compare a single folder's context file
|
|
7
|
+
*/
|
|
8
|
+
export declare function compareFolderContext(oldContextPath: string, newContextPath: string, stats: boolean, quiet?: boolean, gitBaseline?: boolean): Promise<{
|
|
9
|
+
result: CompareResult;
|
|
10
|
+
tokenDelta?: {
|
|
11
|
+
gpt4: number;
|
|
12
|
+
claude: number;
|
|
13
|
+
};
|
|
14
|
+
}>;
|
|
15
|
+
/**
|
|
16
|
+
* Main compare command
|
|
17
|
+
* Returns the comparison result instead of exiting, allowing caller to handle approval logic
|
|
18
|
+
*/
|
|
19
|
+
export declare function compareCommand(options: CompareOptions): Promise<CompareResult>;
|
|
20
|
+
//# sourceMappingURL=singleFile.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"singleFile.d.ts","sourceRoot":"","sources":["../../../../src/cli/commands/compare/singleFile.ts"],"names":[],"mappings":"AAAA;;GAEG;AAQH,OAAO,KAAK,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhE;;GAEG;AACH,wBAAsB,oBAAoB,CACxC,cAAc,EAAE,MAAM,EACtB,cAAc,EAAE,MAAM,EACtB,KAAK,EAAE,OAAO,EACd,KAAK,CAAC,EAAE,OAAO,EACf,WAAW,UAAQ,GAClB,OAAO,CAAC;IAAE,MAAM,EAAE,aAAa,CAAC;IAAC,UAAU,CAAC,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAA;CAAE,CAAC,CAkEnF;AAED;;;GAGG;AACH,wBAAsB,cAAc,CAAC,OAAO,EAAE,cAAc,GAAG,OAAO,CAAC,aAAa,CAAC,CAgRpF"}
|