@reneturcios/greenlight 0.5.0 → 0.6.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 +25 -0
- package/dist/babysit.d.ts +132 -0
- package/dist/babysit.js +439 -0
- package/dist/babysit.js.map +1 -0
- package/dist/cli.js +90 -3
- package/dist/cli.js.map +1 -1
- package/dist/digest.d.ts +1 -1
- package/dist/digest.js +1 -1
- package/dist/evidence.d.ts +48 -0
- package/dist/evidence.js +254 -0
- package/dist/evidence.js.map +1 -0
- package/dist/guard.d.ts +63 -3
- package/dist/guard.js +131 -4
- package/dist/guard.js.map +1 -1
- package/dist/index.js +33 -1
- package/dist/index.js.map +1 -1
- package/dist/passport.d.ts +52 -0
- package/dist/passport.js +218 -0
- package/dist/passport.js.map +1 -0
- package/integrations/README.md +3 -1
- package/package.json +1 -1
- package/server.json +2 -2
package/README.md
CHANGED
|
@@ -142,6 +142,21 @@ npx @reneturcios/greenlight verify-comment https://github.com/modelcontextprotoc
|
|
|
142
142
|
# reason instead of guessing when it cannot run or parse.
|
|
143
143
|
cd your-repo && npx @reneturcios/greenlight verify --base origin/main
|
|
144
144
|
# exit 3 when new failures exist, 1 when unverifiable
|
|
145
|
+
|
|
146
|
+
# PR babysitter: one prioritized action list across your open PRs —
|
|
147
|
+
# needs you now, waiting on them, quiet. Reruns report what changed.
|
|
148
|
+
npx @reneturcios/greenlight babysit --mine --repos acme/widgets,acme/gadgets
|
|
149
|
+
# or: greenlight babysit --prs <url1>,<url2> --fail-on-action (exit 3 when action is needed)
|
|
150
|
+
|
|
151
|
+
# Verified PR evidence pack: guard + CI triage + review triage + protocol
|
|
152
|
+
# status of linked issues, in one markdown document where every claim
|
|
153
|
+
# cites its source. The test delta comes from a verify report you pass in.
|
|
154
|
+
npx @reneturcios/greenlight evidence https://github.com/acme/widgets/pull/42 --out EVIDENCE.md
|
|
155
|
+
# or: greenlight evidence <pr-url> --verify-json verify.json
|
|
156
|
+
|
|
157
|
+
# Contributor passport: protocol claims from the public Claim Ledger plus
|
|
158
|
+
# merged PRs from GitHub. No Ledger file yet? It says so plainly.
|
|
159
|
+
npx @reneturcios/greenlight passport CloudCorpRecords
|
|
145
160
|
```
|
|
146
161
|
|
|
147
162
|
Real examples from our vetting:
|
|
@@ -205,9 +220,19 @@ Tools:
|
|
|
205
220
|
* `review_triage` - triage the review feedback on your PR: each finding classified likely-real / likely-noise / needs-decision with its reason and a reply draft (humans are never called noise; drafts only, nothing posted)
|
|
206
221
|
* `guard_pr` - maintainer-side analysis of an incoming PR: competing fix, prior claims by someone other than the author, missing artifacts (changeset / DCO / CLA), first-time contributor. Returns comment-ready markdown (never posts).
|
|
207
222
|
* `repo_digest` - repo-level maintainer report: PR races with first-claim arbitration, claimed-by-other conflicts, stale claims, assignment-gate conflicts (never posts).
|
|
223
|
+
* `babysit_prs` - watch open PRs and get the one prioritized action list (needs you now, waiting on them, quiet), diffed against stored watermarks
|
|
224
|
+
* `evidence_pack` - the Verified PR evidence pack for one PR: guard verdict, CI triage, review triage, protocol status of linked issues, every claim citing its source
|
|
208
225
|
|
|
209
226
|
Run it locally: `npm run dev` (MCP entry is `src/index.ts`; CLI is `src/cli.ts`).
|
|
210
227
|
|
|
228
|
+
### v0.6.0: the babysitter, the autopilot, and the trust layer
|
|
229
|
+
|
|
230
|
+
**PR Babysitter.** `greenlight babysit` (or the `babysit_prs` MCP tool) is the answer to 34 open PRs and no time to watch them. Point it at PR URLs, or let it discover your open PRs across repos (`--mine --repos`), and it runs CI triage, review triage, and the guard on each one, diffs against stored watermarks, and prints one prioritized list: *needs you now* first (new likely-real review findings, CI newly failing on your code, merge conflicts, new guard flags, checks stuck over 2 hours), then *waiting on them* (checks still running, CI green with no feedback yet), then *quiet* (a PR that merged or closed retires from the watch with its resolution noted). The first run has no watermarks, so it says so and shows the full picture. Exit 0 always (cron-friendly); `--fail-on-action` gives exit 3 when the needs-you-now list is non-empty.
|
|
231
|
+
|
|
232
|
+
**Maintainer Autopilot.** The guard Action can now act, not just report — but only when the maintainer opts in. An `autopilot` section in `.greenlight-guard.json` carries a label map (check id to label name, e.g. `"protocol-claim": "claim-conflict"`) and a nudge toggle. The guard computes label decisions over severity-flag findings and ready-to-copy stale-claim nudge lines for 14+ day claims with no other open PR; it never applies anything itself. The Action applies the decided labels with the Actions token (creating labels that do not exist yet; failures degrade to warnings, never a failed run), and the nudge lines ride inside the single guard comment for the maintainer to post on the issue. Autopilot never closes PRs, never merges, and never posts beyond the one guard comment. `greenlight guard <pr-url> --labels-dry-run` shows exactly what it would do.
|
|
233
|
+
|
|
234
|
+
**Evidence pack and passport.** `greenlight evidence <pr-url>` (or the `evidence_pack` MCP tool) assembles the Verified PR evidence pack: guard verdict, CI triage, review triage, and Claim Protocol status of the linked issues, in one markdown document where every claim cites its source — the check run, the review anchor, the claim comment URL. The test-suite delta is included only when you hand it a `greenlight verify --json` report; the pack never runs suites itself and says so when the report is missing. And `greenlight passport <github-login>` renders the contributor passport: protocol claims from the public Claim Ledger (active, queued, the completed-vs-expired honor record, the over-cap flag) plus merged PRs from GitHub — the trust layer the Claim Protocol was always heading toward.
|
|
235
|
+
|
|
211
236
|
### v0.3.5: CI triage (solve-first)
|
|
212
237
|
|
|
213
238
|
The first solve-side command. On a red PR, `ci` fetches the PR's base and head, collects the failing check runs (with the first failure lines from annotations when it can), and builds the same checks' history from the twelve most recent base-branch commits. Each failing check gets one line with its class and the evidence: `pre-existing` (same check failing on base, with counts and the last failure time), `likely-yours` (failing on head, passing on base, and the PR touches files that relate to the check), `indeterminate` (no base signal to compare), or `external-blocker` (Vercel/Netlify/deploy-preview auth failures, infrastructure not the PR). Indeterminate checks always state their lean: not touching the check's area leans pre-existing, touching it leans yours, with the reason spelled out. A verdict line closes it out: ALL PRE-EXISTING, HAS LIKELY-YOURS, INDETERMINATE, or NO FAILURES.
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { type CiTriageResult, type CiTriageVerdict } from "./ci-triage.js";
|
|
2
|
+
import { type ReviewTriageResult, type ClassifiedFinding } from "./review-triage.js";
|
|
3
|
+
import { type GuardResult } from "./guard.js";
|
|
4
|
+
export declare const BABYSIT_VERSION = "0.6.0";
|
|
5
|
+
/** Checks pending longer than this are reported as stuck, not just running. */
|
|
6
|
+
export declare const STUCK_CHECK_MINUTES = 120;
|
|
7
|
+
/** Cap on discovered PRs per --mine run; the summary always states the cap. */
|
|
8
|
+
export declare const MINE_DISCOVERY_CAP = 100;
|
|
9
|
+
export interface BabysitPull {
|
|
10
|
+
owner: string;
|
|
11
|
+
repo: string;
|
|
12
|
+
number: number;
|
|
13
|
+
title: string;
|
|
14
|
+
author: string;
|
|
15
|
+
state: string;
|
|
16
|
+
headSha: string;
|
|
17
|
+
baseRef: string;
|
|
18
|
+
/** GitHub may report null while it computes mergeability: unknown, not clean. */
|
|
19
|
+
mergeable: boolean | null;
|
|
20
|
+
mergeableState: string | null;
|
|
21
|
+
url: string;
|
|
22
|
+
}
|
|
23
|
+
export interface BabysitCheckRun {
|
|
24
|
+
name: string;
|
|
25
|
+
status: "queued" | "in_progress" | "completed" | string;
|
|
26
|
+
conclusion: string | null;
|
|
27
|
+
startedAt: string | null;
|
|
28
|
+
detailsUrl?: string;
|
|
29
|
+
}
|
|
30
|
+
export interface BabysitDeps {
|
|
31
|
+
fetchPr?: (owner: string, repo: string, number: number) => Promise<BabysitPull>;
|
|
32
|
+
fetchCheckRuns?: (owner: string, repo: string, headSha: string) => Promise<BabysitCheckRun[]>;
|
|
33
|
+
triageCi?: (prUrl: string) => Promise<CiTriageResult>;
|
|
34
|
+
triageReview?: (prUrl: string) => Promise<ReviewTriageResult>;
|
|
35
|
+
guard?: (prUrl: string) => Promise<GuardResult>;
|
|
36
|
+
discoverPrs?: (author: string, repos: string[]) => Promise<string[]>;
|
|
37
|
+
}
|
|
38
|
+
export interface BabysitWatermark {
|
|
39
|
+
headSha: string;
|
|
40
|
+
seenReviewIds: string[];
|
|
41
|
+
seenGuardFlags: string[];
|
|
42
|
+
lastCiVerdict?: string;
|
|
43
|
+
lastMergeableState?: string | null;
|
|
44
|
+
checkedAt: string;
|
|
45
|
+
}
|
|
46
|
+
export interface BabysitStateFile {
|
|
47
|
+
version: 1;
|
|
48
|
+
watermarks: Record<string, BabysitWatermark>;
|
|
49
|
+
}
|
|
50
|
+
export declare function defaultStatePath(): string;
|
|
51
|
+
export declare function loadState(path: string): BabysitStateFile;
|
|
52
|
+
export declare function saveState(path: string, state: BabysitStateFile): void;
|
|
53
|
+
export declare function watermarkKey(owner: string, repo: string, number: number): string;
|
|
54
|
+
/** Deterministic identity for a review finding, for "new since last run". */
|
|
55
|
+
export declare function reviewFindingId(f: Pick<ClassifiedFinding, "author" | "path" | "line" | "summary">): string;
|
|
56
|
+
/** Deterministic identity for a guard finding, for "new since last run". */
|
|
57
|
+
export declare function guardFlagId(check: string, title: string): string;
|
|
58
|
+
export type ActionUrgency = "now" | "waiting";
|
|
59
|
+
export interface BabysitAction {
|
|
60
|
+
urgency: ActionUrgency;
|
|
61
|
+
pr: string;
|
|
62
|
+
text: string;
|
|
63
|
+
next: string;
|
|
64
|
+
}
|
|
65
|
+
export interface BabysitPrInput {
|
|
66
|
+
prUrl: string;
|
|
67
|
+
pr: BabysitPull;
|
|
68
|
+
checkRuns: BabysitCheckRun[];
|
|
69
|
+
ci: CiTriageResult;
|
|
70
|
+
review: ReviewTriageResult;
|
|
71
|
+
guard: GuardResult;
|
|
72
|
+
watermark: BabysitWatermark | null;
|
|
73
|
+
now?: Date;
|
|
74
|
+
}
|
|
75
|
+
export interface BabysitPrReport {
|
|
76
|
+
pr: string;
|
|
77
|
+
owner: string;
|
|
78
|
+
repo: string;
|
|
79
|
+
number: number;
|
|
80
|
+
title: string;
|
|
81
|
+
author: string;
|
|
82
|
+
headSha: string;
|
|
83
|
+
headChanged: boolean;
|
|
84
|
+
/** Set when the PR is no longer open: "merged" or "closed". No actions; the PR drops to the quiet list. */
|
|
85
|
+
resolution?: "merged" | "closed";
|
|
86
|
+
conflicts: boolean;
|
|
87
|
+
mergeableState: string | null;
|
|
88
|
+
ciVerdict: CiTriageVerdict;
|
|
89
|
+
yoursFailing: string[];
|
|
90
|
+
pendingChecks: string[];
|
|
91
|
+
stuckChecks: string[];
|
|
92
|
+
newLikelyReal: ClassifiedFinding[];
|
|
93
|
+
newNeedsDecision: ClassifiedFinding[];
|
|
94
|
+
newGuardFlags: string[];
|
|
95
|
+
guardSummary: string;
|
|
96
|
+
actions: BabysitAction[];
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Build the per-PR report. Pure: everything network-shaped comes in on
|
|
100
|
+
* the input, so fixtures can prove the change detection and ordering.
|
|
101
|
+
*/
|
|
102
|
+
export declare function buildPrReport(input: BabysitPrInput): BabysitPrReport;
|
|
103
|
+
/** The watermark to store after a report, so the next run diffs against it. */
|
|
104
|
+
export declare function watermarkFromReport(report: BabysitPrReport, review: ReviewTriageResult, guard: GuardResult, now: Date): BabysitWatermark;
|
|
105
|
+
export interface BabysitRunOptions {
|
|
106
|
+
/** Comma-joined or array PR URLs. */
|
|
107
|
+
prs?: string[];
|
|
108
|
+
/** Discover this author's open PRs across these repos (search API). */
|
|
109
|
+
mine?: boolean;
|
|
110
|
+
repos?: string[];
|
|
111
|
+
author?: string;
|
|
112
|
+
statePath?: string;
|
|
113
|
+
deps?: BabysitDeps;
|
|
114
|
+
now?: Date;
|
|
115
|
+
}
|
|
116
|
+
export interface BabysitRun {
|
|
117
|
+
reports: BabysitPrReport[];
|
|
118
|
+
needsYouNow: BabysitAction[];
|
|
119
|
+
waitingOnThem: BabysitAction[];
|
|
120
|
+
quiet: string[];
|
|
121
|
+
firstRun: boolean;
|
|
122
|
+
prsChecked: number;
|
|
123
|
+
markdown: string;
|
|
124
|
+
json: Record<string, unknown>;
|
|
125
|
+
}
|
|
126
|
+
/**
|
|
127
|
+
* The full babysit run: discover PRs (or take the list), fetch each PR's
|
|
128
|
+
* signals, diff against watermarks, write the new watermarks, render.
|
|
129
|
+
* Exit-0-friendly: per-PR failures degrade to an action item, never a
|
|
130
|
+
* thrown error (usage errors are the caller's problem).
|
|
131
|
+
*/
|
|
132
|
+
export declare function babysit(opts: BabysitRunOptions): Promise<BabysitRun>;
|
package/dist/babysit.js
ADDED
|
@@ -0,0 +1,439 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PR Babysitter. Rene has dozens of open PRs and no time to watch them;
|
|
3
|
+
* this is the cron-friendly "what needs me right now" report.
|
|
4
|
+
*
|
|
5
|
+
* For each PR it runs the existing engines (CI triage, review triage,
|
|
6
|
+
* guard), diffs the result against a stored watermark (~/.greenlight/
|
|
7
|
+
* babysit.json or --state), and returns ONE prioritized action list:
|
|
8
|
+
*
|
|
9
|
+
* needs you now — new likely-real review findings, CI newly failing on
|
|
10
|
+
* your code, merge conflicts, new guard flags, checks stuck >2h
|
|
11
|
+
* waiting on them — checks still running, CI green with no feedback yet
|
|
12
|
+
* quiet — nothing needs you
|
|
13
|
+
*
|
|
14
|
+
* The first run (no watermark) reports the full picture and says so.
|
|
15
|
+
* Exit code 0 always unless usage is wrong; --fail-on-action gives exit 3
|
|
16
|
+
* when "needs you now" is non-empty, for cron alerting.
|
|
17
|
+
*/
|
|
18
|
+
import { apiGet, parsePullUrl } from "./github.js";
|
|
19
|
+
import { triagePr } from "./ci-triage.js";
|
|
20
|
+
import { triageReview as defaultTriageReview } from "./review-triage.js";
|
|
21
|
+
import { guardPr } from "./guard.js";
|
|
22
|
+
import { mkdirSync, readFileSync, writeFileSync } from "node:fs";
|
|
23
|
+
import { homedir } from "node:os";
|
|
24
|
+
import { dirname, join } from "node:path";
|
|
25
|
+
export const BABYSIT_VERSION = "0.6.0";
|
|
26
|
+
/** Checks pending longer than this are reported as stuck, not just running. */
|
|
27
|
+
export const STUCK_CHECK_MINUTES = 120;
|
|
28
|
+
/** Cap on discovered PRs per --mine run; the summary always states the cap. */
|
|
29
|
+
export const MINE_DISCOVERY_CAP = 100;
|
|
30
|
+
async function defaultFetchPr(owner, repo, number) {
|
|
31
|
+
const p = (await apiGet(`/repos/${owner}/${repo}/pulls/${number}`));
|
|
32
|
+
return {
|
|
33
|
+
owner,
|
|
34
|
+
repo,
|
|
35
|
+
number,
|
|
36
|
+
title: String(p.title ?? ""),
|
|
37
|
+
author: String(p.user?.login ?? "unknown"),
|
|
38
|
+
state: String(p.state ?? "open"),
|
|
39
|
+
headSha: String(p.head?.sha ?? ""),
|
|
40
|
+
baseRef: String(p.base?.ref ?? ""),
|
|
41
|
+
mergeable: typeof p.mergeable === "boolean" ? p.mergeable : null,
|
|
42
|
+
mergeableState: typeof p.mergeable_state === "string" ? p.mergeable_state : null,
|
|
43
|
+
url: String(p.html_url ?? `https://github.com/${owner}/${repo}/pull/${number}`),
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
async function defaultFetchCheckRuns(owner, repo, headSha) {
|
|
47
|
+
if (!headSha)
|
|
48
|
+
return [];
|
|
49
|
+
const out = [];
|
|
50
|
+
for (let page = 1; page <= 3; page++) {
|
|
51
|
+
const data = (await apiGet(`/repos/${owner}/${repo}/commits/${headSha}/check-runs?per_page=100&page=${page}`));
|
|
52
|
+
const runs = data?.check_runs ?? [];
|
|
53
|
+
for (const r of runs) {
|
|
54
|
+
out.push({
|
|
55
|
+
name: String(r.name ?? "unknown"),
|
|
56
|
+
status: String(r.status ?? ""),
|
|
57
|
+
conclusion: typeof r.conclusion === "string" ? r.conclusion : null,
|
|
58
|
+
startedAt: typeof r.started_at === "string" ? r.started_at : null,
|
|
59
|
+
detailsUrl: typeof r.details_url === "string" ? r.details_url : undefined,
|
|
60
|
+
});
|
|
61
|
+
}
|
|
62
|
+
if (runs.length < 100)
|
|
63
|
+
break;
|
|
64
|
+
}
|
|
65
|
+
return out;
|
|
66
|
+
}
|
|
67
|
+
async function defaultDiscoverPrs(author, repos) {
|
|
68
|
+
const urls = [];
|
|
69
|
+
for (const ref of repos) {
|
|
70
|
+
const m = /^([^/]+)\/([^/]+)$/.exec(ref.trim());
|
|
71
|
+
if (!m)
|
|
72
|
+
continue;
|
|
73
|
+
for (let page = 1; page <= 2 && urls.length < MINE_DISCOVERY_CAP; page++) {
|
|
74
|
+
const q = encodeURIComponent(`repo:${m[1]}/${m[2]} is:pr is:open author:${author}`);
|
|
75
|
+
const data = (await apiGet(`/search/issues?q=${q}&per_page=100&page=${page}`));
|
|
76
|
+
for (const item of data?.items ?? []) {
|
|
77
|
+
if (typeof item.html_url === "string" && urls.length < MINE_DISCOVERY_CAP)
|
|
78
|
+
urls.push(item.html_url);
|
|
79
|
+
}
|
|
80
|
+
if ((data?.items ?? []).length < 100)
|
|
81
|
+
break;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
return urls;
|
|
85
|
+
}
|
|
86
|
+
export function defaultStatePath() {
|
|
87
|
+
return join(homedir(), ".greenlight", "babysit.json");
|
|
88
|
+
}
|
|
89
|
+
export function loadState(path) {
|
|
90
|
+
try {
|
|
91
|
+
const parsed = JSON.parse(readFileSync(path, "utf8"));
|
|
92
|
+
if (parsed && typeof parsed === "object" && parsed.watermarks && typeof parsed.watermarks === "object") {
|
|
93
|
+
return { version: 1, watermarks: parsed.watermarks };
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
catch {
|
|
97
|
+
// Missing or broken state: start fresh. The run says so.
|
|
98
|
+
}
|
|
99
|
+
return { version: 1, watermarks: {} };
|
|
100
|
+
}
|
|
101
|
+
export function saveState(path, state) {
|
|
102
|
+
mkdirSync(dirname(path), { recursive: true });
|
|
103
|
+
writeFileSync(path, JSON.stringify(state, null, 2) + "\n", "utf8");
|
|
104
|
+
}
|
|
105
|
+
export function watermarkKey(owner, repo, number) {
|
|
106
|
+
return `${owner}/${repo}#${number}`;
|
|
107
|
+
}
|
|
108
|
+
/** Deterministic identity for a review finding, for "new since last run". */
|
|
109
|
+
export function reviewFindingId(f) {
|
|
110
|
+
return [f.author, f.path ?? "", String(f.line ?? ""), f.summary].join("|");
|
|
111
|
+
}
|
|
112
|
+
/** Deterministic identity for a guard finding, for "new since last run". */
|
|
113
|
+
export function guardFlagId(check, title) {
|
|
114
|
+
return `${check}|${title}`;
|
|
115
|
+
}
|
|
116
|
+
function minutesPending(run, now) {
|
|
117
|
+
if (!run.startedAt)
|
|
118
|
+
return null;
|
|
119
|
+
const t = new Date(run.startedAt).getTime();
|
|
120
|
+
if (Number.isNaN(t))
|
|
121
|
+
return null;
|
|
122
|
+
return (now.getTime() - t) / 60000;
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Build the per-PR report. Pure: everything network-shaped comes in on
|
|
126
|
+
* the input, so fixtures can prove the change detection and ordering.
|
|
127
|
+
*/
|
|
128
|
+
export function buildPrReport(input) {
|
|
129
|
+
const { prUrl, pr, checkRuns, ci, review, guard, watermark } = input;
|
|
130
|
+
const now = input.now ?? new Date();
|
|
131
|
+
const actions = [];
|
|
132
|
+
const headChanged = watermark !== null && watermark.headSha !== "" && pr.headSha !== "" && watermark.headSha !== pr.headSha;
|
|
133
|
+
// CI: which failing checks are actually yours (or lean yours).
|
|
134
|
+
const yoursFailing = [];
|
|
135
|
+
for (const c of ci.checks) {
|
|
136
|
+
if (c.class === "likely-yours")
|
|
137
|
+
yoursFailing.push(c.name);
|
|
138
|
+
else if (c.class === "indeterminate" && c.lean === "yours")
|
|
139
|
+
yoursFailing.push(`${c.name} (lean: yours)`);
|
|
140
|
+
}
|
|
141
|
+
// Pending check runs, with the stuck (>2h) split.
|
|
142
|
+
const pending = [];
|
|
143
|
+
const stuck = [];
|
|
144
|
+
for (const r of checkRuns) {
|
|
145
|
+
if (r.status === "completed")
|
|
146
|
+
continue;
|
|
147
|
+
if (r.conclusion && !["neutral", "skipped"].includes(r.conclusion))
|
|
148
|
+
continue;
|
|
149
|
+
const age = minutesPending(r, now);
|
|
150
|
+
if (age !== null && age > STUCK_CHECK_MINUTES)
|
|
151
|
+
stuck.push(`${r.name} (${Math.round(age)}m)`);
|
|
152
|
+
else
|
|
153
|
+
pending.push(r.name);
|
|
154
|
+
}
|
|
155
|
+
// New review findings since the watermark.
|
|
156
|
+
const seenReviews = new Set(watermark?.seenReviewIds ?? []);
|
|
157
|
+
const actionable = review.findings.filter((f) => f.class === "likely-real" || f.class === "needs-decision");
|
|
158
|
+
const newFindings = actionable.filter((f) => !seenReviews.has(reviewFindingId(f)));
|
|
159
|
+
const newLikelyReal = newFindings.filter((f) => f.class === "likely-real");
|
|
160
|
+
const newNeedsDecision = newFindings.filter((f) => f.class === "needs-decision");
|
|
161
|
+
// New guard flags since the watermark.
|
|
162
|
+
const seenFlags = new Set(watermark?.seenGuardFlags ?? []);
|
|
163
|
+
const newGuardFlags = guard.findings
|
|
164
|
+
.filter((f) => f.severity === "flag" && !seenFlags.has(guardFlagId(f.check, f.title)))
|
|
165
|
+
.map((f) => f.title);
|
|
166
|
+
const conflicts = pr.mergeable === false || pr.mergeableState === "dirty";
|
|
167
|
+
const tag = `${pr.owner}/${pr.repo}#${pr.number}`;
|
|
168
|
+
const add = (urgency, text, next) => {
|
|
169
|
+
actions.push({ urgency, pr: tag, text, next });
|
|
170
|
+
};
|
|
171
|
+
// ---- needs you now ----
|
|
172
|
+
if (conflicts) {
|
|
173
|
+
add("now", `Merge conflicts with ${pr.baseRef}`, "Rebase onto the base branch, resolve the conflicts, and push.");
|
|
174
|
+
}
|
|
175
|
+
if (yoursFailing.length > 0) {
|
|
176
|
+
add("now", `CI failing on your code: ${yoursFailing.join(", ")}`, "Fix the failures and push; the triage evidence names the base comparison for each check.");
|
|
177
|
+
}
|
|
178
|
+
if (newLikelyReal.length > 0) {
|
|
179
|
+
add("now", `${newLikelyReal.length} new review finding${newLikelyReal.length === 1 ? "" : "s"} that look real: ${newLikelyReal
|
|
180
|
+
.slice(0, 3)
|
|
181
|
+
.map((f) => f.summary)
|
|
182
|
+
.join("; ")}${newLikelyReal.length > 3 ? ` (+${newLikelyReal.length - 3} more)` : ""}`, "Work through them and adapt the drafted replies; review triage has the reply text.");
|
|
183
|
+
}
|
|
184
|
+
if (newNeedsDecision.length > 0) {
|
|
185
|
+
add("now", `${newNeedsDecision.length} new review finding${newNeedsDecision.length === 1 ? "" : "s"} need your call: ${newNeedsDecision
|
|
186
|
+
.slice(0, 2)
|
|
187
|
+
.map((f) => f.summary)
|
|
188
|
+
.join("; ")}`, "Decide each one (accept or push back) and reply; the drafts are in the review triage.");
|
|
189
|
+
}
|
|
190
|
+
if (newGuardFlags.length > 0) {
|
|
191
|
+
add("now", `Guard flagged ${newGuardFlags.length} new thing${newGuardFlags.length === 1 ? "" : "s"}: ${newGuardFlags.slice(0, 3).join("; ")}`, "Read the guard comment; competing-fix and claim flags usually mean the issue is being worked by someone else.");
|
|
192
|
+
}
|
|
193
|
+
if (stuck.length > 0) {
|
|
194
|
+
add("now", `Checks stuck for over 2 hours: ${stuck.join(", ")}`, "The runs look wedged; re-run the failed/stuck checks or close and reopen the PR to retrigger.");
|
|
195
|
+
}
|
|
196
|
+
// ---- waiting on them ----
|
|
197
|
+
if (pending.length > 0) {
|
|
198
|
+
add("waiting", `Checks still running: ${pending.slice(0, 5).join(", ")}${pending.length > 5 ? ` (+${pending.length - 5} more)` : ""}`, "Nothing to do yet; this report updates when they finish.");
|
|
199
|
+
}
|
|
200
|
+
const externalBlocked = ci.checks.some((c) => c.class === "external-blocker");
|
|
201
|
+
if (externalBlocked) {
|
|
202
|
+
add("waiting", "CI blocked by the repo's own infrastructure (deploy/auth), not your code", "Nothing to fix; mention it to the maintainer if it persists.");
|
|
203
|
+
}
|
|
204
|
+
const calm = actions.length === 0 &&
|
|
205
|
+
ci.verdict === "NO FAILURES" &&
|
|
206
|
+
review.verdict === "NO FINDINGS" &&
|
|
207
|
+
!conflicts &&
|
|
208
|
+
pending.length === 0 &&
|
|
209
|
+
stuck.length === 0;
|
|
210
|
+
if (calm) {
|
|
211
|
+
add("waiting", "Checks green, no review feedback yet", "Nothing owed. Ping the maintainer after a few days if it stays quiet.");
|
|
212
|
+
}
|
|
213
|
+
return {
|
|
214
|
+
pr: tag,
|
|
215
|
+
owner: pr.owner,
|
|
216
|
+
repo: pr.repo,
|
|
217
|
+
number: pr.number,
|
|
218
|
+
title: pr.title,
|
|
219
|
+
author: pr.author,
|
|
220
|
+
headSha: pr.headSha,
|
|
221
|
+
headChanged,
|
|
222
|
+
conflicts,
|
|
223
|
+
mergeableState: pr.mergeableState,
|
|
224
|
+
ciVerdict: ci.verdict,
|
|
225
|
+
yoursFailing,
|
|
226
|
+
pendingChecks: pending,
|
|
227
|
+
stuckChecks: stuck,
|
|
228
|
+
newLikelyReal,
|
|
229
|
+
newNeedsDecision,
|
|
230
|
+
newGuardFlags,
|
|
231
|
+
guardSummary: guard.summary,
|
|
232
|
+
actions,
|
|
233
|
+
};
|
|
234
|
+
}
|
|
235
|
+
/** The watermark to store after a report, so the next run diffs against it. */
|
|
236
|
+
export function watermarkFromReport(report, review, guard, now) {
|
|
237
|
+
return {
|
|
238
|
+
headSha: report.headSha,
|
|
239
|
+
seenReviewIds: review.findings.map((f) => reviewFindingId(f)),
|
|
240
|
+
seenGuardFlags: guard.findings.filter((f) => f.severity === "flag").map((f) => guardFlagId(f.check, f.title)),
|
|
241
|
+
lastCiVerdict: report.ciVerdict,
|
|
242
|
+
lastMergeableState: report.mergeableState,
|
|
243
|
+
checkedAt: now.toISOString(),
|
|
244
|
+
};
|
|
245
|
+
}
|
|
246
|
+
function renderMarkdown(reports, run) {
|
|
247
|
+
const lines = [];
|
|
248
|
+
lines.push(`**PR babysitter: ${run.needsYouNow.length} need you now, ${run.waitingOnThem.length} waiting, ${run.quiet.length} quiet** (${run.prsChecked} PRs checked)`);
|
|
249
|
+
if (run.firstRun)
|
|
250
|
+
lines.push("_First run: no watermarks yet, so this is the full picture. Reruns report what changed since the last check._");
|
|
251
|
+
lines.push("");
|
|
252
|
+
const section = (title, items) => {
|
|
253
|
+
lines.push(`## ${title}`);
|
|
254
|
+
if (items.length === 0) {
|
|
255
|
+
lines.push("_None._");
|
|
256
|
+
}
|
|
257
|
+
else {
|
|
258
|
+
for (const a of items) {
|
|
259
|
+
lines.push(`- **${a.pr}** — ${a.text}`);
|
|
260
|
+
lines.push(` Next: ${a.next}`);
|
|
261
|
+
}
|
|
262
|
+
}
|
|
263
|
+
lines.push("");
|
|
264
|
+
};
|
|
265
|
+
section("Needs you now", run.needsYouNow);
|
|
266
|
+
section("Waiting on them", run.waitingOnThem);
|
|
267
|
+
lines.push("## Quiet");
|
|
268
|
+
if (run.quiet.length === 0)
|
|
269
|
+
lines.push("_None._");
|
|
270
|
+
else
|
|
271
|
+
for (const q of run.quiet)
|
|
272
|
+
lines.push(`- ${q}`);
|
|
273
|
+
lines.push("");
|
|
274
|
+
for (const r of reports) {
|
|
275
|
+
if (r.headChanged)
|
|
276
|
+
lines.push(`_${r.pr}: new head ${r.headSha.slice(0, 7)} since the last check._`);
|
|
277
|
+
}
|
|
278
|
+
lines.push(`_Checked with Greenlight babysit v${BABYSIT_VERSION}._`);
|
|
279
|
+
return lines.join("\n");
|
|
280
|
+
}
|
|
281
|
+
/**
|
|
282
|
+
* The full babysit run: discover PRs (or take the list), fetch each PR's
|
|
283
|
+
* signals, diff against watermarks, write the new watermarks, render.
|
|
284
|
+
* Exit-0-friendly: per-PR failures degrade to an action item, never a
|
|
285
|
+
* thrown error (usage errors are the caller's problem).
|
|
286
|
+
*/
|
|
287
|
+
export async function babysit(opts) {
|
|
288
|
+
const deps = opts.deps ?? {};
|
|
289
|
+
const now = opts.now ?? new Date();
|
|
290
|
+
const statePath = opts.statePath ?? defaultStatePath();
|
|
291
|
+
const state = loadState(statePath);
|
|
292
|
+
const firstRun = Object.keys(state.watermarks).length === 0;
|
|
293
|
+
let prUrls = [...(opts.prs ?? [])];
|
|
294
|
+
if (opts.mine) {
|
|
295
|
+
const author = opts.author ?? "CloudCorpRecords";
|
|
296
|
+
const repos = opts.repos ?? [];
|
|
297
|
+
const discover = deps.discoverPrs ?? defaultDiscoverPrs;
|
|
298
|
+
try {
|
|
299
|
+
const found = await discover(author, repos);
|
|
300
|
+
prUrls = found.slice(0, MINE_DISCOVERY_CAP);
|
|
301
|
+
}
|
|
302
|
+
catch (err) {
|
|
303
|
+
prUrls = [];
|
|
304
|
+
// Discovery failing degrades to an empty run with the reason stated.
|
|
305
|
+
const run = {
|
|
306
|
+
reports: [],
|
|
307
|
+
needsYouNow: [],
|
|
308
|
+
waitingOnThem: [],
|
|
309
|
+
quiet: [],
|
|
310
|
+
firstRun,
|
|
311
|
+
prsChecked: 0,
|
|
312
|
+
markdown: `**PR babysitter: could not discover PRs** — ${err instanceof Error ? err.message : String(err)}`,
|
|
313
|
+
json: { error: err instanceof Error ? err.message : String(err) },
|
|
314
|
+
};
|
|
315
|
+
return run;
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
const reports = [];
|
|
319
|
+
const fetchPr = deps.fetchPr ?? defaultFetchPr;
|
|
320
|
+
const fetchCheckRuns = deps.fetchCheckRuns ?? defaultFetchCheckRuns;
|
|
321
|
+
const triageCi = deps.triageCi ?? triagePr;
|
|
322
|
+
const triageReview = deps.triageReview ?? defaultTriageReview;
|
|
323
|
+
const guard = deps.guard ?? guardPr;
|
|
324
|
+
for (const prUrl of prUrls) {
|
|
325
|
+
try {
|
|
326
|
+
const { owner, repo, number } = parsePullUrl(prUrl);
|
|
327
|
+
const pr = await fetchPr(owner, repo, number);
|
|
328
|
+
if (pr.state !== "open") {
|
|
329
|
+
// A closed or merged PR is done being babysat: it lands on the
|
|
330
|
+
// quiet list with its resolution, and its watermark is retired so a
|
|
331
|
+
// reopen shows up as a fresh full picture.
|
|
332
|
+
const resolution = pr.state === "merged" ? "merged" : "closed";
|
|
333
|
+
const tag = watermarkKey(owner, repo, number);
|
|
334
|
+
reports.push({
|
|
335
|
+
pr: tag, owner, repo, number,
|
|
336
|
+
title: pr.title, author: pr.author,
|
|
337
|
+
headSha: pr.headSha, headChanged: false,
|
|
338
|
+
resolution,
|
|
339
|
+
conflicts: false, mergeableState: null,
|
|
340
|
+
ciVerdict: "INDETERMINATE",
|
|
341
|
+
yoursFailing: [], pendingChecks: [], stuckChecks: [],
|
|
342
|
+
newLikelyReal: [], newNeedsDecision: [], newGuardFlags: [],
|
|
343
|
+
guardSummary: "",
|
|
344
|
+
actions: [],
|
|
345
|
+
});
|
|
346
|
+
delete state.watermarks[tag];
|
|
347
|
+
continue;
|
|
348
|
+
}
|
|
349
|
+
const [checkRuns, ci, review, guardResult] = await Promise.all([
|
|
350
|
+
fetchCheckRuns(owner, repo, pr.headSha).catch(() => []),
|
|
351
|
+
triageCi(prUrl).catch(() => null),
|
|
352
|
+
triageReview(prUrl).catch(() => null),
|
|
353
|
+
guard(prUrl).catch(() => null),
|
|
354
|
+
]);
|
|
355
|
+
if (!ci || !review || !guardResult) {
|
|
356
|
+
reports.push({
|
|
357
|
+
pr: watermarkKey(owner, repo, number),
|
|
358
|
+
owner, repo, number,
|
|
359
|
+
title: pr.title, author: pr.author,
|
|
360
|
+
headSha: pr.headSha, headChanged: false,
|
|
361
|
+
conflicts: false, mergeableState: pr.mergeableState,
|
|
362
|
+
ciVerdict: "INDETERMINATE",
|
|
363
|
+
yoursFailing: [], pendingChecks: [], stuckChecks: [],
|
|
364
|
+
newLikelyReal: [], newNeedsDecision: [], newGuardFlags: [],
|
|
365
|
+
guardSummary: "",
|
|
366
|
+
actions: [{
|
|
367
|
+
urgency: "waiting",
|
|
368
|
+
pr: watermarkKey(owner, repo, number),
|
|
369
|
+
text: "Could not read this PR's signals this run (API hiccup)",
|
|
370
|
+
next: "Rerun the babysitter; this is a transient gap, not a finding.",
|
|
371
|
+
}],
|
|
372
|
+
});
|
|
373
|
+
continue;
|
|
374
|
+
}
|
|
375
|
+
const key = watermarkKey(owner, repo, number);
|
|
376
|
+
const report = buildPrReport({
|
|
377
|
+
prUrl,
|
|
378
|
+
pr,
|
|
379
|
+
checkRuns,
|
|
380
|
+
ci,
|
|
381
|
+
review,
|
|
382
|
+
guard: guardResult,
|
|
383
|
+
watermark: state.watermarks[key] ?? null,
|
|
384
|
+
now,
|
|
385
|
+
});
|
|
386
|
+
reports.push(report);
|
|
387
|
+
state.watermarks[key] = watermarkFromReport(report, review, guardResult, now);
|
|
388
|
+
}
|
|
389
|
+
catch (err) {
|
|
390
|
+
const tag = prUrl;
|
|
391
|
+
reports.push({
|
|
392
|
+
pr: tag, owner: "", repo: "", number: 0,
|
|
393
|
+
title: "", author: "",
|
|
394
|
+
headSha: "", headChanged: false,
|
|
395
|
+
conflicts: false, mergeableState: null,
|
|
396
|
+
ciVerdict: "INDETERMINATE",
|
|
397
|
+
yoursFailing: [], pendingChecks: [], stuckChecks: [],
|
|
398
|
+
newLikelyReal: [], newNeedsDecision: [], newGuardFlags: [],
|
|
399
|
+
guardSummary: "",
|
|
400
|
+
actions: [{
|
|
401
|
+
urgency: "waiting",
|
|
402
|
+
pr: tag,
|
|
403
|
+
text: `Could not check this PR: ${err instanceof Error ? err.message : String(err)}`,
|
|
404
|
+
next: "Check the URL and rerun.",
|
|
405
|
+
}],
|
|
406
|
+
});
|
|
407
|
+
}
|
|
408
|
+
}
|
|
409
|
+
saveState(statePath, state);
|
|
410
|
+
const needsYouNow = reports.flatMap((r) => r.actions.filter((a) => a.urgency === "now"));
|
|
411
|
+
const waitingOnThem = reports.flatMap((r) => r.actions.filter((a) => a.urgency === "waiting"));
|
|
412
|
+
const withActions = new Set([...needsYouNow, ...waitingOnThem].map((a) => a.pr));
|
|
413
|
+
const quiet = reports
|
|
414
|
+
.filter((r) => !withActions.has(r.pr))
|
|
415
|
+
.map((r) => r.resolution
|
|
416
|
+
? `${r.pr} "${r.title}" — ${r.resolution} since the last check`
|
|
417
|
+
: `${r.pr} "${r.title}" — nothing needs you`);
|
|
418
|
+
const partial = {
|
|
419
|
+
reports, needsYouNow, waitingOnThem, quiet, firstRun, prsChecked: reports.length,
|
|
420
|
+
};
|
|
421
|
+
const markdown = renderMarkdown(reports, partial);
|
|
422
|
+
const json = {
|
|
423
|
+
prsChecked: partial.prsChecked,
|
|
424
|
+
firstRun,
|
|
425
|
+
needsYouNow: needsYouNow.map((a) => ({ pr: a.pr, text: a.text, next: a.next })),
|
|
426
|
+
waitingOnThem: waitingOnThem.map((a) => ({ pr: a.pr, text: a.text, next: a.next })),
|
|
427
|
+
quiet,
|
|
428
|
+
reports: reports.map((r) => ({
|
|
429
|
+
pr: r.pr, title: r.title, headSha: r.headSha, headChanged: r.headChanged,
|
|
430
|
+
conflicts: r.conflicts, ciVerdict: r.ciVerdict,
|
|
431
|
+
yoursFailing: r.yoursFailing, pendingChecks: r.pendingChecks, stuckChecks: r.stuckChecks,
|
|
432
|
+
newLikelyReal: r.newLikelyReal.map((f) => f.summary),
|
|
433
|
+
newNeedsDecision: r.newNeedsDecision.map((f) => f.summary),
|
|
434
|
+
newGuardFlags: r.newGuardFlags, guardSummary: r.guardSummary,
|
|
435
|
+
})),
|
|
436
|
+
};
|
|
437
|
+
return { ...partial, markdown, json };
|
|
438
|
+
}
|
|
439
|
+
//# sourceMappingURL=babysit.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"babysit.js","sourceRoot":"","sources":["../src/babysit.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;GAgBG;AACH,OAAO,EAAE,MAAM,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,EAAE,QAAQ,EAA6C,MAAM,gBAAgB,CAAC;AACrF,OAAO,EAAE,YAAY,IAAI,mBAAmB,EAAmD,MAAM,oBAAoB,CAAC;AAC1H,OAAO,EAAE,OAAO,EAAoB,MAAM,YAAY,CAAC;AACvD,OAAO,EAAc,SAAS,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7E,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAC;AAClC,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,WAAW,CAAC;AAE1C,MAAM,CAAC,MAAM,eAAe,GAAG,OAAO,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,mBAAmB,GAAG,GAAG,CAAC;AAEvC,+EAA+E;AAC/E,MAAM,CAAC,MAAM,kBAAkB,GAAG,GAAG,CAAC;AA0DtC,KAAK,UAAU,cAAc,CAAC,KAAa,EAAE,IAAY,EAAE,MAAc;IACvE,MAAM,CAAC,GAAG,CAAC,MAAM,MAAM,CAAC,UAAU,KAAK,IAAI,IAAI,UAAU,MAAM,EAAE,CAAC,CAAgB,CAAC;IACnF,OAAO;QACL,KAAK;QACL,IAAI;QACJ,MAAM;QACN,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC;QAC5B,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,IAAI,SAAS,CAAC;QAC1C,KAAK,EAAE,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,MAAM,CAAC;QAChC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QAClC,OAAO,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,GAAG,IAAI,EAAE,CAAC;QAClC,SAAS,EAAE,OAAO,CAAC,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI;QAChE,cAAc,EAAE,OAAO,CAAC,CAAC,eAAe,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,IAAI;QAChF,GAAG,EAAE,MAAM,CAAC,CAAC,CAAC,QAAQ,IAAI,sBAAsB,KAAK,IAAI,IAAI,SAAS,MAAM,EAAE,CAAC;KAChF,CAAC;AACJ,CAAC;AAED,KAAK,UAAU,qBAAqB,CAClC,KAAa,EACb,IAAY,EACZ,OAAe;IAEf,IAAI,CAAC,OAAO;QAAE,OAAO,EAAE,CAAC;IACxB,MAAM,GAAG,GAAsB,EAAE,CAAC;IAClC,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,EAAE,IAAI,EAAE,EAAE,CAAC;QACrC,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CACxB,UAAU,KAAK,IAAI,IAAI,YAAY,OAAO,iCAAiC,IAAI,EAAE,CAClF,CAAuC,CAAC;QACzC,MAAM,IAAI,GAAG,IAAI,EAAE,UAAU,IAAI,EAAE,CAAC;QACpC,KAAK,MAAM,CAAC,IAAI,IAAI,EAAE,CAAC;YACrB,GAAG,CAAC,IAAI,CAAC;gBACP,IAAI,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,SAAS,CAAC;gBACjC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC;gBAC9B,UAAU,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;gBAClE,SAAS,EAAE,OAAO,CAAC,CAAC,UAAU,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,IAAI;gBACjE,UAAU,EAAE,OAAO,CAAC,CAAC,WAAW,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,CAAC,SAAS;aAC1E,CAAC,CAAC;QACL,CAAC;QACD,IAAI,IAAI,CAAC,MAAM,GAAG,GAAG;YAAE,MAAM;IAC/B,CAAC;IACD,OAAO,GAAG,CAAC;AACb,CAAC;AAED,KAAK,UAAU,kBAAkB,CAAC,MAAc,EAAE,KAAe;IAC/D,MAAM,IAAI,GAAa,EAAE,CAAC;IAC1B,KAAK,MAAM,GAAG,IAAI,KAAK,EAAE,CAAC;QACxB,MAAM,CAAC,GAAG,oBAAoB,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,EAAE,CAAC,CAAC;QAChD,IAAI,CAAC,CAAC;YAAE,SAAS;QACjB,KAAK,IAAI,IAAI,GAAG,CAAC,EAAE,IAAI,IAAI,CAAC,IAAI,IAAI,CAAC,MAAM,GAAG,kBAAkB,EAAE,IAAI,EAAE,EAAE,CAAC;YACzE,MAAM,CAAC,GAAG,kBAAkB,CAAC,QAAQ,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,yBAAyB,MAAM,EAAE,CAAC,CAAC;YACpF,MAAM,IAAI,GAAG,CAAC,MAAM,MAAM,CAAC,oBAAoB,CAAC,sBAAsB,IAAI,EAAE,CAAC,CAAkB,CAAC;YAChG,KAAK,MAAM,IAAI,IAAI,IAAI,EAAE,KAAK,IAAI,EAAE,EAAE,CAAC;gBACrC,IAAI,OAAO,IAAI,CAAC,QAAQ,KAAK,QAAQ,IAAI,IAAI,CAAC,MAAM,GAAG,kBAAkB;oBAAE,IAAI,CAAC,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC;YACtG,CAAC;YACD,IAAI,CAAC,IAAI,EAAE,KAAK,IAAI,EAAE,CAAC,CAAC,MAAM,GAAG,GAAG;gBAAE,MAAM;QAC9C,CAAC;IACH,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAoBD,MAAM,UAAU,gBAAgB;IAC9B,OAAO,IAAI,CAAC,OAAO,EAAE,EAAE,aAAa,EAAE,cAAc,CAAC,CAAC;AACxD,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY;IACpC,IAAI,CAAC;QACH,MAAM,MAAM,GAAG,IAAI,CAAC,KAAK,CAAC,YAAY,CAAC,IAAI,EAAE,MAAM,CAAC,CAA8B,CAAC;QACnF,IAAI,MAAM,IAAI,OAAO,MAAM,KAAK,QAAQ,IAAI,MAAM,CAAC,UAAU,IAAI,OAAO,MAAM,CAAC,UAAU,KAAK,QAAQ,EAAE,CAAC;YACvG,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,MAAM,CAAC,UAA8C,EAAE,CAAC;QAC3F,CAAC;IACH,CAAC;IAAC,MAAM,CAAC;QACP,yDAAyD;IAC3D,CAAC;IACD,OAAO,EAAE,OAAO,EAAE,CAAC,EAAE,UAAU,EAAE,EAAE,EAAE,CAAC;AACxC,CAAC;AAED,MAAM,UAAU,SAAS,CAAC,IAAY,EAAE,KAAuB;IAC7D,SAAS,CAAC,OAAO,CAAC,IAAI,CAAC,EAAE,EAAE,SAAS,EAAE,IAAI,EAAE,CAAC,CAAC;IAC9C,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,IAAI,EAAE,CAAC,CAAC,GAAG,IAAI,EAAE,MAAM,CAAC,CAAC;AACrE,CAAC;AAED,MAAM,UAAU,YAAY,CAAC,KAAa,EAAE,IAAY,EAAE,MAAc;IACtE,OAAO,GAAG,KAAK,IAAI,IAAI,IAAI,MAAM,EAAE,CAAC;AACtC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,eAAe,CAAC,CAAkE;IAChG,OAAO,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,IAAI,EAAE,EAAE,MAAM,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;AAC7E,CAAC;AAED,4EAA4E;AAC5E,MAAM,UAAU,WAAW,CAAC,KAAa,EAAE,KAAa;IACtD,OAAO,GAAG,KAAK,IAAI,KAAK,EAAE,CAAC;AAC7B,CAAC;AAkDD,SAAS,cAAc,CAAC,GAAoB,EAAE,GAAS;IACrD,IAAI,CAAC,GAAG,CAAC,SAAS;QAAE,OAAO,IAAI,CAAC;IAChC,MAAM,CAAC,GAAG,IAAI,IAAI,CAAC,GAAG,CAAC,SAAS,CAAC,CAAC,OAAO,EAAE,CAAC;IAC5C,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC;QAAE,OAAO,IAAI,CAAC;IACjC,OAAO,CAAC,GAAG,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,GAAG,KAAK,CAAC;AACrC,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,aAAa,CAAC,KAAqB;IACjD,MAAM,EAAE,KAAK,EAAE,EAAE,EAAE,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,KAAK,EAAE,SAAS,EAAE,GAAG,KAAK,CAAC;IACrE,MAAM,GAAG,GAAG,KAAK,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACpC,MAAM,OAAO,GAAoB,EAAE,CAAC;IAEpC,MAAM,WAAW,GAAG,SAAS,KAAK,IAAI,IAAI,SAAS,CAAC,OAAO,KAAK,EAAE,IAAI,EAAE,CAAC,OAAO,KAAK,EAAE,IAAI,SAAS,CAAC,OAAO,KAAK,EAAE,CAAC,OAAO,CAAC;IAE5H,+DAA+D;IAC/D,MAAM,YAAY,GAAa,EAAE,CAAC;IAClC,KAAK,MAAM,CAAC,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,KAAK,KAAK,cAAc;YAAE,YAAY,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;aACrD,IAAI,CAAC,CAAC,KAAK,KAAK,eAAe,IAAI,CAAC,CAAC,IAAI,KAAK,OAAO;YAAE,YAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,gBAAgB,CAAC,CAAC;IAC3G,CAAC;IAED,kDAAkD;IAClD,MAAM,OAAO,GAAa,EAAE,CAAC;IAC7B,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,MAAM,CAAC,IAAI,SAAS,EAAE,CAAC;QAC1B,IAAI,CAAC,CAAC,MAAM,KAAK,WAAW;YAAE,SAAS;QACvC,IAAI,CAAC,CAAC,UAAU,IAAI,CAAC,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,UAAU,CAAC;YAAE,SAAS;QAC7E,MAAM,GAAG,GAAG,cAAc,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC;QACnC,IAAI,GAAG,KAAK,IAAI,IAAI,GAAG,GAAG,mBAAmB;YAAE,KAAK,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,IAAI,KAAK,IAAI,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;;YACxF,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC;IAC5B,CAAC;IAED,2CAA2C;IAC3C,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,aAAa,IAAI,EAAE,CAAC,CAAC;IAC5D,MAAM,UAAU,GAAG,MAAM,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,aAAa,IAAI,CAAC,CAAC,KAAK,KAAK,gBAAgB,CAAC,CAAC;IAC5G,MAAM,WAAW,GAAG,UAAU,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC;IACnF,MAAM,aAAa,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,aAAa,CAAC,CAAC;IAC3E,MAAM,gBAAgB,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,gBAAgB,CAAC,CAAC;IAEjF,uCAAuC;IACvC,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,SAAS,EAAE,cAAc,IAAI,EAAE,CAAC,CAAC;IAC3D,MAAM,aAAa,GAAG,KAAK,CAAC,QAAQ;SACjC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;SACrF,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC;IAEvB,MAAM,SAAS,GAAG,EAAE,CAAC,SAAS,KAAK,KAAK,IAAI,EAAE,CAAC,cAAc,KAAK,OAAO,CAAC;IAE1E,MAAM,GAAG,GAAG,GAAG,EAAE,CAAC,KAAK,IAAI,EAAE,CAAC,IAAI,IAAI,EAAE,CAAC,MAAM,EAAE,CAAC;IAClD,MAAM,GAAG,GAAG,CAAC,OAAsB,EAAE,IAAY,EAAE,IAAY,EAAE,EAAE;QACjE,OAAO,CAAC,IAAI,CAAC,EAAE,OAAO,EAAE,EAAE,EAAE,GAAG,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC;IACjD,CAAC,CAAC;IAEF,0BAA0B;IAC1B,IAAI,SAAS,EAAE,CAAC;QACd,GAAG,CAAC,KAAK,EAAE,wBAAwB,EAAE,CAAC,OAAO,EAAE,EAAE,+DAA+D,CAAC,CAAC;IACpH,CAAC;IACD,IAAI,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC5B,GAAG,CACD,KAAK,EACL,4BAA4B,YAAY,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACrD,0FAA0F,CAC3F,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,GAAG,CACD,KAAK,EACL,GAAG,aAAa,CAAC,MAAM,sBAAsB,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,oBAAoB,aAAa;aAChH,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;aACrB,IAAI,CAAC,IAAI,CAAC,GAAG,aAAa,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,aAAa,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EACxF,oFAAoF,CACrF,CAAC;IACJ,CAAC;IACD,IAAI,gBAAgB,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAChC,GAAG,CACD,KAAK,EACL,GAAG,gBAAgB,CAAC,MAAM,sBAAsB,gBAAgB,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,oBAAoB,gBAAgB;aACzH,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC;aACX,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;aACrB,IAAI,CAAC,IAAI,CAAC,EAAE,EACf,uFAAuF,CACxF,CAAC;IACJ,CAAC;IACD,IAAI,aAAa,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAC7B,GAAG,CAAC,KAAK,EAAE,iBAAiB,aAAa,CAAC,MAAM,aAAa,aAAa,CAAC,MAAM,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,GAAG,KAAK,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EAAE,+GAA+G,CAAC,CAAC;IAClQ,CAAC;IACD,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACrB,GAAG,CACD,KAAK,EACL,kCAAkC,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,EACpD,+FAA+F,CAChG,CAAC;IACJ,CAAC;IAED,4BAA4B;IAC5B,IAAI,OAAO,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QACvB,GAAG,CAAC,SAAS,EAAE,yBAAyB,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,CAAC,CAAC,MAAM,OAAO,CAAC,MAAM,GAAG,CAAC,QAAQ,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,0DAA0D,CAAC,CAAC;IACrM,CAAC;IACD,MAAM,eAAe,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,KAAK,kBAAkB,CAAC,CAAC;IAC9E,IAAI,eAAe,EAAE,CAAC;QACpB,GAAG,CAAC,SAAS,EAAE,0EAA0E,EAAE,8DAA8D,CAAC,CAAC;IAC7J,CAAC;IACD,MAAM,IAAI,GACR,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,EAAE,CAAC,OAAO,KAAK,aAAa;QAC5B,MAAM,CAAC,OAAO,KAAK,aAAa;QAChC,CAAC,SAAS;QACV,OAAO,CAAC,MAAM,KAAK,CAAC;QACpB,KAAK,CAAC,MAAM,KAAK,CAAC,CAAC;IACrB,IAAI,IAAI,EAAE,CAAC;QACT,GAAG,CACD,SAAS,EACT,sCAAsC,EACtC,uEAAuE,CACxE,CAAC;IACJ,CAAC;IAED,OAAO;QACL,EAAE,EAAE,GAAG;QACP,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,IAAI,EAAE,EAAE,CAAC,IAAI;QACb,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,KAAK,EAAE,EAAE,CAAC,KAAK;QACf,MAAM,EAAE,EAAE,CAAC,MAAM;QACjB,OAAO,EAAE,EAAE,CAAC,OAAO;QACnB,WAAW;QACX,SAAS;QACT,cAAc,EAAE,EAAE,CAAC,cAAc;QACjC,SAAS,EAAE,EAAE,CAAC,OAAO;QACrB,YAAY;QACZ,aAAa,EAAE,OAAO;QACtB,WAAW,EAAE,KAAK;QAClB,aAAa;QACb,gBAAgB;QAChB,aAAa;QACb,YAAY,EAAE,KAAK,CAAC,OAAO;QAC3B,OAAO;KACR,CAAC;AACJ,CAAC;AAED,+EAA+E;AAC/E,MAAM,UAAU,mBAAmB,CAAC,MAAuB,EAAE,MAA0B,EAAE,KAAkB,EAAE,GAAS;IACpH,OAAO;QACL,OAAO,EAAE,MAAM,CAAC,OAAO;QACvB,aAAa,EAAE,MAAM,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC;QAC7D,cAAc,EAAE,KAAK,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,QAAQ,KAAK,MAAM,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC;QAC7G,aAAa,EAAE,MAAM,CAAC,SAAS;QAC/B,kBAAkB,EAAE,MAAM,CAAC,cAAc;QACzC,SAAS,EAAE,GAAG,CAAC,WAAW,EAAE;KAC7B,CAAC;AACJ,CAAC;AA6BD,SAAS,cAAc,CAAC,OAA0B,EAAE,GAA0C;IAC5F,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,KAAK,CAAC,IAAI,CAAC,oBAAoB,GAAG,CAAC,WAAW,CAAC,MAAM,kBAAkB,GAAG,CAAC,aAAa,CAAC,MAAM,aAAa,GAAG,CAAC,KAAK,CAAC,MAAM,aAAa,GAAG,CAAC,UAAU,eAAe,CAAC,CAAC;IACxK,IAAI,GAAG,CAAC,QAAQ;QAAE,KAAK,CAAC,IAAI,CAAC,+GAA+G,CAAC,CAAC;IAC9I,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,MAAM,OAAO,GAAG,CAAC,KAAa,EAAE,KAAsB,EAAE,EAAE;QACxD,KAAK,CAAC,IAAI,CAAC,MAAM,KAAK,EAAE,CAAC,CAAC;QAC1B,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;YACvB,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;QACxB,CAAC;aAAM,CAAC;YACN,KAAK,MAAM,CAAC,IAAI,KAAK,EAAE,CAAC;gBACtB,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;gBACxC,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;YAClC,CAAC;QACH,CAAC;QACD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACjB,CAAC,CAAC;IACF,OAAO,CAAC,eAAe,EAAE,GAAG,CAAC,WAAW,CAAC,CAAC;IAC1C,OAAO,CAAC,iBAAiB,EAAE,GAAG,CAAC,aAAa,CAAC,CAAC;IAC9C,KAAK,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACvB,IAAI,GAAG,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;;QAC7C,KAAK,MAAM,CAAC,IAAI,GAAG,CAAC,KAAK;YAAE,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,EAAE,CAAC,CAAC;IACrD,KAAK,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;IACf,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,IAAI,CAAC,CAAC,WAAW;YAAE,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,EAAE,cAAc,CAAC,CAAC,OAAO,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,yBAAyB,CAAC,CAAC;IACtG,CAAC;IACD,KAAK,CAAC,IAAI,CAAC,qCAAqC,eAAe,IAAI,CAAC,CAAC;IACrE,OAAO,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AAC1B,CAAC;AAED;;;;;GAKG;AACH,MAAM,CAAC,KAAK,UAAU,OAAO,CAAC,IAAuB;IACnD,MAAM,IAAI,GAAG,IAAI,CAAC,IAAI,IAAI,EAAE,CAAC;IAC7B,MAAM,GAAG,GAAG,IAAI,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC;IACnC,MAAM,SAAS,GAAG,IAAI,CAAC,SAAS,IAAI,gBAAgB,EAAE,CAAC;IACvD,MAAM,KAAK,GAAG,SAAS,CAAC,SAAS,CAAC,CAAC;IACnC,MAAM,QAAQ,GAAG,MAAM,CAAC,IAAI,CAAC,KAAK,CAAC,UAAU,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC;IAE5D,IAAI,MAAM,GAAG,CAAC,GAAG,CAAC,IAAI,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,IAAI,EAAE,CAAC;QACd,MAAM,MAAM,GAAG,IAAI,CAAC,MAAM,IAAI,kBAAkB,CAAC;QACjD,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,EAAE,CAAC;QAC/B,MAAM,QAAQ,GAAG,IAAI,CAAC,WAAW,IAAI,kBAAkB,CAAC;QACxD,IAAI,CAAC;YACH,MAAM,KAAK,GAAG,MAAM,QAAQ,CAAC,MAAM,EAAE,KAAK,CAAC,CAAC;YAC5C,MAAM,GAAG,KAAK,CAAC,KAAK,CAAC,CAAC,EAAE,kBAAkB,CAAC,CAAC;QAC9C,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,EAAE,CAAC;YACZ,qEAAqE;YACrE,MAAM,GAAG,GAAe;gBACtB,OAAO,EAAE,EAAE;gBACX,WAAW,EAAE,EAAE;gBACf,aAAa,EAAE,EAAE;gBACjB,KAAK,EAAE,EAAE;gBACT,QAAQ;gBACR,UAAU,EAAE,CAAC;gBACb,QAAQ,EAAE,+CAA+C,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBAC3G,IAAI,EAAE,EAAE,KAAK,EAAE,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;aAClE,CAAC;YACF,OAAO,GAAG,CAAC;QACb,CAAC;IACH,CAAC;IAED,MAAM,OAAO,GAAsB,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,IAAI,cAAc,CAAC;IAC/C,MAAM,cAAc,GAAG,IAAI,CAAC,cAAc,IAAI,qBAAqB,CAAC;IACpE,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,IAAI,QAAQ,CAAC;IAC3C,MAAM,YAAY,GAAG,IAAI,CAAC,YAAY,IAAI,mBAAmB,CAAC;IAC9D,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,IAAI,OAAO,CAAC;IAEpC,KAAK,MAAM,KAAK,IAAI,MAAM,EAAE,CAAC;QAC3B,IAAI,CAAC;YACH,MAAM,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM,EAAE,GAAG,YAAY,CAAC,KAAK,CAAC,CAAC;YACpD,MAAM,EAAE,GAAG,MAAM,OAAO,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,IAAI,EAAE,CAAC,KAAK,KAAK,MAAM,EAAE,CAAC;gBACxB,+DAA+D;gBAC/D,oEAAoE;gBACpE,2CAA2C;gBAC3C,MAAM,UAAU,GAAG,EAAE,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,CAAC,QAAQ,CAAC;gBAC/D,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;gBAC9C,OAAO,CAAC,IAAI,CAAC;oBACX,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,IAAI,EAAE,MAAM;oBAC5B,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM;oBAClC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK;oBACvC,UAAU;oBACV,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI;oBACtC,SAAS,EAAE,eAAe;oBAC1B,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;oBACpD,aAAa,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE;oBAC1D,YAAY,EAAE,EAAE;oBAChB,OAAO,EAAE,EAAE;iBACZ,CAAC,CAAC;gBACH,OAAO,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC;gBAC7B,SAAS;YACX,CAAC;YACD,MAAM,CAAC,SAAS,EAAE,EAAE,EAAE,MAAM,EAAE,WAAW,CAAC,GAAG,MAAM,OAAO,CAAC,GAAG,CAAC;gBAC7D,cAAc,CAAC,KAAK,EAAE,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,EAAuB,CAAC;gBAC5E,QAAQ,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;gBACjC,YAAY,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;gBACrC,KAAK,CAAC,KAAK,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC;aAC/B,CAAC,CAAC;YACH,IAAI,CAAC,EAAE,IAAI,CAAC,MAAM,IAAI,CAAC,WAAW,EAAE,CAAC;gBACnC,OAAO,CAAC,IAAI,CAAC;oBACX,EAAE,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC;oBACrC,KAAK,EAAE,IAAI,EAAE,MAAM;oBACnB,KAAK,EAAE,EAAE,CAAC,KAAK,EAAE,MAAM,EAAE,EAAE,CAAC,MAAM;oBAClC,OAAO,EAAE,EAAE,CAAC,OAAO,EAAE,WAAW,EAAE,KAAK;oBACvC,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,EAAE,CAAC,cAAc;oBACnD,SAAS,EAAE,eAAe;oBAC1B,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;oBACpD,aAAa,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE;oBAC1D,YAAY,EAAE,EAAE;oBAChB,OAAO,EAAE,CAAC;4BACR,OAAO,EAAE,SAAS;4BAClB,EAAE,EAAE,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC;4BACrC,IAAI,EAAE,wDAAwD;4BAC9D,IAAI,EAAE,+DAA+D;yBACtE,CAAC;iBACH,CAAC,CAAC;gBACH,SAAS;YACX,CAAC;YACD,MAAM,GAAG,GAAG,YAAY,CAAC,KAAK,EAAE,IAAI,EAAE,MAAM,CAAC,CAAC;YAC9C,MAAM,MAAM,GAAG,aAAa,CAAC;gBAC3B,KAAK;gBACL,EAAE;gBACF,SAAS;gBACT,EAAE;gBACF,MAAM;gBACN,KAAK,EAAE,WAAW;gBAClB,SAAS,EAAE,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,IAAI,IAAI;gBACxC,GAAG;aACJ,CAAC,CAAC;YACH,OAAO,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YACrB,KAAK,CAAC,UAAU,CAAC,GAAG,CAAC,GAAG,mBAAmB,CAAC,MAAM,EAAE,MAAM,EAAE,WAAW,EAAE,GAAG,CAAC,CAAC;QAChF,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,GAAG,GAAG,KAAK,CAAC;YAClB,OAAO,CAAC,IAAI,CAAC;gBACX,EAAE,EAAE,GAAG,EAAE,KAAK,EAAE,EAAE,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,EAAE,CAAC;gBACvC,KAAK,EAAE,EAAE,EAAE,MAAM,EAAE,EAAE;gBACrB,OAAO,EAAE,EAAE,EAAE,WAAW,EAAE,KAAK;gBAC/B,SAAS,EAAE,KAAK,EAAE,cAAc,EAAE,IAAI;gBACtC,SAAS,EAAE,eAAe;gBAC1B,YAAY,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE,EAAE,WAAW,EAAE,EAAE;gBACpD,aAAa,EAAE,EAAE,EAAE,gBAAgB,EAAE,EAAE,EAAE,aAAa,EAAE,EAAE;gBAC1D,YAAY,EAAE,EAAE;gBAChB,OAAO,EAAE,CAAC;wBACR,OAAO,EAAE,SAAS;wBAClB,EAAE,EAAE,GAAG;wBACP,IAAI,EAAE,4BAA4B,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;wBACpF,IAAI,EAAE,0BAA0B;qBACjC,CAAC;aACH,CAAC,CAAC;QACL,CAAC;IACH,CAAC;IAED,SAAS,CAAC,SAAS,EAAE,KAAK,CAAC,CAAC;IAE5B,MAAM,WAAW,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,KAAK,CAAC,CAAC,CAAC;IACzF,MAAM,aAAa,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC;IAC/F,MAAM,WAAW,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,WAAW,EAAE,GAAG,aAAa,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IACjF,MAAM,KAAK,GAAG,OAAO;SAClB,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC;SACrC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CACT,CAAC,CAAC,UAAU;QACV,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,OAAO,CAAC,CAAC,UAAU,uBAAuB;QAC/D,CAAC,CAAC,GAAG,CAAC,CAAC,EAAE,KAAK,CAAC,CAAC,KAAK,uBAAuB,CAC/C,CAAC;IAEJ,MAAM,OAAO,GAA0C;QACrD,OAAO,EAAE,WAAW,EAAE,aAAa,EAAE,KAAK,EAAE,QAAQ,EAAE,UAAU,EAAE,OAAO,CAAC,MAAM;KACjF,CAAC;IACF,MAAM,QAAQ,GAAG,cAAc,CAAC,OAAO,EAAE,OAAO,CAAC,CAAC;IAClD,MAAM,IAAI,GAAG;QACX,UAAU,EAAE,OAAO,CAAC,UAAU;QAC9B,QAAQ;QACR,WAAW,EAAE,WAAW,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QAC/E,aAAa,EAAE,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC;QACnF,KAAK;QACL,OAAO,EAAE,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YAC3B,EAAE,EAAE,CAAC,CAAC,EAAE,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,OAAO,EAAE,CAAC,CAAC,OAAO,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW;YACxE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS;YAC9C,YAAY,EAAE,CAAC,CAAC,YAAY,EAAE,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,WAAW,EAAE,CAAC,CAAC,WAAW;YACxF,aAAa,EAAE,CAAC,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YACpD,gBAAgB,EAAE,CAAC,CAAC,gBAAgB,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,OAAO,CAAC;YAC1D,aAAa,EAAE,CAAC,CAAC,aAAa,EAAE,YAAY,EAAE,CAAC,CAAC,YAAY;SAC7D,CAAC,CAAC;KACJ,CAAC;IACF,OAAO,EAAE,GAAG,OAAO,EAAE,QAAQ,EAAE,IAAI,EAAE,CAAC;AACxC,CAAC"}
|