@jevitate/cli 0.8.0 → 0.10.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/dist/anchor-baselines.d.ts +26 -0
- package/dist/anchor-baselines.js +25 -0
- package/dist/anchor-baselines.js.map +1 -0
- package/dist/approval-provenance.d.ts +48 -2
- package/dist/approval-provenance.js +110 -6
- package/dist/approval-provenance.js.map +1 -1
- package/dist/bin.js +25111 -17835
- package/dist/browser-cli.d.ts +10 -0
- package/dist/browser-cli.js +50 -0
- package/dist/browser-cli.js.map +1 -0
- package/dist/build-info.generated.js +2 -2
- package/dist/catalog-analysis.js +14 -0
- package/dist/catalog-analysis.js.map +1 -1
- package/dist/catalog-api.js +12 -4
- package/dist/catalog-api.js.map +1 -1
- package/dist/catalog-bundle-api.d.ts +73 -0
- package/dist/catalog-bundle-api.js +206 -0
- package/dist/catalog-bundle-api.js.map +1 -0
- package/dist/catalog-bundle-findings.d.ts +54 -0
- package/dist/catalog-bundle-findings.js +252 -0
- package/dist/catalog-bundle-findings.js.map +1 -0
- package/dist/catalog-bundle.d.ts +192 -0
- package/dist/catalog-bundle.js +578 -0
- package/dist/catalog-bundle.js.map +1 -0
- package/dist/catalog-cli.d.ts +6 -0
- package/dist/catalog-cli.js +180 -5
- package/dist/catalog-cli.js.map +1 -1
- package/dist/catalog-refs.d.ts +42 -0
- package/dist/catalog-refs.js +188 -0
- package/dist/catalog-refs.js.map +1 -0
- package/dist/catalog-review.d.ts +3 -1
- package/dist/catalog-review.js +61 -0
- package/dist/catalog-review.js.map +1 -1
- package/dist/catalog.d.ts +27 -3
- package/dist/catalog.js +46 -2
- package/dist/catalog.js.map +1 -1
- package/dist/change-context.d.ts +44 -0
- package/dist/change-context.js +203 -0
- package/dist/change-context.js.map +1 -0
- package/dist/check-api.d.ts +1 -1
- package/dist/check-api.js +206 -16
- package/dist/check-api.js.map +1 -1
- package/dist/check-cli.d.ts +2 -1
- package/dist/check-cli.js +117 -8
- package/dist/check-cli.js.map +1 -1
- package/dist/check-execute.d.ts +28 -1
- package/dist/check-execute.js +110 -27
- package/dist/check-execute.js.map +1 -1
- package/dist/check-plan.d.ts +14 -0
- package/dist/check-plan.js +24 -1
- package/dist/check-plan.js.map +1 -1
- package/dist/check-types.d.ts +137 -5
- package/dist/check-types.js +8 -0
- package/dist/check-types.js.map +1 -1
- package/dist/cli-output.d.ts +6 -0
- package/dist/cli-output.js +26 -1
- package/dist/cli-output.js.map +1 -1
- package/dist/cli-shared.d.ts +10 -0
- package/dist/cli-shared.js +0 -4
- package/dist/cli-shared.js.map +1 -1
- package/dist/exit-codes.d.ts +6 -3
- package/dist/exit-codes.js +24 -3
- package/dist/exit-codes.js.map +1 -1
- package/dist/explore-adversarial.js +2 -2
- package/dist/explore-adversarial.js.map +1 -1
- package/dist/explore-cli.js +3 -2
- package/dist/explore-cli.js.map +1 -1
- package/dist/explore-coverage.js +3 -3
- package/dist/explore-coverage.js.map +1 -1
- package/dist/explore-feature.js +3 -3
- package/dist/explore-feature.js.map +1 -1
- package/dist/explore-goal.js +11 -5
- package/dist/explore-goal.js.map +1 -1
- package/dist/findings-filing.d.ts +6 -0
- package/dist/findings-filing.js +15 -1
- package/dist/findings-filing.js.map +1 -1
- package/dist/forge-verify.d.ts +224 -0
- package/dist/forge-verify.js +649 -0
- package/dist/forge-verify.js.map +1 -0
- package/dist/heal-probe-guard.d.ts +9 -0
- package/dist/heal-probe-guard.js +113 -0
- package/dist/heal-probe-guard.js.map +1 -0
- package/dist/host-health-run.d.ts +32 -1
- package/dist/host-health-run.js +38 -1
- package/dist/host-health-run.js.map +1 -1
- package/dist/init-codeowners.d.ts +19 -0
- package/dist/init-codeowners.js +66 -0
- package/dist/init-codeowners.js.map +1 -1
- package/dist/job-draft-api.d.ts +52 -0
- package/dist/job-draft-api.js +110 -0
- package/dist/job-draft-api.js.map +1 -0
- package/dist/journeeze-api.d.ts +71 -0
- package/dist/journeeze-api.js +285 -0
- package/dist/journeeze-api.js.map +1 -0
- package/dist/journeeze-connect.d.ts +156 -0
- package/dist/journeeze-connect.js +357 -0
- package/dist/journeeze-connect.js.map +1 -0
- package/dist/journey-anchor-gate.d.ts +52 -0
- package/dist/journey-anchor-gate.js +101 -0
- package/dist/journey-anchor-gate.js.map +1 -0
- package/dist/journey-api.d.ts +43 -3
- package/dist/journey-api.js +226 -21
- package/dist/journey-api.js.map +1 -1
- package/dist/journey-cli.js +162 -20
- package/dist/journey-cli.js.map +1 -1
- package/dist/journey-heal.d.ts +74 -0
- package/dist/journey-heal.js +180 -0
- package/dist/journey-heal.js.map +1 -0
- package/dist/journey-lint-sarif.d.ts +3 -2
- package/dist/journey-lint-sarif.js +9 -2
- package/dist/journey-lint-sarif.js.map +1 -1
- package/dist/journey-migrate-api.d.ts +54 -0
- package/dist/journey-migrate-api.js +64 -0
- package/dist/journey-migrate-api.js.map +1 -0
- package/dist/journey-network-checks.d.ts +5 -1
- package/dist/journey-network-checks.js +15 -4
- package/dist/journey-network-checks.js.map +1 -1
- package/dist/journey-prefix.js +2 -2
- package/dist/journey-prefix.js.map +1 -1
- package/dist/journey-proposal-store.d.ts +109 -0
- package/dist/journey-proposal-store.js +365 -0
- package/dist/journey-proposal-store.js.map +1 -0
- package/dist/journey-result-record.d.ts +42 -0
- package/dist/journey-result-record.js +33 -0
- package/dist/journey-result-record.js.map +1 -0
- package/dist/journey-review-api.js +16 -1
- package/dist/journey-review-api.js.map +1 -1
- package/dist/journey-review.d.ts +18 -1
- package/dist/journey-review.js +116 -5
- package/dist/journey-review.js.map +1 -1
- package/dist/journey-stale-api.d.ts +40 -0
- package/dist/journey-stale-api.js +57 -0
- package/dist/journey-stale-api.js.map +1 -0
- package/dist/launch-armed.js +5 -1
- package/dist/launch-armed.js.map +1 -1
- package/dist/locator-health-api.d.ts +101 -0
- package/dist/locator-health-api.js +203 -0
- package/dist/locator-health-api.js.map +1 -0
- package/dist/locator-health.d.ts +195 -0
- package/dist/locator-health.js +419 -0
- package/dist/locator-health.js.map +1 -0
- package/dist/login-cli.d.ts +2 -0
- package/dist/login-cli.js +56 -11
- package/dist/login-cli.js.map +1 -1
- package/dist/mcp-api.d.ts +5 -1
- package/dist/mcp-api.js +53 -8
- package/dist/mcp-api.js.map +1 -1
- package/dist/mcp-cli-tools.d.ts +3 -1
- package/dist/mcp-cli-tools.js +80 -10
- package/dist/mcp-cli-tools.js.map +1 -1
- package/dist/multi-run.d.ts +7 -6
- package/dist/multi-run.js +5 -4
- package/dist/multi-run.js.map +1 -1
- package/dist/persona-login.d.ts +60 -3
- package/dist/persona-login.js +341 -31
- package/dist/persona-login.js.map +1 -1
- package/dist/program.js +2 -0
- package/dist/program.js.map +1 -1
- package/dist/project-config.d.ts +29 -0
- package/dist/project-config.js +76 -0
- package/dist/project-config.js.map +1 -0
- package/dist/report-api.d.ts +1 -0
- package/dist/report-api.js +1 -0
- package/dist/report-api.js.map +1 -1
- package/dist/resource-preflight.js +5 -3
- package/dist/resource-preflight.js.map +1 -1
- package/dist/run-metadata.d.ts +5 -2
- package/dist/run-metadata.js +10 -3
- package/dist/run-metadata.js.map +1 -1
- package/dist/run-tags-cli.d.ts +2 -0
- package/dist/run-tags-cli.js +8 -2
- package/dist/run-tags-cli.js.map +1 -1
- package/dist/self-heal-adapter.d.ts +43 -27
- package/dist/self-heal-adapter.js +196 -62
- package/dist/self-heal-adapter.js.map +1 -1
- package/dist/source-cli.js +5 -3
- package/dist/source-cli.js.map +1 -1
- package/dist/suite-explore-options.js +1 -0
- package/dist/suite-explore-options.js.map +1 -1
- package/dist/sweep-api.d.ts +23 -0
- package/dist/sweep-api.js +39 -8
- package/dist/sweep-api.js.map +1 -1
- package/dist/sweep-cli.js +3 -1
- package/dist/sweep-cli.js.map +1 -1
- package/dist/ux-usability.js +3 -2
- package/dist/ux-usability.js.map +1 -1
- package/package.json +17 -15
- package/skills/jevitate-ci-check/SKILL.md +25 -1
- package/skills/jevitate-getting-started/SKILL.md +9 -3
- package/skills/jevitate-mission-scope/SKILL.md +2 -2
- package/skills/jevitate-run-journey/SKILL.md +36 -5
- package/skills/jevitate-test-campaign/SKILL.md +13 -0
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { looksGenerated } from "@jevitate/recorder";
|
|
2
|
+
// === Classification ===
|
|
3
|
+
const LEVEL_RANK = { low: 0, medium: 1, high: 2 };
|
|
4
|
+
/** One notch down: a rung that only resolves with an ordinal (the recorder's `CAPPED_STABILITY`). */
|
|
5
|
+
const CAPPED = { high: "medium", medium: "low", low: "low" };
|
|
6
|
+
const REASON_TEXT = {
|
|
7
|
+
"no-test-id": "no test id",
|
|
8
|
+
"test-id-not-in-convention": "test id attribute is not in the convention",
|
|
9
|
+
"tflow-id-not-a-test-id": "data-tflow-id is tracking metadata, not a test id",
|
|
10
|
+
"generated-value": "generated-looking id or name",
|
|
11
|
+
"no-accessible-name": "no accessible name",
|
|
12
|
+
"duplicate-name": "duplicate name needs disambiguation (nth)",
|
|
13
|
+
"positional-css": "deep or positional css path",
|
|
14
|
+
"text-copy": "text locator on copy likely to change",
|
|
15
|
+
};
|
|
16
|
+
/** The target a step acts on, or null (navigate, press, assert, a forEach's items are its own). */
|
|
17
|
+
export function stepTarget(step) {
|
|
18
|
+
switch (step.kind) {
|
|
19
|
+
case "click":
|
|
20
|
+
case "fill":
|
|
21
|
+
case "waitFor":
|
|
22
|
+
case "extract":
|
|
23
|
+
case "select":
|
|
24
|
+
case "upload":
|
|
25
|
+
case "editText":
|
|
26
|
+
return step.target;
|
|
27
|
+
default:
|
|
28
|
+
return null;
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
/** The recorded rung replay tries (an anchor first, as `resolveTarget` does). */
|
|
32
|
+
function recordedRung(d) {
|
|
33
|
+
if (d.anchor !== undefined && d.testId === undefined && (d.anchor.id !== undefined || d.anchor.name !== undefined))
|
|
34
|
+
return "anchor";
|
|
35
|
+
return ownRung(d);
|
|
36
|
+
}
|
|
37
|
+
function ownRung(d) {
|
|
38
|
+
if (d.testId)
|
|
39
|
+
return "testId";
|
|
40
|
+
if (d.role && d.name)
|
|
41
|
+
return "role+name";
|
|
42
|
+
if (d.label)
|
|
43
|
+
return "label";
|
|
44
|
+
if (d.text)
|
|
45
|
+
return "text";
|
|
46
|
+
if (d.css)
|
|
47
|
+
return "css";
|
|
48
|
+
return d.role ? "role" : "css";
|
|
49
|
+
}
|
|
50
|
+
function asRung(r) {
|
|
51
|
+
return ["testId", "anchor", "role+name", "role", "label", "text", "css"].find((x) => x === r) ?? "css";
|
|
52
|
+
}
|
|
53
|
+
/** How deep a css path is, and whether it is positional. */
|
|
54
|
+
function cssShape(css) {
|
|
55
|
+
return { depth: css.split(">").length, positional: /:nth-(of-type|child)\(|:first-|:last-/.test(css) };
|
|
56
|
+
}
|
|
57
|
+
function describeLocator(d, rung) {
|
|
58
|
+
const nth = d.ordinal === undefined ? "" : ` nth=${d.ordinal}`;
|
|
59
|
+
switch (rung) {
|
|
60
|
+
case "testId":
|
|
61
|
+
return `testId[${d.testIdAttr ?? "data-testid"}]=${d.testId ?? "?"}`;
|
|
62
|
+
case "anchor":
|
|
63
|
+
return d.anchor?.id !== undefined ? `[id=${JSON.stringify(d.anchor.id)}]` : `[name=${JSON.stringify(d.anchor?.name ?? "")}]`;
|
|
64
|
+
case "role+name":
|
|
65
|
+
return `role=${d.role ?? "?"} name=${JSON.stringify(d.name ?? "")}${nth}`;
|
|
66
|
+
case "label":
|
|
67
|
+
return `label=${JSON.stringify(d.label ?? "")}${nth}`;
|
|
68
|
+
case "text":
|
|
69
|
+
return `text=${JSON.stringify(d.text ?? "")}${nth}`;
|
|
70
|
+
default:
|
|
71
|
+
return `css=${d.css ?? "?"}`;
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
/**
|
|
75
|
+
* One target's verdict against the convention. `via` (a run's resolution) replaces the recorded rung
|
|
76
|
+
* when present; everything else is read from the descriptor.
|
|
77
|
+
*/
|
|
78
|
+
export function classifyTarget(d, testIdAttributes, via) {
|
|
79
|
+
const rung = via === undefined ? recordedRung(d) : asRung(via.rung);
|
|
80
|
+
const ordinal = via === undefined ? d.ordinal : via.ordinal;
|
|
81
|
+
const codes = [];
|
|
82
|
+
let level;
|
|
83
|
+
switch (rung) {
|
|
84
|
+
case "testId": {
|
|
85
|
+
const attr = (via?.testIdAttr ?? d.testIdAttr ?? "data-testid").toLowerCase();
|
|
86
|
+
const generated = looksGenerated(d.testId ?? "");
|
|
87
|
+
level = generated ? "low" : "high";
|
|
88
|
+
if (attr === "data-tflow-id")
|
|
89
|
+
codes.push("tflow-id-not-a-test-id");
|
|
90
|
+
else if (!testIdAttributes.includes(attr))
|
|
91
|
+
codes.push("test-id-not-in-convention");
|
|
92
|
+
if (generated)
|
|
93
|
+
codes.push("generated-value");
|
|
94
|
+
break;
|
|
95
|
+
}
|
|
96
|
+
case "anchor":
|
|
97
|
+
// A non-generated id/name attribute (the recorder refuses generated ones): sturdy, but not the convention.
|
|
98
|
+
level = "medium";
|
|
99
|
+
codes.push("no-test-id");
|
|
100
|
+
break;
|
|
101
|
+
case "role+name":
|
|
102
|
+
level = looksGenerated(d.name ?? "") ? "low" : "high";
|
|
103
|
+
codes.push("no-test-id");
|
|
104
|
+
if (level === "low")
|
|
105
|
+
codes.push("generated-value");
|
|
106
|
+
break;
|
|
107
|
+
case "label":
|
|
108
|
+
level = "medium";
|
|
109
|
+
codes.push("no-test-id");
|
|
110
|
+
break;
|
|
111
|
+
case "text":
|
|
112
|
+
level = "medium";
|
|
113
|
+
codes.push("no-test-id", "text-copy");
|
|
114
|
+
break;
|
|
115
|
+
default: {
|
|
116
|
+
level = "low";
|
|
117
|
+
codes.push("no-test-id");
|
|
118
|
+
const shape = cssShape(d.css ?? "");
|
|
119
|
+
if (shape.positional || shape.depth > 3)
|
|
120
|
+
codes.push("positional-css");
|
|
121
|
+
if (/#[A-Za-z0-9_-]*\d{4}|[0-9a-fA-F]{8}/.test(d.css ?? ""))
|
|
122
|
+
codes.push("generated-value");
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
if (ordinal !== undefined && rung !== "testId" && rung !== "anchor" && rung !== "css") {
|
|
126
|
+
level = CAPPED[level];
|
|
127
|
+
codes.push("duplicate-name");
|
|
128
|
+
}
|
|
129
|
+
if (rung !== "testId" && !(d.name || d.label))
|
|
130
|
+
codes.push("no-accessible-name");
|
|
131
|
+
if (d.tflowId !== undefined && rung !== "testId" && !codes.includes("tflow-id-not-a-test-id"))
|
|
132
|
+
codes.push("tflow-id-not-a-test-id");
|
|
133
|
+
return { rung, level, codes };
|
|
134
|
+
}
|
|
135
|
+
// === Suggestions ===
|
|
136
|
+
/** `"Save contact"` → `save-contact` (ASCII letters and digits, at most 40 chars). */
|
|
137
|
+
export function kebabCase(s) {
|
|
138
|
+
return s
|
|
139
|
+
.normalize("NFKD")
|
|
140
|
+
.replace(/[̀-ͯ]/g, "")
|
|
141
|
+
.replace(/([a-z0-9])([A-Z])/g, "$1-$2")
|
|
142
|
+
.toLowerCase()
|
|
143
|
+
.replace(/[^a-z0-9]+/g, "-")
|
|
144
|
+
.replace(/^-+|-+$/g, "")
|
|
145
|
+
.slice(0, 40)
|
|
146
|
+
.replace(/-+$/g, "");
|
|
147
|
+
}
|
|
148
|
+
/** The path of a page URL (`https://x/contacts/new?a=1` → `/contacts/new`); a path is kept as is. */
|
|
149
|
+
export function routeOf(url) {
|
|
150
|
+
if (url === undefined || url === "")
|
|
151
|
+
return undefined;
|
|
152
|
+
try {
|
|
153
|
+
return new URL(url).pathname;
|
|
154
|
+
}
|
|
155
|
+
catch {
|
|
156
|
+
const path = url.split(/[?#]/)[0] ?? url;
|
|
157
|
+
return path.startsWith("/") ? path : `/${path}`;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
function singular(word) {
|
|
161
|
+
if (/ies$/.test(word))
|
|
162
|
+
return word.replace(/ies$/, "y");
|
|
163
|
+
if (/(ss|us)$/.test(word))
|
|
164
|
+
return word;
|
|
165
|
+
return word.replace(/s$/, "");
|
|
166
|
+
}
|
|
167
|
+
/** The route's first meaningful segment (not an id or a verb like `new`/`edit`), singular. */
|
|
168
|
+
function routeWords(route) {
|
|
169
|
+
return (route ?? "").split("/").filter((s) => s !== "" && !/^\d+$/.test(s) && !looksGenerated(s) && !/^(new|edit|create|index|view)$/i.test(s));
|
|
170
|
+
}
|
|
171
|
+
function routeNoun(route) {
|
|
172
|
+
const first = routeWords(route)[0];
|
|
173
|
+
return first === undefined ? undefined : singular(kebabCase(first));
|
|
174
|
+
}
|
|
175
|
+
/**
|
|
176
|
+
* The suggested test id: the element's name in kebab-case, with the route's noun when the name is a
|
|
177
|
+
* single word (`Save` on /contacts/new → `save-contact`); an unnamed element is named by its route
|
|
178
|
+
* and tag (`contacts-div`).
|
|
179
|
+
*/
|
|
180
|
+
export function suggestTestId(name, route, fallbackTag) {
|
|
181
|
+
const base = name === undefined ? "" : kebabCase(name);
|
|
182
|
+
const noun = routeNoun(route);
|
|
183
|
+
if (base !== "")
|
|
184
|
+
return !base.includes("-") && noun !== undefined && !base.includes(noun) ? `${base}-${noun}` : base;
|
|
185
|
+
const where = kebabCase(routeWords(route).join("-"));
|
|
186
|
+
return `${where === "" ? "page" : where}-${fallbackTag}`;
|
|
187
|
+
}
|
|
188
|
+
function lastCssTag(css) {
|
|
189
|
+
const last = (css ?? "").split(">").pop()?.trim() ?? "";
|
|
190
|
+
return /^([a-z][a-z0-9-]*)/i.exec(last)?.[1]?.toLowerCase() ?? "element";
|
|
191
|
+
}
|
|
192
|
+
function describeElement(d) {
|
|
193
|
+
const name = d.name ?? d.label;
|
|
194
|
+
if (d.role && name)
|
|
195
|
+
return `the ${JSON.stringify(name)} ${d.role}`;
|
|
196
|
+
if (d.label)
|
|
197
|
+
return `the ${JSON.stringify(d.label)} field`;
|
|
198
|
+
if (d.role)
|
|
199
|
+
return `the ${d.role}`;
|
|
200
|
+
if (d.text)
|
|
201
|
+
return `the element with text ${JSON.stringify(d.text.length > 40 ? `${d.text.slice(0, 40)}…` : d.text)}`;
|
|
202
|
+
if (d.testId)
|
|
203
|
+
return `the element with ${d.testIdAttr ?? "data-testid"}=${JSON.stringify(d.testId)}`;
|
|
204
|
+
return `the element at css ${JSON.stringify(d.css ?? "?")}`;
|
|
205
|
+
}
|
|
206
|
+
/** The element's identity across steps and runs: route + role + name (else its css). */
|
|
207
|
+
export function suggestionKey(d, route) {
|
|
208
|
+
const name = d.name ?? d.label ?? d.text;
|
|
209
|
+
if (name !== undefined)
|
|
210
|
+
return `${route ?? ""}|${d.role ?? ""}|${name}`;
|
|
211
|
+
if (d.testId !== undefined)
|
|
212
|
+
return `${route ?? ""}|testid|${d.testId}`;
|
|
213
|
+
return `${route ?? ""}|css|${d.css ?? ""}`;
|
|
214
|
+
}
|
|
215
|
+
function fixFor(d, codes, attribute, testId, element, route) {
|
|
216
|
+
const on = route === undefined ? "" : ` on ${route}`;
|
|
217
|
+
const named = codes.includes("no-accessible-name") ? " and give it an accessible name (visible text or aria-label)" : "";
|
|
218
|
+
if (codes.includes("test-id-not-in-convention") && d.testId !== undefined && !looksGenerated(d.testId)) {
|
|
219
|
+
return `use ${attribute}=${JSON.stringify(d.testId)} instead of ${d.testIdAttr ?? "?"} on ${element}${on} (or add ${d.testIdAttr ?? "?"} to testIdAttributes in .jevitate/project.json)`;
|
|
220
|
+
}
|
|
221
|
+
if (d.testId !== undefined && looksGenerated(d.testId)) {
|
|
222
|
+
return `replace the generated ${d.testIdAttr ?? attribute}=${JSON.stringify(d.testId)} on ${element}${on} with a stable ${attribute}=${JSON.stringify(testId)}`;
|
|
223
|
+
}
|
|
224
|
+
return `add ${attribute}=${JSON.stringify(testId)} to ${element}${on}${named}`;
|
|
225
|
+
}
|
|
226
|
+
function buildSuggestion(d, codes, route, attribute, html, occurrence) {
|
|
227
|
+
const name = d.name ?? d.label ?? d.text;
|
|
228
|
+
const testId = suggestTestId(d.testId !== undefined && !looksGenerated(d.testId) ? d.testId : name, route, lastCssTag(d.css));
|
|
229
|
+
const element = describeElement(d);
|
|
230
|
+
return {
|
|
231
|
+
key: suggestionKey(d, route),
|
|
232
|
+
...(route === undefined ? {} : { route }),
|
|
233
|
+
...(d.role === undefined ? {} : { role: d.role }),
|
|
234
|
+
...(name === undefined ? {} : { name }),
|
|
235
|
+
element,
|
|
236
|
+
...(html === undefined ? {} : { html: html.length > 160 ? `${html.slice(0, 160)}…` : html }),
|
|
237
|
+
attribute,
|
|
238
|
+
testId,
|
|
239
|
+
fix: fixFor(d, codes, attribute, testId, element, route),
|
|
240
|
+
reasons: codes.map((c) => REASON_TEXT[c]),
|
|
241
|
+
occurrences: [occurrence],
|
|
242
|
+
};
|
|
243
|
+
}
|
|
244
|
+
/** Merges suggestions for the same element (route + role + name): occurrences and reasons combined. */
|
|
245
|
+
export function dedupeSuggestions(lists) {
|
|
246
|
+
const byKey = new Map();
|
|
247
|
+
for (const s of lists.flat()) {
|
|
248
|
+
const prev = byKey.get(s.key);
|
|
249
|
+
if (prev === undefined) {
|
|
250
|
+
byKey.set(s.key, s);
|
|
251
|
+
continue;
|
|
252
|
+
}
|
|
253
|
+
const occ = [...prev.occurrences];
|
|
254
|
+
for (const o of s.occurrences) {
|
|
255
|
+
if (!occ.some((p) => p.journeyId === o.journeyId && p.index === o.index && p.stepId === o.stepId))
|
|
256
|
+
occ.push(o);
|
|
257
|
+
}
|
|
258
|
+
byKey.set(s.key, {
|
|
259
|
+
...prev,
|
|
260
|
+
...(prev.html === undefined && s.html !== undefined ? { html: s.html } : {}),
|
|
261
|
+
reasons: [...new Set([...prev.reasons, ...s.reasons])],
|
|
262
|
+
occurrences: occ,
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
// The elements most steps depend on first: the highest-value fixes lead the work list.
|
|
266
|
+
return [...byKey.values()].sort((a, b) => b.occurrences.length - a.occurrences.length || a.key.localeCompare(b.key));
|
|
267
|
+
}
|
|
268
|
+
// === Analysis ===
|
|
269
|
+
function flatWithRoute(rec) {
|
|
270
|
+
return rec.pages.flatMap((p) => p.steps.map((recorded) => ({ recorded, route: routeOf(p.url) })));
|
|
271
|
+
}
|
|
272
|
+
export function emptyLevels() {
|
|
273
|
+
return { high: 0, medium: 0, low: 0 };
|
|
274
|
+
}
|
|
275
|
+
/** `7/9 steps on stable locators; 2 brittle (high 7 · medium 1 · low 1)`. */
|
|
276
|
+
export function healthLine(h) {
|
|
277
|
+
const total = h.stable + h.brittle;
|
|
278
|
+
if (total === 0)
|
|
279
|
+
return "no steps act on a target";
|
|
280
|
+
return `${h.stable}/${total} steps on stable locators; ${h.brittle} brittle (high ${h.levels.high} · medium ${h.levels.medium} · low ${h.levels.low})`;
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* A recording's locator health: every step with a target (flat index, as the interpreter numbers
|
|
284
|
+
* them), against the convention; with `resolved`, the rung each step actually matched at replay.
|
|
285
|
+
*/
|
|
286
|
+
export function analyzeRecording(rec, opts) {
|
|
287
|
+
const attribute = opts.testIdAttributes[0] ?? "data-testid";
|
|
288
|
+
const resolvedBy = new Map((opts.resolved ?? []).map((r) => [r.index, r]));
|
|
289
|
+
const steps = [];
|
|
290
|
+
const suggestions = [];
|
|
291
|
+
const levels = { high: 0, medium: 0, low: 0 };
|
|
292
|
+
flatWithRoute(rec).forEach(({ recorded, route }, index) => {
|
|
293
|
+
const d = stepTarget(recorded.step);
|
|
294
|
+
if (d === null)
|
|
295
|
+
return;
|
|
296
|
+
const via = resolvedBy.get(index);
|
|
297
|
+
const v = classifyTarget(d, opts.testIdAttributes, via);
|
|
298
|
+
const brittle = v.codes.length > 0;
|
|
299
|
+
levels[v.level] += 1;
|
|
300
|
+
const stepId = recorded.stepId ?? via?.stepId;
|
|
301
|
+
let key;
|
|
302
|
+
if (brittle) {
|
|
303
|
+
const occurrence = { ...(opts.journeyId === undefined ? {} : { journeyId: opts.journeyId }), index, ...(stepId === undefined ? {} : { stepId }) };
|
|
304
|
+
const s = buildSuggestion(d, v.codes, route, attribute, opts.html?.get(index), occurrence);
|
|
305
|
+
suggestions.push(s);
|
|
306
|
+
key = s.key;
|
|
307
|
+
}
|
|
308
|
+
steps.push({
|
|
309
|
+
...(stepId === undefined ? {} : { stepId }),
|
|
310
|
+
index,
|
|
311
|
+
kind: recorded.step.kind,
|
|
312
|
+
rung: v.rung,
|
|
313
|
+
level: v.level,
|
|
314
|
+
stability: brittle ? "brittle" : "stable",
|
|
315
|
+
source: via === undefined ? "recorded" : "resolved",
|
|
316
|
+
...(route === undefined ? {} : { route }),
|
|
317
|
+
locator: describeLocator(d, v.rung),
|
|
318
|
+
reasons: v.codes.map((c) => REASON_TEXT[c]),
|
|
319
|
+
reasonCodes: v.codes,
|
|
320
|
+
...(key === undefined ? {} : { suggestion: key }),
|
|
321
|
+
});
|
|
322
|
+
});
|
|
323
|
+
const stable = steps.filter((s) => s.stability === "stable").length;
|
|
324
|
+
const brittle = steps.length - stable;
|
|
325
|
+
return { stable, brittle, steps, levels, line: healthLine({ stable, brittle, levels }), suggestions: dedupeSuggestions([suggestions]) };
|
|
326
|
+
}
|
|
327
|
+
/** Totals over several healths (a report, a check): counts, levels and the de-duplicated work list. */
|
|
328
|
+
export function combineHealth(healths) {
|
|
329
|
+
const levels = { high: 0, medium: 0, low: 0 };
|
|
330
|
+
let stable = 0;
|
|
331
|
+
let brittle = 0;
|
|
332
|
+
for (const h of healths) {
|
|
333
|
+
stable += h.stable;
|
|
334
|
+
brittle += h.brittle;
|
|
335
|
+
levels.high += h.levels.high;
|
|
336
|
+
levels.medium += h.levels.medium;
|
|
337
|
+
levels.low += h.levels.low;
|
|
338
|
+
}
|
|
339
|
+
return { stable, brittle, levels, line: healthLine({ stable, brittle, levels }), suggestions: dedupeSuggestions(healths.map((h) => h.suggestions)) };
|
|
340
|
+
}
|
|
341
|
+
// === Gate ===
|
|
342
|
+
/** `check --max-brittle-steps <n>`: true when a Journey item's brittle steps exceed the opt-in threshold. */
|
|
343
|
+
export function exceedsBrittleSteps(health, maxBrittleSteps) {
|
|
344
|
+
return maxBrittleSteps !== undefined && health.brittle > maxBrittleSteps;
|
|
345
|
+
}
|
|
346
|
+
function stepKey(s) {
|
|
347
|
+
return s.stepId ?? `#${s.index}`;
|
|
348
|
+
}
|
|
349
|
+
function score(s) {
|
|
350
|
+
return (s.stability === "stable" ? 10 : 0) + LEVEL_RANK[s.level ?? (s.stability === "stable" ? "high" : "low")];
|
|
351
|
+
}
|
|
352
|
+
/**
|
|
353
|
+
* The trend of `current` against `baseline` (a previous report or run of the same Journey), keyed by
|
|
354
|
+
* step id (else index): a Journey re-recorded or healed after the app added test ids shows its
|
|
355
|
+
* improvement; a step that fell back to a brittle rung shows as a regression.
|
|
356
|
+
*/
|
|
357
|
+
export function compareLocatorHealth(current, baseline) {
|
|
358
|
+
const before = new Map(baseline.steps.map((s) => [stepKey(s), s]));
|
|
359
|
+
const seen = new Set();
|
|
360
|
+
const changes = [];
|
|
361
|
+
let unchanged = 0;
|
|
362
|
+
let added = 0;
|
|
363
|
+
const shape = (s) => ({ rung: s.rung, level: s.level ?? (s.stability === "stable" ? "high" : "low"), stability: s.stability });
|
|
364
|
+
for (const s of current.steps) {
|
|
365
|
+
const key = stepKey(s);
|
|
366
|
+
seen.add(key);
|
|
367
|
+
const b = before.get(key);
|
|
368
|
+
if (b === undefined) {
|
|
369
|
+
added++;
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
const delta = score(s) - score(b);
|
|
373
|
+
if (delta === 0)
|
|
374
|
+
unchanged++;
|
|
375
|
+
else
|
|
376
|
+
changes.push({ key, from: shape(b), to: shape(s), direction: delta > 0 ? "improved" : "regressed" });
|
|
377
|
+
}
|
|
378
|
+
const removed = [...before.keys()].filter((k) => !seen.has(k)).length;
|
|
379
|
+
return {
|
|
380
|
+
improved: changes.filter((c) => c.direction === "improved").length,
|
|
381
|
+
regressed: changes.filter((c) => c.direction === "regressed").length,
|
|
382
|
+
unchanged,
|
|
383
|
+
added,
|
|
384
|
+
removed,
|
|
385
|
+
brittleDelta: current.brittle - baseline.brittle,
|
|
386
|
+
changes,
|
|
387
|
+
};
|
|
388
|
+
}
|
|
389
|
+
/** `trend vs baseline: 2 improved, 1 regressed (brittle -1)`. */
|
|
390
|
+
export function trendLine(t) {
|
|
391
|
+
const sign = t.brittleDelta > 0 ? `+${t.brittleDelta}` : String(t.brittleDelta);
|
|
392
|
+
return `trend vs baseline: ${t.improved} improved, ${t.regressed} regressed (brittle ${sign})`;
|
|
393
|
+
}
|
|
394
|
+
/** The compact form of a detail: per-step rung/stability/reasons, and the top `top` fixes. */
|
|
395
|
+
export function compactHealth(h, top = 5) {
|
|
396
|
+
return {
|
|
397
|
+
stable: h.stable,
|
|
398
|
+
brittle: h.brittle,
|
|
399
|
+
levels: h.levels,
|
|
400
|
+
line: h.line,
|
|
401
|
+
steps: h.steps.map((s) => ({
|
|
402
|
+
...(s.stepId === undefined ? {} : { stepId: s.stepId }),
|
|
403
|
+
index: s.index,
|
|
404
|
+
rung: s.rung,
|
|
405
|
+
stability: s.stability,
|
|
406
|
+
reasons: s.reasons,
|
|
407
|
+
...("level" in s ? { level: s.level } : {}),
|
|
408
|
+
})),
|
|
409
|
+
suggestions: h.suggestions.slice(0, top).map((s) => ({
|
|
410
|
+
key: s.key,
|
|
411
|
+
element: s.element,
|
|
412
|
+
fix: s.fix,
|
|
413
|
+
reasons: s.reasons,
|
|
414
|
+
...(s.route === undefined ? {} : { route: s.route }),
|
|
415
|
+
steps: s.occurrences.length,
|
|
416
|
+
})),
|
|
417
|
+
};
|
|
418
|
+
}
|
|
419
|
+
//# sourceMappingURL=locator-health.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"locator-health.js","sourceRoot":"","sources":["../src/locator-health.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,oBAAoB,CAAC;AA6GpD,yBAAyB;AAEzB,MAAM,UAAU,GAA2C,EAAE,GAAG,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,CAAC,EAAE,CAAC;AAC1F,qGAAqG;AACrG,MAAM,MAAM,GAAiD,EAAE,IAAI,EAAE,QAAQ,EAAE,MAAM,EAAE,KAAK,EAAE,GAAG,EAAE,KAAK,EAAE,CAAC;AAE3G,MAAM,WAAW,GAAgD;IAC/D,YAAY,EAAE,YAAY;IAC1B,2BAA2B,EAAE,4CAA4C;IACzE,wBAAwB,EAAE,mDAAmD;IAC7E,iBAAiB,EAAE,8BAA8B;IACjD,oBAAoB,EAAE,oBAAoB;IAC1C,gBAAgB,EAAE,2CAA2C;IAC7D,gBAAgB,EAAE,6BAA6B;IAC/C,WAAW,EAAE,uCAAuC;CACrD,CAAC;AAEF,mGAAmG;AACnG,MAAM,UAAU,UAAU,CAAC,IAAU;IACnC,QAAQ,IAAI,CAAC,IAAI,EAAE,CAAC;QAClB,KAAK,OAAO,CAAC;QACb,KAAK,MAAM,CAAC;QACZ,KAAK,SAAS,CAAC;QACf,KAAK,SAAS,CAAC;QACf,KAAK,QAAQ,CAAC;QACd,KAAK,QAAQ,CAAC;QACd,KAAK,UAAU;YACb,OAAO,IAAI,CAAC,MAAM,CAAC;QACrB;YACE,OAAO,IAAI,CAAC;IAChB,CAAC;AACH,CAAC;AAED,iFAAiF;AACjF,SAAS,YAAY,CAAC,CAAmB;IACvC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,KAAK,SAAS,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,KAAK,SAAS,CAAC;QAAE,OAAO,QAAQ,CAAC;IACpI,OAAO,OAAO,CAAC,CAAC,CAAC,CAAC;AACpB,CAAC;AAED,SAAS,OAAO,CAAC,CAAmB;IAClC,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,QAAQ,CAAC;IAC9B,IAAI,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,WAAW,CAAC;IACzC,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,OAAO,CAAC;IAC5B,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,MAAM,CAAC;IAC1B,IAAI,CAAC,CAAC,GAAG;QAAE,OAAO,KAAK,CAAC;IACxB,OAAO,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC;AACjC,CAAC;AAED,SAAS,MAAM,CAAC,CAAS;IACvB,OAAQ,CAAC,QAAQ,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAW,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,CAAC;AACpH,CAAC;AAED,4DAA4D;AAC5D,SAAS,QAAQ,CAAC,GAAW;IAC3B,OAAO,EAAE,KAAK,EAAE,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,EAAE,UAAU,EAAE,uCAAuC,CAAC,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC;AACzG,CAAC;AAED,SAAS,eAAe,CAAC,CAAmB,EAAE,IAAiB;IAC7D,MAAM,GAAG,GAAG,CAAC,CAAC,OAAO,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,QAAQ,CAAC,CAAC,OAAO,EAAE,CAAC;IAC/D,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ;YACX,OAAO,UAAU,CAAC,CAAC,UAAU,IAAI,aAAa,KAAK,CAAC,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;QACvE,KAAK,QAAQ;YACX,OAAO,CAAC,CAAC,MAAM,EAAE,EAAE,KAAK,SAAS,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,EAAE,IAAI,IAAI,EAAE,CAAC,GAAG,CAAC;QAC/H,KAAK,WAAW;YACd,OAAO,QAAQ,CAAC,CAAC,IAAI,IAAI,GAAG,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC;QAC5E,KAAK,OAAO;YACV,OAAO,SAAS,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC;QACxD,KAAK,MAAM;YACT,OAAO,QAAQ,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,GAAG,GAAG,EAAE,CAAC;QACtD;YACE,OAAO,OAAO,CAAC,CAAC,GAAG,IAAI,GAAG,EAAE,CAAC;IACjC,CAAC;AACH,CAAC;AAQD;;;GAGG;AACH,MAAM,UAAU,cAAc,CAAC,CAAmB,EAAE,gBAAmC,EAAE,GAAuB;IAC9G,MAAM,IAAI,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACpE,MAAM,OAAO,GAAG,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC;IAC5D,MAAM,KAAK,GAAwB,EAAE,CAAC;IACtC,IAAI,KAAmB,CAAC;IACxB,QAAQ,IAAI,EAAE,CAAC;QACb,KAAK,QAAQ,CAAC,CAAC,CAAC;YACd,MAAM,IAAI,GAAG,CAAC,GAAG,EAAE,UAAU,IAAI,CAAC,CAAC,UAAU,IAAI,aAAa,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9E,MAAM,SAAS,GAAG,cAAc,CAAC,CAAC,CAAC,MAAM,IAAI,EAAE,CAAC,CAAC;YACjD,KAAK,GAAG,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YACnC,IAAI,IAAI,KAAK,eAAe;gBAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;iBAC9D,IAAI,CAAC,gBAAgB,CAAC,QAAQ,CAAC,IAAI,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,2BAA2B,CAAC,CAAC;YACnF,IAAI,SAAS;gBAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YAC7C,MAAM;QACR,CAAC;QACD,KAAK,QAAQ;YACX,2GAA2G;YAC3G,KAAK,GAAG,QAAQ,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,MAAM;QACR,KAAK,WAAW;YACd,KAAK,GAAG,cAAc,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC;YACtD,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,IAAI,KAAK,KAAK,KAAK;gBAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;YACnD,MAAM;QACR,KAAK,OAAO;YACV,KAAK,GAAG,QAAQ,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,MAAM;QACR,KAAK,MAAM;YACT,KAAK,GAAG,QAAQ,CAAC;YACjB,KAAK,CAAC,IAAI,CAAC,YAAY,EAAE,WAAW,CAAC,CAAC;YACtC,MAAM;QACR,OAAO,CAAC,CAAC,CAAC;YACR,KAAK,GAAG,KAAK,CAAC;YACd,KAAK,CAAC,IAAI,CAAC,YAAY,CAAC,CAAC;YACzB,MAAM,KAAK,GAAG,QAAQ,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC;YACpC,IAAI,KAAK,CAAC,UAAU,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;YACtE,IAAI,qCAAqC,CAAC,IAAI,CAAC,CAAC,CAAC,GAAG,IAAI,EAAE,CAAC;gBAAE,KAAK,CAAC,IAAI,CAAC,iBAAiB,CAAC,CAAC;QAC7F,CAAC;IACH,CAAC;IACD,IAAI,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,QAAQ,IAAI,IAAI,KAAK,KAAK,EAAE,CAAC;QACtF,KAAK,GAAG,MAAM,CAAC,KAAK,CAAC,CAAC;QACtB,KAAK,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;IAC/B,CAAC;IACD,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,CAAC,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,oBAAoB,CAAC,CAAC;IAChF,IAAI,CAAC,CAAC,OAAO,KAAK,SAAS,IAAI,IAAI,KAAK,QAAQ,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,wBAAwB,CAAC;QAAE,KAAK,CAAC,IAAI,CAAC,wBAAwB,CAAC,CAAC;IACpI,OAAO,EAAE,IAAI,EAAE,KAAK,EAAE,KAAK,EAAE,CAAC;AAChC,CAAC;AAED,sBAAsB;AAEtB,sFAAsF;AACtF,MAAM,UAAU,SAAS,CAAC,CAAS;IACjC,OAAO,CAAC;SACL,SAAS,CAAC,MAAM,CAAC;SACjB,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;SACrB,OAAO,CAAC,oBAAoB,EAAE,OAAO,CAAC;SACtC,WAAW,EAAE;SACb,OAAO,CAAC,aAAa,EAAE,GAAG,CAAC;SAC3B,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC;SACvB,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC;SACZ,OAAO,CAAC,MAAM,EAAE,EAAE,CAAC,CAAC;AACzB,CAAC;AAED,qGAAqG;AACrG,MAAM,UAAU,OAAO,CAAC,GAAuB;IAC7C,IAAI,GAAG,KAAK,SAAS,IAAI,GAAG,KAAK,EAAE;QAAE,OAAO,SAAS,CAAC;IACtD,IAAI,CAAC;QACH,OAAO,IAAI,GAAG,CAAC,GAAG,CAAC,CAAC,QAAQ,CAAC;IAC/B,CAAC;IAAC,MAAM,CAAC;QACP,MAAM,IAAI,GAAG,GAAG,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;QACzC,OAAO,IAAI,CAAC,UAAU,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,IAAI,EAAE,CAAC;IAClD,CAAC;AACH,CAAC;AAED,SAAS,QAAQ,CAAC,IAAY;IAC5B,IAAI,MAAM,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC,OAAO,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACxD,IAAI,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC;QAAE,OAAO,IAAI,CAAC;IACvC,OAAO,IAAI,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;AAChC,CAAC;AAED,8FAA8F;AAC9F,SAAS,UAAU,CAAC,KAAyB;IAC3C,OAAO,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,KAAK,EAAE,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,IAAI,CAAC,iCAAiC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,CAAC;AAClJ,CAAC;AAED,SAAS,SAAS,CAAC,KAAyB;IAC1C,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC;AACtE,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,aAAa,CAAC,IAAwB,EAAE,KAAyB,EAAE,WAAmB;IACpG,MAAM,IAAI,GAAG,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;IACvD,MAAM,IAAI,GAAG,SAAS,CAAC,KAAK,CAAC,CAAC;IAC9B,IAAI,IAAI,KAAK,EAAE;QAAE,OAAO,CAAC,IAAI,CAAC,QAAQ,CAAC,GAAG,CAAC,IAAI,IAAI,KAAK,SAAS,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,GAAG,IAAI,IAAI,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,CAAC;IACrH,MAAM,KAAK,GAAG,SAAS,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC;IACrD,OAAO,GAAG,KAAK,KAAK,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,IAAI,WAAW,EAAE,CAAC;AAC3D,CAAC;AAED,SAAS,UAAU,CAAC,GAAuB;IACzC,MAAM,IAAI,GAAG,CAAC,GAAG,IAAI,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,GAAG,EAAE,EAAE,IAAI,EAAE,IAAI,EAAE,CAAC;IACxD,OAAO,qBAAqB,CAAC,IAAI,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,IAAI,SAAS,CAAC;AAC3E,CAAC;AAED,SAAS,eAAe,CAAC,CAAmB;IAC1C,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,CAAC;IAC/B,IAAI,CAAC,CAAC,IAAI,IAAI,IAAI;QAAE,OAAO,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC,IAAI,EAAE,CAAC;IACnE,IAAI,CAAC,CAAC,KAAK;QAAE,OAAO,OAAO,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,KAAK,CAAC,QAAQ,CAAC;IAC3D,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,OAAO,CAAC,CAAC,IAAI,EAAE,CAAC;IACnC,IAAI,CAAC,CAAC,IAAI;QAAE,OAAO,yBAAyB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,IAAI,CAAC,MAAM,GAAG,EAAE,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,EAAE,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,EAAE,CAAC;IACtH,IAAI,CAAC,CAAC,MAAM;QAAE,OAAO,oBAAoB,CAAC,CAAC,UAAU,IAAI,aAAa,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;IACrG,OAAO,sBAAsB,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,GAAG,IAAI,GAAG,CAAC,EAAE,CAAC;AAC9D,CAAC;AAED,wFAAwF;AACxF,MAAM,UAAU,aAAa,CAAC,CAAmB,EAAE,KAAyB;IAC1E,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC;IACzC,IAAI,IAAI,KAAK,SAAS;QAAE,OAAO,GAAG,KAAK,IAAI,EAAE,IAAI,CAAC,CAAC,IAAI,IAAI,EAAE,IAAI,IAAI,EAAE,CAAC;IACxE,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS;QAAE,OAAO,GAAG,KAAK,IAAI,EAAE,WAAW,CAAC,CAAC,MAAM,EAAE,CAAC;IACvE,OAAO,GAAG,KAAK,IAAI,EAAE,QAAQ,CAAC,CAAC,GAAG,IAAI,EAAE,EAAE,CAAC;AAC7C,CAAC;AAED,SAAS,MAAM,CAAC,CAAmB,EAAE,KAAmC,EAAE,SAAiB,EAAE,MAAc,EAAE,OAAe,EAAE,KAAyB;IACrJ,MAAM,EAAE,GAAG,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,OAAO,KAAK,EAAE,CAAC;IACrD,MAAM,KAAK,GAAG,KAAK,CAAC,QAAQ,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,8DAA8D,CAAC,CAAC,CAAC,EAAE,CAAC;IACzH,IAAI,KAAK,CAAC,QAAQ,CAAC,2BAA2B,CAAC,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACvG,OAAO,OAAO,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,eAAe,CAAC,CAAC,UAAU,IAAI,GAAG,OAAO,OAAO,GAAG,EAAE,YAAY,CAAC,CAAC,UAAU,IAAI,GAAG,iDAAiD,CAAC;IAC3L,CAAC;IACD,IAAI,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,EAAE,CAAC;QACvD,OAAO,yBAAyB,CAAC,CAAC,UAAU,IAAI,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,OAAO,GAAG,EAAE,kBAAkB,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,EAAE,CAAC;IAClK,CAAC;IACD,OAAO,OAAO,SAAS,IAAI,IAAI,CAAC,SAAS,CAAC,MAAM,CAAC,OAAO,OAAO,GAAG,EAAE,GAAG,KAAK,EAAE,CAAC;AACjF,CAAC;AAED,SAAS,eAAe,CAAC,CAAmB,EAAE,KAAmC,EAAE,KAAyB,EAAE,SAAiB,EAAE,IAAwB,EAAE,UAA6B;IACtL,MAAM,IAAI,GAAG,CAAC,CAAC,IAAI,IAAI,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,IAAI,CAAC;IACzC,MAAM,MAAM,GAAG,aAAa,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,IAAI,CAAC,cAAc,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,UAAU,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;IAC9H,MAAM,OAAO,GAAG,eAAe,CAAC,CAAC,CAAC,CAAC;IACnC,OAAO;QACL,GAAG,EAAE,aAAa,CAAC,CAAC,EAAE,KAAK,CAAC;QAC5B,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;QACzC,GAAG,CAAC,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC;QACjD,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC;QACvC,OAAO;QACP,GAAG,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,IAAI,CAAC,MAAM,GAAG,GAAG,CAAC,CAAC,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,GAAG,CAAC,CAAC,CAAC,IAAI,EAAE,CAAC;QAC5F,SAAS;QACT,MAAM;QACN,GAAG,EAAE,MAAM,CAAC,CAAC,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,CAAC;QACxD,OAAO,EAAE,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;QACzC,WAAW,EAAE,CAAC,UAAU,CAAC;KAC1B,CAAC;AACJ,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,iBAAiB,CAAC,KAAkD;IAClF,MAAM,KAAK,GAAG,IAAI,GAAG,EAA6B,CAAC;IACnD,KAAK,MAAM,CAAC,IAAI,KAAK,CAAC,IAAI,EAAE,EAAE,CAAC;QAC7B,MAAM,IAAI,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC;QAC9B,IAAI,IAAI,KAAK,SAAS,EAAE,CAAC;YACvB,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE,CAAC,CAAC,CAAC;YACpB,SAAS;QACX,CAAC;QACD,MAAM,GAAG,GAAG,CAAC,GAAG,IAAI,CAAC,WAAW,CAAC,CAAC;QAClC,KAAK,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;YAC9B,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,CAAC,CAAC,SAAS,IAAI,CAAC,CAAC,KAAK,KAAK,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,MAAM,KAAK,CAAC,CAAC,MAAM,CAAC;gBAAE,GAAG,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QACjH,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,GAAG,EAAE;YACf,GAAG,IAAI;YACP,GAAG,CAAC,IAAI,CAAC,IAAI,KAAK,SAAS,IAAI,CAAC,CAAC,IAAI,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;YAC5E,OAAO,EAAE,CAAC,GAAG,IAAI,GAAG,CAAC,CAAC,GAAG,IAAI,CAAC,OAAO,EAAE,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC;YACtD,WAAW,EAAE,GAAG;SACjB,CAAC,CAAC;IACL,CAAC;IACD,uFAAuF;IACvF,OAAO,CAAC,GAAG,KAAK,CAAC,MAAM,EAAE,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,MAAM,GAAG,CAAC,CAAC,WAAW,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,aAAa,CAAC,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC;AACvH,CAAC;AAED,mBAAmB;AAEnB,SAAS,aAAa,CAAC,GAAc;IACnC,OAAO,GAAG,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,OAAO,CAAC,CAAC,CAAC,GAAG,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AACpG,CAAC;AAED,MAAM,UAAU,WAAW;IACzB,OAAO,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;AACxC,CAAC;AAED,6EAA6E;AAC7E,MAAM,UAAU,UAAU,CAAC,CAAwF;IACjH,MAAM,KAAK,GAAG,CAAC,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC;IACnC,IAAI,KAAK,KAAK,CAAC;QAAE,OAAO,0BAA0B,CAAC;IACnD,OAAO,GAAG,CAAC,CAAC,MAAM,IAAI,KAAK,8BAA8B,CAAC,CAAC,OAAO,kBAAkB,CAAC,CAAC,MAAM,CAAC,IAAI,aAAa,CAAC,CAAC,MAAM,CAAC,MAAM,UAAU,CAAC,CAAC,MAAM,CAAC,GAAG,GAAG,CAAC;AACzJ,CAAC;AAED;;;GAGG;AACH,MAAM,UAAU,gBAAgB,CAAC,GAAc,EAAE,IAAoB;IACnE,MAAM,SAAS,GAAG,IAAI,CAAC,gBAAgB,CAAC,CAAC,CAAC,IAAI,aAAa,CAAC;IAC5D,MAAM,UAAU,GAAG,IAAI,GAAG,CAAC,CAAC,IAAI,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IAC3E,MAAM,KAAK,GAA8B,EAAE,CAAC;IAC5C,MAAM,WAAW,GAAwB,EAAE,CAAC;IAC5C,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC9C,aAAa,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,EAAE,QAAQ,EAAE,KAAK,EAAE,EAAE,KAAK,EAAE,EAAE;QACxD,MAAM,CAAC,GAAG,UAAU,CAAC,QAAQ,CAAC,IAAI,CAAC,CAAC;QACpC,IAAI,CAAC,KAAK,IAAI;YAAE,OAAO;QACvB,MAAM,GAAG,GAAG,UAAU,CAAC,GAAG,CAAC,KAAK,CAAC,CAAC;QAClC,MAAM,CAAC,GAAG,cAAc,CAAC,CAAC,EAAE,IAAI,CAAC,gBAAgB,EAAE,GAAG,CAAC,CAAC;QACxD,MAAM,OAAO,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC;QACnC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;QACrB,MAAM,MAAM,GAAG,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,MAAM,CAAC;QAC9C,IAAI,GAAuB,CAAC;QAC5B,IAAI,OAAO,EAAE,CAAC;YACZ,MAAM,UAAU,GAAsB,EAAE,GAAG,CAAC,IAAI,CAAC,SAAS,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,IAAI,CAAC,SAAS,EAAE,CAAC,EAAE,KAAK,EAAE,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,CAAC;YACrK,MAAM,CAAC,GAAG,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,KAAK,EAAE,KAAK,EAAE,SAAS,EAAE,IAAI,CAAC,IAAI,EAAE,GAAG,CAAC,KAAK,CAAC,EAAE,UAAU,CAAC,CAAC;YAC3F,WAAW,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;YACpB,GAAG,GAAG,CAAC,CAAC,GAAG,CAAC;QACd,CAAC;QACD,KAAK,CAAC,IAAI,CAAC;YACT,GAAG,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC;YAC3C,KAAK;YACL,IAAI,EAAE,QAAQ,CAAC,IAAI,CAAC,IAAI;YACxB,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,SAAS,EAAE,OAAO,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,CAAC,QAAQ;YACzC,MAAM,EAAE,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,UAAU;YACnD,GAAG,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC;YACzC,OAAO,EAAE,eAAe,CAAC,CAAC,EAAE,CAAC,CAAC,IAAI,CAAC;YACnC,OAAO,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,WAAW,CAAC,CAAC,CAAC,CAAC;YAC3C,WAAW,EAAE,CAAC,CAAC,KAAK;YACpB,GAAG,CAAC,GAAG,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,UAAU,EAAE,GAAG,EAAE,CAAC;SAClD,CAAC,CAAC;IACL,CAAC,CAAC,CAAC;IACH,MAAM,MAAM,GAAG,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,MAAM,CAAC;IACpE,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,GAAG,MAAM,CAAC;IACtC,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,KAAK,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,iBAAiB,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;AAC1I,CAAC;AAED,uGAAuG;AACvG,MAAM,UAAU,aAAa,CAAC,OAAuC;IACnE,MAAM,MAAM,GAAG,EAAE,IAAI,EAAE,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,EAAE,CAAC,EAAE,CAAC;IAC9C,IAAI,MAAM,GAAG,CAAC,CAAC;IACf,IAAI,OAAO,GAAG,CAAC,CAAC;IAChB,KAAK,MAAM,CAAC,IAAI,OAAO,EAAE,CAAC;QACxB,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC;QACnB,OAAO,IAAI,CAAC,CAAC,OAAO,CAAC;QACrB,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,MAAM,CAAC,IAAI,CAAC;QAC7B,MAAM,CAAC,MAAM,IAAI,CAAC,CAAC,MAAM,CAAC,MAAM,CAAC;QACjC,MAAM,CAAC,GAAG,IAAI,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC;IAC7B,CAAC;IACD,OAAO,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,IAAI,EAAE,UAAU,CAAC,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,CAAC,EAAE,WAAW,EAAE,iBAAiB,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,WAAW,CAAC,CAAC,EAAE,CAAC;AACvJ,CAAC;AAED,eAAe;AAEf,6GAA6G;AAC7G,MAAM,UAAU,mBAAmB,CAAC,MAAsC,EAAE,eAAmC;IAC7G,OAAO,eAAe,KAAK,SAAS,IAAI,MAAM,CAAC,OAAO,GAAG,eAAe,CAAC;AAC3E,CAAC;AAyBD,SAAS,OAAO,CAAC,CAA8C;IAC7D,OAAO,CAAC,CAAC,MAAM,IAAI,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC;AACnC,CAAC;AAED,SAAS,KAAK,CAAC,CAAiB;IAC9B,OAAO,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC,GAAG,UAAU,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC;AAClH,CAAC;AAED;;;;GAIG;AACH,MAAM,UAAU,oBAAoB,CAAC,OAAgF,EAAE,QAAiF;IACtM,MAAM,MAAM,GAAG,IAAI,GAAG,CAAC,QAAQ,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,CAAC;IACnE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,MAAM,OAAO,GAAsE,EAAE,CAAC;IACtF,IAAI,SAAS,GAAG,CAAC,CAAC;IAClB,IAAI,KAAK,GAAG,CAAC,CAAC;IACd,MAAM,KAAK,GAAG,CAAC,CAAiB,EAAE,EAAE,CAAC,CAAC,EAAE,IAAI,EAAE,CAAC,CAAC,IAAI,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,IAAI,CAAC,CAAC,CAAC,SAAS,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,KAAK,CAAC,EAAE,SAAS,EAAE,CAAC,CAAC,SAAS,EAAE,CAAU,CAAC;IACxJ,KAAK,MAAM,CAAC,IAAI,OAAO,CAAC,KAAK,EAAE,CAAC;QAC9B,MAAM,GAAG,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC;QACvB,IAAI,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QACd,MAAM,CAAC,GAAG,MAAM,CAAC,GAAG,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,CAAC,KAAK,SAAS,EAAE,CAAC;YACpB,KAAK,EAAE,CAAC;YACR,SAAS;QACX,CAAC;QACD,MAAM,KAAK,GAAG,KAAK,CAAC,CAAC,CAAC,GAAG,KAAK,CAAC,CAAC,CAAC,CAAC;QAClC,IAAI,KAAK,KAAK,CAAC;YAAE,SAAS,EAAE,CAAC;;YACxB,OAAO,CAAC,IAAI,CAAC,EAAE,GAAG,EAAE,IAAI,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,KAAK,CAAC,CAAC,CAAC,EAAE,SAAS,EAAE,KAAK,GAAG,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC,CAAC,WAAW,EAAE,CAAC,CAAC;IAC5G,CAAC;IACD,MAAM,OAAO,GAAG,CAAC,GAAG,MAAM,CAAC,IAAI,EAAE,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,CAAC,MAAM,CAAC;IACtE,OAAO;QACL,QAAQ,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,UAAU,CAAC,CAAC,MAAM;QAClE,SAAS,EAAE,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,KAAK,WAAW,CAAC,CAAC,MAAM;QACpE,SAAS;QACT,KAAK;QACL,OAAO;QACP,YAAY,EAAE,OAAO,CAAC,OAAO,GAAG,QAAQ,CAAC,OAAO;QAChD,OAAO;KACR,CAAC;AACJ,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,SAAS,CAAC,CAAqB;IAC7C,MAAM,IAAI,GAAG,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,YAAY,EAAE,CAAC,CAAC,CAAC,MAAM,CAAC,CAAC,CAAC,YAAY,CAAC,CAAC;IAChF,OAAO,sBAAsB,CAAC,CAAC,QAAQ,cAAc,CAAC,CAAC,SAAS,uBAAuB,IAAI,GAAG,CAAC;AACjG,CAAC;AAYD,8FAA8F;AAC9F,MAAM,UAAU,aAAa,CAAC,CAAgG,EAAE,GAAG,GAAG,CAAC;IACrI,OAAO;QACL,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,OAAO,EAAE,CAAC,CAAC,OAAO;QAClB,MAAM,EAAE,CAAC,CAAC,MAAM;QAChB,IAAI,EAAE,CAAC,CAAC,IAAI;QACZ,KAAK,EAAE,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACzB,GAAG,CAAC,CAAC,CAAC,MAAM,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,CAAC,MAAM,EAAE,CAAC;YACvD,KAAK,EAAE,CAAC,CAAC,KAAK;YACd,IAAI,EAAE,CAAC,CAAC,IAAI;YACZ,SAAS,EAAE,CAAC,CAAC,SAAS;YACtB,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC;SAC5C,CAAC,CAAC;QACH,WAAW,EAAE,CAAC,CAAC,WAAW,CAAC,KAAK,CAAC,CAAC,EAAE,GAAG,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC;YACnD,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,EAAE,CAAC,CAAC,GAAG;YACV,OAAO,EAAE,CAAC,CAAC,OAAO;YAClB,GAAG,CAAC,CAAC,CAAC,KAAK,KAAK,SAAS,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,EAAE,CAAC,CAAC,KAAK,EAAE,CAAC;YACpD,KAAK,EAAE,CAAC,CAAC,WAAW,CAAC,MAAM;SAC5B,CAAC,CAAC;KACJ,CAAC;AACJ,CAAC"}
|
package/dist/login-cli.d.ts
CHANGED
|
@@ -6,6 +6,8 @@ export interface LoginResult {
|
|
|
6
6
|
/** Absolute path of the saved storage state (mode 0600). */
|
|
7
7
|
readonly saved: string;
|
|
8
8
|
readonly loginUrl: string;
|
|
9
|
+
/** #449: `form` (a sign-in page driven) or `api` (an HTTP endpoint POSTed to). */
|
|
10
|
+
readonly method: "form" | "api";
|
|
9
11
|
/** Where the sign-in ended (token-like query values redacted). */
|
|
10
12
|
readonly landedUrl: string;
|
|
11
13
|
readonly userEnv: string;
|
package/dist/login-cli.js
CHANGED
|
@@ -5,12 +5,12 @@ import { fail, ok } from "./envelope.js";
|
|
|
5
5
|
import { emitCommandResult } from "./cli-shared.js";
|
|
6
6
|
import { positiveIntArg } from "./cli-args.js";
|
|
7
7
|
import { loadPersonasFile, MultiRunArgsError, projectPersonas } from "./multi-run.js";
|
|
8
|
-
import { checkSaveTarget, LoginArgsError, LoginFailedError, loginFromFlags, mintStorageState } from "./persona-login.js";
|
|
8
|
+
import { apiVerifyUrl, checkSaveTarget, LoginArgsError, LoginFailedError, loginFromFlags, mintStorageState, parseAuthCheck } from "./persona-login.js";
|
|
9
9
|
const DEFAULT_TIMEOUT_S = 30;
|
|
10
10
|
const PERSONA_NAME = /^[A-Za-z0-9][A-Za-z0-9_.-]{0,63}$/;
|
|
11
11
|
function formatLoginHuman(data) {
|
|
12
12
|
const r = data;
|
|
13
|
-
return `signed in${r.persona === undefined ? "" : ` as persona ${r.persona}`} (${r.userEnv}/${r.passwordEnv}) — storage state saved to ${r.saved} (mode 0600)\n`;
|
|
13
|
+
return `signed in${r.persona === undefined ? "" : ` as persona ${r.persona}`}${r.method === "api" ? " through the API" : ""} (${r.userEnv}/${r.passwordEnv}) — storage state saved to ${r.saved} (mode 0600)\n`;
|
|
14
14
|
}
|
|
15
15
|
/** The persona's declared login parameters and session, from `--personas` or the project's `.jevitate/personas.json`. */
|
|
16
16
|
function declaredPersona(name, personasFile) {
|
|
@@ -25,6 +25,14 @@ export function registerLoginCommand(program, deps) {
|
|
|
25
25
|
.option("--persona <name>", "the persona being signed in (names it in the result); with a declared persona (--personas or .jevitate/personas.json) its login parameters and storage state path are the defaults")
|
|
26
26
|
.option("--personas <file>", "personas JSON to read --persona's login parameters from (default: the project's .jevitate/personas.json)")
|
|
27
27
|
.option("--url <loginUrl>", "the sign-in page (must be an authorized origin: its own, or --allow)")
|
|
28
|
+
.option("--api <url>", "#449: sign in through this HTTP endpoint instead of a form: the credentials are POSTed as JSON (must be an authorized origin; redirects are never followed)")
|
|
29
|
+
.option("--api-user-key <key>", "with --api: the JSON body key the username is sent under (default username)")
|
|
30
|
+
.option("--api-password-key <key>", "with --api: the JSON body key the password is sent under (default password)")
|
|
31
|
+
.option("--token-path <path>", "with --api: a dotted path into the JSON response whose value is the session token (e.g. token, data.accessToken); without it the response's cookies are the session")
|
|
32
|
+
.option("--storage-key <key>", "with --token-path: the localStorage key the token is written under (default: the path's last segment)")
|
|
33
|
+
.option("--storage <where>", "with --token-path: local (the only choice — a Playwright storage state has no sessionStorage)")
|
|
34
|
+
.option("--verify-url <url>", "with --api: the app page the new session is proven on, and whose origin receives the token (default: the endpoint's origin root)")
|
|
35
|
+
.option("--auth-check <check>", "with --api: how --verify-url proves the session: off | auto | urlExcludes:<text> | selector:<css> (default auto)")
|
|
28
36
|
.option("--user-env <VAR>", "environment variable holding the username (its NAME — the value is read from the environment)")
|
|
29
37
|
.option("--password-env <VAR>", "environment variable holding the password (its NAME — the value is read from the environment)")
|
|
30
38
|
.option("--user-field <field>", "the username field: its label, else a CSS selector (default: found by autocomplete/type/name)")
|
|
@@ -41,6 +49,7 @@ export function registerLoginCommand(program, deps) {
|
|
|
41
49
|
let login;
|
|
42
50
|
let save;
|
|
43
51
|
let warnings;
|
|
52
|
+
let authCheck;
|
|
44
53
|
try {
|
|
45
54
|
if (o.persona !== undefined && !PERSONA_NAME.test(o.persona)) {
|
|
46
55
|
throw new LoginArgsError(`--persona ${JSON.stringify(o.persona)} must be 1-64 of [A-Za-z0-9_.-], starting alphanumeric`);
|
|
@@ -51,22 +60,55 @@ export function registerLoginCommand(program, deps) {
|
|
|
51
60
|
if (o.personas !== undefined && declared === undefined)
|
|
52
61
|
throw new LoginArgsError(`persona ${o.persona} is not declared in ${o.personas}`);
|
|
53
62
|
const base = declared?.login;
|
|
54
|
-
const
|
|
63
|
+
const apiFlags = [
|
|
64
|
+
["--api-user-key", o.apiUserKey],
|
|
65
|
+
["--api-password-key", o.apiPasswordKey],
|
|
66
|
+
["--token-path", o.tokenPath],
|
|
67
|
+
["--storage-key", o.storageKey],
|
|
68
|
+
["--storage", o.storage],
|
|
69
|
+
["--verify-url", o.verifyUrl],
|
|
70
|
+
["--auth-check", o.authCheck],
|
|
71
|
+
]
|
|
72
|
+
.filter(([, v]) => v !== undefined)
|
|
73
|
+
.map(([k]) => k);
|
|
74
|
+
if (o.api !== undefined && o.url !== undefined)
|
|
75
|
+
throw new LoginArgsError("--api and --url are two ways to sign in: pass one");
|
|
76
|
+
const viaApi = o.api !== undefined || (o.url === undefined && base?.api !== undefined);
|
|
77
|
+
if (!viaApi && apiFlags.length > 0)
|
|
78
|
+
throw new LoginArgsError(`${apiFlags.join(", ")} ${apiFlags.length === 1 ? "applies" : "apply"} to a sign-in through an HTTP endpoint: pass --api <url> too`);
|
|
79
|
+
authCheck = parseAuthCheck(o.authCheck);
|
|
80
|
+
const url = viaApi ? undefined : (o.url ?? base?.url);
|
|
81
|
+
const apiUrl = viaApi ? (o.api ?? base?.api?.url) : undefined;
|
|
55
82
|
const userEnv = o.userEnv ?? base?.userEnv;
|
|
56
83
|
const passwordEnv = o.passwordEnv ?? base?.passwordEnv;
|
|
57
84
|
const target = o.save ?? declared?.storageState;
|
|
58
|
-
const missing = [url === undefined ? "--url" : null, userEnv === undefined ? "--user-env" : null, passwordEnv === undefined ? "--password-env" : null, target === undefined ? "--save" : null].filter((m) => m !== null);
|
|
85
|
+
const missing = [url === undefined && apiUrl === undefined ? "--url (or --api)" : null, userEnv === undefined ? "--user-env" : null, passwordEnv === undefined ? "--password-env" : null, target === undefined ? "--save" : null].filter((m) => m !== null);
|
|
59
86
|
if (missing.length > 0) {
|
|
60
87
|
throw new LoginArgsError(`missing ${missing.join(", ")}${o.persona === undefined ? "" : ` (persona ${o.persona} declares no login parameters for ${missing.length === 1 ? "it" : "them"})`}`);
|
|
61
88
|
}
|
|
89
|
+
const b = base?.api;
|
|
62
90
|
login = loginFromFlags({
|
|
63
|
-
url: url,
|
|
91
|
+
...(url === undefined ? {} : { url }),
|
|
92
|
+
...(apiUrl === undefined
|
|
93
|
+
? {}
|
|
94
|
+
: {
|
|
95
|
+
api: {
|
|
96
|
+
url: apiUrl,
|
|
97
|
+
userKey: o.apiUserKey ?? b?.userKey,
|
|
98
|
+
passwordKey: o.apiPasswordKey ?? b?.passwordKey,
|
|
99
|
+
tokenPath: o.tokenPath ?? b?.tokenPath,
|
|
100
|
+
// A declared storage key belongs to the declared token path: a --token-path flag takes its own default.
|
|
101
|
+
storageKey: o.storageKey ?? (o.tokenPath === undefined ? b?.storageKey : undefined),
|
|
102
|
+
storage: o.storage,
|
|
103
|
+
verifyUrl: o.verifyUrl ?? b?.verifyUrl,
|
|
104
|
+
},
|
|
105
|
+
}),
|
|
64
106
|
userEnv: userEnv,
|
|
65
107
|
passwordEnv: passwordEnv,
|
|
66
|
-
...pick("userField", o.userField ?? base?.userField),
|
|
67
|
-
...pick("passwordField", o.passwordField ?? base?.passwordField),
|
|
68
|
-
...pick("submit", o.submit ?? base?.submit),
|
|
69
|
-
...pick("success", o.success ?? base?.success),
|
|
108
|
+
...pick("userField", o.userField ?? (viaApi ? undefined : base?.userField)),
|
|
109
|
+
...pick("passwordField", o.passwordField ?? (viaApi ? undefined : base?.passwordField)),
|
|
110
|
+
...pick("submit", o.submit ?? (viaApi ? undefined : base?.submit)),
|
|
111
|
+
...pick("success", o.success ?? (viaApi ? undefined : base?.success)),
|
|
70
112
|
});
|
|
71
113
|
({ path: save, warnings } = checkSaveTarget(target, "--save"));
|
|
72
114
|
}
|
|
@@ -77,7 +119,8 @@ export function registerLoginCommand(program, deps) {
|
|
|
77
119
|
}
|
|
78
120
|
throw err;
|
|
79
121
|
}
|
|
80
|
-
const
|
|
122
|
+
const loginUrl = login.api?.url ?? login.url;
|
|
123
|
+
const allowlist = o.allow.length > 0 ? normalizeAllowlist(o.allow) : normalizeAllowlist([loginUrl]);
|
|
81
124
|
for (const w of warnings)
|
|
82
125
|
program.configureOutput().writeErr?.(`warning: ${w}\n`);
|
|
83
126
|
try {
|
|
@@ -88,11 +131,13 @@ export function registerLoginCommand(program, deps) {
|
|
|
88
131
|
env: deps.explore?.env ?? process.env,
|
|
89
132
|
port: (deps.explore?.browserPortFactory ?? (() => new PlaywrightBrowserPort()))(),
|
|
90
133
|
timeoutMs: (o.timeout ?? DEFAULT_TIMEOUT_S) * 1000,
|
|
134
|
+
...(login.api === undefined ? {} : { verify: { url: apiVerifyUrl(login.api), check: authCheck } }),
|
|
91
135
|
});
|
|
92
136
|
const result = {
|
|
93
137
|
...(o.persona === undefined ? {} : { persona: o.persona }),
|
|
94
138
|
saved: minted.saved,
|
|
95
|
-
loginUrl: redactUrl(
|
|
139
|
+
loginUrl: redactUrl(loginUrl),
|
|
140
|
+
method: login.api === undefined ? "form" : "api",
|
|
96
141
|
landedUrl: minted.landedUrl,
|
|
97
142
|
userEnv: login.userEnv,
|
|
98
143
|
passwordEnv: login.passwordEnv,
|
package/dist/login-cli.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"login-cli.js","sourceRoot":"","sources":["../src/login-cli.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,kBAAkB,EAAE,MAAM,mBAAmB,CAAC;AACvD,OAAO,EAAE,qBAAqB,EAAE,MAAM,sBAAsB,CAAC;AAC7D,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,MAAM,eAAe,CAAC;AACzC,OAAO,EAAE,iBAAiB,EAAgB,MAAM,iBAAiB,CAAC;AAClE,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,eAAe,EAAgB,MAAM,gBAAgB,CAAC;AACpG,OAAO,EAAE,eAAe,EAAE,cAAc,EAAE,gBAAgB,EAAE,cAAc,EAAE,gBAAgB,
|
|
1
|
+
{"version":3,"file":"login-cli.js","sourceRoot":"","sources":["../src/login-cli.ts"],"names":[],"mappings":"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"}
|
package/dist/mcp-api.d.ts
CHANGED
|
@@ -2,7 +2,7 @@ import { Server } from "@modelcontextprotocol/sdk/server/index.js";
|
|
|
2
2
|
import { type AiGenerateTextArgs, type AiGenerateTextResult } from "@jevitate/mcp-facade";
|
|
3
3
|
import { type CredentialStore, type GenerationPort, type SetupRequiredResult } from "@jevitate/ai-core";
|
|
4
4
|
import type { JudgmentPort, UsageTracker } from "@jevitate/ai-core";
|
|
5
|
-
import type { SelfHealer } from "@jevitate/runtime";
|
|
5
|
+
import type { ChangeScope, SelfHealer } from "@jevitate/runtime";
|
|
6
6
|
import type { EmulationSpec } from "@jevitate/playwright";
|
|
7
7
|
import { type RunPolicy } from "@jevitate/domain";
|
|
8
8
|
import { type RunVerifyFixOptions, type VerifyFixReport } from "./verify-fix-api.js";
|
|
@@ -46,6 +46,10 @@ export interface McpTool {
|
|
|
46
46
|
export interface McpJourneyRunOptions {
|
|
47
47
|
readonly policy?: RunPolicy;
|
|
48
48
|
readonly selfHealer?: SelfHealer;
|
|
49
|
+
/** #453: the change context a hybrid/full self-heal is explained by (`changes`/`changeNote`). */
|
|
50
|
+
readonly heal?: {
|
|
51
|
+
readonly scope: ChangeScope;
|
|
52
|
+
};
|
|
49
53
|
readonly environment?: ResolvedJourneyEnvironment;
|
|
50
54
|
readonly browser?: BrowserRunOptions;
|
|
51
55
|
readonly emulation?: EmulationSpec;
|