@quickchatai/pi-quickreview 1.1.0 → 1.3.1
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 +79 -27
- package/assets/config.example.toml +60 -14
- package/assets/prompts/onboarding.md +58 -18
- package/assets/schemas/review-result.v1.json +60 -0
- package/dist/extensions/quickreview.d.ts +13 -5
- package/dist/extensions/quickreview.d.ts.map +1 -1
- package/dist/extensions/quickreview.js +77 -25
- package/dist/extensions/quickreview.js.map +1 -1
- package/dist/src/engine/auth.d.ts +4 -0
- package/dist/src/engine/auth.d.ts.map +1 -1
- package/dist/src/engine/auth.js +11 -2
- package/dist/src/engine/auth.js.map +1 -1
- package/dist/src/engine/envmap.d.ts.map +1 -1
- package/dist/src/engine/envmap.js +5 -0
- package/dist/src/engine/envmap.js.map +1 -1
- package/dist/src/engine/lens/activity.d.ts +45 -0
- package/dist/src/engine/lens/activity.d.ts.map +1 -0
- package/dist/src/engine/lens/activity.js +118 -0
- package/dist/src/engine/lens/activity.js.map +1 -0
- package/dist/src/engine/lens/runlens.d.ts +7 -0
- package/dist/src/engine/lens/runlens.d.ts.map +1 -1
- package/dist/src/engine/lens/runlens.js +30 -1
- package/dist/src/engine/lens/runlens.js.map +1 -1
- package/dist/src/engine/lens/tool.d.ts +7 -0
- package/dist/src/engine/lens/tool.d.ts.map +1 -1
- package/dist/src/engine/lens/tool.js +101 -18
- package/dist/src/engine/lens/tool.js.map +1 -1
- package/dist/src/engine/lens/wave.d.ts +6 -0
- package/dist/src/engine/lens/wave.d.ts.map +1 -1
- package/dist/src/engine/lens/wave.js +16 -0
- package/dist/src/engine/lens/wave.js.map +1 -1
- package/dist/src/engine/pisdk.d.ts +9 -0
- package/dist/src/engine/pisdk.d.ts.map +1 -1
- package/dist/src/engine/pisdk.js +29 -4
- package/dist/src/engine/pisdk.js.map +1 -1
- package/dist/src/githubAuth.d.ts +39 -1
- package/dist/src/githubAuth.d.ts.map +1 -1
- package/dist/src/githubAuth.js +75 -8
- package/dist/src/githubAuth.js.map +1 -1
- package/dist/src/guards.d.ts +14 -1
- package/dist/src/guards.d.ts.map +1 -1
- package/dist/src/guards.js +61 -2
- package/dist/src/guards.js.map +1 -1
- package/dist/src/homes.js +1 -1
- package/dist/src/homes.js.map +1 -1
- package/dist/src/identity.d.ts +34 -0
- package/dist/src/identity.d.ts.map +1 -0
- package/dist/src/identity.js +67 -0
- package/dist/src/identity.js.map +1 -0
- package/dist/src/live/events.d.ts +3 -0
- package/dist/src/live/events.d.ts.map +1 -1
- package/dist/src/live/events.js.map +1 -1
- package/dist/src/live/lensline.d.ts +20 -0
- package/dist/src/live/lensline.d.ts.map +1 -0
- package/dist/src/live/lensline.js +70 -0
- package/dist/src/live/lensline.js.map +1 -0
- package/dist/src/live/projection.d.ts +55 -0
- package/dist/src/live/projection.d.ts.map +1 -0
- package/dist/src/live/projection.js +465 -0
- package/dist/src/live/projection.js.map +1 -0
- package/dist/src/live/read.d.ts +24 -0
- package/dist/src/live/read.d.ts.map +1 -0
- package/dist/src/live/read.js +60 -0
- package/dist/src/live/read.js.map +1 -0
- package/dist/src/live/writer.d.ts +3 -0
- package/dist/src/live/writer.d.ts.map +1 -1
- package/dist/src/live/writer.js +6 -1
- package/dist/src/live/writer.js.map +1 -1
- package/dist/src/localreview.d.ts +18 -8
- package/dist/src/localreview.d.ts.map +1 -1
- package/dist/src/localreview.js +103 -43
- package/dist/src/localreview.js.map +1 -1
- package/dist/src/modelroute.d.ts +42 -0
- package/dist/src/modelroute.d.ts.map +1 -0
- package/dist/src/modelroute.js +126 -0
- package/dist/src/modelroute.js.map +1 -0
- package/dist/src/plugin/args.d.ts +38 -7
- package/dist/src/plugin/args.d.ts.map +1 -1
- package/dist/src/plugin/args.js +134 -37
- package/dist/src/plugin/args.js.map +1 -1
- package/dist/src/plugin/login.d.ts +11 -4
- package/dist/src/plugin/login.d.ts.map +1 -1
- package/dist/src/plugin/login.js +28 -26
- package/dist/src/plugin/login.js.map +1 -1
- package/dist/src/plugin/messages.d.ts +7 -0
- package/dist/src/plugin/messages.d.ts.map +1 -0
- package/dist/src/plugin/messages.js +13 -0
- package/dist/src/plugin/messages.js.map +1 -0
- package/dist/src/plugin/review.d.ts +52 -6
- package/dist/src/plugin/review.d.ts.map +1 -1
- package/dist/src/plugin/review.js +269 -99
- package/dist/src/plugin/review.js.map +1 -1
- package/dist/src/plugin/scan.d.ts +80 -44
- package/dist/src/plugin/scan.d.ts.map +1 -1
- package/dist/src/plugin/scan.js +450 -233
- package/dist/src/plugin/scan.js.map +1 -1
- package/dist/src/plugin/scancases.d.ts +33 -0
- package/dist/src/plugin/scancases.d.ts.map +1 -0
- package/dist/src/plugin/scancases.js +153 -0
- package/dist/src/plugin/scancases.js.map +1 -0
- package/dist/src/plugin/settings.d.ts +18 -0
- package/dist/src/plugin/settings.d.ts.map +1 -0
- package/dist/src/plugin/settings.js +47 -0
- package/dist/src/plugin/settings.js.map +1 -0
- package/dist/src/plugin/setup.d.ts +35 -12
- package/dist/src/plugin/setup.d.ts.map +1 -1
- package/dist/src/plugin/setup.js +258 -118
- package/dist/src/plugin/setup.js.map +1 -1
- package/dist/src/plugin/versiongate.js +1 -1
- package/dist/src/plugin/versiongate.js.map +1 -1
- package/dist/src/profileoverrides.d.ts +3 -0
- package/dist/src/profileoverrides.d.ts.map +1 -1
- package/dist/src/profileoverrides.js +9 -2
- package/dist/src/profileoverrides.js.map +1 -1
- package/dist/src/reviewapi.d.ts +22 -31
- package/dist/src/reviewapi.d.ts.map +1 -1
- package/dist/src/reviewapi.js +90 -66
- package/dist/src/reviewapi.js.map +1 -1
- package/dist/src/reviewconfig.d.ts +12 -0
- package/dist/src/reviewconfig.d.ts.map +1 -1
- package/dist/src/reviewconfig.js +9 -1
- package/dist/src/reviewconfig.js.map +1 -1
- package/dist/src/reviewdest.d.ts +1 -1
- package/dist/src/reviewdest.d.ts.map +1 -1
- package/dist/src/reviewdest.js +4 -3
- package/dist/src/reviewdest.js.map +1 -1
- package/dist/src/reviewtarget.d.ts +36 -0
- package/dist/src/reviewtarget.d.ts.map +1 -0
- package/dist/src/reviewtarget.js +6 -0
- package/dist/src/reviewtarget.js.map +1 -0
- package/dist/src/round-progress.d.ts +5 -0
- package/dist/src/round-progress.d.ts.map +1 -1
- package/dist/src/round-progress.js.map +1 -1
- package/dist/src/savedpost.d.ts +65 -0
- package/dist/src/savedpost.d.ts.map +1 -0
- package/dist/src/savedpost.js +131 -0
- package/dist/src/savedpost.js.map +1 -0
- package/dist/src/scan/caseread.d.ts +84 -0
- package/dist/src/scan/caseread.d.ts.map +1 -0
- package/dist/src/scan/caseread.js +263 -0
- package/dist/src/scan/caseread.js.map +1 -0
- package/dist/src/scan/channelfs.d.ts +6 -0
- package/dist/src/scan/channelfs.d.ts.map +1 -0
- package/dist/src/scan/channelfs.js +27 -0
- package/dist/src/scan/channelfs.js.map +1 -0
- package/dist/src/scan/cutrender.d.ts +13 -0
- package/dist/src/scan/cutrender.d.ts.map +1 -0
- package/dist/src/scan/cutrender.js +51 -0
- package/dist/src/scan/cutrender.js.map +1 -0
- package/dist/src/scan/facts.d.ts +72 -0
- package/dist/src/scan/facts.d.ts.map +1 -0
- package/dist/src/scan/facts.js +593 -0
- package/dist/src/scan/facts.js.map +1 -0
- package/dist/src/scan/findings.d.ts +320 -0
- package/dist/src/scan/findings.d.ts.map +1 -0
- package/dist/src/scan/findings.js +948 -0
- package/dist/src/scan/findings.js.map +1 -0
- package/dist/src/scan/ledger.d.ts +116 -0
- package/dist/src/scan/ledger.d.ts.map +1 -0
- package/dist/src/scan/ledger.js +207 -0
- package/dist/src/scan/ledger.js.map +1 -0
- package/dist/src/scan/presentation.d.ts +19 -0
- package/dist/src/scan/presentation.d.ts.map +1 -0
- package/dist/src/scan/presentation.js +9 -0
- package/dist/src/scan/presentation.js.map +1 -0
- package/dist/src/scan/scan.d.ts +354 -0
- package/dist/src/scan/scan.d.ts.map +1 -0
- package/dist/src/scan/scan.js +725 -0
- package/dist/src/scan/scan.js.map +1 -0
- package/dist/src/scan/scanagents.d.ts +23 -0
- package/dist/src/scan/scanagents.d.ts.map +1 -0
- package/dist/src/scan/scanagents.js +99 -0
- package/dist/src/scan/scanagents.js.map +1 -0
- package/dist/src/scan/scanassemble.d.ts +65 -0
- package/dist/src/scan/scanassemble.d.ts.map +1 -0
- package/dist/src/scan/scanassemble.js +93 -0
- package/dist/src/scan/scanassemble.js.map +1 -0
- package/dist/src/scan/scanfs.d.ts +26 -0
- package/dist/src/scan/scanfs.d.ts.map +1 -0
- package/dist/src/scan/scanfs.js +229 -0
- package/dist/src/scan/scanfs.js.map +1 -0
- package/dist/src/scan/scanlease.d.ts +50 -0
- package/dist/src/scan/scanlease.d.ts.map +1 -0
- package/dist/src/scan/scanlease.js +251 -0
- package/dist/src/scan/scanlease.js.map +1 -0
- package/dist/src/scan/scanleaves.d.ts +55 -0
- package/dist/src/scan/scanleaves.d.ts.map +1 -0
- package/dist/src/scan/scanleaves.js +258 -0
- package/dist/src/scan/scanleaves.js.map +1 -0
- package/dist/src/scan/scanports.d.ts +79 -0
- package/dist/src/scan/scanports.d.ts.map +1 -0
- package/dist/src/scan/scanports.js +8 -0
- package/dist/src/scan/scanports.js.map +1 -0
- package/dist/src/scan/scanrender.d.ts +128 -0
- package/dist/src/scan/scanrender.d.ts.map +1 -0
- package/dist/src/scan/scanrender.js +527 -0
- package/dist/src/scan/scanrender.js.map +1 -0
- package/dist/src/scan/scanreport.d.ts +126 -0
- package/dist/src/scan/scanreport.d.ts.map +1 -0
- package/dist/src/scan/scanreport.js +289 -0
- package/dist/src/scan/scanreport.js.map +1 -0
- package/dist/src/scan/scanrun.d.ts +472 -0
- package/dist/src/scan/scanrun.d.ts.map +1 -0
- package/dist/src/scan/scanrun.js +1733 -0
- package/dist/src/scan/scanrun.js.map +1 -0
- package/dist/src/scan/scantree.d.ts +21 -0
- package/dist/src/scan/scantree.d.ts.map +1 -0
- package/dist/src/scan/scantree.js +297 -0
- package/dist/src/scan/scantree.js.map +1 -0
- package/dist/src/scan/scanverbs.d.ts +208 -0
- package/dist/src/scan/scanverbs.d.ts.map +1 -0
- package/dist/src/scan/scanverbs.js +689 -0
- package/dist/src/scan/scanverbs.js.map +1 -0
- package/dist/src/scan/stage2.d.ts +221 -0
- package/dist/src/scan/stage2.d.ts.map +1 -0
- package/dist/src/scan/stage2.js +617 -0
- package/dist/src/scan/stage2.js.map +1 -0
- package/dist/src/scan/stage2request.d.ts +125 -0
- package/dist/src/scan/stage2request.d.ts.map +1 -0
- package/dist/src/scan/stage2request.js +259 -0
- package/dist/src/scan/stage2request.js.map +1 -0
- package/dist/src/scan/textsniff.d.ts +14 -0
- package/dist/src/scan/textsniff.d.ts.map +1 -0
- package/dist/src/scan/textsniff.js +88 -0
- package/dist/src/scan/textsniff.js.map +1 -0
- package/dist/src/scan/unitcut.d.ts +135 -0
- package/dist/src/scan/unitcut.d.ts.map +1 -0
- package/dist/src/scan/unitcut.js +437 -0
- package/dist/src/scan/unitcut.js.map +1 -0
- package/dist/src/scan/unitcutstore.d.ts +155 -0
- package/dist/src/scan/unitcutstore.d.ts.map +1 -0
- package/dist/src/scan/unitcutstore.js +381 -0
- package/dist/src/scan/unitcutstore.js.map +1 -0
- package/dist/src/setupchecklist.d.ts +240 -0
- package/dist/src/setupchecklist.d.ts.map +1 -0
- package/dist/src/setupchecklist.js +407 -0
- package/dist/src/setupchecklist.js.map +1 -0
- package/package.json +7 -3
- package/skills/qcr-review/SKILL.md +24 -0
- package/skills/qcr-scan/SKILL.md +23 -0
- package/skills/qcr-setup/SKILL.md +18 -0
|
@@ -0,0 +1,155 @@
|
|
|
1
|
+
import { type UnitCandidate } from "./facts.js";
|
|
2
|
+
import type { Refusal, RepoReader, StateFs } from "./scanports.js";
|
|
3
|
+
import { type CaseBudget, type CasePlan, type UnitCut } from "./unitcut.js";
|
|
4
|
+
export declare const UNIT_CUT_FILE = "setup/unit-cut.json";
|
|
5
|
+
export declare const UNIT_CUT_VERSION = 1;
|
|
6
|
+
export interface SavedCut extends UnitCut {
|
|
7
|
+
saved_at: string;
|
|
8
|
+
/** The commit the cut was checked against, when readable. */
|
|
9
|
+
head: string | null;
|
|
10
|
+
/** How many files the cut covered at save — a later listing that differs is
|
|
11
|
+
* how a stale cut shows itself. */
|
|
12
|
+
files: number;
|
|
13
|
+
}
|
|
14
|
+
export interface DraftCut extends UnitCut {
|
|
15
|
+
updated_at: string;
|
|
16
|
+
/** `candidates` = the deterministic guess taken as-is; `companion` = a
|
|
17
|
+
* proposal the companion wrote; `adjusted` = either, after operator edits. */
|
|
18
|
+
source: "candidates" | "companion" | "adjusted";
|
|
19
|
+
}
|
|
20
|
+
export interface UnitCutFile {
|
|
21
|
+
version: number;
|
|
22
|
+
saved: SavedCut | null;
|
|
23
|
+
previous: SavedCut | null;
|
|
24
|
+
draft: DraftCut | null;
|
|
25
|
+
}
|
|
26
|
+
export interface UnitSummary {
|
|
27
|
+
name: string;
|
|
28
|
+
kind: string;
|
|
29
|
+
roots: string[];
|
|
30
|
+
note: string;
|
|
31
|
+
files: number | null;
|
|
32
|
+
/** Files a pass would actually read (lockfiles, binaries, prose skipped). */
|
|
33
|
+
reviewable: number | null;
|
|
34
|
+
lines: number | null;
|
|
35
|
+
/** One per case; a unit that fits is one case under its own name. */
|
|
36
|
+
cases: Array<{
|
|
37
|
+
id: string;
|
|
38
|
+
files: number;
|
|
39
|
+
lines: number;
|
|
40
|
+
over_budget: boolean;
|
|
41
|
+
}> | null;
|
|
42
|
+
}
|
|
43
|
+
export interface CutView {
|
|
44
|
+
units: UnitSummary[];
|
|
45
|
+
ignored: string[];
|
|
46
|
+
ignored_files: number | null;
|
|
47
|
+
unassigned: string[] | null;
|
|
48
|
+
/** Structural refusals — should never appear on a stored cut; shown if a
|
|
49
|
+
* hand-edited file carries one. */
|
|
50
|
+
errors: string[];
|
|
51
|
+
/** What save would refuse for (a draft may carry these; a saved cut that
|
|
52
|
+
* shows one has gone stale against the repo). */
|
|
53
|
+
blocking_save: string[];
|
|
54
|
+
}
|
|
55
|
+
export interface CutStatus {
|
|
56
|
+
ok: boolean;
|
|
57
|
+
/** Why the file or the repo could not be read — the rest is then partial. */
|
|
58
|
+
problems: string[];
|
|
59
|
+
/** The cut file exists but could not be read: `saved`/`draft` are then
|
|
60
|
+
* unknown, not absent. */
|
|
61
|
+
cut_file_unreadable: boolean;
|
|
62
|
+
saved: (CutView & {
|
|
63
|
+
saved_at: string;
|
|
64
|
+
head: string | null;
|
|
65
|
+
files_at_save: number;
|
|
66
|
+
}) | null;
|
|
67
|
+
draft: (CutView & {
|
|
68
|
+
updated_at: string;
|
|
69
|
+
source: DraftCut["source"];
|
|
70
|
+
}) | null;
|
|
71
|
+
has_previous: boolean;
|
|
72
|
+
repo_files: number | null;
|
|
73
|
+
head: string | null;
|
|
74
|
+
}
|
|
75
|
+
/** The cut setup offers when none is saved: the candidates as units, the
|
|
76
|
+
* vendored roots ignored. */
|
|
77
|
+
export declare function candidateCut(candidates: readonly UnitCandidate[], files: readonly string[]): UnitCut;
|
|
78
|
+
/** What the store reads and writes through. */
|
|
79
|
+
export interface UnitCutPorts {
|
|
80
|
+
repo: RepoReader;
|
|
81
|
+
state: StateFs;
|
|
82
|
+
clock: () => Date;
|
|
83
|
+
}
|
|
84
|
+
export declare class UnitCutStore {
|
|
85
|
+
private readonly ports;
|
|
86
|
+
private readonly budget;
|
|
87
|
+
constructor(ports: UnitCutPorts,
|
|
88
|
+
/** How much one case of the unit view may read. */
|
|
89
|
+
caseBudget?: CaseBudget);
|
|
90
|
+
files(): string[] | null;
|
|
91
|
+
noRepo(): Refusal;
|
|
92
|
+
load(): {
|
|
93
|
+
file: UnitCutFile;
|
|
94
|
+
error: string | null;
|
|
95
|
+
};
|
|
96
|
+
private store;
|
|
97
|
+
/** Load for a write: an unreadable file refuses rather than being replaced. */
|
|
98
|
+
private loadForWrite;
|
|
99
|
+
/** A unit's case plans over its reviewable (not sweep-skipped) files. */
|
|
100
|
+
private unitCases;
|
|
101
|
+
view(cut: UnitCut, files: readonly string[], lines: (p: string) => number): CutView;
|
|
102
|
+
lineCounter(): (p: string) => number;
|
|
103
|
+
/** The saved cut and the draft, each re-checked against the repo as it is
|
|
104
|
+
* now — so a saved cut the repo has outgrown (a new top-level directory no
|
|
105
|
+
* unit claims) shows up here instead of being silently skipped later. */
|
|
106
|
+
status(): CutStatus;
|
|
107
|
+
/**
|
|
108
|
+
* Store a proposal as the draft, replacing any earlier draft (never the
|
|
109
|
+
* saved cut). `raw` is the companion's proposal — `{units, ignored?}` — or
|
|
110
|
+
* undefined to take the deterministic candidates as they are (vendored
|
|
111
|
+
* trees ignored). Refused when it is structurally wrong; save-blocking
|
|
112
|
+
* conditions are allowed in a draft and reported.
|
|
113
|
+
*/
|
|
114
|
+
propose(raw?: unknown): {
|
|
115
|
+
ok: true;
|
|
116
|
+
draft: CutView;
|
|
117
|
+
} | Refusal;
|
|
118
|
+
/**
|
|
119
|
+
* Apply the operator's corrections to the draft — starting one from the
|
|
120
|
+
* saved cut when there is no draft — all-or-nothing: a refused op, or a
|
|
121
|
+
* result that is structurally wrong, leaves the stored draft as it was.
|
|
122
|
+
*/
|
|
123
|
+
adjust(ops: unknown): {
|
|
124
|
+
ok: true;
|
|
125
|
+
draft: CutView;
|
|
126
|
+
} | Refusal;
|
|
127
|
+
/**
|
|
128
|
+
* Promote the draft to the unit cut. Refused unless it is a complete
|
|
129
|
+
* partition of the repo as it is now — every file in exactly one unit or
|
|
130
|
+
* deliberately ignored, no unit left empty. The cut it replaces is kept as
|
|
131
|
+
* `previous`.
|
|
132
|
+
*/
|
|
133
|
+
save(): {
|
|
134
|
+
ok: true;
|
|
135
|
+
saved: CutView;
|
|
136
|
+
} | Refusal;
|
|
137
|
+
/** The saved cut, for every later survey and scan; null when none is saved
|
|
138
|
+
* (or the file cannot be read — `status()` says which). */
|
|
139
|
+
savedCut(): SavedCut | null;
|
|
140
|
+
/**
|
|
141
|
+
* The saved cut as cases: every unit's reviewable files (optionally only
|
|
142
|
+
* those `include` keeps — a scan's stage 1 drops tests and migrations),
|
|
143
|
+
* split to fit the case budget, each case under its unit's name. Refused
|
|
144
|
+
* when there is no saved cut: a survey or scan never runs on a guess.
|
|
145
|
+
*/
|
|
146
|
+
cases(include?: (path: string) => boolean): {
|
|
147
|
+
ok: true;
|
|
148
|
+
cases: CasePlan[];
|
|
149
|
+
} | Refusal;
|
|
150
|
+
}
|
|
151
|
+
/** What a scan reads of the unit cut: the saved cut, and why there is none. */
|
|
152
|
+
export type UnitCutStatusPort = Pick<UnitCutStore, "savedCut" | "status">;
|
|
153
|
+
/** The unit-cut verbs `qcr scan units` and `/qcr-scan units` call. */
|
|
154
|
+
export type UnitCutPort = Pick<UnitCutStore, "status" | "propose" | "adjust" | "save">;
|
|
155
|
+
//# sourceMappingURL=unitcutstore.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unitcutstore.d.ts","sourceRoot":"","sources":["../../../src/scan/unitcutstore.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,381 @@
|
|
|
1
|
+
// The unit cut, stored: the saved cut every survey and scan reads by, the cut
|
|
2
|
+
// it replaced, and at most one draft (the companion's proposal as the
|
|
3
|
+
// operator adjusts it), in `<state home>/setup/unit-cut.json`, tmp+rename
|
|
4
|
+
// atomic through the state port. A saved cut is never touched by a propose or
|
|
5
|
+
// an adjust — only `save` replaces it. An unreadable file is reported and
|
|
6
|
+
// refuses every write: it may hold the operator's saved cut, and silently
|
|
7
|
+
// starting fresh over it would lose that.
|
|
8
|
+
//
|
|
9
|
+
// Its ports are the checkout (read-only), the state home and the clock, and
|
|
10
|
+
// nothing else: the setup engine (engine.ts) owns one for its views, and a
|
|
11
|
+
// scan host with no setup engine (the pi plugin's /qcr-scan) builds one of its
|
|
12
|
+
// own over the same file.
|
|
13
|
+
import { isSweepSkipped } from "../heuristics.js";
|
|
14
|
+
import { unitCandidates, vendoredRoots } from "./facts.js";
|
|
15
|
+
import { DEFAULT_CASE_BUDGET, applyOps, assign, checkCut, normalizeCut, splitUnit, } from "./unitcut.js";
|
|
16
|
+
// ---- the persisted file ------------------------------------------------------
|
|
17
|
+
export const UNIT_CUT_FILE = "setup/unit-cut.json";
|
|
18
|
+
export const UNIT_CUT_VERSION = 1;
|
|
19
|
+
/** Why a stored cut is not one this version can read, or null when it is (or
|
|
20
|
+
* is absent). Structure only — the partition itself is `checkCut`'s. */
|
|
21
|
+
function cutShapeError(cut) {
|
|
22
|
+
if (cut === null)
|
|
23
|
+
return null;
|
|
24
|
+
if (typeof cut !== "object")
|
|
25
|
+
return "is not an object";
|
|
26
|
+
const c = cut;
|
|
27
|
+
const strings = (v) => Array.isArray(v) && v.every((x) => typeof x === "string");
|
|
28
|
+
if (!Array.isArray(c.units))
|
|
29
|
+
return "has no `units` array";
|
|
30
|
+
for (const [i, u] of c.units.entries()) {
|
|
31
|
+
const unit = (u ?? {});
|
|
32
|
+
if (typeof unit.name !== "string" ||
|
|
33
|
+
!strings(unit.roots) ||
|
|
34
|
+
typeof unit.kind !== "string" ||
|
|
35
|
+
typeof unit.note !== "string") {
|
|
36
|
+
return `units[${i}] is not {name, roots, kind, note}`;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
if (!strings(c.ignored))
|
|
40
|
+
return "has no `ignored` array of paths";
|
|
41
|
+
return null;
|
|
42
|
+
}
|
|
43
|
+
/** The cut setup offers when none is saved: the candidates as units, the
|
|
44
|
+
* vendored roots ignored. */
|
|
45
|
+
export function candidateCut(candidates, files) {
|
|
46
|
+
return {
|
|
47
|
+
units: candidates.map((c) => ({ name: c.name, roots: c.roots, kind: c.kind, note: c.reason })),
|
|
48
|
+
ignored: vendoredRoots(files),
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
export class UnitCutStore {
|
|
52
|
+
ports;
|
|
53
|
+
budget;
|
|
54
|
+
constructor(ports,
|
|
55
|
+
/** How much one case of the unit view may read. */
|
|
56
|
+
caseBudget = DEFAULT_CASE_BUDGET) {
|
|
57
|
+
this.ports = ports;
|
|
58
|
+
this.budget = caseBudget;
|
|
59
|
+
}
|
|
60
|
+
files() {
|
|
61
|
+
const listed = this.ports.repo.listFiles();
|
|
62
|
+
return listed === null ? null : [...listed].sort();
|
|
63
|
+
}
|
|
64
|
+
noRepo() {
|
|
65
|
+
return {
|
|
66
|
+
ok: false,
|
|
67
|
+
errors: [
|
|
68
|
+
`no readable checkout at ${this.ports.repo.location} — is the reviewed repo mounted?`,
|
|
69
|
+
],
|
|
70
|
+
};
|
|
71
|
+
}
|
|
72
|
+
// -- the file --
|
|
73
|
+
load() {
|
|
74
|
+
const empty = {
|
|
75
|
+
version: UNIT_CUT_VERSION,
|
|
76
|
+
saved: null,
|
|
77
|
+
previous: null,
|
|
78
|
+
draft: null,
|
|
79
|
+
};
|
|
80
|
+
let text;
|
|
81
|
+
try {
|
|
82
|
+
text = this.ports.state.read(UNIT_CUT_FILE);
|
|
83
|
+
}
|
|
84
|
+
catch (err) {
|
|
85
|
+
return {
|
|
86
|
+
file: empty,
|
|
87
|
+
error: `${UNIT_CUT_FILE} in ${this.ports.state.location} cannot be read: ${String(err)}`,
|
|
88
|
+
};
|
|
89
|
+
}
|
|
90
|
+
if (text === null)
|
|
91
|
+
return { file: empty, error: null };
|
|
92
|
+
try {
|
|
93
|
+
const raw = JSON.parse(text);
|
|
94
|
+
if (typeof raw !== "object" || raw === null || raw.version !== UNIT_CUT_VERSION) {
|
|
95
|
+
throw new Error(`unknown version ${JSON.stringify(raw?.version)}`);
|
|
96
|
+
}
|
|
97
|
+
const file = {
|
|
98
|
+
version: UNIT_CUT_VERSION,
|
|
99
|
+
saved: raw.saved ?? null,
|
|
100
|
+
previous: raw.previous ?? null,
|
|
101
|
+
draft: raw.draft ?? null,
|
|
102
|
+
};
|
|
103
|
+
// A hand-edited file must be reported, never crash a view: every later
|
|
104
|
+
// reader (assign, splitUnit) takes the shape on trust.
|
|
105
|
+
for (const key of ["saved", "previous", "draft"]) {
|
|
106
|
+
const bad = cutShapeError(file[key]);
|
|
107
|
+
if (bad !== null)
|
|
108
|
+
throw new Error(`\`${key}\` ${bad}`);
|
|
109
|
+
}
|
|
110
|
+
return { file, error: null };
|
|
111
|
+
}
|
|
112
|
+
catch (err) {
|
|
113
|
+
return {
|
|
114
|
+
file: empty,
|
|
115
|
+
error: `${UNIT_CUT_FILE} in ${this.ports.state.location} is not a unit cut this version reads (${String(err)}) — ` +
|
|
116
|
+
"nothing will overwrite it; move it aside to start over",
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
store(file) {
|
|
121
|
+
this.ports.state.write(UNIT_CUT_FILE, `${JSON.stringify(file, null, 2)}\n`);
|
|
122
|
+
}
|
|
123
|
+
/** Load for a write: an unreadable file refuses rather than being replaced. */
|
|
124
|
+
loadForWrite() {
|
|
125
|
+
const { file, error } = this.load();
|
|
126
|
+
return error === null ? { file } : { ok: false, errors: [error] };
|
|
127
|
+
}
|
|
128
|
+
// -- views --
|
|
129
|
+
/** A unit's case plans over its reviewable (not sweep-skipped) files. */
|
|
130
|
+
unitCases(name, owned, lines) {
|
|
131
|
+
return splitUnit(name, owned.filter((f) => !isSweepSkipped(f)), lines, this.budget);
|
|
132
|
+
}
|
|
133
|
+
view(cut, files, lines) {
|
|
134
|
+
const { errors, blocking_save } = checkCut(cut, files);
|
|
135
|
+
// A cut with structural errors (a hand-edited file) still gets a
|
|
136
|
+
// best-effort view, with the errors beside it.
|
|
137
|
+
const a = assign(cut, files);
|
|
138
|
+
const sizeErrors = [];
|
|
139
|
+
const units = cut.units.map((u) => {
|
|
140
|
+
const owned = a.byUnit.get(u.name) ?? [];
|
|
141
|
+
const reviewable = owned.filter((f) => !isSweepSkipped(f));
|
|
142
|
+
let cases = [];
|
|
143
|
+
let unavailable = false;
|
|
144
|
+
try {
|
|
145
|
+
cases = this.unitCases(u.name, owned, lines);
|
|
146
|
+
}
|
|
147
|
+
catch (err) {
|
|
148
|
+
unavailable = true;
|
|
149
|
+
sizeErrors.push(String(err));
|
|
150
|
+
}
|
|
151
|
+
return {
|
|
152
|
+
name: u.name,
|
|
153
|
+
kind: u.kind,
|
|
154
|
+
roots: u.roots,
|
|
155
|
+
note: u.note,
|
|
156
|
+
files: owned.length,
|
|
157
|
+
reviewable: reviewable.length,
|
|
158
|
+
lines: unavailable ? null : cases.reduce((n, c) => n + c.lines, 0),
|
|
159
|
+
cases: unavailable
|
|
160
|
+
? null
|
|
161
|
+
: cases.map((c) => ({
|
|
162
|
+
id: c.id,
|
|
163
|
+
files: c.files.length,
|
|
164
|
+
lines: c.lines,
|
|
165
|
+
over_budget: c.over_budget,
|
|
166
|
+
})),
|
|
167
|
+
};
|
|
168
|
+
});
|
|
169
|
+
return {
|
|
170
|
+
units,
|
|
171
|
+
ignored: cut.ignored,
|
|
172
|
+
ignored_files: a.ignored.length,
|
|
173
|
+
unassigned: a.unassigned,
|
|
174
|
+
errors: [...errors, ...sizeErrors],
|
|
175
|
+
blocking_save,
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
lineCounter() {
|
|
179
|
+
const cache = new Map();
|
|
180
|
+
return (p) => {
|
|
181
|
+
let n = cache.get(p);
|
|
182
|
+
if (n === undefined) {
|
|
183
|
+
const measured = this.ports.repo.lines(p);
|
|
184
|
+
if (measured === null)
|
|
185
|
+
throw new Error(`line count UNKNOWN for ${p} — unreadable, binary or too large; no case or price can be inferred`);
|
|
186
|
+
n = measured;
|
|
187
|
+
cache.set(p, n);
|
|
188
|
+
}
|
|
189
|
+
return n;
|
|
190
|
+
};
|
|
191
|
+
}
|
|
192
|
+
/** The saved cut and the draft, each re-checked against the repo as it is
|
|
193
|
+
* now — so a saved cut the repo has outgrown (a new top-level directory no
|
|
194
|
+
* unit claims) shows up here instead of being silently skipped later. */
|
|
195
|
+
status() {
|
|
196
|
+
const { file, error } = this.load();
|
|
197
|
+
const problems = error === null ? [] : [error];
|
|
198
|
+
const files = this.files();
|
|
199
|
+
if (files === null)
|
|
200
|
+
problems.push(this.noRepo().errors[0]);
|
|
201
|
+
const head = files === null ? null : this.ports.repo.head();
|
|
202
|
+
const lines = this.lineCounter();
|
|
203
|
+
const see = (cut) => files === null
|
|
204
|
+
? {
|
|
205
|
+
units: cut.units.map((u) => ({
|
|
206
|
+
...u,
|
|
207
|
+
files: null,
|
|
208
|
+
reviewable: null,
|
|
209
|
+
lines: null,
|
|
210
|
+
cases: null,
|
|
211
|
+
})),
|
|
212
|
+
ignored: cut.ignored,
|
|
213
|
+
ignored_files: null,
|
|
214
|
+
unassigned: null,
|
|
215
|
+
errors: [],
|
|
216
|
+
blocking_save: [],
|
|
217
|
+
}
|
|
218
|
+
: this.view(cut, files, lines);
|
|
219
|
+
return {
|
|
220
|
+
ok: problems.length === 0,
|
|
221
|
+
problems,
|
|
222
|
+
cut_file_unreadable: error !== null,
|
|
223
|
+
saved: file.saved
|
|
224
|
+
? {
|
|
225
|
+
...see(file.saved),
|
|
226
|
+
saved_at: file.saved.saved_at,
|
|
227
|
+
head: file.saved.head,
|
|
228
|
+
files_at_save: file.saved.files,
|
|
229
|
+
}
|
|
230
|
+
: null,
|
|
231
|
+
draft: file.draft
|
|
232
|
+
? { ...see(file.draft), updated_at: file.draft.updated_at, source: file.draft.source }
|
|
233
|
+
: null,
|
|
234
|
+
has_previous: file.previous !== null,
|
|
235
|
+
repo_files: files?.length ?? null,
|
|
236
|
+
head,
|
|
237
|
+
};
|
|
238
|
+
}
|
|
239
|
+
// -- the three verbs --
|
|
240
|
+
/**
|
|
241
|
+
* Store a proposal as the draft, replacing any earlier draft (never the
|
|
242
|
+
* saved cut). `raw` is the companion's proposal — `{units, ignored?}` — or
|
|
243
|
+
* undefined to take the deterministic candidates as they are (vendored
|
|
244
|
+
* trees ignored). Refused when it is structurally wrong; save-blocking
|
|
245
|
+
* conditions are allowed in a draft and reported.
|
|
246
|
+
*/
|
|
247
|
+
propose(raw) {
|
|
248
|
+
const files = this.files();
|
|
249
|
+
if (files === null)
|
|
250
|
+
return this.noRepo();
|
|
251
|
+
const loaded = this.loadForWrite();
|
|
252
|
+
if ("ok" in loaded)
|
|
253
|
+
return loaded;
|
|
254
|
+
let cut;
|
|
255
|
+
let source;
|
|
256
|
+
if (raw === undefined || raw === null || (typeof raw === "object" && !("units" in raw))) {
|
|
257
|
+
cut = candidateCut(unitCandidates(files), files);
|
|
258
|
+
source = "candidates";
|
|
259
|
+
}
|
|
260
|
+
else {
|
|
261
|
+
const n = normalizeCut(raw);
|
|
262
|
+
if (!n.ok)
|
|
263
|
+
return n;
|
|
264
|
+
cut = n.cut;
|
|
265
|
+
source = "companion";
|
|
266
|
+
}
|
|
267
|
+
const problems = checkCut(cut, files);
|
|
268
|
+
if (problems.errors.length > 0)
|
|
269
|
+
return { ok: false, errors: problems.errors };
|
|
270
|
+
loaded.file.draft = { ...cut, updated_at: this.ports.clock().toISOString(), source };
|
|
271
|
+
this.store(loaded.file);
|
|
272
|
+
return { ok: true, draft: this.view(cut, files, this.lineCounter()) };
|
|
273
|
+
}
|
|
274
|
+
/**
|
|
275
|
+
* Apply the operator's corrections to the draft — starting one from the
|
|
276
|
+
* saved cut when there is no draft — all-or-nothing: a refused op, or a
|
|
277
|
+
* result that is structurally wrong, leaves the stored draft as it was.
|
|
278
|
+
*/
|
|
279
|
+
adjust(ops) {
|
|
280
|
+
if (!Array.isArray(ops) || ops.length === 0) {
|
|
281
|
+
return { ok: false, errors: ["`ops` must be a non-empty array of adjust operations"] };
|
|
282
|
+
}
|
|
283
|
+
const files = this.files();
|
|
284
|
+
if (files === null)
|
|
285
|
+
return this.noRepo();
|
|
286
|
+
const loaded = this.loadForWrite();
|
|
287
|
+
if ("ok" in loaded)
|
|
288
|
+
return loaded;
|
|
289
|
+
const base = loaded.file.draft ?? loaded.file.saved;
|
|
290
|
+
if (!base)
|
|
291
|
+
return { ok: false, errors: ["there is no unit cut to adjust yet — propose one first"] };
|
|
292
|
+
const applied = applyOps({ units: base.units, ignored: base.ignored }, ops);
|
|
293
|
+
if (!applied.ok)
|
|
294
|
+
return applied;
|
|
295
|
+
const problems = checkCut(applied.cut, files);
|
|
296
|
+
if (problems.errors.length > 0)
|
|
297
|
+
return { ok: false, errors: problems.errors };
|
|
298
|
+
loaded.file.draft = {
|
|
299
|
+
...applied.cut,
|
|
300
|
+
updated_at: this.ports.clock().toISOString(),
|
|
301
|
+
source: "adjusted",
|
|
302
|
+
};
|
|
303
|
+
this.store(loaded.file);
|
|
304
|
+
return { ok: true, draft: this.view(applied.cut, files, this.lineCounter()) };
|
|
305
|
+
}
|
|
306
|
+
/**
|
|
307
|
+
* Promote the draft to the unit cut. Refused unless it is a complete
|
|
308
|
+
* partition of the repo as it is now — every file in exactly one unit or
|
|
309
|
+
* deliberately ignored, no unit left empty. The cut it replaces is kept as
|
|
310
|
+
* `previous`.
|
|
311
|
+
*/
|
|
312
|
+
save() {
|
|
313
|
+
const files = this.files();
|
|
314
|
+
if (files === null)
|
|
315
|
+
return this.noRepo();
|
|
316
|
+
const loaded = this.loadForWrite();
|
|
317
|
+
if ("ok" in loaded)
|
|
318
|
+
return loaded;
|
|
319
|
+
const draft = loaded.file.draft;
|
|
320
|
+
if (!draft) {
|
|
321
|
+
return {
|
|
322
|
+
ok: false,
|
|
323
|
+
errors: [
|
|
324
|
+
loaded.file.saved
|
|
325
|
+
? "no draft to save — the saved cut is already in use; adjust it to start a draft"
|
|
326
|
+
: "no draft to save — propose a unit cut first",
|
|
327
|
+
],
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
const cut = { units: draft.units, ignored: draft.ignored };
|
|
331
|
+
const problems = checkCut(cut, files);
|
|
332
|
+
if (problems.errors.length > 0 || problems.blocking_save.length > 0) {
|
|
333
|
+
return { ok: false, errors: [...problems.errors, ...problems.blocking_save] };
|
|
334
|
+
}
|
|
335
|
+
loaded.file.previous = loaded.file.saved;
|
|
336
|
+
loaded.file.saved = {
|
|
337
|
+
...cut,
|
|
338
|
+
saved_at: this.ports.clock().toISOString(),
|
|
339
|
+
head: this.ports.repo.head(),
|
|
340
|
+
files: files.length,
|
|
341
|
+
};
|
|
342
|
+
loaded.file.draft = null;
|
|
343
|
+
this.store(loaded.file);
|
|
344
|
+
return { ok: true, saved: this.view(cut, files, this.lineCounter()) };
|
|
345
|
+
}
|
|
346
|
+
// -- reuse --
|
|
347
|
+
/** The saved cut, for every later survey and scan; null when none is saved
|
|
348
|
+
* (or the file cannot be read — `status()` says which). */
|
|
349
|
+
savedCut() {
|
|
350
|
+
return this.load().file.saved;
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The saved cut as cases: every unit's reviewable files (optionally only
|
|
354
|
+
* those `include` keeps — a scan's stage 1 drops tests and migrations),
|
|
355
|
+
* split to fit the case budget, each case under its unit's name. Refused
|
|
356
|
+
* when there is no saved cut: a survey or scan never runs on a guess.
|
|
357
|
+
*/
|
|
358
|
+
cases(include = () => true) {
|
|
359
|
+
const files = this.files();
|
|
360
|
+
if (files === null)
|
|
361
|
+
return this.noRepo();
|
|
362
|
+
const { file, error } = this.load();
|
|
363
|
+
if (error !== null)
|
|
364
|
+
return { ok: false, errors: [error] };
|
|
365
|
+
if (!file.saved)
|
|
366
|
+
return { ok: false, errors: ["no saved unit cut — propose, adjust and save one first"] };
|
|
367
|
+
const a = assign(file.saved, files);
|
|
368
|
+
const lines = this.lineCounter();
|
|
369
|
+
const cases = [];
|
|
370
|
+
try {
|
|
371
|
+
for (const u of file.saved.units) {
|
|
372
|
+
cases.push(...this.unitCases(u.name, (a.byUnit.get(u.name) ?? []).filter(include), lines));
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
catch (err) {
|
|
376
|
+
return { ok: false, errors: [String(err)] };
|
|
377
|
+
}
|
|
378
|
+
return { ok: true, cases };
|
|
379
|
+
}
|
|
380
|
+
}
|
|
381
|
+
//# sourceMappingURL=unitcutstore.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"unitcutstore.js","sourceRoot":"","sources":["../../../src/scan/unitcutstore.ts"],"names":[],"mappings":"AAAA,8EAA8E;AAC9E,sEAAsE;AACtE,0EAA0E;AAC1E,8EAA8E;AAC9E,0EAA0E;AAC1E,0EAA0E;AAC1E,0CAA0C;AAC1C,EAAE;AACF,4EAA4E;AAC5E,2EAA2E;AAC3E,+EAA+E;AAC/E,0BAA0B;AAC1B,OAAO,EAAE,cAAc,EAAE,MAAM,kBAAkB,CAAC;AAClD,OAAO,EAAE,cAAc,EAAE,aAAa,EAAsB,MAAM,YAAY,CAAC;AAE/E,OAAO,EACL,mBAAmB,EACnB,QAAQ,EACR,MAAM,EACN,QAAQ,EACR,YAAY,EACZ,SAAS,GAIV,MAAM,cAAc,CAAC;AAEtB,iFAAiF;AAEjF,MAAM,CAAC,MAAM,aAAa,GAAG,qBAAqB,CAAC;AACnD,MAAM,CAAC,MAAM,gBAAgB,GAAG,CAAC,CAAC;AAmElC;wEACwE;AACxE,SAAS,aAAa,CAAC,GAAY;IACjC,IAAI,GAAG,KAAK,IAAI;QAAE,OAAO,IAAI,CAAC;IAC9B,IAAI,OAAO,GAAG,KAAK,QAAQ;QAAE,OAAO,kBAAkB,CAAC;IACvD,MAAM,CAAC,GAAG,GAA6C,CAAC;IACxD,MAAM,OAAO,GAAG,CAAC,CAAU,EAAW,EAAE,CACtC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC;IAC5D,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,KAAK,CAAC;QAAE,OAAO,sBAAsB,CAAC;IAC3D,KAAK,MAAM,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QACvC,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,EAAE,CAAwE,CAAC;QAC9F,IACE,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC7B,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC;YACpB,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ;YAC7B,OAAO,IAAI,CAAC,IAAI,KAAK,QAAQ,EAC7B,CAAC;YACD,OAAO,SAAS,CAAC,oCAAoC,CAAC;QACxD,CAAC;IACH,CAAC;IACD,IAAI,CAAC,OAAO,CAAC,CAAC,CAAC,OAAO,CAAC;QAAE,OAAO,iCAAiC,CAAC;IAClE,OAAO,IAAI,CAAC;AACd,CAAC;AAED;6BAC6B;AAC7B,MAAM,UAAU,YAAY,CAC1B,UAAoC,EACpC,KAAwB;IAExB,OAAO;QACL,KAAK,EAAE,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC;QAC9F,OAAO,EAAE,aAAa,CAAC,KAAK,CAAC;KAC9B,CAAC;AACJ,CAAC;AASD,MAAM,OAAO,YAAY;IAIJ;IAHF,MAAM,CAAa;IAEpC,YACmB,KAAmB;IACpC,mDAAmD;IACnD,aAAyB,mBAAmB;QAF3B,UAAK,GAAL,KAAK,CAAc;QAIpC,IAAI,CAAC,MAAM,GAAG,UAAU,CAAC;IAC3B,CAAC;IAED,KAAK;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,SAAS,EAAE,CAAC;QAC3C,OAAO,MAAM,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,MAAM,CAAC,CAAC,IAAI,EAAE,CAAC;IACrD,CAAC;IAED,MAAM;QACJ,OAAO;YACL,EAAE,EAAE,KAAK;YACT,MAAM,EAAE;gBACN,2BAA2B,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,QAAQ,kCAAkC;aACtF;SACF,CAAC;IACJ,CAAC;IAED,iBAAiB;IAEjB,IAAI;QACF,MAAM,KAAK,GAAgB;YACzB,OAAO,EAAE,gBAAgB;YACzB,KAAK,EAAE,IAAI;YACX,QAAQ,EAAE,IAAI;YACd,KAAK,EAAE,IAAI;SACZ,CAAC;QACF,IAAI,IAAmB,CAAC;QACxB,IAAI,CAAC;YACH,IAAI,GAAG,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,CAAC,aAAa,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EAAE,GAAG,aAAa,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,oBAAoB,MAAM,CAAC,GAAG,CAAC,EAAE;aACzF,CAAC;QACJ,CAAC;QACD,IAAI,IAAI,KAAK,IAAI;YAAE,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QACvD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAyB,CAAC;YACrD,IAAI,OAAO,GAAG,KAAK,QAAQ,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,CAAC,OAAO,KAAK,gBAAgB,EAAE,CAAC;gBAChF,MAAM,IAAI,KAAK,CACb,mBAAmB,IAAI,CAAC,SAAS,CAAE,GAAoC,EAAE,OAAO,CAAC,EAAE,CACpF,CAAC;YACJ,CAAC;YACD,MAAM,IAAI,GAAgB;gBACxB,OAAO,EAAE,gBAAgB;gBACzB,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI;gBACxB,QAAQ,EAAE,GAAG,CAAC,QAAQ,IAAI,IAAI;gBAC9B,KAAK,EAAE,GAAG,CAAC,KAAK,IAAI,IAAI;aACzB,CAAC;YACF,uEAAuE;YACvE,uDAAuD;YACvD,KAAK,MAAM,GAAG,IAAI,CAAC,OAAO,EAAE,UAAU,EAAE,OAAO,CAAU,EAAE,CAAC;gBAC1D,MAAM,GAAG,GAAG,aAAa,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;gBACrC,IAAI,GAAG,KAAK,IAAI;oBAAE,MAAM,IAAI,KAAK,CAAC,KAAK,GAAG,MAAM,GAAG,EAAE,CAAC,CAAC;YACzD,CAAC;YACD,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,EAAE,CAAC;QAC/B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO;gBACL,IAAI,EAAE,KAAK;gBACX,KAAK,EACH,GAAG,aAAa,OAAO,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,QAAQ,0CAA0C,MAAM,CAAC,GAAG,CAAC,MAAM;oBAC3G,wDAAwD;aAC3D,CAAC;QACJ,CAAC;IACH,CAAC;IAEO,KAAK,CAAC,IAAiB;QAC7B,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,KAAK,CAAC,aAAa,EAAE,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC;IAC9E,CAAC;IAED,+EAA+E;IACvE,YAAY;QAClB,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,OAAO,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;IACpE,CAAC;IAED,cAAc;IAEd,yEAAyE;IACjE,SAAS,CACf,IAAY,EACZ,KAAwB,EACxB,KAA4B;QAE5B,OAAO,SAAS,CACd,IAAI,EACJ,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,EACvC,KAAK,EACL,IAAI,CAAC,MAAM,CACZ,CAAC;IACJ,CAAC;IAED,IAAI,CAAC,GAAY,EAAE,KAAwB,EAAE,KAA4B;QACvE,MAAM,EAAE,MAAM,EAAE,aAAa,EAAE,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACvD,iEAAiE;QACjE,+CAA+C;QAC/C,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC7B,MAAM,UAAU,GAAa,EAAE,CAAC;QAChC,MAAM,KAAK,GAAkB,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE;YAC/C,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;YACzC,MAAM,UAAU,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,cAAc,CAAC,CAAC,CAAC,CAAC,CAAC;YAC3D,IAAI,KAAK,GAAe,EAAE,CAAC;YAC3B,IAAI,WAAW,GAAG,KAAK,CAAC;YACxB,IAAI,CAAC;gBACH,KAAK,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;YAC/C,CAAC;YAAC,OAAO,GAAG,EAAE,CAAC;gBACb,WAAW,GAAG,IAAI,CAAC;gBACnB,UAAU,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC;YAC/B,CAAC;YACD,OAAO;gBACL,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,CAAC,CAAC,KAAK;gBACd,IAAI,EAAE,CAAC,CAAC,IAAI;gBACZ,KAAK,EAAE,KAAK,CAAC,MAAM;gBACnB,UAAU,EAAE,UAAU,CAAC,MAAM;gBAC7B,KAAK,EAAE,WAAW,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC;gBAClE,KAAK,EAAE,WAAW;oBAChB,CAAC,CAAC,IAAI;oBACN,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;wBAChB,EAAE,EAAE,CAAC,CAAC,EAAE;wBACR,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,MAAM;wBACrB,KAAK,EAAE,CAAC,CAAC,KAAK;wBACd,WAAW,EAAE,CAAC,CAAC,WAAW;qBAC3B,CAAC,CAAC;aACR,CAAC;QACJ,CAAC,CAAC,CAAC;QACH,OAAO;YACL,KAAK;YACL,OAAO,EAAE,GAAG,CAAC,OAAO;YACpB,aAAa,EAAE,CAAC,CAAC,OAAO,CAAC,MAAM;YAC/B,UAAU,EAAE,CAAC,CAAC,UAAU;YACxB,MAAM,EAAE,CAAC,GAAG,MAAM,EAAE,GAAG,UAAU,CAAC;YAClC,aAAa;SACd,CAAC;IACJ,CAAC;IAED,WAAW;QACT,MAAM,KAAK,GAAG,IAAI,GAAG,EAAkB,CAAC;QACxC,OAAO,CAAC,CAAC,EAAE,EAAE;YACX,IAAI,CAAC,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC;YACrB,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;gBACpB,MAAM,QAAQ,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC;gBAC1C,IAAI,QAAQ,KAAK,IAAI;oBACnB,MAAM,IAAI,KAAK,CACb,0BAA0B,CAAC,sEAAsE,CAClG,CAAC;gBACJ,CAAC,GAAG,QAAQ,CAAC;gBACb,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;YAClB,CAAC;YACD,OAAO,CAAC,CAAC;QACX,CAAC,CAAC;IACJ,CAAC;IAED;;6EAEyE;IACzE,MAAM;QACJ,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,MAAM,QAAQ,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;QAC/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,QAAQ,CAAC,IAAI,CAAC,IAAI,CAAC,MAAM,EAAE,CAAC,MAAM,CAAC,CAAC,CAAE,CAAC,CAAC;QAC5D,MAAM,IAAI,GAAG,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC;QAC5D,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,GAAG,GAAG,CAAC,GAAY,EAAW,EAAE,CACpC,KAAK,KAAK,IAAI;YACZ,CAAC,CAAC;gBACE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;oBAC3B,GAAG,CAAC;oBACJ,KAAK,EAAE,IAAI;oBACX,UAAU,EAAE,IAAI;oBAChB,KAAK,EAAE,IAAI;oBACX,KAAK,EAAE,IAAI;iBACZ,CAAC,CAAC;gBACH,OAAO,EAAE,GAAG,CAAC,OAAO;gBACpB,aAAa,EAAE,IAAI;gBACnB,UAAU,EAAE,IAAI;gBAChB,MAAM,EAAE,EAAE;gBACV,aAAa,EAAE,EAAE;aAClB;YACH,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,KAAK,CAAC,CAAC;QACnC,OAAO;YACL,EAAE,EAAE,QAAQ,CAAC,MAAM,KAAK,CAAC;YACzB,QAAQ;YACR,mBAAmB,EAAE,KAAK,KAAK,IAAI;YACnC,KAAK,EAAE,IAAI,CAAC,KAAK;gBACf,CAAC,CAAC;oBACE,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC;oBAClB,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,QAAQ;oBAC7B,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI;oBACrB,aAAa,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK;iBAChC;gBACH,CAAC,CAAC,IAAI;YACR,KAAK,EAAE,IAAI,CAAC,KAAK;gBACf,CAAC,CAAC,EAAE,GAAG,GAAG,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,EAAE;gBACtF,CAAC,CAAC,IAAI;YACR,YAAY,EAAE,IAAI,CAAC,QAAQ,KAAK,IAAI;YACpC,UAAU,EAAE,KAAK,EAAE,MAAM,IAAI,IAAI;YACjC,IAAI;SACL,CAAC;IACJ,CAAC;IAED,wBAAwB;IAExB;;;;;;OAMG;IACH,OAAO,CAAC,GAAa;QACnB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAClC,IAAI,GAAY,CAAC;QACjB,IAAI,MAA0B,CAAC;QAC/B,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,IAAI,IAAI,CAAC,OAAO,GAAG,KAAK,QAAQ,IAAI,CAAC,CAAC,OAAO,IAAI,GAAG,CAAC,CAAC,EAAE,CAAC;YACxF,GAAG,GAAG,YAAY,CAAC,cAAc,CAAC,KAAK,CAAC,EAAE,KAAK,CAAC,CAAC;YACjD,MAAM,GAAG,YAAY,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,MAAM,CAAC,GAAG,YAAY,CAAC,GAAG,CAAC,CAAC;YAC5B,IAAI,CAAC,CAAC,CAAC,EAAE;gBAAE,OAAO,CAAC,CAAC;YACpB,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;YACZ,MAAM,GAAG,WAAW,CAAC;QACvB,CAAC;QACD,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,EAAE,GAAG,GAAG,EAAE,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE,EAAE,MAAM,EAAE,CAAC;QACrF,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IAED;;;;OAIG;IACH,MAAM,CAAC,GAAY;QACjB,IAAI,CAAC,KAAK,CAAC,OAAO,CAAC,GAAG,CAAC,IAAI,GAAG,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YAC5C,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,sDAAsD,CAAC,EAAE,CAAC;QACzF,CAAC;QACD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAClC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,IAAI,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACpD,IAAI,CAAC,IAAI;YACP,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,wDAAwD,CAAC,EAAE,CAAC;QAC3F,MAAM,OAAO,GAAG,QAAQ,CAAC,EAAE,KAAK,EAAE,IAAI,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,CAAC,OAAO,EAAE,EAAE,GAAG,CAAC,CAAC;QAC5E,IAAI,CAAC,OAAO,CAAC,EAAE;YAAE,OAAO,OAAO,CAAC;QAChC,MAAM,QAAQ,GAAG,QAAQ,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QAC9C,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ,CAAC,MAAM,EAAE,CAAC;QAC9E,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG;YAClB,GAAG,OAAO,CAAC,GAAG;YACd,UAAU,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE;YAC5C,MAAM,EAAE,UAAU;SACnB,CAAC;QACF,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;IAChF,CAAC;IAED;;;;;OAKG;IACH,IAAI;QACF,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,MAAM,GAAG,IAAI,CAAC,YAAY,EAAE,CAAC;QACnC,IAAI,IAAI,IAAI,MAAM;YAAE,OAAO,MAAM,CAAC;QAClC,MAAM,KAAK,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QAChC,IAAI,CAAC,KAAK,EAAE,CAAC;YACX,OAAO;gBACL,EAAE,EAAE,KAAK;gBACT,MAAM,EAAE;oBACN,MAAM,CAAC,IAAI,CAAC,KAAK;wBACf,CAAC,CAAC,gFAAgF;wBAClF,CAAC,CAAC,6CAA6C;iBAClD;aACF,CAAC;QACJ,CAAC;QACD,MAAM,GAAG,GAAY,EAAE,KAAK,EAAE,KAAK,CAAC,KAAK,EAAE,OAAO,EAAE,KAAK,CAAC,OAAO,EAAE,CAAC;QACpE,MAAM,QAAQ,GAAG,QAAQ,CAAC,GAAG,EAAE,KAAK,CAAC,CAAC;QACtC,IAAI,QAAQ,CAAC,MAAM,CAAC,MAAM,GAAG,CAAC,IAAI,QAAQ,CAAC,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;YACpE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,GAAG,QAAQ,CAAC,MAAM,EAAE,GAAG,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAChF,CAAC;QACD,MAAM,CAAC,IAAI,CAAC,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC;QACzC,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG;YAClB,GAAG,GAAG;YACN,QAAQ,EAAE,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC,WAAW,EAAE;YAC1C,IAAI,EAAE,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,IAAI,EAAE;YAC5B,KAAK,EAAE,KAAK,CAAC,MAAM;SACpB,CAAC;QACF,MAAM,CAAC,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACzB,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;QACxB,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,CAAC,EAAE,CAAC;IACxE,CAAC;IAED,cAAc;IAEd;+DAC2D;IAC3D,QAAQ;QACN,OAAO,IAAI,CAAC,IAAI,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC;IAChC,CAAC;IAED;;;;;OAKG;IACH,KAAK,CACH,UAAqC,GAAG,EAAE,CAAC,IAAI;QAE/C,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,IAAI,CAAC,MAAM,EAAE,CAAC;QACzC,MAAM,EAAE,IAAI,EAAE,KAAK,EAAE,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;QACpC,IAAI,KAAK,KAAK,IAAI;YAAE,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,KAAK,CAAC,EAAE,CAAC;QAC1D,IAAI,CAAC,IAAI,CAAC,KAAK;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,wDAAwD,CAAC,EAAE,CAAC;QAC3F,MAAM,CAAC,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,EAAE,KAAK,CAAC,CAAC;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,WAAW,EAAE,CAAC;QACjC,MAAM,KAAK,GAAe,EAAE,CAAC;QAC7B,IAAI,CAAC;YACH,KAAK,MAAM,CAAC,IAAI,IAAI,CAAC,KAAK,CAAC,KAAK,EAAE,CAAC;gBACjC,KAAK,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,EAAE,KAAK,CAAC,CAAC,CAAC;YAC7F,CAAC;QACH,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,OAAO,EAAE,EAAE,EAAE,KAAK,EAAE,MAAM,EAAE,CAAC,MAAM,CAAC,GAAG,CAAC,CAAC,EAAE,CAAC;QAC9C,CAAC;QACD,OAAO,EAAE,EAAE,EAAE,IAAI,EAAE,KAAK,EAAE,CAAC;IAC7B,CAAC;CACF"}
|