frontend-harness 0.6.5 → 0.7.4
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/CHANGELOG.md +51 -0
- package/README.md +5 -2
- package/dist/cli/index.js +291 -11
- package/dist/cli/index.js.map +1 -1
- package/dist/runtime/clean.js +4 -0
- package/dist/runtime/clean.js.map +1 -1
- package/dist/runtime/command-taxonomy.js +3 -0
- package/dist/runtime/command-taxonomy.js.map +1 -1
- package/dist/runtime/knowledge.d.ts +3 -0
- package/dist/runtime/knowledge.js +24 -4
- package/dist/runtime/knowledge.js.map +1 -1
- package/dist/runtime/plan/component-resolver.d.ts +2 -2
- package/dist/runtime/plan/component-resolver.js +74 -8
- package/dist/runtime/plan/component-resolver.js.map +1 -1
- package/dist/runtime/plan.js +1 -1
- package/dist/runtime/plan.js.map +1 -1
- package/dist/runtime/project-paths.d.ts +5 -0
- package/dist/runtime/project-paths.js +28 -0
- package/dist/runtime/project-paths.js.map +1 -1
- package/dist/runtime/protocol-init.js +2 -2
- package/dist/runtime/protocol-init.js.map +1 -1
- package/dist/runtime/state.js +95 -18
- package/dist/runtime/state.js.map +1 -1
- package/dist/runtime/verify.d.ts +24 -0
- package/dist/runtime/verify.js +218 -11
- package/dist/runtime/verify.js.map +1 -1
- package/dist/runtime/visual-compare.d.ts +35 -0
- package/dist/runtime/visual-compare.js +271 -0
- package/dist/runtime/visual-compare.js.map +1 -0
- package/package.json +1 -1
- package/templates/scaffold/vue/gitignore.tpl +8 -1
- package/templates/scaffold/vue/playwright.config.mjs +1 -0
|
@@ -0,0 +1,271 @@
|
|
|
1
|
+
import { createHash } from "node:crypto";
|
|
2
|
+
import fs from "node:fs";
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import zlib from "node:zlib";
|
|
5
|
+
import { writeJson } from "../storage/json.js";
|
|
6
|
+
import { resolveProjectOrHarnessRelativePath } from "./project-paths.js";
|
|
7
|
+
const PNG_SIGNATURE = Buffer.from([137, 80, 78, 71, 13, 10, 26, 10]);
|
|
8
|
+
const VISUAL_COMPARE_LIMITATIONS = [
|
|
9
|
+
"Pixel-level PNG comparison intended for deterministic harness evidence, not perceptual production visual regression.",
|
|
10
|
+
"Stabilize browser rendering, viewport, fonts, data, animation, and dynamic regions before using scores as a release signal.",
|
|
11
|
+
"Use manual review or a dedicated visual regression service for masked regions, anti-alias tolerance, perceptual thresholds, and cross-platform rendering drift."
|
|
12
|
+
];
|
|
13
|
+
export function compareVisualArtifacts(projectRoot, input) {
|
|
14
|
+
const design = resolveRequiredFile(projectRoot, input.design, "visual compare design image");
|
|
15
|
+
const actual = resolveRequiredFile(projectRoot, input.actual, "visual compare actual image");
|
|
16
|
+
const diff = resolveOutputPath(projectRoot, input.diff, "visual compare diff image");
|
|
17
|
+
const report = input.report ? resolveOutputPath(projectRoot, input.report, "visual compare report") : null;
|
|
18
|
+
const threshold = input.threshold ?? 90;
|
|
19
|
+
if (threshold < 0 || threshold > 100 || !Number.isFinite(threshold)) {
|
|
20
|
+
throw new Error("visual compare --threshold must be a number between 0 and 100");
|
|
21
|
+
}
|
|
22
|
+
const designImage = decodePng(fs.readFileSync(design.fullPath), design.relativePath);
|
|
23
|
+
const actualImage = decodePng(fs.readFileSync(actual.fullPath), actual.relativePath);
|
|
24
|
+
const comparedWidth = Math.min(designImage.width, actualImage.width);
|
|
25
|
+
const comparedHeight = Math.min(designImage.height, actualImage.height);
|
|
26
|
+
const diffWidth = Math.max(designImage.width, actualImage.width);
|
|
27
|
+
const diffHeight = Math.max(designImage.height, actualImage.height);
|
|
28
|
+
if (comparedWidth <= 0 || comparedHeight <= 0) {
|
|
29
|
+
throw new Error("visual compare images must have non-empty overlapping dimensions");
|
|
30
|
+
}
|
|
31
|
+
const diffImage = new Uint8Array(diffWidth * diffHeight * 4);
|
|
32
|
+
let changedPixels = 0;
|
|
33
|
+
let totalDelta = 0;
|
|
34
|
+
let maxChannelDelta = 0;
|
|
35
|
+
for (let y = 0; y < diffHeight; y += 1) {
|
|
36
|
+
for (let x = 0; x < diffWidth; x += 1) {
|
|
37
|
+
const hasDesignPixel = x < designImage.width && y < designImage.height;
|
|
38
|
+
const hasActualPixel = x < actualImage.width && y < actualImage.height;
|
|
39
|
+
const designOffset = hasDesignPixel ? (y * designImage.width + x) * 4 : -1;
|
|
40
|
+
const actualOffset = hasActualPixel ? (y * actualImage.width + x) * 4 : -1;
|
|
41
|
+
const deltas = channelDeltas(designImage.rgba, designOffset, actualImage.rgba, actualOffset);
|
|
42
|
+
const pixelDelta = Math.max(...deltas);
|
|
43
|
+
if (pixelDelta > 0) {
|
|
44
|
+
changedPixels += 1;
|
|
45
|
+
}
|
|
46
|
+
maxChannelDelta = Math.max(maxChannelDelta, pixelDelta);
|
|
47
|
+
totalDelta += deltas.reduce((sum, delta) => sum + delta, 0);
|
|
48
|
+
const diffOffset = (y * diffWidth + x) * 4;
|
|
49
|
+
diffImage[diffOffset] = 255;
|
|
50
|
+
diffImage[diffOffset + 1] = 0;
|
|
51
|
+
diffImage[diffOffset + 2] = 0;
|
|
52
|
+
diffImage[diffOffset + 3] = Math.max(32, pixelDelta);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
fs.mkdirSync(path.dirname(diff.fullPath), { recursive: true });
|
|
56
|
+
fs.writeFileSync(diff.fullPath, encodePngRgba(diffWidth, diffHeight, diffImage));
|
|
57
|
+
const comparedPixels = diffWidth * diffHeight;
|
|
58
|
+
const meanAbsoluteError = totalDelta / (comparedPixels * 4);
|
|
59
|
+
const score = roundScore(Math.max(0, 100 * (1 - meanAbsoluteError / 255)));
|
|
60
|
+
const result = {
|
|
61
|
+
status: score >= threshold ? "passed" : "failed",
|
|
62
|
+
score,
|
|
63
|
+
threshold,
|
|
64
|
+
width: designImage.width,
|
|
65
|
+
height: designImage.height,
|
|
66
|
+
actualWidth: actualImage.width,
|
|
67
|
+
actualHeight: actualImage.height,
|
|
68
|
+
comparedWidth,
|
|
69
|
+
comparedHeight,
|
|
70
|
+
diffWidth,
|
|
71
|
+
diffHeight,
|
|
72
|
+
changedPixels,
|
|
73
|
+
changedRatio: Number((changedPixels / comparedPixels).toFixed(6)),
|
|
74
|
+
meanAbsoluteError: Number(meanAbsoluteError.toFixed(4)),
|
|
75
|
+
maxChannelDelta,
|
|
76
|
+
diffPath: diff.relativePath,
|
|
77
|
+
reportPath: report?.relativePath ?? null,
|
|
78
|
+
artifactSha256: {
|
|
79
|
+
design: sha256File(design.fullPath),
|
|
80
|
+
actual: sha256File(actual.fullPath),
|
|
81
|
+
diff: sha256File(diff.fullPath)
|
|
82
|
+
},
|
|
83
|
+
comparisonTool: "frontend-harness visual compare",
|
|
84
|
+
comparisonCommand: `frontend-harness visual compare --design ${design.relativePath} --actual ${actual.relativePath} --diff ${diff.relativePath}`,
|
|
85
|
+
limitations: VISUAL_COMPARE_LIMITATIONS
|
|
86
|
+
};
|
|
87
|
+
if (report) {
|
|
88
|
+
writeJson(report.fullPath, result);
|
|
89
|
+
}
|
|
90
|
+
return result;
|
|
91
|
+
}
|
|
92
|
+
function channelDeltas(left, leftOffset, right, rightOffset) {
|
|
93
|
+
if (leftOffset < 0 || rightOffset < 0) {
|
|
94
|
+
return [255, 255, 255, 255];
|
|
95
|
+
}
|
|
96
|
+
return [
|
|
97
|
+
Math.abs(byteAt(left, leftOffset) - byteAt(right, rightOffset)),
|
|
98
|
+
Math.abs(byteAt(left, leftOffset + 1) - byteAt(right, rightOffset + 1)),
|
|
99
|
+
Math.abs(byteAt(left, leftOffset + 2) - byteAt(right, rightOffset + 2)),
|
|
100
|
+
Math.abs(byteAt(left, leftOffset + 3) - byteAt(right, rightOffset + 3))
|
|
101
|
+
];
|
|
102
|
+
}
|
|
103
|
+
function resolveRequiredFile(projectRoot, value, label) {
|
|
104
|
+
if (!value) {
|
|
105
|
+
throw new Error(`${label} requires a project-relative path`);
|
|
106
|
+
}
|
|
107
|
+
const resolved = resolveProjectOrHarnessRelativePath(projectRoot, value, label);
|
|
108
|
+
if (!fs.existsSync(resolved.fullPath) || !fs.statSync(resolved.fullPath).isFile()) {
|
|
109
|
+
throw new Error(`${label} does not exist: ${resolved.relativePath}`);
|
|
110
|
+
}
|
|
111
|
+
return resolved;
|
|
112
|
+
}
|
|
113
|
+
function resolveOutputPath(projectRoot, value, label) {
|
|
114
|
+
if (!value) {
|
|
115
|
+
throw new Error(`${label} requires a project-relative path`);
|
|
116
|
+
}
|
|
117
|
+
return resolveProjectOrHarnessRelativePath(projectRoot, value, label);
|
|
118
|
+
}
|
|
119
|
+
function decodePng(buffer, label) {
|
|
120
|
+
if (buffer.length < 8 || !buffer.subarray(0, 8).equals(PNG_SIGNATURE)) {
|
|
121
|
+
throw new Error(`Unsupported PNG for ${label}: missing PNG signature`);
|
|
122
|
+
}
|
|
123
|
+
let offset = 8;
|
|
124
|
+
let width = 0;
|
|
125
|
+
let height = 0;
|
|
126
|
+
let colorType = -1;
|
|
127
|
+
let bitDepth = -1;
|
|
128
|
+
let interlace = -1;
|
|
129
|
+
const idat = [];
|
|
130
|
+
while (offset < buffer.length) {
|
|
131
|
+
const length = buffer.readUInt32BE(offset);
|
|
132
|
+
const type = buffer.subarray(offset + 4, offset + 8).toString("ascii");
|
|
133
|
+
const data = buffer.subarray(offset + 8, offset + 8 + length);
|
|
134
|
+
offset += 12 + length;
|
|
135
|
+
if (type === "IHDR") {
|
|
136
|
+
width = data.readUInt32BE(0);
|
|
137
|
+
height = data.readUInt32BE(4);
|
|
138
|
+
bitDepth = byteAt(data, 8);
|
|
139
|
+
colorType = byteAt(data, 9);
|
|
140
|
+
interlace = byteAt(data, 12);
|
|
141
|
+
}
|
|
142
|
+
else if (type === "IDAT") {
|
|
143
|
+
idat.push(data);
|
|
144
|
+
}
|
|
145
|
+
else if (type === "IEND") {
|
|
146
|
+
break;
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
if (bitDepth !== 8 || ![2, 6].includes(colorType) || interlace !== 0) {
|
|
150
|
+
throw new Error(`Unsupported PNG for ${label}: only 8-bit non-interlaced RGB/RGBA PNGs are supported`);
|
|
151
|
+
}
|
|
152
|
+
const channels = colorType === 6 ? 4 : 3;
|
|
153
|
+
const raw = zlib.inflateSync(Buffer.concat(idat));
|
|
154
|
+
const rowBytes = width * channels;
|
|
155
|
+
const rgba = new Uint8Array(width * height * 4);
|
|
156
|
+
let rawOffset = 0;
|
|
157
|
+
let previous = new Uint8Array(rowBytes);
|
|
158
|
+
for (let y = 0; y < height; y += 1) {
|
|
159
|
+
const filter = byteAt(raw, rawOffset);
|
|
160
|
+
rawOffset += 1;
|
|
161
|
+
const current = new Uint8Array(rowBytes);
|
|
162
|
+
current.set(raw.subarray(rawOffset, rawOffset + rowBytes));
|
|
163
|
+
rawOffset += rowBytes;
|
|
164
|
+
unfilterRow(current, previous, channels, filter);
|
|
165
|
+
for (let x = 0; x < width; x += 1) {
|
|
166
|
+
const source = x * channels;
|
|
167
|
+
const target = (y * width + x) * 4;
|
|
168
|
+
rgba[target] = byteAt(current, source);
|
|
169
|
+
rgba[target + 1] = byteAt(current, source + 1);
|
|
170
|
+
rgba[target + 2] = byteAt(current, source + 2);
|
|
171
|
+
rgba[target + 3] = channels === 4 ? byteAt(current, source + 3) : 255;
|
|
172
|
+
}
|
|
173
|
+
previous = current;
|
|
174
|
+
}
|
|
175
|
+
return { width, height, rgba };
|
|
176
|
+
}
|
|
177
|
+
function unfilterRow(row, previous, bytesPerPixel, filter) {
|
|
178
|
+
for (let index = 0; index < row.length; index += 1) {
|
|
179
|
+
const current = byteAt(row, index);
|
|
180
|
+
const left = index >= bytesPerPixel ? byteAt(row, index - bytesPerPixel) : 0;
|
|
181
|
+
const up = index < previous.length ? byteAt(previous, index) : 0;
|
|
182
|
+
const upLeft = index >= bytesPerPixel && index - bytesPerPixel < previous.length ? byteAt(previous, index - bytesPerPixel) : 0;
|
|
183
|
+
switch (filter) {
|
|
184
|
+
case 0:
|
|
185
|
+
break;
|
|
186
|
+
case 1:
|
|
187
|
+
row[index] = (current + left) & 0xff;
|
|
188
|
+
break;
|
|
189
|
+
case 2:
|
|
190
|
+
row[index] = (current + up) & 0xff;
|
|
191
|
+
break;
|
|
192
|
+
case 3:
|
|
193
|
+
row[index] = (current + Math.floor((left + up) / 2)) & 0xff;
|
|
194
|
+
break;
|
|
195
|
+
case 4:
|
|
196
|
+
row[index] = (current + paeth(left, up, upLeft)) & 0xff;
|
|
197
|
+
break;
|
|
198
|
+
default:
|
|
199
|
+
throw new Error(`Unsupported PNG filter type: ${filter}`);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
function byteAt(buffer, index) {
|
|
204
|
+
const value = buffer[index];
|
|
205
|
+
if (value === undefined) {
|
|
206
|
+
throw new Error(`Unexpected out-of-range byte read at ${index}`);
|
|
207
|
+
}
|
|
208
|
+
return value;
|
|
209
|
+
}
|
|
210
|
+
function encodePngRgba(width, height, rgba) {
|
|
211
|
+
const rowBytes = width * 4;
|
|
212
|
+
const raw = Buffer.alloc((rowBytes + 1) * height);
|
|
213
|
+
for (let y = 0; y < height; y += 1) {
|
|
214
|
+
const rowStart = y * (rowBytes + 1);
|
|
215
|
+
raw[rowStart] = 0;
|
|
216
|
+
Buffer.from(rgba.buffer, rgba.byteOffset + y * rowBytes, rowBytes).copy(raw, rowStart + 1);
|
|
217
|
+
}
|
|
218
|
+
return Buffer.concat([
|
|
219
|
+
PNG_SIGNATURE,
|
|
220
|
+
pngChunk("IHDR", Buffer.from([
|
|
221
|
+
...uint32(width),
|
|
222
|
+
...uint32(height),
|
|
223
|
+
8,
|
|
224
|
+
6,
|
|
225
|
+
0,
|
|
226
|
+
0,
|
|
227
|
+
0
|
|
228
|
+
])),
|
|
229
|
+
pngChunk("IDAT", zlib.deflateSync(raw)),
|
|
230
|
+
pngChunk("IEND", Buffer.alloc(0))
|
|
231
|
+
]);
|
|
232
|
+
}
|
|
233
|
+
function pngChunk(type, data) {
|
|
234
|
+
const typeBuffer = Buffer.from(type, "ascii");
|
|
235
|
+
return Buffer.concat([
|
|
236
|
+
Buffer.from(uint32(data.length)),
|
|
237
|
+
typeBuffer,
|
|
238
|
+
data,
|
|
239
|
+
Buffer.from(uint32(crc32(Buffer.concat([typeBuffer, data]))))
|
|
240
|
+
]);
|
|
241
|
+
}
|
|
242
|
+
function uint32(value) {
|
|
243
|
+
return [(value >>> 24) & 0xff, (value >>> 16) & 0xff, (value >>> 8) & 0xff, value & 0xff];
|
|
244
|
+
}
|
|
245
|
+
function paeth(left, up, upLeft) {
|
|
246
|
+
const estimate = left + up - upLeft;
|
|
247
|
+
const leftDistance = Math.abs(estimate - left);
|
|
248
|
+
const upDistance = Math.abs(estimate - up);
|
|
249
|
+
const upLeftDistance = Math.abs(estimate - upLeft);
|
|
250
|
+
if (leftDistance <= upDistance && leftDistance <= upLeftDistance) {
|
|
251
|
+
return left;
|
|
252
|
+
}
|
|
253
|
+
return upDistance <= upLeftDistance ? up : upLeft;
|
|
254
|
+
}
|
|
255
|
+
function crc32(buffer) {
|
|
256
|
+
let crc = 0xffffffff;
|
|
257
|
+
for (const byte of buffer) {
|
|
258
|
+
crc ^= byte;
|
|
259
|
+
for (let bit = 0; bit < 8; bit += 1) {
|
|
260
|
+
crc = (crc >>> 1) ^ (0xedb88320 & -(crc & 1));
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
return (crc ^ 0xffffffff) >>> 0;
|
|
264
|
+
}
|
|
265
|
+
function sha256File(filePath) {
|
|
266
|
+
return createHash("sha256").update(fs.readFileSync(filePath)).digest("hex");
|
|
267
|
+
}
|
|
268
|
+
function roundScore(value) {
|
|
269
|
+
return Number(value.toFixed(2));
|
|
270
|
+
}
|
|
271
|
+
//# sourceMappingURL=visual-compare.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"visual-compare.js","sourceRoot":"","sources":["../../src/runtime/visual-compare.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,UAAU,EAAE,MAAM,aAAa,CAAC;AACzC,OAAO,EAAE,MAAM,SAAS,CAAC;AACzB,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,IAAI,MAAM,WAAW,CAAC;AAC7B,OAAO,EAAE,SAAS,EAAE,MAAM,oBAAoB,CAAC;AAC/C,OAAO,EAAE,mCAAmC,EAAE,MAAM,oBAAoB,CAAC;AA4CzE,MAAM,aAAa,GAAG,MAAM,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC;AACrE,MAAM,0BAA0B,GAAG;IACjC,sHAAsH;IACtH,6HAA6H;IAC7H,iKAAiK;CAClK,CAAC;AAEF,MAAM,UAAU,sBAAsB,CAAC,WAAmB,EAAE,KAAyB;IACnF,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IAC7F,MAAM,MAAM,GAAG,mBAAmB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,6BAA6B,CAAC,CAAC;IAC7F,MAAM,IAAI,GAAG,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,IAAI,EAAE,2BAA2B,CAAC,CAAC;IACrF,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,iBAAiB,CAAC,WAAW,EAAE,KAAK,CAAC,MAAM,EAAE,uBAAuB,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC;IAC3G,MAAM,SAAS,GAAG,KAAK,CAAC,SAAS,IAAI,EAAE,CAAC;IACxC,IAAI,SAAS,GAAG,CAAC,IAAI,SAAS,GAAG,GAAG,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE,CAAC;QACpE,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;IACnF,CAAC;IAED,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACrF,MAAM,WAAW,GAAG,SAAS,CAAC,EAAE,CAAC,YAAY,CAAC,MAAM,CAAC,QAAQ,CAAC,EAAE,MAAM,CAAC,YAAY,CAAC,CAAC;IACrF,MAAM,aAAa,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACrE,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACxE,MAAM,SAAS,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,KAAK,EAAE,WAAW,CAAC,KAAK,CAAC,CAAC;IACjE,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,MAAM,EAAE,WAAW,CAAC,MAAM,CAAC,CAAC;IACpE,IAAI,aAAa,IAAI,CAAC,IAAI,cAAc,IAAI,CAAC,EAAE,CAAC;QAC9C,MAAM,IAAI,KAAK,CAAC,kEAAkE,CAAC,CAAC;IACtF,CAAC;IAED,MAAM,SAAS,GAAG,IAAI,UAAU,CAAC,SAAS,GAAG,UAAU,GAAG,CAAC,CAAC,CAAC;IAC7D,IAAI,aAAa,GAAG,CAAC,CAAC;IACtB,IAAI,UAAU,GAAG,CAAC,CAAC;IACnB,IAAI,eAAe,GAAG,CAAC,CAAC;IACxB,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,UAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACvC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,SAAS,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YACtC,MAAM,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;YACvE,MAAM,cAAc,GAAG,CAAC,GAAG,WAAW,CAAC,KAAK,IAAI,CAAC,GAAG,WAAW,CAAC,MAAM,CAAC;YACvE,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,MAAM,YAAY,GAAG,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,WAAW,CAAC,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3E,MAAM,MAAM,GAAG,aAAa,CAAC,WAAW,CAAC,IAAI,EAAE,YAAY,EAAE,WAAW,CAAC,IAAI,EAAE,YAAY,CAAC,CAAC;YAC7F,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;YACvC,IAAI,UAAU,GAAG,CAAC,EAAE,CAAC;gBACnB,aAAa,IAAI,CAAC,CAAC;YACrB,CAAC;YACD,eAAe,GAAG,IAAI,CAAC,GAAG,CAAC,eAAe,EAAE,UAAU,CAAC,CAAC;YACxD,UAAU,IAAI,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,GAAG,GAAG,KAAK,EAAE,CAAC,CAAC,CAAC;YAC5D,MAAM,UAAU,GAAG,CAAC,CAAC,GAAG,SAAS,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC3C,SAAS,CAAC,UAAU,CAAC,GAAG,GAAG,CAAC;YAC5B,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC9B,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YAC9B,SAAS,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,GAAG,CAAC,EAAE,EAAE,UAAU,CAAC,CAAC;QACvD,CAAC;IACH,CAAC;IAED,EAAE,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC/D,EAAE,CAAC,aAAa,CAAC,IAAI,CAAC,QAAQ,EAAE,aAAa,CAAC,SAAS,EAAE,UAAU,EAAE,SAAS,CAAC,CAAC,CAAC;IACjF,MAAM,cAAc,GAAG,SAAS,GAAG,UAAU,CAAC;IAC9C,MAAM,iBAAiB,GAAG,UAAU,GAAG,CAAC,cAAc,GAAG,CAAC,CAAC,CAAC;IAC5D,MAAM,KAAK,GAAG,UAAU,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,CAAC,GAAG,iBAAiB,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,MAAM,GAAwB;QAClC,MAAM,EAAE,KAAK,IAAI,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ;QAChD,KAAK;QACL,SAAS;QACT,KAAK,EAAE,WAAW,CAAC,KAAK;QACxB,MAAM,EAAE,WAAW,CAAC,MAAM;QAC1B,WAAW,EAAE,WAAW,CAAC,KAAK;QAC9B,YAAY,EAAE,WAAW,CAAC,MAAM;QAChC,aAAa;QACb,cAAc;QACd,SAAS;QACT,UAAU;QACV,aAAa;QACb,YAAY,EAAE,MAAM,CAAC,CAAC,aAAa,GAAG,cAAc,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACjE,iBAAiB,EAAE,MAAM,CAAC,iBAAiB,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;QACvD,eAAe;QACf,QAAQ,EAAE,IAAI,CAAC,YAAY;QAC3B,UAAU,EAAE,MAAM,EAAE,YAAY,IAAI,IAAI;QACxC,cAAc,EAAE;YACd,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC;YACnC,MAAM,EAAE,UAAU,CAAC,MAAM,CAAC,QAAQ,CAAC;YACnC,IAAI,EAAE,UAAU,CAAC,IAAI,CAAC,QAAQ,CAAC;SAChC;QACD,cAAc,EAAE,iCAAiC;QACjD,iBAAiB,EAAE,4CAA4C,MAAM,CAAC,YAAY,aAAa,MAAM,CAAC,YAAY,WAAW,IAAI,CAAC,YAAY,EAAE;QAChJ,WAAW,EAAE,0BAA0B;KACxC,CAAC;IACF,IAAI,MAAM,EAAE,CAAC;QACX,SAAS,CAAC,MAAM,CAAC,QAAQ,EAAE,MAAM,CAAC,CAAC;IACrC,CAAC;IACD,OAAO,MAAM,CAAC;AAChB,CAAC;AAED,SAAS,aAAa,CAAC,IAAgB,EAAE,UAAkB,EAAE,KAAiB,EAAE,WAAmB;IACjG,IAAI,UAAU,GAAG,CAAC,IAAI,WAAW,GAAG,CAAC,EAAE,CAAC;QACtC,OAAO,CAAC,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC,CAAC;IAC9B,CAAC;IACD,OAAO;QACL,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,CAAC,CAAC;QAC/D,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,GAAG,CAAC,MAAM,CAAC,IAAI,EAAE,UAAU,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,KAAK,EAAE,WAAW,GAAG,CAAC,CAAC,CAAC;KACxE,CAAC;AACJ,CAAC;AAED,SAAS,mBAAmB,CAAC,WAAmB,EAAE,KAAyB,EAAE,KAAa;IACxF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mCAAmC,CAAC,CAAC;IAC/D,CAAC;IACD,MAAM,QAAQ,GAAG,mCAAmC,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;IAChF,IAAI,CAAC,EAAE,CAAC,UAAU,CAAC,QAAQ,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,QAAQ,CAAC,QAAQ,CAAC,QAAQ,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC;QAClF,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,oBAAoB,QAAQ,CAAC,YAAY,EAAE,CAAC,CAAC;IACvE,CAAC;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,iBAAiB,CAAC,WAAmB,EAAE,KAAyB,EAAE,KAAa;IACtF,IAAI,CAAC,KAAK,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,GAAG,KAAK,mCAAmC,CAAC,CAAC;IAC/D,CAAC;IACD,OAAO,mCAAmC,CAAC,WAAW,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;AACxE,CAAC;AAED,SAAS,SAAS,CAAC,MAAc,EAAE,KAAa;IAC9C,IAAI,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,aAAa,CAAC,EAAE,CAAC;QACtE,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,yBAAyB,CAAC,CAAC;IACzE,CAAC;IACD,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,IAAI,QAAQ,GAAG,CAAC,CAAC,CAAC;IAClB,IAAI,SAAS,GAAG,CAAC,CAAC,CAAC;IACnB,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,OAAO,MAAM,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC;QAC9B,MAAM,MAAM,GAAG,MAAM,CAAC,YAAY,CAAC,MAAM,CAAC,CAAC;QAC3C,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,QAAQ,CAAC,OAAO,CAAC,CAAC;QACvE,MAAM,IAAI,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,GAAG,CAAC,EAAE,MAAM,GAAG,CAAC,GAAG,MAAM,CAAC,CAAC;QAC9D,MAAM,IAAI,EAAE,GAAG,MAAM,CAAC;QACtB,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YACpB,KAAK,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC7B,MAAM,GAAG,IAAI,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC;YAC9B,QAAQ,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC3B,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC;YAC5B,SAAS,GAAG,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC/B,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;QAClB,CAAC;aAAM,IAAI,IAAI,KAAK,MAAM,EAAE,CAAC;YAC3B,MAAM;QACR,CAAC;IACH,CAAC;IACD,IAAI,QAAQ,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,IAAI,SAAS,KAAK,CAAC,EAAE,CAAC;QACrE,MAAM,IAAI,KAAK,CAAC,uBAAuB,KAAK,yDAAyD,CAAC,CAAC;IACzG,CAAC;IACD,MAAM,QAAQ,GAAG,SAAS,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACzC,MAAM,GAAG,GAAG,IAAI,CAAC,WAAW,CAAC,MAAM,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC;IAClD,MAAM,QAAQ,GAAG,KAAK,GAAG,QAAQ,CAAC;IAClC,MAAM,IAAI,GAAG,IAAI,UAAU,CAAC,KAAK,GAAG,MAAM,GAAG,CAAC,CAAC,CAAC;IAChD,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,QAAQ,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;IACxC,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,MAAM,GAAG,MAAM,CAAC,GAAG,EAAE,SAAS,CAAC,CAAC;QACtC,SAAS,IAAI,CAAC,CAAC;QACf,MAAM,OAAO,GAAG,IAAI,UAAU,CAAC,QAAQ,CAAC,CAAC;QACzC,OAAO,CAAC,GAAG,CAAC,GAAG,CAAC,QAAQ,CAAC,SAAS,EAAE,SAAS,GAAG,QAAQ,CAAC,CAAC,CAAC;QAC3D,SAAS,IAAI,QAAQ,CAAC;QACtB,WAAW,CAAC,OAAO,EAAE,QAAQ,EAAE,QAAQ,EAAE,MAAM,CAAC,CAAC;QACjD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,KAAK,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;YAClC,MAAM,MAAM,GAAG,CAAC,GAAG,QAAQ,CAAC;YAC5B,MAAM,MAAM,GAAG,CAAC,CAAC,GAAG,KAAK,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC;YACnC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACvC,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC;YAC/C,IAAI,CAAC,MAAM,GAAG,CAAC,CAAC,GAAG,QAAQ,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,EAAE,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,CAAC;QACxE,CAAC;QACD,QAAQ,GAAG,OAAO,CAAC;IACrB,CAAC;IACD,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,CAAC;AACjC,CAAC;AAED,SAAS,WAAW,CAAC,GAAe,EAAE,QAAoB,EAAE,aAAqB,EAAE,MAAc;IAC/F,KAAK,IAAI,KAAK,GAAG,CAAC,EAAE,KAAK,GAAG,GAAG,CAAC,MAAM,EAAE,KAAK,IAAI,CAAC,EAAE,CAAC;QACnD,MAAM,OAAO,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACnC,MAAM,IAAI,GAAG,KAAK,IAAI,aAAa,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC7E,MAAM,EAAE,GAAG,KAAK,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QACjE,MAAM,MAAM,GAAG,KAAK,IAAI,aAAa,IAAI,KAAK,GAAG,aAAa,GAAG,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,MAAM,CAAC,QAAQ,EAAE,KAAK,GAAG,aAAa,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;QAC/H,QAAQ,MAAM,EAAE,CAAC;YACf,KAAK,CAAC;gBACJ,MAAM;YACR,KAAK,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,GAAG,IAAI,CAAC;gBACrC,MAAM;YACR,KAAK,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,EAAE,CAAC,GAAG,IAAI,CAAC;gBACnC,MAAM;YACR,KAAK,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,IAAI,GAAG,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC;gBAC5D,MAAM;YACR,KAAK,CAAC;gBACJ,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,OAAO,GAAG,KAAK,CAAC,IAAI,EAAE,EAAE,EAAE,MAAM,CAAC,CAAC,GAAG,IAAI,CAAC;gBACxD,MAAM;YACR;gBACE,MAAM,IAAI,KAAK,CAAC,gCAAgC,MAAM,EAAE,CAAC,CAAC;QAC9D,CAAC;IACH,CAAC;AACH,CAAC;AAED,SAAS,MAAM,CAAC,MAAkB,EAAE,KAAa;IAC/C,MAAM,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;IAC5B,IAAI,KAAK,KAAK,SAAS,EAAE,CAAC;QACxB,MAAM,IAAI,KAAK,CAAC,wCAAwC,KAAK,EAAE,CAAC,CAAC;IACnE,CAAC;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,SAAS,aAAa,CAAC,KAAa,EAAE,MAAc,EAAE,IAAgB;IACpE,MAAM,QAAQ,GAAG,KAAK,GAAG,CAAC,CAAC;IAC3B,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC,QAAQ,GAAG,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC;IAClD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,MAAM,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;QACnC,MAAM,QAAQ,GAAG,CAAC,GAAG,CAAC,QAAQ,GAAG,CAAC,CAAC,CAAC;QACpC,GAAG,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC;QAClB,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,IAAI,CAAC,UAAU,GAAG,CAAC,GAAG,QAAQ,EAAE,QAAQ,CAAC,CAAC,IAAI,CAAC,GAAG,EAAE,QAAQ,GAAG,CAAC,CAAC,CAAC;IAC7F,CAAC;IACD,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,aAAa;QACb,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,IAAI,CAAC;YAC3B,GAAG,MAAM,CAAC,KAAK,CAAC;YAChB,GAAG,MAAM,CAAC,MAAM,CAAC;YACjB,CAAC;YACD,CAAC;YACD,CAAC;YACD,CAAC;YACD,CAAC;SACF,CAAC,CAAC;QACH,QAAQ,CAAC,MAAM,EAAE,IAAI,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC;QACvC,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;KAClC,CAAC,CAAC;AACL,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY,EAAE,IAAY;IAC1C,MAAM,UAAU,GAAG,MAAM,CAAC,IAAI,CAAC,IAAI,EAAE,OAAO,CAAC,CAAC;IAC9C,OAAO,MAAM,CAAC,MAAM,CAAC;QACnB,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;QAChC,UAAU;QACV,IAAI;QACJ,MAAM,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;KAC9D,CAAC,CAAC;AACL,CAAC;AAED,SAAS,MAAM,CAAC,KAAa;IAC3B,OAAO,CAAC,CAAC,KAAK,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,KAAK,EAAE,CAAC,GAAG,IAAI,EAAE,CAAC,KAAK,KAAK,CAAC,CAAC,GAAG,IAAI,EAAE,KAAK,GAAG,IAAI,CAAC,CAAC;AAC5F,CAAC;AAED,SAAS,KAAK,CAAC,IAAY,EAAE,EAAU,EAAE,MAAc;IACrD,MAAM,QAAQ,GAAG,IAAI,GAAG,EAAE,GAAG,MAAM,CAAC;IACpC,MAAM,YAAY,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,IAAI,CAAC,CAAC;IAC/C,MAAM,UAAU,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,EAAE,CAAC,CAAC;IAC3C,MAAM,cAAc,GAAG,IAAI,CAAC,GAAG,CAAC,QAAQ,GAAG,MAAM,CAAC,CAAC;IACnD,IAAI,YAAY,IAAI,UAAU,IAAI,YAAY,IAAI,cAAc,EAAE,CAAC;QACjE,OAAO,IAAI,CAAC;IACd,CAAC;IACD,OAAO,UAAU,IAAI,cAAc,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC;AACpD,CAAC;AAED,SAAS,KAAK,CAAC,MAAc;IAC3B,IAAI,GAAG,GAAG,UAAU,CAAC;IACrB,KAAK,MAAM,IAAI,IAAI,MAAM,EAAE,CAAC;QAC1B,GAAG,IAAI,IAAI,CAAC;QACZ,KAAK,IAAI,GAAG,GAAG,CAAC,EAAE,GAAG,GAAG,CAAC,EAAE,GAAG,IAAI,CAAC,EAAE,CAAC;YACpC,GAAG,GAAG,CAAC,GAAG,KAAK,CAAC,CAAC,GAAG,CAAC,UAAU,GAAG,CAAC,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,CAAC;QAChD,CAAC;IACH,CAAC;IACD,OAAO,CAAC,GAAG,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC;AAClC,CAAC;AAED,SAAS,UAAU,CAAC,QAAgB;IAClC,OAAO,UAAU,CAAC,QAAQ,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,YAAY,CAAC,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC;AAC9E,CAAC;AAED,SAAS,UAAU,CAAC,KAAa;IAC/B,OAAO,MAAM,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC;AAClC,CAAC"}
|
package/package.json
CHANGED
|
@@ -9,7 +9,7 @@ test-results
|
|
|
9
9
|
src/types/auto-imports.d.ts
|
|
10
10
|
src/types/components.d.ts
|
|
11
11
|
|
|
12
|
-
# frontend-harness generated
|
|
12
|
+
# frontend-harness generated local state and evidence
|
|
13
13
|
.frontend-harness/context/
|
|
14
14
|
.frontend-harness/plans/
|
|
15
15
|
.frontend-harness/execution-units/
|
|
@@ -17,7 +17,14 @@ src/types/components.d.ts
|
|
|
17
17
|
.frontend-harness/guidance/
|
|
18
18
|
.frontend-harness/state.json
|
|
19
19
|
.frontend-harness/verification/
|
|
20
|
+
.frontend-harness/design-sources/
|
|
21
|
+
.frontend-harness/evidence/
|
|
22
|
+
.frontend-harness/visual/
|
|
20
23
|
.frontend-harness/logs/
|
|
21
24
|
.frontend-harness/repair/
|
|
22
25
|
.frontend-harness/repair-decision/
|
|
23
26
|
.frontend-harness/state-explain/
|
|
27
|
+
|
|
28
|
+
# Keep project-owned harness policy and knowledge tracked when useful:
|
|
29
|
+
# .frontend-harness/knowledge/
|
|
30
|
+
# .frontend-harness/skills/
|