@sackville-mcp/cli 0.0.1-alpha.3 → 0.0.1-alpha.5
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/bin.mjs +1 -1
- package/dist/index.mjs +1 -1
- package/dist/{src-DM4aqvlX.mjs → src-BbMlgjP6.mjs} +64 -70
- package/dist/src-BbMlgjP6.mjs.map +1 -0
- package/package.json +14 -14
- package/dist/src-DM4aqvlX.mjs.map +0 -1
package/dist/bin.mjs
CHANGED
package/dist/index.mjs
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { t as run } from "./src-
|
|
1
|
+
import { t as run } from "./src-BbMlgjP6.mjs";
|
|
2
2
|
export { run };
|
|
@@ -5,10 +5,10 @@ import { dirname, join, resolve } from "node:path";
|
|
|
5
5
|
import { pathToFileURL } from "node:url";
|
|
6
6
|
import { ArtifactStore, Redactor, importToCollection, isGraphqlEnvelope, loadCollection, resolveSecretStore, runRequest, runRequestForContract, runRequestToHar, runSequence, validateCapturedTraffic, validateGraphqlOperation, validateOpenApiRequest, validateOpenApiResponse } from "@sackville-mcp/api";
|
|
7
7
|
import { tmpdir } from "node:os";
|
|
8
|
-
import { ArtifactStore as ArtifactStore$1,
|
|
9
|
-
import { Redactor as Redactor$1, resolveAndPin } from "@sackville-mcp/safety";
|
|
8
|
+
import { ArtifactStore as ArtifactStore$1, PageDriver, auditA11y, browserSecretsFromEnv, buildCaptureRuntime, driveBrowserFlowToHar, loadFlow, resolveEngine, runFlow } from "@sackville-mcp/browser";
|
|
10
9
|
import { CoverageGateError, coveragePyToIstanbul, runScoped, runScopedPython, uncoveredInDiff } from "@sackville-mcp/coverage";
|
|
11
10
|
import { CHANGELOG_FILENAMES, auditDependency, changedDependencies, comparatorFor, dependencyNames, gemRepoUrl, githubOwnerRepo, loadOsvSnapshot, matchName, normalizePypiName, npmRepoUrl, pypiJsonToPackument, pypiRepoUrl, rubygemsToPackument, sliceChangelog } from "@sackville-mcp/deps";
|
|
11
|
+
import { Redactor as Redactor$1, resolveAndPin } from "@sackville-mcp/safety";
|
|
12
12
|
import { FlakeGateError, HistoryStore, Quarantine, QuarantineGateError, quarantineCandidates, runAndRecord, runAndRecordPytest } from "@sackville-mcp/flake";
|
|
13
13
|
import { LanguageServerManager, LspGateError, LspQueryEngine, LspRenameEngine, defaultListFiles, parseServerRegistry } from "@sackville-mcp/lsp";
|
|
14
14
|
import { MutateGateError, parseMutmutResults, runCosmicRay, runMutation, runMutmut, summarizeMutation } from "@sackville-mcp/mutate";
|
|
@@ -568,16 +568,6 @@ function flagsFrom(values) {
|
|
|
568
568
|
engine: resolveEngine(values.engine)
|
|
569
569
|
};
|
|
570
570
|
}
|
|
571
|
-
/** Launch thunk for a `BrowserManager`, honoring the selected engine + the
|
|
572
|
-
* mandatory SSRF proxy (chromium gets the hardening args; firefox/webkit get the
|
|
573
|
-
* proxy + the Tier-1 route allowlist). */
|
|
574
|
-
function launchFor(flags, proxyUrl) {
|
|
575
|
-
return engineLauncher(flags.engine, {
|
|
576
|
-
headless: !flags.headed,
|
|
577
|
-
proxyServer: proxyUrl,
|
|
578
|
-
noSandbox: flags.noSandbox
|
|
579
|
-
});
|
|
580
|
-
}
|
|
581
571
|
/**
|
|
582
572
|
* Stand up a gated, proxy-fronted browser, navigate to `url`, run `fn`, and tear
|
|
583
573
|
* everything down. Returns `undefined` for a bad URL (after reporting it).
|
|
@@ -590,19 +580,20 @@ async function withSession(url, flags, io, fn) {
|
|
|
590
580
|
io.err(`invalid url: ${url}\n`);
|
|
591
581
|
return 1;
|
|
592
582
|
}
|
|
593
|
-
const
|
|
594
|
-
|
|
595
|
-
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
583
|
+
const runtime = await buildCaptureRuntime({
|
|
584
|
+
allowedHosts: [host, ...flags.allowHost],
|
|
585
|
+
allowPrivate: flags.allowPrivate,
|
|
586
|
+
engine: flags.engine,
|
|
587
|
+
headless: !flags.headed,
|
|
588
|
+
noSandbox: flags.noSandbox
|
|
599
589
|
});
|
|
590
|
+
const store = new ArtifactStore$1(mkdtempSync(join(tmpdir(), "sackville-browser-cli-")));
|
|
600
591
|
try {
|
|
601
|
-
const page = await (await manager.createSession("cli")).newPage();
|
|
592
|
+
const page = await (await runtime.manager.createSession("cli")).newPage();
|
|
602
593
|
const driver = new PageDriver(page, {
|
|
603
594
|
runId: "cli",
|
|
604
595
|
store,
|
|
605
|
-
gate
|
|
596
|
+
gate: runtime.gate
|
|
606
597
|
});
|
|
607
598
|
await driver.navigate(url);
|
|
608
599
|
return await fn({
|
|
@@ -614,8 +605,7 @@ async function withSession(url, flags, io, fn) {
|
|
|
614
605
|
io.err(`${err.message}\n`);
|
|
615
606
|
return 1;
|
|
616
607
|
} finally {
|
|
617
|
-
await
|
|
618
|
-
await proxy.close();
|
|
608
|
+
await runtime.shutdown();
|
|
619
609
|
}
|
|
620
610
|
}
|
|
621
611
|
async function runBrowser(args, io) {
|
|
@@ -679,36 +669,28 @@ async function cmdRun$2(args, io) {
|
|
|
679
669
|
io.err(`${err.message}\n`);
|
|
680
670
|
return 1;
|
|
681
671
|
}
|
|
682
|
-
const
|
|
683
|
-
const redactor = new Redactor$1();
|
|
684
|
-
const secrets = /* @__PURE__ */ new Map();
|
|
685
|
-
for (const [key, val] of Object.entries(env)) {
|
|
686
|
-
const m = /^SACKVILLE_BROWSER_SECRET_(.+)$/.exec(key);
|
|
687
|
-
if (m?.[1] && val) {
|
|
688
|
-
redactor.register(m[1], val);
|
|
689
|
-
secrets.set(m[1], val);
|
|
690
|
-
}
|
|
691
|
-
}
|
|
672
|
+
const { redact, resolveSecret } = browserSecretsFromEnv(io.env ?? {});
|
|
692
673
|
const flags = flagsFrom(values);
|
|
693
|
-
const
|
|
674
|
+
const runtime = await buildCaptureRuntime({
|
|
675
|
+
allowedHosts: flags.allowHost,
|
|
694
676
|
allowUnsafe: values.unsafe ?? false,
|
|
695
|
-
|
|
677
|
+
allowPrivate: flags.allowPrivate,
|
|
678
|
+
engine: flags.engine,
|
|
679
|
+
headless: !flags.headed,
|
|
680
|
+
noSandbox: flags.noSandbox,
|
|
681
|
+
redact,
|
|
682
|
+
resolveSecret
|
|
696
683
|
});
|
|
697
|
-
const proxy = await createSsrfProxy({ allowPrivate: flags.allowPrivate });
|
|
698
684
|
const store = new ArtifactStore$1(mkdtempSync(join(tmpdir(), "sackville-browser-flow-")));
|
|
699
|
-
const manager = new BrowserManager({
|
|
700
|
-
gate,
|
|
701
|
-
launch: launchFor(flags, proxy.url)
|
|
702
|
-
});
|
|
703
685
|
try {
|
|
704
|
-
const result = await runFlow(new PageDriver(await (await manager.createSession("cli")).newPage(), {
|
|
686
|
+
const result = await runFlow(new PageDriver(await (await runtime.manager.createSession("cli")).newPage(), {
|
|
705
687
|
runId: "cli",
|
|
706
688
|
store,
|
|
707
|
-
gate,
|
|
708
|
-
redact:
|
|
689
|
+
gate: runtime.gate,
|
|
690
|
+
redact: runtime.redact
|
|
709
691
|
}), flow, {
|
|
710
692
|
vars: parseVars$1(values.var),
|
|
711
|
-
resolveSecret:
|
|
693
|
+
resolveSecret: runtime.resolveSecret
|
|
712
694
|
});
|
|
713
695
|
if (values.json) io.out(`${JSON.stringify(result, null, 2)}\n`);
|
|
714
696
|
else printFlowResult(result, io);
|
|
@@ -717,8 +699,7 @@ async function cmdRun$2(args, io) {
|
|
|
717
699
|
io.err(`${err.message}\n`);
|
|
718
700
|
return 1;
|
|
719
701
|
} finally {
|
|
720
|
-
await
|
|
721
|
-
await proxy.close();
|
|
702
|
+
await runtime.shutdown();
|
|
722
703
|
}
|
|
723
704
|
}
|
|
724
705
|
function printFlowResult(result, io) {
|
|
@@ -1505,6 +1486,7 @@ async function cmdRun$1(store, args, io, deps) {
|
|
|
1505
1486
|
type: "string",
|
|
1506
1487
|
multiple: true
|
|
1507
1488
|
},
|
|
1489
|
+
related: { type: "boolean" },
|
|
1508
1490
|
"run-group": { type: "string" },
|
|
1509
1491
|
"allow-run": { type: "boolean" },
|
|
1510
1492
|
"timeout-ms": { type: "string" },
|
|
@@ -1530,6 +1512,7 @@ async function cmdRun$1(store, args, io, deps) {
|
|
|
1530
1512
|
}, {
|
|
1531
1513
|
repeat: num$2(values.repeat) ?? 1,
|
|
1532
1514
|
files: values.file,
|
|
1515
|
+
related: values.related,
|
|
1533
1516
|
runGroup: values["run-group"]
|
|
1534
1517
|
}, { runner: deps.runner });
|
|
1535
1518
|
if (values.json) {
|
|
@@ -2281,7 +2264,10 @@ async function cmdVerifyRun(args, io, deps) {
|
|
|
2281
2264
|
allowedRoots,
|
|
2282
2265
|
allowRun,
|
|
2283
2266
|
timeoutMs
|
|
2284
|
-
}, {
|
|
2267
|
+
}, {
|
|
2268
|
+
files: changedFiles,
|
|
2269
|
+
related: changedFiles.length > 0
|
|
2270
|
+
}, { runner: deps.flakeRunner })).verdicts;
|
|
2285
2271
|
} finally {
|
|
2286
2272
|
if (!deps.historyStore && dbPath) store.close();
|
|
2287
2273
|
}
|
|
@@ -2415,32 +2401,40 @@ function readCaptureContract(values) {
|
|
|
2415
2401
|
};
|
|
2416
2402
|
return contract;
|
|
2417
2403
|
}
|
|
2418
|
-
/**
|
|
2419
|
-
*
|
|
2420
|
-
|
|
2421
|
-
|
|
2422
|
-
|
|
2423
|
-
|
|
2424
|
-
|
|
2425
|
-
|
|
2426
|
-
harDir,
|
|
2427
|
-
launch: engineLauncher(resolveEngine(values.engine), {
|
|
2428
|
-
headless: !values.headed,
|
|
2429
|
-
proxyServer: proxy.url,
|
|
2430
|
-
noSandbox: values["no-sandbox"] ?? false
|
|
2431
|
-
})
|
|
2432
|
-
});
|
|
2404
|
+
/**
|
|
2405
|
+
* BrowserGate options for the `--flow` capture path, from the parsed CLI flags.
|
|
2406
|
+
* Exported for testing: a flow with `fill`/`click` steps is a MUTATION, so it
|
|
2407
|
+
* needs `--allow-unsafe` — without it every interaction dry-runs and the
|
|
2408
|
+
* flow-completeness guard fails the capture (the human typing the flag is the
|
|
2409
|
+
* operator, exactly as `sackville browser run --unsafe`).
|
|
2410
|
+
*/
|
|
2411
|
+
function captureGateOptionsFromFlags(values) {
|
|
2433
2412
|
return {
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
redact: (s) => s,
|
|
2437
|
-
config: { harDir },
|
|
2438
|
-
shutdown: async () => {
|
|
2439
|
-
await manager.shutdown();
|
|
2440
|
-
await proxy.close();
|
|
2441
|
-
}
|
|
2413
|
+
allowedHosts: values["allow-host"] ?? [],
|
|
2414
|
+
allowUnsafe: values["allow-unsafe"] ?? false
|
|
2442
2415
|
};
|
|
2443
2416
|
}
|
|
2417
|
+
/**
|
|
2418
|
+
* Build the `--flow` capture runtime from the CLI's browser egress flags. A thin
|
|
2419
|
+
* adapter over the shared `@sackville-mcp/browser` `buildCaptureRuntime` (one source
|
|
2420
|
+
* of truth across the browser CLI, this path, and the MCP server) — flags map to
|
|
2421
|
+
* the gate/proxy/engine options, `{{secret:NAME}}` resolves from
|
|
2422
|
+
* `SACKVILLE_BROWSER_SECRET_*` via the shared `browserSecretsFromEnv`, and a fresh
|
|
2423
|
+
* temp dir arms HAR recording for `driveBrowserFlowToHar`.
|
|
2424
|
+
*/
|
|
2425
|
+
async function captureRuntimeFromFlags(values) {
|
|
2426
|
+
const { redact, resolveSecret } = browserSecretsFromEnv(process.env);
|
|
2427
|
+
return buildCaptureRuntime({
|
|
2428
|
+
...captureGateOptionsFromFlags(values),
|
|
2429
|
+
allowPrivate: values["allow-private"] ?? false,
|
|
2430
|
+
engine: values.engine,
|
|
2431
|
+
headless: !values.headed,
|
|
2432
|
+
noSandbox: values["no-sandbox"] ?? false,
|
|
2433
|
+
harDir: mkdtempSync(join(tmpdir(), "sackville-verify-har-")),
|
|
2434
|
+
redact,
|
|
2435
|
+
resolveSecret
|
|
2436
|
+
});
|
|
2437
|
+
}
|
|
2444
2438
|
function runVerifyCompose(args, io) {
|
|
2445
2439
|
const { values } = parseArgs({
|
|
2446
2440
|
args,
|
|
@@ -2749,4 +2743,4 @@ function cmdDetect(args, io) {
|
|
|
2749
2743
|
//#endregion
|
|
2750
2744
|
export { run as t };
|
|
2751
2745
|
|
|
2752
|
-
//# sourceMappingURL=src-
|
|
2746
|
+
//# sourceMappingURL=src-BbMlgjP6.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"src-BbMlgjP6.mjs","names":["parseVars","cmdGet","cmdRun","ArtifactStore","cmdAudit","cmdRun","parseVars","cmdRun","num","printVerdict","num","ArtifactStore","Redactor"],"sources":["../src/api.ts","../src/browser.ts","../src/coverage.ts","../src/deps.ts","../src/flake.ts","../src/lsp.ts","../src/mutate.ts","../src/verify.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { parseArgs } from 'node:util'\nimport {\n ArtifactStore,\n type ContractRequestCapture,\n type ContractResult,\n type ImportFormat,\n importToCollection,\n isGraphqlEnvelope,\n loadCollection,\n Redactor,\n type RunResult,\n resolveSecretStore,\n runRequest,\n runRequestForContract,\n runSequence,\n type ScalarCoercer,\n type SecretStore,\n validateCapturedTraffic,\n validateGraphqlOperation,\n validateOpenApiRequest,\n validateOpenApiResponse,\n} from '@sackville-mcp/api'\nimport type { CliIO } from './index.js'\n\n/**\n * Load an operator-supplied custom-scalar coercer module (ADR 0018 slice 6). The human is the\n * operator, so a real module path is permitted. Returns the coercer record, or `undefined` on\n * ANY failure (missing/throwing module, or a non-object default export) AFTER writing a loud\n * error — the caller MUST then exit non-zero, never silently fall back to no coercers (which\n * would look clean — an absence-laundering hazard).\n */\nasync function loadCoercers(\n file: string,\n io: CliIO,\n): Promise<Record<string, ScalarCoercer> | undefined> {\n let exported: unknown\n try {\n const mod = (await import(pathToFileURL(resolve(file)).href)) as { default?: unknown }\n exported = mod.default\n } catch (err) {\n io.err(`api: failed to load --coercers module ${file}: ${(err as Error).message}\\n`)\n return undefined\n }\n if (!exported || typeof exported !== 'object') {\n io.err(`api: --coercers module ${file} must default-export an object of scalar coercers\\n`)\n return undefined\n }\n return exported as Record<string, ScalarCoercer>\n}\n\n/** Matches `{{secret:NAME}}` references; captures the NAME only (never a value). */\nconst SECRET_RE = /\\{\\{\\s*secret:\\s*([^}\\s]+)\\s*\\}\\}/g\n\n/** Collect sorted, unique secret NAMES referenced anywhere in a string. */\nfunction secretNames(...sources: (string | undefined)[]): string[] {\n const names = new Set<string>()\n for (const s of sources) {\n if (!s) continue\n for (const m of s.matchAll(SECRET_RE)) {\n if (m[1]) names.add(m[1])\n }\n }\n return [...names].sort()\n}\n\n/** Replace `{{secret:NAME}}` references with a `[secret:NAME]` placeholder. */\nfunction maskSecrets(s: string): string {\n return s.replace(SECRET_RE, (_m, name) => `[secret:${name}]`)\n}\n\n/** Parse repeatable `--var k=v` flags (split on the FIRST `=`) into a record. */\nfunction parseVars(raw: string[] | undefined): Record<string, unknown> {\n const vars: Record<string, unknown> = {}\n for (const item of raw ?? []) {\n const eq = item.indexOf('=')\n if (eq === -1) {\n vars[item] = ''\n } else {\n vars[item.slice(0, eq)] = item.slice(eq + 1)\n }\n }\n return vars\n}\n\nexport async function runApi(args: string[], io: CliIO): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'list':\n return cmdList(rest, io)\n case 'get':\n return cmdGet(rest, io)\n case 'run':\n return cmdRun(rest, io)\n case 'run-collection':\n return cmdRunCollection(rest, io)\n case 'validate':\n return await cmdValidate(rest, io)\n case 'validate-request':\n return cmdValidateRequest(rest, io)\n case 'validate-capture':\n return cmdValidateCapture(rest, io)\n case 'import':\n return cmdImport(rest, io)\n default:\n io.err(`unknown api subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nfunction cmdList(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { json: { type: 'boolean' } },\n })\n const dir = positionals[0]\n if (!dir) {\n io.err('api list needs <dir>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n const requests = [...collection.requests.values()].map((e) => ({\n name: e.request.name,\n method: e.request.method,\n url: e.request.url,\n }))\n if (values.json) {\n io.out(`${JSON.stringify({ requests }, null, 2)}\\n`)\n return 0\n }\n for (const r of requests) {\n io.out(`${r.method} ${r.name} ${r.url}\\n`)\n }\n return 0\n}\n\nfunction cmdGet(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { json: { type: 'boolean' } },\n })\n const [dir, name] = positionals\n if (!dir || !name) {\n io.err('api get needs <dir> <name>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n const entry = collection.requests.get(name)\n if (!entry) {\n io.err(`no request named ${name}\\n`)\n return 1\n }\n const { request } = entry\n // Secret NAMES referenced in url/headers/body — never their values.\n const secrets = secretNames(\n request.url,\n ...request.headers.flatMap((h) => [h.name, h.value]),\n request.body?.content,\n )\n if (values.json) {\n io.out(\n `${JSON.stringify(\n {\n name: request.name,\n method: request.method,\n url: request.url,\n headers: request.headers,\n requiredSecrets: secrets,\n },\n null,\n 2,\n )}\\n`,\n )\n return 0\n }\n // Show headers but mask secret references so the value column never carries a\n // `{{secret:NAME}}` template (the required-secrets line is the canonical list).\n io.out(`${request.method} ${maskSecrets(request.url)}\\n`)\n for (const h of request.headers) {\n io.out(` ${h.name}: ${maskSecrets(h.value)}\\n`)\n }\n io.out(`required secrets: ${secrets.length ? secrets.join(', ') : '(none)'}\\n`)\n return 0\n}\n\n/** Shared run-option flags for `run` and `run-collection`. */\nconst RUN_OPTIONS = {\n var: { type: 'string', multiple: true },\n env: { type: 'string' },\n unsafe: { type: 'boolean' },\n 'allow-host': { type: 'string', multiple: true },\n 'block-private': { type: 'boolean' },\n 'max-redirects': { type: 'string' },\n keyring: { type: 'boolean' },\n json: { type: 'boolean' },\n} as const\n\n/** Parse `--max-redirects` (a non-negative integer) or undefined. */\nfunction parseMaxRedirects(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isInteger(n) && n >= 0 ? n : undefined\n}\n\n/** Secret store for a run: opt into the OS keyring (chained ahead of env) with\n * `--keyring`, else the env default (`SACKVILLE_SECRET_<NAME>`). */\nfunction secretsFor(keyring: boolean | undefined): SecretStore | undefined {\n return keyring ? resolveSecretStore({ keyring: true }) : undefined\n}\n\n/** Read a stored response body by handle and JSON-parse it; fall back to raw. */\nfunction parseStoredBody(artifacts: ArtifactStore, handle: string): unknown {\n const raw = artifacts.get(handle)?.body ?? ''\n try {\n return JSON.parse(raw)\n } catch {\n return raw\n }\n}\n\n/** Redact every finding's message AND path through a redactor that learned the run's\n * resolved secrets — a finding can echo a captured body/param/variable value. */\nfunction redactContract(\n raw: ContractResult,\n secrets: { name: string; value: string }[],\n): ContractResult {\n const redactor = new Redactor()\n for (const s of secrets) redactor.register(s.name, s.value)\n return {\n ...raw,\n findings: raw.findings.map((f) => ({\n ...f,\n message: redactor.redact(f.message),\n ...(f.path !== undefined ? { path: redactor.redact(f.path) } : {}),\n })),\n }\n}\n\nfunction printContract(io: CliIO, contract: ContractResult, label = 'contract'): void {\n io.out(`${label}: ${contract.valid ? 'valid' : 'INVALID'}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n}\n\nasync function cmdRun(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...RUN_OPTIONS,\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n coercers: { type: 'string' },\n },\n })\n const [dir, name] = positionals\n if (!dir || !name) {\n io.err('api run needs <dir> <name>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n if (!collection.requests.has(name)) {\n io.err(`no request named ${name}\\n`)\n return 1\n }\n const artifacts = new ArtifactStore()\n // --unsafe/--allow-host are operator (human) controlled here — correct for a\n // CLI the human runs; pass them straight through to the engine.\n const runOpts = {\n vars: parseVars(values.var),\n env: values.env,\n allowUnsafe: values.unsafe ?? false,\n allowedHosts: values['allow-host'],\n allowPrivate: !values['block-private'],\n maxRedirects: parseMaxRedirects(values['max-redirects']),\n secrets: secretsFor(values.keyring),\n artifacts,\n }\n // When validating against a contract, capture the UN-redacted sent request too, so\n // its body/params can be type-checked (ADR 0014); RunResult itself stays redacted.\n let result: RunResult\n let reqCapture: ContractRequestCapture | undefined\n if (values.openapi || values.graphql) {\n const driven = await runRequestForContract(collection, name, runOpts)\n result = driven.result\n reqCapture = driven.capture\n } else {\n result = await runRequest(collection, name, runOpts)\n }\n\n let contract: ContractResult | undefined\n let requestContract: ContractResult | undefined\n if (values.openapi) {\n const spec = JSON.parse(readFileSync(values.openapi, 'utf8'))\n const baseDir = dirname(values.openapi)\n // Response validation needs a sent response; request validation does not — the\n // request is fully known at prepare time, so it runs even on a withheld dry-run.\n if (result.sent && result.response) {\n const url = new URL(result.request.url)\n contract = validateOpenApiResponse(\n spec,\n { method: result.request.method, path: url.pathname },\n {\n status: result.response.status,\n headers: result.response.headers,\n body: parseStoredBody(artifacts, result.response.bodyHandle),\n },\n // External local-file $refs resolve relative to the spec file's directory.\n { baseDir },\n )\n }\n // A GraphQL request envelope has no REST requestBody/param model — skip it (the\n // capture→contract bridge routes GraphQL to schema validation separately).\n if (reqCapture && !isGraphqlEnvelope(reqCapture.request.body)) {\n const raw = validateOpenApiRequest(spec, reqCapture.request, {\n baseDir,\n // The CLI holds the real sent request, so body presence + params are authoritative.\n bodyPresenceAuthoritative: true,\n paramsAuthoritative: true,\n })\n requestContract = redactContract(raw, reqCapture.registeredSecrets)\n }\n }\n\n // --graphql validates a GraphQL run's query + variables (+ response errors) against the\n // supplied SDL — the symmetric parallel to --openapi (ADR 0015). The CLI holds the real\n // request, so variables are authoritative.\n let graphqlContract: ContractResult | undefined\n if (values.graphql && reqCapture && isGraphqlEnvelope(reqCapture.request.body)) {\n const sdl = readFileSync(values.graphql, 'utf8')\n // --coercers loads operator custom-scalar coercers (ADR 0018, the second wire point);\n // a load failure is LOUD + non-zero, never a silent no-coercer fall-through.\n let scalarCoercers: Record<string, ScalarCoercer> | undefined\n if (values.coercers !== undefined) {\n scalarCoercers = await loadCoercers(values.coercers, io)\n if (scalarCoercers === undefined) return 1\n }\n const env = reqCapture.request.body as {\n query: string\n operationName?: string\n variables?: unknown\n }\n const raw = validateGraphqlOperation(sdl, env.query, {\n operationName: env.operationName,\n ...(scalarCoercers ? { scalarCoercers } : {}),\n ...(result.sent && result.response\n ? { json: parseStoredBody(artifacts, result.response.bodyHandle) }\n : {}),\n ...(env.variables !== undefined\n ? { variables: env.variables, variablesAuthoritative: true }\n : {}),\n })\n graphqlContract = redactContract(raw, reqCapture.registeredSecrets)\n }\n\n // Return code: 0 only if SENT and every assertion passed and (if validated) both the\n // response AND request contracts are valid; 1 otherwise — including a dry-run, since a\n // withheld request verified nothing (though its request contract is still surfaced).\n const assertionsOk = !!result.response?.assertions.every((a) => a.pass)\n const ok =\n result.sent &&\n assertionsOk &&\n (contract ? contract.valid : true) &&\n (requestContract ? requestContract.valid : true) &&\n (graphqlContract ? graphqlContract.valid : true)\n\n if (values.json) {\n io.out(\n `${JSON.stringify({ ...result, ...(contract ? { contract } : {}), ...(requestContract ? { requestContract } : {}), ...(graphqlContract ? { graphqlContract } : {}) }, null, 2)}\\n`,\n )\n return ok ? 0 : 1\n }\n\n io.out(`${result.request.method} ${result.request.url}\\n`)\n if (result.sent) {\n io.out('sent\\n')\n } else {\n io.out(`dry-run (not sent)${result.reason ? `: ${result.reason}` : ''}\\n`)\n }\n if (result.response) {\n const res = result.response\n io.out(`status ${res.status} ${res.latencyMs}ms\\n`)\n for (const a of res.assertions) {\n io.out(`${a.pass ? 'PASS' : 'FAIL'} ${a.source} ${a.op}${a.path ? ` ${a.path}` : ''}\\n`)\n }\n for (const t of res.scriptTests) {\n io.out(`${t.pass ? 'PASS' : 'FAIL'} script: ${t.name}${t.error ? ` — ${t.error}` : ''}\\n`)\n }\n io.out(`body: ${res.bodyHandle}\\n`)\n }\n if (requestContract) printContract(io, requestContract, 'request contract')\n if (contract) printContract(io, contract, 'response contract')\n if (graphqlContract) printContract(io, graphqlContract, 'graphql contract')\n return ok ? 0 : 1\n}\n\nasync function cmdRunCollection(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...RUN_OPTIONS, 'stop-on-failure': { type: 'boolean' } },\n })\n const [dir, ...names] = positionals\n if (!dir || names.length === 0) {\n io.err('api run-collection needs <dir> <name...>\\n')\n return 1\n }\n const artifacts = new ArtifactStore()\n const result = await runSequence(loadCollection(dir), names, {\n vars: parseVars(values.var),\n env: values.env,\n allowUnsafe: values.unsafe ?? false,\n allowedHosts: values['allow-host'],\n allowPrivate: !values['block-private'],\n maxRedirects: parseMaxRedirects(values['max-redirects']),\n secrets: secretsFor(values.keyring),\n stopOnFailure: values['stop-on-failure'] ?? false,\n artifacts,\n })\n\n // 0 only if every SENT step passed its assertions.\n const ok = result.steps.every(\n (s) => s.result.sent && (s.result.response?.assertions.every((a) => a.pass) ?? false),\n )\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return ok ? 0 : 1\n }\n\n for (const step of result.steps) {\n const res = step.result\n const status = res.sent ? String(res.response?.status ?? '-') : 'dry-run'\n const passed = res.sent && (res.response?.assertions.every((a) => a.pass) ?? false)\n io.out(`${step.name} ${status} ${passed ? 'PASS' : 'FAIL'}\\n`)\n }\n io.out(`captured: ${Object.keys(result.captured).join(', ') || '(none)'}\\n`)\n return ok ? 0 : 1\n}\n\nconst IMPORT_FORMATS = new Set<ImportFormat>(['postman', 'insomnia', 'openapi', 'har'])\n\nfunction cmdImport(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { name: { type: 'string' } },\n })\n const [format, source, dest] = positionals\n if (!format || !source || !dest) {\n io.err('api import needs <postman|insomnia|openapi|har> <source-file> <dest-dir>\\n')\n return 1\n }\n if (!IMPORT_FORMATS.has(format as ImportFormat)) {\n io.err(`unknown import format: ${format} (expected postman|insomnia|openapi|har)\\n`)\n return 1\n }\n const text = readFileSync(source, 'utf8')\n const count = importToCollection(format as ImportFormat, text, dest, { name: values.name })\n io.out(`imported ${count} request(s) into ${dest}\\n`)\n return 0\n}\n\nasync function cmdValidate(args: string[], io: CliIO): Promise<number> {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n graphql: { type: 'string' },\n query: { type: 'string' },\n operation: { type: 'string' },\n variables: { type: 'string' },\n coercers: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n if (!values.graphql || !values.query) {\n io.err('api validate needs --graphql <schemafile> --query <queryfile>\\n')\n return 1\n }\n const sdl = readFileSync(values.graphql, 'utf8')\n const query = readFileSync(values.query, 'utf8')\n // --variables accepts inline JSON or a file path. The human supplies the real request,\n // so variables are authoritative (an absent required variable is a finding, not skipped).\n let variables: unknown\n if (values.variables !== undefined) {\n try {\n variables = JSON.parse(values.variables)\n } catch {\n variables = JSON.parse(readFileSync(values.variables, 'utf8'))\n }\n }\n // --coercers loads an operator module of custom-scalar coercers (ADR 0018). A load failure\n // is LOUD + non-zero — never a silent fall-through to no-coercer `unverified` (which looks clean).\n let scalarCoercers: Record<string, ScalarCoercer> | undefined\n if (values.coercers !== undefined) {\n scalarCoercers = await loadCoercers(values.coercers, io)\n if (scalarCoercers === undefined) return 1\n }\n const contract = validateGraphqlOperation(sdl, query, {\n operationName: values.operation,\n ...(scalarCoercers ? { scalarCoercers } : {}),\n ...(variables !== undefined ? { variables, variablesAuthoritative: true } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(contract, null, 2)}\\n`)\n return contract.valid ? 0 : 1\n }\n io.out(`valid: ${contract.valid}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n return contract.valid ? 0 : 1\n}\n\n/**\n * `api validate-request --openapi <spec.json> --method <M> --path </p> [--body <file>]\n * [--query k=v]…` — a preflight: validate a request's body + params against an OpenAPI\n * operation BEFORE sending it. The human supplies the real request, so body presence\n * and params are authoritative. (A GraphQL envelope is refused, not schema-failed.)\n */\nfunction cmdValidateRequest(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n openapi: { type: 'string' },\n method: { type: 'string' },\n path: { type: 'string' },\n body: { type: 'string' },\n query: { type: 'string', multiple: true },\n header: { type: 'string', multiple: true },\n form: { type: 'string', multiple: true },\n 'form-file': { type: 'string', multiple: true },\n json: { type: 'boolean' },\n },\n })\n if (!values.openapi || !values.method || !values.path) {\n io.err('api validate-request needs --openapi <spec.json> --method <M> --path </p>\\n')\n return 1\n }\n const spec = JSON.parse(readFileSync(values.openapi, 'utf8'))\n const body = values.body !== undefined ? JSON.parse(readFileSync(values.body, 'utf8')) : undefined\n if (isGraphqlEnvelope(body)) {\n io.err(\n 'the request body is a GraphQL envelope ({query}); use `api validate --graphql` instead\\n',\n )\n return 1\n }\n // `--query name=value` (repeatable; repeated names collect into an array).\n const query: Record<string, string | string[]> = {}\n for (const kv of values.query ?? []) {\n const eq = kv.indexOf('=')\n if (eq < 0) continue\n const k = kv.slice(0, eq)\n const v = kv.slice(eq + 1)\n const cur = query[k]\n query[k] = cur === undefined ? v : Array.isArray(cur) ? [...cur, v] : [cur, v]\n }\n // `--header name:value` (repeatable), lower-cased.\n const headers: Record<string, string> = {}\n for (const hv of values.header ?? []) {\n const c = hv.indexOf(':')\n if (c < 0) continue\n headers[hv.slice(0, c).trim().toLowerCase()] = hv.slice(c + 1).trim()\n }\n // `--form name=value` (repeatable; repeated names → array): the structured field map of\n // a form-urlencoded / multipart text body. The content-type header routes validation.\n const form: Record<string, string | string[]> = {}\n for (const kv of values.form ?? []) {\n const eq = kv.indexOf('=')\n if (eq < 0) continue\n const k = kv.slice(0, eq)\n const v = kv.slice(eq + 1)\n const cur = form[k]\n form[k] = cur === undefined ? v : Array.isArray(cur) ? [...cur, v] : [cur, v]\n }\n // `--form-file name` (repeatable): multipart FILE part names (presence only).\n const formFileFields = values['form-file'] ?? []\n\n const contract = validateOpenApiRequest(\n spec,\n {\n method: values.method,\n path: values.path,\n body,\n ...(Object.keys(query).length > 0 ? { query } : {}),\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(Object.keys(form).length > 0 ? { form } : {}),\n ...(formFileFields.length > 0 ? { formFileFields } : {}),\n },\n {\n baseDir: dirname(values.openapi),\n bodyPresenceAuthoritative: true,\n paramsAuthoritative: true,\n },\n )\n\n if (values.json) {\n io.out(`${JSON.stringify(contract, null, 2)}\\n`)\n return contract.valid ? 0 : 1\n }\n io.out(`valid: ${contract.valid}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n return contract.valid ? 0 : 1\n}\n\n/**\n * `api validate-capture <har.zip> --openapi <spec.json> | --graphql <schema.graphql>`\n * — validate the traffic in a captured HAR against an OpenAPI and/or GraphQL\n * contract (ADR 0013, the capture→contract bridge). The human is the operator, so\n * the local HAR file is read directly (no surface capture gate). REST entries are\n * checked against the OpenAPI spec; GraphQL entries (at `--graphql-endpoint`,\n * default `/graphql`) are checked against the SDL. Exits 1 when not clean.\n */\nfunction cmdValidateCapture(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n 'graphql-endpoint': { type: 'string' },\n origin: { type: 'string', multiple: true },\n json: { type: 'boolean' },\n },\n })\n const [harPath] = positionals\n if (!harPath || (!values.openapi && !values.graphql)) {\n io.err(\n 'api validate-capture needs <har.zip> and --openapi <spec.json> and/or --graphql <schema.graphql>\\n',\n )\n return 1\n }\n const harZip = readFileSync(harPath)\n const contract: import('@sackville-mcp/api').CaptureContract = {\n ...(values.openapi ? { openapi: JSON.parse(readFileSync(values.openapi, 'utf8')) } : {}),\n ...(values.graphql\n ? {\n graphql: {\n endpointPath: values['graphql-endpoint'] ?? '/graphql',\n sdl: readFileSync(values.graphql, 'utf8'),\n },\n }\n : {}),\n }\n const verdict = validateCapturedTraffic(harZip, contract, {\n allowedOrigins: values.origin,\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(verdict, null, 2)}\\n`)\n return verdict.clean ? 0 : 1\n }\n io.out(\n `capture: ${verdict.clean ? 'clean' : 'NOT CLEAN'} (${verdict.entriesValidated} entries)\\n`,\n )\n for (const [kind, count] of Object.entries(verdict.findingsByKind)) {\n io.out(` ${count}× ${kind}\\n`)\n }\n if (verdict.firstFailing) {\n const f = verdict.firstFailing\n io.out(` first failing: ${f.method} ${f.path} — ${f.kind}: ${f.message}\\n`)\n }\n io.out(` exercised: ${verdict.exercisedOperations.join(', ') || '(none)'}\\n`)\n if (verdict.unexercisedOperations.length > 0) {\n io.out(` unexercised: ${verdict.unexercisedOperations.join(', ')}\\n`)\n }\n return verdict.clean ? 0 : 1\n}\n","import { mkdtempSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n ArtifactStore,\n auditA11y,\n type BrowserEngine,\n browserSecretsFromEnv,\n buildCaptureRuntime,\n type FlowResult,\n loadFlow,\n PageDriver,\n resolveEngine,\n runFlow,\n} from '@sackville-mcp/browser'\nimport type { Page } from 'playwright-core'\nimport type { CliIO } from './index.js'\n\n/**\n * Human-facing `sackville browser …` — single-shot page-inspection commands over\n * the `@sackville-mcp/browser` engine. Each command navigates once and reads, so the\n * per-snapshot refs never need to outlive the process (unlike the stateful MCP\n * surface). The egress boundary mirrors the server bin: navigation is gated by an\n * allowlist (the typed host is auto-allowed, since the human explicitly asked for\n * it) and a **mandatory** DNS-pinning SSRF proxy fronts every request. The human\n * is the operator here, so the safety flags are theirs to set.\n */\n\ninterface BrowserFlags {\n allowHost: string[]\n allowPrivate: boolean\n noSandbox: boolean\n headed: boolean\n engine: BrowserEngine\n}\n\n/** Flags shared by every browser command. */\nconst COMMON_OPTIONS = {\n 'allow-host': { type: 'string', multiple: true },\n 'allow-private': { type: 'boolean' },\n 'no-sandbox': { type: 'boolean' },\n headed: { type: 'boolean' },\n engine: { type: 'string' },\n json: { type: 'boolean' },\n} as const\n\ntype CommonValues = {\n 'allow-host'?: string[]\n 'allow-private'?: boolean\n 'no-sandbox'?: boolean\n headed?: boolean\n engine?: string\n}\n\nfunction flagsFrom(values: CommonValues): BrowserFlags {\n return {\n allowHost: values['allow-host'] ?? [],\n allowPrivate: values['allow-private'] ?? false,\n noSandbox: values['no-sandbox'] ?? false,\n headed: values.headed ?? false,\n engine: resolveEngine(values.engine),\n }\n}\n\ninterface SessionContext {\n driver: PageDriver\n store: ArtifactStore\n page: Page\n}\n\n/**\n * Stand up a gated, proxy-fronted browser, navigate to `url`, run `fn`, and tear\n * everything down. Returns `undefined` for a bad URL (after reporting it).\n */\nasync function withSession(\n url: string,\n flags: BrowserFlags,\n io: CliIO,\n fn: (ctx: SessionContext) => Promise<number>,\n): Promise<number> {\n let host: string\n try {\n host = new URL(url).hostname\n } catch {\n io.err(`invalid url: ${url}\\n`)\n return 1\n }\n // The human typed this URL → auto-allow its host, plus any extra --allow-host.\n const runtime = await buildCaptureRuntime({\n allowedHosts: [host, ...flags.allowHost],\n allowPrivate: flags.allowPrivate,\n engine: flags.engine,\n headless: !flags.headed,\n noSandbox: flags.noSandbox,\n })\n const store = new ArtifactStore(mkdtempSync(join(tmpdir(), 'sackville-browser-cli-')))\n try {\n const context = await runtime.manager.createSession('cli')\n const page = await context.newPage()\n const driver = new PageDriver(page, { runId: 'cli', store, gate: runtime.gate })\n await driver.navigate(url)\n return await fn({ driver, store, page })\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n } finally {\n await runtime.shutdown()\n }\n}\n\nexport async function runBrowser(args: string[], io: CliIO): Promise<number> {\n const [sub, ...rest] = args\n try {\n switch (sub) {\n case 'snapshot':\n return await cmdSnapshot(rest, io)\n case 'audit':\n return await cmdAudit(rest, io)\n case 'screenshot':\n return await cmdScreenshot(rest, io)\n case 'run':\n return await cmdRun(rest, io)\n default:\n io.err(`unknown browser subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n } catch (err) {\n // Early flag-validation errors (e.g. an unknown --engine) surface as a clean\n // message + exit 1 rather than an uncaught rejection.\n io.err(`${(err as Error).message}\\n`)\n return 1\n }\n}\n\n/** Parse repeatable `--var k=v` flags (split on the FIRST `=`) into a record. */\nfunction parseVars(raw: string[] | undefined): Record<string, unknown> {\n const vars: Record<string, unknown> = {}\n for (const item of raw ?? []) {\n const eq = item.indexOf('=')\n if (eq === -1) vars[item] = ''\n else vars[item.slice(0, eq)] = item.slice(eq + 1)\n }\n return vars\n}\n\n/**\n * Replay a persisted browser flow (`<flow>.bru` + sidecar) — `sackville browser\n * run <flow.bru>`. Unlike the single-shot commands the flow drives its own\n * navigations, so no URL is auto-allowed: the human allowlists target hosts with\n * `--allow-host` and unlocks mutations with `--unsafe` (else they dry-run).\n * `{{secret:NAME}}` resolves from `SACKVILLE_BROWSER_SECRET_<NAME>` env (the human\n * is the operator); a `Redactor` scrubs those values from every result. Exits\n * non-zero when the flow fails (a step error or a failed assertion) — CI-usable.\n */\nasync function cmdRun(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...COMMON_OPTIONS,\n unsafe: { type: 'boolean' },\n var: { type: 'string', multiple: true },\n },\n })\n const flowPath = positionals[0]\n if (!flowPath) {\n io.err('browser run needs <flow.bru>\\n')\n return 1\n }\n\n let flow: ReturnType<typeof loadFlow>\n try {\n flow = loadFlow(flowPath)\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n }\n\n // Operator secrets from env (SACKVILLE_BROWSER_SECRET_<NAME>); registered with a\n // redactor so they never surface, exposed only by NAME. Shared with the verify\n // CLI + the browser MCP server (one source of truth, `@sackville-mcp/browser`).\n const { redact, resolveSecret } = browserSecretsFromEnv(io.env ?? {})\n const flags = flagsFrom(values)\n const runtime = await buildCaptureRuntime({\n allowedHosts: flags.allowHost,\n allowUnsafe: values.unsafe ?? false,\n allowPrivate: flags.allowPrivate,\n engine: flags.engine,\n headless: !flags.headed,\n noSandbox: flags.noSandbox,\n redact,\n resolveSecret,\n })\n const store = new ArtifactStore(mkdtempSync(join(tmpdir(), 'sackville-browser-flow-')))\n try {\n const context = await runtime.manager.createSession('cli')\n const page = await context.newPage()\n const driver = new PageDriver(page, {\n runId: 'cli',\n store,\n gate: runtime.gate,\n redact: runtime.redact,\n })\n const result = await runFlow(driver, flow, {\n vars: parseVars(values.var),\n resolveSecret: runtime.resolveSecret,\n })\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else {\n printFlowResult(result, io)\n }\n return result.passed ? 0 : 1\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n } finally {\n await runtime.shutdown()\n }\n}\n\nfunction printFlowResult(result: FlowResult, io: CliIO): void {\n io.out(`flow: ${result.name}\\n`)\n for (const step of result.steps) {\n if (step.error) {\n io.out(` FAIL ${step.action} — ${step.error}\\n`)\n } else if (step.assertions) {\n const passed = step.assertions.filter((a) => a.pass).length\n const total = step.assertions.length\n io.out(` ${passed === total ? 'ok ' : 'FAIL'} assert (${passed}/${total} passed)\\n`)\n } else {\n io.out(` ok ${step.action}${step.dryRun ? ' (dry-run)' : ''}\\n`)\n }\n }\n io.out(`${result.passed ? 'PASS' : 'FAIL'}\\n`)\n}\n\nasync function cmdSnapshot(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: COMMON_OPTIONS,\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser snapshot needs <url>\\n')\n return 1\n }\n return withSession(url, flagsFrom(values), io, async ({ driver }) => {\n const snap = await driver.snapshot()\n if (values.json) {\n io.out(`${JSON.stringify(snap, null, 2)}\\n`)\n return 0\n }\n io.out(`${snap.snapshot}\\n`)\n if (snap.truncated) io.err('(snapshot truncated — re-run with --json for the full handle)\\n')\n return 0\n })\n}\n\nasync function cmdAudit(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: COMMON_OPTIONS,\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser audit needs <url>\\n')\n return 1\n }\n return withSession(url, flagsFrom(values), io, async ({ store, page }) => {\n const res = await auditA11y(page, { runId: 'cli', store })\n if (values.json) {\n io.out(`${JSON.stringify(res, null, 2)}\\n`)\n return res.summary.violationCount === 0 ? 0 : 1\n }\n const s = res.summary\n io.out(`violations: ${s.violationCount}\\n`)\n for (const v of s.top) {\n io.out(` [${v.impact ?? '-'}] ${v.id}: ${v.nodeCount} node(s) — ${v.help}\\n`)\n }\n const path = store.get(res.resultsHandle)?.path\n if (path) io.out(`full report: ${path}\\n`)\n // exit non-zero when violations exist, so the command is usable as a CI gate\n return s.violationCount === 0 ? 0 : 1\n })\n}\n\nasync function cmdScreenshot(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...COMMON_OPTIONS, out: { type: 'string' }, 'full-page': { type: 'boolean' } },\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser screenshot needs <url>\\n')\n return 1\n }\n const out = values.out ?? 'screenshot.png'\n return withSession(url, flagsFrom(values), io, async ({ driver, store }) => {\n const shot = await driver.screenshot({ fullPage: values['full-page'] ?? false })\n const bytes = shot.handle ? store.get(shot.handle)?.body : undefined\n if (!bytes) {\n io.err('screenshot capture failed\\n')\n return 1\n }\n writeFileSync(out, bytes)\n if (values.json) {\n io.out(`${JSON.stringify({ ...shot, savedTo: out }, null, 2)}\\n`)\n return 0\n }\n io.out(`saved ${shot.byteSize} bytes to ${out}\\n`)\n return 0\n })\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n CoverageGateError,\n type CoveragePyReport,\n coveragePyToIstanbul,\n type DiffCoverageReport,\n type FileCoverage,\n runScoped,\n runScopedPython,\n type ScopedPythonResult,\n type ScopeMode,\n type TestRunner,\n uncoveredInDiff,\n} from '@sackville-mcp/coverage'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville coverage` — the human surface over `@sackville-mcp/coverage`.\n *\n * `uncovered-in-diff` is the pure forgotten-assertion catch: classify a diff's new lines\n * against an istanbul or coverage.py report and surface the executable-but-unhit ones.\n * `run-scoped` is the gated impact-scoped runner (`vitest related`). The human IS the\n * operator, so the gate is a straight-through `--allow-run` flag and the typed root is\n * auto-allowed; the test runner is injectable so the suite never spawns a real vitest\n * (ADR 0010: no real spawn in the gate). Both commands exit 1 when a new line is uncovered —\n * the catch is CI-actionable, like `sackville browser audit`.\n */\nexport async function runCoverage(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'uncovered-in-diff':\n return cmdUncoveredInDiff(rest, io)\n case 'run-scoped':\n return cmdRunScoped(rest, io, deps)\n default:\n io.err(`unknown coverage subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nfunction printReport(io: CliIO, report: DiffCoverageReport): void {\n const s = report.summary\n io.out(\n `files: ${report.files.length} (${s.filesWithoutCoverage} without coverage) ` +\n `covered ${s.covered} uncovered ${s.uncovered} non-executable ${s.nonExecutable}\\n`,\n )\n if (report.uncovered.length === 0) {\n io.out('uncovered new lines: (none)\\n')\n return\n }\n io.out(`uncovered new lines (${report.uncovered.length}):\\n`)\n for (const u of report.uncovered) {\n io.out(` ${u.path}:${u.line}\\n`)\n }\n}\n\nfunction cmdUncoveredInDiff(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n diff: { type: 'string' },\n coverage: { type: 'string' },\n 'coverage-format': { type: 'string' },\n 'project-root': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n if (!values.diff || !values.coverage) {\n io.err('coverage uncovered-in-diff needs --diff <file> and --coverage <file>\\n')\n return 1\n }\n const format = values['coverage-format'] ?? 'istanbul'\n if (format !== 'istanbul' && format !== 'coveragepy') {\n io.err(`unknown coverage format: ${format} (expected istanbul|coveragepy)\\n`)\n return 1\n }\n const diff = readFileSync(values.diff, 'utf8')\n const parsed = JSON.parse(readFileSync(values.coverage, 'utf8'))\n const coverage: Record<string, FileCoverage> =\n format === 'coveragepy' ? coveragePyToIstanbul(parsed as CoveragePyReport) : parsed\n const report = uncoveredInDiff(diff, coverage, { projectRoot: values['project-root'] })\n\n if (values.json) {\n io.out(`${JSON.stringify(report, null, 2)}\\n`)\n } else {\n printReport(io, report)\n }\n // An executable new line with no test is the catch — exit non-zero so CI fails on it.\n return report.uncovered.length === 0 ? 0 : 1\n}\n\nasync function cmdRunScoped(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n 'changed-file': { type: 'string', multiple: true },\n diff: { type: 'string' },\n python: { type: 'boolean' },\n measure: { type: 'string', multiple: true },\n 'scope-mode': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('coverage run-scoped needs a <project-root>\\n')\n return 1\n }\n const scopeMode = values['scope-mode'] ?? 'report-gap'\n if (values.python && scopeMode !== 'report-gap' && scopeMode !== 'widen') {\n io.err(`unknown scope mode: ${scopeMode} (expected report-gap|widen)\\n`)\n return 1\n }\n const timeoutRaw = values['timeout-ms']\n const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) : undefined\n\n try {\n const config = {\n projectRoot,\n // Human-typed root = the operator allowlist (explicit intent), like `api`'s host.\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: timeoutMs !== undefined && Number.isFinite(timeoutMs) ? timeoutMs : undefined,\n }\n const changedFiles = values['changed-file'] ?? []\n const diff = values.diff !== undefined ? readFileSync(values.diff, 'utf8') : undefined\n\n const result = values.python\n ? await runScopedPython(\n config,\n {\n changedFiles,\n diff,\n measureTargets: values.measure ?? [],\n scopeMode: scopeMode as ScopeMode,\n },\n { runner: deps.runner },\n )\n : await runScoped(config, { changedFiles, diff }, { runner: deps.runner })\n\n const py = values.python ? (result as ScopedPythonResult) : undefined\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else if (!result.ran) {\n io.out('no changed files — nothing to run\\n')\n } else {\n io.out(\n `ran ${values.python ? 'pytest' : 'vitest'} (exit ${result.exitCode}); tests ${\n py?.inconclusive ? 'INCONCLUSIVE' : result.passed ? 'passed' : 'FAILED'\n }; scoped: ${result.scopedFiles.join(', ')}\\n`,\n )\n if (py?.unmatched)\n io.out(`uncovered-by-scope (no mirrored test): ${py.unmatched.join(', ')}\\n`)\n if (result.report) printReport(io, result.report)\n }\n // 0 only if tests passed, not inconclusive, AND (when a diff was analysed) no new line uncovered.\n const ok =\n result.passed &&\n !py?.inconclusive &&\n (result.report ? result.report.uncovered.length === 0 : true)\n return ok ? 0 : 1\n } catch (e) {\n if (e instanceof CoverageGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { parseArgs } from 'node:util'\nimport { detectInstalledVersion, type Ecosystem } from '@sackville-mcp/core'\nimport {\n auditDependency,\n CHANGELOG_FILENAMES,\n comparatorFor,\n type DependencyAudit,\n dependencyNames,\n gemRepoUrl,\n githubOwnerRepo,\n loadOsvSnapshot,\n matchName,\n normalizePypiName,\n npmRepoUrl,\n type OsvAdvisory,\n type OsvEcosystem,\n type Packument,\n type PyPiJson,\n pypiJsonToPackument,\n pypiRepoUrl,\n type RubyGemMetadata,\n type RubyGemsVersion,\n rubygemsToPackument,\n sliceChangelog,\n} from '@sackville-mcp/deps'\nimport { resolveAndPin } from '@sackville-mcp/safety'\nimport type { CliIO } from './index.js'\n\n/** Injected (so tests stay offline) registry-metadata fetcher; the real one is SSRF-pinned. */\nexport type PackumentFetcher = (packageName: string, ecosystem: OsvEcosystem) => Promise<Packument>\n/** Injected CHANGELOG fetcher (npm only); the real one is SSRF-pinned to raw.githubusercontent. */\ntype ChangelogFetcher = (\n packageName: string,\n ecosystem: OsvEcosystem,\n) => Promise<{ text: string; source: string }>\n\n/** Map an OSV ecosystem to the `@sackville-mcp/core` installed-version detection ecosystem. */\nconst DETECT_ECOSYSTEM: Record<OsvEcosystem, Ecosystem> = {\n npm: 'node',\n PyPI: 'python',\n RubyGems: 'ruby',\n}\n\n/**\n * `sackville deps` — the human surface over `@sackville-mcp/deps`. Answers deprecation /\n * vulnerability / freshness for the version ACTUALLY INSTALLED in a project (not \"latest\").\n *\n * The human invoked the audit, so the CLI fetches by default (operator intent), with the\n * same SSRF pre-flight the bins use (`resolveAndPin`: metadata/link-local always refused,\n * private registries gated by `--allow-private`). Network + comparator dispatch reuse the\n * ecosystem helpers lifted into `@sackville-mcp/deps`. `audit`/`audit-project` exit 1 on a\n * security or deprecation finding (CI-actionable); `changelog` is informational.\n */\nexport async function runDeps(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher; fetchChangelog?: ChangelogFetcher } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'audit':\n return cmdAudit(rest, io, deps)\n case 'audit-project':\n return cmdAuditProject(rest, io, deps)\n case 'changelog':\n return cmdChangelog(rest, io, deps)\n default:\n io.err(`unknown deps subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Operator registry/SSRF flags shared by every deps command. */\nconst REGISTRY_OPTIONS = {\n ecosystem: { type: 'string' },\n 'osv-db': { type: 'string' },\n registry: { type: 'string' },\n 'pypi-registry': { type: 'string' },\n 'rubygems-registry': { type: 'string' },\n 'allow-private': { type: 'boolean' },\n json: { type: 'boolean' },\n} as const\n\ninterface Registries {\n registry: string\n pypiRegistry: string\n rubygemsRegistry: string\n allowPrivate: boolean\n}\n\nexport function registriesFrom(values: Record<string, unknown>): Registries {\n return {\n registry: (values.registry as string) || 'https://registry.npmjs.org',\n pypiRegistry: (values['pypi-registry'] as string) || 'https://pypi.org/pypi',\n rubygemsRegistry: (values['rubygems-registry'] as string) || 'https://rubygems.org/api/v1',\n allowPrivate: (values['allow-private'] as boolean) ?? false,\n }\n}\n\nfunction ecosystemFrom(values: Record<string, unknown>, io: CliIO): OsvEcosystem | null {\n const e = (values.ecosystem as string) ?? 'npm'\n if (e !== 'npm' && e !== 'PyPI' && e !== 'RubyGems') {\n io.err(`unknown ecosystem: ${e} (expected npm|PyPI|RubyGems)\\n`)\n return null\n }\n return e\n}\n\n/** npm packument path: keep a scope's `@` but escape the `/` (registry idiom). */\nfunction packumentUrl(registry: string, packageName: string): string {\n return `${registry.replace(/\\/+$/, '')}/${packageName.replace('/', '%2f')}`\n}\n\n/** Build the SSRF-pinned packument fetcher (npm/PyPI/RubyGems), mirroring the deps bin. */\nexport function makeFetcher(r: Registries): PackumentFetcher {\n return async (packageName, ecosystem) => {\n if (ecosystem === 'npm') {\n const url = packumentUrl(r.registry, packageName)\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`registry returned ${res.status} for ${packageName}`)\n return (await res.json()) as Packument\n }\n if (ecosystem === 'PyPI') {\n const base = r.pypiRegistry.replace(/\\/+$/, '')\n const url = `${base}/${encodeURIComponent(normalizePypiName(packageName))}/json`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`PyPI returned ${res.status} for ${packageName}`)\n return pypiJsonToPackument((await res.json()) as PyPiJson)\n }\n const base = r.rubygemsRegistry.replace(/\\/+$/, '')\n const url = `${base}/versions/${encodeURIComponent(packageName)}.json`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`RubyGems returned ${res.status} for ${packageName}`)\n return rubygemsToPackument(packageName, (await res.json()) as RubyGemsVersion[])\n }\n}\n\n/** SSRF-pinned JSON GET (pre-flight resolve-and-refuse, then fetch). */\nasync function pinnedFetchJson(url: string, allowPrivate: boolean): Promise<unknown> {\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`metadata fetch returned ${res.status} for ${url}`)\n return res.json()\n}\n\n/**\n * Build the SSRF-pinned changelog fetcher (npm/PyPI/RubyGems). Resolves the source GitHub repo\n * from registry metadata — npm packument `repository`, PyPI `info.project_urls`, or the RubyGems\n * `/api/v1/gems/<name>.json` `source_code_uri`/`homepage_uri` — then fetches the CHANGELOG from\n * `raw.githubusercontent.com/<owner>/<repo>/HEAD/<file>`, pinning every request.\n */\nfunction makeChangelogFetcher(r: Registries): ChangelogFetcher {\n const fetchPackument = makeFetcher(r)\n const repoUrlFor = async (\n packageName: string,\n ecosystem: string,\n ): Promise<string | undefined> => {\n if (ecosystem === 'npm') return npmRepoUrl(await fetchPackument(packageName, 'npm'))\n if (ecosystem === 'PyPI') {\n const base = r.pypiRegistry.replace(/\\/+$/, '')\n const url = `${base}/${encodeURIComponent(normalizePypiName(packageName))}/json`\n return pypiRepoUrl((await pinnedFetchJson(url, r.allowPrivate)) as PyPiJson)\n }\n if (ecosystem === 'RubyGems') {\n const base = r.rubygemsRegistry.replace(/\\/+$/, '')\n const url = `${base}/gems/${encodeURIComponent(packageName)}.json`\n return gemRepoUrl((await pinnedFetchJson(url, r.allowPrivate)) as RubyGemMetadata)\n }\n throw new Error(`changelog fetch supports npm, PyPI, and RubyGems (got \"${ecosystem}\")`)\n }\n return async (packageName, ecosystem) => {\n const gh = githubOwnerRepo(await repoUrlFor(packageName, ecosystem))\n if (!gh) throw new Error(`could not resolve a GitHub repository for \"${packageName}\"`)\n for (const file of CHANGELOG_FILENAMES) {\n const url = `https://raw.githubusercontent.com/${gh.owner}/${gh.repo}/HEAD/${file}`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url)\n if (res.ok) return { text: await res.text(), source: url }\n }\n throw new Error(`no CHANGELOG found in github.com/${gh.owner}/${gh.repo}`)\n }\n}\n\n/** Load advisories + snapshotDate for an ecosystem, or empty when no snapshot dir is set. */\nfunction loadAdvisories(\n osvDir: string | undefined,\n ecosystem: string,\n): { advisories: OsvAdvisory[]; snapshotDate?: string; loaded: boolean } {\n if (osvDir === undefined) return { advisories: [], loaded: false }\n const snapshot = loadOsvSnapshot(osvDir, ecosystem)\n return { advisories: snapshot.advisories, snapshotDate: snapshot.snapshotDate, loaded: true }\n}\n\n/** Detect → fetch → audit one package (the thin orchestration the pure core needs). */\nasync function auditOne(\n project: string,\n packageName: string,\n ecosystem: OsvEcosystem,\n fetchPackument: PackumentFetcher,\n advisories: OsvAdvisory[],\n snapshotDate: string | undefined,\n versionOverride?: string,\n): Promise<DependencyAudit> {\n const version =\n versionOverride ??\n detectInstalledVersion(project, packageName, { ecosystem: DETECT_ECOSYSTEM[ecosystem] }).version\n if (version === null || version === undefined) {\n throw new Error(`could not detect an installed version of \"${packageName}\" in ${project}`)\n }\n const packument = await fetchPackument(packageName, ecosystem)\n return auditDependency({\n packageName: matchName(packageName, ecosystem),\n ecosystem,\n installedVersion: version,\n packument,\n advisories,\n snapshotDate,\n comparator: comparatorFor(ecosystem),\n })\n}\n\n/**\n * Detect → fetch → audit each declared (or `names`-scoped) dependency of a project,\n * isolating per-package failures — the reusable project audit the `verify run --deps`\n * path reuses (mirrors the MCP `auditProjectDependencies`). Returns the\n * `{audits, osvSnapshotLoaded}` shape the verify orchestrator's deps adapter consumes.\n */\nexport async function auditProjectScoped(input: {\n project: string\n ecosystem: OsvEcosystem\n /** Audit ONLY these names (the diff-changed deps); omitted ⇒ all declared deps. */\n names?: string[]\n osvDir?: string\n fetchPackument: PackumentFetcher\n}): Promise<{\n audits: DependencyAudit[]\n osvSnapshotLoaded: boolean\n errors: { package: string; error: string }[]\n}> {\n const { advisories, snapshotDate, loaded } = loadAdvisories(input.osvDir, input.ecosystem)\n const names = input.names ?? dependencyNames(input.project, input.ecosystem, true)\n const audits: DependencyAudit[] = []\n const errors: { package: string; error: string }[] = []\n for (const name of names) {\n try {\n audits.push(\n await auditOne(\n input.project,\n name,\n input.ecosystem,\n input.fetchPackument,\n advisories,\n snapshotDate,\n ),\n )\n } catch (e) {\n errors.push({ package: name, error: (e as Error).message })\n }\n }\n return { audits, osvSnapshotLoaded: loaded, errors }\n}\n\n/** A security or deprecation finding — the CI-actionable signal (outdated alone is not). */\nfunction isActionable(audit: DependencyAudit): boolean {\n return audit.worstSeverity !== 'none' || audit.deprecated.isDeprecated\n}\n\nfunction printAudit(\n io: CliIO,\n audit: DependencyAudit,\n loaded: boolean,\n snapshotDate?: string,\n): void {\n io.out(`${audit.package} ${audit.installedVersion} (${audit.ecosystem})\\n`)\n io.out(\n audit.deprecated.isDeprecated\n ? `deprecated [${audit.deprecated.scope}]: ${audit.deprecated.message}\\n`\n : 'deprecated: no\\n',\n )\n if (audit.vulnerabilities.length > 0) {\n io.out(`vulnerabilities (${audit.vulnerabilities.length}):\\n`)\n for (const v of audit.vulnerabilities) {\n const fixed = v.fixedIn.length ? ` fixed in: ${v.fixedIn.join(', ')}` : ''\n io.out(` ${v.id} [${v.severity}] ${v.summary ?? ''}${fixed}\\n`)\n }\n } else {\n io.out('vulnerabilities: none\\n')\n }\n const f = audit.freshness\n io.out(\n `freshness: installed ${f.installed}, latest ${f.latest ?? '?'}, same-major ${f.latestSameMajor ?? '?'}, outdated ${f.isOutdated ? 'yes' : 'no'}\\n`,\n )\n if (audit.recommendedTarget) io.out(`recommended target: ${audit.recommendedTarget}\\n`)\n if (audit.minimumSafeUpgrade) io.out(`minimum safe upgrade: ${audit.minimumSafeUpgrade}\\n`)\n io.out(\n loaded\n ? `osv snapshot: loaded${snapshotDate ? ` (${snapshotDate})` : ''}\\n`\n : 'osv snapshot: NOT loaded — treat \"no known vulnerabilities\" as unknown, not clean\\n',\n )\n}\n\nasync function cmdAudit(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...REGISTRY_OPTIONS, version: { type: 'string' } },\n })\n const [project, packageName] = positionals\n if (!project || !packageName) {\n io.err('deps audit needs <project> <package>\\n')\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchPackument = deps.fetchPackument ?? makeFetcher(r)\n const { advisories, snapshotDate, loaded } = loadAdvisories(values['osv-db'], ecosystem)\n\n try {\n const audit = await auditOne(\n project,\n packageName,\n ecosystem,\n fetchPackument,\n advisories,\n snapshotDate,\n values.version,\n )\n if (values.json) {\n io.out(`${JSON.stringify({ ...audit, osvSnapshotLoaded: loaded }, null, 2)}\\n`)\n } else {\n printAudit(io, audit, loaded, snapshotDate)\n }\n return isActionable(audit) ? 1 : 0\n } catch (e) {\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n\nasync function cmdAuditProject(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...REGISTRY_OPTIONS, 'skip-dev': { type: 'boolean' } },\n })\n const project = positionals[0]\n if (!project) {\n io.err('deps audit-project needs <project>\\n')\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchPackument = deps.fetchPackument ?? makeFetcher(r)\n const { advisories, snapshotDate, loaded } = loadAdvisories(values['osv-db'], ecosystem)\n const names = dependencyNames(project, ecosystem, !values['skip-dev'])\n\n const dependencies: {\n package: string\n installedVersion: string\n worstSeverity: DependencyAudit['worstSeverity']\n deprecated: boolean\n isOutdated: boolean\n recommendedTarget?: string\n minimumSafeUpgrade?: string\n vulnerabilityCount: number\n }[] = []\n const errors: { package: string; error: string }[] = []\n for (const name of names) {\n try {\n const audit = await auditOne(\n project,\n name,\n ecosystem,\n fetchPackument,\n advisories,\n snapshotDate,\n )\n dependencies.push({\n package: name,\n installedVersion: audit.installedVersion,\n worstSeverity: audit.worstSeverity,\n deprecated: audit.deprecated.isDeprecated,\n isOutdated: audit.freshness.isOutdated,\n recommendedTarget: audit.recommendedTarget,\n minimumSafeUpgrade: audit.minimumSafeUpgrade,\n vulnerabilityCount: audit.vulnerabilities.length,\n })\n } catch (err) {\n errors.push({ package: name, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const bySeverity: Record<string, number> = {}\n for (const d of dependencies) {\n if (d.worstSeverity !== 'none')\n bySeverity[d.worstSeverity] = (bySeverity[d.worstSeverity] ?? 0) + 1\n }\n const summary = {\n total: dependencies.length,\n withFindings: dependencies.filter((d) => d.worstSeverity !== 'none' || d.deprecated).length,\n deprecated: dependencies.filter((d) => d.deprecated).length,\n outdated: dependencies.filter((d) => d.isOutdated).length,\n bySeverity,\n osvSnapshotLoaded: loaded,\n snapshotDate,\n }\n\n if (values.json) {\n io.out(`${JSON.stringify({ project, ecosystem, summary, dependencies, errors }, null, 2)}\\n`)\n return summary.withFindings > 0 ? 1 : 0\n }\n io.out(\n `${project} (${ecosystem}) ${summary.total} deps; findings ${summary.withFindings}, deprecated ${summary.deprecated}, outdated ${summary.outdated}\\n`,\n )\n io.out(\n loaded\n ? `osv snapshot: loaded${snapshotDate ? ` (${snapshotDate})` : ''}\\n`\n : 'osv snapshot: NOT loaded — \"no known vulnerabilities\" is unknown, not clean\\n',\n )\n for (const d of dependencies) {\n if (d.worstSeverity === 'none' && !d.deprecated && !d.isOutdated) continue\n const tags = [\n d.worstSeverity !== 'none' ? `[${d.worstSeverity}]` : '',\n d.deprecated ? 'deprecated' : '',\n d.isOutdated ? 'outdated' : '',\n ]\n .filter(Boolean)\n .join(' ')\n const target = d.minimumSafeUpgrade ?? d.recommendedTarget\n io.out(` ${d.package} ${d.installedVersion} ${tags}${target ? ` → ${target}` : ''}\\n`)\n }\n for (const e of errors) io.out(` ! ${e.package}: ${e.error}\\n`)\n return summary.withFindings > 0 ? 1 : 0\n}\n\nasync function cmdChangelog(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher; fetchChangelog?: ChangelogFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...REGISTRY_OPTIONS,\n project: { type: 'string' },\n from: { type: 'string' },\n to: { type: 'string' },\n },\n })\n const packageName = positionals[0]\n if (!packageName) {\n io.err(\n 'deps changelog needs <package> (with --from or --project to detect the installed version)\\n',\n )\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchChangelog = deps.fetchChangelog ?? makeChangelogFetcher(r)\n\n try {\n let from = values.from\n if (from === undefined) {\n if (!values.project) {\n io.err('provide --from <version> or --project <dir> to determine the installed version\\n')\n return 1\n }\n const detected = detectInstalledVersion(values.project, packageName, {\n ecosystem: DETECT_ECOSYSTEM[ecosystem],\n })\n if (!detected.version) {\n io.err(`could not detect an installed version of \"${packageName}\" in ${values.project}\\n`)\n return 1\n }\n from = detected.version\n }\n const { text: markdown, source } = await fetchChangelog(packageName, ecosystem)\n const slice = sliceChangelog(markdown, {\n from,\n to: values.to,\n comparator: comparatorFor(ecosystem),\n })\n\n if (values.json) {\n io.out(\n `${JSON.stringify(\n {\n package: packageName,\n from: slice.from,\n to: slice.to ?? null,\n versionsCovered: slice.entries.map((e) => e.version),\n source,\n body: slice.entries.map((e) => e.body).join('\\n\\n'),\n },\n null,\n 2,\n )}\\n`,\n )\n return 0\n }\n io.out(\n `${packageName} ${slice.from} → ${slice.to ?? 'latest'} (${slice.entries.length} section(s)) [${source}]\\n`,\n )\n if (slice.entries.length === 0) {\n io.out('(no changelog sections in the requested range)\\n')\n return 0\n }\n for (const e of slice.entries) io.out(`\\n## ${e.version}\\n${e.body}\\n`)\n return 0\n } catch (e) {\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n FlakeGateError,\n type FlakeVerdict,\n HistoryStore,\n Quarantine,\n QuarantineGateError,\n quarantineCandidates,\n runAndRecord,\n runAndRecordPytest,\n type TestRunner,\n} from '@sackville-mcp/flake'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville flake` — the human surface over `@sackville-mcp/flake`.\n *\n * Reads (`status`/`candidates`) + `ingest`/`release` are always available against the\n * operator's private run-history DB (`--db`). `run` (spawns vitest) and `quarantine`\n * (the only write) each sit behind their own paired deny-by-default gate. The human IS\n * the operator, so those gates are straight-through flags (`--allow-run` /\n * `--allow-quarantine` + `--max-expiry-ms`), the typed root is auto-allowed, and the\n * vitest runner is injectable so the suite never spawns a real vitest (ADR 0010).\n */\nexport async function runFlake(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'status':\n return withStore(rest, io, cmdStatus)\n case 'candidates':\n return withStore(rest, io, cmdCandidates)\n case 'ingest':\n return withStore(rest, io, cmdIngest)\n case 'release':\n return withStore(rest, io, cmdRelease)\n case 'run':\n return withStore(rest, io, (store, a, o) => cmdRun(store, a, o, deps))\n case 'quarantine':\n return withStore(rest, io, cmdQuarantine)\n default:\n io.err(`unknown flake subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Open the operator's history DB (from `--db`/`SACKVILLE_FLAKE_DB`), run the command, close. */\nasync function withStore(\n args: string[],\n io: CliIO,\n fn: (store: HistoryStore, args: string[], io: CliIO) => number | Promise<number>,\n): Promise<number> {\n // `--db` is parsed here too so a missing path is caught before any work; the command\n // re-parses its own flags (parseArgs ignores unknown-but-declared elsewhere is false, so\n // we pass the full args through — each command declares `db` in its own options).\n const dbPath = readDbFlag(args) ?? io.env?.SACKVILLE_FLAKE_DB\n if (!dbPath) {\n io.err('no run-history DB given: pass --db <file> or set SACKVILLE_FLAKE_DB\\n')\n return 1\n }\n const store = HistoryStore.open(dbPath)\n try {\n return await fn(store, args, io)\n } finally {\n store.close()\n }\n}\n\n/** Pull just `--db <path>` out of an argv without consuming the rest. */\nfunction readDbFlag(args: string[]): string | undefined {\n const i = args.indexOf('--db')\n return i >= 0 ? args[i + 1] : undefined\n}\n\nfunction num(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\nfunction printVerdict(io: CliIO, v: FlakeVerdict): void {\n io.out(\n ` [${v.state}] ${v.id} runs ${v.runs} fail ${v.failures}/${v.runs} score ${v.flakeScore.toFixed(3)}\\n`,\n )\n}\n\nfunction cmdStatus(store: HistoryStore, args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n 'min-runs': { type: 'string' },\n 'limit-per-test': { type: 'string' },\n since: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const verdicts = store.classify({\n minRuns: num(values['min-runs']),\n limitPerTest: num(values['limit-per-test']),\n since: values.since,\n })\n const quarantined = new Quarantine(store, { allowQuarantine: false, maxExpiryMs: 0 }).active()\n\n if (values.json) {\n const summary: Record<string, number> = {}\n for (const v of verdicts) summary[v.state] = (summary[v.state] ?? 0) + 1\n io.out(`${JSON.stringify({ summary, verdicts, quarantined }, null, 2)}\\n`)\n return 0\n }\n const counts = { flaky: 0, reliable: 0, broken: 0, 'insufficient-data': 0 }\n for (const v of verdicts) counts[v.state]++\n io.out(\n `flaky ${counts.flaky} reliable ${counts.reliable} broken ${counts.broken} insufficient-data ${counts['insufficient-data']}\\n`,\n )\n if (verdicts.length > 0) {\n io.out('verdicts:\\n')\n for (const v of verdicts) printVerdict(io, v)\n }\n if (quarantined.length > 0) {\n io.out(`quarantined (${quarantined.length}):\\n`)\n for (const q of quarantined) io.out(` ${q.testId} until ${q.expiresAt} (${q.reason})\\n`)\n }\n return 0\n}\n\nfunction cmdCandidates(store: HistoryStore, args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n 'min-flake-score': { type: 'string' },\n 'min-runs': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const verdicts = store.classify({ minRuns: num(values['min-runs']) })\n const candidates = quarantineCandidates(verdicts, {\n minFlakeScore: num(values['min-flake-score']),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify({ candidates }, null, 2)}\\n`)\n return 0\n }\n if (candidates.length === 0) {\n io.out('no quarantine candidates\\n')\n return 0\n }\n io.out(`candidates (${candidates.length}):\\n`)\n for (const v of candidates) printVerdict(io, v)\n return 0\n}\n\nfunction cmdIngest(store: HistoryStore, args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n format: { type: 'string' },\n at: { type: 'string' },\n 'project-root': { type: 'string' },\n 'run-group': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const reportFile = positionals[0]\n if (!reportFile) {\n io.err('flake ingest needs a <report-file>\\n')\n return 1\n }\n const format = values.format ?? 'vitest'\n if (format !== 'vitest' && format !== 'pytest') {\n io.err(`unknown report format: ${format} (expected vitest|pytest)\\n`)\n return 1\n }\n const report = JSON.parse(readFileSync(reportFile, 'utf8'))\n const opts = {\n at: values.at ?? new Date().toISOString(),\n projectRoot: values['project-root'],\n runGroup: values['run-group'],\n }\n const recorded =\n format === 'pytest' ? store.ingestPytestReport(report, opts) : store.ingestReport(report, opts)\n\n if (values.json) {\n io.out(`${JSON.stringify({ format, recorded }, null, 2)}\\n`)\n return 0\n }\n io.out(`recorded ${recorded} run(s) from the ${format} report\\n`)\n return 0\n}\n\nfunction cmdRelease(store: HistoryStore, args: string[], io: CliIO): number {\n const { positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { db: { type: 'string' } },\n })\n const testId = positionals[0]\n if (!testId) {\n io.err('flake release needs a <testId>\\n')\n return 1\n }\n const released = new Quarantine(store, { allowQuarantine: false, maxExpiryMs: 0 }).release(testId)\n io.out(released ? `released ${testId}\\n` : `${testId} was not quarantined\\n`)\n return 0\n}\n\nasync function cmdRun(\n store: HistoryStore,\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n framework: { type: 'string' },\n repeat: { type: 'string' },\n file: { type: 'string', multiple: true },\n related: { type: 'boolean' },\n 'run-group': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('flake run needs a <project-root>\\n')\n return 1\n }\n const framework = values.framework ?? 'vitest'\n if (framework !== 'vitest' && framework !== 'pytest') {\n io.err(`unknown framework: ${framework} (expected vitest|pytest)\\n`)\n return 1\n }\n try {\n const run = framework === 'pytest' ? runAndRecordPytest : runAndRecord\n const result = await run(\n store,\n {\n projectRoot,\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: num(values['timeout-ms']),\n },\n {\n repeat: num(values.repeat) ?? 1,\n files: values.file,\n related: values.related,\n runGroup: values['run-group'],\n },\n { runner: deps.runner },\n )\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return 0\n }\n io.out(`ran ${result.iterations} iteration(s); recorded ${result.recorded} run(s)\\n`)\n for (const v of result.verdicts) printVerdict(io, v)\n return 0\n } catch (e) {\n if (e instanceof FlakeGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n\nfunction cmdQuarantine(store: HistoryStore, args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n reason: { type: 'string' },\n 'expires-at': { type: 'string' },\n 'flake-score': { type: 'string' },\n 'allow-quarantine': { type: 'boolean' },\n 'max-expiry-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const testId = positionals[0]\n if (!testId || !values.reason || !values['expires-at']) {\n io.err('flake quarantine needs <testId> --reason <r> --expires-at <ISO>\\n')\n return 1\n }\n const policy = {\n allowQuarantine: values['allow-quarantine'] ?? false,\n maxExpiryMs: num(values['max-expiry-ms']) ?? 0,\n }\n try {\n const entry = new Quarantine(store, policy).quarantine({\n testId,\n reason: values.reason,\n expiresAt: values['expires-at'],\n flakeScore: num(values['flake-score']),\n })\n if (values.json) {\n io.out(`${JSON.stringify({ entry }, null, 2)}\\n`)\n return 0\n }\n io.out(`quarantined ${entry.testId} until ${entry.expiresAt} (${entry.reason})\\n`)\n return 0\n } catch (e) {\n if (e instanceof QuarantineGateError) {\n io.err(`refused: ${e.message} (pass --allow-quarantine and --max-expiry-ms)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n defaultListFiles,\n LanguageServerManager,\n LspGateError,\n LspQueryEngine,\n type LspQueryInput,\n type LspQueryKind,\n type LspQueryResult,\n LspRenameEngine,\n type LspRenameInput,\n type LspRenameResult,\n parseServerRegistry,\n type ResultDiagnostic,\n type ResultSymbol,\n type ResultWorkspaceSymbol,\n type ServerDescription,\n type ServerRegistry,\n} from '@sackville-mcp/lsp'\nimport type { CliIO } from './index.js'\n\n/** Injected (test) or real engine entries. */\ntype QueryFn = (input: LspQueryInput) => Promise<LspQueryResult>\ntype RenameFn = (input: LspRenameInput) => Promise<LspRenameResult>\ntype DescribeFn = () => ServerDescription[]\n\nexport interface LspDeps {\n query?: QueryFn\n rename?: RenameFn\n describeServers?: DescribeFn\n}\n\n/**\n * `sackville lsp` — the human surface over `@sackville-mcp/lsp`. Single-shot semantic code\n * navigation: each invocation binds the operator's server registry, drives one query against\n * a live Language Server subprocess, then shuts it down.\n *\n * The human IS the operator, so the gates are straight-through flags: `--allow-run` (required\n * for any navigation — it spawns a code-executing indexing daemon, ADR 0011's\n * load-bearing gate) and `--allow-write` (lets `rename` write to disk; default = dry-run\n * preview). The typed `--project` root is the allowlist (explicit operator intent). Per ADR\n * 0011 the engine is **injectable** so the suite never spawns a real server — the production\n * path builds the real `LanguageServerManager`/`LspQueryEngine`/`LspRenameEngine` from flags\n * (mirroring `sackville-lsp-mcp`), and the gate throws *before* any spawn when `--allow-run` is\n * absent.\n *\n * Exit codes: 0 = the query ran (`ok`/`no_result`, or a rename preview/apply); 1 = denied,\n * refused, or error; 2 = `not_ready` (the server was still indexing — retry shortly).\n */\nexport async function runLsp(args: string[], io: CliIO, deps: LspDeps = {}): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'languages':\n return cmdLanguages(rest, io, deps)\n case 'definition':\n return cmdQuery('definition', rest, io, deps)\n case 'type-definition':\n return cmdQuery('typeDefinition', rest, io, deps)\n case 'references':\n return cmdQuery('references', rest, io, deps)\n case 'hover':\n return cmdQuery('hover', rest, io, deps)\n case 'symbols':\n return cmdQuery('documentSymbols', rest, io, deps)\n case 'diagnostics':\n return cmdQuery('diagnostics', rest, io, deps)\n case 'workspace-symbols':\n return cmdWorkspaceSymbols(rest, io, deps)\n case 'call-hierarchy':\n return cmdQuery('callHierarchy', rest, io, deps)\n case 'rename':\n return cmdRename(rest, io, deps)\n default:\n io.err(`unknown lsp subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nconst GATE_OPTIONS = {\n project: { type: 'string' },\n // Additional roots bound as workspace folders on the SAME server (multi-root). Repeatable.\n // The human is the operator, so passing a root authorizes it (it joins the allowlist).\n 'workspace-root': { type: 'string', multiple: true },\n servers: { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'allow-write': { type: 'boolean' },\n // Apply a rename the completeness guard flags `suspect` (open-files-scoped server → likely\n // partial). Deny-by-default: a suspect rename is refused for write without this.\n 'allow-partial-rename': { type: 'boolean' },\n // Apply a server `overwrite` on a Create/Rename (truncate-and-replace an EXISTING regular file).\n // Deny-by-default; requires --allow-write. Symlink/dir targets + recursive delete stay refused.\n 'allow-destructive-resource-ops': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n} as const\n\nfunction num(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\ninterface Engines {\n query: QueryFn\n rename: RenameFn\n describeServers: DescribeFn\n shutdown: () => Promise<void>\n projectRoot: string\n /** Resolved additional multi-root workspace folders (from `--workspace-root`). */\n workspaceRoots: string[]\n}\n\n/**\n * Build the query/rename engines — injected stubs in tests, else the real manager + engines\n * from the operator registry (`--servers`/`SACKVILLE_LSP_SERVERS`), gated by `--allow-run` /\n * `--allow-write` and confined to the `--project` root. Returns null on a config error (the\n * caller has already had the message written).\n */\nfunction makeEngines(values: Record<string, unknown>, io: CliIO, deps: LspDeps): Engines | null {\n const projectRoot = resolve((values.project as string) ?? process.cwd())\n const workspaceRoots = ((values['workspace-root'] as string[]) ?? []).map((r) => resolve(r))\n // A destructive overwrite is meaningless without write-mode; refuse the contradiction HARD (not a\n // silently-inert flag), uniformly for the stub + real paths.\n if (values['allow-destructive-resource-ops'] && !values['allow-write']) {\n io.err('--allow-destructive-resource-ops requires --allow-write\\n')\n return null\n }\n if (deps.query || deps.rename || deps.describeServers) {\n return {\n query: deps.query ?? (async () => fail('query')),\n rename: deps.rename ?? (async () => fail('rename')),\n describeServers: deps.describeServers ?? (() => []),\n shutdown: async () => {},\n projectRoot,\n workspaceRoots,\n }\n }\n const raw = (values.servers as string) ?? io.env?.SACKVILLE_LSP_SERVERS\n if (!raw || raw.trim() === '') {\n io.err('no servers bound: pass --servers <json> or set SACKVILLE_LSP_SERVERS\\n')\n return null\n }\n let registry: ServerRegistry\n try {\n registry = parseServerRegistry(raw)\n } catch (e) {\n io.err(`invalid --servers registry: ${(e as Error).message}\\n`)\n return null\n }\n const allowedRoots = [projectRoot, ...workspaceRoots]\n const manager = new LanguageServerManager({\n registry,\n allowedRoots,\n timeoutMs: num(values['timeout-ms'] as string) ?? 15_000,\n })\n const query = new LspQueryEngine({\n manager,\n allowRun: (values['allow-run'] as boolean) ?? false,\n allowedRoots,\n })\n const rename = new LspRenameEngine({\n manager,\n allowRun: (values['allow-run'] as boolean) ?? false,\n allowedRoots,\n allowWrite: (values['allow-write'] as boolean) ?? false,\n allowPartialRename: (values['allow-partial-rename'] as boolean) ?? false,\n allowDestructiveResourceOps: (values['allow-destructive-resource-ops'] as boolean) ?? false,\n // Wire the real walker so the partial-rename guard is active for the human CLI too.\n listFiles: defaultListFiles,\n })\n return {\n query: (input) => query.query(input),\n rename: (input) => rename.rename(input),\n describeServers: () => manager.describe(),\n shutdown: () => manager.shutdown(),\n projectRoot,\n workspaceRoots,\n }\n}\n\nfunction fail(what: string): never {\n throw new Error(`no ${what} engine available`)\n}\n\nfunction cmdLanguages(args: string[], io: CliIO, deps: LspDeps): number {\n const { values } = parseArgs({ args, allowPositionals: true, options: GATE_OPTIONS })\n const raw = (values.servers as string) ?? io.env?.SACKVILLE_LSP_SERVERS\n let languages: string[] = []\n if (raw && raw.trim() !== '') {\n try {\n languages = Object.keys(parseServerRegistry(raw)).sort()\n } catch (e) {\n io.err(`invalid --servers registry: ${(e as Error).message}\\n`)\n return 1\n }\n }\n const servers = (deps.describeServers ?? (() => []))()\n if (values.json) {\n io.out(`${JSON.stringify({ languages, servers }, null, 2)}\\n`)\n return 0\n }\n io.out(languages.length ? `bound languages: ${languages.join(', ')}\\n` : 'no languages bound\\n')\n for (const s of servers) {\n const v = s.serverInfo\n ? `${s.serverInfo.name}${s.serverInfo.version ? ` ${s.serverInfo.version}` : ''}`\n : '(no serverInfo)'\n io.out(` ${s.language} @ ${s.projectRoot} ${v}\\n`)\n }\n return 0\n}\n\n/** Tri-state status → exit code (ok/no_result ran; not_ready is transient). */\nfunction statusExit(status: string): number {\n return status === 'not_ready' ? 2 : 0\n}\n\nfunction rangeStr(r: {\n start: { line: number; column: number }\n end: { line: number; column: number }\n}): string {\n return `${r.start.line}:${r.start.column}-${r.end.line}:${r.end.column}`\n}\n\nfunction printHeader(io: CliIO, r: LspQueryResult): void {\n const info = r.serverInfo\n ? `${r.serverInfo.name}${r.serverInfo.version ? ` ${r.serverInfo.version}` : ''}`\n : 'unknown server'\n io.out(`status: ${r.status} [${r.kind}, ${r.encoding}, ${info}]\\n`)\n if (r.versionWarning) io.err(`warning: ${r.versionWarning}\\n`)\n}\n\nfunction printSymbols(io: CliIO, symbols: ResultSymbol[], depth: number): void {\n for (const s of symbols) {\n const detail = s.detail ? ` ${s.detail}` : ''\n io.out(`${' '.repeat(depth + 1)}${s.name} [${s.kindName}] ${rangeStr(s.range)}${detail}\\n`)\n if (s.children && s.children.length > 0) printSymbols(io, s.children, depth + 1)\n }\n}\n\nasync function cmdQuery(\n kind: LspQueryKind,\n args: string[],\n io: CliIO,\n deps: LspDeps,\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...GATE_OPTIONS, direction: { type: 'string' } },\n })\n const positionLess = kind === 'documentSymbols' || kind === 'diagnostics'\n const [language, file, lineRaw, colRaw] = positionals\n if (!language || !file || (!positionLess && (lineRaw === undefined || colRaw === undefined))) {\n io.err(\n positionLess\n ? `lsp ${kindCommand(kind)} needs <language> <file>\\n`\n : `lsp ${kindCommand(kind)} needs <language> <file> <line> <column>\\n`,\n )\n return 1\n }\n\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const input: LspQueryInput = {\n language,\n projectRoot: engines.projectRoot,\n file,\n kind,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n ...(positionLess ? {} : { line: Number(lineRaw), column: Number(colRaw) }),\n ...(kind === 'callHierarchy'\n ? { direction: (values.direction as 'incoming' | 'outgoing') ?? 'incoming' }\n : {}),\n }\n const result = await engines.query(input)\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return statusExit(result.status)\n }\n\n printHeader(io, result)\n if (result.status === 'not_ready') {\n io.out('the server is still indexing — retry shortly\\n')\n return 2\n }\n if (kind === 'hover') {\n io.out(result.hover ? `${result.hover.value}\\n` : 'no hover info\\n')\n } else if (kind === 'documentSymbols') {\n const symbols = result.symbols ?? []\n io.out(`${symbols.length} symbol(s):\\n`)\n printSymbols(io, symbols, 0)\n } else if (kind === 'diagnostics') {\n const diags = result.diagnostics ?? []\n io.out(`${diags.length} diagnostic(s):\\n`)\n for (const d of diags) {\n printDiagnostic(io, d)\n }\n } else if (kind === 'callHierarchy') {\n const groups = result.callHierarchy ?? []\n for (const g of groups) {\n io.out(`${g.source.name} [${g.source.kindName}] (${g.direction})\\n`)\n for (const c of g.calls) {\n io.out(` ${c.item.name} ${c.item.uri} ${c.fromRanges.map(rangeStr).join(', ')}\\n`)\n }\n }\n } else {\n const locations = result.locations ?? []\n io.out(`${locations.length} location(s):\\n`)\n for (const loc of locations) {\n io.out(` ${loc.uri} ${rangeStr(loc.range)}${loc.mapped ? '' : ' (unmapped)'}\\n`)\n }\n }\n return statusExit(result.status)\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\n/**\n * `workspace-symbols <language> <query> [anchorFile]` — position-less project-wide symbol search.\n * The optional `[anchorFile]` is opened first to establish the project; pass it for servers (like\n * `typescript-language-server`) that only build a project once a file is open.\n */\nasync function cmdWorkspaceSymbols(args: string[], io: CliIO, deps: LspDeps): Promise<number> {\n const { values, positionals } = parseArgs({ args, allowPositionals: true, options: GATE_OPTIONS })\n const [language, query, anchorFile] = positionals\n if (!language || query === undefined) {\n io.err('lsp workspace-symbols needs <language> <query> [anchorFile]\\n')\n return 1\n }\n\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const result = await engines.query({\n language,\n projectRoot: engines.projectRoot,\n kind: 'workspaceSymbol',\n query,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n ...(anchorFile !== undefined ? { file: anchorFile } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return statusExit(result.status)\n }\n\n printHeader(io, result)\n if (result.status === 'not_ready') {\n io.out('the server is still indexing — retry shortly\\n')\n return 2\n }\n const symbols = result.workspaceSymbols ?? []\n io.out(`${symbols.length} symbol(s):\\n`)\n for (const s of symbols) {\n printWorkspaceSymbol(io, s)\n }\n return statusExit(result.status)\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\nfunction printDiagnostic(io: CliIO, d: ResultDiagnostic): void {\n const sev = d.severityName ?? (d.severity !== undefined ? `severity ${d.severity}` : 'Diagnostic')\n const where = `${d.range.start.line}:${d.range.start.column}`\n const code = d.code !== undefined ? ` [${d.source ? `${d.source} ` : ''}${d.code}]` : ''\n io.out(` ${where} ${sev}${code} ${d.message}\\n`)\n for (const r of d.related ?? []) {\n io.out(` ↳ ${r.uri} ${r.range.start.line}:${r.range.start.column} ${r.message}\\n`)\n }\n}\n\nfunction printWorkspaceSymbol(io: CliIO, s: ResultWorkspaceSymbol): void {\n const container = s.container ? ` (in ${s.container})` : ''\n const loc = s.range ? ` ${rangeStr(s.range)}${s.mapped ? '' : ' (unmapped)'}` : ''\n io.out(` ${s.name} [${s.kindName}] ${s.uri}${loc}${container}\\n`)\n}\n\n/** Map a query kind back to its CLI subcommand name (for error messages). */\nfunction kindCommand(kind: LspQueryKind): string {\n if (kind === 'typeDefinition') return 'type-definition'\n if (kind === 'documentSymbols') return 'symbols'\n if (kind === 'callHierarchy') return 'call-hierarchy'\n return kind\n}\n\nasync function cmdRename(args: string[], io: CliIO, deps: LspDeps): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: GATE_OPTIONS,\n })\n const [language, file, lineRaw, colRaw, newName] = positionals\n if (!language || !file || lineRaw === undefined || colRaw === undefined || !newName) {\n io.err('lsp rename needs <language> <file> <line> <column> <newName>\\n')\n return 1\n }\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const result = await engines.rename({\n language,\n projectRoot: engines.projectRoot,\n file,\n line: Number(lineRaw),\n column: Number(colRaw),\n newName,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else {\n printRename(io, result)\n }\n if (result.status === 'not_ready') return 2\n if (result.refused) return 1\n return 0\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\nfunction printRename(io: CliIO, r: LspRenameResult): void {\n const info = r.serverInfo\n ? `${r.serverInfo.name}${r.serverInfo.version ? ` ${r.serverInfo.version}` : ''}`\n : 'unknown server'\n const mode = r.applied ? 'APPLIED to disk' : 'dry-run (not applied)'\n io.out(`status: ${r.status} ${mode} [${r.encoding}, ${info}]\\n`)\n if (r.versionWarning) io.err(`warning: ${r.versionWarning}\\n`)\n if (r.completeness === 'suspect') {\n const miss = r.suspectedMissedFiles ?? []\n io.err(\n `warning: rename may be INCOMPLETE — the symbol also appears in ${miss.length} same-language file(s) NOT in this edit: ${miss.join(', ')}\\n`,\n )\n io.err(\n ' the language server may scope rename to open files; re-run with --allow-partial-rename to apply anyway\\n',\n )\n } else if (r.completeness === 'unknown') {\n io.err('warning: rename completeness unverified (file scan was truncated)\\n')\n }\n if (r.refused) {\n io.err(`refused: ${r.refused}\\n`)\n return\n }\n io.out(`rename → ${r.newName}: ${r.totalEditCount} edit(s) across ${r.fileCount} file(s)\\n`)\n for (const f of r.edits) {\n io.out(` ${f.file} ${f.editCount} edit(s)${f.outOfRoot ? ' (out of project root)' : ''}\\n`)\n for (const h of f.hunks ?? []) {\n io.out(` ${rangeStr(h.range)} ${h.oldText} → ${h.newText}\\n`)\n }\n }\n for (const op of r.resourceOps ?? []) {\n io.out(` ${op.kind} file: ${op.uris.join(' → ')}\\n`)\n }\n if (r.overwritten?.length)\n io.err(\n `warning: DESTRUCTIVELY overwrote ${r.overwritten.length} existing file(s): ${r.overwritten.join(', ')}\\n`,\n )\n if (r.partial)\n io.err(`warning: PARTIAL apply (no rollback — reconcile via VCS): ${r.partialError ?? ''}\\n`)\n for (const d of r.digests ?? []) {\n io.out(\n ` digest ${d.file}: ${d.before.slice(0, 12)} → ${d.after.slice(0, 12) || '(deleted)'}\\n`,\n )\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n MutateGateError,\n type MutationReport,\n type MutationRunner,\n type MutationSummary,\n parseMutmutResults,\n runCosmicRay,\n runMutation,\n runMutmut,\n summarizeMutation,\n} from '@sackville-mcp/mutate'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville mutate` — the human surface over `@sackville-mcp/mutate`.\n *\n * `summarize` is a pure report viewer (Stryker JSON or `mutmut results` text). `run` is the\n * gated, diff-scopable mutation run. The CLI's human IS the operator, so the run gate is a\n * straight-through `--allow-run` flag (mirroring `sackville api --unsafe`): the typed project\n * root is auto-allowed (explicit operator intent). The `runner` is injectable so the suite\n * never spawns a real Stryker (ADR 0010: no real spawn in the gate).\n */\nexport async function runMutate(\n args: string[],\n io: CliIO,\n deps: { runner?: MutationRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'summarize':\n return cmdSummarize(rest, io)\n case 'run':\n return cmdRun(rest, io, deps)\n default:\n io.err(`unknown mutate subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Format a percent metric (`null` ⇒ not applicable, e.g. zero valid mutants). */\nfunction pct(value: number | null): string {\n return value === null ? 'n/a' : `${value.toFixed(1)}%`\n}\n\nfunction printSummary(io: CliIO, summary: MutationSummary): void {\n const { metrics, survivors } = summary\n const c = metrics.counts\n io.out(\n `mutation score: ${pct(metrics.mutationScore)} (detected ${metrics.detected} / valid ${metrics.valid})\\n`,\n )\n io.out(`covered-code score: ${pct(metrics.mutationScoreBasedOnCoveredCode)}\\n`)\n io.out(\n `killed ${c.killed} survived ${c.survived} timeout ${c.timeout} no-coverage ${c.noCoverage} ` +\n `compile-errors ${c.compileErrors} runtime-errors ${c.runtimeErrors} ignored ${c.ignored} pending ${c.pending}\\n`,\n )\n if (survivors.length === 0) {\n io.out('survivors: (none)\\n')\n return\n }\n io.out(`survivors (${survivors.length}):\\n`)\n for (const s of survivors) {\n io.out(` ${s.file}:${s.line} ${s.mutatorName} [${s.status}]\\n`)\n }\n}\n\nfunction cmdSummarize(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { format: { type: 'string' }, json: { type: 'boolean' } },\n })\n const reportFile = positionals[0]\n if (!reportFile) {\n io.err('mutate summarize needs a <report-file>\\n')\n return 1\n }\n const format = values.format ?? 'stryker'\n if (format !== 'stryker' && format !== 'mutmut') {\n io.err(`unknown report format: ${format} (expected stryker|mutmut)\\n`)\n return 1\n }\n const text = readFileSync(reportFile, 'utf8')\n // mutmut emits plain `module.fn__mutmut_N: status` lines; Stryker emits the\n // mutation-testing-elements JSON. Both normalize to a MutationReport.\n const report: MutationReport =\n format === 'mutmut' ? parseMutmutResults(text) : (JSON.parse(text) as MutationReport)\n const summary = summarizeMutation(report)\n\n if (values.json) {\n io.out(`${JSON.stringify(summary, null, 2)}\\n`)\n return 0\n }\n printSummary(io, summary)\n return 0\n}\n\nasync function cmdRun(\n args: string[],\n io: CliIO,\n deps: { runner?: MutationRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n tool: { type: 'string' },\n file: { type: 'string', multiple: true },\n incremental: { type: 'boolean' },\n 'config-path': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n 'report-path': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('mutate run needs a <project-root>\\n')\n return 1\n }\n const tool = values.tool ?? 'stryker'\n if (tool !== 'stryker' && tool !== 'mutmut' && tool !== 'cosmic-ray') {\n io.err(`unknown tool: ${tool} (expected stryker|mutmut|cosmic-ray)\\n`)\n return 1\n }\n const timeoutRaw = values['timeout-ms']\n const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) : undefined\n\n try {\n const config = {\n projectRoot,\n // The human typed this root, so it is the operator allowlist (explicit intent),\n // exactly as `sackville browser` auto-allows the typed host.\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: timeoutMs !== undefined && Number.isFinite(timeoutMs) ? timeoutMs : undefined,\n }\n const input = {\n mutateFiles: values.file,\n incremental: values.incremental ?? false,\n configPath: values['config-path'],\n }\n const result =\n tool === 'mutmut'\n ? await runMutmut(config, input, { runner: deps.runner })\n : tool === 'cosmic-ray'\n ? await runCosmicRay(config, input, { runner: deps.runner })\n : await runMutation(config, input, {\n runner: deps.runner,\n reportPath: values['report-path'],\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return result.exitCode === 0 ? 0 : 1\n }\n io.out(\n `ran ${tool} (exit ${result.exitCode}); scoped: ${result.scopedFiles.join(', ') || '(project default)'}\\n`,\n )\n printSummary(io, result.summary)\n return result.exitCode === 0 ? 0 : 1\n } catch (e) {\n if (e instanceof MutateGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { mkdtempSync, readFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n type CaptureContract,\n type ContractResult,\n loadCollection,\n runRequestToHar,\n validateCapturedTraffic,\n} from '@sackville-mcp/api'\nimport { ArtifactStore } from '@sackville-mcp/artifacts'\nimport {\n browserSecretsFromEnv,\n buildCaptureRuntime,\n type CaptureRequest,\n type CaptureRuntime,\n driveBrowserFlowToHar,\n} from '@sackville-mcp/browser'\nimport { type DiffCoverageReport, runScoped, type TestRunner } from '@sackville-mcp/coverage'\nimport { changedDependencies, type DependencyAudit, type OsvEcosystem } from '@sackville-mcp/deps'\nimport { type FlakeVerdict, HistoryStore, runAndRecord } from '@sackville-mcp/flake'\nimport {\n type MutationRunner,\n type MutationSummary,\n runCosmicRay,\n runMutation,\n runMutmut,\n} from '@sackville-mcp/mutate'\nimport { Redactor } from '@sackville-mcp/safety'\nimport {\n type CaptureVerdictFacts,\n type ComposeInputs,\n type CompositeVerdict,\n composeVerdict,\n fromContractResults,\n fromDependencyAudits,\n fromDiffCoverage,\n fromFlakeVerdicts,\n fromMutationSummary,\n type Severity,\n} from '@sackville-mcp/verdict'\nimport { type OrchestrateRequest, orchestrate } from '@sackville-mcp/verify'\nimport { auditProjectScoped, makeFetcher, type PackumentFetcher, registriesFrom } from './deps.js'\nimport type { CliIO } from './index.js'\n\nconst SEVERITIES = ['critical', 'high', 'moderate', 'low', 'none']\n\nconst EMPTY_COVERAGE: DiffCoverageReport = {\n files: [],\n uncovered: [],\n summary: { covered: 0, uncovered: 0, nonExecutable: 0, total: 0, filesWithoutCoverage: 0 },\n}\n\n/**\n * Per-pillar run thunk overrides — the test seam (mirrors the MCP `RunDrivingOptions`\n * shape). When absent, `verify run` builds the REAL engine-backed thunk; tests inject\n * fakes so the suite never spawns. The engine runner seams (`TestRunner`/`MutationRunner`)\n * are also injectable for the realistic path.\n */\nexport interface VerifyRunDeps {\n coverage?: (ctx: RunCtx) => Promise<DiffCoverageReport>\n flake?: (ctx: RunCtx) => Promise<FlakeVerdict[]>\n mutate?: (ctx: RunCtx) => Promise<MutationSummary>\n deps?: (ctx: RunCtx) => Promise<{ audits: DependencyAudit[]; osvSnapshotLoaded: boolean }>\n /** Produce-mode contract capture (drive a browser flow → validate). Injected in tests so\n * the suite never spawns a browser; the real path builds the runtime from CLI flags. */\n contract?: (req: CaptureRequest) => Promise<ContractResult[]>\n /** Produce-API contract capture (drive the api runner → synthesize + validate, 5f).\n * Injected in tests so the suite never fetches; the real path builds it from CLI flags. */\n contractApi?: (req: {\n request: string\n collectionDir?: string\n vars?: Record<string, string>\n }) => Promise<ContractResult[] | CaptureVerdictFacts>\n coverageRunner?: TestRunner\n flakeRunner?: TestRunner\n mutateRunner?: MutationRunner\n /** Injected packument fetcher for the realistic deps path (keeps the suite offline). */\n depsFetcher?: PackumentFetcher\n historyStore?: HistoryStore\n}\n\ninterface RunCtx {\n projectRoot: string\n changedFiles: string[]\n diff?: string\n}\n\n/**\n * `sackville verify` — the human surface over the cross-pillar verdict.\n *\n * - `verify [--contract f] [--coverage f] ...` (COMPOSE): fold per-pillar JSON results\n * on disk into one verdict (ADR 0013 §1). The human supplies each pillar's output.\n * - `verify run <root> [--coverage] [--flake --flake-db f] [--mutate [--mutate-tool T --mutate-config f]] [--deps] [--allow-run] ...`\n * (RUN-DRIVING, ADR 0013 Addendum 5c/5d): DRIVE the selected pillars and fold them. The\n * human is the operator, so `--allow-run` is the straight-through gate for the SPAWN\n * pillars (coverage/flake/mutate) and the typed root is auto-allowed; each pillar's own\n * `assertAllowed` still denies without it (⇒ `skipReason:gate-not-set`, never run —\n * \"compose, never widen\"). `--mutate-tool` picks the mutation engine (stryker default |\n * cosmic-ray | mutmut; the Python tools diff-scope via a synthesized config from\n * `--mutate-config`, ADR 0010 addendum 2). `--deps` is gated by NETWORK not spawn (a packument fetch),\n * so it needs no `--allow-run`; a `--diff` scopes the audit to the changed packages\n * (`changedDependencies`). `--flow <name>` (5e) DRIVES an operator-authored browser flow\n * to capture a HAR and validate it against `--openapi`/`--graphql` — gated by the browser\n * egress flags (`--flows-dir`/`--allow-host` + the mandatory SSRF proxy), not `--allow-run`.\n * Runners are injectable so the suite never spawns (ADR 0010).\n *\n * Exit codes (both modes): 0 pass / 1 fail|warn / 2 inconclusive.\n */\nexport async function runVerify(\n args: string[],\n io: CliIO,\n deps: VerifyRunDeps = {},\n): Promise<number> {\n if (args[0] === 'run') return cmdVerifyRun(args.slice(1), io, deps)\n return runVerifyCompose(args, io)\n}\n\nfunction printVerdict(io: CliIO, verdict: CompositeVerdict, json: boolean | undefined): void {\n if (json) {\n io.out(`${JSON.stringify(verdict, null, 2)}\\n`)\n return\n }\n io.out(`verdict: ${verdict.status.toUpperCase()} (worst severity ${verdict.worstSeverity})\\n`)\n for (const p of verdict.pillars) {\n const sev = p.severity !== 'none' ? ` [${p.severity}]` : ''\n const why = p.skipReason ? ` (skipped: ${p.skipReason})` : p.errorReason ? ' (errored)' : ''\n io.out(` ${p.pillar}: ${p.status}${sev}${why} — ${p.headline}\\n`)\n }\n}\n\nfunction exitFor(verdict: CompositeVerdict): number {\n if (verdict.status === 'pass') return 0\n if (verdict.status === 'inconclusive') return 2\n return 1\n}\n\nfunction num(value: string | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Number(value)\n return Number.isFinite(n) ? n : undefined\n}\n\nasync function cmdVerifyRun(args: string[], io: CliIO, deps: VerifyRunDeps): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n coverage: { type: 'boolean' },\n flake: { type: 'boolean' },\n mutate: { type: 'boolean' },\n 'mutate-tool': { type: 'string' },\n 'mutate-config': { type: 'string' },\n deps: { type: 'boolean' },\n 'allow-run': { type: 'boolean' },\n 'changed-file': { type: 'string', multiple: true },\n diff: { type: 'string' },\n 'flake-db': { type: 'string' },\n // deps run-driving: its gate is NETWORK (a packument fetch), not spawn — the human\n // typing --deps is the operator intent, so it needs no --allow-run.\n 'osv-db': { type: 'string' },\n registry: { type: 'string' },\n 'allow-private': { type: 'boolean' },\n // contract PRODUCE mode (5e): drive an operator-authored flow → capture → validate.\n // Gated by the browser egress flags (allowlist + the mandatory SSRF proxy), not --allow-run.\n flow: { type: 'string' },\n 'flows-dir': { type: 'string' },\n // contract PRODUCE-API mode (5f): drive an operator-authored api request → synthesize\n // + validate. Gated by --allow-unsafe + --allow-host (the api pillar gate), not --allow-run.\n request: { type: 'string' },\n 'collection-dir': { type: 'string' },\n 'allow-unsafe': { type: 'boolean' },\n 'allow-host': { type: 'string', multiple: true },\n var: { type: 'string', multiple: true },\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n 'graphql-endpoint': { type: 'string' },\n engine: { type: 'string' },\n 'no-sandbox': { type: 'boolean' },\n headed: { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n 'fail-at-or-above': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('verify run needs a <project-root>\\n')\n return 2\n }\n const failAtOrAbove = values['fail-at-or-above']\n if (failAtOrAbove !== undefined && !SEVERITIES.includes(failAtOrAbove)) {\n io.err(`--fail-at-or-above must be one of ${SEVERITIES.join('|')}\\n`)\n return 2\n }\n\n const allowRun = values['allow-run'] ?? false\n const allowedRoots = [resolve(projectRoot)]\n const changedFiles = values['changed-file'] ?? []\n const diff = values.diff !== undefined ? readFileSync(values.diff, 'utf8') : undefined\n const timeoutMs = num(values['timeout-ms'])\n const ctx: RunCtx = { projectRoot, changedFiles, diff }\n\n const request: OrchestrateRequest = {}\n if (values.coverage) {\n const ovr = deps.coverage\n request.coverage = {\n run: ovr\n ? () => ovr(ctx)\n : async () => {\n const r = await runScoped(\n { projectRoot, allowedRoots, allowRun, timeoutMs },\n { changedFiles, diff },\n { runner: deps.coverageRunner },\n )\n return r.report ?? EMPTY_COVERAGE\n },\n }\n }\n if (values.mutate) {\n const ovr = deps.mutate\n // Fork D: --mutate-tool selects the engine (default stryker); --mutate-config supplies the\n // Python tools' base config (cosmic-ray.toml / pyproject.toml). The runner is injectable so\n // the suite never spawns; --diff/--changed-file scope the run.\n const tool = values['mutate-tool'] ?? 'stryker'\n if (tool !== 'stryker' && tool !== 'cosmic-ray' && tool !== 'mutmut') {\n io.err(`verify run --mutate-tool must be stryker | cosmic-ray | mutmut (got ${tool})\\n`)\n return 2\n }\n const configPath = values['mutate-config']\n request.mutate = {\n run: ovr\n ? () => ovr(ctx)\n : async () => {\n const cfg = { projectRoot, allowedRoots, allowRun, timeoutMs }\n const mInput = { mutateFiles: changedFiles, configPath }\n const r =\n tool === 'cosmic-ray'\n ? await runCosmicRay(cfg, mInput, { runner: deps.mutateRunner })\n : tool === 'mutmut'\n ? await runMutmut(cfg, mInput, { runner: deps.mutateRunner })\n : await runMutation(cfg, mInput, { runner: deps.mutateRunner })\n return r.summary\n },\n }\n }\n if (values.flake) {\n const ovr = deps.flake\n if (ovr) {\n request.flake = { run: () => ovr(ctx) }\n } else {\n const dbPath = values['flake-db']\n const store = deps.historyStore ?? (dbPath ? HistoryStore.open(dbPath) : undefined)\n if (!store) {\n io.err('verify run --flake needs --flake-db <path>\\n')\n return 2\n }\n request.flake = {\n run: async () => {\n try {\n const r = await runAndRecord(\n store,\n { projectRoot, allowedRoots, allowRun, timeoutMs },\n // Diff-scope via `vitest related` (changed files are SOURCE files); no change set ⇒\n // whole suite, unchanged. See the MCP bin-verify flake thunk for the rationale.\n { files: changedFiles, related: changedFiles.length > 0 },\n { runner: deps.flakeRunner },\n )\n return r.verdicts\n } finally {\n if (!deps.historyStore && dbPath) store.close()\n }\n },\n }\n }\n }\n\n if (values.deps) {\n const ovr = deps.deps\n if (ovr) {\n request.deps = { run: () => ovr(ctx) }\n } else {\n // npm-first (matches the deps run-wiring); the diff scopes the audit to the\n // changed packages, falling back to the whole project when none changed.\n const ecosystem: OsvEcosystem = 'npm'\n const fetchPackument = deps.depsFetcher ?? makeFetcher(registriesFrom(values))\n const osvDir = values['osv-db']\n request.deps = {\n run: async () => {\n const scoped = diff ? changedDependencies(diff, ecosystem) : []\n const { audits, osvSnapshotLoaded } = await auditProjectScoped({\n project: projectRoot,\n ecosystem,\n names: scoped.length > 0 ? scoped : undefined,\n osvDir,\n fetchPackument,\n })\n return { audits, osvSnapshotLoaded }\n },\n }\n }\n }\n\n if (values.request && values.flow) {\n io.err('verify run: --request and --flow are mutually exclusive\\n')\n return 2\n }\n\n if (values.request) {\n const requestName = values.request\n const vars = parseVars(values.var)\n const ovr = deps.contractApi\n if (ovr) {\n request.contract = {\n source: 'capture-from-HAR',\n run: () => ovr({ request: requestName, collectionDir: values['collection-dir'], vars }),\n }\n } else {\n const colDir = values['collection-dir']\n if (!colDir) {\n io.err('verify run --request needs --collection-dir <dir>\\n')\n return 2\n }\n const contract = readCaptureContract(values)\n const store = new ArtifactStore(\n mkdtempSync(join(tmpdir(), 'sackville-verify-cap-')),\n 'verify',\n )\n // The human is the operator: --allow-unsafe + --allow-host are the api pillar gate\n // (a mutating request without them dry-runs ⇒ the driver throws ⇒ inconclusive). The\n // run-resolved {{secret:NAME}} pairs are folded into the redactor by the driver, so a\n // fresh Redactor scrubs both the stored HAR AND the findings (NOT the empty `{}` the\n // browser path can use — the synthesized api HAR holds raw bytes until redaction).\n request.contract = {\n source: 'capture-from-HAR',\n run: async () => {\n const out = await runRequestToHar(\n loadCollection(colDir),\n requestName,\n {\n vars,\n allowUnsafe: values['allow-unsafe'] ?? false,\n allowedHosts: values['allow-host'] ?? [],\n },\n { store, redactor: new Redactor(), contract },\n )\n return out.verdict\n },\n }\n }\n }\n\n if (values.flow) {\n const flow = values.flow\n const vars = parseVars(values.var)\n const ovr = deps.contract\n if (ovr) {\n request.contract = { source: 'capture-from-HAR', run: () => ovr({ flow, vars }) }\n } else {\n if (!values['flows-dir']) {\n io.err('verify run --flow needs --flows-dir <dir>\\n')\n return 2\n }\n const flowsDir = values['flows-dir']\n const contract = readCaptureContract(values)\n // The human is the operator: the typed flow's hosts are allowlisted via --allow-host;\n // the mandatory SSRF proxy fronts every request (built in the runtime factory).\n const store = new ArtifactStore(\n mkdtempSync(join(tmpdir(), 'sackville-verify-cap-')),\n 'verify',\n )\n request.contract = {\n source: 'capture-from-HAR',\n run: async () => {\n const { harHandle } = await driveBrowserFlowToHar(\n { flow, vars },\n { runtimeFactory: () => captureRuntimeFromFlags(values), store, flowsDir },\n )\n const har = store.get(harHandle)?.body\n if (!har) throw new Error('no HAR was captured for the driven flow')\n return validateCapturedTraffic(har, contract, {}).results\n },\n }\n }\n }\n\n if (Object.keys(request).length === 0) {\n io.err(\n 'verify run needs ≥1 pillar (--coverage / --flake / --mutate / --deps / --flow / --request)\\n',\n )\n return 2\n }\n\n const { verdict } = await orchestrate(request, {\n policy: { failAtOrAbove: failAtOrAbove as Severity | undefined },\n })\n printVerdict(io, verdict, values.json)\n return exitFor(verdict)\n}\n\n/** Parse repeated `--var k=v` flags into a map (non-secret flow vars). */\nfunction parseVars(pairs: string[] | undefined): Record<string, string> {\n const vars: Record<string, string> = {}\n for (const p of pairs ?? []) {\n const i = p.indexOf('=')\n if (i > 0) vars[p.slice(0, i)] = p.slice(i + 1)\n }\n return vars\n}\n\n/** Build the capture→contract from the openapi/graphql flags (≥1 needed, like the MCP tool). */\nfunction readCaptureContract(values: {\n openapi?: string\n graphql?: string\n 'graphql-endpoint'?: string\n}): CaptureContract {\n const contract: CaptureContract = {}\n if (values.openapi) contract.openapi = JSON.parse(readFileSync(values.openapi, 'utf8'))\n if (values.graphql) {\n contract.graphql = {\n endpointPath: values['graphql-endpoint'] ?? '/graphql',\n sdl: readFileSync(values.graphql, 'utf8'),\n }\n }\n return contract\n}\n\n/**\n * BrowserGate options for the `--flow` capture path, from the parsed CLI flags.\n * Exported for testing: a flow with `fill`/`click` steps is a MUTATION, so it\n * needs `--allow-unsafe` — without it every interaction dry-runs and the\n * flow-completeness guard fails the capture (the human typing the flag is the\n * operator, exactly as `sackville browser run --unsafe`).\n */\nexport function captureGateOptionsFromFlags(values: {\n 'allow-host'?: string[]\n 'allow-unsafe'?: boolean\n}): { allowedHosts: string[]; allowUnsafe: boolean } {\n return {\n allowedHosts: values['allow-host'] ?? [],\n allowUnsafe: values['allow-unsafe'] ?? false,\n }\n}\n\n/**\n * Build the `--flow` capture runtime from the CLI's browser egress flags. A thin\n * adapter over the shared `@sackville-mcp/browser` `buildCaptureRuntime` (one source\n * of truth across the browser CLI, this path, and the MCP server) — flags map to\n * the gate/proxy/engine options, `{{secret:NAME}}` resolves from\n * `SACKVILLE_BROWSER_SECRET_*` via the shared `browserSecretsFromEnv`, and a fresh\n * temp dir arms HAR recording for `driveBrowserFlowToHar`.\n */\nasync function captureRuntimeFromFlags(values: {\n 'allow-host'?: string[]\n 'allow-unsafe'?: boolean\n 'allow-private'?: boolean\n 'no-sandbox'?: boolean\n headed?: boolean\n engine?: string\n}): Promise<CaptureRuntime> {\n const { redact, resolveSecret } = browserSecretsFromEnv(process.env)\n return buildCaptureRuntime({\n ...captureGateOptionsFromFlags(values),\n allowPrivate: values['allow-private'] ?? false,\n engine: values.engine,\n headless: !values.headed,\n noSandbox: values['no-sandbox'] ?? false,\n harDir: mkdtempSync(join(tmpdir(), 'sackville-verify-har-')),\n redact,\n resolveSecret,\n })\n}\n\nfunction runVerifyCompose(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n options: {\n contract: { type: 'string' },\n source: { type: 'string' },\n coverage: { type: 'string' },\n deps: { type: 'string' },\n 'osv-snapshot-loaded': { type: 'boolean' },\n flake: { type: 'string' },\n mutate: { type: 'string' },\n 'fail-at-or-above': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n\n const failAtOrAbove = values['fail-at-or-above']\n if (failAtOrAbove !== undefined && !SEVERITIES.includes(failAtOrAbove)) {\n io.err(`--fail-at-or-above must be one of ${SEVERITIES.join('|')}\\n`)\n return 2\n }\n\n const readJson = (p: string): unknown => JSON.parse(readFileSync(p, 'utf8'))\n const inputs: ComposeInputs = {}\n\n if (values.contract) {\n const c = readJson(values.contract) as ContractResult[] | { results?: ContractResult[] }\n const results = Array.isArray(c) ? c : (c.results ?? [])\n inputs.contract = fromContractResults(\n results,\n values.source === 'run' ? 'run' : 'capture-from-HAR',\n )\n }\n if (values.coverage) {\n inputs.coverage = fromDiffCoverage(\n readJson(values.coverage) as Parameters<typeof fromDiffCoverage>[0],\n )\n }\n if (values.deps) {\n inputs.deps = fromDependencyAudits(\n readJson(values.deps) as Parameters<typeof fromDependencyAudits>[0],\n { osvSnapshotLoaded: values['osv-snapshot-loaded'] ?? false },\n )\n }\n if (values.flake) {\n inputs.flake = fromFlakeVerdicts(\n readJson(values.flake) as Parameters<typeof fromFlakeVerdicts>[0],\n )\n }\n if (values.mutate) {\n inputs.mutate = fromMutationSummary(\n readJson(values.mutate) as Parameters<typeof fromMutationSummary>[0],\n )\n }\n\n const verdict = composeVerdict(inputs, { failAtOrAbove: failAtOrAbove as Severity | undefined })\n printVerdict(io, verdict, values.json)\n return exitFor(verdict)\n}\n","import { parseArgs } from 'node:util'\nimport {\n detectInstalledVersion,\n type Ecosystem,\n getDoc,\n listVersions,\n openDb,\n resolveVersion,\n searchDocs,\n} from '@sackville-mcp/core'\nimport type { Embedder } from '@sackville-mcp/embed'\nimport type DatabaseType from 'better-sqlite3'\nimport { runApi } from './api.js'\nimport { runBrowser } from './browser.js'\nimport { runCoverage } from './coverage.js'\nimport { runDeps } from './deps.js'\nimport { runFlake } from './flake.js'\nimport { runLsp } from './lsp.js'\nimport { runMutate } from './mutate.js'\nimport { runVerify } from './verify.js'\n\n/** Output sinks and dependencies injected into `run` (so it is testable). */\nexport interface CliIO {\n out: (text: string) => void\n err: (text: string) => void\n /** When present, queries are embedded for hybrid search. */\n embedder?: Embedder\n env?: Record<string, string | undefined>\n}\n\nconst HELP = `sackville — version-pinned documentation search\n\nUsage:\n sackville search <query…> [-l <lib>] [--version <v>] [--installed <v>] [-p <dir>] [--ecosystem <e>] [--type <t>] [--limit <n>] [--json]\n sackville get <id> [--json]\n sackville versions <library>\n sackville detect <project> <library> [--ecosystem <node|python|ruby>]\n\nAPI testing:\n sackville api list <dir> [--json]\n sackville api get <dir> <name> [--json]\n sackville api run <dir> <name> [--var k=v…] [--env <e>] [--unsafe] [--allow-host <h>…] [--keyring] [--block-private] [--max-redirects <n>] [--openapi <spec.json>] [--json]\n sackville api run-collection <dir> <name…> [--var k=v…] [--env <e>] [--unsafe] [--allow-host <h>…] [--keyring] [--block-private] [--max-redirects <n>] [--stop-on-failure] [--json]\n sackville api validate --graphql <schema> --query <q> [--operation <name>] [--json]\n sackville api import <postman|insomnia|openapi|har> <source-file> <dest-dir> [--name <n>]\n\nBrowser testing (single-shot; the typed host is auto-allowed):\n sackville browser snapshot <url> [--allow-host <h>…] [--allow-private] [--no-sandbox] [--headed] [--engine chromium|firefox|webkit] [--json]\n sackville browser audit <url> [same flags] (exit 1 if any a11y violations)\n sackville browser screenshot <url> [--out <file>] [--full-page] [same flags]\n sackville browser run <flow.bru> [--var k=v…] [--unsafe] [--allow-host <h>…] [same flags] (replay a persisted flow; exit 1 on failure)\n\nMutation testing:\n sackville mutate summarize <report-file> [--format stryker|mutmut] [--json]\n sackville mutate run <project-root> [--file <f>…] [--incremental] [--allow-run] [--timeout-ms <n>] [--report-path <p>] [--json] (gated; needs --allow-run)\n\nCoverage (impact-scoped; exit 1 when a new line is uncovered):\n sackville coverage uncovered-in-diff --diff <file> --coverage <file> [--coverage-format istanbul|coveragepy] [--project-root <p>] [--json]\n sackville coverage run-scoped <project-root> --changed-file <f>… [--diff <file>] [--allow-run] [--timeout-ms <n>] [--json] (gated; needs --allow-run)\n\nFlaky-test detection (--db <run-history.db> or SACKVILLE_FLAKE_DB):\n sackville flake status [--min-runs <n>] [--limit-per-test <n>] [--since <ISO>] [--json]\n sackville flake candidates [--min-flake-score <0..1>] [--min-runs <n>] [--json]\n sackville flake ingest <report-file> [--format vitest|pytest] [--at <ISO>] [--project-root <p>] [--run-group <g>] [--json]\n sackville flake release <testId>\n sackville flake run <project-root> [--repeat <n>] [--file <f>…] [--run-group <g>] [--allow-run] [--timeout-ms <n>] [--json] (gated)\n sackville flake quarantine <testId> --reason <r> --expires-at <ISO> [--flake-score <s>] [--allow-quarantine] [--max-expiry-ms <n>] [--json] (gated write)\n\nDependency/version intelligence (for the INSTALLED version; exit 1 on a finding):\n sackville deps audit <project> <package> [--ecosystem npm|PyPI|RubyGems] [--version <v>] [--osv-db <dir>] [--registry <url>] [--allow-private] [--json]\n sackville deps audit-project <project> [--ecosystem <e>] [--skip-dev] [--osv-db <dir>] [--registry <url>] [--allow-private] [--json]\n sackville deps changelog <package> (--from <v> | --project <dir>) [--to <v>] [--ecosystem <e>] [--registry <url>] [--json]\n\nSemantic code navigation (LSP; single-shot; --servers <json> or SACKVILLE_LSP_SERVERS binds the server registry):\n sackville lsp languages [--servers <json>] [--json]\n sackville lsp definition|type-definition|references|hover <lang> <file> <line> <col> --project <dir> --allow-run [--servers <json>] [--timeout-ms <n>] [--json]\n sackville lsp symbols <lang> <file> --project <dir> --allow-run [--servers <json>] [--json]\n sackville lsp call-hierarchy <lang> <file> <line> <col> --project <dir> --allow-run [--direction incoming|outgoing] [--json]\n sackville lsp rename <lang> <file> <line> <col> <newName> --project <dir> --allow-run [--allow-write] [--allow-partial-rename] [--json] (dry-run unless --allow-write)\n (exit 2 = server still indexing, retry; a \"suspect\" rename — an open-files-scoped server's likely-partial edit — is refused for write unless --allow-partial-rename)\n\nGlobal:\n -i, --index <file> index to query (or set SACKVILLE_INDEX)\n`\n\nexport async function run(argv: string[], io: CliIO): Promise<number> {\n const [command, ...rest] = argv\n switch (command) {\n case 'search':\n return cmdSearch(rest, io)\n case 'get':\n return cmdGet(rest, io)\n case 'versions':\n return cmdVersions(rest, io)\n case 'detect':\n return cmdDetect(rest, io)\n case 'api':\n return runApi(rest, io)\n case 'browser':\n return runBrowser(rest, io)\n case 'mutate':\n return runMutate(rest, io)\n case 'coverage':\n return runCoverage(rest, io)\n case 'flake':\n return runFlake(rest, io)\n case 'deps':\n return runDeps(rest, io)\n case 'lsp':\n return runLsp(rest, io)\n case 'verify':\n return runVerify(rest, io)\n case 'help':\n case '--help':\n case '-h':\n io.out(HELP)\n return 0\n case undefined:\n io.err(HELP)\n return 1\n default:\n io.err(`unknown command: ${command}\\n`)\n io.err(HELP)\n return 1\n }\n}\n\nfunction openIndex(indexFlag: string | undefined, io: CliIO): DatabaseType.Database | null {\n const path = indexFlag ?? io.env?.SACKVILLE_INDEX\n if (!path) {\n io.err('no index given: pass --index <file> or set SACKVILLE_INDEX\\n')\n return null\n }\n return openDb(path)\n}\n\nasync function cmdSearch(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n index: { type: 'string', short: 'i' },\n library: { type: 'string', short: 'l' },\n version: { type: 'string' },\n installed: { type: 'string' },\n project: { type: 'string', short: 'p' },\n ecosystem: { type: 'string' },\n type: { type: 'string' },\n limit: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const query = positionals.join(' ').trim()\n if (!query) {\n io.err('search needs a query\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n\n try {\n // Version precedence: --version > --installed > --project (auto-detect).\n let effectiveVersion = values.version\n let note: string | undefined\n if (!values.version && (values.installed || values.project) && values.library) {\n let requested = values.installed\n if (!requested && values.project) {\n const detected = detectInstalledVersion(values.project, values.library, {\n ecosystem: values.ecosystem as Ecosystem | undefined,\n })\n requested = detected.version ?? undefined\n if (!requested) note = `could not detect ${values.library} in ${values.project}`\n }\n if (requested) {\n const res = resolveVersion(listVersions(db, values.library), requested)\n note = res.note\n if (res.resolved) effectiveVersion = res.resolved\n }\n }\n\n let queryVector: number[] | undefined\n if (io.embedder) {\n try {\n queryVector = await io.embedder.embed(query)\n } catch {\n queryVector = undefined\n }\n }\n\n const results = searchDocs(db, query, {\n library: values.library,\n version: effectiveVersion,\n type: values.type,\n limit: values.limit ? Number(values.limit) : undefined,\n queryVector,\n })\n\n if (values.json) {\n io.out(\n `${JSON.stringify({ query, version: effectiveVersion ?? null, note, results }, null, 2)}\\n`,\n )\n return 0\n }\n if (note) io.err(`${note}\\n`)\n if (results.length === 0) {\n io.out('no matches\\n')\n return 0\n }\n for (const r of results) {\n const sym = r.symbol ? ` (${r.symbol})` : ''\n io.out(`${r.version} [${r.type ?? '-'}] ${r.title}${sym}\\n`)\n io.out(` ${r.snippet}\\n`)\n io.out(` sackville://doc/${r.id}\\n`)\n }\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdGet(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' }, json: { type: 'boolean' } },\n })\n const id = Number(positionals[0])\n if (!Number.isInteger(id)) {\n io.err('get needs a numeric id\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const doc = getDoc(db, id)\n if (!doc) {\n io.err(`no document with id ${id}\\n`)\n return 1\n }\n if (values.json) {\n io.out(`${JSON.stringify(doc, null, 2)}\\n`)\n return 0\n }\n io.out(`${doc.title} [${doc.type ?? '-'}] ${doc.library} ${doc.version}\\n`)\n if (doc.headingPath) io.out(`${doc.headingPath}\\n`)\n if (doc.url) io.out(`${doc.url}\\n`)\n io.out(`\\n${doc.body}\\n`)\n if (doc.attribution) io.out(`\\n— ${doc.attribution}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdVersions(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' } },\n })\n const library = positionals[0]\n if (!library) {\n io.err('versions needs a library\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const versions = listVersions(db, library)\n io.out(versions.length ? `${versions.join('\\n')}\\n` : `no versions indexed for ${library}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdDetect(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' }, ecosystem: { type: 'string' } },\n })\n const [project, library] = positionals\n if (!project || !library) {\n io.err('detect needs <project> <library>\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const detected = detectInstalledVersion(project, library, {\n ecosystem: values.ecosystem as Ecosystem | undefined,\n })\n const res = resolveVersion(listVersions(db, library), detected.version ?? '')\n io.out(`detected: ${detected.version ?? '(none)'} (${detected.source})\\n`)\n io.out(`resolved: ${res.resolved ?? '(none)'}\\n`)\n io.out(`${res.note}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sackville-mcp/cli",
|
|
3
|
-
"version": "0.0.1-alpha.
|
|
3
|
+
"version": "0.0.1-alpha.5",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"license": "Apache-2.0",
|
|
6
6
|
"bin": {
|
|
@@ -20,19 +20,19 @@
|
|
|
20
20
|
],
|
|
21
21
|
"dependencies": {
|
|
22
22
|
"playwright-core": "1.60.0",
|
|
23
|
-
"@sackville-mcp/api": "0.0.1-alpha.
|
|
24
|
-
"@sackville-mcp/artifacts": "0.0.1-alpha.
|
|
25
|
-
"@sackville-mcp/
|
|
26
|
-
"@sackville-mcp/
|
|
27
|
-
"@sackville-mcp/
|
|
28
|
-
"@sackville-mcp/
|
|
29
|
-
"@sackville-mcp/
|
|
30
|
-
"@sackville-mcp/
|
|
31
|
-
"@sackville-mcp/
|
|
32
|
-
"@sackville-mcp/
|
|
33
|
-
"@sackville-mcp/
|
|
34
|
-
"@sackville-mcp/verdict": "0.0.1-alpha.
|
|
35
|
-
"@sackville-mcp/verify": "0.0.1-alpha.
|
|
23
|
+
"@sackville-mcp/api": "0.0.1-alpha.5",
|
|
24
|
+
"@sackville-mcp/artifacts": "0.0.1-alpha.5",
|
|
25
|
+
"@sackville-mcp/browser": "0.0.1-alpha.5",
|
|
26
|
+
"@sackville-mcp/core": "0.0.1-alpha.5",
|
|
27
|
+
"@sackville-mcp/deps": "0.0.1-alpha.5",
|
|
28
|
+
"@sackville-mcp/coverage": "0.0.1-alpha.5",
|
|
29
|
+
"@sackville-mcp/embed": "0.0.1-alpha.5",
|
|
30
|
+
"@sackville-mcp/flake": "0.0.1-alpha.5",
|
|
31
|
+
"@sackville-mcp/lsp": "0.0.1-alpha.5",
|
|
32
|
+
"@sackville-mcp/safety": "0.0.1-alpha.5",
|
|
33
|
+
"@sackville-mcp/mutate": "0.0.1-alpha.5",
|
|
34
|
+
"@sackville-mcp/verdict": "0.0.1-alpha.5",
|
|
35
|
+
"@sackville-mcp/verify": "0.0.1-alpha.5"
|
|
36
36
|
},
|
|
37
37
|
"devDependencies": {
|
|
38
38
|
"@types/better-sqlite3": "^7.6.13",
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"src-DM4aqvlX.mjs","names":["parseVars","cmdGet","cmdRun","ArtifactStore","cmdAudit","cmdRun","parseVars","Redactor","cmdRun","num","printVerdict","num","ArtifactStore","Redactor"],"sources":["../src/api.ts","../src/browser.ts","../src/coverage.ts","../src/deps.ts","../src/flake.ts","../src/lsp.ts","../src/mutate.ts","../src/verify.ts","../src/index.ts"],"sourcesContent":["import { readFileSync } from 'node:fs'\nimport { dirname, resolve } from 'node:path'\nimport { pathToFileURL } from 'node:url'\nimport { parseArgs } from 'node:util'\nimport {\n ArtifactStore,\n type ContractRequestCapture,\n type ContractResult,\n type ImportFormat,\n importToCollection,\n isGraphqlEnvelope,\n loadCollection,\n Redactor,\n type RunResult,\n resolveSecretStore,\n runRequest,\n runRequestForContract,\n runSequence,\n type ScalarCoercer,\n type SecretStore,\n validateCapturedTraffic,\n validateGraphqlOperation,\n validateOpenApiRequest,\n validateOpenApiResponse,\n} from '@sackville-mcp/api'\nimport type { CliIO } from './index.js'\n\n/**\n * Load an operator-supplied custom-scalar coercer module (ADR 0018 slice 6). The human is the\n * operator, so a real module path is permitted. Returns the coercer record, or `undefined` on\n * ANY failure (missing/throwing module, or a non-object default export) AFTER writing a loud\n * error — the caller MUST then exit non-zero, never silently fall back to no coercers (which\n * would look clean — an absence-laundering hazard).\n */\nasync function loadCoercers(\n file: string,\n io: CliIO,\n): Promise<Record<string, ScalarCoercer> | undefined> {\n let exported: unknown\n try {\n const mod = (await import(pathToFileURL(resolve(file)).href)) as { default?: unknown }\n exported = mod.default\n } catch (err) {\n io.err(`api: failed to load --coercers module ${file}: ${(err as Error).message}\\n`)\n return undefined\n }\n if (!exported || typeof exported !== 'object') {\n io.err(`api: --coercers module ${file} must default-export an object of scalar coercers\\n`)\n return undefined\n }\n return exported as Record<string, ScalarCoercer>\n}\n\n/** Matches `{{secret:NAME}}` references; captures the NAME only (never a value). */\nconst SECRET_RE = /\\{\\{\\s*secret:\\s*([^}\\s]+)\\s*\\}\\}/g\n\n/** Collect sorted, unique secret NAMES referenced anywhere in a string. */\nfunction secretNames(...sources: (string | undefined)[]): string[] {\n const names = new Set<string>()\n for (const s of sources) {\n if (!s) continue\n for (const m of s.matchAll(SECRET_RE)) {\n if (m[1]) names.add(m[1])\n }\n }\n return [...names].sort()\n}\n\n/** Replace `{{secret:NAME}}` references with a `[secret:NAME]` placeholder. */\nfunction maskSecrets(s: string): string {\n return s.replace(SECRET_RE, (_m, name) => `[secret:${name}]`)\n}\n\n/** Parse repeatable `--var k=v` flags (split on the FIRST `=`) into a record. */\nfunction parseVars(raw: string[] | undefined): Record<string, unknown> {\n const vars: Record<string, unknown> = {}\n for (const item of raw ?? []) {\n const eq = item.indexOf('=')\n if (eq === -1) {\n vars[item] = ''\n } else {\n vars[item.slice(0, eq)] = item.slice(eq + 1)\n }\n }\n return vars\n}\n\nexport async function runApi(args: string[], io: CliIO): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'list':\n return cmdList(rest, io)\n case 'get':\n return cmdGet(rest, io)\n case 'run':\n return cmdRun(rest, io)\n case 'run-collection':\n return cmdRunCollection(rest, io)\n case 'validate':\n return await cmdValidate(rest, io)\n case 'validate-request':\n return cmdValidateRequest(rest, io)\n case 'validate-capture':\n return cmdValidateCapture(rest, io)\n case 'import':\n return cmdImport(rest, io)\n default:\n io.err(`unknown api subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nfunction cmdList(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { json: { type: 'boolean' } },\n })\n const dir = positionals[0]\n if (!dir) {\n io.err('api list needs <dir>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n const requests = [...collection.requests.values()].map((e) => ({\n name: e.request.name,\n method: e.request.method,\n url: e.request.url,\n }))\n if (values.json) {\n io.out(`${JSON.stringify({ requests }, null, 2)}\\n`)\n return 0\n }\n for (const r of requests) {\n io.out(`${r.method} ${r.name} ${r.url}\\n`)\n }\n return 0\n}\n\nfunction cmdGet(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { json: { type: 'boolean' } },\n })\n const [dir, name] = positionals\n if (!dir || !name) {\n io.err('api get needs <dir> <name>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n const entry = collection.requests.get(name)\n if (!entry) {\n io.err(`no request named ${name}\\n`)\n return 1\n }\n const { request } = entry\n // Secret NAMES referenced in url/headers/body — never their values.\n const secrets = secretNames(\n request.url,\n ...request.headers.flatMap((h) => [h.name, h.value]),\n request.body?.content,\n )\n if (values.json) {\n io.out(\n `${JSON.stringify(\n {\n name: request.name,\n method: request.method,\n url: request.url,\n headers: request.headers,\n requiredSecrets: secrets,\n },\n null,\n 2,\n )}\\n`,\n )\n return 0\n }\n // Show headers but mask secret references so the value column never carries a\n // `{{secret:NAME}}` template (the required-secrets line is the canonical list).\n io.out(`${request.method} ${maskSecrets(request.url)}\\n`)\n for (const h of request.headers) {\n io.out(` ${h.name}: ${maskSecrets(h.value)}\\n`)\n }\n io.out(`required secrets: ${secrets.length ? secrets.join(', ') : '(none)'}\\n`)\n return 0\n}\n\n/** Shared run-option flags for `run` and `run-collection`. */\nconst RUN_OPTIONS = {\n var: { type: 'string', multiple: true },\n env: { type: 'string' },\n unsafe: { type: 'boolean' },\n 'allow-host': { type: 'string', multiple: true },\n 'block-private': { type: 'boolean' },\n 'max-redirects': { type: 'string' },\n keyring: { type: 'boolean' },\n json: { type: 'boolean' },\n} as const\n\n/** Parse `--max-redirects` (a non-negative integer) or undefined. */\nfunction parseMaxRedirects(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isInteger(n) && n >= 0 ? n : undefined\n}\n\n/** Secret store for a run: opt into the OS keyring (chained ahead of env) with\n * `--keyring`, else the env default (`SACKVILLE_SECRET_<NAME>`). */\nfunction secretsFor(keyring: boolean | undefined): SecretStore | undefined {\n return keyring ? resolveSecretStore({ keyring: true }) : undefined\n}\n\n/** Read a stored response body by handle and JSON-parse it; fall back to raw. */\nfunction parseStoredBody(artifacts: ArtifactStore, handle: string): unknown {\n const raw = artifacts.get(handle)?.body ?? ''\n try {\n return JSON.parse(raw)\n } catch {\n return raw\n }\n}\n\n/** Redact every finding's message AND path through a redactor that learned the run's\n * resolved secrets — a finding can echo a captured body/param/variable value. */\nfunction redactContract(\n raw: ContractResult,\n secrets: { name: string; value: string }[],\n): ContractResult {\n const redactor = new Redactor()\n for (const s of secrets) redactor.register(s.name, s.value)\n return {\n ...raw,\n findings: raw.findings.map((f) => ({\n ...f,\n message: redactor.redact(f.message),\n ...(f.path !== undefined ? { path: redactor.redact(f.path) } : {}),\n })),\n }\n}\n\nfunction printContract(io: CliIO, contract: ContractResult, label = 'contract'): void {\n io.out(`${label}: ${contract.valid ? 'valid' : 'INVALID'}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n}\n\nasync function cmdRun(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...RUN_OPTIONS,\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n coercers: { type: 'string' },\n },\n })\n const [dir, name] = positionals\n if (!dir || !name) {\n io.err('api run needs <dir> <name>\\n')\n return 1\n }\n const collection = loadCollection(dir)\n if (!collection.requests.has(name)) {\n io.err(`no request named ${name}\\n`)\n return 1\n }\n const artifacts = new ArtifactStore()\n // --unsafe/--allow-host are operator (human) controlled here — correct for a\n // CLI the human runs; pass them straight through to the engine.\n const runOpts = {\n vars: parseVars(values.var),\n env: values.env,\n allowUnsafe: values.unsafe ?? false,\n allowedHosts: values['allow-host'],\n allowPrivate: !values['block-private'],\n maxRedirects: parseMaxRedirects(values['max-redirects']),\n secrets: secretsFor(values.keyring),\n artifacts,\n }\n // When validating against a contract, capture the UN-redacted sent request too, so\n // its body/params can be type-checked (ADR 0014); RunResult itself stays redacted.\n let result: RunResult\n let reqCapture: ContractRequestCapture | undefined\n if (values.openapi || values.graphql) {\n const driven = await runRequestForContract(collection, name, runOpts)\n result = driven.result\n reqCapture = driven.capture\n } else {\n result = await runRequest(collection, name, runOpts)\n }\n\n let contract: ContractResult | undefined\n let requestContract: ContractResult | undefined\n if (values.openapi) {\n const spec = JSON.parse(readFileSync(values.openapi, 'utf8'))\n const baseDir = dirname(values.openapi)\n // Response validation needs a sent response; request validation does not — the\n // request is fully known at prepare time, so it runs even on a withheld dry-run.\n if (result.sent && result.response) {\n const url = new URL(result.request.url)\n contract = validateOpenApiResponse(\n spec,\n { method: result.request.method, path: url.pathname },\n {\n status: result.response.status,\n headers: result.response.headers,\n body: parseStoredBody(artifacts, result.response.bodyHandle),\n },\n // External local-file $refs resolve relative to the spec file's directory.\n { baseDir },\n )\n }\n // A GraphQL request envelope has no REST requestBody/param model — skip it (the\n // capture→contract bridge routes GraphQL to schema validation separately).\n if (reqCapture && !isGraphqlEnvelope(reqCapture.request.body)) {\n const raw = validateOpenApiRequest(spec, reqCapture.request, {\n baseDir,\n // The CLI holds the real sent request, so body presence + params are authoritative.\n bodyPresenceAuthoritative: true,\n paramsAuthoritative: true,\n })\n requestContract = redactContract(raw, reqCapture.registeredSecrets)\n }\n }\n\n // --graphql validates a GraphQL run's query + variables (+ response errors) against the\n // supplied SDL — the symmetric parallel to --openapi (ADR 0015). The CLI holds the real\n // request, so variables are authoritative.\n let graphqlContract: ContractResult | undefined\n if (values.graphql && reqCapture && isGraphqlEnvelope(reqCapture.request.body)) {\n const sdl = readFileSync(values.graphql, 'utf8')\n // --coercers loads operator custom-scalar coercers (ADR 0018, the second wire point);\n // a load failure is LOUD + non-zero, never a silent no-coercer fall-through.\n let scalarCoercers: Record<string, ScalarCoercer> | undefined\n if (values.coercers !== undefined) {\n scalarCoercers = await loadCoercers(values.coercers, io)\n if (scalarCoercers === undefined) return 1\n }\n const env = reqCapture.request.body as {\n query: string\n operationName?: string\n variables?: unknown\n }\n const raw = validateGraphqlOperation(sdl, env.query, {\n operationName: env.operationName,\n ...(scalarCoercers ? { scalarCoercers } : {}),\n ...(result.sent && result.response\n ? { json: parseStoredBody(artifacts, result.response.bodyHandle) }\n : {}),\n ...(env.variables !== undefined\n ? { variables: env.variables, variablesAuthoritative: true }\n : {}),\n })\n graphqlContract = redactContract(raw, reqCapture.registeredSecrets)\n }\n\n // Return code: 0 only if SENT and every assertion passed and (if validated) both the\n // response AND request contracts are valid; 1 otherwise — including a dry-run, since a\n // withheld request verified nothing (though its request contract is still surfaced).\n const assertionsOk = !!result.response?.assertions.every((a) => a.pass)\n const ok =\n result.sent &&\n assertionsOk &&\n (contract ? contract.valid : true) &&\n (requestContract ? requestContract.valid : true) &&\n (graphqlContract ? graphqlContract.valid : true)\n\n if (values.json) {\n io.out(\n `${JSON.stringify({ ...result, ...(contract ? { contract } : {}), ...(requestContract ? { requestContract } : {}), ...(graphqlContract ? { graphqlContract } : {}) }, null, 2)}\\n`,\n )\n return ok ? 0 : 1\n }\n\n io.out(`${result.request.method} ${result.request.url}\\n`)\n if (result.sent) {\n io.out('sent\\n')\n } else {\n io.out(`dry-run (not sent)${result.reason ? `: ${result.reason}` : ''}\\n`)\n }\n if (result.response) {\n const res = result.response\n io.out(`status ${res.status} ${res.latencyMs}ms\\n`)\n for (const a of res.assertions) {\n io.out(`${a.pass ? 'PASS' : 'FAIL'} ${a.source} ${a.op}${a.path ? ` ${a.path}` : ''}\\n`)\n }\n for (const t of res.scriptTests) {\n io.out(`${t.pass ? 'PASS' : 'FAIL'} script: ${t.name}${t.error ? ` — ${t.error}` : ''}\\n`)\n }\n io.out(`body: ${res.bodyHandle}\\n`)\n }\n if (requestContract) printContract(io, requestContract, 'request contract')\n if (contract) printContract(io, contract, 'response contract')\n if (graphqlContract) printContract(io, graphqlContract, 'graphql contract')\n return ok ? 0 : 1\n}\n\nasync function cmdRunCollection(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...RUN_OPTIONS, 'stop-on-failure': { type: 'boolean' } },\n })\n const [dir, ...names] = positionals\n if (!dir || names.length === 0) {\n io.err('api run-collection needs <dir> <name...>\\n')\n return 1\n }\n const artifacts = new ArtifactStore()\n const result = await runSequence(loadCollection(dir), names, {\n vars: parseVars(values.var),\n env: values.env,\n allowUnsafe: values.unsafe ?? false,\n allowedHosts: values['allow-host'],\n allowPrivate: !values['block-private'],\n maxRedirects: parseMaxRedirects(values['max-redirects']),\n secrets: secretsFor(values.keyring),\n stopOnFailure: values['stop-on-failure'] ?? false,\n artifacts,\n })\n\n // 0 only if every SENT step passed its assertions.\n const ok = result.steps.every(\n (s) => s.result.sent && (s.result.response?.assertions.every((a) => a.pass) ?? false),\n )\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return ok ? 0 : 1\n }\n\n for (const step of result.steps) {\n const res = step.result\n const status = res.sent ? String(res.response?.status ?? '-') : 'dry-run'\n const passed = res.sent && (res.response?.assertions.every((a) => a.pass) ?? false)\n io.out(`${step.name} ${status} ${passed ? 'PASS' : 'FAIL'}\\n`)\n }\n io.out(`captured: ${Object.keys(result.captured).join(', ') || '(none)'}\\n`)\n return ok ? 0 : 1\n}\n\nconst IMPORT_FORMATS = new Set<ImportFormat>(['postman', 'insomnia', 'openapi', 'har'])\n\nfunction cmdImport(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { name: { type: 'string' } },\n })\n const [format, source, dest] = positionals\n if (!format || !source || !dest) {\n io.err('api import needs <postman|insomnia|openapi|har> <source-file> <dest-dir>\\n')\n return 1\n }\n if (!IMPORT_FORMATS.has(format as ImportFormat)) {\n io.err(`unknown import format: ${format} (expected postman|insomnia|openapi|har)\\n`)\n return 1\n }\n const text = readFileSync(source, 'utf8')\n const count = importToCollection(format as ImportFormat, text, dest, { name: values.name })\n io.out(`imported ${count} request(s) into ${dest}\\n`)\n return 0\n}\n\nasync function cmdValidate(args: string[], io: CliIO): Promise<number> {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n graphql: { type: 'string' },\n query: { type: 'string' },\n operation: { type: 'string' },\n variables: { type: 'string' },\n coercers: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n if (!values.graphql || !values.query) {\n io.err('api validate needs --graphql <schemafile> --query <queryfile>\\n')\n return 1\n }\n const sdl = readFileSync(values.graphql, 'utf8')\n const query = readFileSync(values.query, 'utf8')\n // --variables accepts inline JSON or a file path. The human supplies the real request,\n // so variables are authoritative (an absent required variable is a finding, not skipped).\n let variables: unknown\n if (values.variables !== undefined) {\n try {\n variables = JSON.parse(values.variables)\n } catch {\n variables = JSON.parse(readFileSync(values.variables, 'utf8'))\n }\n }\n // --coercers loads an operator module of custom-scalar coercers (ADR 0018). A load failure\n // is LOUD + non-zero — never a silent fall-through to no-coercer `unverified` (which looks clean).\n let scalarCoercers: Record<string, ScalarCoercer> | undefined\n if (values.coercers !== undefined) {\n scalarCoercers = await loadCoercers(values.coercers, io)\n if (scalarCoercers === undefined) return 1\n }\n const contract = validateGraphqlOperation(sdl, query, {\n operationName: values.operation,\n ...(scalarCoercers ? { scalarCoercers } : {}),\n ...(variables !== undefined ? { variables, variablesAuthoritative: true } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(contract, null, 2)}\\n`)\n return contract.valid ? 0 : 1\n }\n io.out(`valid: ${contract.valid}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n return contract.valid ? 0 : 1\n}\n\n/**\n * `api validate-request --openapi <spec.json> --method <M> --path </p> [--body <file>]\n * [--query k=v]…` — a preflight: validate a request's body + params against an OpenAPI\n * operation BEFORE sending it. The human supplies the real request, so body presence\n * and params are authoritative. (A GraphQL envelope is refused, not schema-failed.)\n */\nfunction cmdValidateRequest(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n openapi: { type: 'string' },\n method: { type: 'string' },\n path: { type: 'string' },\n body: { type: 'string' },\n query: { type: 'string', multiple: true },\n header: { type: 'string', multiple: true },\n form: { type: 'string', multiple: true },\n 'form-file': { type: 'string', multiple: true },\n json: { type: 'boolean' },\n },\n })\n if (!values.openapi || !values.method || !values.path) {\n io.err('api validate-request needs --openapi <spec.json> --method <M> --path </p>\\n')\n return 1\n }\n const spec = JSON.parse(readFileSync(values.openapi, 'utf8'))\n const body = values.body !== undefined ? JSON.parse(readFileSync(values.body, 'utf8')) : undefined\n if (isGraphqlEnvelope(body)) {\n io.err(\n 'the request body is a GraphQL envelope ({query}); use `api validate --graphql` instead\\n',\n )\n return 1\n }\n // `--query name=value` (repeatable; repeated names collect into an array).\n const query: Record<string, string | string[]> = {}\n for (const kv of values.query ?? []) {\n const eq = kv.indexOf('=')\n if (eq < 0) continue\n const k = kv.slice(0, eq)\n const v = kv.slice(eq + 1)\n const cur = query[k]\n query[k] = cur === undefined ? v : Array.isArray(cur) ? [...cur, v] : [cur, v]\n }\n // `--header name:value` (repeatable), lower-cased.\n const headers: Record<string, string> = {}\n for (const hv of values.header ?? []) {\n const c = hv.indexOf(':')\n if (c < 0) continue\n headers[hv.slice(0, c).trim().toLowerCase()] = hv.slice(c + 1).trim()\n }\n // `--form name=value` (repeatable; repeated names → array): the structured field map of\n // a form-urlencoded / multipart text body. The content-type header routes validation.\n const form: Record<string, string | string[]> = {}\n for (const kv of values.form ?? []) {\n const eq = kv.indexOf('=')\n if (eq < 0) continue\n const k = kv.slice(0, eq)\n const v = kv.slice(eq + 1)\n const cur = form[k]\n form[k] = cur === undefined ? v : Array.isArray(cur) ? [...cur, v] : [cur, v]\n }\n // `--form-file name` (repeatable): multipart FILE part names (presence only).\n const formFileFields = values['form-file'] ?? []\n\n const contract = validateOpenApiRequest(\n spec,\n {\n method: values.method,\n path: values.path,\n body,\n ...(Object.keys(query).length > 0 ? { query } : {}),\n ...(Object.keys(headers).length > 0 ? { headers } : {}),\n ...(Object.keys(form).length > 0 ? { form } : {}),\n ...(formFileFields.length > 0 ? { formFileFields } : {}),\n },\n {\n baseDir: dirname(values.openapi),\n bodyPresenceAuthoritative: true,\n paramsAuthoritative: true,\n },\n )\n\n if (values.json) {\n io.out(`${JSON.stringify(contract, null, 2)}\\n`)\n return contract.valid ? 0 : 1\n }\n io.out(`valid: ${contract.valid}\\n`)\n for (const f of contract.findings) {\n io.out(` ${f.severity.toUpperCase()} ${f.kind}: ${f.message}${f.path ? ` (${f.path})` : ''}\\n`)\n }\n return contract.valid ? 0 : 1\n}\n\n/**\n * `api validate-capture <har.zip> --openapi <spec.json> | --graphql <schema.graphql>`\n * — validate the traffic in a captured HAR against an OpenAPI and/or GraphQL\n * contract (ADR 0013, the capture→contract bridge). The human is the operator, so\n * the local HAR file is read directly (no surface capture gate). REST entries are\n * checked against the OpenAPI spec; GraphQL entries (at `--graphql-endpoint`,\n * default `/graphql`) are checked against the SDL. Exits 1 when not clean.\n */\nfunction cmdValidateCapture(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n 'graphql-endpoint': { type: 'string' },\n origin: { type: 'string', multiple: true },\n json: { type: 'boolean' },\n },\n })\n const [harPath] = positionals\n if (!harPath || (!values.openapi && !values.graphql)) {\n io.err(\n 'api validate-capture needs <har.zip> and --openapi <spec.json> and/or --graphql <schema.graphql>\\n',\n )\n return 1\n }\n const harZip = readFileSync(harPath)\n const contract: import('@sackville-mcp/api').CaptureContract = {\n ...(values.openapi ? { openapi: JSON.parse(readFileSync(values.openapi, 'utf8')) } : {}),\n ...(values.graphql\n ? {\n graphql: {\n endpointPath: values['graphql-endpoint'] ?? '/graphql',\n sdl: readFileSync(values.graphql, 'utf8'),\n },\n }\n : {}),\n }\n const verdict = validateCapturedTraffic(harZip, contract, {\n allowedOrigins: values.origin,\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(verdict, null, 2)}\\n`)\n return verdict.clean ? 0 : 1\n }\n io.out(\n `capture: ${verdict.clean ? 'clean' : 'NOT CLEAN'} (${verdict.entriesValidated} entries)\\n`,\n )\n for (const [kind, count] of Object.entries(verdict.findingsByKind)) {\n io.out(` ${count}× ${kind}\\n`)\n }\n if (verdict.firstFailing) {\n const f = verdict.firstFailing\n io.out(` first failing: ${f.method} ${f.path} — ${f.kind}: ${f.message}\\n`)\n }\n io.out(` exercised: ${verdict.exercisedOperations.join(', ') || '(none)'}\\n`)\n if (verdict.unexercisedOperations.length > 0) {\n io.out(` unexercised: ${verdict.unexercisedOperations.join(', ')}\\n`)\n }\n return verdict.clean ? 0 : 1\n}\n","import { mkdtempSync, writeFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n ArtifactStore,\n auditA11y,\n type BrowserEngine,\n BrowserGate,\n BrowserManager,\n createSsrfProxy,\n engineLauncher,\n type FlowResult,\n loadFlow,\n PageDriver,\n resolveEngine,\n runFlow,\n} from '@sackville-mcp/browser'\nimport { Redactor } from '@sackville-mcp/safety'\nimport type { Browser, Page } from 'playwright-core'\nimport type { CliIO } from './index.js'\n\n/**\n * Human-facing `sackville browser …` — single-shot page-inspection commands over\n * the `@sackville-mcp/browser` engine. Each command navigates once and reads, so the\n * per-snapshot refs never need to outlive the process (unlike the stateful MCP\n * surface). The egress boundary mirrors the server bin: navigation is gated by an\n * allowlist (the typed host is auto-allowed, since the human explicitly asked for\n * it) and a **mandatory** DNS-pinning SSRF proxy fronts every request. The human\n * is the operator here, so the safety flags are theirs to set.\n */\n\ninterface BrowserFlags {\n allowHost: string[]\n allowPrivate: boolean\n noSandbox: boolean\n headed: boolean\n engine: BrowserEngine\n}\n\n/** Flags shared by every browser command. */\nconst COMMON_OPTIONS = {\n 'allow-host': { type: 'string', multiple: true },\n 'allow-private': { type: 'boolean' },\n 'no-sandbox': { type: 'boolean' },\n headed: { type: 'boolean' },\n engine: { type: 'string' },\n json: { type: 'boolean' },\n} as const\n\ntype CommonValues = {\n 'allow-host'?: string[]\n 'allow-private'?: boolean\n 'no-sandbox'?: boolean\n headed?: boolean\n engine?: string\n}\n\nfunction flagsFrom(values: CommonValues): BrowserFlags {\n return {\n allowHost: values['allow-host'] ?? [],\n allowPrivate: values['allow-private'] ?? false,\n noSandbox: values['no-sandbox'] ?? false,\n headed: values.headed ?? false,\n engine: resolveEngine(values.engine),\n }\n}\n\n/** Launch thunk for a `BrowserManager`, honoring the selected engine + the\n * mandatory SSRF proxy (chromium gets the hardening args; firefox/webkit get the\n * proxy + the Tier-1 route allowlist). */\nfunction launchFor(flags: BrowserFlags, proxyUrl: string): () => Promise<Browser> {\n return engineLauncher(flags.engine, {\n headless: !flags.headed,\n proxyServer: proxyUrl,\n noSandbox: flags.noSandbox,\n })\n}\n\ninterface SessionContext {\n driver: PageDriver\n store: ArtifactStore\n page: Page\n}\n\n/**\n * Stand up a gated, proxy-fronted browser, navigate to `url`, run `fn`, and tear\n * everything down. Returns `undefined` for a bad URL (after reporting it).\n */\nasync function withSession(\n url: string,\n flags: BrowserFlags,\n io: CliIO,\n fn: (ctx: SessionContext) => Promise<number>,\n): Promise<number> {\n let host: string\n try {\n host = new URL(url).hostname\n } catch {\n io.err(`invalid url: ${url}\\n`)\n return 1\n }\n // The human typed this URL → auto-allow its host, plus any extra --allow-host.\n const gate = new BrowserGate({ allowedHosts: [host, ...flags.allowHost] })\n const proxy = await createSsrfProxy({ allowPrivate: flags.allowPrivate })\n const store = new ArtifactStore(mkdtempSync(join(tmpdir(), 'sackville-browser-cli-')))\n const manager = new BrowserManager({\n gate,\n launch: launchFor(flags, proxy.url),\n })\n try {\n const context = await manager.createSession('cli')\n const page = await context.newPage()\n const driver = new PageDriver(page, { runId: 'cli', store, gate })\n await driver.navigate(url)\n return await fn({ driver, store, page })\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n } finally {\n await manager.shutdown()\n await proxy.close()\n }\n}\n\nexport async function runBrowser(args: string[], io: CliIO): Promise<number> {\n const [sub, ...rest] = args\n try {\n switch (sub) {\n case 'snapshot':\n return await cmdSnapshot(rest, io)\n case 'audit':\n return await cmdAudit(rest, io)\n case 'screenshot':\n return await cmdScreenshot(rest, io)\n case 'run':\n return await cmdRun(rest, io)\n default:\n io.err(`unknown browser subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n } catch (err) {\n // Early flag-validation errors (e.g. an unknown --engine) surface as a clean\n // message + exit 1 rather than an uncaught rejection.\n io.err(`${(err as Error).message}\\n`)\n return 1\n }\n}\n\n/** Parse repeatable `--var k=v` flags (split on the FIRST `=`) into a record. */\nfunction parseVars(raw: string[] | undefined): Record<string, unknown> {\n const vars: Record<string, unknown> = {}\n for (const item of raw ?? []) {\n const eq = item.indexOf('=')\n if (eq === -1) vars[item] = ''\n else vars[item.slice(0, eq)] = item.slice(eq + 1)\n }\n return vars\n}\n\n/**\n * Replay a persisted browser flow (`<flow>.bru` + sidecar) — `sackville browser\n * run <flow.bru>`. Unlike the single-shot commands the flow drives its own\n * navigations, so no URL is auto-allowed: the human allowlists target hosts with\n * `--allow-host` and unlocks mutations with `--unsafe` (else they dry-run).\n * `{{secret:NAME}}` resolves from `SACKVILLE_BROWSER_SECRET_<NAME>` env (the human\n * is the operator); a `Redactor` scrubs those values from every result. Exits\n * non-zero when the flow fails (a step error or a failed assertion) — CI-usable.\n */\nasync function cmdRun(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...COMMON_OPTIONS,\n unsafe: { type: 'boolean' },\n var: { type: 'string', multiple: true },\n },\n })\n const flowPath = positionals[0]\n if (!flowPath) {\n io.err('browser run needs <flow.bru>\\n')\n return 1\n }\n\n let flow: ReturnType<typeof loadFlow>\n try {\n flow = loadFlow(flowPath)\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n }\n\n // Operator secrets from env (SACKVILLE_BROWSER_SECRET_<NAME>); register the\n // values with a redactor so they never surface, expose them only by NAME.\n const env = io.env ?? {}\n const redactor = new Redactor()\n const secrets = new Map<string, string>()\n for (const [key, val] of Object.entries(env)) {\n const m = /^SACKVILLE_BROWSER_SECRET_(.+)$/.exec(key)\n if (m?.[1] && val) {\n redactor.register(m[1], val)\n secrets.set(m[1], val)\n }\n }\n\n const flags = flagsFrom(values)\n const gate = new BrowserGate({\n allowUnsafe: values.unsafe ?? false,\n allowedHosts: flags.allowHost,\n })\n const proxy = await createSsrfProxy({ allowPrivate: flags.allowPrivate })\n const store = new ArtifactStore(mkdtempSync(join(tmpdir(), 'sackville-browser-flow-')))\n const manager = new BrowserManager({\n gate,\n launch: launchFor(flags, proxy.url),\n })\n try {\n const context = await manager.createSession('cli')\n const page = await context.newPage()\n const driver = new PageDriver(page, {\n runId: 'cli',\n store,\n gate,\n redact: (v) => redactor.redact(v),\n })\n const result = await runFlow(driver, flow, {\n vars: parseVars(values.var),\n resolveSecret: (name) => secrets.get(name),\n })\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else {\n printFlowResult(result, io)\n }\n return result.passed ? 0 : 1\n } catch (err) {\n io.err(`${(err as Error).message}\\n`)\n return 1\n } finally {\n await manager.shutdown()\n await proxy.close()\n }\n}\n\nfunction printFlowResult(result: FlowResult, io: CliIO): void {\n io.out(`flow: ${result.name}\\n`)\n for (const step of result.steps) {\n if (step.error) {\n io.out(` FAIL ${step.action} — ${step.error}\\n`)\n } else if (step.assertions) {\n const passed = step.assertions.filter((a) => a.pass).length\n const total = step.assertions.length\n io.out(` ${passed === total ? 'ok ' : 'FAIL'} assert (${passed}/${total} passed)\\n`)\n } else {\n io.out(` ok ${step.action}${step.dryRun ? ' (dry-run)' : ''}\\n`)\n }\n }\n io.out(`${result.passed ? 'PASS' : 'FAIL'}\\n`)\n}\n\nasync function cmdSnapshot(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: COMMON_OPTIONS,\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser snapshot needs <url>\\n')\n return 1\n }\n return withSession(url, flagsFrom(values), io, async ({ driver }) => {\n const snap = await driver.snapshot()\n if (values.json) {\n io.out(`${JSON.stringify(snap, null, 2)}\\n`)\n return 0\n }\n io.out(`${snap.snapshot}\\n`)\n if (snap.truncated) io.err('(snapshot truncated — re-run with --json for the full handle)\\n')\n return 0\n })\n}\n\nasync function cmdAudit(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: COMMON_OPTIONS,\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser audit needs <url>\\n')\n return 1\n }\n return withSession(url, flagsFrom(values), io, async ({ store, page }) => {\n const res = await auditA11y(page, { runId: 'cli', store })\n if (values.json) {\n io.out(`${JSON.stringify(res, null, 2)}\\n`)\n return res.summary.violationCount === 0 ? 0 : 1\n }\n const s = res.summary\n io.out(`violations: ${s.violationCount}\\n`)\n for (const v of s.top) {\n io.out(` [${v.impact ?? '-'}] ${v.id}: ${v.nodeCount} node(s) — ${v.help}\\n`)\n }\n const path = store.get(res.resultsHandle)?.path\n if (path) io.out(`full report: ${path}\\n`)\n // exit non-zero when violations exist, so the command is usable as a CI gate\n return s.violationCount === 0 ? 0 : 1\n })\n}\n\nasync function cmdScreenshot(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...COMMON_OPTIONS, out: { type: 'string' }, 'full-page': { type: 'boolean' } },\n })\n const url = positionals[0]\n if (!url) {\n io.err('browser screenshot needs <url>\\n')\n return 1\n }\n const out = values.out ?? 'screenshot.png'\n return withSession(url, flagsFrom(values), io, async ({ driver, store }) => {\n const shot = await driver.screenshot({ fullPage: values['full-page'] ?? false })\n const bytes = shot.handle ? store.get(shot.handle)?.body : undefined\n if (!bytes) {\n io.err('screenshot capture failed\\n')\n return 1\n }\n writeFileSync(out, bytes)\n if (values.json) {\n io.out(`${JSON.stringify({ ...shot, savedTo: out }, null, 2)}\\n`)\n return 0\n }\n io.out(`saved ${shot.byteSize} bytes to ${out}\\n`)\n return 0\n })\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n CoverageGateError,\n type CoveragePyReport,\n coveragePyToIstanbul,\n type DiffCoverageReport,\n type FileCoverage,\n runScoped,\n runScopedPython,\n type ScopedPythonResult,\n type ScopeMode,\n type TestRunner,\n uncoveredInDiff,\n} from '@sackville-mcp/coverage'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville coverage` — the human surface over `@sackville-mcp/coverage`.\n *\n * `uncovered-in-diff` is the pure forgotten-assertion catch: classify a diff's new lines\n * against an istanbul or coverage.py report and surface the executable-but-unhit ones.\n * `run-scoped` is the gated impact-scoped runner (`vitest related`). The human IS the\n * operator, so the gate is a straight-through `--allow-run` flag and the typed root is\n * auto-allowed; the test runner is injectable so the suite never spawns a real vitest\n * (ADR 0010: no real spawn in the gate). Both commands exit 1 when a new line is uncovered —\n * the catch is CI-actionable, like `sackville browser audit`.\n */\nexport async function runCoverage(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'uncovered-in-diff':\n return cmdUncoveredInDiff(rest, io)\n case 'run-scoped':\n return cmdRunScoped(rest, io, deps)\n default:\n io.err(`unknown coverage subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nfunction printReport(io: CliIO, report: DiffCoverageReport): void {\n const s = report.summary\n io.out(\n `files: ${report.files.length} (${s.filesWithoutCoverage} without coverage) ` +\n `covered ${s.covered} uncovered ${s.uncovered} non-executable ${s.nonExecutable}\\n`,\n )\n if (report.uncovered.length === 0) {\n io.out('uncovered new lines: (none)\\n')\n return\n }\n io.out(`uncovered new lines (${report.uncovered.length}):\\n`)\n for (const u of report.uncovered) {\n io.out(` ${u.path}:${u.line}\\n`)\n }\n}\n\nfunction cmdUncoveredInDiff(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n diff: { type: 'string' },\n coverage: { type: 'string' },\n 'coverage-format': { type: 'string' },\n 'project-root': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n if (!values.diff || !values.coverage) {\n io.err('coverage uncovered-in-diff needs --diff <file> and --coverage <file>\\n')\n return 1\n }\n const format = values['coverage-format'] ?? 'istanbul'\n if (format !== 'istanbul' && format !== 'coveragepy') {\n io.err(`unknown coverage format: ${format} (expected istanbul|coveragepy)\\n`)\n return 1\n }\n const diff = readFileSync(values.diff, 'utf8')\n const parsed = JSON.parse(readFileSync(values.coverage, 'utf8'))\n const coverage: Record<string, FileCoverage> =\n format === 'coveragepy' ? coveragePyToIstanbul(parsed as CoveragePyReport) : parsed\n const report = uncoveredInDiff(diff, coverage, { projectRoot: values['project-root'] })\n\n if (values.json) {\n io.out(`${JSON.stringify(report, null, 2)}\\n`)\n } else {\n printReport(io, report)\n }\n // An executable new line with no test is the catch — exit non-zero so CI fails on it.\n return report.uncovered.length === 0 ? 0 : 1\n}\n\nasync function cmdRunScoped(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n 'changed-file': { type: 'string', multiple: true },\n diff: { type: 'string' },\n python: { type: 'boolean' },\n measure: { type: 'string', multiple: true },\n 'scope-mode': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('coverage run-scoped needs a <project-root>\\n')\n return 1\n }\n const scopeMode = values['scope-mode'] ?? 'report-gap'\n if (values.python && scopeMode !== 'report-gap' && scopeMode !== 'widen') {\n io.err(`unknown scope mode: ${scopeMode} (expected report-gap|widen)\\n`)\n return 1\n }\n const timeoutRaw = values['timeout-ms']\n const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) : undefined\n\n try {\n const config = {\n projectRoot,\n // Human-typed root = the operator allowlist (explicit intent), like `api`'s host.\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: timeoutMs !== undefined && Number.isFinite(timeoutMs) ? timeoutMs : undefined,\n }\n const changedFiles = values['changed-file'] ?? []\n const diff = values.diff !== undefined ? readFileSync(values.diff, 'utf8') : undefined\n\n const result = values.python\n ? await runScopedPython(\n config,\n {\n changedFiles,\n diff,\n measureTargets: values.measure ?? [],\n scopeMode: scopeMode as ScopeMode,\n },\n { runner: deps.runner },\n )\n : await runScoped(config, { changedFiles, diff }, { runner: deps.runner })\n\n const py = values.python ? (result as ScopedPythonResult) : undefined\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else if (!result.ran) {\n io.out('no changed files — nothing to run\\n')\n } else {\n io.out(\n `ran ${values.python ? 'pytest' : 'vitest'} (exit ${result.exitCode}); tests ${\n py?.inconclusive ? 'INCONCLUSIVE' : result.passed ? 'passed' : 'FAILED'\n }; scoped: ${result.scopedFiles.join(', ')}\\n`,\n )\n if (py?.unmatched)\n io.out(`uncovered-by-scope (no mirrored test): ${py.unmatched.join(', ')}\\n`)\n if (result.report) printReport(io, result.report)\n }\n // 0 only if tests passed, not inconclusive, AND (when a diff was analysed) no new line uncovered.\n const ok =\n result.passed &&\n !py?.inconclusive &&\n (result.report ? result.report.uncovered.length === 0 : true)\n return ok ? 0 : 1\n } catch (e) {\n if (e instanceof CoverageGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { parseArgs } from 'node:util'\nimport { detectInstalledVersion, type Ecosystem } from '@sackville-mcp/core'\nimport {\n auditDependency,\n CHANGELOG_FILENAMES,\n comparatorFor,\n type DependencyAudit,\n dependencyNames,\n gemRepoUrl,\n githubOwnerRepo,\n loadOsvSnapshot,\n matchName,\n normalizePypiName,\n npmRepoUrl,\n type OsvAdvisory,\n type OsvEcosystem,\n type Packument,\n type PyPiJson,\n pypiJsonToPackument,\n pypiRepoUrl,\n type RubyGemMetadata,\n type RubyGemsVersion,\n rubygemsToPackument,\n sliceChangelog,\n} from '@sackville-mcp/deps'\nimport { resolveAndPin } from '@sackville-mcp/safety'\nimport type { CliIO } from './index.js'\n\n/** Injected (so tests stay offline) registry-metadata fetcher; the real one is SSRF-pinned. */\nexport type PackumentFetcher = (packageName: string, ecosystem: OsvEcosystem) => Promise<Packument>\n/** Injected CHANGELOG fetcher (npm only); the real one is SSRF-pinned to raw.githubusercontent. */\ntype ChangelogFetcher = (\n packageName: string,\n ecosystem: OsvEcosystem,\n) => Promise<{ text: string; source: string }>\n\n/** Map an OSV ecosystem to the `@sackville-mcp/core` installed-version detection ecosystem. */\nconst DETECT_ECOSYSTEM: Record<OsvEcosystem, Ecosystem> = {\n npm: 'node',\n PyPI: 'python',\n RubyGems: 'ruby',\n}\n\n/**\n * `sackville deps` — the human surface over `@sackville-mcp/deps`. Answers deprecation /\n * vulnerability / freshness for the version ACTUALLY INSTALLED in a project (not \"latest\").\n *\n * The human invoked the audit, so the CLI fetches by default (operator intent), with the\n * same SSRF pre-flight the bins use (`resolveAndPin`: metadata/link-local always refused,\n * private registries gated by `--allow-private`). Network + comparator dispatch reuse the\n * ecosystem helpers lifted into `@sackville-mcp/deps`. `audit`/`audit-project` exit 1 on a\n * security or deprecation finding (CI-actionable); `changelog` is informational.\n */\nexport async function runDeps(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher; fetchChangelog?: ChangelogFetcher } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'audit':\n return cmdAudit(rest, io, deps)\n case 'audit-project':\n return cmdAuditProject(rest, io, deps)\n case 'changelog':\n return cmdChangelog(rest, io, deps)\n default:\n io.err(`unknown deps subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Operator registry/SSRF flags shared by every deps command. */\nconst REGISTRY_OPTIONS = {\n ecosystem: { type: 'string' },\n 'osv-db': { type: 'string' },\n registry: { type: 'string' },\n 'pypi-registry': { type: 'string' },\n 'rubygems-registry': { type: 'string' },\n 'allow-private': { type: 'boolean' },\n json: { type: 'boolean' },\n} as const\n\ninterface Registries {\n registry: string\n pypiRegistry: string\n rubygemsRegistry: string\n allowPrivate: boolean\n}\n\nexport function registriesFrom(values: Record<string, unknown>): Registries {\n return {\n registry: (values.registry as string) || 'https://registry.npmjs.org',\n pypiRegistry: (values['pypi-registry'] as string) || 'https://pypi.org/pypi',\n rubygemsRegistry: (values['rubygems-registry'] as string) || 'https://rubygems.org/api/v1',\n allowPrivate: (values['allow-private'] as boolean) ?? false,\n }\n}\n\nfunction ecosystemFrom(values: Record<string, unknown>, io: CliIO): OsvEcosystem | null {\n const e = (values.ecosystem as string) ?? 'npm'\n if (e !== 'npm' && e !== 'PyPI' && e !== 'RubyGems') {\n io.err(`unknown ecosystem: ${e} (expected npm|PyPI|RubyGems)\\n`)\n return null\n }\n return e\n}\n\n/** npm packument path: keep a scope's `@` but escape the `/` (registry idiom). */\nfunction packumentUrl(registry: string, packageName: string): string {\n return `${registry.replace(/\\/+$/, '')}/${packageName.replace('/', '%2f')}`\n}\n\n/** Build the SSRF-pinned packument fetcher (npm/PyPI/RubyGems), mirroring the deps bin. */\nexport function makeFetcher(r: Registries): PackumentFetcher {\n return async (packageName, ecosystem) => {\n if (ecosystem === 'npm') {\n const url = packumentUrl(r.registry, packageName)\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`registry returned ${res.status} for ${packageName}`)\n return (await res.json()) as Packument\n }\n if (ecosystem === 'PyPI') {\n const base = r.pypiRegistry.replace(/\\/+$/, '')\n const url = `${base}/${encodeURIComponent(normalizePypiName(packageName))}/json`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`PyPI returned ${res.status} for ${packageName}`)\n return pypiJsonToPackument((await res.json()) as PyPiJson)\n }\n const base = r.rubygemsRegistry.replace(/\\/+$/, '')\n const url = `${base}/versions/${encodeURIComponent(packageName)}.json`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`RubyGems returned ${res.status} for ${packageName}`)\n return rubygemsToPackument(packageName, (await res.json()) as RubyGemsVersion[])\n }\n}\n\n/** SSRF-pinned JSON GET (pre-flight resolve-and-refuse, then fetch). */\nasync function pinnedFetchJson(url: string, allowPrivate: boolean): Promise<unknown> {\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate })\n const res = await fetch(url, { headers: { accept: 'application/json' } })\n if (!res.ok) throw new Error(`metadata fetch returned ${res.status} for ${url}`)\n return res.json()\n}\n\n/**\n * Build the SSRF-pinned changelog fetcher (npm/PyPI/RubyGems). Resolves the source GitHub repo\n * from registry metadata — npm packument `repository`, PyPI `info.project_urls`, or the RubyGems\n * `/api/v1/gems/<name>.json` `source_code_uri`/`homepage_uri` — then fetches the CHANGELOG from\n * `raw.githubusercontent.com/<owner>/<repo>/HEAD/<file>`, pinning every request.\n */\nfunction makeChangelogFetcher(r: Registries): ChangelogFetcher {\n const fetchPackument = makeFetcher(r)\n const repoUrlFor = async (\n packageName: string,\n ecosystem: string,\n ): Promise<string | undefined> => {\n if (ecosystem === 'npm') return npmRepoUrl(await fetchPackument(packageName, 'npm'))\n if (ecosystem === 'PyPI') {\n const base = r.pypiRegistry.replace(/\\/+$/, '')\n const url = `${base}/${encodeURIComponent(normalizePypiName(packageName))}/json`\n return pypiRepoUrl((await pinnedFetchJson(url, r.allowPrivate)) as PyPiJson)\n }\n if (ecosystem === 'RubyGems') {\n const base = r.rubygemsRegistry.replace(/\\/+$/, '')\n const url = `${base}/gems/${encodeURIComponent(packageName)}.json`\n return gemRepoUrl((await pinnedFetchJson(url, r.allowPrivate)) as RubyGemMetadata)\n }\n throw new Error(`changelog fetch supports npm, PyPI, and RubyGems (got \"${ecosystem}\")`)\n }\n return async (packageName, ecosystem) => {\n const gh = githubOwnerRepo(await repoUrlFor(packageName, ecosystem))\n if (!gh) throw new Error(`could not resolve a GitHub repository for \"${packageName}\"`)\n for (const file of CHANGELOG_FILENAMES) {\n const url = `https://raw.githubusercontent.com/${gh.owner}/${gh.repo}/HEAD/${file}`\n await resolveAndPin(new URL(url).hostname, undefined, { allowPrivate: r.allowPrivate })\n const res = await fetch(url)\n if (res.ok) return { text: await res.text(), source: url }\n }\n throw new Error(`no CHANGELOG found in github.com/${gh.owner}/${gh.repo}`)\n }\n}\n\n/** Load advisories + snapshotDate for an ecosystem, or empty when no snapshot dir is set. */\nfunction loadAdvisories(\n osvDir: string | undefined,\n ecosystem: string,\n): { advisories: OsvAdvisory[]; snapshotDate?: string; loaded: boolean } {\n if (osvDir === undefined) return { advisories: [], loaded: false }\n const snapshot = loadOsvSnapshot(osvDir, ecosystem)\n return { advisories: snapshot.advisories, snapshotDate: snapshot.snapshotDate, loaded: true }\n}\n\n/** Detect → fetch → audit one package (the thin orchestration the pure core needs). */\nasync function auditOne(\n project: string,\n packageName: string,\n ecosystem: OsvEcosystem,\n fetchPackument: PackumentFetcher,\n advisories: OsvAdvisory[],\n snapshotDate: string | undefined,\n versionOverride?: string,\n): Promise<DependencyAudit> {\n const version =\n versionOverride ??\n detectInstalledVersion(project, packageName, { ecosystem: DETECT_ECOSYSTEM[ecosystem] }).version\n if (version === null || version === undefined) {\n throw new Error(`could not detect an installed version of \"${packageName}\" in ${project}`)\n }\n const packument = await fetchPackument(packageName, ecosystem)\n return auditDependency({\n packageName: matchName(packageName, ecosystem),\n ecosystem,\n installedVersion: version,\n packument,\n advisories,\n snapshotDate,\n comparator: comparatorFor(ecosystem),\n })\n}\n\n/**\n * Detect → fetch → audit each declared (or `names`-scoped) dependency of a project,\n * isolating per-package failures — the reusable project audit the `verify run --deps`\n * path reuses (mirrors the MCP `auditProjectDependencies`). Returns the\n * `{audits, osvSnapshotLoaded}` shape the verify orchestrator's deps adapter consumes.\n */\nexport async function auditProjectScoped(input: {\n project: string\n ecosystem: OsvEcosystem\n /** Audit ONLY these names (the diff-changed deps); omitted ⇒ all declared deps. */\n names?: string[]\n osvDir?: string\n fetchPackument: PackumentFetcher\n}): Promise<{\n audits: DependencyAudit[]\n osvSnapshotLoaded: boolean\n errors: { package: string; error: string }[]\n}> {\n const { advisories, snapshotDate, loaded } = loadAdvisories(input.osvDir, input.ecosystem)\n const names = input.names ?? dependencyNames(input.project, input.ecosystem, true)\n const audits: DependencyAudit[] = []\n const errors: { package: string; error: string }[] = []\n for (const name of names) {\n try {\n audits.push(\n await auditOne(\n input.project,\n name,\n input.ecosystem,\n input.fetchPackument,\n advisories,\n snapshotDate,\n ),\n )\n } catch (e) {\n errors.push({ package: name, error: (e as Error).message })\n }\n }\n return { audits, osvSnapshotLoaded: loaded, errors }\n}\n\n/** A security or deprecation finding — the CI-actionable signal (outdated alone is not). */\nfunction isActionable(audit: DependencyAudit): boolean {\n return audit.worstSeverity !== 'none' || audit.deprecated.isDeprecated\n}\n\nfunction printAudit(\n io: CliIO,\n audit: DependencyAudit,\n loaded: boolean,\n snapshotDate?: string,\n): void {\n io.out(`${audit.package} ${audit.installedVersion} (${audit.ecosystem})\\n`)\n io.out(\n audit.deprecated.isDeprecated\n ? `deprecated [${audit.deprecated.scope}]: ${audit.deprecated.message}\\n`\n : 'deprecated: no\\n',\n )\n if (audit.vulnerabilities.length > 0) {\n io.out(`vulnerabilities (${audit.vulnerabilities.length}):\\n`)\n for (const v of audit.vulnerabilities) {\n const fixed = v.fixedIn.length ? ` fixed in: ${v.fixedIn.join(', ')}` : ''\n io.out(` ${v.id} [${v.severity}] ${v.summary ?? ''}${fixed}\\n`)\n }\n } else {\n io.out('vulnerabilities: none\\n')\n }\n const f = audit.freshness\n io.out(\n `freshness: installed ${f.installed}, latest ${f.latest ?? '?'}, same-major ${f.latestSameMajor ?? '?'}, outdated ${f.isOutdated ? 'yes' : 'no'}\\n`,\n )\n if (audit.recommendedTarget) io.out(`recommended target: ${audit.recommendedTarget}\\n`)\n if (audit.minimumSafeUpgrade) io.out(`minimum safe upgrade: ${audit.minimumSafeUpgrade}\\n`)\n io.out(\n loaded\n ? `osv snapshot: loaded${snapshotDate ? ` (${snapshotDate})` : ''}\\n`\n : 'osv snapshot: NOT loaded — treat \"no known vulnerabilities\" as unknown, not clean\\n',\n )\n}\n\nasync function cmdAudit(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...REGISTRY_OPTIONS, version: { type: 'string' } },\n })\n const [project, packageName] = positionals\n if (!project || !packageName) {\n io.err('deps audit needs <project> <package>\\n')\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchPackument = deps.fetchPackument ?? makeFetcher(r)\n const { advisories, snapshotDate, loaded } = loadAdvisories(values['osv-db'], ecosystem)\n\n try {\n const audit = await auditOne(\n project,\n packageName,\n ecosystem,\n fetchPackument,\n advisories,\n snapshotDate,\n values.version,\n )\n if (values.json) {\n io.out(`${JSON.stringify({ ...audit, osvSnapshotLoaded: loaded }, null, 2)}\\n`)\n } else {\n printAudit(io, audit, loaded, snapshotDate)\n }\n return isActionable(audit) ? 1 : 0\n } catch (e) {\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n\nasync function cmdAuditProject(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...REGISTRY_OPTIONS, 'skip-dev': { type: 'boolean' } },\n })\n const project = positionals[0]\n if (!project) {\n io.err('deps audit-project needs <project>\\n')\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchPackument = deps.fetchPackument ?? makeFetcher(r)\n const { advisories, snapshotDate, loaded } = loadAdvisories(values['osv-db'], ecosystem)\n const names = dependencyNames(project, ecosystem, !values['skip-dev'])\n\n const dependencies: {\n package: string\n installedVersion: string\n worstSeverity: DependencyAudit['worstSeverity']\n deprecated: boolean\n isOutdated: boolean\n recommendedTarget?: string\n minimumSafeUpgrade?: string\n vulnerabilityCount: number\n }[] = []\n const errors: { package: string; error: string }[] = []\n for (const name of names) {\n try {\n const audit = await auditOne(\n project,\n name,\n ecosystem,\n fetchPackument,\n advisories,\n snapshotDate,\n )\n dependencies.push({\n package: name,\n installedVersion: audit.installedVersion,\n worstSeverity: audit.worstSeverity,\n deprecated: audit.deprecated.isDeprecated,\n isOutdated: audit.freshness.isOutdated,\n recommendedTarget: audit.recommendedTarget,\n minimumSafeUpgrade: audit.minimumSafeUpgrade,\n vulnerabilityCount: audit.vulnerabilities.length,\n })\n } catch (err) {\n errors.push({ package: name, error: err instanceof Error ? err.message : String(err) })\n }\n }\n\n const bySeverity: Record<string, number> = {}\n for (const d of dependencies) {\n if (d.worstSeverity !== 'none')\n bySeverity[d.worstSeverity] = (bySeverity[d.worstSeverity] ?? 0) + 1\n }\n const summary = {\n total: dependencies.length,\n withFindings: dependencies.filter((d) => d.worstSeverity !== 'none' || d.deprecated).length,\n deprecated: dependencies.filter((d) => d.deprecated).length,\n outdated: dependencies.filter((d) => d.isOutdated).length,\n bySeverity,\n osvSnapshotLoaded: loaded,\n snapshotDate,\n }\n\n if (values.json) {\n io.out(`${JSON.stringify({ project, ecosystem, summary, dependencies, errors }, null, 2)}\\n`)\n return summary.withFindings > 0 ? 1 : 0\n }\n io.out(\n `${project} (${ecosystem}) ${summary.total} deps; findings ${summary.withFindings}, deprecated ${summary.deprecated}, outdated ${summary.outdated}\\n`,\n )\n io.out(\n loaded\n ? `osv snapshot: loaded${snapshotDate ? ` (${snapshotDate})` : ''}\\n`\n : 'osv snapshot: NOT loaded — \"no known vulnerabilities\" is unknown, not clean\\n',\n )\n for (const d of dependencies) {\n if (d.worstSeverity === 'none' && !d.deprecated && !d.isOutdated) continue\n const tags = [\n d.worstSeverity !== 'none' ? `[${d.worstSeverity}]` : '',\n d.deprecated ? 'deprecated' : '',\n d.isOutdated ? 'outdated' : '',\n ]\n .filter(Boolean)\n .join(' ')\n const target = d.minimumSafeUpgrade ?? d.recommendedTarget\n io.out(` ${d.package} ${d.installedVersion} ${tags}${target ? ` → ${target}` : ''}\\n`)\n }\n for (const e of errors) io.out(` ! ${e.package}: ${e.error}\\n`)\n return summary.withFindings > 0 ? 1 : 0\n}\n\nasync function cmdChangelog(\n args: string[],\n io: CliIO,\n deps: { fetchPackument?: PackumentFetcher; fetchChangelog?: ChangelogFetcher },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n ...REGISTRY_OPTIONS,\n project: { type: 'string' },\n from: { type: 'string' },\n to: { type: 'string' },\n },\n })\n const packageName = positionals[0]\n if (!packageName) {\n io.err(\n 'deps changelog needs <package> (with --from or --project to detect the installed version)\\n',\n )\n return 1\n }\n const ecosystem = ecosystemFrom(values, io)\n if (!ecosystem) return 1\n const r = registriesFrom(values)\n const fetchChangelog = deps.fetchChangelog ?? makeChangelogFetcher(r)\n\n try {\n let from = values.from\n if (from === undefined) {\n if (!values.project) {\n io.err('provide --from <version> or --project <dir> to determine the installed version\\n')\n return 1\n }\n const detected = detectInstalledVersion(values.project, packageName, {\n ecosystem: DETECT_ECOSYSTEM[ecosystem],\n })\n if (!detected.version) {\n io.err(`could not detect an installed version of \"${packageName}\" in ${values.project}\\n`)\n return 1\n }\n from = detected.version\n }\n const { text: markdown, source } = await fetchChangelog(packageName, ecosystem)\n const slice = sliceChangelog(markdown, {\n from,\n to: values.to,\n comparator: comparatorFor(ecosystem),\n })\n\n if (values.json) {\n io.out(\n `${JSON.stringify(\n {\n package: packageName,\n from: slice.from,\n to: slice.to ?? null,\n versionsCovered: slice.entries.map((e) => e.version),\n source,\n body: slice.entries.map((e) => e.body).join('\\n\\n'),\n },\n null,\n 2,\n )}\\n`,\n )\n return 0\n }\n io.out(\n `${packageName} ${slice.from} → ${slice.to ?? 'latest'} (${slice.entries.length} section(s)) [${source}]\\n`,\n )\n if (slice.entries.length === 0) {\n io.out('(no changelog sections in the requested range)\\n')\n return 0\n }\n for (const e of slice.entries) io.out(`\\n## ${e.version}\\n${e.body}\\n`)\n return 0\n } catch (e) {\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n FlakeGateError,\n type FlakeVerdict,\n HistoryStore,\n Quarantine,\n QuarantineGateError,\n quarantineCandidates,\n runAndRecord,\n runAndRecordPytest,\n type TestRunner,\n} from '@sackville-mcp/flake'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville flake` — the human surface over `@sackville-mcp/flake`.\n *\n * Reads (`status`/`candidates`) + `ingest`/`release` are always available against the\n * operator's private run-history DB (`--db`). `run` (spawns vitest) and `quarantine`\n * (the only write) each sit behind their own paired deny-by-default gate. The human IS\n * the operator, so those gates are straight-through flags (`--allow-run` /\n * `--allow-quarantine` + `--max-expiry-ms`), the typed root is auto-allowed, and the\n * vitest runner is injectable so the suite never spawns a real vitest (ADR 0010).\n */\nexport async function runFlake(\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'status':\n return withStore(rest, io, cmdStatus)\n case 'candidates':\n return withStore(rest, io, cmdCandidates)\n case 'ingest':\n return withStore(rest, io, cmdIngest)\n case 'release':\n return withStore(rest, io, cmdRelease)\n case 'run':\n return withStore(rest, io, (store, a, o) => cmdRun(store, a, o, deps))\n case 'quarantine':\n return withStore(rest, io, cmdQuarantine)\n default:\n io.err(`unknown flake subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Open the operator's history DB (from `--db`/`SACKVILLE_FLAKE_DB`), run the command, close. */\nasync function withStore(\n args: string[],\n io: CliIO,\n fn: (store: HistoryStore, args: string[], io: CliIO) => number | Promise<number>,\n): Promise<number> {\n // `--db` is parsed here too so a missing path is caught before any work; the command\n // re-parses its own flags (parseArgs ignores unknown-but-declared elsewhere is false, so\n // we pass the full args through — each command declares `db` in its own options).\n const dbPath = readDbFlag(args) ?? io.env?.SACKVILLE_FLAKE_DB\n if (!dbPath) {\n io.err('no run-history DB given: pass --db <file> or set SACKVILLE_FLAKE_DB\\n')\n return 1\n }\n const store = HistoryStore.open(dbPath)\n try {\n return await fn(store, args, io)\n } finally {\n store.close()\n }\n}\n\n/** Pull just `--db <path>` out of an argv without consuming the rest. */\nfunction readDbFlag(args: string[]): string | undefined {\n const i = args.indexOf('--db')\n return i >= 0 ? args[i + 1] : undefined\n}\n\nfunction num(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\nfunction printVerdict(io: CliIO, v: FlakeVerdict): void {\n io.out(\n ` [${v.state}] ${v.id} runs ${v.runs} fail ${v.failures}/${v.runs} score ${v.flakeScore.toFixed(3)}\\n`,\n )\n}\n\nfunction cmdStatus(store: HistoryStore, args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n 'min-runs': { type: 'string' },\n 'limit-per-test': { type: 'string' },\n since: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const verdicts = store.classify({\n minRuns: num(values['min-runs']),\n limitPerTest: num(values['limit-per-test']),\n since: values.since,\n })\n const quarantined = new Quarantine(store, { allowQuarantine: false, maxExpiryMs: 0 }).active()\n\n if (values.json) {\n const summary: Record<string, number> = {}\n for (const v of verdicts) summary[v.state] = (summary[v.state] ?? 0) + 1\n io.out(`${JSON.stringify({ summary, verdicts, quarantined }, null, 2)}\\n`)\n return 0\n }\n const counts = { flaky: 0, reliable: 0, broken: 0, 'insufficient-data': 0 }\n for (const v of verdicts) counts[v.state]++\n io.out(\n `flaky ${counts.flaky} reliable ${counts.reliable} broken ${counts.broken} insufficient-data ${counts['insufficient-data']}\\n`,\n )\n if (verdicts.length > 0) {\n io.out('verdicts:\\n')\n for (const v of verdicts) printVerdict(io, v)\n }\n if (quarantined.length > 0) {\n io.out(`quarantined (${quarantined.length}):\\n`)\n for (const q of quarantined) io.out(` ${q.testId} until ${q.expiresAt} (${q.reason})\\n`)\n }\n return 0\n}\n\nfunction cmdCandidates(store: HistoryStore, args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n 'min-flake-score': { type: 'string' },\n 'min-runs': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const verdicts = store.classify({ minRuns: num(values['min-runs']) })\n const candidates = quarantineCandidates(verdicts, {\n minFlakeScore: num(values['min-flake-score']),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify({ candidates }, null, 2)}\\n`)\n return 0\n }\n if (candidates.length === 0) {\n io.out('no quarantine candidates\\n')\n return 0\n }\n io.out(`candidates (${candidates.length}):\\n`)\n for (const v of candidates) printVerdict(io, v)\n return 0\n}\n\nfunction cmdIngest(store: HistoryStore, args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n format: { type: 'string' },\n at: { type: 'string' },\n 'project-root': { type: 'string' },\n 'run-group': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const reportFile = positionals[0]\n if (!reportFile) {\n io.err('flake ingest needs a <report-file>\\n')\n return 1\n }\n const format = values.format ?? 'vitest'\n if (format !== 'vitest' && format !== 'pytest') {\n io.err(`unknown report format: ${format} (expected vitest|pytest)\\n`)\n return 1\n }\n const report = JSON.parse(readFileSync(reportFile, 'utf8'))\n const opts = {\n at: values.at ?? new Date().toISOString(),\n projectRoot: values['project-root'],\n runGroup: values['run-group'],\n }\n const recorded =\n format === 'pytest' ? store.ingestPytestReport(report, opts) : store.ingestReport(report, opts)\n\n if (values.json) {\n io.out(`${JSON.stringify({ format, recorded }, null, 2)}\\n`)\n return 0\n }\n io.out(`recorded ${recorded} run(s) from the ${format} report\\n`)\n return 0\n}\n\nfunction cmdRelease(store: HistoryStore, args: string[], io: CliIO): number {\n const { positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { db: { type: 'string' } },\n })\n const testId = positionals[0]\n if (!testId) {\n io.err('flake release needs a <testId>\\n')\n return 1\n }\n const released = new Quarantine(store, { allowQuarantine: false, maxExpiryMs: 0 }).release(testId)\n io.out(released ? `released ${testId}\\n` : `${testId} was not quarantined\\n`)\n return 0\n}\n\nasync function cmdRun(\n store: HistoryStore,\n args: string[],\n io: CliIO,\n deps: { runner?: TestRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n framework: { type: 'string' },\n repeat: { type: 'string' },\n file: { type: 'string', multiple: true },\n 'run-group': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('flake run needs a <project-root>\\n')\n return 1\n }\n const framework = values.framework ?? 'vitest'\n if (framework !== 'vitest' && framework !== 'pytest') {\n io.err(`unknown framework: ${framework} (expected vitest|pytest)\\n`)\n return 1\n }\n try {\n const run = framework === 'pytest' ? runAndRecordPytest : runAndRecord\n const result = await run(\n store,\n {\n projectRoot,\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: num(values['timeout-ms']),\n },\n { repeat: num(values.repeat) ?? 1, files: values.file, runGroup: values['run-group'] },\n { runner: deps.runner },\n )\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return 0\n }\n io.out(`ran ${result.iterations} iteration(s); recorded ${result.recorded} run(s)\\n`)\n for (const v of result.verdicts) printVerdict(io, v)\n return 0\n } catch (e) {\n if (e instanceof FlakeGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n\nfunction cmdQuarantine(store: HistoryStore, args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n db: { type: 'string' },\n reason: { type: 'string' },\n 'expires-at': { type: 'string' },\n 'flake-score': { type: 'string' },\n 'allow-quarantine': { type: 'boolean' },\n 'max-expiry-ms': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const testId = positionals[0]\n if (!testId || !values.reason || !values['expires-at']) {\n io.err('flake quarantine needs <testId> --reason <r> --expires-at <ISO>\\n')\n return 1\n }\n const policy = {\n allowQuarantine: values['allow-quarantine'] ?? false,\n maxExpiryMs: num(values['max-expiry-ms']) ?? 0,\n }\n try {\n const entry = new Quarantine(store, policy).quarantine({\n testId,\n reason: values.reason,\n expiresAt: values['expires-at'],\n flakeScore: num(values['flake-score']),\n })\n if (values.json) {\n io.out(`${JSON.stringify({ entry }, null, 2)}\\n`)\n return 0\n }\n io.out(`quarantined ${entry.testId} until ${entry.expiresAt} (${entry.reason})\\n`)\n return 0\n } catch (e) {\n if (e instanceof QuarantineGateError) {\n io.err(`refused: ${e.message} (pass --allow-quarantine and --max-expiry-ms)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n defaultListFiles,\n LanguageServerManager,\n LspGateError,\n LspQueryEngine,\n type LspQueryInput,\n type LspQueryKind,\n type LspQueryResult,\n LspRenameEngine,\n type LspRenameInput,\n type LspRenameResult,\n parseServerRegistry,\n type ResultDiagnostic,\n type ResultSymbol,\n type ResultWorkspaceSymbol,\n type ServerDescription,\n type ServerRegistry,\n} from '@sackville-mcp/lsp'\nimport type { CliIO } from './index.js'\n\n/** Injected (test) or real engine entries. */\ntype QueryFn = (input: LspQueryInput) => Promise<LspQueryResult>\ntype RenameFn = (input: LspRenameInput) => Promise<LspRenameResult>\ntype DescribeFn = () => ServerDescription[]\n\nexport interface LspDeps {\n query?: QueryFn\n rename?: RenameFn\n describeServers?: DescribeFn\n}\n\n/**\n * `sackville lsp` — the human surface over `@sackville-mcp/lsp`. Single-shot semantic code\n * navigation: each invocation binds the operator's server registry, drives one query against\n * a live Language Server subprocess, then shuts it down.\n *\n * The human IS the operator, so the gates are straight-through flags: `--allow-run` (required\n * for any navigation — it spawns a code-executing indexing daemon, ADR 0011's\n * load-bearing gate) and `--allow-write` (lets `rename` write to disk; default = dry-run\n * preview). The typed `--project` root is the allowlist (explicit operator intent). Per ADR\n * 0011 the engine is **injectable** so the suite never spawns a real server — the production\n * path builds the real `LanguageServerManager`/`LspQueryEngine`/`LspRenameEngine` from flags\n * (mirroring `sackville-lsp-mcp`), and the gate throws *before* any spawn when `--allow-run` is\n * absent.\n *\n * Exit codes: 0 = the query ran (`ok`/`no_result`, or a rename preview/apply); 1 = denied,\n * refused, or error; 2 = `not_ready` (the server was still indexing — retry shortly).\n */\nexport async function runLsp(args: string[], io: CliIO, deps: LspDeps = {}): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'languages':\n return cmdLanguages(rest, io, deps)\n case 'definition':\n return cmdQuery('definition', rest, io, deps)\n case 'type-definition':\n return cmdQuery('typeDefinition', rest, io, deps)\n case 'references':\n return cmdQuery('references', rest, io, deps)\n case 'hover':\n return cmdQuery('hover', rest, io, deps)\n case 'symbols':\n return cmdQuery('documentSymbols', rest, io, deps)\n case 'diagnostics':\n return cmdQuery('diagnostics', rest, io, deps)\n case 'workspace-symbols':\n return cmdWorkspaceSymbols(rest, io, deps)\n case 'call-hierarchy':\n return cmdQuery('callHierarchy', rest, io, deps)\n case 'rename':\n return cmdRename(rest, io, deps)\n default:\n io.err(`unknown lsp subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\nconst GATE_OPTIONS = {\n project: { type: 'string' },\n // Additional roots bound as workspace folders on the SAME server (multi-root). Repeatable.\n // The human is the operator, so passing a root authorizes it (it joins the allowlist).\n 'workspace-root': { type: 'string', multiple: true },\n servers: { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'allow-write': { type: 'boolean' },\n // Apply a rename the completeness guard flags `suspect` (open-files-scoped server → likely\n // partial). Deny-by-default: a suspect rename is refused for write without this.\n 'allow-partial-rename': { type: 'boolean' },\n // Apply a server `overwrite` on a Create/Rename (truncate-and-replace an EXISTING regular file).\n // Deny-by-default; requires --allow-write. Symlink/dir targets + recursive delete stay refused.\n 'allow-destructive-resource-ops': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n json: { type: 'boolean' },\n} as const\n\nfunction num(raw: string | undefined): number | undefined {\n if (raw === undefined) return undefined\n const n = Number(raw)\n return Number.isFinite(n) ? n : undefined\n}\n\ninterface Engines {\n query: QueryFn\n rename: RenameFn\n describeServers: DescribeFn\n shutdown: () => Promise<void>\n projectRoot: string\n /** Resolved additional multi-root workspace folders (from `--workspace-root`). */\n workspaceRoots: string[]\n}\n\n/**\n * Build the query/rename engines — injected stubs in tests, else the real manager + engines\n * from the operator registry (`--servers`/`SACKVILLE_LSP_SERVERS`), gated by `--allow-run` /\n * `--allow-write` and confined to the `--project` root. Returns null on a config error (the\n * caller has already had the message written).\n */\nfunction makeEngines(values: Record<string, unknown>, io: CliIO, deps: LspDeps): Engines | null {\n const projectRoot = resolve((values.project as string) ?? process.cwd())\n const workspaceRoots = ((values['workspace-root'] as string[]) ?? []).map((r) => resolve(r))\n // A destructive overwrite is meaningless without write-mode; refuse the contradiction HARD (not a\n // silently-inert flag), uniformly for the stub + real paths.\n if (values['allow-destructive-resource-ops'] && !values['allow-write']) {\n io.err('--allow-destructive-resource-ops requires --allow-write\\n')\n return null\n }\n if (deps.query || deps.rename || deps.describeServers) {\n return {\n query: deps.query ?? (async () => fail('query')),\n rename: deps.rename ?? (async () => fail('rename')),\n describeServers: deps.describeServers ?? (() => []),\n shutdown: async () => {},\n projectRoot,\n workspaceRoots,\n }\n }\n const raw = (values.servers as string) ?? io.env?.SACKVILLE_LSP_SERVERS\n if (!raw || raw.trim() === '') {\n io.err('no servers bound: pass --servers <json> or set SACKVILLE_LSP_SERVERS\\n')\n return null\n }\n let registry: ServerRegistry\n try {\n registry = parseServerRegistry(raw)\n } catch (e) {\n io.err(`invalid --servers registry: ${(e as Error).message}\\n`)\n return null\n }\n const allowedRoots = [projectRoot, ...workspaceRoots]\n const manager = new LanguageServerManager({\n registry,\n allowedRoots,\n timeoutMs: num(values['timeout-ms'] as string) ?? 15_000,\n })\n const query = new LspQueryEngine({\n manager,\n allowRun: (values['allow-run'] as boolean) ?? false,\n allowedRoots,\n })\n const rename = new LspRenameEngine({\n manager,\n allowRun: (values['allow-run'] as boolean) ?? false,\n allowedRoots,\n allowWrite: (values['allow-write'] as boolean) ?? false,\n allowPartialRename: (values['allow-partial-rename'] as boolean) ?? false,\n allowDestructiveResourceOps: (values['allow-destructive-resource-ops'] as boolean) ?? false,\n // Wire the real walker so the partial-rename guard is active for the human CLI too.\n listFiles: defaultListFiles,\n })\n return {\n query: (input) => query.query(input),\n rename: (input) => rename.rename(input),\n describeServers: () => manager.describe(),\n shutdown: () => manager.shutdown(),\n projectRoot,\n workspaceRoots,\n }\n}\n\nfunction fail(what: string): never {\n throw new Error(`no ${what} engine available`)\n}\n\nfunction cmdLanguages(args: string[], io: CliIO, deps: LspDeps): number {\n const { values } = parseArgs({ args, allowPositionals: true, options: GATE_OPTIONS })\n const raw = (values.servers as string) ?? io.env?.SACKVILLE_LSP_SERVERS\n let languages: string[] = []\n if (raw && raw.trim() !== '') {\n try {\n languages = Object.keys(parseServerRegistry(raw)).sort()\n } catch (e) {\n io.err(`invalid --servers registry: ${(e as Error).message}\\n`)\n return 1\n }\n }\n const servers = (deps.describeServers ?? (() => []))()\n if (values.json) {\n io.out(`${JSON.stringify({ languages, servers }, null, 2)}\\n`)\n return 0\n }\n io.out(languages.length ? `bound languages: ${languages.join(', ')}\\n` : 'no languages bound\\n')\n for (const s of servers) {\n const v = s.serverInfo\n ? `${s.serverInfo.name}${s.serverInfo.version ? ` ${s.serverInfo.version}` : ''}`\n : '(no serverInfo)'\n io.out(` ${s.language} @ ${s.projectRoot} ${v}\\n`)\n }\n return 0\n}\n\n/** Tri-state status → exit code (ok/no_result ran; not_ready is transient). */\nfunction statusExit(status: string): number {\n return status === 'not_ready' ? 2 : 0\n}\n\nfunction rangeStr(r: {\n start: { line: number; column: number }\n end: { line: number; column: number }\n}): string {\n return `${r.start.line}:${r.start.column}-${r.end.line}:${r.end.column}`\n}\n\nfunction printHeader(io: CliIO, r: LspQueryResult): void {\n const info = r.serverInfo\n ? `${r.serverInfo.name}${r.serverInfo.version ? ` ${r.serverInfo.version}` : ''}`\n : 'unknown server'\n io.out(`status: ${r.status} [${r.kind}, ${r.encoding}, ${info}]\\n`)\n if (r.versionWarning) io.err(`warning: ${r.versionWarning}\\n`)\n}\n\nfunction printSymbols(io: CliIO, symbols: ResultSymbol[], depth: number): void {\n for (const s of symbols) {\n const detail = s.detail ? ` ${s.detail}` : ''\n io.out(`${' '.repeat(depth + 1)}${s.name} [${s.kindName}] ${rangeStr(s.range)}${detail}\\n`)\n if (s.children && s.children.length > 0) printSymbols(io, s.children, depth + 1)\n }\n}\n\nasync function cmdQuery(\n kind: LspQueryKind,\n args: string[],\n io: CliIO,\n deps: LspDeps,\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { ...GATE_OPTIONS, direction: { type: 'string' } },\n })\n const positionLess = kind === 'documentSymbols' || kind === 'diagnostics'\n const [language, file, lineRaw, colRaw] = positionals\n if (!language || !file || (!positionLess && (lineRaw === undefined || colRaw === undefined))) {\n io.err(\n positionLess\n ? `lsp ${kindCommand(kind)} needs <language> <file>\\n`\n : `lsp ${kindCommand(kind)} needs <language> <file> <line> <column>\\n`,\n )\n return 1\n }\n\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const input: LspQueryInput = {\n language,\n projectRoot: engines.projectRoot,\n file,\n kind,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n ...(positionLess ? {} : { line: Number(lineRaw), column: Number(colRaw) }),\n ...(kind === 'callHierarchy'\n ? { direction: (values.direction as 'incoming' | 'outgoing') ?? 'incoming' }\n : {}),\n }\n const result = await engines.query(input)\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return statusExit(result.status)\n }\n\n printHeader(io, result)\n if (result.status === 'not_ready') {\n io.out('the server is still indexing — retry shortly\\n')\n return 2\n }\n if (kind === 'hover') {\n io.out(result.hover ? `${result.hover.value}\\n` : 'no hover info\\n')\n } else if (kind === 'documentSymbols') {\n const symbols = result.symbols ?? []\n io.out(`${symbols.length} symbol(s):\\n`)\n printSymbols(io, symbols, 0)\n } else if (kind === 'diagnostics') {\n const diags = result.diagnostics ?? []\n io.out(`${diags.length} diagnostic(s):\\n`)\n for (const d of diags) {\n printDiagnostic(io, d)\n }\n } else if (kind === 'callHierarchy') {\n const groups = result.callHierarchy ?? []\n for (const g of groups) {\n io.out(`${g.source.name} [${g.source.kindName}] (${g.direction})\\n`)\n for (const c of g.calls) {\n io.out(` ${c.item.name} ${c.item.uri} ${c.fromRanges.map(rangeStr).join(', ')}\\n`)\n }\n }\n } else {\n const locations = result.locations ?? []\n io.out(`${locations.length} location(s):\\n`)\n for (const loc of locations) {\n io.out(` ${loc.uri} ${rangeStr(loc.range)}${loc.mapped ? '' : ' (unmapped)'}\\n`)\n }\n }\n return statusExit(result.status)\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\n/**\n * `workspace-symbols <language> <query> [anchorFile]` — position-less project-wide symbol search.\n * The optional `[anchorFile]` is opened first to establish the project; pass it for servers (like\n * `typescript-language-server`) that only build a project once a file is open.\n */\nasync function cmdWorkspaceSymbols(args: string[], io: CliIO, deps: LspDeps): Promise<number> {\n const { values, positionals } = parseArgs({ args, allowPositionals: true, options: GATE_OPTIONS })\n const [language, query, anchorFile] = positionals\n if (!language || query === undefined) {\n io.err('lsp workspace-symbols needs <language> <query> [anchorFile]\\n')\n return 1\n }\n\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const result = await engines.query({\n language,\n projectRoot: engines.projectRoot,\n kind: 'workspaceSymbol',\n query,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n ...(anchorFile !== undefined ? { file: anchorFile } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return statusExit(result.status)\n }\n\n printHeader(io, result)\n if (result.status === 'not_ready') {\n io.out('the server is still indexing — retry shortly\\n')\n return 2\n }\n const symbols = result.workspaceSymbols ?? []\n io.out(`${symbols.length} symbol(s):\\n`)\n for (const s of symbols) {\n printWorkspaceSymbol(io, s)\n }\n return statusExit(result.status)\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\nfunction printDiagnostic(io: CliIO, d: ResultDiagnostic): void {\n const sev = d.severityName ?? (d.severity !== undefined ? `severity ${d.severity}` : 'Diagnostic')\n const where = `${d.range.start.line}:${d.range.start.column}`\n const code = d.code !== undefined ? ` [${d.source ? `${d.source} ` : ''}${d.code}]` : ''\n io.out(` ${where} ${sev}${code} ${d.message}\\n`)\n for (const r of d.related ?? []) {\n io.out(` ↳ ${r.uri} ${r.range.start.line}:${r.range.start.column} ${r.message}\\n`)\n }\n}\n\nfunction printWorkspaceSymbol(io: CliIO, s: ResultWorkspaceSymbol): void {\n const container = s.container ? ` (in ${s.container})` : ''\n const loc = s.range ? ` ${rangeStr(s.range)}${s.mapped ? '' : ' (unmapped)'}` : ''\n io.out(` ${s.name} [${s.kindName}] ${s.uri}${loc}${container}\\n`)\n}\n\n/** Map a query kind back to its CLI subcommand name (for error messages). */\nfunction kindCommand(kind: LspQueryKind): string {\n if (kind === 'typeDefinition') return 'type-definition'\n if (kind === 'documentSymbols') return 'symbols'\n if (kind === 'callHierarchy') return 'call-hierarchy'\n return kind\n}\n\nasync function cmdRename(args: string[], io: CliIO, deps: LspDeps): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: GATE_OPTIONS,\n })\n const [language, file, lineRaw, colRaw, newName] = positionals\n if (!language || !file || lineRaw === undefined || colRaw === undefined || !newName) {\n io.err('lsp rename needs <language> <file> <line> <column> <newName>\\n')\n return 1\n }\n const engines = makeEngines(values, io, deps)\n if (!engines) return 1\n try {\n const result = await engines.rename({\n language,\n projectRoot: engines.projectRoot,\n file,\n line: Number(lineRaw),\n column: Number(colRaw),\n newName,\n ...(engines.workspaceRoots.length ? { workspaceRoots: engines.workspaceRoots } : {}),\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n } else {\n printRename(io, result)\n }\n if (result.status === 'not_ready') return 2\n if (result.refused) return 1\n return 0\n } catch (e) {\n if (e instanceof LspGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n } finally {\n await engines.shutdown()\n }\n}\n\nfunction printRename(io: CliIO, r: LspRenameResult): void {\n const info = r.serverInfo\n ? `${r.serverInfo.name}${r.serverInfo.version ? ` ${r.serverInfo.version}` : ''}`\n : 'unknown server'\n const mode = r.applied ? 'APPLIED to disk' : 'dry-run (not applied)'\n io.out(`status: ${r.status} ${mode} [${r.encoding}, ${info}]\\n`)\n if (r.versionWarning) io.err(`warning: ${r.versionWarning}\\n`)\n if (r.completeness === 'suspect') {\n const miss = r.suspectedMissedFiles ?? []\n io.err(\n `warning: rename may be INCOMPLETE — the symbol also appears in ${miss.length} same-language file(s) NOT in this edit: ${miss.join(', ')}\\n`,\n )\n io.err(\n ' the language server may scope rename to open files; re-run with --allow-partial-rename to apply anyway\\n',\n )\n } else if (r.completeness === 'unknown') {\n io.err('warning: rename completeness unverified (file scan was truncated)\\n')\n }\n if (r.refused) {\n io.err(`refused: ${r.refused}\\n`)\n return\n }\n io.out(`rename → ${r.newName}: ${r.totalEditCount} edit(s) across ${r.fileCount} file(s)\\n`)\n for (const f of r.edits) {\n io.out(` ${f.file} ${f.editCount} edit(s)${f.outOfRoot ? ' (out of project root)' : ''}\\n`)\n for (const h of f.hunks ?? []) {\n io.out(` ${rangeStr(h.range)} ${h.oldText} → ${h.newText}\\n`)\n }\n }\n for (const op of r.resourceOps ?? []) {\n io.out(` ${op.kind} file: ${op.uris.join(' → ')}\\n`)\n }\n if (r.overwritten?.length)\n io.err(\n `warning: DESTRUCTIVELY overwrote ${r.overwritten.length} existing file(s): ${r.overwritten.join(', ')}\\n`,\n )\n if (r.partial)\n io.err(`warning: PARTIAL apply (no rollback — reconcile via VCS): ${r.partialError ?? ''}\\n`)\n for (const d of r.digests ?? []) {\n io.out(\n ` digest ${d.file}: ${d.before.slice(0, 12)} → ${d.after.slice(0, 12) || '(deleted)'}\\n`,\n )\n }\n}\n","import { readFileSync } from 'node:fs'\nimport { resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n MutateGateError,\n type MutationReport,\n type MutationRunner,\n type MutationSummary,\n parseMutmutResults,\n runCosmicRay,\n runMutation,\n runMutmut,\n summarizeMutation,\n} from '@sackville-mcp/mutate'\nimport type { CliIO } from './index.js'\n\n/**\n * `sackville mutate` — the human surface over `@sackville-mcp/mutate`.\n *\n * `summarize` is a pure report viewer (Stryker JSON or `mutmut results` text). `run` is the\n * gated, diff-scopable mutation run. The CLI's human IS the operator, so the run gate is a\n * straight-through `--allow-run` flag (mirroring `sackville api --unsafe`): the typed project\n * root is auto-allowed (explicit operator intent). The `runner` is injectable so the suite\n * never spawns a real Stryker (ADR 0010: no real spawn in the gate).\n */\nexport async function runMutate(\n args: string[],\n io: CliIO,\n deps: { runner?: MutationRunner } = {},\n): Promise<number> {\n const [sub, ...rest] = args\n switch (sub) {\n case 'summarize':\n return cmdSummarize(rest, io)\n case 'run':\n return cmdRun(rest, io, deps)\n default:\n io.err(`unknown mutate subcommand: ${sub ?? '(none)'}\\n`)\n return 1\n }\n}\n\n/** Format a percent metric (`null` ⇒ not applicable, e.g. zero valid mutants). */\nfunction pct(value: number | null): string {\n return value === null ? 'n/a' : `${value.toFixed(1)}%`\n}\n\nfunction printSummary(io: CliIO, summary: MutationSummary): void {\n const { metrics, survivors } = summary\n const c = metrics.counts\n io.out(\n `mutation score: ${pct(metrics.mutationScore)} (detected ${metrics.detected} / valid ${metrics.valid})\\n`,\n )\n io.out(`covered-code score: ${pct(metrics.mutationScoreBasedOnCoveredCode)}\\n`)\n io.out(\n `killed ${c.killed} survived ${c.survived} timeout ${c.timeout} no-coverage ${c.noCoverage} ` +\n `compile-errors ${c.compileErrors} runtime-errors ${c.runtimeErrors} ignored ${c.ignored} pending ${c.pending}\\n`,\n )\n if (survivors.length === 0) {\n io.out('survivors: (none)\\n')\n return\n }\n io.out(`survivors (${survivors.length}):\\n`)\n for (const s of survivors) {\n io.out(` ${s.file}:${s.line} ${s.mutatorName} [${s.status}]\\n`)\n }\n}\n\nfunction cmdSummarize(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { format: { type: 'string' }, json: { type: 'boolean' } },\n })\n const reportFile = positionals[0]\n if (!reportFile) {\n io.err('mutate summarize needs a <report-file>\\n')\n return 1\n }\n const format = values.format ?? 'stryker'\n if (format !== 'stryker' && format !== 'mutmut') {\n io.err(`unknown report format: ${format} (expected stryker|mutmut)\\n`)\n return 1\n }\n const text = readFileSync(reportFile, 'utf8')\n // mutmut emits plain `module.fn__mutmut_N: status` lines; Stryker emits the\n // mutation-testing-elements JSON. Both normalize to a MutationReport.\n const report: MutationReport =\n format === 'mutmut' ? parseMutmutResults(text) : (JSON.parse(text) as MutationReport)\n const summary = summarizeMutation(report)\n\n if (values.json) {\n io.out(`${JSON.stringify(summary, null, 2)}\\n`)\n return 0\n }\n printSummary(io, summary)\n return 0\n}\n\nasync function cmdRun(\n args: string[],\n io: CliIO,\n deps: { runner?: MutationRunner },\n): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n tool: { type: 'string' },\n file: { type: 'string', multiple: true },\n incremental: { type: 'boolean' },\n 'config-path': { type: 'string' },\n 'allow-run': { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n 'report-path': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('mutate run needs a <project-root>\\n')\n return 1\n }\n const tool = values.tool ?? 'stryker'\n if (tool !== 'stryker' && tool !== 'mutmut' && tool !== 'cosmic-ray') {\n io.err(`unknown tool: ${tool} (expected stryker|mutmut|cosmic-ray)\\n`)\n return 1\n }\n const timeoutRaw = values['timeout-ms']\n const timeoutMs = timeoutRaw !== undefined ? Number(timeoutRaw) : undefined\n\n try {\n const config = {\n projectRoot,\n // The human typed this root, so it is the operator allowlist (explicit intent),\n // exactly as `sackville browser` auto-allows the typed host.\n allowedRoots: [resolve(projectRoot)],\n allowRun: values['allow-run'] ?? false,\n timeoutMs: timeoutMs !== undefined && Number.isFinite(timeoutMs) ? timeoutMs : undefined,\n }\n const input = {\n mutateFiles: values.file,\n incremental: values.incremental ?? false,\n configPath: values['config-path'],\n }\n const result =\n tool === 'mutmut'\n ? await runMutmut(config, input, { runner: deps.runner })\n : tool === 'cosmic-ray'\n ? await runCosmicRay(config, input, { runner: deps.runner })\n : await runMutation(config, input, {\n runner: deps.runner,\n reportPath: values['report-path'],\n })\n\n if (values.json) {\n io.out(`${JSON.stringify(result, null, 2)}\\n`)\n return result.exitCode === 0 ? 0 : 1\n }\n io.out(\n `ran ${tool} (exit ${result.exitCode}); scoped: ${result.scopedFiles.join(', ') || '(project default)'}\\n`,\n )\n printSummary(io, result.summary)\n return result.exitCode === 0 ? 0 : 1\n } catch (e) {\n if (e instanceof MutateGateError) {\n io.err(`refused: ${e.message} (pass --allow-run)\\n`)\n return 1\n }\n io.err(`${(e as Error).message}\\n`)\n return 1\n }\n}\n","import { mkdtempSync, readFileSync } from 'node:fs'\nimport { tmpdir } from 'node:os'\nimport { join, resolve } from 'node:path'\nimport { parseArgs } from 'node:util'\nimport {\n type CaptureContract,\n type ContractResult,\n loadCollection,\n runRequestToHar,\n validateCapturedTraffic,\n} from '@sackville-mcp/api'\nimport { ArtifactStore } from '@sackville-mcp/artifacts'\nimport {\n BrowserGate,\n BrowserManager,\n type CaptureRequest,\n type CaptureRuntime,\n createSsrfProxy,\n driveBrowserFlowToHar,\n engineLauncher,\n resolveEngine,\n} from '@sackville-mcp/browser'\nimport { type DiffCoverageReport, runScoped, type TestRunner } from '@sackville-mcp/coverage'\nimport { changedDependencies, type DependencyAudit, type OsvEcosystem } from '@sackville-mcp/deps'\nimport { type FlakeVerdict, HistoryStore, runAndRecord } from '@sackville-mcp/flake'\nimport {\n type MutationRunner,\n type MutationSummary,\n runCosmicRay,\n runMutation,\n runMutmut,\n} from '@sackville-mcp/mutate'\nimport { Redactor } from '@sackville-mcp/safety'\nimport {\n type CaptureVerdictFacts,\n type ComposeInputs,\n type CompositeVerdict,\n composeVerdict,\n fromContractResults,\n fromDependencyAudits,\n fromDiffCoverage,\n fromFlakeVerdicts,\n fromMutationSummary,\n type Severity,\n} from '@sackville-mcp/verdict'\nimport { type OrchestrateRequest, orchestrate } from '@sackville-mcp/verify'\nimport { auditProjectScoped, makeFetcher, type PackumentFetcher, registriesFrom } from './deps.js'\nimport type { CliIO } from './index.js'\n\nconst SEVERITIES = ['critical', 'high', 'moderate', 'low', 'none']\n\nconst EMPTY_COVERAGE: DiffCoverageReport = {\n files: [],\n uncovered: [],\n summary: { covered: 0, uncovered: 0, nonExecutable: 0, total: 0, filesWithoutCoverage: 0 },\n}\n\n/**\n * Per-pillar run thunk overrides — the test seam (mirrors the MCP `RunDrivingOptions`\n * shape). When absent, `verify run` builds the REAL engine-backed thunk; tests inject\n * fakes so the suite never spawns. The engine runner seams (`TestRunner`/`MutationRunner`)\n * are also injectable for the realistic path.\n */\nexport interface VerifyRunDeps {\n coverage?: (ctx: RunCtx) => Promise<DiffCoverageReport>\n flake?: (ctx: RunCtx) => Promise<FlakeVerdict[]>\n mutate?: (ctx: RunCtx) => Promise<MutationSummary>\n deps?: (ctx: RunCtx) => Promise<{ audits: DependencyAudit[]; osvSnapshotLoaded: boolean }>\n /** Produce-mode contract capture (drive a browser flow → validate). Injected in tests so\n * the suite never spawns a browser; the real path builds the runtime from CLI flags. */\n contract?: (req: CaptureRequest) => Promise<ContractResult[]>\n /** Produce-API contract capture (drive the api runner → synthesize + validate, 5f).\n * Injected in tests so the suite never fetches; the real path builds it from CLI flags. */\n contractApi?: (req: {\n request: string\n collectionDir?: string\n vars?: Record<string, string>\n }) => Promise<ContractResult[] | CaptureVerdictFacts>\n coverageRunner?: TestRunner\n flakeRunner?: TestRunner\n mutateRunner?: MutationRunner\n /** Injected packument fetcher for the realistic deps path (keeps the suite offline). */\n depsFetcher?: PackumentFetcher\n historyStore?: HistoryStore\n}\n\ninterface RunCtx {\n projectRoot: string\n changedFiles: string[]\n diff?: string\n}\n\n/**\n * `sackville verify` — the human surface over the cross-pillar verdict.\n *\n * - `verify [--contract f] [--coverage f] ...` (COMPOSE): fold per-pillar JSON results\n * on disk into one verdict (ADR 0013 §1). The human supplies each pillar's output.\n * - `verify run <root> [--coverage] [--flake --flake-db f] [--mutate [--mutate-tool T --mutate-config f]] [--deps] [--allow-run] ...`\n * (RUN-DRIVING, ADR 0013 Addendum 5c/5d): DRIVE the selected pillars and fold them. The\n * human is the operator, so `--allow-run` is the straight-through gate for the SPAWN\n * pillars (coverage/flake/mutate) and the typed root is auto-allowed; each pillar's own\n * `assertAllowed` still denies without it (⇒ `skipReason:gate-not-set`, never run —\n * \"compose, never widen\"). `--mutate-tool` picks the mutation engine (stryker default |\n * cosmic-ray | mutmut; the Python tools diff-scope via a synthesized config from\n * `--mutate-config`, ADR 0010 addendum 2). `--deps` is gated by NETWORK not spawn (a packument fetch),\n * so it needs no `--allow-run`; a `--diff` scopes the audit to the changed packages\n * (`changedDependencies`). `--flow <name>` (5e) DRIVES an operator-authored browser flow\n * to capture a HAR and validate it against `--openapi`/`--graphql` — gated by the browser\n * egress flags (`--flows-dir`/`--allow-host` + the mandatory SSRF proxy), not `--allow-run`.\n * Runners are injectable so the suite never spawns (ADR 0010).\n *\n * Exit codes (both modes): 0 pass / 1 fail|warn / 2 inconclusive.\n */\nexport async function runVerify(\n args: string[],\n io: CliIO,\n deps: VerifyRunDeps = {},\n): Promise<number> {\n if (args[0] === 'run') return cmdVerifyRun(args.slice(1), io, deps)\n return runVerifyCompose(args, io)\n}\n\nfunction printVerdict(io: CliIO, verdict: CompositeVerdict, json: boolean | undefined): void {\n if (json) {\n io.out(`${JSON.stringify(verdict, null, 2)}\\n`)\n return\n }\n io.out(`verdict: ${verdict.status.toUpperCase()} (worst severity ${verdict.worstSeverity})\\n`)\n for (const p of verdict.pillars) {\n const sev = p.severity !== 'none' ? ` [${p.severity}]` : ''\n const why = p.skipReason ? ` (skipped: ${p.skipReason})` : p.errorReason ? ' (errored)' : ''\n io.out(` ${p.pillar}: ${p.status}${sev}${why} — ${p.headline}\\n`)\n }\n}\n\nfunction exitFor(verdict: CompositeVerdict): number {\n if (verdict.status === 'pass') return 0\n if (verdict.status === 'inconclusive') return 2\n return 1\n}\n\nfunction num(value: string | undefined): number | undefined {\n if (value === undefined) return undefined\n const n = Number(value)\n return Number.isFinite(n) ? n : undefined\n}\n\nasync function cmdVerifyRun(args: string[], io: CliIO, deps: VerifyRunDeps): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n coverage: { type: 'boolean' },\n flake: { type: 'boolean' },\n mutate: { type: 'boolean' },\n 'mutate-tool': { type: 'string' },\n 'mutate-config': { type: 'string' },\n deps: { type: 'boolean' },\n 'allow-run': { type: 'boolean' },\n 'changed-file': { type: 'string', multiple: true },\n diff: { type: 'string' },\n 'flake-db': { type: 'string' },\n // deps run-driving: its gate is NETWORK (a packument fetch), not spawn — the human\n // typing --deps is the operator intent, so it needs no --allow-run.\n 'osv-db': { type: 'string' },\n registry: { type: 'string' },\n 'allow-private': { type: 'boolean' },\n // contract PRODUCE mode (5e): drive an operator-authored flow → capture → validate.\n // Gated by the browser egress flags (allowlist + the mandatory SSRF proxy), not --allow-run.\n flow: { type: 'string' },\n 'flows-dir': { type: 'string' },\n // contract PRODUCE-API mode (5f): drive an operator-authored api request → synthesize\n // + validate. Gated by --allow-unsafe + --allow-host (the api pillar gate), not --allow-run.\n request: { type: 'string' },\n 'collection-dir': { type: 'string' },\n 'allow-unsafe': { type: 'boolean' },\n 'allow-host': { type: 'string', multiple: true },\n var: { type: 'string', multiple: true },\n openapi: { type: 'string' },\n graphql: { type: 'string' },\n 'graphql-endpoint': { type: 'string' },\n engine: { type: 'string' },\n 'no-sandbox': { type: 'boolean' },\n headed: { type: 'boolean' },\n 'timeout-ms': { type: 'string' },\n 'fail-at-or-above': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n\n const projectRoot = positionals[0]\n if (!projectRoot) {\n io.err('verify run needs a <project-root>\\n')\n return 2\n }\n const failAtOrAbove = values['fail-at-or-above']\n if (failAtOrAbove !== undefined && !SEVERITIES.includes(failAtOrAbove)) {\n io.err(`--fail-at-or-above must be one of ${SEVERITIES.join('|')}\\n`)\n return 2\n }\n\n const allowRun = values['allow-run'] ?? false\n const allowedRoots = [resolve(projectRoot)]\n const changedFiles = values['changed-file'] ?? []\n const diff = values.diff !== undefined ? readFileSync(values.diff, 'utf8') : undefined\n const timeoutMs = num(values['timeout-ms'])\n const ctx: RunCtx = { projectRoot, changedFiles, diff }\n\n const request: OrchestrateRequest = {}\n if (values.coverage) {\n const ovr = deps.coverage\n request.coverage = {\n run: ovr\n ? () => ovr(ctx)\n : async () => {\n const r = await runScoped(\n { projectRoot, allowedRoots, allowRun, timeoutMs },\n { changedFiles, diff },\n { runner: deps.coverageRunner },\n )\n return r.report ?? EMPTY_COVERAGE\n },\n }\n }\n if (values.mutate) {\n const ovr = deps.mutate\n // Fork D: --mutate-tool selects the engine (default stryker); --mutate-config supplies the\n // Python tools' base config (cosmic-ray.toml / pyproject.toml). The runner is injectable so\n // the suite never spawns; --diff/--changed-file scope the run.\n const tool = values['mutate-tool'] ?? 'stryker'\n if (tool !== 'stryker' && tool !== 'cosmic-ray' && tool !== 'mutmut') {\n io.err(`verify run --mutate-tool must be stryker | cosmic-ray | mutmut (got ${tool})\\n`)\n return 2\n }\n const configPath = values['mutate-config']\n request.mutate = {\n run: ovr\n ? () => ovr(ctx)\n : async () => {\n const cfg = { projectRoot, allowedRoots, allowRun, timeoutMs }\n const mInput = { mutateFiles: changedFiles, configPath }\n const r =\n tool === 'cosmic-ray'\n ? await runCosmicRay(cfg, mInput, { runner: deps.mutateRunner })\n : tool === 'mutmut'\n ? await runMutmut(cfg, mInput, { runner: deps.mutateRunner })\n : await runMutation(cfg, mInput, { runner: deps.mutateRunner })\n return r.summary\n },\n }\n }\n if (values.flake) {\n const ovr = deps.flake\n if (ovr) {\n request.flake = { run: () => ovr(ctx) }\n } else {\n const dbPath = values['flake-db']\n const store = deps.historyStore ?? (dbPath ? HistoryStore.open(dbPath) : undefined)\n if (!store) {\n io.err('verify run --flake needs --flake-db <path>\\n')\n return 2\n }\n request.flake = {\n run: async () => {\n try {\n const r = await runAndRecord(\n store,\n { projectRoot, allowedRoots, allowRun, timeoutMs },\n { files: changedFiles },\n { runner: deps.flakeRunner },\n )\n return r.verdicts\n } finally {\n if (!deps.historyStore && dbPath) store.close()\n }\n },\n }\n }\n }\n\n if (values.deps) {\n const ovr = deps.deps\n if (ovr) {\n request.deps = { run: () => ovr(ctx) }\n } else {\n // npm-first (matches the deps run-wiring); the diff scopes the audit to the\n // changed packages, falling back to the whole project when none changed.\n const ecosystem: OsvEcosystem = 'npm'\n const fetchPackument = deps.depsFetcher ?? makeFetcher(registriesFrom(values))\n const osvDir = values['osv-db']\n request.deps = {\n run: async () => {\n const scoped = diff ? changedDependencies(diff, ecosystem) : []\n const { audits, osvSnapshotLoaded } = await auditProjectScoped({\n project: projectRoot,\n ecosystem,\n names: scoped.length > 0 ? scoped : undefined,\n osvDir,\n fetchPackument,\n })\n return { audits, osvSnapshotLoaded }\n },\n }\n }\n }\n\n if (values.request && values.flow) {\n io.err('verify run: --request and --flow are mutually exclusive\\n')\n return 2\n }\n\n if (values.request) {\n const requestName = values.request\n const vars = parseVars(values.var)\n const ovr = deps.contractApi\n if (ovr) {\n request.contract = {\n source: 'capture-from-HAR',\n run: () => ovr({ request: requestName, collectionDir: values['collection-dir'], vars }),\n }\n } else {\n const colDir = values['collection-dir']\n if (!colDir) {\n io.err('verify run --request needs --collection-dir <dir>\\n')\n return 2\n }\n const contract = readCaptureContract(values)\n const store = new ArtifactStore(\n mkdtempSync(join(tmpdir(), 'sackville-verify-cap-')),\n 'verify',\n )\n // The human is the operator: --allow-unsafe + --allow-host are the api pillar gate\n // (a mutating request without them dry-runs ⇒ the driver throws ⇒ inconclusive). The\n // run-resolved {{secret:NAME}} pairs are folded into the redactor by the driver, so a\n // fresh Redactor scrubs both the stored HAR AND the findings (NOT the empty `{}` the\n // browser path can use — the synthesized api HAR holds raw bytes until redaction).\n request.contract = {\n source: 'capture-from-HAR',\n run: async () => {\n const out = await runRequestToHar(\n loadCollection(colDir),\n requestName,\n {\n vars,\n allowUnsafe: values['allow-unsafe'] ?? false,\n allowedHosts: values['allow-host'] ?? [],\n },\n { store, redactor: new Redactor(), contract },\n )\n return out.verdict\n },\n }\n }\n }\n\n if (values.flow) {\n const flow = values.flow\n const vars = parseVars(values.var)\n const ovr = deps.contract\n if (ovr) {\n request.contract = { source: 'capture-from-HAR', run: () => ovr({ flow, vars }) }\n } else {\n if (!values['flows-dir']) {\n io.err('verify run --flow needs --flows-dir <dir>\\n')\n return 2\n }\n const flowsDir = values['flows-dir']\n const contract = readCaptureContract(values)\n // The human is the operator: the typed flow's hosts are allowlisted via --allow-host;\n // the mandatory SSRF proxy fronts every request (built in the runtime factory).\n const store = new ArtifactStore(\n mkdtempSync(join(tmpdir(), 'sackville-verify-cap-')),\n 'verify',\n )\n request.contract = {\n source: 'capture-from-HAR',\n run: async () => {\n const { harHandle } = await driveBrowserFlowToHar(\n { flow, vars },\n { runtimeFactory: () => captureRuntimeFromFlags(values), store, flowsDir },\n )\n const har = store.get(harHandle)?.body\n if (!har) throw new Error('no HAR was captured for the driven flow')\n return validateCapturedTraffic(har, contract, {}).results\n },\n }\n }\n }\n\n if (Object.keys(request).length === 0) {\n io.err(\n 'verify run needs ≥1 pillar (--coverage / --flake / --mutate / --deps / --flow / --request)\\n',\n )\n return 2\n }\n\n const { verdict } = await orchestrate(request, {\n policy: { failAtOrAbove: failAtOrAbove as Severity | undefined },\n })\n printVerdict(io, verdict, values.json)\n return exitFor(verdict)\n}\n\n/** Parse repeated `--var k=v` flags into a map (non-secret flow vars). */\nfunction parseVars(pairs: string[] | undefined): Record<string, string> {\n const vars: Record<string, string> = {}\n for (const p of pairs ?? []) {\n const i = p.indexOf('=')\n if (i > 0) vars[p.slice(0, i)] = p.slice(i + 1)\n }\n return vars\n}\n\n/** Build the capture→contract from the openapi/graphql flags (≥1 needed, like the MCP tool). */\nfunction readCaptureContract(values: {\n openapi?: string\n graphql?: string\n 'graphql-endpoint'?: string\n}): CaptureContract {\n const contract: CaptureContract = {}\n if (values.openapi) contract.openapi = JSON.parse(readFileSync(values.openapi, 'utf8'))\n if (values.graphql) {\n contract.graphql = {\n endpointPath: values['graphql-endpoint'] ?? '/graphql',\n sdl: readFileSync(values.graphql, 'utf8'),\n }\n }\n return contract\n}\n\n/** Build a single-shot CaptureRuntime from the CLI's browser egress flags (mirrors\n * `sackville browser`): a gated, proxy-fronted manager with HAR recording armed. */\nasync function captureRuntimeFromFlags(values: {\n 'allow-host'?: string[]\n 'allow-private'?: boolean\n 'no-sandbox'?: boolean\n headed?: boolean\n engine?: string\n}): Promise<CaptureRuntime> {\n const gate = new BrowserGate({ allowedHosts: values['allow-host'] ?? [] })\n const proxy = await createSsrfProxy({ allowPrivate: values['allow-private'] ?? false })\n const harDir = mkdtempSync(join(tmpdir(), 'sackville-verify-har-'))\n const manager = new BrowserManager({\n gate,\n harDir,\n launch: engineLauncher(resolveEngine(values.engine), {\n headless: !values.headed,\n proxyServer: proxy.url,\n noSandbox: values['no-sandbox'] ?? false,\n }),\n })\n return {\n manager,\n gate,\n redact: (s) => s,\n config: { harDir },\n shutdown: async () => {\n await manager.shutdown()\n await proxy.close()\n },\n }\n}\n\nfunction runVerifyCompose(args: string[], io: CliIO): number {\n const { values } = parseArgs({\n args,\n options: {\n contract: { type: 'string' },\n source: { type: 'string' },\n coverage: { type: 'string' },\n deps: { type: 'string' },\n 'osv-snapshot-loaded': { type: 'boolean' },\n flake: { type: 'string' },\n mutate: { type: 'string' },\n 'fail-at-or-above': { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n\n const failAtOrAbove = values['fail-at-or-above']\n if (failAtOrAbove !== undefined && !SEVERITIES.includes(failAtOrAbove)) {\n io.err(`--fail-at-or-above must be one of ${SEVERITIES.join('|')}\\n`)\n return 2\n }\n\n const readJson = (p: string): unknown => JSON.parse(readFileSync(p, 'utf8'))\n const inputs: ComposeInputs = {}\n\n if (values.contract) {\n const c = readJson(values.contract) as ContractResult[] | { results?: ContractResult[] }\n const results = Array.isArray(c) ? c : (c.results ?? [])\n inputs.contract = fromContractResults(\n results,\n values.source === 'run' ? 'run' : 'capture-from-HAR',\n )\n }\n if (values.coverage) {\n inputs.coverage = fromDiffCoverage(\n readJson(values.coverage) as Parameters<typeof fromDiffCoverage>[0],\n )\n }\n if (values.deps) {\n inputs.deps = fromDependencyAudits(\n readJson(values.deps) as Parameters<typeof fromDependencyAudits>[0],\n { osvSnapshotLoaded: values['osv-snapshot-loaded'] ?? false },\n )\n }\n if (values.flake) {\n inputs.flake = fromFlakeVerdicts(\n readJson(values.flake) as Parameters<typeof fromFlakeVerdicts>[0],\n )\n }\n if (values.mutate) {\n inputs.mutate = fromMutationSummary(\n readJson(values.mutate) as Parameters<typeof fromMutationSummary>[0],\n )\n }\n\n const verdict = composeVerdict(inputs, { failAtOrAbove: failAtOrAbove as Severity | undefined })\n printVerdict(io, verdict, values.json)\n return exitFor(verdict)\n}\n","import { parseArgs } from 'node:util'\nimport {\n detectInstalledVersion,\n type Ecosystem,\n getDoc,\n listVersions,\n openDb,\n resolveVersion,\n searchDocs,\n} from '@sackville-mcp/core'\nimport type { Embedder } from '@sackville-mcp/embed'\nimport type DatabaseType from 'better-sqlite3'\nimport { runApi } from './api.js'\nimport { runBrowser } from './browser.js'\nimport { runCoverage } from './coverage.js'\nimport { runDeps } from './deps.js'\nimport { runFlake } from './flake.js'\nimport { runLsp } from './lsp.js'\nimport { runMutate } from './mutate.js'\nimport { runVerify } from './verify.js'\n\n/** Output sinks and dependencies injected into `run` (so it is testable). */\nexport interface CliIO {\n out: (text: string) => void\n err: (text: string) => void\n /** When present, queries are embedded for hybrid search. */\n embedder?: Embedder\n env?: Record<string, string | undefined>\n}\n\nconst HELP = `sackville — version-pinned documentation search\n\nUsage:\n sackville search <query…> [-l <lib>] [--version <v>] [--installed <v>] [-p <dir>] [--ecosystem <e>] [--type <t>] [--limit <n>] [--json]\n sackville get <id> [--json]\n sackville versions <library>\n sackville detect <project> <library> [--ecosystem <node|python|ruby>]\n\nAPI testing:\n sackville api list <dir> [--json]\n sackville api get <dir> <name> [--json]\n sackville api run <dir> <name> [--var k=v…] [--env <e>] [--unsafe] [--allow-host <h>…] [--keyring] [--block-private] [--max-redirects <n>] [--openapi <spec.json>] [--json]\n sackville api run-collection <dir> <name…> [--var k=v…] [--env <e>] [--unsafe] [--allow-host <h>…] [--keyring] [--block-private] [--max-redirects <n>] [--stop-on-failure] [--json]\n sackville api validate --graphql <schema> --query <q> [--operation <name>] [--json]\n sackville api import <postman|insomnia|openapi|har> <source-file> <dest-dir> [--name <n>]\n\nBrowser testing (single-shot; the typed host is auto-allowed):\n sackville browser snapshot <url> [--allow-host <h>…] [--allow-private] [--no-sandbox] [--headed] [--engine chromium|firefox|webkit] [--json]\n sackville browser audit <url> [same flags] (exit 1 if any a11y violations)\n sackville browser screenshot <url> [--out <file>] [--full-page] [same flags]\n sackville browser run <flow.bru> [--var k=v…] [--unsafe] [--allow-host <h>…] [same flags] (replay a persisted flow; exit 1 on failure)\n\nMutation testing:\n sackville mutate summarize <report-file> [--format stryker|mutmut] [--json]\n sackville mutate run <project-root> [--file <f>…] [--incremental] [--allow-run] [--timeout-ms <n>] [--report-path <p>] [--json] (gated; needs --allow-run)\n\nCoverage (impact-scoped; exit 1 when a new line is uncovered):\n sackville coverage uncovered-in-diff --diff <file> --coverage <file> [--coverage-format istanbul|coveragepy] [--project-root <p>] [--json]\n sackville coverage run-scoped <project-root> --changed-file <f>… [--diff <file>] [--allow-run] [--timeout-ms <n>] [--json] (gated; needs --allow-run)\n\nFlaky-test detection (--db <run-history.db> or SACKVILLE_FLAKE_DB):\n sackville flake status [--min-runs <n>] [--limit-per-test <n>] [--since <ISO>] [--json]\n sackville flake candidates [--min-flake-score <0..1>] [--min-runs <n>] [--json]\n sackville flake ingest <report-file> [--format vitest|pytest] [--at <ISO>] [--project-root <p>] [--run-group <g>] [--json]\n sackville flake release <testId>\n sackville flake run <project-root> [--repeat <n>] [--file <f>…] [--run-group <g>] [--allow-run] [--timeout-ms <n>] [--json] (gated)\n sackville flake quarantine <testId> --reason <r> --expires-at <ISO> [--flake-score <s>] [--allow-quarantine] [--max-expiry-ms <n>] [--json] (gated write)\n\nDependency/version intelligence (for the INSTALLED version; exit 1 on a finding):\n sackville deps audit <project> <package> [--ecosystem npm|PyPI|RubyGems] [--version <v>] [--osv-db <dir>] [--registry <url>] [--allow-private] [--json]\n sackville deps audit-project <project> [--ecosystem <e>] [--skip-dev] [--osv-db <dir>] [--registry <url>] [--allow-private] [--json]\n sackville deps changelog <package> (--from <v> | --project <dir>) [--to <v>] [--ecosystem <e>] [--registry <url>] [--json]\n\nSemantic code navigation (LSP; single-shot; --servers <json> or SACKVILLE_LSP_SERVERS binds the server registry):\n sackville lsp languages [--servers <json>] [--json]\n sackville lsp definition|type-definition|references|hover <lang> <file> <line> <col> --project <dir> --allow-run [--servers <json>] [--timeout-ms <n>] [--json]\n sackville lsp symbols <lang> <file> --project <dir> --allow-run [--servers <json>] [--json]\n sackville lsp call-hierarchy <lang> <file> <line> <col> --project <dir> --allow-run [--direction incoming|outgoing] [--json]\n sackville lsp rename <lang> <file> <line> <col> <newName> --project <dir> --allow-run [--allow-write] [--allow-partial-rename] [--json] (dry-run unless --allow-write)\n (exit 2 = server still indexing, retry; a \"suspect\" rename — an open-files-scoped server's likely-partial edit — is refused for write unless --allow-partial-rename)\n\nGlobal:\n -i, --index <file> index to query (or set SACKVILLE_INDEX)\n`\n\nexport async function run(argv: string[], io: CliIO): Promise<number> {\n const [command, ...rest] = argv\n switch (command) {\n case 'search':\n return cmdSearch(rest, io)\n case 'get':\n return cmdGet(rest, io)\n case 'versions':\n return cmdVersions(rest, io)\n case 'detect':\n return cmdDetect(rest, io)\n case 'api':\n return runApi(rest, io)\n case 'browser':\n return runBrowser(rest, io)\n case 'mutate':\n return runMutate(rest, io)\n case 'coverage':\n return runCoverage(rest, io)\n case 'flake':\n return runFlake(rest, io)\n case 'deps':\n return runDeps(rest, io)\n case 'lsp':\n return runLsp(rest, io)\n case 'verify':\n return runVerify(rest, io)\n case 'help':\n case '--help':\n case '-h':\n io.out(HELP)\n return 0\n case undefined:\n io.err(HELP)\n return 1\n default:\n io.err(`unknown command: ${command}\\n`)\n io.err(HELP)\n return 1\n }\n}\n\nfunction openIndex(indexFlag: string | undefined, io: CliIO): DatabaseType.Database | null {\n const path = indexFlag ?? io.env?.SACKVILLE_INDEX\n if (!path) {\n io.err('no index given: pass --index <file> or set SACKVILLE_INDEX\\n')\n return null\n }\n return openDb(path)\n}\n\nasync function cmdSearch(args: string[], io: CliIO): Promise<number> {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: {\n index: { type: 'string', short: 'i' },\n library: { type: 'string', short: 'l' },\n version: { type: 'string' },\n installed: { type: 'string' },\n project: { type: 'string', short: 'p' },\n ecosystem: { type: 'string' },\n type: { type: 'string' },\n limit: { type: 'string' },\n json: { type: 'boolean' },\n },\n })\n const query = positionals.join(' ').trim()\n if (!query) {\n io.err('search needs a query\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n\n try {\n // Version precedence: --version > --installed > --project (auto-detect).\n let effectiveVersion = values.version\n let note: string | undefined\n if (!values.version && (values.installed || values.project) && values.library) {\n let requested = values.installed\n if (!requested && values.project) {\n const detected = detectInstalledVersion(values.project, values.library, {\n ecosystem: values.ecosystem as Ecosystem | undefined,\n })\n requested = detected.version ?? undefined\n if (!requested) note = `could not detect ${values.library} in ${values.project}`\n }\n if (requested) {\n const res = resolveVersion(listVersions(db, values.library), requested)\n note = res.note\n if (res.resolved) effectiveVersion = res.resolved\n }\n }\n\n let queryVector: number[] | undefined\n if (io.embedder) {\n try {\n queryVector = await io.embedder.embed(query)\n } catch {\n queryVector = undefined\n }\n }\n\n const results = searchDocs(db, query, {\n library: values.library,\n version: effectiveVersion,\n type: values.type,\n limit: values.limit ? Number(values.limit) : undefined,\n queryVector,\n })\n\n if (values.json) {\n io.out(\n `${JSON.stringify({ query, version: effectiveVersion ?? null, note, results }, null, 2)}\\n`,\n )\n return 0\n }\n if (note) io.err(`${note}\\n`)\n if (results.length === 0) {\n io.out('no matches\\n')\n return 0\n }\n for (const r of results) {\n const sym = r.symbol ? ` (${r.symbol})` : ''\n io.out(`${r.version} [${r.type ?? '-'}] ${r.title}${sym}\\n`)\n io.out(` ${r.snippet}\\n`)\n io.out(` sackville://doc/${r.id}\\n`)\n }\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdGet(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' }, json: { type: 'boolean' } },\n })\n const id = Number(positionals[0])\n if (!Number.isInteger(id)) {\n io.err('get needs a numeric id\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const doc = getDoc(db, id)\n if (!doc) {\n io.err(`no document with id ${id}\\n`)\n return 1\n }\n if (values.json) {\n io.out(`${JSON.stringify(doc, null, 2)}\\n`)\n return 0\n }\n io.out(`${doc.title} [${doc.type ?? '-'}] ${doc.library} ${doc.version}\\n`)\n if (doc.headingPath) io.out(`${doc.headingPath}\\n`)\n if (doc.url) io.out(`${doc.url}\\n`)\n io.out(`\\n${doc.body}\\n`)\n if (doc.attribution) io.out(`\\n— ${doc.attribution}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdVersions(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' } },\n })\n const library = positionals[0]\n if (!library) {\n io.err('versions needs a library\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const versions = listVersions(db, library)\n io.out(versions.length ? `${versions.join('\\n')}\\n` : `no versions indexed for ${library}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n\nfunction cmdDetect(args: string[], io: CliIO): number {\n const { values, positionals } = parseArgs({\n args,\n allowPositionals: true,\n options: { index: { type: 'string', short: 'i' }, ecosystem: { type: 'string' } },\n })\n const [project, library] = positionals\n if (!project || !library) {\n io.err('detect needs <project> <library>\\n')\n return 1\n }\n const db = openIndex(values.index, io)\n if (!db) return 1\n try {\n const detected = detectInstalledVersion(project, library, {\n ecosystem: values.ecosystem as Ecosystem | undefined,\n })\n const res = resolveVersion(listVersions(db, library), detected.version ?? '')\n io.out(`detected: ${detected.version ?? '(none)'} (${detected.source})\\n`)\n io.out(`resolved: ${res.resolved ?? '(none)'}\\n`)\n io.out(`${res.note}\\n`)\n return 0\n } finally {\n db.close()\n }\n}\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;AAkCA,eAAe,aACb,MACA,IACoD;CACpD,IAAI;CACJ,IAAI;EAEF,YAAW,MADQ,OAAO,cAAc,QAAQ,IAAI,CAAC,EAAE,OACxC;CACjB,SAAS,KAAK;EACZ,GAAG,IAAI,yCAAyC,KAAK,IAAK,IAAc,QAAQ,GAAG;EACnF;CACF;CACA,IAAI,CAAC,YAAY,OAAO,aAAa,UAAU;EAC7C,GAAG,IAAI,0BAA0B,KAAK,oDAAoD;EAC1F;CACF;CACA,OAAO;AACT;;AAGA,MAAM,YAAY;;AAGlB,SAAS,YAAY,GAAG,SAA2C;CACjE,MAAM,wBAAQ,IAAI,IAAY;CAC9B,KAAK,MAAM,KAAK,SAAS;EACvB,IAAI,CAAC,GAAG;EACR,KAAK,MAAM,KAAK,EAAE,SAAS,SAAS,GAClC,IAAI,EAAE,IAAI,MAAM,IAAI,EAAE,EAAE;CAE5B;CACA,OAAO,CAAC,GAAG,KAAK,EAAE,KAAK;AACzB;;AAGA,SAAS,YAAY,GAAmB;CACtC,OAAO,EAAE,QAAQ,YAAY,IAAI,SAAS,WAAW,KAAK,EAAE;AAC9D;;AAGA,SAASA,YAAU,KAAoD;CACrE,MAAM,OAAgC,CAAC;CACvC,KAAK,MAAM,QAAQ,OAAO,CAAC,GAAG;EAC5B,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,OAAO,IACT,KAAK,QAAQ;OAEb,KAAK,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,MAAM,KAAK,CAAC;CAE/C;CACA,OAAO;AACT;AAEA,eAAsB,OAAO,MAAgB,IAA4B;CACvE,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,QACH,OAAO,QAAQ,MAAM,EAAE;EACzB,KAAK,OACH,OAAOC,SAAO,MAAM,EAAE;EACxB,KAAK,OACH,OAAOC,SAAO,MAAM,EAAE;EACxB,KAAK,kBACH,OAAO,iBAAiB,MAAM,EAAE;EAClC,KAAK,YACH,OAAO,MAAM,YAAY,MAAM,EAAE;EACnC,KAAK,oBACH,OAAO,mBAAmB,MAAM,EAAE;EACpC,KAAK,oBACH,OAAO,mBAAmB,MAAM,EAAE;EACpC,KAAK,UACH,OAAO,UAAU,MAAM,EAAE;EAC3B;GACE,GAAG,IAAI,2BAA2B,OAAO,SAAS,GAAG;GACrD,OAAO;CACX;AACF;AAEA,SAAS,QAAQ,MAAgB,IAAmB;CAClD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,EAAE;CACvC,CAAC;CACD,MAAM,MAAM,YAAY;CACxB,IAAI,CAAC,KAAK;EACR,GAAG,IAAI,wBAAwB;EAC/B,OAAO;CACT;CAEA,MAAM,WAAW,CAAC,GADC,eAAe,GACJ,EAAE,SAAS,OAAO,CAAC,EAAE,KAAK,OAAO;EAC7D,MAAM,EAAE,QAAQ;EAChB,QAAQ,EAAE,QAAQ;EAClB,KAAK,EAAE,QAAQ;CACjB,EAAE;CACF,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,EAAE,SAAS,GAAG,MAAM,CAAC,EAAE,GAAG;EACnD,OAAO;CACT;CACA,KAAK,MAAM,KAAK,UACd,GAAG,IAAI,GAAG,EAAE,OAAO,IAAI,EAAE,KAAK,IAAI,EAAE,IAAI,GAAG;CAE7C,OAAO;AACT;AAEA,SAASD,SAAO,MAAgB,IAAmB;CACjD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS,EAAE,MAAM,EAAE,MAAM,UAAU,EAAE;CACvC,CAAC;CACD,MAAM,CAAC,KAAK,QAAQ;CACpB,IAAI,CAAC,OAAO,CAAC,MAAM;EACjB,GAAG,IAAI,8BAA8B;EACrC,OAAO;CACT;CAEA,MAAM,QADa,eAAe,GACX,EAAE,SAAS,IAAI,IAAI;CAC1C,IAAI,CAAC,OAAO;EACV,GAAG,IAAI,oBAAoB,KAAK,GAAG;EACnC,OAAO;CACT;CACA,MAAM,EAAE,YAAY;CAEpB,MAAM,UAAU,YACd,QAAQ,KACR,GAAG,QAAQ,QAAQ,SAAS,MAAM,CAAC,EAAE,MAAM,EAAE,KAAK,CAAC,GACnD,QAAQ,MAAM,OAChB;CACA,IAAI,OAAO,MAAM;EACf,GAAG,IACD,GAAG,KAAK,UACN;GACE,MAAM,QAAQ;GACd,QAAQ,QAAQ;GAChB,KAAK,QAAQ;GACb,SAAS,QAAQ;GACjB,iBAAiB;EACnB,GACA,MACA,CACF,EAAE,GACJ;EACA,OAAO;CACT;CAGA,GAAG,IAAI,GAAG,QAAQ,OAAO,IAAI,YAAY,QAAQ,GAAG,EAAE,GAAG;CACzD,KAAK,MAAM,KAAK,QAAQ,SACtB,GAAG,IAAI,KAAK,EAAE,KAAK,IAAI,YAAY,EAAE,KAAK,EAAE,GAAG;CAEjD,GAAG,IAAI,qBAAqB,QAAQ,SAAS,QAAQ,KAAK,IAAI,IAAI,SAAS,GAAG;CAC9E,OAAO;AACT;;AAGA,MAAM,cAAc;CAClB,KAAK;EAAE,MAAM;EAAU,UAAU;CAAK;CACtC,KAAK,EAAE,MAAM,SAAS;CACtB,QAAQ,EAAE,MAAM,UAAU;CAC1B,cAAc;EAAE,MAAM;EAAU,UAAU;CAAK;CAC/C,iBAAiB,EAAE,MAAM,UAAU;CACnC,iBAAiB,EAAE,MAAM,SAAS;CAClC,SAAS,EAAE,MAAM,UAAU;CAC3B,MAAM,EAAE,MAAM,UAAU;AAC1B;;AAGA,SAAS,kBAAkB,KAA6C;CACtE,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAA;CAC9B,MAAM,IAAI,OAAO,GAAG;CACpB,OAAO,OAAO,UAAU,CAAC,KAAK,KAAK,IAAI,IAAI,KAAA;AAC7C;;;AAIA,SAAS,WAAW,SAAuD;CACzE,OAAO,UAAU,mBAAmB,EAAE,SAAS,KAAK,CAAC,IAAI,KAAA;AAC3D;;AAGA,SAAS,gBAAgB,WAA0B,QAAyB;CAC1E,MAAM,MAAM,UAAU,IAAI,MAAM,GAAG,QAAQ;CAC3C,IAAI;EACF,OAAO,KAAK,MAAM,GAAG;CACvB,QAAQ;EACN,OAAO;CACT;AACF;;;AAIA,SAAS,eACP,KACA,SACgB;CAChB,MAAM,WAAW,IAAI,SAAS;CAC9B,KAAK,MAAM,KAAK,SAAS,SAAS,SAAS,EAAE,MAAM,EAAE,KAAK;CAC1D,OAAO;EACL,GAAG;EACH,UAAU,IAAI,SAAS,KAAK,OAAO;GACjC,GAAG;GACH,SAAS,SAAS,OAAO,EAAE,OAAO;GAClC,GAAI,EAAE,SAAS,KAAA,IAAY,EAAE,MAAM,SAAS,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;EAClE,EAAE;CACJ;AACF;AAEA,SAAS,cAAc,IAAW,UAA0B,QAAQ,YAAkB;CACpF,GAAG,IAAI,GAAG,MAAM,IAAI,SAAS,QAAQ,UAAU,UAAU,GAAG;CAC5D,KAAK,MAAM,KAAK,SAAS,UACvB,GAAG,IAAI,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,UAAU,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,GAAG,GAAG;AAEnG;AAEA,eAAeC,SAAO,MAAgB,IAA4B;CAChE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,GAAG;GACH,SAAS,EAAE,MAAM,SAAS;GAC1B,SAAS,EAAE,MAAM,SAAS;GAC1B,UAAU,EAAE,MAAM,SAAS;EAC7B;CACF,CAAC;CACD,MAAM,CAAC,KAAK,QAAQ;CACpB,IAAI,CAAC,OAAO,CAAC,MAAM;EACjB,GAAG,IAAI,8BAA8B;EACrC,OAAO;CACT;CACA,MAAM,aAAa,eAAe,GAAG;CACrC,IAAI,CAAC,WAAW,SAAS,IAAI,IAAI,GAAG;EAClC,GAAG,IAAI,oBAAoB,KAAK,GAAG;EACnC,OAAO;CACT;CACA,MAAM,YAAY,IAAI,cAAc;CAGpC,MAAM,UAAU;EACd,MAAMF,YAAU,OAAO,GAAG;EAC1B,KAAK,OAAO;EACZ,aAAa,OAAO,UAAU;EAC9B,cAAc,OAAO;EACrB,cAAc,CAAC,OAAO;EACtB,cAAc,kBAAkB,OAAO,gBAAgB;EACvD,SAAS,WAAW,OAAO,OAAO;EAClC;CACF;CAGA,IAAI;CACJ,IAAI;CACJ,IAAI,OAAO,WAAW,OAAO,SAAS;EACpC,MAAM,SAAS,MAAM,sBAAsB,YAAY,MAAM,OAAO;EACpE,SAAS,OAAO;EAChB,aAAa,OAAO;CACtB,OACE,SAAS,MAAM,WAAW,YAAY,MAAM,OAAO;CAGrD,IAAI;CACJ,IAAI;CACJ,IAAI,OAAO,SAAS;EAClB,MAAM,OAAO,KAAK,MAAM,aAAa,OAAO,SAAS,MAAM,CAAC;EAC5D,MAAM,UAAU,QAAQ,OAAO,OAAO;EAGtC,IAAI,OAAO,QAAQ,OAAO,UAAU;GAClC,MAAM,MAAM,IAAI,IAAI,OAAO,QAAQ,GAAG;GACtC,WAAW,wBACT,MACA;IAAE,QAAQ,OAAO,QAAQ;IAAQ,MAAM,IAAI;GAAS,GACpD;IACE,QAAQ,OAAO,SAAS;IACxB,SAAS,OAAO,SAAS;IACzB,MAAM,gBAAgB,WAAW,OAAO,SAAS,UAAU;GAC7D,GAEA,EAAE,QAAQ,CACZ;EACF;EAGA,IAAI,cAAc,CAAC,kBAAkB,WAAW,QAAQ,IAAI,GAO1D,kBAAkB,eANN,uBAAuB,MAAM,WAAW,SAAS;GAC3D;GAEA,2BAA2B;GAC3B,qBAAqB;EACvB,CACmC,GAAG,WAAW,iBAAiB;CAEtE;CAKA,IAAI;CACJ,IAAI,OAAO,WAAW,cAAc,kBAAkB,WAAW,QAAQ,IAAI,GAAG;EAC9E,MAAM,MAAM,aAAa,OAAO,SAAS,MAAM;EAG/C,IAAI;EACJ,IAAI,OAAO,aAAa,KAAA,GAAW;GACjC,iBAAiB,MAAM,aAAa,OAAO,UAAU,EAAE;GACvD,IAAI,mBAAmB,KAAA,GAAW,OAAO;EAC3C;EACA,MAAM,MAAM,WAAW,QAAQ;EAe/B,kBAAkB,eAVN,yBAAyB,KAAK,IAAI,OAAO;GACnD,eAAe,IAAI;GACnB,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;GAC3C,GAAI,OAAO,QAAQ,OAAO,WACtB,EAAE,MAAM,gBAAgB,WAAW,OAAO,SAAS,UAAU,EAAE,IAC/D,CAAC;GACL,GAAI,IAAI,cAAc,KAAA,IAClB;IAAE,WAAW,IAAI;IAAW,wBAAwB;GAAK,IACzD,CAAC;EACP,CACmC,GAAG,WAAW,iBAAiB;CACpE;CAKA,MAAM,eAAe,CAAC,CAAC,OAAO,UAAU,WAAW,OAAO,MAAM,EAAE,IAAI;CACtE,MAAM,KACJ,OAAO,QACP,iBACC,WAAW,SAAS,QAAQ,UAC5B,kBAAkB,gBAAgB,QAAQ,UAC1C,kBAAkB,gBAAgB,QAAQ;CAE7C,IAAI,OAAO,MAAM;EACf,GAAG,IACD,GAAG,KAAK,UAAU;GAAE,GAAG;GAAQ,GAAI,WAAW,EAAE,SAAS,IAAI,CAAC;GAAI,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;GAAI,GAAI,kBAAkB,EAAE,gBAAgB,IAAI,CAAC;EAAG,GAAG,MAAM,CAAC,EAAE,GACjL;EACA,OAAO,KAAK,IAAI;CAClB;CAEA,GAAG,IAAI,GAAG,OAAO,QAAQ,OAAO,IAAI,OAAO,QAAQ,IAAI,GAAG;CAC1D,IAAI,OAAO,MACT,GAAG,IAAI,QAAQ;MAEf,GAAG,IAAI,qBAAqB,OAAO,SAAS,KAAK,OAAO,WAAW,GAAG,GAAG;CAE3E,IAAI,OAAO,UAAU;EACnB,MAAM,MAAM,OAAO;EACnB,GAAG,IAAI,UAAU,IAAI,OAAO,IAAI,IAAI,UAAU,KAAK;EACnD,KAAK,MAAM,KAAK,IAAI,YAClB,GAAG,IAAI,GAAG,EAAE,OAAO,SAAS,OAAO,IAAI,EAAE,OAAO,GAAG,EAAE,KAAK,EAAE,OAAO,IAAI,EAAE,SAAS,GAAG,GAAG;EAE1F,KAAK,MAAM,KAAK,IAAI,aAClB,GAAG,IAAI,GAAG,EAAE,OAAO,SAAS,OAAO,YAAY,EAAE,OAAO,EAAE,QAAQ,MAAM,EAAE,UAAU,GAAG,GAAG;EAE5F,GAAG,IAAI,SAAS,IAAI,WAAW,GAAG;CACpC;CACA,IAAI,iBAAiB,cAAc,IAAI,iBAAiB,kBAAkB;CAC1E,IAAI,UAAU,cAAc,IAAI,UAAU,mBAAmB;CAC7D,IAAI,iBAAiB,cAAc,IAAI,iBAAiB,kBAAkB;CAC1E,OAAO,KAAK,IAAI;AAClB;AAEA,eAAe,iBAAiB,MAAgB,IAA4B;CAC1E,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,GAAG;GAAa,mBAAmB,EAAE,MAAM,UAAU;EAAE;CACpE,CAAC;CACD,MAAM,CAAC,KAAK,GAAG,SAAS;CACxB,IAAI,CAAC,OAAO,MAAM,WAAW,GAAG;EAC9B,GAAG,IAAI,4CAA4C;EACnD,OAAO;CACT;CACA,MAAM,YAAY,IAAI,cAAc;CACpC,MAAM,SAAS,MAAM,YAAY,eAAe,GAAG,GAAG,OAAO;EAC3D,MAAMA,YAAU,OAAO,GAAG;EAC1B,KAAK,OAAO;EACZ,aAAa,OAAO,UAAU;EAC9B,cAAc,OAAO;EACrB,cAAc,CAAC,OAAO;EACtB,cAAc,kBAAkB,OAAO,gBAAgB;EACvD,SAAS,WAAW,OAAO,OAAO;EAClC,eAAe,OAAO,sBAAsB;EAC5C;CACF,CAAC;CAGD,MAAM,KAAK,OAAO,MAAM,OACrB,MAAM,EAAE,OAAO,SAAS,EAAE,OAAO,UAAU,WAAW,OAAO,MAAM,EAAE,IAAI,KAAK,MACjF;CAEA,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;EAC7C,OAAO,KAAK,IAAI;CAClB;CAEA,KAAK,MAAM,QAAQ,OAAO,OAAO;EAC/B,MAAM,MAAM,KAAK;EACjB,MAAM,SAAS,IAAI,OAAO,OAAO,IAAI,UAAU,UAAU,GAAG,IAAI;EAChE,MAAM,SAAS,IAAI,SAAS,IAAI,UAAU,WAAW,OAAO,MAAM,EAAE,IAAI,KAAK;EAC7E,GAAG,IAAI,GAAG,KAAK,KAAK,IAAI,OAAO,IAAI,SAAS,SAAS,OAAO,GAAG;CACjE;CACA,GAAG,IAAI,aAAa,OAAO,KAAK,OAAO,QAAQ,EAAE,KAAK,IAAI,KAAK,SAAS,GAAG;CAC3E,OAAO,KAAK,IAAI;AAClB;AAEA,MAAM,iBAAiB,IAAI,IAAkB;CAAC;CAAW;CAAY;CAAW;AAAK,CAAC;AAEtF,SAAS,UAAU,MAAgB,IAAmB;CACpD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS,EAAE,MAAM,EAAE,MAAM,SAAS,EAAE;CACtC,CAAC;CACD,MAAM,CAAC,QAAQ,QAAQ,QAAQ;CAC/B,IAAI,CAAC,UAAU,CAAC,UAAU,CAAC,MAAM;EAC/B,GAAG,IAAI,4EAA4E;EACnF,OAAO;CACT;CACA,IAAI,CAAC,eAAe,IAAI,MAAsB,GAAG;EAC/C,GAAG,IAAI,0BAA0B,OAAO,2CAA2C;EACnF,OAAO;CACT;CAEA,MAAM,QAAQ,mBAAmB,QADpB,aAAa,QAAQ,MAC0B,GAAG,MAAM,EAAE,MAAM,OAAO,KAAK,CAAC;CAC1F,GAAG,IAAI,YAAY,MAAM,mBAAmB,KAAK,GAAG;CACpD,OAAO;AACT;AAEA,eAAe,YAAY,MAAgB,IAA4B;CACrE,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,kBAAkB;EAClB,SAAS;GACP,SAAS,EAAE,MAAM,SAAS;GAC1B,OAAO,EAAE,MAAM,SAAS;GACxB,WAAW,EAAE,MAAM,SAAS;GAC5B,WAAW,EAAE,MAAM,SAAS;GAC5B,UAAU,EAAE,MAAM,SAAS;GAC3B,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,IAAI,CAAC,OAAO,WAAW,CAAC,OAAO,OAAO;EACpC,GAAG,IAAI,iEAAiE;EACxE,OAAO;CACT;CACA,MAAM,MAAM,aAAa,OAAO,SAAS,MAAM;CAC/C,MAAM,QAAQ,aAAa,OAAO,OAAO,MAAM;CAG/C,IAAI;CACJ,IAAI,OAAO,cAAc,KAAA,GACvB,IAAI;EACF,YAAY,KAAK,MAAM,OAAO,SAAS;CACzC,QAAQ;EACN,YAAY,KAAK,MAAM,aAAa,OAAO,WAAW,MAAM,CAAC;CAC/D;CAIF,IAAI;CACJ,IAAI,OAAO,aAAa,KAAA,GAAW;EACjC,iBAAiB,MAAM,aAAa,OAAO,UAAU,EAAE;EACvD,IAAI,mBAAmB,KAAA,GAAW,OAAO;CAC3C;CACA,MAAM,WAAW,yBAAyB,KAAK,OAAO;EACpD,eAAe,OAAO;EACtB,GAAI,iBAAiB,EAAE,eAAe,IAAI,CAAC;EAC3C,GAAI,cAAc,KAAA,IAAY;GAAE;GAAW,wBAAwB;EAAK,IAAI,CAAC;CAC/E,CAAC;CAED,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,GAAG;EAC/C,OAAO,SAAS,QAAQ,IAAI;CAC9B;CACA,GAAG,IAAI,UAAU,SAAS,MAAM,GAAG;CACnC,KAAK,MAAM,KAAK,SAAS,UACvB,GAAG,IAAI,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,UAAU,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,GAAG,GAAG;CAEjG,OAAO,SAAS,QAAQ,IAAI;AAC9B;;;;;;;AAQA,SAAS,mBAAmB,MAAgB,IAAmB;CAC7D,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,kBAAkB;EAClB,SAAS;GACP,SAAS,EAAE,MAAM,SAAS;GAC1B,QAAQ,EAAE,MAAM,SAAS;GACzB,MAAM,EAAE,MAAM,SAAS;GACvB,MAAM,EAAE,MAAM,SAAS;GACvB,OAAO;IAAE,MAAM;IAAU,UAAU;GAAK;GACxC,QAAQ;IAAE,MAAM;IAAU,UAAU;GAAK;GACzC,MAAM;IAAE,MAAM;IAAU,UAAU;GAAK;GACvC,aAAa;IAAE,MAAM;IAAU,UAAU;GAAK;GAC9C,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,IAAI,CAAC,OAAO,WAAW,CAAC,OAAO,UAAU,CAAC,OAAO,MAAM;EACrD,GAAG,IAAI,6EAA6E;EACpF,OAAO;CACT;CACA,MAAM,OAAO,KAAK,MAAM,aAAa,OAAO,SAAS,MAAM,CAAC;CAC5D,MAAM,OAAO,OAAO,SAAS,KAAA,IAAY,KAAK,MAAM,aAAa,OAAO,MAAM,MAAM,CAAC,IAAI,KAAA;CACzF,IAAI,kBAAkB,IAAI,GAAG;EAC3B,GAAG,IACD,0FACF;EACA,OAAO;CACT;CAEA,MAAM,QAA2C,CAAC;CAClD,KAAK,MAAM,MAAM,OAAO,SAAS,CAAC,GAAG;EACnC,MAAM,KAAK,GAAG,QAAQ,GAAG;EACzB,IAAI,KAAK,GAAG;EACZ,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE;EACxB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC;EACzB,MAAM,MAAM,MAAM;EAClB,MAAM,KAAK,QAAQ,KAAA,IAAY,IAAI,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;CAC/E;CAEA,MAAM,UAAkC,CAAC;CACzC,KAAK,MAAM,MAAM,OAAO,UAAU,CAAC,GAAG;EACpC,MAAM,IAAI,GAAG,QAAQ,GAAG;EACxB,IAAI,IAAI,GAAG;EACX,QAAQ,GAAG,MAAM,GAAG,CAAC,EAAE,KAAK,EAAE,YAAY,KAAK,GAAG,MAAM,IAAI,CAAC,EAAE,KAAK;CACtE;CAGA,MAAM,OAA0C,CAAC;CACjD,KAAK,MAAM,MAAM,OAAO,QAAQ,CAAC,GAAG;EAClC,MAAM,KAAK,GAAG,QAAQ,GAAG;EACzB,IAAI,KAAK,GAAG;EACZ,MAAM,IAAI,GAAG,MAAM,GAAG,EAAE;EACxB,MAAM,IAAI,GAAG,MAAM,KAAK,CAAC;EACzB,MAAM,MAAM,KAAK;EACjB,KAAK,KAAK,QAAQ,KAAA,IAAY,IAAI,MAAM,QAAQ,GAAG,IAAI,CAAC,GAAG,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC;CAC9E;CAEA,MAAM,iBAAiB,OAAO,gBAAgB,CAAC;CAE/C,MAAM,WAAW,uBACf,MACA;EACE,QAAQ,OAAO;EACf,MAAM,OAAO;EACb;EACA,GAAI,OAAO,KAAK,KAAK,EAAE,SAAS,IAAI,EAAE,MAAM,IAAI,CAAC;EACjD,GAAI,OAAO,KAAK,OAAO,EAAE,SAAS,IAAI,EAAE,QAAQ,IAAI,CAAC;EACrD,GAAI,OAAO,KAAK,IAAI,EAAE,SAAS,IAAI,EAAE,KAAK,IAAI,CAAC;EAC/C,GAAI,eAAe,SAAS,IAAI,EAAE,eAAe,IAAI,CAAC;CACxD,GACA;EACE,SAAS,QAAQ,OAAO,OAAO;EAC/B,2BAA2B;EAC3B,qBAAqB;CACvB,CACF;CAEA,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,UAAU,MAAM,CAAC,EAAE,GAAG;EAC/C,OAAO,SAAS,QAAQ,IAAI;CAC9B;CACA,GAAG,IAAI,UAAU,SAAS,MAAM,GAAG;CACnC,KAAK,MAAM,KAAK,SAAS,UACvB,GAAG,IAAI,KAAK,EAAE,SAAS,YAAY,EAAE,GAAG,EAAE,KAAK,IAAI,EAAE,UAAU,EAAE,OAAO,KAAK,EAAE,KAAK,KAAK,GAAG,GAAG;CAEjG,OAAO,SAAS,QAAQ,IAAI;AAC9B;;;;;;;;;AAUA,SAAS,mBAAmB,MAAgB,IAAmB;CAC7D,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,SAAS,EAAE,MAAM,SAAS;GAC1B,SAAS,EAAE,MAAM,SAAS;GAC1B,oBAAoB,EAAE,MAAM,SAAS;GACrC,QAAQ;IAAE,MAAM;IAAU,UAAU;GAAK;GACzC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,CAAC,WAAW;CAClB,IAAI,CAAC,WAAY,CAAC,OAAO,WAAW,CAAC,OAAO,SAAU;EACpD,GAAG,IACD,oGACF;EACA,OAAO;CACT;CAaA,MAAM,UAAU,wBAZD,aAAa,OAYiB,GAAG;EAV9C,GAAI,OAAO,UAAU,EAAE,SAAS,KAAK,MAAM,aAAa,OAAO,SAAS,MAAM,CAAC,EAAE,IAAI,CAAC;EACtF,GAAI,OAAO,UACP,EACE,SAAS;GACP,cAAc,OAAO,uBAAuB;GAC5C,KAAK,aAAa,OAAO,SAAS,MAAM;EAC1C,EACF,IACA,CAAC;CAEgD,GAAG,EACxD,gBAAgB,OAAO,OACzB,CAAC;CAED,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GAAG;EAC9C,OAAO,QAAQ,QAAQ,IAAI;CAC7B;CACA,GAAG,IACD,YAAY,QAAQ,QAAQ,UAAU,YAAY,IAAI,QAAQ,iBAAiB,YACjF;CACA,KAAK,MAAM,CAAC,MAAM,UAAU,OAAO,QAAQ,QAAQ,cAAc,GAC/D,GAAG,IAAI,KAAK,MAAM,IAAI,KAAK,GAAG;CAEhC,IAAI,QAAQ,cAAc;EACxB,MAAM,IAAI,QAAQ;EAClB,GAAG,IAAI,oBAAoB,EAAE,OAAO,GAAG,EAAE,KAAK,KAAK,EAAE,KAAK,IAAI,EAAE,QAAQ,GAAG;CAC7E;CACA,GAAG,IAAI,gBAAgB,QAAQ,oBAAoB,KAAK,IAAI,KAAK,SAAS,GAAG;CAC7E,IAAI,QAAQ,sBAAsB,SAAS,GACzC,GAAG,IAAI,kBAAkB,QAAQ,sBAAsB,KAAK,IAAI,EAAE,GAAG;CAEvE,OAAO,QAAQ,QAAQ,IAAI;AAC7B;;;;AC5nBA,MAAM,iBAAiB;CACrB,cAAc;EAAE,MAAM;EAAU,UAAU;CAAK;CAC/C,iBAAiB,EAAE,MAAM,UAAU;CACnC,cAAc,EAAE,MAAM,UAAU;CAChC,QAAQ,EAAE,MAAM,UAAU;CAC1B,QAAQ,EAAE,MAAM,SAAS;CACzB,MAAM,EAAE,MAAM,UAAU;AAC1B;AAUA,SAAS,UAAU,QAAoC;CACrD,OAAO;EACL,WAAW,OAAO,iBAAiB,CAAC;EACpC,cAAc,OAAO,oBAAoB;EACzC,WAAW,OAAO,iBAAiB;EACnC,QAAQ,OAAO,UAAU;EACzB,QAAQ,cAAc,OAAO,MAAM;CACrC;AACF;;;;AAKA,SAAS,UAAU,OAAqB,UAA0C;CAChF,OAAO,eAAe,MAAM,QAAQ;EAClC,UAAU,CAAC,MAAM;EACjB,aAAa;EACb,WAAW,MAAM;CACnB,CAAC;AACH;;;;;AAYA,eAAe,YACb,KACA,OACA,IACA,IACiB;CACjB,IAAI;CACJ,IAAI;EACF,OAAO,IAAI,IAAI,GAAG,EAAE;CACtB,QAAQ;EACN,GAAG,IAAI,gBAAgB,IAAI,GAAG;EAC9B,OAAO;CACT;CAEA,MAAM,OAAO,IAAI,YAAY,EAAE,cAAc,CAAC,MAAM,GAAG,MAAM,SAAS,EAAE,CAAC;CACzE,MAAM,QAAQ,MAAM,gBAAgB,EAAE,cAAc,MAAM,aAAa,CAAC;CACxE,MAAM,QAAQ,IAAIG,gBAAc,YAAY,KAAK,OAAO,GAAG,wBAAwB,CAAC,CAAC;CACrF,MAAM,UAAU,IAAI,eAAe;EACjC;EACA,QAAQ,UAAU,OAAO,MAAM,GAAG;CACpC,CAAC;CACD,IAAI;EAEF,MAAM,OAAO,OAAM,MADG,QAAQ,cAAc,KAAK,GACtB,QAAQ;EACnC,MAAM,SAAS,IAAI,WAAW,MAAM;GAAE,OAAO;GAAO;GAAO;EAAK,CAAC;EACjE,MAAM,OAAO,SAAS,GAAG;EACzB,OAAO,MAAM,GAAG;GAAE;GAAQ;GAAO;EAAK,CAAC;CACzC,SAAS,KAAK;EACZ,GAAG,IAAI,GAAI,IAAc,QAAQ,GAAG;EACpC,OAAO;CACT,UAAU;EACR,MAAM,QAAQ,SAAS;EACvB,MAAM,MAAM,MAAM;CACpB;AACF;AAEA,eAAsB,WAAW,MAAgB,IAA4B;CAC3E,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,IAAI;EACF,QAAQ,KAAR;GACE,KAAK,YACH,OAAO,MAAM,YAAY,MAAM,EAAE;GACnC,KAAK,SACH,OAAO,MAAMC,WAAS,MAAM,EAAE;GAChC,KAAK,cACH,OAAO,MAAM,cAAc,MAAM,EAAE;GACrC,KAAK,OACH,OAAO,MAAMC,SAAO,MAAM,EAAE;GAC9B;IACE,GAAG,IAAI,+BAA+B,OAAO,SAAS,GAAG;IACzD,OAAO;EACX;CACF,SAAS,KAAK;EAGZ,GAAG,IAAI,GAAI,IAAc,QAAQ,GAAG;EACpC,OAAO;CACT;AACF;;AAGA,SAASC,YAAU,KAAoD;CACrE,MAAM,OAAgC,CAAC;CACvC,KAAK,MAAM,QAAQ,OAAO,CAAC,GAAG;EAC5B,MAAM,KAAK,KAAK,QAAQ,GAAG;EAC3B,IAAI,OAAO,IAAI,KAAK,QAAQ;OACvB,KAAK,KAAK,MAAM,GAAG,EAAE,KAAK,KAAK,MAAM,KAAK,CAAC;CAClD;CACA,OAAO;AACT;;;;;;;;;;AAWA,eAAeD,SAAO,MAAgB,IAA4B;CAChE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,GAAG;GACH,QAAQ,EAAE,MAAM,UAAU;GAC1B,KAAK;IAAE,MAAM;IAAU,UAAU;GAAK;EACxC;CACF,CAAC;CACD,MAAM,WAAW,YAAY;CAC7B,IAAI,CAAC,UAAU;EACb,GAAG,IAAI,gCAAgC;EACvC,OAAO;CACT;CAEA,IAAI;CACJ,IAAI;EACF,OAAO,SAAS,QAAQ;CAC1B,SAAS,KAAK;EACZ,GAAG,IAAI,GAAI,IAAc,QAAQ,GAAG;EACpC,OAAO;CACT;CAIA,MAAM,MAAM,GAAG,OAAO,CAAC;CACvB,MAAM,WAAW,IAAIE,WAAS;CAC9B,MAAM,0BAAU,IAAI,IAAoB;CACxC,KAAK,MAAM,CAAC,KAAK,QAAQ,OAAO,QAAQ,GAAG,GAAG;EAC5C,MAAM,IAAI,kCAAkC,KAAK,GAAG;EACpD,IAAI,IAAI,MAAM,KAAK;GACjB,SAAS,SAAS,EAAE,IAAI,GAAG;GAC3B,QAAQ,IAAI,EAAE,IAAI,GAAG;EACvB;CACF;CAEA,MAAM,QAAQ,UAAU,MAAM;CAC9B,MAAM,OAAO,IAAI,YAAY;EAC3B,aAAa,OAAO,UAAU;EAC9B,cAAc,MAAM;CACtB,CAAC;CACD,MAAM,QAAQ,MAAM,gBAAgB,EAAE,cAAc,MAAM,aAAa,CAAC;CACxE,MAAM,QAAQ,IAAIJ,gBAAc,YAAY,KAAK,OAAO,GAAG,yBAAyB,CAAC,CAAC;CACtF,MAAM,UAAU,IAAI,eAAe;EACjC;EACA,QAAQ,UAAU,OAAO,MAAM,GAAG;CACpC,CAAC;CACD,IAAI;EASF,MAAM,SAAS,MAAM,QAAQ,IANV,WAAW,OADX,MADG,QAAQ,cAAc,KAAK,GACtB,QAAQ,GACC;GAClC,OAAO;GACP;GACA;GACA,SAAS,MAAM,SAAS,OAAO,CAAC;EAClC,CACkC,GAAG,MAAM;GACzC,MAAMG,YAAU,OAAO,GAAG;GAC1B,gBAAgB,SAAS,QAAQ,IAAI,IAAI;EAC3C,CAAC;EACD,IAAI,OAAO,MACT,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;OAE7C,gBAAgB,QAAQ,EAAE;EAE5B,OAAO,OAAO,SAAS,IAAI;CAC7B,SAAS,KAAK;EACZ,GAAG,IAAI,GAAI,IAAc,QAAQ,GAAG;EACpC,OAAO;CACT,UAAU;EACR,MAAM,QAAQ,SAAS;EACvB,MAAM,MAAM,MAAM;CACpB;AACF;AAEA,SAAS,gBAAgB,QAAoB,IAAiB;CAC5D,GAAG,IAAI,SAAS,OAAO,KAAK,GAAG;CAC/B,KAAK,MAAM,QAAQ,OAAO,OACxB,IAAI,KAAK,OACP,GAAG,IAAI,UAAU,KAAK,OAAO,KAAK,KAAK,MAAM,GAAG;MAC3C,IAAI,KAAK,YAAY;EAC1B,MAAM,SAAS,KAAK,WAAW,QAAQ,MAAM,EAAE,IAAI,EAAE;EACrD,MAAM,QAAQ,KAAK,WAAW;EAC9B,GAAG,IAAI,KAAK,WAAW,QAAQ,SAAS,OAAO,WAAW,OAAO,GAAG,MAAM,WAAW;CACvF,OACE,GAAG,IAAI,UAAU,KAAK,SAAS,KAAK,SAAS,eAAe,GAAG,GAAG;CAGtE,GAAG,IAAI,GAAG,OAAO,SAAS,SAAS,OAAO,GAAG;AAC/C;AAEA,eAAe,YAAY,MAAgB,IAA4B;CACrE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;CACX,CAAC;CACD,MAAM,MAAM,YAAY;CACxB,IAAI,CAAC,KAAK;EACR,GAAG,IAAI,gCAAgC;EACvC,OAAO;CACT;CACA,OAAO,YAAY,KAAK,UAAU,MAAM,GAAG,IAAI,OAAO,EAAE,aAAa;EACnE,MAAM,OAAO,MAAM,OAAO,SAAS;EACnC,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,MAAM,MAAM,CAAC,EAAE,GAAG;GAC3C,OAAO;EACT;EACA,GAAG,IAAI,GAAG,KAAK,SAAS,GAAG;EAC3B,IAAI,KAAK,WAAW,GAAG,IAAI,iEAAiE;EAC5F,OAAO;CACT,CAAC;AACH;AAEA,eAAeF,WAAS,MAAgB,IAA4B;CAClE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;CACX,CAAC;CACD,MAAM,MAAM,YAAY;CACxB,IAAI,CAAC,KAAK;EACR,GAAG,IAAI,6BAA6B;EACpC,OAAO;CACT;CACA,OAAO,YAAY,KAAK,UAAU,MAAM,GAAG,IAAI,OAAO,EAAE,OAAO,WAAW;EACxE,MAAM,MAAM,MAAM,UAAU,MAAM;GAAE,OAAO;GAAO;EAAM,CAAC;EACzD,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,GAAG;GAC1C,OAAO,IAAI,QAAQ,mBAAmB,IAAI,IAAI;EAChD;EACA,MAAM,IAAI,IAAI;EACd,GAAG,IAAI,eAAe,EAAE,eAAe,GAAG;EAC1C,KAAK,MAAM,KAAK,EAAE,KAChB,GAAG,IAAI,MAAM,EAAE,UAAU,IAAI,IAAI,EAAE,GAAG,IAAI,EAAE,UAAU,aAAa,EAAE,KAAK,GAAG;EAE/E,MAAM,OAAO,MAAM,IAAI,IAAI,aAAa,GAAG;EAC3C,IAAI,MAAM,GAAG,IAAI,gBAAgB,KAAK,GAAG;EAEzC,OAAO,EAAE,mBAAmB,IAAI,IAAI;CACtC,CAAC;AACH;AAEA,eAAe,cAAc,MAAgB,IAA4B;CACvE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,GAAG;GAAgB,KAAK,EAAE,MAAM,SAAS;GAAG,aAAa,EAAE,MAAM,UAAU;EAAE;CAC1F,CAAC;CACD,MAAM,MAAM,YAAY;CACxB,IAAI,CAAC,KAAK;EACR,GAAG,IAAI,kCAAkC;EACzC,OAAO;CACT;CACA,MAAM,MAAM,OAAO,OAAO;CAC1B,OAAO,YAAY,KAAK,UAAU,MAAM,GAAG,IAAI,OAAO,EAAE,QAAQ,YAAY;EAC1E,MAAM,OAAO,MAAM,OAAO,WAAW,EAAE,UAAU,OAAO,gBAAgB,MAAM,CAAC;EAC/E,MAAM,QAAQ,KAAK,SAAS,MAAM,IAAI,KAAK,MAAM,GAAG,OAAO,KAAA;EAC3D,IAAI,CAAC,OAAO;GACV,GAAG,IAAI,6BAA6B;GACpC,OAAO;EACT;EACA,cAAc,KAAK,KAAK;EACxB,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU;IAAE,GAAG;IAAM,SAAS;GAAI,GAAG,MAAM,CAAC,EAAE,GAAG;GAChE,OAAO;EACT;EACA,GAAG,IAAI,SAAS,KAAK,SAAS,YAAY,IAAI,GAAG;EACjD,OAAO;CACT,CAAC;AACH;;;;;;;;;;;;;;ACvTA,eAAsB,YACpB,MACA,IACA,OAAgC,CAAC,GAChB;CACjB,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,qBACH,OAAO,mBAAmB,MAAM,EAAE;EACpC,KAAK,cACH,OAAO,aAAa,MAAM,IAAI,IAAI;EACpC;GACE,GAAG,IAAI,gCAAgC,OAAO,SAAS,GAAG;GAC1D,OAAO;CACX;AACF;AAEA,SAAS,YAAY,IAAW,QAAkC;CAChE,MAAM,IAAI,OAAO;CACjB,GAAG,IACD,UAAU,OAAO,MAAM,OAAO,IAAI,EAAE,qBAAqB,8BAC5C,EAAE,QAAQ,cAAc,EAAE,UAAU,mBAAmB,EAAE,cAAc,GACtF;CACA,IAAI,OAAO,UAAU,WAAW,GAAG;EACjC,GAAG,IAAI,+BAA+B;EACtC;CACF;CACA,GAAG,IAAI,wBAAwB,OAAO,UAAU,OAAO,KAAK;CAC5D,KAAK,MAAM,KAAK,OAAO,WACrB,GAAG,IAAI,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,GAAG;AAEpC;AAEA,SAAS,mBAAmB,MAAgB,IAAmB;CAC7D,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,kBAAkB;EAClB,SAAS;GACP,MAAM,EAAE,MAAM,SAAS;GACvB,UAAU,EAAE,MAAM,SAAS;GAC3B,mBAAmB,EAAE,MAAM,SAAS;GACpC,gBAAgB,EAAE,MAAM,SAAS;GACjC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,IAAI,CAAC,OAAO,QAAQ,CAAC,OAAO,UAAU;EACpC,GAAG,IAAI,wEAAwE;EAC/E,OAAO;CACT;CACA,MAAM,SAAS,OAAO,sBAAsB;CAC5C,IAAI,WAAW,cAAc,WAAW,cAAc;EACpD,GAAG,IAAI,4BAA4B,OAAO,kCAAkC;EAC5E,OAAO;CACT;CACA,MAAM,OAAO,aAAa,OAAO,MAAM,MAAM;CAC7C,MAAM,SAAS,KAAK,MAAM,aAAa,OAAO,UAAU,MAAM,CAAC;CAG/D,MAAM,SAAS,gBAAgB,MAD7B,WAAW,eAAe,qBAAqB,MAA0B,IAAI,QAChC,EAAE,aAAa,OAAO,gBAAgB,CAAC;CAEtF,IAAI,OAAO,MACT,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;MAE7C,YAAY,IAAI,MAAM;CAGxB,OAAO,OAAO,UAAU,WAAW,IAAI,IAAI;AAC7C;AAEA,eAAe,aACb,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,gBAAgB;IAAE,MAAM;IAAU,UAAU;GAAK;GACjD,MAAM,EAAE,MAAM,SAAS;GACvB,QAAQ,EAAE,MAAM,UAAU;GAC1B,SAAS;IAAE,MAAM;IAAU,UAAU;GAAK;GAC1C,cAAc,EAAE,MAAM,SAAS;GAC/B,aAAa,EAAE,MAAM,UAAU;GAC/B,cAAc,EAAE,MAAM,SAAS;GAC/B,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,cAAc,YAAY;CAChC,IAAI,CAAC,aAAa;EAChB,GAAG,IAAI,8CAA8C;EACrD,OAAO;CACT;CACA,MAAM,YAAY,OAAO,iBAAiB;CAC1C,IAAI,OAAO,UAAU,cAAc,gBAAgB,cAAc,SAAS;EACxE,GAAG,IAAI,uBAAuB,UAAU,+BAA+B;EACvE,OAAO;CACT;CACA,MAAM,aAAa,OAAO;CAC1B,MAAM,YAAY,eAAe,KAAA,IAAY,OAAO,UAAU,IAAI,KAAA;CAElE,IAAI;EACF,MAAM,SAAS;GACb;GAEA,cAAc,CAAC,QAAQ,WAAW,CAAC;GACnC,UAAU,OAAO,gBAAgB;GACjC,WAAW,cAAc,KAAA,KAAa,OAAO,SAAS,SAAS,IAAI,YAAY,KAAA;EACjF;EACA,MAAM,eAAe,OAAO,mBAAmB,CAAC;EAChD,MAAM,OAAO,OAAO,SAAS,KAAA,IAAY,aAAa,OAAO,MAAM,MAAM,IAAI,KAAA;EAE7E,MAAM,SAAS,OAAO,SAClB,MAAM,gBACJ,QACA;GACE;GACA;GACA,gBAAgB,OAAO,WAAW,CAAC;GACxB;EACb,GACA,EAAE,QAAQ,KAAK,OAAO,CACxB,IACA,MAAM,UAAU,QAAQ;GAAE;GAAc;EAAK,GAAG,EAAE,QAAQ,KAAK,OAAO,CAAC;EAE3E,MAAM,KAAK,OAAO,SAAU,SAAgC,KAAA;EAC5D,IAAI,OAAO,MACT,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;OACxC,IAAI,CAAC,OAAO,KACjB,GAAG,IAAI,qCAAqC;OACvC;GACL,GAAG,IACD,OAAO,OAAO,SAAS,WAAW,SAAS,SAAS,OAAO,SAAS,WAClE,IAAI,eAAe,iBAAiB,OAAO,SAAS,WAAW,SAChE,YAAY,OAAO,YAAY,KAAK,IAAI,EAAE,GAC7C;GACA,IAAI,IAAI,WACN,GAAG,IAAI,0CAA0C,GAAG,UAAU,KAAK,IAAI,EAAE,GAAG;GAC9E,IAAI,OAAO,QAAQ,YAAY,IAAI,OAAO,MAAM;EAClD;EAMA,OAHE,OAAO,UACP,CAAC,IAAI,iBACJ,OAAO,SAAS,OAAO,OAAO,UAAU,WAAW,IAAI,QAC9C,IAAI;CAClB,SAAS,GAAG;EACV,IAAI,aAAa,mBAAmB;GAClC,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;;;;AClJA,MAAM,mBAAoD;CACxD,KAAK;CACL,MAAM;CACN,UAAU;AACZ;;;;;;;;;;;AAYA,eAAsB,QACpB,MACA,IACA,OAAiF,CAAC,GACjE;CACjB,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,SACH,OAAO,SAAS,MAAM,IAAI,IAAI;EAChC,KAAK,iBACH,OAAO,gBAAgB,MAAM,IAAI,IAAI;EACvC,KAAK,aACH,OAAO,aAAa,MAAM,IAAI,IAAI;EACpC;GACE,GAAG,IAAI,4BAA4B,OAAO,SAAS,GAAG;GACtD,OAAO;CACX;AACF;;AAGA,MAAM,mBAAmB;CACvB,WAAW,EAAE,MAAM,SAAS;CAC5B,UAAU,EAAE,MAAM,SAAS;CAC3B,UAAU,EAAE,MAAM,SAAS;CAC3B,iBAAiB,EAAE,MAAM,SAAS;CAClC,qBAAqB,EAAE,MAAM,SAAS;CACtC,iBAAiB,EAAE,MAAM,UAAU;CACnC,MAAM,EAAE,MAAM,UAAU;AAC1B;AASA,SAAgB,eAAe,QAA6C;CAC1E,OAAO;EACL,UAAW,OAAO,YAAuB;EACzC,cAAe,OAAO,oBAA+B;EACrD,kBAAmB,OAAO,wBAAmC;EAC7D,cAAe,OAAO,oBAAgC;CACxD;AACF;AAEA,SAAS,cAAc,QAAiC,IAAgC;CACtF,MAAM,IAAK,OAAO,aAAwB;CAC1C,IAAI,MAAM,SAAS,MAAM,UAAU,MAAM,YAAY;EACnD,GAAG,IAAI,sBAAsB,EAAE,gCAAgC;EAC/D,OAAO;CACT;CACA,OAAO;AACT;;AAGA,SAAS,aAAa,UAAkB,aAA6B;CACnE,OAAO,GAAG,SAAS,QAAQ,QAAQ,EAAE,EAAE,GAAG,YAAY,QAAQ,KAAK,KAAK;AAC1E;;AAGA,SAAgB,YAAY,GAAiC;CAC3D,OAAO,OAAO,aAAa,cAAc;EACvC,IAAI,cAAc,OAAO;GACvB,MAAM,MAAM,aAAa,EAAE,UAAU,WAAW;GAChD,MAAM,cAAc,IAAI,IAAI,GAAG,EAAE,UAAU,KAAA,GAAW,EAAE,cAAc,EAAE,aAAa,CAAC;GACtF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;GACxE,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,MAAM,qBAAqB,IAAI,OAAO,OAAO,aAAa;GACjF,OAAQ,MAAM,IAAI,KAAK;EACzB;EACA,IAAI,cAAc,QAAQ;GAExB,MAAM,MAAM,GADC,EAAE,aAAa,QAAQ,QAAQ,EAC1B,EAAE,GAAG,mBAAmB,kBAAkB,WAAW,CAAC,EAAE;GAC1E,MAAM,cAAc,IAAI,IAAI,GAAG,EAAE,UAAU,KAAA,GAAW,EAAE,cAAc,EAAE,aAAa,CAAC;GACtF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;GACxE,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,MAAM,iBAAiB,IAAI,OAAO,OAAO,aAAa;GAC7E,OAAO,oBAAqB,MAAM,IAAI,KAAK,CAAc;EAC3D;EAEA,MAAM,MAAM,GADC,EAAE,iBAAiB,QAAQ,QAAQ,EAC9B,EAAE,YAAY,mBAAmB,WAAW,EAAE;EAChE,MAAM,cAAc,IAAI,IAAI,GAAG,EAAE,UAAU,KAAA,GAAW,EAAE,cAAc,EAAE,aAAa,CAAC;EACtF,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;EACxE,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,MAAM,qBAAqB,IAAI,OAAO,OAAO,aAAa;EACjF,OAAO,oBAAoB,aAAc,MAAM,IAAI,KAAK,CAAuB;CACjF;AACF;;AAGA,eAAe,gBAAgB,KAAa,cAAyC;CACnF,MAAM,cAAc,IAAI,IAAI,GAAG,EAAE,UAAU,KAAA,GAAW,EAAE,aAAa,CAAC;CACtE,MAAM,MAAM,MAAM,MAAM,KAAK,EAAE,SAAS,EAAE,QAAQ,mBAAmB,EAAE,CAAC;CACxE,IAAI,CAAC,IAAI,IAAI,MAAM,IAAI,MAAM,2BAA2B,IAAI,OAAO,OAAO,KAAK;CAC/E,OAAO,IAAI,KAAK;AAClB;;;;;;;AAQA,SAAS,qBAAqB,GAAiC;CAC7D,MAAM,iBAAiB,YAAY,CAAC;CACpC,MAAM,aAAa,OACjB,aACA,cACgC;EAChC,IAAI,cAAc,OAAO,OAAO,WAAW,MAAM,eAAe,aAAa,KAAK,CAAC;EACnF,IAAI,cAAc,QAGhB,OAAO,YAAa,MAAM,gBAAgB,GAF7B,EAAE,aAAa,QAAQ,QAAQ,EAC1B,EAAE,GAAG,mBAAmB,kBAAkB,WAAW,CAAC,EAAE,QAC3B,EAAE,YAAY,CAAc;EAE7E,IAAI,cAAc,YAGhB,OAAO,WAAY,MAAM,gBAAgB,GAF5B,EAAE,iBAAiB,QAAQ,QAAQ,EAC9B,EAAE,QAAQ,mBAAmB,WAAW,EAAE,QACd,EAAE,YAAY,CAAqB;EAEnF,MAAM,IAAI,MAAM,0DAA0D,UAAU,GAAG;CACzF;CACA,OAAO,OAAO,aAAa,cAAc;EACvC,MAAM,KAAK,gBAAgB,MAAM,WAAW,aAAa,SAAS,CAAC;EACnE,IAAI,CAAC,IAAI,MAAM,IAAI,MAAM,8CAA8C,YAAY,EAAE;EACrF,KAAK,MAAM,QAAQ,qBAAqB;GACtC,MAAM,MAAM,qCAAqC,GAAG,MAAM,GAAG,GAAG,KAAK,QAAQ;GAC7E,MAAM,cAAc,IAAI,IAAI,GAAG,EAAE,UAAU,KAAA,GAAW,EAAE,cAAc,EAAE,aAAa,CAAC;GACtF,MAAM,MAAM,MAAM,MAAM,GAAG;GAC3B,IAAI,IAAI,IAAI,OAAO;IAAE,MAAM,MAAM,IAAI,KAAK;IAAG,QAAQ;GAAI;EAC3D;EACA,MAAM,IAAI,MAAM,oCAAoC,GAAG,MAAM,GAAG,GAAG,MAAM;CAC3E;AACF;;AAGA,SAAS,eACP,QACA,WACuE;CACvE,IAAI,WAAW,KAAA,GAAW,OAAO;EAAE,YAAY,CAAC;EAAG,QAAQ;CAAM;CACjE,MAAM,WAAW,gBAAgB,QAAQ,SAAS;CAClD,OAAO;EAAE,YAAY,SAAS;EAAY,cAAc,SAAS;EAAc,QAAQ;CAAK;AAC9F;;AAGA,eAAe,SACb,SACA,aACA,WACA,gBACA,YACA,cACA,iBAC0B;CAC1B,MAAM,UACJ,mBACA,uBAAuB,SAAS,aAAa,EAAE,WAAW,iBAAiB,WAAW,CAAC,EAAE;CAC3F,IAAI,YAAY,QAAQ,YAAY,KAAA,GAClC,MAAM,IAAI,MAAM,6CAA6C,YAAY,OAAO,SAAS;CAE3F,MAAM,YAAY,MAAM,eAAe,aAAa,SAAS;CAC7D,OAAO,gBAAgB;EACrB,aAAa,UAAU,aAAa,SAAS;EAC7C;EACA,kBAAkB;EAClB;EACA;EACA;EACA,YAAY,cAAc,SAAS;CACrC,CAAC;AACH;;;;;;;AAQA,eAAsB,mBAAmB,OAWtC;CACD,MAAM,EAAE,YAAY,cAAc,WAAW,eAAe,MAAM,QAAQ,MAAM,SAAS;CACzF,MAAM,QAAQ,MAAM,SAAS,gBAAgB,MAAM,SAAS,MAAM,WAAW,IAAI;CACjF,MAAM,SAA4B,CAAC;CACnC,MAAM,SAA+C,CAAC;CACtD,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,OAAO,KACL,MAAM,SACJ,MAAM,SACN,MACA,MAAM,WACN,MAAM,gBACN,YACA,YACF,CACF;CACF,SAAS,GAAG;EACV,OAAO,KAAK;GAAE,SAAS;GAAM,OAAQ,EAAY;EAAQ,CAAC;CAC5D;CAEF,OAAO;EAAE;EAAQ,mBAAmB;EAAQ;CAAO;AACrD;;AAGA,SAAS,aAAa,OAAiC;CACrD,OAAO,MAAM,kBAAkB,UAAU,MAAM,WAAW;AAC5D;AAEA,SAAS,WACP,IACA,OACA,QACA,cACM;CACN,GAAG,IAAI,GAAG,MAAM,QAAQ,IAAI,MAAM,iBAAiB,KAAK,MAAM,UAAU,IAAI;CAC5E,GAAG,IACD,MAAM,WAAW,eACb,eAAe,MAAM,WAAW,MAAM,KAAK,MAAM,WAAW,QAAQ,MACpE,kBACN;CACA,IAAI,MAAM,gBAAgB,SAAS,GAAG;EACpC,GAAG,IAAI,oBAAoB,MAAM,gBAAgB,OAAO,KAAK;EAC7D,KAAK,MAAM,KAAK,MAAM,iBAAiB;GACrC,MAAM,QAAQ,EAAE,QAAQ,SAAS,eAAe,EAAE,QAAQ,KAAK,IAAI,MAAM;GACzE,GAAG,IAAI,KAAK,EAAE,GAAG,IAAI,EAAE,SAAS,KAAK,EAAE,WAAW,KAAK,MAAM,GAAG;EAClE;CACF,OACE,GAAG,IAAI,yBAAyB;CAElC,MAAM,IAAI,MAAM;CAChB,GAAG,IACD,wBAAwB,EAAE,UAAU,WAAW,EAAE,UAAU,IAAI,eAAe,EAAE,mBAAmB,IAAI,aAAa,EAAE,aAAa,QAAQ,KAAK,GAClJ;CACA,IAAI,MAAM,mBAAmB,GAAG,IAAI,uBAAuB,MAAM,kBAAkB,GAAG;CACtF,IAAI,MAAM,oBAAoB,GAAG,IAAI,yBAAyB,MAAM,mBAAmB,GAAG;CAC1F,GAAG,IACD,SACI,uBAAuB,eAAe,KAAK,aAAa,KAAK,GAAG,MAChE,uFACN;AACF;AAEA,eAAe,SACb,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,GAAG;GAAkB,SAAS,EAAE,MAAM,SAAS;EAAE;CAC9D,CAAC;CACD,MAAM,CAAC,SAAS,eAAe;CAC/B,IAAI,CAAC,WAAW,CAAC,aAAa;EAC5B,GAAG,IAAI,wCAAwC;EAC/C,OAAO;CACT;CACA,MAAM,YAAY,cAAc,QAAQ,EAAE;CAC1C,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,IAAI,eAAe,MAAM;CAC/B,MAAM,iBAAiB,KAAK,kBAAkB,YAAY,CAAC;CAC3D,MAAM,EAAE,YAAY,cAAc,WAAW,eAAe,OAAO,WAAW,SAAS;CAEvF,IAAI;EACF,MAAM,QAAQ,MAAM,SAClB,SACA,aACA,WACA,gBACA,YACA,cACA,OAAO,OACT;EACA,IAAI,OAAO,MACT,GAAG,IAAI,GAAG,KAAK,UAAU;GAAE,GAAG;GAAO,mBAAmB;EAAO,GAAG,MAAM,CAAC,EAAE,GAAG;OAE9E,WAAW,IAAI,OAAO,QAAQ,YAAY;EAE5C,OAAO,aAAa,KAAK,IAAI,IAAI;CACnC,SAAS,GAAG;EACV,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;AAEA,eAAe,gBACb,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,GAAG;GAAkB,YAAY,EAAE,MAAM,UAAU;EAAE;CAClE,CAAC;CACD,MAAM,UAAU,YAAY;CAC5B,IAAI,CAAC,SAAS;EACZ,GAAG,IAAI,sCAAsC;EAC7C,OAAO;CACT;CACA,MAAM,YAAY,cAAc,QAAQ,EAAE;CAC1C,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,IAAI,eAAe,MAAM;CAC/B,MAAM,iBAAiB,KAAK,kBAAkB,YAAY,CAAC;CAC3D,MAAM,EAAE,YAAY,cAAc,WAAW,eAAe,OAAO,WAAW,SAAS;CACvF,MAAM,QAAQ,gBAAgB,SAAS,WAAW,CAAC,OAAO,WAAW;CAErE,MAAM,eASA,CAAC;CACP,MAAM,SAA+C,CAAC;CACtD,KAAK,MAAM,QAAQ,OACjB,IAAI;EACF,MAAM,QAAQ,MAAM,SAClB,SACA,MACA,WACA,gBACA,YACA,YACF;EACA,aAAa,KAAK;GAChB,SAAS;GACT,kBAAkB,MAAM;GACxB,eAAe,MAAM;GACrB,YAAY,MAAM,WAAW;GAC7B,YAAY,MAAM,UAAU;GAC5B,mBAAmB,MAAM;GACzB,oBAAoB,MAAM;GAC1B,oBAAoB,MAAM,gBAAgB;EAC5C,CAAC;CACH,SAAS,KAAK;EACZ,OAAO,KAAK;GAAE,SAAS;GAAM,OAAO,eAAe,QAAQ,IAAI,UAAU,OAAO,GAAG;EAAE,CAAC;CACxF;CAGF,MAAM,aAAqC,CAAC;CAC5C,KAAK,MAAM,KAAK,cACd,IAAI,EAAE,kBAAkB,QACtB,WAAW,EAAE,kBAAkB,WAAW,EAAE,kBAAkB,KAAK;CAEvE,MAAM,UAAU;EACd,OAAO,aAAa;EACpB,cAAc,aAAa,QAAQ,MAAM,EAAE,kBAAkB,UAAU,EAAE,UAAU,EAAE;EACrF,YAAY,aAAa,QAAQ,MAAM,EAAE,UAAU,EAAE;EACrD,UAAU,aAAa,QAAQ,MAAM,EAAE,UAAU,EAAE;EACnD;EACA,mBAAmB;EACnB;CACF;CAEA,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU;GAAE;GAAS;GAAW;GAAS;GAAc;EAAO,GAAG,MAAM,CAAC,EAAE,GAAG;EAC5F,OAAO,QAAQ,eAAe,IAAI,IAAI;CACxC;CACA,GAAG,IACD,GAAG,QAAQ,KAAK,UAAU,KAAK,QAAQ,MAAM,kBAAkB,QAAQ,aAAa,eAAe,QAAQ,WAAW,aAAa,QAAQ,SAAS,GACtJ;CACA,GAAG,IACD,SACI,uBAAuB,eAAe,KAAK,aAAa,KAAK,GAAG,MAChE,iFACN;CACA,KAAK,MAAM,KAAK,cAAc;EAC5B,IAAI,EAAE,kBAAkB,UAAU,CAAC,EAAE,cAAc,CAAC,EAAE,YAAY;EAClE,MAAM,OAAO;GACX,EAAE,kBAAkB,SAAS,IAAI,EAAE,cAAc,KAAK;GACtD,EAAE,aAAa,eAAe;GAC9B,EAAE,aAAa,aAAa;EAC9B,EACG,OAAO,OAAO,EACd,KAAK,GAAG;EACX,MAAM,SAAS,EAAE,sBAAsB,EAAE;EACzC,GAAG,IAAI,KAAK,EAAE,QAAQ,GAAG,EAAE,iBAAiB,IAAI,OAAO,SAAS,MAAM,WAAW,GAAG,GAAG;CACzF;CACA,KAAK,MAAM,KAAK,QAAQ,GAAG,IAAI,OAAO,EAAE,QAAQ,IAAI,EAAE,MAAM,GAAG;CAC/D,OAAO,QAAQ,eAAe,IAAI,IAAI;AACxC;AAEA,eAAe,aACb,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,GAAG;GACH,SAAS,EAAE,MAAM,SAAS;GAC1B,MAAM,EAAE,MAAM,SAAS;GACvB,IAAI,EAAE,MAAM,SAAS;EACvB;CACF,CAAC;CACD,MAAM,cAAc,YAAY;CAChC,IAAI,CAAC,aAAa;EAChB,GAAG,IACD,6FACF;EACA,OAAO;CACT;CACA,MAAM,YAAY,cAAc,QAAQ,EAAE;CAC1C,IAAI,CAAC,WAAW,OAAO;CACvB,MAAM,IAAI,eAAe,MAAM;CAC/B,MAAM,iBAAiB,KAAK,kBAAkB,qBAAqB,CAAC;CAEpE,IAAI;EACF,IAAI,OAAO,OAAO;EAClB,IAAI,SAAS,KAAA,GAAW;GACtB,IAAI,CAAC,OAAO,SAAS;IACnB,GAAG,IAAI,kFAAkF;IACzF,OAAO;GACT;GACA,MAAM,WAAW,uBAAuB,OAAO,SAAS,aAAa,EACnE,WAAW,iBAAiB,WAC9B,CAAC;GACD,IAAI,CAAC,SAAS,SAAS;IACrB,GAAG,IAAI,6CAA6C,YAAY,OAAO,OAAO,QAAQ,GAAG;IACzF,OAAO;GACT;GACA,OAAO,SAAS;EAClB;EACA,MAAM,EAAE,MAAM,UAAU,WAAW,MAAM,eAAe,aAAa,SAAS;EAC9E,MAAM,QAAQ,eAAe,UAAU;GACrC;GACA,IAAI,OAAO;GACX,YAAY,cAAc,SAAS;EACrC,CAAC;EAED,IAAI,OAAO,MAAM;GACf,GAAG,IACD,GAAG,KAAK,UACN;IACE,SAAS;IACT,MAAM,MAAM;IACZ,IAAI,MAAM,MAAM;IAChB,iBAAiB,MAAM,QAAQ,KAAK,MAAM,EAAE,OAAO;IACnD;IACA,MAAM,MAAM,QAAQ,KAAK,MAAM,EAAE,IAAI,EAAE,KAAK,MAAM;GACpD,GACA,MACA,CACF,EAAE,GACJ;GACA,OAAO;EACT;EACA,GAAG,IACD,GAAG,YAAY,GAAG,MAAM,KAAK,KAAK,MAAM,MAAM,SAAS,KAAK,MAAM,QAAQ,OAAO,iBAAiB,OAAO,IAC3G;EACA,IAAI,MAAM,QAAQ,WAAW,GAAG;GAC9B,GAAG,IAAI,kDAAkD;GACzD,OAAO;EACT;EACA,KAAK,MAAM,KAAK,MAAM,SAAS,GAAG,IAAI,QAAQ,EAAE,QAAQ,IAAI,EAAE,KAAK,GAAG;EACtE,OAAO;CACT,SAAS,GAAG;EACV,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;;;;;;;;;;;;;ACtfA,eAAsB,SACpB,MACA,IACA,OAAgC,CAAC,GAChB;CACjB,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,UACH,OAAO,UAAU,MAAM,IAAI,SAAS;EACtC,KAAK,cACH,OAAO,UAAU,MAAM,IAAI,aAAa;EAC1C,KAAK,UACH,OAAO,UAAU,MAAM,IAAI,SAAS;EACtC,KAAK,WACH,OAAO,UAAU,MAAM,IAAI,UAAU;EACvC,KAAK,OACH,OAAO,UAAU,MAAM,KAAK,OAAO,GAAG,MAAMI,SAAO,OAAO,GAAG,GAAG,IAAI,CAAC;EACvE,KAAK,cACH,OAAO,UAAU,MAAM,IAAI,aAAa;EAC1C;GACE,GAAG,IAAI,6BAA6B,OAAO,SAAS,GAAG;GACvD,OAAO;CACX;AACF;;AAGA,eAAe,UACb,MACA,IACA,IACiB;CAIjB,MAAM,SAAS,WAAW,IAAI,KAAK,GAAG,KAAK;CAC3C,IAAI,CAAC,QAAQ;EACX,GAAG,IAAI,uEAAuE;EAC9E,OAAO;CACT;CACA,MAAM,QAAQ,aAAa,KAAK,MAAM;CACtC,IAAI;EACF,OAAO,MAAM,GAAG,OAAO,MAAM,EAAE;CACjC,UAAU;EACR,MAAM,MAAM;CACd;AACF;;AAGA,SAAS,WAAW,MAAoC;CACtD,MAAM,IAAI,KAAK,QAAQ,MAAM;CAC7B,OAAO,KAAK,IAAI,KAAK,IAAI,KAAK,KAAA;AAChC;AAEA,SAASC,MAAI,KAA6C;CACxD,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAA;CAC9B,MAAM,IAAI,OAAO,GAAG;CACpB,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,KAAA;AAClC;AAEA,SAASC,eAAa,IAAW,GAAuB;CACtD,GAAG,IACD,MAAM,EAAE,MAAM,IAAI,EAAE,GAAG,SAAS,EAAE,KAAK,SAAS,EAAE,SAAS,GAAG,EAAE,KAAK,UAAU,EAAE,WAAW,QAAQ,CAAC,EAAE,GACzG;AACF;AAEA,SAAS,UAAU,OAAqB,MAAgB,IAAmB;CACzE,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,kBAAkB;EAClB,SAAS;GACP,IAAI,EAAE,MAAM,SAAS;GACrB,YAAY,EAAE,MAAM,SAAS;GAC7B,kBAAkB,EAAE,MAAM,SAAS;GACnC,OAAO,EAAE,MAAM,SAAS;GACxB,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,WAAW,MAAM,SAAS;EAC9B,SAASD,MAAI,OAAO,WAAW;EAC/B,cAAcA,MAAI,OAAO,iBAAiB;EAC1C,OAAO,OAAO;CAChB,CAAC;CACD,MAAM,cAAc,IAAI,WAAW,OAAO;EAAE,iBAAiB;EAAO,aAAa;CAAE,CAAC,EAAE,OAAO;CAE7F,IAAI,OAAO,MAAM;EACf,MAAM,UAAkC,CAAC;EACzC,KAAK,MAAM,KAAK,UAAU,QAAQ,EAAE,UAAU,QAAQ,EAAE,UAAU,KAAK;EACvE,GAAG,IAAI,GAAG,KAAK,UAAU;GAAE;GAAS;GAAU;EAAY,GAAG,MAAM,CAAC,EAAE,GAAG;EACzE,OAAO;CACT;CACA,MAAM,SAAS;EAAE,OAAO;EAAG,UAAU;EAAG,QAAQ;EAAG,qBAAqB;CAAE;CAC1E,KAAK,MAAM,KAAK,UAAU,OAAO,EAAE;CACnC,GAAG,IACD,SAAS,OAAO,MAAM,aAAa,OAAO,SAAS,WAAW,OAAO,OAAO,sBAAsB,OAAO,qBAAqB,GAChI;CACA,IAAI,SAAS,SAAS,GAAG;EACvB,GAAG,IAAI,aAAa;EACpB,KAAK,MAAM,KAAK,UAAU,eAAa,IAAI,CAAC;CAC9C;CACA,IAAI,YAAY,SAAS,GAAG;EAC1B,GAAG,IAAI,gBAAgB,YAAY,OAAO,KAAK;EAC/C,KAAK,MAAM,KAAK,aAAa,GAAG,IAAI,KAAK,EAAE,OAAO,UAAU,EAAE,UAAU,KAAK,EAAE,OAAO,IAAI;CAC5F;CACA,OAAO;AACT;AAEA,SAAS,cAAc,OAAqB,MAAgB,IAAmB;CAC7E,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,kBAAkB;EAClB,SAAS;GACP,IAAI,EAAE,MAAM,SAAS;GACrB,mBAAmB,EAAE,MAAM,SAAS;GACpC,YAAY,EAAE,MAAM,SAAS;GAC7B,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CAED,MAAM,aAAa,qBADF,MAAM,SAAS,EAAE,SAASA,MAAI,OAAO,WAAW,EAAE,CACpB,GAAG,EAChD,eAAeA,MAAI,OAAO,kBAAkB,EAC9C,CAAC;CAED,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,EAAE,WAAW,GAAG,MAAM,CAAC,EAAE,GAAG;EACrD,OAAO;CACT;CACA,IAAI,WAAW,WAAW,GAAG;EAC3B,GAAG,IAAI,4BAA4B;EACnC,OAAO;CACT;CACA,GAAG,IAAI,eAAe,WAAW,OAAO,KAAK;CAC7C,KAAK,MAAM,KAAK,YAAY,eAAa,IAAI,CAAC;CAC9C,OAAO;AACT;AAEA,SAAS,UAAU,OAAqB,MAAgB,IAAmB;CACzE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,IAAI,EAAE,MAAM,SAAS;GACrB,QAAQ,EAAE,MAAM,SAAS;GACzB,IAAI,EAAE,MAAM,SAAS;GACrB,gBAAgB,EAAE,MAAM,SAAS;GACjC,aAAa,EAAE,MAAM,SAAS;GAC9B,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,aAAa,YAAY;CAC/B,IAAI,CAAC,YAAY;EACf,GAAG,IAAI,sCAAsC;EAC7C,OAAO;CACT;CACA,MAAM,SAAS,OAAO,UAAU;CAChC,IAAI,WAAW,YAAY,WAAW,UAAU;EAC9C,GAAG,IAAI,0BAA0B,OAAO,4BAA4B;EACpE,OAAO;CACT;CACA,MAAM,SAAS,KAAK,MAAM,aAAa,YAAY,MAAM,CAAC;CAC1D,MAAM,OAAO;EACX,IAAI,OAAO,uBAAM,IAAI,KAAK,GAAE,YAAY;EACxC,aAAa,OAAO;EACpB,UAAU,OAAO;CACnB;CACA,MAAM,WACJ,WAAW,WAAW,MAAM,mBAAmB,QAAQ,IAAI,IAAI,MAAM,aAAa,QAAQ,IAAI;CAEhG,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU;GAAE;GAAQ;EAAS,GAAG,MAAM,CAAC,EAAE,GAAG;EAC3D,OAAO;CACT;CACA,GAAG,IAAI,YAAY,SAAS,mBAAmB,OAAO,UAAU;CAChE,OAAO;AACT;AAEA,SAAS,WAAW,OAAqB,MAAgB,IAAmB;CAC1E,MAAM,EAAE,gBAAgB,UAAU;EAChC;EACA,kBAAkB;EAClB,SAAS,EAAE,IAAI,EAAE,MAAM,SAAS,EAAE;CACpC,CAAC;CACD,MAAM,SAAS,YAAY;CAC3B,IAAI,CAAC,QAAQ;EACX,GAAG,IAAI,kCAAkC;EACzC,OAAO;CACT;CACA,MAAM,WAAW,IAAI,WAAW,OAAO;EAAE,iBAAiB;EAAO,aAAa;CAAE,CAAC,EAAE,QAAQ,MAAM;CACjG,GAAG,IAAI,WAAW,YAAY,OAAO,MAAM,GAAG,OAAO,uBAAuB;CAC5E,OAAO;AACT;AAEA,eAAeD,SACb,OACA,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,IAAI,EAAE,MAAM,SAAS;GACrB,WAAW,EAAE,MAAM,SAAS;GAC5B,QAAQ,EAAE,MAAM,SAAS;GACzB,MAAM;IAAE,MAAM;IAAU,UAAU;GAAK;GACvC,aAAa,EAAE,MAAM,SAAS;GAC9B,aAAa,EAAE,MAAM,UAAU;GAC/B,cAAc,EAAE,MAAM,SAAS;GAC/B,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,cAAc,YAAY;CAChC,IAAI,CAAC,aAAa;EAChB,GAAG,IAAI,oCAAoC;EAC3C,OAAO;CACT;CACA,MAAM,YAAY,OAAO,aAAa;CACtC,IAAI,cAAc,YAAY,cAAc,UAAU;EACpD,GAAG,IAAI,sBAAsB,UAAU,4BAA4B;EACnE,OAAO;CACT;CACA,IAAI;EAEF,MAAM,SAAS,OADH,cAAc,WAAW,qBAAqB,cAExD,OACA;GACE;GACA,cAAc,CAAC,QAAQ,WAAW,CAAC;GACnC,UAAU,OAAO,gBAAgB;GACjC,WAAWC,MAAI,OAAO,aAAa;EACrC,GACA;GAAE,QAAQA,MAAI,OAAO,MAAM,KAAK;GAAG,OAAO,OAAO;GAAM,UAAU,OAAO;EAAa,GACrF,EAAE,QAAQ,KAAK,OAAO,CACxB;EACA,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;GAC7C,OAAO;EACT;EACA,GAAG,IAAI,OAAO,OAAO,WAAW,0BAA0B,OAAO,SAAS,UAAU;EACpF,KAAK,MAAM,KAAK,OAAO,UAAU,eAAa,IAAI,CAAC;EACnD,OAAO;CACT,SAAS,GAAG;EACV,IAAI,aAAa,gBAAgB;GAC/B,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;AAEA,SAAS,cAAc,OAAqB,MAAgB,IAAmB;CAC7E,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,IAAI,EAAE,MAAM,SAAS;GACrB,QAAQ,EAAE,MAAM,SAAS;GACzB,cAAc,EAAE,MAAM,SAAS;GAC/B,eAAe,EAAE,MAAM,SAAS;GAChC,oBAAoB,EAAE,MAAM,UAAU;GACtC,iBAAiB,EAAE,MAAM,SAAS;GAClC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,SAAS,YAAY;CAC3B,IAAI,CAAC,UAAU,CAAC,OAAO,UAAU,CAAC,OAAO,eAAe;EACtD,GAAG,IAAI,mEAAmE;EAC1E,OAAO;CACT;CACA,MAAM,SAAS;EACb,iBAAiB,OAAO,uBAAuB;EAC/C,aAAaA,MAAI,OAAO,gBAAgB,KAAK;CAC/C;CACA,IAAI;EACF,MAAM,QAAQ,IAAI,WAAW,OAAO,MAAM,EAAE,WAAW;GACrD;GACA,QAAQ,OAAO;GACf,WAAW,OAAO;GAClB,YAAYA,MAAI,OAAO,cAAc;EACvC,CAAC;EACD,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,EAAE,MAAM,GAAG,MAAM,CAAC,EAAE,GAAG;GAChD,OAAO;EACT;EACA,GAAG,IAAI,eAAe,MAAM,OAAO,SAAS,MAAM,UAAU,KAAK,MAAM,OAAO,IAAI;EAClF,OAAO;CACT,SAAS,GAAG;EACV,IAAI,aAAa,qBAAqB;GACpC,GAAG,IAAI,YAAY,EAAE,QAAQ,iDAAiD;GAC9E,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;;;;;;;;;;;;;;;;;;;;AC/QA,eAAsB,OAAO,MAAgB,IAAW,OAAgB,CAAC,GAAoB;CAC3F,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,aACH,OAAO,aAAa,MAAM,IAAI,IAAI;EACpC,KAAK,cACH,OAAO,SAAS,cAAc,MAAM,IAAI,IAAI;EAC9C,KAAK,mBACH,OAAO,SAAS,kBAAkB,MAAM,IAAI,IAAI;EAClD,KAAK,cACH,OAAO,SAAS,cAAc,MAAM,IAAI,IAAI;EAC9C,KAAK,SACH,OAAO,SAAS,SAAS,MAAM,IAAI,IAAI;EACzC,KAAK,WACH,OAAO,SAAS,mBAAmB,MAAM,IAAI,IAAI;EACnD,KAAK,eACH,OAAO,SAAS,eAAe,MAAM,IAAI,IAAI;EAC/C,KAAK,qBACH,OAAO,oBAAoB,MAAM,IAAI,IAAI;EAC3C,KAAK,kBACH,OAAO,SAAS,iBAAiB,MAAM,IAAI,IAAI;EACjD,KAAK,UACH,OAAO,UAAU,MAAM,IAAI,IAAI;EACjC;GACE,GAAG,IAAI,2BAA2B,OAAO,SAAS,GAAG;GACrD,OAAO;CACX;AACF;AAEA,MAAM,eAAe;CACnB,SAAS,EAAE,MAAM,SAAS;CAG1B,kBAAkB;EAAE,MAAM;EAAU,UAAU;CAAK;CACnD,SAAS,EAAE,MAAM,SAAS;CAC1B,aAAa,EAAE,MAAM,UAAU;CAC/B,eAAe,EAAE,MAAM,UAAU;CAGjC,wBAAwB,EAAE,MAAM,UAAU;CAG1C,kCAAkC,EAAE,MAAM,UAAU;CACpD,cAAc,EAAE,MAAM,SAAS;CAC/B,MAAM,EAAE,MAAM,UAAU;AAC1B;AAEA,SAASE,MAAI,KAA6C;CACxD,IAAI,QAAQ,KAAA,GAAW,OAAO,KAAA;CAC9B,MAAM,IAAI,OAAO,GAAG;CACpB,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,KAAA;AAClC;;;;;;;AAkBA,SAAS,YAAY,QAAiC,IAAW,MAA+B;CAC9F,MAAM,cAAc,QAAS,OAAO,WAAsB,QAAQ,IAAI,CAAC;CACvE,MAAM,kBAAmB,OAAO,qBAAkC,CAAC,GAAG,KAAK,MAAM,QAAQ,CAAC,CAAC;CAG3F,IAAI,OAAO,qCAAqC,CAAC,OAAO,gBAAgB;EACtE,GAAG,IAAI,2DAA2D;EAClE,OAAO;CACT;CACA,IAAI,KAAK,SAAS,KAAK,UAAU,KAAK,iBACpC,OAAO;EACL,OAAO,KAAK,UAAU,YAAY,KAAK,OAAO;EAC9C,QAAQ,KAAK,WAAW,YAAY,KAAK,QAAQ;EACjD,iBAAiB,KAAK,0BAA0B,CAAC;EACjD,UAAU,YAAY,CAAC;EACvB;EACA;CACF;CAEF,MAAM,MAAO,OAAO,WAAsB,GAAG,KAAK;CAClD,IAAI,CAAC,OAAO,IAAI,KAAK,MAAM,IAAI;EAC7B,GAAG,IAAI,wEAAwE;EAC/E,OAAO;CACT;CACA,IAAI;CACJ,IAAI;EACF,WAAW,oBAAoB,GAAG;CACpC,SAAS,GAAG;EACV,GAAG,IAAI,+BAAgC,EAAY,QAAQ,GAAG;EAC9D,OAAO;CACT;CACA,MAAM,eAAe,CAAC,aAAa,GAAG,cAAc;CACpD,MAAM,UAAU,IAAI,sBAAsB;EACxC;EACA;EACA,WAAWA,MAAI,OAAO,aAAuB,KAAK;CACpD,CAAC;CACD,MAAM,QAAQ,IAAI,eAAe;EAC/B;EACA,UAAW,OAAO,gBAA4B;EAC9C;CACF,CAAC;CACD,MAAM,SAAS,IAAI,gBAAgB;EACjC;EACA,UAAW,OAAO,gBAA4B;EAC9C;EACA,YAAa,OAAO,kBAA8B;EAClD,oBAAqB,OAAO,2BAAuC;EACnE,6BAA8B,OAAO,qCAAiD;EAEtF,WAAW;CACb,CAAC;CACD,OAAO;EACL,QAAQ,UAAU,MAAM,MAAM,KAAK;EACnC,SAAS,UAAU,OAAO,OAAO,KAAK;EACtC,uBAAuB,QAAQ,SAAS;EACxC,gBAAgB,QAAQ,SAAS;EACjC;EACA;CACF;AACF;AAEA,SAAS,KAAK,MAAqB;CACjC,MAAM,IAAI,MAAM,MAAM,KAAK,kBAAkB;AAC/C;AAEA,SAAS,aAAa,MAAgB,IAAW,MAAuB;CACtE,MAAM,EAAE,WAAW,UAAU;EAAE;EAAM,kBAAkB;EAAM,SAAS;CAAa,CAAC;CACpF,MAAM,MAAO,OAAO,WAAsB,GAAG,KAAK;CAClD,IAAI,YAAsB,CAAC;CAC3B,IAAI,OAAO,IAAI,KAAK,MAAM,IACxB,IAAI;EACF,YAAY,OAAO,KAAK,oBAAoB,GAAG,CAAC,EAAE,KAAK;CACzD,SAAS,GAAG;EACV,GAAG,IAAI,+BAAgC,EAAY,QAAQ,GAAG;EAC9D,OAAO;CACT;CAEF,MAAM,WAAW,KAAK,0BAA0B,CAAC,IAAI;CACrD,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU;GAAE;GAAW;EAAQ,GAAG,MAAM,CAAC,EAAE,GAAG;EAC7D,OAAO;CACT;CACA,GAAG,IAAI,UAAU,SAAS,oBAAoB,UAAU,KAAK,IAAI,EAAE,MAAM,sBAAsB;CAC/F,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,IAAI,EAAE,aACR,GAAG,EAAE,WAAW,OAAO,EAAE,WAAW,UAAU,IAAI,EAAE,WAAW,YAAY,OAC3E;EACJ,GAAG,IAAI,KAAK,EAAE,SAAS,KAAK,EAAE,YAAY,IAAI,EAAE,GAAG;CACrD;CACA,OAAO;AACT;;AAGA,SAAS,WAAW,QAAwB;CAC1C,OAAO,WAAW,cAAc,IAAI;AACtC;AAEA,SAAS,SAAS,GAGP;CACT,OAAO,GAAG,EAAE,MAAM,KAAK,GAAG,EAAE,MAAM,OAAO,GAAG,EAAE,IAAI,KAAK,GAAG,EAAE,IAAI;AAClE;AAEA,SAAS,YAAY,IAAW,GAAyB;CACvD,MAAM,OAAO,EAAE,aACX,GAAG,EAAE,WAAW,OAAO,EAAE,WAAW,UAAU,IAAI,EAAE,WAAW,YAAY,OAC3E;CACJ,GAAG,IAAI,WAAW,EAAE,OAAO,KAAK,EAAE,KAAK,IAAI,EAAE,SAAS,IAAI,KAAK,IAAI;CACnE,IAAI,EAAE,gBAAgB,GAAG,IAAI,YAAY,EAAE,eAAe,GAAG;AAC/D;AAEA,SAAS,aAAa,IAAW,SAAyB,OAAqB;CAC7E,KAAK,MAAM,KAAK,SAAS;EACvB,MAAM,SAAS,EAAE,SAAS,KAAK,EAAE,WAAW;EAC5C,GAAG,IAAI,GAAG,KAAK,OAAO,QAAQ,CAAC,IAAI,EAAE,KAAK,KAAK,EAAE,SAAS,KAAK,SAAS,EAAE,KAAK,IAAI,OAAO,GAAG;EAC7F,IAAI,EAAE,YAAY,EAAE,SAAS,SAAS,GAAG,aAAa,IAAI,EAAE,UAAU,QAAQ,CAAC;CACjF;AACF;AAEA,eAAe,SACb,MACA,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,GAAG;GAAc,WAAW,EAAE,MAAM,SAAS;EAAE;CAC5D,CAAC;CACD,MAAM,eAAe,SAAS,qBAAqB,SAAS;CAC5D,MAAM,CAAC,UAAU,MAAM,SAAS,UAAU;CAC1C,IAAI,CAAC,YAAY,CAAC,QAAS,CAAC,iBAAiB,YAAY,KAAA,KAAa,WAAW,KAAA,IAAa;EAC5F,GAAG,IACD,eACI,OAAO,YAAY,IAAI,EAAE,8BACzB,OAAO,YAAY,IAAI,EAAE,2CAC/B;EACA,OAAO;CACT;CAEA,MAAM,UAAU,YAAY,QAAQ,IAAI,IAAI;CAC5C,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI;EACF,MAAM,QAAuB;GAC3B;GACA,aAAa,QAAQ;GACrB;GACA;GACA,GAAI,QAAQ,eAAe,SAAS,EAAE,gBAAgB,QAAQ,eAAe,IAAI,CAAC;GAClF,GAAI,eAAe,CAAC,IAAI;IAAE,MAAM,OAAO,OAAO;IAAG,QAAQ,OAAO,MAAM;GAAE;GACxE,GAAI,SAAS,kBACT,EAAE,WAAY,OAAO,aAAyC,WAAW,IACzE,CAAC;EACP;EACA,MAAM,SAAS,MAAM,QAAQ,MAAM,KAAK;EAExC,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;GAC7C,OAAO,WAAW,OAAO,MAAM;EACjC;EAEA,YAAY,IAAI,MAAM;EACtB,IAAI,OAAO,WAAW,aAAa;GACjC,GAAG,IAAI,gDAAgD;GACvD,OAAO;EACT;EACA,IAAI,SAAS,SACX,GAAG,IAAI,OAAO,QAAQ,GAAG,OAAO,MAAM,MAAM,MAAM,iBAAiB;OAC9D,IAAI,SAAS,mBAAmB;GACrC,MAAM,UAAU,OAAO,WAAW,CAAC;GACnC,GAAG,IAAI,GAAG,QAAQ,OAAO,cAAc;GACvC,aAAa,IAAI,SAAS,CAAC;EAC7B,OAAO,IAAI,SAAS,eAAe;GACjC,MAAM,QAAQ,OAAO,eAAe,CAAC;GACrC,GAAG,IAAI,GAAG,MAAM,OAAO,kBAAkB;GACzC,KAAK,MAAM,KAAK,OACd,gBAAgB,IAAI,CAAC;EAEzB,OAAO,IAAI,SAAS,iBAAiB;GACnC,MAAM,SAAS,OAAO,iBAAiB,CAAC;GACxC,KAAK,MAAM,KAAK,QAAQ;IACtB,GAAG,IAAI,GAAG,EAAE,OAAO,KAAK,KAAK,EAAE,OAAO,SAAS,MAAM,EAAE,UAAU,IAAI;IACrE,KAAK,MAAM,KAAK,EAAE,OAChB,GAAG,IAAI,KAAK,EAAE,KAAK,KAAK,IAAI,EAAE,KAAK,IAAI,IAAI,EAAE,WAAW,IAAI,QAAQ,EAAE,KAAK,IAAI,EAAE,GAAG;GAExF;EACF,OAAO;GACL,MAAM,YAAY,OAAO,aAAa,CAAC;GACvC,GAAG,IAAI,GAAG,UAAU,OAAO,gBAAgB;GAC3C,KAAK,MAAM,OAAO,WAChB,GAAG,IAAI,KAAK,IAAI,IAAI,IAAI,SAAS,IAAI,KAAK,IAAI,IAAI,SAAS,KAAK,eAAe,GAAG;EAEtF;EACA,OAAO,WAAW,OAAO,MAAM;CACjC,SAAS,GAAG;EACV,IAAI,aAAa,cAAc;GAC7B,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT,UAAU;EACR,MAAM,QAAQ,SAAS;CACzB;AACF;;;;;;AAOA,eAAe,oBAAoB,MAAgB,IAAW,MAAgC;CAC5F,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EAAE;EAAM,kBAAkB;EAAM,SAAS;CAAa,CAAC;CACjG,MAAM,CAAC,UAAU,OAAO,cAAc;CACtC,IAAI,CAAC,YAAY,UAAU,KAAA,GAAW;EACpC,GAAG,IAAI,+DAA+D;EACtE,OAAO;CACT;CAEA,MAAM,UAAU,YAAY,QAAQ,IAAI,IAAI;CAC5C,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI;EACF,MAAM,SAAS,MAAM,QAAQ,MAAM;GACjC;GACA,aAAa,QAAQ;GACrB,MAAM;GACN;GACA,GAAI,QAAQ,eAAe,SAAS,EAAE,gBAAgB,QAAQ,eAAe,IAAI,CAAC;GAClF,GAAI,eAAe,KAAA,IAAY,EAAE,MAAM,WAAW,IAAI,CAAC;EACzD,CAAC;EAED,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;GAC7C,OAAO,WAAW,OAAO,MAAM;EACjC;EAEA,YAAY,IAAI,MAAM;EACtB,IAAI,OAAO,WAAW,aAAa;GACjC,GAAG,IAAI,gDAAgD;GACvD,OAAO;EACT;EACA,MAAM,UAAU,OAAO,oBAAoB,CAAC;EAC5C,GAAG,IAAI,GAAG,QAAQ,OAAO,cAAc;EACvC,KAAK,MAAM,KAAK,SACd,qBAAqB,IAAI,CAAC;EAE5B,OAAO,WAAW,OAAO,MAAM;CACjC,SAAS,GAAG;EACV,IAAI,aAAa,cAAc;GAC7B,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT,UAAU;EACR,MAAM,QAAQ,SAAS;CACzB;AACF;AAEA,SAAS,gBAAgB,IAAW,GAA2B;CAC7D,MAAM,MAAM,EAAE,iBAAiB,EAAE,aAAa,KAAA,IAAY,YAAY,EAAE,aAAa;CACrF,MAAM,QAAQ,GAAG,EAAE,MAAM,MAAM,KAAK,GAAG,EAAE,MAAM,MAAM;CACrD,MAAM,OAAO,EAAE,SAAS,KAAA,IAAY,KAAK,EAAE,SAAS,GAAG,EAAE,OAAO,KAAK,KAAK,EAAE,KAAK,KAAK;CACtF,GAAG,IAAI,KAAK,MAAM,IAAI,MAAM,KAAK,IAAI,EAAE,QAAQ,GAAG;CAClD,KAAK,MAAM,KAAK,EAAE,WAAW,CAAC,GAC5B,GAAG,IAAI,WAAW,EAAE,IAAI,GAAG,EAAE,MAAM,MAAM,KAAK,GAAG,EAAE,MAAM,MAAM,OAAO,IAAI,EAAE,QAAQ,GAAG;AAE3F;AAEA,SAAS,qBAAqB,IAAW,GAAgC;CACvE,MAAM,YAAY,EAAE,YAAY,SAAS,EAAE,UAAU,KAAK;CAC1D,MAAM,MAAM,EAAE,QAAQ,KAAK,SAAS,EAAE,KAAK,IAAI,EAAE,SAAS,KAAK,mBAAmB;CAClF,GAAG,IAAI,KAAK,EAAE,KAAK,KAAK,EAAE,SAAS,KAAK,EAAE,MAAM,MAAM,UAAU,GAAG;AACrE;;AAGA,SAAS,YAAY,MAA4B;CAC/C,IAAI,SAAS,kBAAkB,OAAO;CACtC,IAAI,SAAS,mBAAmB,OAAO;CACvC,IAAI,SAAS,iBAAiB,OAAO;CACrC,OAAO;AACT;AAEA,eAAe,UAAU,MAAgB,IAAW,MAAgC;CAClF,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;CACX,CAAC;CACD,MAAM,CAAC,UAAU,MAAM,SAAS,QAAQ,WAAW;CACnD,IAAI,CAAC,YAAY,CAAC,QAAQ,YAAY,KAAA,KAAa,WAAW,KAAA,KAAa,CAAC,SAAS;EACnF,GAAG,IAAI,gEAAgE;EACvE,OAAO;CACT;CACA,MAAM,UAAU,YAAY,QAAQ,IAAI,IAAI;CAC5C,IAAI,CAAC,SAAS,OAAO;CACrB,IAAI;EACF,MAAM,SAAS,MAAM,QAAQ,OAAO;GAClC;GACA,aAAa,QAAQ;GACrB;GACA,MAAM,OAAO,OAAO;GACpB,QAAQ,OAAO,MAAM;GACrB;GACA,GAAI,QAAQ,eAAe,SAAS,EAAE,gBAAgB,QAAQ,eAAe,IAAI,CAAC;EACpF,CAAC;EAED,IAAI,OAAO,MACT,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;OAE7C,YAAY,IAAI,MAAM;EAExB,IAAI,OAAO,WAAW,aAAa,OAAO;EAC1C,IAAI,OAAO,SAAS,OAAO;EAC3B,OAAO;CACT,SAAS,GAAG;EACV,IAAI,aAAa,cAAc;GAC7B,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT,UAAU;EACR,MAAM,QAAQ,SAAS;CACzB;AACF;AAEA,SAAS,YAAY,IAAW,GAA0B;CACxD,MAAM,OAAO,EAAE,aACX,GAAG,EAAE,WAAW,OAAO,EAAE,WAAW,UAAU,IAAI,EAAE,WAAW,YAAY,OAC3E;CACJ,MAAM,OAAO,EAAE,UAAU,oBAAoB;CAC7C,GAAG,IAAI,WAAW,EAAE,OAAO,IAAI,KAAK,KAAK,EAAE,SAAS,IAAI,KAAK,IAAI;CACjE,IAAI,EAAE,gBAAgB,GAAG,IAAI,YAAY,EAAE,eAAe,GAAG;CAC7D,IAAI,EAAE,iBAAiB,WAAW;EAChC,MAAM,OAAO,EAAE,wBAAwB,CAAC;EACxC,GAAG,IACD,kEAAkE,KAAK,OAAO,2CAA2C,KAAK,KAAK,IAAI,EAAE,GAC3I;EACA,GAAG,IACD,4GACF;CACF,OAAO,IAAI,EAAE,iBAAiB,WAC5B,GAAG,IAAI,qEAAqE;CAE9E,IAAI,EAAE,SAAS;EACb,GAAG,IAAI,YAAY,EAAE,QAAQ,GAAG;EAChC;CACF;CACA,GAAG,IAAI,YAAY,EAAE,QAAQ,IAAI,EAAE,eAAe,kBAAkB,EAAE,UAAU,WAAW;CAC3F,KAAK,MAAM,KAAK,EAAE,OAAO;EACvB,GAAG,IAAI,KAAK,EAAE,KAAK,IAAI,EAAE,UAAU,UAAU,EAAE,YAAY,4BAA4B,GAAG,GAAG;EAC7F,KAAK,MAAM,KAAK,EAAE,SAAS,CAAC,GAC1B,GAAG,IAAI,OAAO,SAAS,EAAE,KAAK,EAAE,IAAI,EAAE,QAAQ,KAAK,EAAE,QAAQ,GAAG;CAEpE;CACA,KAAK,MAAM,MAAM,EAAE,eAAe,CAAC,GACjC,GAAG,IAAI,KAAK,GAAG,KAAK,SAAS,GAAG,KAAK,KAAK,KAAK,EAAE,GAAG;CAEtD,IAAI,EAAE,aAAa,QACjB,GAAG,IACD,oCAAoC,EAAE,YAAY,OAAO,qBAAqB,EAAE,YAAY,KAAK,IAAI,EAAE,GACzG;CACF,IAAI,EAAE,SACJ,GAAG,IAAI,6DAA6D,EAAE,gBAAgB,GAAG,GAAG;CAC9F,KAAK,MAAM,KAAK,EAAE,WAAW,CAAC,GAC5B,GAAG,IACD,YAAY,EAAE,KAAK,IAAI,EAAE,OAAO,MAAM,GAAG,EAAE,EAAE,KAAK,EAAE,MAAM,MAAM,GAAG,EAAE,KAAK,YAAY,GACxF;AAEJ;;;;;;;;;;;;ACndA,eAAsB,UACpB,MACA,IACA,OAAoC,CAAC,GACpB;CACjB,MAAM,CAAC,KAAK,GAAG,QAAQ;CACvB,QAAQ,KAAR;EACE,KAAK,aACH,OAAO,aAAa,MAAM,EAAE;EAC9B,KAAK,OACH,OAAO,OAAO,MAAM,IAAI,IAAI;EAC9B;GACE,GAAG,IAAI,8BAA8B,OAAO,SAAS,GAAG;GACxD,OAAO;CACX;AACF;;AAGA,SAAS,IAAI,OAA8B;CACzC,OAAO,UAAU,OAAO,QAAQ,GAAG,MAAM,QAAQ,CAAC,EAAE;AACtD;AAEA,SAAS,aAAa,IAAW,SAAgC;CAC/D,MAAM,EAAE,SAAS,cAAc;CAC/B,MAAM,IAAI,QAAQ;CAClB,GAAG,IACD,mBAAmB,IAAI,QAAQ,aAAa,EAAE,cAAc,QAAQ,SAAS,WAAW,QAAQ,MAAM,IACxG;CACA,GAAG,IAAI,uBAAuB,IAAI,QAAQ,+BAA+B,EAAE,GAAG;CAC9E,GAAG,IACD,UAAU,EAAE,OAAO,aAAa,EAAE,SAAS,YAAY,EAAE,QAAQ,gBAAgB,EAAE,WAAW,mBAC1E,EAAE,cAAc,mBAAmB,EAAE,cAAc,YAAY,EAAE,QAAQ,YAAY,EAAE,QAAQ,GACrH;CACA,IAAI,UAAU,WAAW,GAAG;EAC1B,GAAG,IAAI,qBAAqB;EAC5B;CACF;CACA,GAAG,IAAI,cAAc,UAAU,OAAO,KAAK;CAC3C,KAAK,MAAM,KAAK,WACd,GAAG,IAAI,KAAK,EAAE,KAAK,GAAG,EAAE,KAAK,IAAI,EAAE,YAAY,KAAK,EAAE,OAAO,IAAI;AAErE;AAEA,SAAS,aAAa,MAAgB,IAAmB;CACvD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,QAAQ,EAAE,MAAM,SAAS;GAAG,MAAM,EAAE,MAAM,UAAU;EAAE;CACnE,CAAC;CACD,MAAM,aAAa,YAAY;CAC/B,IAAI,CAAC,YAAY;EACf,GAAG,IAAI,0CAA0C;EACjD,OAAO;CACT;CACA,MAAM,SAAS,OAAO,UAAU;CAChC,IAAI,WAAW,aAAa,WAAW,UAAU;EAC/C,GAAG,IAAI,0BAA0B,OAAO,6BAA6B;EACrE,OAAO;CACT;CACA,MAAM,OAAO,aAAa,YAAY,MAAM;CAK5C,MAAM,UAAU,kBADd,WAAW,WAAW,mBAAmB,IAAI,IAAK,KAAK,MAAM,IAAI,CAC3B;CAExC,IAAI,OAAO,MAAM;EACf,GAAG,IAAI,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GAAG;EAC9C,OAAO;CACT;CACA,aAAa,IAAI,OAAO;CACxB,OAAO;AACT;AAEA,eAAe,OACb,MACA,IACA,MACiB;CACjB,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,MAAM,EAAE,MAAM,SAAS;GACvB,MAAM;IAAE,MAAM;IAAU,UAAU;GAAK;GACvC,aAAa,EAAE,MAAM,UAAU;GAC/B,eAAe,EAAE,MAAM,SAAS;GAChC,aAAa,EAAE,MAAM,UAAU;GAC/B,cAAc,EAAE,MAAM,SAAS;GAC/B,eAAe,EAAE,MAAM,SAAS;GAChC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,cAAc,YAAY;CAChC,IAAI,CAAC,aAAa;EAChB,GAAG,IAAI,qCAAqC;EAC5C,OAAO;CACT;CACA,MAAM,OAAO,OAAO,QAAQ;CAC5B,IAAI,SAAS,aAAa,SAAS,YAAY,SAAS,cAAc;EACpE,GAAG,IAAI,iBAAiB,KAAK,wCAAwC;EACrE,OAAO;CACT;CACA,MAAM,aAAa,OAAO;CAC1B,MAAM,YAAY,eAAe,KAAA,IAAY,OAAO,UAAU,IAAI,KAAA;CAElE,IAAI;EACF,MAAM,SAAS;GACb;GAGA,cAAc,CAAC,QAAQ,WAAW,CAAC;GACnC,UAAU,OAAO,gBAAgB;GACjC,WAAW,cAAc,KAAA,KAAa,OAAO,SAAS,SAAS,IAAI,YAAY,KAAA;EACjF;EACA,MAAM,QAAQ;GACZ,aAAa,OAAO;GACpB,aAAa,OAAO,eAAe;GACnC,YAAY,OAAO;EACrB;EACA,MAAM,SACJ,SAAS,WACL,MAAM,UAAU,QAAQ,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,IACtD,SAAS,eACP,MAAM,aAAa,QAAQ,OAAO,EAAE,QAAQ,KAAK,OAAO,CAAC,IACzD,MAAM,YAAY,QAAQ,OAAO;GAC/B,QAAQ,KAAK;GACb,YAAY,OAAO;EACrB,CAAC;EAET,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,QAAQ,MAAM,CAAC,EAAE,GAAG;GAC7C,OAAO,OAAO,aAAa,IAAI,IAAI;EACrC;EACA,GAAG,IACD,OAAO,KAAK,SAAS,OAAO,SAAS,aAAa,OAAO,YAAY,KAAK,IAAI,KAAK,oBAAoB,GACzG;EACA,aAAa,IAAI,OAAO,OAAO;EAC/B,OAAO,OAAO,aAAa,IAAI,IAAI;CACrC,SAAS,GAAG;EACV,IAAI,aAAa,iBAAiB;GAChC,GAAG,IAAI,YAAY,EAAE,QAAQ,sBAAsB;GACnD,OAAO;EACT;EACA,GAAG,IAAI,GAAI,EAAY,QAAQ,GAAG;EAClC,OAAO;CACT;AACF;;;AC3HA,MAAM,aAAa;CAAC;CAAY;CAAQ;CAAY;CAAO;AAAM;AAEjE,MAAM,iBAAqC;CACzC,OAAO,CAAC;CACR,WAAW,CAAC;CACZ,SAAS;EAAE,SAAS;EAAG,WAAW;EAAG,eAAe;EAAG,OAAO;EAAG,sBAAsB;CAAE;AAC3F;;;;;;;;;;;;;;;;;;;;;;AA0DA,eAAsB,UACpB,MACA,IACA,OAAsB,CAAC,GACN;CACjB,IAAI,KAAK,OAAO,OAAO,OAAO,aAAa,KAAK,MAAM,CAAC,GAAG,IAAI,IAAI;CAClE,OAAO,iBAAiB,MAAM,EAAE;AAClC;AAEA,SAAS,aAAa,IAAW,SAA2B,MAAiC;CAC3F,IAAI,MAAM;EACR,GAAG,IAAI,GAAG,KAAK,UAAU,SAAS,MAAM,CAAC,EAAE,GAAG;EAC9C;CACF;CACA,GAAG,IAAI,YAAY,QAAQ,OAAO,YAAY,EAAE,mBAAmB,QAAQ,cAAc,IAAI;CAC7F,KAAK,MAAM,KAAK,QAAQ,SAAS;EAC/B,MAAM,MAAM,EAAE,aAAa,SAAS,KAAK,EAAE,SAAS,KAAK;EACzD,MAAM,MAAM,EAAE,aAAa,cAAc,EAAE,WAAW,KAAK,EAAE,cAAc,eAAe;EAC1F,GAAG,IAAI,KAAK,EAAE,OAAO,IAAI,EAAE,SAAS,MAAM,IAAI,KAAK,EAAE,SAAS,GAAG;CACnE;AACF;AAEA,SAAS,QAAQ,SAAmC;CAClD,IAAI,QAAQ,WAAW,QAAQ,OAAO;CACtC,IAAI,QAAQ,WAAW,gBAAgB,OAAO;CAC9C,OAAO;AACT;AAEA,SAAS,IAAI,OAA+C;CAC1D,IAAI,UAAU,KAAA,GAAW,OAAO,KAAA;CAChC,MAAM,IAAI,OAAO,KAAK;CACtB,OAAO,OAAO,SAAS,CAAC,IAAI,IAAI,KAAA;AAClC;AAEA,eAAe,aAAa,MAAgB,IAAW,MAAsC;CAC3F,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,UAAU,EAAE,MAAM,UAAU;GAC5B,OAAO,EAAE,MAAM,UAAU;GACzB,QAAQ,EAAE,MAAM,UAAU;GAC1B,eAAe,EAAE,MAAM,SAAS;GAChC,iBAAiB,EAAE,MAAM,SAAS;GAClC,MAAM,EAAE,MAAM,UAAU;GACxB,aAAa,EAAE,MAAM,UAAU;GAC/B,gBAAgB;IAAE,MAAM;IAAU,UAAU;GAAK;GACjD,MAAM,EAAE,MAAM,SAAS;GACvB,YAAY,EAAE,MAAM,SAAS;GAG7B,UAAU,EAAE,MAAM,SAAS;GAC3B,UAAU,EAAE,MAAM,SAAS;GAC3B,iBAAiB,EAAE,MAAM,UAAU;GAGnC,MAAM,EAAE,MAAM,SAAS;GACvB,aAAa,EAAE,MAAM,SAAS;GAG9B,SAAS,EAAE,MAAM,SAAS;GAC1B,kBAAkB,EAAE,MAAM,SAAS;GACnC,gBAAgB,EAAE,MAAM,UAAU;GAClC,cAAc;IAAE,MAAM;IAAU,UAAU;GAAK;GAC/C,KAAK;IAAE,MAAM;IAAU,UAAU;GAAK;GACtC,SAAS,EAAE,MAAM,SAAS;GAC1B,SAAS,EAAE,MAAM,SAAS;GAC1B,oBAAoB,EAAE,MAAM,SAAS;GACrC,QAAQ,EAAE,MAAM,SAAS;GACzB,cAAc,EAAE,MAAM,UAAU;GAChC,QAAQ,EAAE,MAAM,UAAU;GAC1B,cAAc,EAAE,MAAM,SAAS;GAC/B,oBAAoB,EAAE,MAAM,SAAS;GACrC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CAED,MAAM,cAAc,YAAY;CAChC,IAAI,CAAC,aAAa;EAChB,GAAG,IAAI,qCAAqC;EAC5C,OAAO;CACT;CACA,MAAM,gBAAgB,OAAO;CAC7B,IAAI,kBAAkB,KAAA,KAAa,CAAC,WAAW,SAAS,aAAa,GAAG;EACtE,GAAG,IAAI,qCAAqC,WAAW,KAAK,GAAG,EAAE,GAAG;EACpE,OAAO;CACT;CAEA,MAAM,WAAW,OAAO,gBAAgB;CACxC,MAAM,eAAe,CAAC,QAAQ,WAAW,CAAC;CAC1C,MAAM,eAAe,OAAO,mBAAmB,CAAC;CAChD,MAAM,OAAO,OAAO,SAAS,KAAA,IAAY,aAAa,OAAO,MAAM,MAAM,IAAI,KAAA;CAC7E,MAAM,YAAY,IAAI,OAAO,aAAa;CAC1C,MAAM,MAAc;EAAE;EAAa;EAAc;CAAK;CAEtD,MAAM,UAA8B,CAAC;CACrC,IAAI,OAAO,UAAU;EACnB,MAAM,MAAM,KAAK;EACjB,QAAQ,WAAW,EACjB,KAAK,YACK,IAAI,GAAG,IACb,YAAY;GAMV,QAAO,MALS,UACd;IAAE;IAAa;IAAc;IAAU;GAAU,GACjD;IAAE;IAAc;GAAK,GACrB,EAAE,QAAQ,KAAK,eAAe,CAChC,GACS,UAAU;EACrB,EACN;CACF;CACA,IAAI,OAAO,QAAQ;EACjB,MAAM,MAAM,KAAK;EAIjB,MAAM,OAAO,OAAO,kBAAkB;EACtC,IAAI,SAAS,aAAa,SAAS,gBAAgB,SAAS,UAAU;GACpE,GAAG,IAAI,uEAAuE,KAAK,IAAI;GACvF,OAAO;EACT;EACA,MAAM,aAAa,OAAO;EAC1B,QAAQ,SAAS,EACf,KAAK,YACK,IAAI,GAAG,IACb,YAAY;GACV,MAAM,MAAM;IAAE;IAAa;IAAc;IAAU;GAAU;GAC7D,MAAM,SAAS;IAAE,aAAa;IAAc;GAAW;GAOvD,QALE,SAAS,eACL,MAAM,aAAa,KAAK,QAAQ,EAAE,QAAQ,KAAK,aAAa,CAAC,IAC7D,SAAS,WACP,MAAM,UAAU,KAAK,QAAQ,EAAE,QAAQ,KAAK,aAAa,CAAC,IAC1D,MAAM,YAAY,KAAK,QAAQ,EAAE,QAAQ,KAAK,aAAa,CAAC,GAC3D;EACX,EACN;CACF;CACA,IAAI,OAAO,OAAO;EAChB,MAAM,MAAM,KAAK;EACjB,IAAI,KACF,QAAQ,QAAQ,EAAE,WAAW,IAAI,GAAG,EAAE;OACjC;GACL,MAAM,SAAS,OAAO;GACtB,MAAM,QAAQ,KAAK,iBAAiB,SAAS,aAAa,KAAK,MAAM,IAAI,KAAA;GACzE,IAAI,CAAC,OAAO;IACV,GAAG,IAAI,8CAA8C;IACrD,OAAO;GACT;GACA,QAAQ,QAAQ,EACd,KAAK,YAAY;IACf,IAAI;KAOF,QAAO,MANS,aACd,OACA;MAAE;MAAa;MAAc;MAAU;KAAU,GACjD,EAAE,OAAO,aAAa,GACtB,EAAE,QAAQ,KAAK,YAAY,CAC7B,GACS;IACX,UAAU;KACR,IAAI,CAAC,KAAK,gBAAgB,QAAQ,MAAM,MAAM;IAChD;GACF,EACF;EACF;CACF;CAEA,IAAI,OAAO,MAAM;EACf,MAAM,MAAM,KAAK;EACjB,IAAI,KACF,QAAQ,OAAO,EAAE,WAAW,IAAI,GAAG,EAAE;OAChC;GAGL,MAAM,YAA0B;GAChC,MAAM,iBAAiB,KAAK,eAAe,YAAY,eAAe,MAAM,CAAC;GAC7E,MAAM,SAAS,OAAO;GACtB,QAAQ,OAAO,EACb,KAAK,YAAY;IACf,MAAM,SAAS,OAAO,oBAAoB,MAAM,SAAS,IAAI,CAAC;IAC9D,MAAM,EAAE,QAAQ,sBAAsB,MAAM,mBAAmB;KAC7D,SAAS;KACT;KACA,OAAO,OAAO,SAAS,IAAI,SAAS,KAAA;KACpC;KACA;IACF,CAAC;IACD,OAAO;KAAE;KAAQ;IAAkB;GACrC,EACF;EACF;CACF;CAEA,IAAI,OAAO,WAAW,OAAO,MAAM;EACjC,GAAG,IAAI,2DAA2D;EAClE,OAAO;CACT;CAEA,IAAI,OAAO,SAAS;EAClB,MAAM,cAAc,OAAO;EAC3B,MAAM,OAAO,UAAU,OAAO,GAAG;EACjC,MAAM,MAAM,KAAK;EACjB,IAAI,KACF,QAAQ,WAAW;GACjB,QAAQ;GACR,WAAW,IAAI;IAAE,SAAS;IAAa,eAAe,OAAO;IAAmB;GAAK,CAAC;EACxF;OACK;GACL,MAAM,SAAS,OAAO;GACtB,IAAI,CAAC,QAAQ;IACX,GAAG,IAAI,qDAAqD;IAC5D,OAAO;GACT;GACA,MAAM,WAAW,oBAAoB,MAAM;GAC3C,MAAM,QAAQ,IAAIC,gBAChB,YAAY,KAAK,OAAO,GAAG,uBAAuB,CAAC,GACnD,QACF;GAMA,QAAQ,WAAW;IACjB,QAAQ;IACR,KAAK,YAAY;KAWf,QAAO,MAVW,gBAChB,eAAe,MAAM,GACrB,aACA;MACE;MACA,aAAa,OAAO,mBAAmB;MACvC,cAAc,OAAO,iBAAiB,CAAC;KACzC,GACA;MAAE;MAAO,UAAU,IAAIC,WAAS;MAAG;KAAS,CAC9C,GACW;IACb;GACF;EACF;CACF;CAEA,IAAI,OAAO,MAAM;EACf,MAAM,OAAO,OAAO;EACpB,MAAM,OAAO,UAAU,OAAO,GAAG;EACjC,MAAM,MAAM,KAAK;EACjB,IAAI,KACF,QAAQ,WAAW;GAAE,QAAQ;GAAoB,WAAW,IAAI;IAAE;IAAM;GAAK,CAAC;EAAE;OAC3E;GACL,IAAI,CAAC,OAAO,cAAc;IACxB,GAAG,IAAI,6CAA6C;IACpD,OAAO;GACT;GACA,MAAM,WAAW,OAAO;GACxB,MAAM,WAAW,oBAAoB,MAAM;GAG3C,MAAM,QAAQ,IAAID,gBAChB,YAAY,KAAK,OAAO,GAAG,uBAAuB,CAAC,GACnD,QACF;GACA,QAAQ,WAAW;IACjB,QAAQ;IACR,KAAK,YAAY;KACf,MAAM,EAAE,cAAc,MAAM,sBAC1B;MAAE;MAAM;KAAK,GACb;MAAE,sBAAsB,wBAAwB,MAAM;MAAG;MAAO;KAAS,CAC3E;KACA,MAAM,MAAM,MAAM,IAAI,SAAS,GAAG;KAClC,IAAI,CAAC,KAAK,MAAM,IAAI,MAAM,yCAAyC;KACnE,OAAO,wBAAwB,KAAK,UAAU,CAAC,CAAC,EAAE;IACpD;GACF;EACF;CACF;CAEA,IAAI,OAAO,KAAK,OAAO,EAAE,WAAW,GAAG;EACrC,GAAG,IACD,8FACF;EACA,OAAO;CACT;CAEA,MAAM,EAAE,YAAY,MAAM,YAAY,SAAS,EAC7C,QAAQ,EAAiB,cAAsC,EACjE,CAAC;CACD,aAAa,IAAI,SAAS,OAAO,IAAI;CACrC,OAAO,QAAQ,OAAO;AACxB;;AAGA,SAAS,UAAU,OAAqD;CACtE,MAAM,OAA+B,CAAC;CACtC,KAAK,MAAM,KAAK,SAAS,CAAC,GAAG;EAC3B,MAAM,IAAI,EAAE,QAAQ,GAAG;EACvB,IAAI,IAAI,GAAG,KAAK,EAAE,MAAM,GAAG,CAAC,KAAK,EAAE,MAAM,IAAI,CAAC;CAChD;CACA,OAAO;AACT;;AAGA,SAAS,oBAAoB,QAIT;CAClB,MAAM,WAA4B,CAAC;CACnC,IAAI,OAAO,SAAS,SAAS,UAAU,KAAK,MAAM,aAAa,OAAO,SAAS,MAAM,CAAC;CACtF,IAAI,OAAO,SACT,SAAS,UAAU;EACjB,cAAc,OAAO,uBAAuB;EAC5C,KAAK,aAAa,OAAO,SAAS,MAAM;CAC1C;CAEF,OAAO;AACT;;;AAIA,eAAe,wBAAwB,QAMX;CAC1B,MAAM,OAAO,IAAI,YAAY,EAAE,cAAc,OAAO,iBAAiB,CAAC,EAAE,CAAC;CACzE,MAAM,QAAQ,MAAM,gBAAgB,EAAE,cAAc,OAAO,oBAAoB,MAAM,CAAC;CACtF,MAAM,SAAS,YAAY,KAAK,OAAO,GAAG,uBAAuB,CAAC;CAClE,MAAM,UAAU,IAAI,eAAe;EACjC;EACA;EACA,QAAQ,eAAe,cAAc,OAAO,MAAM,GAAG;GACnD,UAAU,CAAC,OAAO;GAClB,aAAa,MAAM;GACnB,WAAW,OAAO,iBAAiB;EACrC,CAAC;CACH,CAAC;CACD,OAAO;EACL;EACA;EACA,SAAS,MAAM;EACf,QAAQ,EAAE,OAAO;EACjB,UAAU,YAAY;GACpB,MAAM,QAAQ,SAAS;GACvB,MAAM,MAAM,MAAM;EACpB;CACF;AACF;AAEA,SAAS,iBAAiB,MAAgB,IAAmB;CAC3D,MAAM,EAAE,WAAW,UAAU;EAC3B;EACA,SAAS;GACP,UAAU,EAAE,MAAM,SAAS;GAC3B,QAAQ,EAAE,MAAM,SAAS;GACzB,UAAU,EAAE,MAAM,SAAS;GAC3B,MAAM,EAAE,MAAM,SAAS;GACvB,uBAAuB,EAAE,MAAM,UAAU;GACzC,OAAO,EAAE,MAAM,SAAS;GACxB,QAAQ,EAAE,MAAM,SAAS;GACzB,oBAAoB,EAAE,MAAM,SAAS;GACrC,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CAED,MAAM,gBAAgB,OAAO;CAC7B,IAAI,kBAAkB,KAAA,KAAa,CAAC,WAAW,SAAS,aAAa,GAAG;EACtE,GAAG,IAAI,qCAAqC,WAAW,KAAK,GAAG,EAAE,GAAG;EACpE,OAAO;CACT;CAEA,MAAM,YAAY,MAAuB,KAAK,MAAM,aAAa,GAAG,MAAM,CAAC;CAC3E,MAAM,SAAwB,CAAC;CAE/B,IAAI,OAAO,UAAU;EACnB,MAAM,IAAI,SAAS,OAAO,QAAQ;EAElC,OAAO,WAAW,oBADF,MAAM,QAAQ,CAAC,IAAI,IAAK,EAAE,WAAW,CAAC,GAGpD,OAAO,WAAW,QAAQ,QAAQ,kBACpC;CACF;CACA,IAAI,OAAO,UACT,OAAO,WAAW,iBAChB,SAAS,OAAO,QAAQ,CAC1B;CAEF,IAAI,OAAO,MACT,OAAO,OAAO,qBACZ,SAAS,OAAO,IAAI,GACpB,EAAE,mBAAmB,OAAO,0BAA0B,MAAM,CAC9D;CAEF,IAAI,OAAO,OACT,OAAO,QAAQ,kBACb,SAAS,OAAO,KAAK,CACvB;CAEF,IAAI,OAAO,QACT,OAAO,SAAS,oBACd,SAAS,OAAO,MAAM,CACxB;CAGF,MAAM,UAAU,eAAe,QAAQ,EAAiB,cAAsC,CAAC;CAC/F,aAAa,IAAI,SAAS,OAAO,IAAI;CACrC,OAAO,QAAQ,OAAO;AACxB;;;AC3eA,MAAM,OAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAuDb,eAAsB,IAAI,MAAgB,IAA4B;CACpE,MAAM,CAAC,SAAS,GAAG,QAAQ;CAC3B,QAAQ,SAAR;EACE,KAAK,UACH,OAAO,UAAU,MAAM,EAAE;EAC3B,KAAK,OACH,OAAO,OAAO,MAAM,EAAE;EACxB,KAAK,YACH,OAAO,YAAY,MAAM,EAAE;EAC7B,KAAK,UACH,OAAO,UAAU,MAAM,EAAE;EAC3B,KAAK,OACH,OAAO,OAAO,MAAM,EAAE;EACxB,KAAK,WACH,OAAO,WAAW,MAAM,EAAE;EAC5B,KAAK,UACH,OAAO,UAAU,MAAM,EAAE;EAC3B,KAAK,YACH,OAAO,YAAY,MAAM,EAAE;EAC7B,KAAK,SACH,OAAO,SAAS,MAAM,EAAE;EAC1B,KAAK,QACH,OAAO,QAAQ,MAAM,EAAE;EACzB,KAAK,OACH,OAAO,OAAO,MAAM,EAAE;EACxB,KAAK,UACH,OAAO,UAAU,MAAM,EAAE;EAC3B,KAAK;EACL,KAAK;EACL,KAAK;GACH,GAAG,IAAI,IAAI;GACX,OAAO;EACT,KAAK,KAAA;GACH,GAAG,IAAI,IAAI;GACX,OAAO;EACT;GACE,GAAG,IAAI,oBAAoB,QAAQ,GAAG;GACtC,GAAG,IAAI,IAAI;GACX,OAAO;CACX;AACF;AAEA,SAAS,UAAU,WAA+B,IAAyC;CACzF,MAAM,OAAO,aAAa,GAAG,KAAK;CAClC,IAAI,CAAC,MAAM;EACT,GAAG,IAAI,8DAA8D;EACrE,OAAO;CACT;CACA,OAAO,OAAO,IAAI;AACpB;AAEA,eAAe,UAAU,MAAgB,IAA4B;CACnE,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GACP,OAAO;IAAE,MAAM;IAAU,OAAO;GAAI;GACpC,SAAS;IAAE,MAAM;IAAU,OAAO;GAAI;GACtC,SAAS,EAAE,MAAM,SAAS;GAC1B,WAAW,EAAE,MAAM,SAAS;GAC5B,SAAS;IAAE,MAAM;IAAU,OAAO;GAAI;GACtC,WAAW,EAAE,MAAM,SAAS;GAC5B,MAAM,EAAE,MAAM,SAAS;GACvB,OAAO,EAAE,MAAM,SAAS;GACxB,MAAM,EAAE,MAAM,UAAU;EAC1B;CACF,CAAC;CACD,MAAM,QAAQ,YAAY,KAAK,GAAG,EAAE,KAAK;CACzC,IAAI,CAAC,OAAO;EACV,GAAG,IAAI,wBAAwB;EAC/B,OAAO;CACT;CACA,MAAM,KAAK,UAAU,OAAO,OAAO,EAAE;CACrC,IAAI,CAAC,IAAI,OAAO;CAEhB,IAAI;EAEF,IAAI,mBAAmB,OAAO;EAC9B,IAAI;EACJ,IAAI,CAAC,OAAO,YAAY,OAAO,aAAa,OAAO,YAAY,OAAO,SAAS;GAC7E,IAAI,YAAY,OAAO;GACvB,IAAI,CAAC,aAAa,OAAO,SAAS;IAIhC,YAHiB,uBAAuB,OAAO,SAAS,OAAO,SAAS,EACtE,WAAW,OAAO,UACpB,CACmB,EAAE,WAAW,KAAA;IAChC,IAAI,CAAC,WAAW,OAAO,oBAAoB,OAAO,QAAQ,MAAM,OAAO;GACzE;GACA,IAAI,WAAW;IACb,MAAM,MAAM,eAAe,aAAa,IAAI,OAAO,OAAO,GAAG,SAAS;IACtE,OAAO,IAAI;IACX,IAAI,IAAI,UAAU,mBAAmB,IAAI;GAC3C;EACF;EAEA,IAAI;EACJ,IAAI,GAAG,UACL,IAAI;GACF,cAAc,MAAM,GAAG,SAAS,MAAM,KAAK;EAC7C,QAAQ;GACN,cAAc,KAAA;EAChB;EAGF,MAAM,UAAU,WAAW,IAAI,OAAO;GACpC,SAAS,OAAO;GAChB,SAAS;GACT,MAAM,OAAO;GACb,OAAO,OAAO,QAAQ,OAAO,OAAO,KAAK,IAAI,KAAA;GAC7C;EACF,CAAC;EAED,IAAI,OAAO,MAAM;GACf,GAAG,IACD,GAAG,KAAK,UAAU;IAAE;IAAO,SAAS,oBAAoB;IAAM;IAAM;GAAQ,GAAG,MAAM,CAAC,EAAE,GAC1F;GACA,OAAO;EACT;EACA,IAAI,MAAM,GAAG,IAAI,GAAG,KAAK,GAAG;EAC5B,IAAI,QAAQ,WAAW,GAAG;GACxB,GAAG,IAAI,cAAc;GACrB,OAAO;EACT;EACA,KAAK,MAAM,KAAK,SAAS;GACvB,MAAM,MAAM,EAAE,SAAS,MAAM,EAAE,OAAO,KAAK;GAC3C,GAAG,IAAI,GAAG,EAAE,QAAQ,KAAK,EAAE,QAAQ,IAAI,KAAK,EAAE,QAAQ,IAAI,GAAG;GAC7D,GAAG,IAAI,OAAO,EAAE,QAAQ,GAAG;GAC3B,GAAG,IAAI,uBAAuB,EAAE,GAAG,GAAG;EACxC;EACA,OAAO;CACT,UAAU;EACR,GAAG,MAAM;CACX;AACF;AAEA,SAAS,OAAO,MAAgB,IAAmB;CACjD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,OAAO;IAAE,MAAM;IAAU,OAAO;GAAI;GAAG,MAAM,EAAE,MAAM,UAAU;EAAE;CAC9E,CAAC;CACD,MAAM,KAAK,OAAO,YAAY,EAAE;CAChC,IAAI,CAAC,OAAO,UAAU,EAAE,GAAG;EACzB,GAAG,IAAI,0BAA0B;EACjC,OAAO;CACT;CACA,MAAM,KAAK,UAAU,OAAO,OAAO,EAAE;CACrC,IAAI,CAAC,IAAI,OAAO;CAChB,IAAI;EACF,MAAM,MAAM,OAAO,IAAI,EAAE;EACzB,IAAI,CAAC,KAAK;GACR,GAAG,IAAI,uBAAuB,GAAG,GAAG;GACpC,OAAO;EACT;EACA,IAAI,OAAO,MAAM;GACf,GAAG,IAAI,GAAG,KAAK,UAAU,KAAK,MAAM,CAAC,EAAE,GAAG;GAC1C,OAAO;EACT;EACA,GAAG,IAAI,GAAG,IAAI,MAAM,KAAK,IAAI,QAAQ,IAAI,KAAK,IAAI,QAAQ,GAAG,IAAI,QAAQ,GAAG;EAC5E,IAAI,IAAI,aAAa,GAAG,IAAI,GAAG,IAAI,YAAY,GAAG;EAClD,IAAI,IAAI,KAAK,GAAG,IAAI,GAAG,IAAI,IAAI,GAAG;EAClC,GAAG,IAAI,KAAK,IAAI,KAAK,GAAG;EACxB,IAAI,IAAI,aAAa,GAAG,IAAI,OAAO,IAAI,YAAY,GAAG;EACtD,OAAO;CACT,UAAU;EACR,GAAG,MAAM;CACX;AACF;AAEA,SAAS,YAAY,MAAgB,IAAmB;CACtD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS,EAAE,OAAO;GAAE,MAAM;GAAU,OAAO;EAAI,EAAE;CACnD,CAAC;CACD,MAAM,UAAU,YAAY;CAC5B,IAAI,CAAC,SAAS;EACZ,GAAG,IAAI,4BAA4B;EACnC,OAAO;CACT;CACA,MAAM,KAAK,UAAU,OAAO,OAAO,EAAE;CACrC,IAAI,CAAC,IAAI,OAAO;CAChB,IAAI;EACF,MAAM,WAAW,aAAa,IAAI,OAAO;EACzC,GAAG,IAAI,SAAS,SAAS,GAAG,SAAS,KAAK,IAAI,EAAE,MAAM,2BAA2B,QAAQ,GAAG;EAC5F,OAAO;CACT,UAAU;EACR,GAAG,MAAM;CACX;AACF;AAEA,SAAS,UAAU,MAAgB,IAAmB;CACpD,MAAM,EAAE,QAAQ,gBAAgB,UAAU;EACxC;EACA,kBAAkB;EAClB,SAAS;GAAE,OAAO;IAAE,MAAM;IAAU,OAAO;GAAI;GAAG,WAAW,EAAE,MAAM,SAAS;EAAE;CAClF,CAAC;CACD,MAAM,CAAC,SAAS,WAAW;CAC3B,IAAI,CAAC,WAAW,CAAC,SAAS;EACxB,GAAG,IAAI,oCAAoC;EAC3C,OAAO;CACT;CACA,MAAM,KAAK,UAAU,OAAO,OAAO,EAAE;CACrC,IAAI,CAAC,IAAI,OAAO;CAChB,IAAI;EACF,MAAM,WAAW,uBAAuB,SAAS,SAAS,EACxD,WAAW,OAAO,UACpB,CAAC;EACD,MAAM,MAAM,eAAe,aAAa,IAAI,OAAO,GAAG,SAAS,WAAW,EAAE;EAC5E,GAAG,IAAI,aAAa,SAAS,WAAW,SAAS,IAAI,SAAS,OAAO,IAAI;EACzE,GAAG,IAAI,aAAa,IAAI,YAAY,SAAS,GAAG;EAChD,GAAG,IAAI,GAAG,IAAI,KAAK,GAAG;EACtB,OAAO;CACT,UAAU;EACR,GAAG,MAAM;CACX;AACF"}
|