@bensandee/tooling 0.89.0 → 0.90.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bin.mjs +590 -384
- package/package.json +4 -4
- package/tooling.schema.json +5 -1
package/dist/bin.mjs
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
import { accessSync, appendFileSync, closeSync, constants, copyFileSync, existsSync, fstatSync, lstatSync, mkdirSync, mkdtempSync, openSync, readFileSync, readSync, readdirSync, readlinkSync, realpathSync, renameSync, rmSync, statSync, symlinkSync, unlinkSync, writeFileSync, writeSync } from "node:fs";
|
|
3
|
-
import * as path$1 from "node:path";
|
|
4
|
-
import path from "node:path";
|
|
3
|
+
import path, * as path$1 from "node:path";
|
|
5
4
|
import { parseArgs, parseEnv } from "node:util";
|
|
6
5
|
import { FatalError, TransientError, UnexpectedError, describeError, describeError as describeError$1, redact, redact as redact$1 } from "@bensandee/common";
|
|
7
6
|
import { defineCommand, renderUsage, runCommand, runMain } from "citty";
|
|
@@ -176,7 +175,7 @@ function loadEnvFileForBin(rawArgs, bin, io = processIo) {
|
|
|
176
175
|
//#region src/env-file-preload.ts
|
|
177
176
|
const envFileLoad = loadEnvFileForBin(process.argv.slice(2), {
|
|
178
177
|
name: "bst",
|
|
179
|
-
version: "0.
|
|
178
|
+
version: "0.90.0"
|
|
180
179
|
});
|
|
181
180
|
//#endregion
|
|
182
181
|
//#region ../cli-kit/src/logger.ts
|
|
@@ -828,7 +827,7 @@ const DockerImageOverrideSchema = z.strictObject({
|
|
|
828
827
|
buildArgs: z.record(z.string(), z.string()).optional().meta({ description: "Build args passed to `docker build` for this package. Values support ${VAR} and ${VAR:-default} expansion against process.env." }),
|
|
829
828
|
imageName: z.string().min(1).optional().meta({ description: "Image name used for docker:build tags, docker:publish refs, and docker:check cross-referencing. Falls back to the derived name: the package.json name for the root package (npm scope stripped), or {root-name}-{package-name} for a monorepo package. A value that already carries a registry host (e.g. 'ghcr.io/me/app') is used as written by docker:publish, with no registryNamespace prefix added, and must name the registry this run logs in to -- one naming any other host refuses before login." }),
|
|
830
829
|
version: z.string().optional().meta({ description: "Version used for docker:publish tags; overrides the version resolved from the enclosing package." }),
|
|
831
|
-
publish: z.boolean().optional().meta({ description: "The publish decision either way: true keeps an image published -- including one
|
|
830
|
+
publish: z.boolean().optional().meta({ description: "The publish decision either way: true keeps an image published -- including one whose compose service is declared only in the check overlay, which is not published by default -- and false excludes it while publishDocker stays true. Unset means the discovery default, which publishes everything except a check-only image." })
|
|
832
831
|
});
|
|
833
832
|
const DockerMapSchema = z.record(z.string(), DockerImageOverrideSchema);
|
|
834
833
|
const TolerantDockerMapSchema = z.record(z.string(), tolerantBlock(DockerImageOverrideSchema));
|
|
@@ -1701,6 +1700,7 @@ const LintSweepConfigSchema = z.strictObject({
|
|
|
1701
1700
|
});
|
|
1702
1701
|
const AgentEgressConfigSchema = z.strictObject({ browseHosts: z.array(z.string().min(1)).optional().meta({ description: "Host patterns this repo's agent containers may fetch from, on top of the hosts every run needs: an exact host (`fastdl.mongodb.org`) or a wildcard over its leftmost label (`*.example.com`). No ports. These join the browse lane, which serves GET and HEAD only." }) });
|
|
1703
1702
|
const AgentConfigSchema = z.strictObject({
|
|
1703
|
+
enabled: z.boolean().optional().meta({ description: "The repo's explicit consent to the agent (default false). Only `true`, read from the repo's **default branch**, lets the agent work the repo: claim units, run sweeps, recover orphans, merge, act on a chat proposal or start a new spec. A missing key, `false`, a missing `.tooling.json` or a read that fails all mean not enabled, and the answer is re-read within about a minute. Every other `agent.*` key below has no effect without this one; `repo:sync` warns when the block sets one of them and this key is not `true`. Where this is `true`, `repo:sync` also installs `@bensandee/agent-cli`. Provisioning the agent's labels is not consent, and is never gated by this key." }),
|
|
1704
1704
|
autonomy: z.boolean().optional().meta({ description: "Opt into interior autonomy (default false). When a phase's latest rationale reports readiness \"ready\" with an empty openQuestions[] and the review phase is clean, the agent applies the existing plan -> implement -> review -> park-at-mergeable advance itself instead of parking for a human. Never applies to the design/spec gate or the final merge from the mergeable terminal -- those always wait on a human. Also arms the trunk-red detector: when this repo's default branch combined status settles red, the agent files a tracking issue naming the failing checks and labels it agent/spec, starting the fix through the ordinary spec/plan/implement/review pipeline. It also closes that issue, with a comment, if the default branch recovers on its own before a human acts on it. Also arms the world-changed retrigger sweep: a pull request labelled agent-flags/autopilot that is parked at a -stuck or -failed terminal is re-queued when the fact its park recorded stops being true (the default branch went green, or moved past a conflicted base)." }),
|
|
1705
1705
|
preRunRebase: z.boolean().optional().meta({ description: "Merge the current default branch into the work branch before the implement (execute) phase's container starts (default true). A clean merge or an already-up-to-date branch runs the container as is; a conflicting merge is aborted, recorded on the run's status comment, and the run proceeds on the un-synced branch -- it never fails the run. Two consecutive conflicting attempts hand the unit to agent/repair before any container runs; a timeout or a failed merge never counts toward that pair. Set false to skip the attempt entirely for this repo: no fetch, no merge, no abort, and the branch is worked exactly as cloned." }),
|
|
1706
1706
|
backlog: z.boolean().optional().meta({ description: "Whether the agent may self-trigger backlog runs consuming this repo's .agent/findings/ ledger (default: on wherever the ledger exists, which only happens in a repo whose own review loop wrote it). A backlog run opens a pull request that fixes or refutes the pending findings; false disarms it, leaving the ledger to accumulate for a human. A run starts only once at least three findings are pending or one is older than seven days." }),
|
|
@@ -1938,6 +1938,11 @@ function resolveOperationalRepo(cwd) {
|
|
|
1938
1938
|
function resolveOperationalRepoUrl(cwd) {
|
|
1939
1939
|
return resolveRepoUrlFrom(() => readOriginUrl(cwd), () => readPackageRepositoryUrl(cwd));
|
|
1940
1940
|
}
|
|
1941
|
+
function repositoryFromRemoteUrl(remoteUrl) {
|
|
1942
|
+
const url = normalizeGitUrl(remoteUrl.trim());
|
|
1943
|
+
if (url === null) return null;
|
|
1944
|
+
return parseGitUrl(url)?.repository ?? null;
|
|
1945
|
+
}
|
|
1941
1946
|
function parseRepositoryUrl(cwd) {
|
|
1942
1947
|
const urlStr = readPackageRepositoryUrl(cwd);
|
|
1943
1948
|
return urlStr === null ? null : parseGitUrl(urlStr);
|
|
@@ -3370,7 +3375,7 @@ function localTarget(call, entry) {
|
|
|
3370
3375
|
}
|
|
3371
3376
|
//#endregion
|
|
3372
3377
|
//#region src/release/docker-check-only-phase.ts
|
|
3373
|
-
const DOCKER_CHECK_ONLY_PHASE = "
|
|
3378
|
+
const DOCKER_CHECK_ONLY_PHASE = "enforce";
|
|
3374
3379
|
//#endregion
|
|
3375
3380
|
//#region src/release/docker.ts
|
|
3376
3381
|
function defaultPublish(checkOnlyIn, phase) {
|
|
@@ -3811,7 +3816,7 @@ function runDockerBuild(executor, config) {
|
|
|
3811
3816
|
log$1.info(`Built ${pkg.imageName}:latest`);
|
|
3812
3817
|
return { packages: [pkg] };
|
|
3813
3818
|
}
|
|
3814
|
-
const packages = detectDockerPackages(executor, config.cwd, repoName, config.checkOnlyPhase ?? "
|
|
3819
|
+
const packages = detectDockerPackages(executor, config.cwd, repoName, config.checkOnlyPhase ?? "enforce");
|
|
3815
3820
|
if (packages.length === 0) {
|
|
3816
3821
|
log$1.info("No packages with docker config found");
|
|
3817
3822
|
return { packages: [] };
|
|
@@ -3971,7 +3976,7 @@ function reportCheckOnlyImages(packages, phase) {
|
|
|
3971
3976
|
}
|
|
3972
3977
|
}
|
|
3973
3978
|
function runDockerPublish(executor, config) {
|
|
3974
|
-
const checkOnlyPhase = config.checkOnlyPhase ?? "
|
|
3979
|
+
const checkOnlyPhase = config.checkOnlyPhase ?? "enforce";
|
|
3975
3980
|
const { packages } = runDockerBuild(executor, {
|
|
3976
3981
|
cwd: config.cwd,
|
|
3977
3982
|
packageDir: void 0,
|
|
@@ -4343,7 +4348,7 @@ function removeLefthookCommand(existing, name, expectedRun) {
|
|
|
4343
4348
|
};
|
|
4344
4349
|
}
|
|
4345
4350
|
}
|
|
4346
|
-
function normalizeWorkflow(content) {
|
|
4351
|
+
function normalizeWorkflow(content, owned = []) {
|
|
4347
4352
|
const withoutCustom = stripCustomBlocks(content);
|
|
4348
4353
|
const doc = parseDocument(withoutCustom);
|
|
4349
4354
|
doc.comment = null;
|
|
@@ -4354,7 +4359,11 @@ function normalizeWorkflow(content) {
|
|
|
4354
4359
|
if ("commentBefore" in node) node.commentBefore = null;
|
|
4355
4360
|
},
|
|
4356
4361
|
Pair(_key, node) {
|
|
4357
|
-
if (isScalar(node.key) && node.key.value === "uses" && isScalar(node.value) && typeof node.value.value === "string")
|
|
4362
|
+
if (isScalar(node.key) && node.key.value === "uses" && isScalar(node.value) && typeof node.value.value === "string") {
|
|
4363
|
+
const name = node.value.value.replace(/@.*$/, "");
|
|
4364
|
+
if (owned.some((action) => action.name === name)) return;
|
|
4365
|
+
node.value.value = name;
|
|
4366
|
+
}
|
|
4358
4367
|
}
|
|
4359
4368
|
});
|
|
4360
4369
|
return doc.toString({
|
|
@@ -4430,11 +4439,11 @@ function buildWorkflowYaml(options) {
|
|
|
4430
4439
|
}
|
|
4431
4440
|
//#endregion
|
|
4432
4441
|
//#region src/generators/mise-pin.ts
|
|
4433
|
-
const MISE_VERSION = "2026.10.
|
|
4434
|
-
const MISE_LINUX_X64_SHA256 = "
|
|
4442
|
+
const MISE_VERSION = "2026.10.8";
|
|
4443
|
+
const MISE_LINUX_X64_SHA256 = "c72477ae6c3a8e7d817a322f43da70e4643e75ee5c21265f1c19c894273b7428";
|
|
4435
4444
|
const SETUP_MISE_ACTION_URL = "https://code.orangebikelabs.com/bensandee/common/actions/setup-mise";
|
|
4436
4445
|
const SETUP_MISE_ACTION_TAG = "setup-mise@latest";
|
|
4437
|
-
const SETUP_MISE_ACTION_SHA = "
|
|
4446
|
+
const SETUP_MISE_ACTION_SHA = "ebe622ef0d24c7efec4a5f6093ddb18500900e24";
|
|
4438
4447
|
//#endregion
|
|
4439
4448
|
//#region src/generators/ci-utils.ts
|
|
4440
4449
|
function actionsExpr(expr) {
|
|
@@ -4446,7 +4455,7 @@ const IS_NOT_MAIN_BRANCH = `github.ref != '${MAIN_BRANCH_REF}'`;
|
|
|
4446
4455
|
const IS_MAIN_JOB_ENV = { IS_MAIN: actionsExpr(IS_MAIN_BRANCH) };
|
|
4447
4456
|
const IS_MAIN_ENV_GUARD = "env.IS_MAIN == 'true'";
|
|
4448
4457
|
function onlyOnDefaultBranch(condition) {
|
|
4449
|
-
return `${IS_MAIN_BRANCH} && ${condition}`;
|
|
4458
|
+
return `${IS_MAIN_BRANCH} && (${condition})`;
|
|
4450
4459
|
}
|
|
4451
4460
|
function npmrcAuthKey(registryUrl) {
|
|
4452
4461
|
return `${registryUrl.replace(/^https?:/i, "").replace(/\/+$/, "")}/`;
|
|
@@ -4770,6 +4779,16 @@ function resolveHealthConfig(targetDir) {
|
|
|
4770
4779
|
config: { stack }
|
|
4771
4780
|
}, { isMonorepo });
|
|
4772
4781
|
}
|
|
4782
|
+
function healthOverridesAt(targetDir) {
|
|
4783
|
+
const full = path.join(targetDir, ".tooling.json");
|
|
4784
|
+
let raw;
|
|
4785
|
+
if (existsSync(full)) try {
|
|
4786
|
+
raw = readFileSync(full, "utf-8");
|
|
4787
|
+
} catch (_error) {
|
|
4788
|
+
raw = void 0;
|
|
4789
|
+
}
|
|
4790
|
+
return parseToolingConfigSlice(raw, ToolingShallowSchema$2, { block: "health" })?.health;
|
|
4791
|
+
}
|
|
4773
4792
|
//#endregion
|
|
4774
4793
|
//#region src/utils/script-forwarding.ts
|
|
4775
4794
|
function commandSegments(script) {
|
|
@@ -4839,6 +4858,39 @@ function diagnoseCheckScriptForwardingAt(targetDir) {
|
|
|
4839
4858
|
return diagnoseCheckScriptForwarding(scripts);
|
|
4840
4859
|
}
|
|
4841
4860
|
//#endregion
|
|
4861
|
+
//#region src/generators/agent-cli-dep.ts
|
|
4862
|
+
const AGENT_CLI_PACKAGE = "@bensandee/agent-cli";
|
|
4863
|
+
const AgentEnabledSliceSchema = z.looseObject({ agent: z.looseObject({ enabled: z.boolean().optional() }).optional() });
|
|
4864
|
+
function agentEnabled(ctx) {
|
|
4865
|
+
return parseToolingConfigSlice(ctx.read(".tooling.json"), AgentEnabledSliceSchema, { block: "agent" })?.agent?.enabled === true;
|
|
4866
|
+
}
|
|
4867
|
+
function wantsAgentCli(ctx) {
|
|
4868
|
+
if (!agentEnabled(ctx)) return false;
|
|
4869
|
+
if (isWorkspacePackage(ctx, "@bensandee/agent-cli")) return false;
|
|
4870
|
+
return !readUnmanagedDevDepNames(ctx).has(AGENT_CLI_PACKAGE);
|
|
4871
|
+
}
|
|
4872
|
+
function isWorkspacePackage(ctx, packageName) {
|
|
4873
|
+
if (ctx.config.structure !== "monorepo") return false;
|
|
4874
|
+
const packagesDir = path.join(ctx.targetDir, "packages");
|
|
4875
|
+
if (!existsSync(packagesDir)) return false;
|
|
4876
|
+
try {
|
|
4877
|
+
for (const entry of readdirSync(packagesDir, { withFileTypes: true })) {
|
|
4878
|
+
if (!entry.isDirectory()) continue;
|
|
4879
|
+
const pkgJsonPath = path.join(packagesDir, entry.name, "package.json");
|
|
4880
|
+
if (!existsSync(pkgJsonPath)) continue;
|
|
4881
|
+
try {
|
|
4882
|
+
if (parsePackageJson(readFileSync(pkgJsonPath, "utf-8"))?.name === packageName) return true;
|
|
4883
|
+
} catch (_error) {}
|
|
4884
|
+
}
|
|
4885
|
+
} catch (_error) {}
|
|
4886
|
+
return false;
|
|
4887
|
+
}
|
|
4888
|
+
const UnmanagedSliceSchema = z.object({ unmanagedDevDependencies: UnmanagedDevDependenciesSchema.optional() });
|
|
4889
|
+
function readUnmanagedDevDepNames(ctx) {
|
|
4890
|
+
const slice = parseToolingConfigSlice(ctx.read(".tooling.json"), UnmanagedSliceSchema, { block: "unmanagedDevDependencies" });
|
|
4891
|
+
return new Set(slice?.unmanagedDevDependencies ?? []);
|
|
4892
|
+
}
|
|
4893
|
+
//#endregion
|
|
4842
4894
|
//#region src/generators/package-json.ts
|
|
4843
4895
|
const NODE_ENGINES_FLOOR = "24.13.0";
|
|
4844
4896
|
const ENGINES_NODE = `>=${NODE_ENGINES_FLOOR}`;
|
|
@@ -4947,18 +4999,18 @@ function perPackageDevDeps(config) {
|
|
|
4947
4999
|
"@types/node": "24.19.1",
|
|
4948
5000
|
"@vitest/coverage-v8": "5.0.3",
|
|
4949
5001
|
"commit-and-tag-version": "13.2.1",
|
|
4950
|
-
"knip": "6.
|
|
4951
|
-
"lefthook": "2.1
|
|
4952
|
-
"modern-web-guidance": "0.0.
|
|
4953
|
-
"oxfmt": "0.
|
|
4954
|
-
"oxlint": "1.
|
|
5002
|
+
"knip": "6.41.0",
|
|
5003
|
+
"lefthook": "2.2.1",
|
|
5004
|
+
"modern-web-guidance": "0.0.193",
|
|
5005
|
+
"oxfmt": "0.72.0",
|
|
5006
|
+
"oxlint": "1.87.0",
|
|
4955
5007
|
"oxlint-tsgolint": "7.0.2003",
|
|
4956
5008
|
"prettier": "3.9.9",
|
|
4957
|
-
"release-it": "21.1.
|
|
5009
|
+
"release-it": "21.1.1",
|
|
4958
5010
|
"tsdown": "0.23.0",
|
|
4959
5011
|
"typescript": "6.0.3",
|
|
4960
5012
|
"vitest": "5.0.3",
|
|
4961
|
-
"pnpm": "11.28.
|
|
5013
|
+
"pnpm": "11.28.5"
|
|
4962
5014
|
}["typescript"];
|
|
4963
5015
|
deps["@types/node"] = {
|
|
4964
5016
|
"@changesets/cli": "3.0.3",
|
|
@@ -4966,18 +5018,18 @@ function perPackageDevDeps(config) {
|
|
|
4966
5018
|
"@types/node": "24.19.1",
|
|
4967
5019
|
"@vitest/coverage-v8": "5.0.3",
|
|
4968
5020
|
"commit-and-tag-version": "13.2.1",
|
|
4969
|
-
"knip": "6.
|
|
4970
|
-
"lefthook": "2.1
|
|
4971
|
-
"modern-web-guidance": "0.0.
|
|
4972
|
-
"oxfmt": "0.
|
|
4973
|
-
"oxlint": "1.
|
|
5021
|
+
"knip": "6.41.0",
|
|
5022
|
+
"lefthook": "2.2.1",
|
|
5023
|
+
"modern-web-guidance": "0.0.193",
|
|
5024
|
+
"oxfmt": "0.72.0",
|
|
5025
|
+
"oxlint": "1.87.0",
|
|
4974
5026
|
"oxlint-tsgolint": "7.0.2003",
|
|
4975
5027
|
"prettier": "3.9.9",
|
|
4976
|
-
"release-it": "21.1.
|
|
5028
|
+
"release-it": "21.1.1",
|
|
4977
5029
|
"tsdown": "0.23.0",
|
|
4978
5030
|
"typescript": "6.0.3",
|
|
4979
5031
|
"vitest": "5.0.3",
|
|
4980
|
-
"pnpm": "11.28.
|
|
5032
|
+
"pnpm": "11.28.5"
|
|
4981
5033
|
}["@types/node"];
|
|
4982
5034
|
}
|
|
4983
5035
|
if (config.builder === "tsdown") deps["tsdown"] = {
|
|
@@ -4986,18 +5038,18 @@ function perPackageDevDeps(config) {
|
|
|
4986
5038
|
"@types/node": "24.19.1",
|
|
4987
5039
|
"@vitest/coverage-v8": "5.0.3",
|
|
4988
5040
|
"commit-and-tag-version": "13.2.1",
|
|
4989
|
-
"knip": "6.
|
|
4990
|
-
"lefthook": "2.1
|
|
4991
|
-
"modern-web-guidance": "0.0.
|
|
4992
|
-
"oxfmt": "0.
|
|
4993
|
-
"oxlint": "1.
|
|
5041
|
+
"knip": "6.41.0",
|
|
5042
|
+
"lefthook": "2.2.1",
|
|
5043
|
+
"modern-web-guidance": "0.0.193",
|
|
5044
|
+
"oxfmt": "0.72.0",
|
|
5045
|
+
"oxlint": "1.87.0",
|
|
4994
5046
|
"oxlint-tsgolint": "7.0.2003",
|
|
4995
5047
|
"prettier": "3.9.9",
|
|
4996
|
-
"release-it": "21.1.
|
|
5048
|
+
"release-it": "21.1.1",
|
|
4997
5049
|
"tsdown": "0.23.0",
|
|
4998
5050
|
"typescript": "6.0.3",
|
|
4999
5051
|
"vitest": "5.0.3",
|
|
5000
|
-
"pnpm": "11.28.
|
|
5052
|
+
"pnpm": "11.28.5"
|
|
5001
5053
|
}["tsdown"];
|
|
5002
5054
|
return deps;
|
|
5003
5055
|
}
|
|
@@ -5009,18 +5061,18 @@ function vitestDevDeps() {
|
|
|
5009
5061
|
"@types/node": "24.19.1",
|
|
5010
5062
|
"@vitest/coverage-v8": "5.0.3",
|
|
5011
5063
|
"commit-and-tag-version": "13.2.1",
|
|
5012
|
-
"knip": "6.
|
|
5013
|
-
"lefthook": "2.1
|
|
5014
|
-
"modern-web-guidance": "0.0.
|
|
5015
|
-
"oxfmt": "0.
|
|
5016
|
-
"oxlint": "1.
|
|
5064
|
+
"knip": "6.41.0",
|
|
5065
|
+
"lefthook": "2.2.1",
|
|
5066
|
+
"modern-web-guidance": "0.0.193",
|
|
5067
|
+
"oxfmt": "0.72.0",
|
|
5068
|
+
"oxlint": "1.87.0",
|
|
5017
5069
|
"oxlint-tsgolint": "7.0.2003",
|
|
5018
5070
|
"prettier": "3.9.9",
|
|
5019
|
-
"release-it": "21.1.
|
|
5071
|
+
"release-it": "21.1.1",
|
|
5020
5072
|
"tsdown": "0.23.0",
|
|
5021
5073
|
"typescript": "6.0.3",
|
|
5022
5074
|
"vitest": "5.0.3",
|
|
5023
|
-
"pnpm": "11.28.
|
|
5075
|
+
"pnpm": "11.28.5"
|
|
5024
5076
|
}["vitest"],
|
|
5025
5077
|
"@vitest/coverage-v8": {
|
|
5026
5078
|
"@changesets/cli": "3.0.3",
|
|
@@ -5028,18 +5080,18 @@ function vitestDevDeps() {
|
|
|
5028
5080
|
"@types/node": "24.19.1",
|
|
5029
5081
|
"@vitest/coverage-v8": "5.0.3",
|
|
5030
5082
|
"commit-and-tag-version": "13.2.1",
|
|
5031
|
-
"knip": "6.
|
|
5032
|
-
"lefthook": "2.1
|
|
5033
|
-
"modern-web-guidance": "0.0.
|
|
5034
|
-
"oxfmt": "0.
|
|
5035
|
-
"oxlint": "1.
|
|
5083
|
+
"knip": "6.41.0",
|
|
5084
|
+
"lefthook": "2.2.1",
|
|
5085
|
+
"modern-web-guidance": "0.0.193",
|
|
5086
|
+
"oxfmt": "0.72.0",
|
|
5087
|
+
"oxlint": "1.87.0",
|
|
5036
5088
|
"oxlint-tsgolint": "7.0.2003",
|
|
5037
5089
|
"prettier": "3.9.9",
|
|
5038
|
-
"release-it": "21.1.
|
|
5090
|
+
"release-it": "21.1.1",
|
|
5039
5091
|
"tsdown": "0.23.0",
|
|
5040
5092
|
"typescript": "6.0.3",
|
|
5041
5093
|
"vitest": "5.0.3",
|
|
5042
|
-
"pnpm": "11.28.
|
|
5094
|
+
"pnpm": "11.28.5"
|
|
5043
5095
|
}["@vitest/coverage-v8"]
|
|
5044
5096
|
};
|
|
5045
5097
|
}
|
|
@@ -5050,18 +5102,18 @@ function rootDevDeps(config) {
|
|
|
5050
5102
|
"@types/node": "24.19.1",
|
|
5051
5103
|
"@vitest/coverage-v8": "5.0.3",
|
|
5052
5104
|
"commit-and-tag-version": "13.2.1",
|
|
5053
|
-
"knip": "6.
|
|
5054
|
-
"lefthook": "2.1
|
|
5055
|
-
"modern-web-guidance": "0.0.
|
|
5056
|
-
"oxfmt": "0.
|
|
5057
|
-
"oxlint": "1.
|
|
5105
|
+
"knip": "6.41.0",
|
|
5106
|
+
"lefthook": "2.2.1",
|
|
5107
|
+
"modern-web-guidance": "0.0.193",
|
|
5108
|
+
"oxfmt": "0.72.0",
|
|
5109
|
+
"oxlint": "1.87.0",
|
|
5058
5110
|
"oxlint-tsgolint": "7.0.2003",
|
|
5059
5111
|
"prettier": "3.9.9",
|
|
5060
|
-
"release-it": "21.1.
|
|
5112
|
+
"release-it": "21.1.1",
|
|
5061
5113
|
"tsdown": "0.23.0",
|
|
5062
5114
|
"typescript": "6.0.3",
|
|
5063
5115
|
"vitest": "5.0.3",
|
|
5064
|
-
"pnpm": "11.28.
|
|
5116
|
+
"pnpm": "11.28.5"
|
|
5065
5117
|
}["lefthook"] };
|
|
5066
5118
|
if (config.stack !== "none") {
|
|
5067
5119
|
deps["knip"] = {
|
|
@@ -5070,18 +5122,18 @@ function rootDevDeps(config) {
|
|
|
5070
5122
|
"@types/node": "24.19.1",
|
|
5071
5123
|
"@vitest/coverage-v8": "5.0.3",
|
|
5072
5124
|
"commit-and-tag-version": "13.2.1",
|
|
5073
|
-
"knip": "6.
|
|
5074
|
-
"lefthook": "2.1
|
|
5075
|
-
"modern-web-guidance": "0.0.
|
|
5076
|
-
"oxfmt": "0.
|
|
5077
|
-
"oxlint": "1.
|
|
5125
|
+
"knip": "6.41.0",
|
|
5126
|
+
"lefthook": "2.2.1",
|
|
5127
|
+
"modern-web-guidance": "0.0.193",
|
|
5128
|
+
"oxfmt": "0.72.0",
|
|
5129
|
+
"oxlint": "1.87.0",
|
|
5078
5130
|
"oxlint-tsgolint": "7.0.2003",
|
|
5079
5131
|
"prettier": "3.9.9",
|
|
5080
|
-
"release-it": "21.1.
|
|
5132
|
+
"release-it": "21.1.1",
|
|
5081
5133
|
"tsdown": "0.23.0",
|
|
5082
5134
|
"typescript": "6.0.3",
|
|
5083
5135
|
"vitest": "5.0.3",
|
|
5084
|
-
"pnpm": "11.28.
|
|
5136
|
+
"pnpm": "11.28.5"
|
|
5085
5137
|
}["knip"];
|
|
5086
5138
|
deps["oxlint"] = {
|
|
5087
5139
|
"@changesets/cli": "3.0.3",
|
|
@@ -5089,18 +5141,18 @@ function rootDevDeps(config) {
|
|
|
5089
5141
|
"@types/node": "24.19.1",
|
|
5090
5142
|
"@vitest/coverage-v8": "5.0.3",
|
|
5091
5143
|
"commit-and-tag-version": "13.2.1",
|
|
5092
|
-
"knip": "6.
|
|
5093
|
-
"lefthook": "2.1
|
|
5094
|
-
"modern-web-guidance": "0.0.
|
|
5095
|
-
"oxfmt": "0.
|
|
5096
|
-
"oxlint": "1.
|
|
5144
|
+
"knip": "6.41.0",
|
|
5145
|
+
"lefthook": "2.2.1",
|
|
5146
|
+
"modern-web-guidance": "0.0.193",
|
|
5147
|
+
"oxfmt": "0.72.0",
|
|
5148
|
+
"oxlint": "1.87.0",
|
|
5097
5149
|
"oxlint-tsgolint": "7.0.2003",
|
|
5098
5150
|
"prettier": "3.9.9",
|
|
5099
|
-
"release-it": "21.1.
|
|
5151
|
+
"release-it": "21.1.1",
|
|
5100
5152
|
"tsdown": "0.23.0",
|
|
5101
5153
|
"typescript": "6.0.3",
|
|
5102
5154
|
"vitest": "5.0.3",
|
|
5103
|
-
"pnpm": "11.28.
|
|
5155
|
+
"pnpm": "11.28.5"
|
|
5104
5156
|
}["oxlint"];
|
|
5105
5157
|
Object.assign(deps, vitestDevDeps());
|
|
5106
5158
|
}
|
|
@@ -5110,37 +5162,21 @@ function rootDevDeps(config) {
|
|
|
5110
5162
|
"@types/node": "24.19.1",
|
|
5111
5163
|
"@vitest/coverage-v8": "5.0.3",
|
|
5112
5164
|
"commit-and-tag-version": "13.2.1",
|
|
5113
|
-
"knip": "6.
|
|
5114
|
-
"lefthook": "2.1
|
|
5115
|
-
"modern-web-guidance": "0.0.
|
|
5116
|
-
"oxfmt": "0.
|
|
5117
|
-
"oxlint": "1.
|
|
5165
|
+
"knip": "6.41.0",
|
|
5166
|
+
"lefthook": "2.2.1",
|
|
5167
|
+
"modern-web-guidance": "0.0.193",
|
|
5168
|
+
"oxfmt": "0.72.0",
|
|
5169
|
+
"oxlint": "1.87.0",
|
|
5118
5170
|
"oxlint-tsgolint": "7.0.2003",
|
|
5119
5171
|
"prettier": "3.9.9",
|
|
5120
|
-
"release-it": "21.1.
|
|
5172
|
+
"release-it": "21.1.1",
|
|
5121
5173
|
"tsdown": "0.23.0",
|
|
5122
5174
|
"typescript": "6.0.3",
|
|
5123
5175
|
"vitest": "5.0.3",
|
|
5124
|
-
"pnpm": "11.28.
|
|
5176
|
+
"pnpm": "11.28.5"
|
|
5125
5177
|
}["oxlint-tsgolint"];
|
|
5126
5178
|
return deps;
|
|
5127
5179
|
}
|
|
5128
|
-
function isWorkspacePackage(ctx, packageName) {
|
|
5129
|
-
if (ctx.config.structure !== "monorepo") return false;
|
|
5130
|
-
const packagesDir = path.join(ctx.targetDir, "packages");
|
|
5131
|
-
if (!existsSync(packagesDir)) return false;
|
|
5132
|
-
try {
|
|
5133
|
-
for (const entry of readdirSync(packagesDir, { withFileTypes: true })) {
|
|
5134
|
-
if (!entry.isDirectory()) continue;
|
|
5135
|
-
const pkgJsonPath = path.join(packagesDir, entry.name, "package.json");
|
|
5136
|
-
if (!existsSync(pkgJsonPath)) continue;
|
|
5137
|
-
try {
|
|
5138
|
-
if (parsePackageJson(readFileSync(pkgJsonPath, "utf-8"))?.name === packageName) return true;
|
|
5139
|
-
} catch (_error) {}
|
|
5140
|
-
}
|
|
5141
|
-
} catch (_error) {}
|
|
5142
|
-
return false;
|
|
5143
|
-
}
|
|
5144
5180
|
function addReleaseDeps(deps, config) {
|
|
5145
5181
|
switch (config.releaseStrategy) {
|
|
5146
5182
|
case "release-it":
|
|
@@ -5150,18 +5186,18 @@ function addReleaseDeps(deps, config) {
|
|
|
5150
5186
|
"@types/node": "24.19.1",
|
|
5151
5187
|
"@vitest/coverage-v8": "5.0.3",
|
|
5152
5188
|
"commit-and-tag-version": "13.2.1",
|
|
5153
|
-
"knip": "6.
|
|
5154
|
-
"lefthook": "2.1
|
|
5155
|
-
"modern-web-guidance": "0.0.
|
|
5156
|
-
"oxfmt": "0.
|
|
5157
|
-
"oxlint": "1.
|
|
5189
|
+
"knip": "6.41.0",
|
|
5190
|
+
"lefthook": "2.2.1",
|
|
5191
|
+
"modern-web-guidance": "0.0.193",
|
|
5192
|
+
"oxfmt": "0.72.0",
|
|
5193
|
+
"oxlint": "1.87.0",
|
|
5158
5194
|
"oxlint-tsgolint": "7.0.2003",
|
|
5159
5195
|
"prettier": "3.9.9",
|
|
5160
|
-
"release-it": "21.1.
|
|
5196
|
+
"release-it": "21.1.1",
|
|
5161
5197
|
"tsdown": "0.23.0",
|
|
5162
5198
|
"typescript": "6.0.3",
|
|
5163
5199
|
"vitest": "5.0.3",
|
|
5164
|
-
"pnpm": "11.28.
|
|
5200
|
+
"pnpm": "11.28.5"
|
|
5165
5201
|
}["release-it"];
|
|
5166
5202
|
if (config.structure === "monorepo") deps["@release-it/bumper"] = {
|
|
5167
5203
|
"@changesets/cli": "3.0.3",
|
|
@@ -5169,18 +5205,18 @@ function addReleaseDeps(deps, config) {
|
|
|
5169
5205
|
"@types/node": "24.19.1",
|
|
5170
5206
|
"@vitest/coverage-v8": "5.0.3",
|
|
5171
5207
|
"commit-and-tag-version": "13.2.1",
|
|
5172
|
-
"knip": "6.
|
|
5173
|
-
"lefthook": "2.1
|
|
5174
|
-
"modern-web-guidance": "0.0.
|
|
5175
|
-
"oxfmt": "0.
|
|
5176
|
-
"oxlint": "1.
|
|
5208
|
+
"knip": "6.41.0",
|
|
5209
|
+
"lefthook": "2.2.1",
|
|
5210
|
+
"modern-web-guidance": "0.0.193",
|
|
5211
|
+
"oxfmt": "0.72.0",
|
|
5212
|
+
"oxlint": "1.87.0",
|
|
5177
5213
|
"oxlint-tsgolint": "7.0.2003",
|
|
5178
5214
|
"prettier": "3.9.9",
|
|
5179
|
-
"release-it": "21.1.
|
|
5215
|
+
"release-it": "21.1.1",
|
|
5180
5216
|
"tsdown": "0.23.0",
|
|
5181
5217
|
"typescript": "6.0.3",
|
|
5182
5218
|
"vitest": "5.0.3",
|
|
5183
|
-
"pnpm": "11.28.
|
|
5219
|
+
"pnpm": "11.28.5"
|
|
5184
5220
|
}["@release-it/bumper"];
|
|
5185
5221
|
break;
|
|
5186
5222
|
case "simple":
|
|
@@ -5190,18 +5226,18 @@ function addReleaseDeps(deps, config) {
|
|
|
5190
5226
|
"@types/node": "24.19.1",
|
|
5191
5227
|
"@vitest/coverage-v8": "5.0.3",
|
|
5192
5228
|
"commit-and-tag-version": "13.2.1",
|
|
5193
|
-
"knip": "6.
|
|
5194
|
-
"lefthook": "2.1
|
|
5195
|
-
"modern-web-guidance": "0.0.
|
|
5196
|
-
"oxfmt": "0.
|
|
5197
|
-
"oxlint": "1.
|
|
5229
|
+
"knip": "6.41.0",
|
|
5230
|
+
"lefthook": "2.2.1",
|
|
5231
|
+
"modern-web-guidance": "0.0.193",
|
|
5232
|
+
"oxfmt": "0.72.0",
|
|
5233
|
+
"oxlint": "1.87.0",
|
|
5198
5234
|
"oxlint-tsgolint": "7.0.2003",
|
|
5199
5235
|
"prettier": "3.9.9",
|
|
5200
|
-
"release-it": "21.1.
|
|
5236
|
+
"release-it": "21.1.1",
|
|
5201
5237
|
"tsdown": "0.23.0",
|
|
5202
5238
|
"typescript": "6.0.3",
|
|
5203
5239
|
"vitest": "5.0.3",
|
|
5204
|
-
"pnpm": "11.28.
|
|
5240
|
+
"pnpm": "11.28.5"
|
|
5205
5241
|
}["commit-and-tag-version"];
|
|
5206
5242
|
break;
|
|
5207
5243
|
case "changesets": deps["@changesets/cli"] = {
|
|
@@ -5210,18 +5246,18 @@ function addReleaseDeps(deps, config) {
|
|
|
5210
5246
|
"@types/node": "24.19.1",
|
|
5211
5247
|
"@vitest/coverage-v8": "5.0.3",
|
|
5212
5248
|
"commit-and-tag-version": "13.2.1",
|
|
5213
|
-
"knip": "6.
|
|
5214
|
-
"lefthook": "2.1
|
|
5215
|
-
"modern-web-guidance": "0.0.
|
|
5216
|
-
"oxfmt": "0.
|
|
5217
|
-
"oxlint": "1.
|
|
5249
|
+
"knip": "6.41.0",
|
|
5250
|
+
"lefthook": "2.2.1",
|
|
5251
|
+
"modern-web-guidance": "0.0.193",
|
|
5252
|
+
"oxfmt": "0.72.0",
|
|
5253
|
+
"oxlint": "1.87.0",
|
|
5218
5254
|
"oxlint-tsgolint": "7.0.2003",
|
|
5219
5255
|
"prettier": "3.9.9",
|
|
5220
|
-
"release-it": "21.1.
|
|
5256
|
+
"release-it": "21.1.1",
|
|
5221
5257
|
"tsdown": "0.23.0",
|
|
5222
5258
|
"typescript": "6.0.3",
|
|
5223
5259
|
"vitest": "5.0.3",
|
|
5224
|
-
"pnpm": "11.28.
|
|
5260
|
+
"pnpm": "11.28.5"
|
|
5225
5261
|
}["@changesets/cli"];
|
|
5226
5262
|
}
|
|
5227
5263
|
}
|
|
@@ -5288,10 +5324,6 @@ function reclaimManagedDevDeps(ctx, pkg, managedDevDeps, unmanaged, changes) {
|
|
|
5288
5324
|
}
|
|
5289
5325
|
pkg.devDependencies = existingDevDeps;
|
|
5290
5326
|
}
|
|
5291
|
-
function readUnmanagedDevDeps(ctx) {
|
|
5292
|
-
const slice = parseToolingConfigSlice(ctx.read(".tooling.json"), z.object({ unmanagedDevDependencies: UnmanagedDevDependenciesSchema.optional() }), { block: "unmanagedDevDependencies" });
|
|
5293
|
-
return new Set(slice?.unmanagedDevDependencies ?? []);
|
|
5294
|
-
}
|
|
5295
5327
|
function isAsciiCheckEnabled(ctx) {
|
|
5296
5328
|
return parseToolingConfigSlice(ctx.read(".tooling.json"), z.object({ ascii: AsciiConfigSchema.optional() }), { block: "ascii" })?.ascii?.enabled === true;
|
|
5297
5329
|
}
|
|
@@ -5326,18 +5358,18 @@ function applyMetadataDefaults(pkg, ctx, changes) {
|
|
|
5326
5358
|
"@types/node": "24.19.1",
|
|
5327
5359
|
"@vitest/coverage-v8": "5.0.3",
|
|
5328
5360
|
"commit-and-tag-version": "13.2.1",
|
|
5329
|
-
"knip": "6.
|
|
5330
|
-
"lefthook": "2.1
|
|
5331
|
-
"modern-web-guidance": "0.0.
|
|
5332
|
-
"oxfmt": "0.
|
|
5333
|
-
"oxlint": "1.
|
|
5361
|
+
"knip": "6.41.0",
|
|
5362
|
+
"lefthook": "2.2.1",
|
|
5363
|
+
"modern-web-guidance": "0.0.193",
|
|
5364
|
+
"oxfmt": "0.72.0",
|
|
5365
|
+
"oxlint": "1.87.0",
|
|
5334
5366
|
"oxlint-tsgolint": "7.0.2003",
|
|
5335
5367
|
"prettier": "3.9.9",
|
|
5336
|
-
"release-it": "21.1.
|
|
5368
|
+
"release-it": "21.1.1",
|
|
5337
5369
|
"tsdown": "0.23.0",
|
|
5338
5370
|
"typescript": "6.0.3",
|
|
5339
5371
|
"vitest": "5.0.3",
|
|
5340
|
-
"pnpm": "11.28.
|
|
5372
|
+
"pnpm": "11.28.5"
|
|
5341
5373
|
}["pnpm"];
|
|
5342
5374
|
const desiredPm = pinnedPnpm ? `pnpm@${pinnedPnpm}` : void 0;
|
|
5343
5375
|
if (desiredPm) {
|
|
@@ -5376,26 +5408,27 @@ function buildManagedDevDeps(ctx) {
|
|
|
5376
5408
|
const devDeps = { ...rootDevDeps(ctx.config) };
|
|
5377
5409
|
if (!isMonorepo) Object.assign(devDeps, perPackageDevDeps(ctx.config));
|
|
5378
5410
|
if (ctx.config.stack !== "none" || ctx.config.ci === "forgejo") devDeps["@bensandee/config"] = isWorkspacePackage(ctx, "@bensandee/config") ? "workspace:*" : "0.15.0";
|
|
5379
|
-
if (!isWorkspacePackage(ctx, "@bensandee/tooling")) devDeps["@bensandee/tooling"] = "0.
|
|
5411
|
+
if (!isWorkspacePackage(ctx, "@bensandee/tooling")) devDeps["@bensandee/tooling"] = "0.90.0";
|
|
5380
5412
|
if (ctx.config.useEslintPlugin && ctx.config.stack !== "none") devDeps["@bensandee/eslint-plugin"] = isWorkspacePackage(ctx, "@bensandee/eslint-plugin") ? "workspace:*" : "0.17.0";
|
|
5413
|
+
if (wantsAgentCli(ctx)) devDeps[AGENT_CLI_PACKAGE] = "0.1.1";
|
|
5381
5414
|
if (ctx.config.formatter === "oxfmt") devDeps["oxfmt"] = {
|
|
5382
5415
|
"@changesets/cli": "3.0.3",
|
|
5383
5416
|
"@release-it/bumper": "8.0.1",
|
|
5384
5417
|
"@types/node": "24.19.1",
|
|
5385
5418
|
"@vitest/coverage-v8": "5.0.3",
|
|
5386
5419
|
"commit-and-tag-version": "13.2.1",
|
|
5387
|
-
"knip": "6.
|
|
5388
|
-
"lefthook": "2.1
|
|
5389
|
-
"modern-web-guidance": "0.0.
|
|
5390
|
-
"oxfmt": "0.
|
|
5391
|
-
"oxlint": "1.
|
|
5420
|
+
"knip": "6.41.0",
|
|
5421
|
+
"lefthook": "2.2.1",
|
|
5422
|
+
"modern-web-guidance": "0.0.193",
|
|
5423
|
+
"oxfmt": "0.72.0",
|
|
5424
|
+
"oxlint": "1.87.0",
|
|
5392
5425
|
"oxlint-tsgolint": "7.0.2003",
|
|
5393
5426
|
"prettier": "3.9.9",
|
|
5394
|
-
"release-it": "21.1.
|
|
5427
|
+
"release-it": "21.1.1",
|
|
5395
5428
|
"tsdown": "0.23.0",
|
|
5396
5429
|
"typescript": "6.0.3",
|
|
5397
5430
|
"vitest": "5.0.3",
|
|
5398
|
-
"pnpm": "11.28.
|
|
5431
|
+
"pnpm": "11.28.5"
|
|
5399
5432
|
}["oxfmt"];
|
|
5400
5433
|
if (ctx.config.formatter === "prettier") devDeps["prettier"] = {
|
|
5401
5434
|
"@changesets/cli": "3.0.3",
|
|
@@ -5403,18 +5436,18 @@ function buildManagedDevDeps(ctx) {
|
|
|
5403
5436
|
"@types/node": "24.19.1",
|
|
5404
5437
|
"@vitest/coverage-v8": "5.0.3",
|
|
5405
5438
|
"commit-and-tag-version": "13.2.1",
|
|
5406
|
-
"knip": "6.
|
|
5407
|
-
"lefthook": "2.1
|
|
5408
|
-
"modern-web-guidance": "0.0.
|
|
5409
|
-
"oxfmt": "0.
|
|
5410
|
-
"oxlint": "1.
|
|
5439
|
+
"knip": "6.41.0",
|
|
5440
|
+
"lefthook": "2.2.1",
|
|
5441
|
+
"modern-web-guidance": "0.0.193",
|
|
5442
|
+
"oxfmt": "0.72.0",
|
|
5443
|
+
"oxlint": "1.87.0",
|
|
5411
5444
|
"oxlint-tsgolint": "7.0.2003",
|
|
5412
5445
|
"prettier": "3.9.9",
|
|
5413
|
-
"release-it": "21.1.
|
|
5446
|
+
"release-it": "21.1.1",
|
|
5414
5447
|
"tsdown": "0.23.0",
|
|
5415
5448
|
"typescript": "6.0.3",
|
|
5416
5449
|
"vitest": "5.0.3",
|
|
5417
|
-
"pnpm": "11.28.
|
|
5450
|
+
"pnpm": "11.28.5"
|
|
5418
5451
|
}["prettier"];
|
|
5419
5452
|
addReleaseDeps(devDeps, ctx.config);
|
|
5420
5453
|
return devDeps;
|
|
@@ -5423,7 +5456,7 @@ async function generatePackageJson(ctx) {
|
|
|
5423
5456
|
const filePath = "package.json";
|
|
5424
5457
|
const existing = ctx.read(filePath);
|
|
5425
5458
|
const allScripts = buildManagedScripts(ctx);
|
|
5426
|
-
const unmanaged =
|
|
5459
|
+
const unmanaged = readUnmanagedDevDepNames(ctx);
|
|
5427
5460
|
const devDeps = buildManagedDevDeps(ctx);
|
|
5428
5461
|
if (existing) {
|
|
5429
5462
|
const pkg = parsePackageJson(existing);
|
|
@@ -5473,18 +5506,18 @@ async function generatePackageJson(ctx) {
|
|
|
5473
5506
|
"@types/node": "24.19.1",
|
|
5474
5507
|
"@vitest/coverage-v8": "5.0.3",
|
|
5475
5508
|
"commit-and-tag-version": "13.2.1",
|
|
5476
|
-
"knip": "6.
|
|
5477
|
-
"lefthook": "2.1
|
|
5478
|
-
"modern-web-guidance": "0.0.
|
|
5479
|
-
"oxfmt": "0.
|
|
5480
|
-
"oxlint": "1.
|
|
5509
|
+
"knip": "6.41.0",
|
|
5510
|
+
"lefthook": "2.2.1",
|
|
5511
|
+
"modern-web-guidance": "0.0.193",
|
|
5512
|
+
"oxfmt": "0.72.0",
|
|
5513
|
+
"oxlint": "1.87.0",
|
|
5481
5514
|
"oxlint-tsgolint": "7.0.2003",
|
|
5482
5515
|
"prettier": "3.9.9",
|
|
5483
|
-
"release-it": "21.1.
|
|
5516
|
+
"release-it": "21.1.1",
|
|
5484
5517
|
"tsdown": "0.23.0",
|
|
5485
5518
|
"typescript": "6.0.3",
|
|
5486
5519
|
"vitest": "5.0.3",
|
|
5487
|
-
"pnpm": "11.28.
|
|
5520
|
+
"pnpm": "11.28.5"
|
|
5488
5521
|
}["pnpm"]}`
|
|
5489
5522
|
};
|
|
5490
5523
|
ctx.write(filePath, JSON.stringify(pkg, null, 2) + "\n");
|
|
@@ -7554,7 +7587,7 @@ async function generateReleaseCi(ctx) {
|
|
|
7554
7587
|
action: "skipped",
|
|
7555
7588
|
description: "Release workflow has ignore comment"
|
|
7556
7589
|
};
|
|
7557
|
-
if (existing.includes("Managed by @bensandee/tooling --") && normalizeWorkflow(existing) === normalizeWorkflow(withDevPath)) return {
|
|
7590
|
+
if (existing.includes("Managed by @bensandee/tooling --") && normalizeWorkflow(existing, GENERATOR_OWNED_ACTIONS) === normalizeWorkflow(withDevPath, GENERATOR_OWNED_ACTIONS)) return {
|
|
7558
7591
|
filePath: workflowPath,
|
|
7559
7592
|
action: "skipped",
|
|
7560
7593
|
description: "Release workflow already up to date"
|
|
@@ -7781,7 +7814,7 @@ async function generateCi(ctx) {
|
|
|
7781
7814
|
action: "skipped",
|
|
7782
7815
|
description: "CI workflow has ignore comment"
|
|
7783
7816
|
};
|
|
7784
|
-
if (existing.includes("Managed by @bensandee/tooling --") && normalizeWorkflow(existing) === normalizeWorkflow(withDevPath)) return {
|
|
7817
|
+
if (existing.includes("Managed by @bensandee/tooling --") && normalizeWorkflow(existing, GENERATOR_OWNED_ACTIONS) === normalizeWorkflow(withDevPath, GENERATOR_OWNED_ACTIONS)) return {
|
|
7785
7818
|
filePath,
|
|
7786
7819
|
action: "skipped",
|
|
7787
7820
|
description: "CI workflow already up to date"
|
|
@@ -7809,19 +7842,25 @@ function foreignOwnedBinaries(ctx) {
|
|
|
7809
7842
|
function ignoreBinariesField(binaries) {
|
|
7810
7843
|
return binaries.length > 0 ? `\n ignoreBinaries: ${JSON.stringify(binaries)},` : "";
|
|
7811
7844
|
}
|
|
7812
|
-
function
|
|
7845
|
+
function ignorableDependencies(ctx) {
|
|
7846
|
+
return wantsAgentCli(ctx) ? [AGENT_CLI_PACKAGE] : [];
|
|
7847
|
+
}
|
|
7848
|
+
function ignoreDependenciesField(dependencies) {
|
|
7849
|
+
return dependencies.length > 0 ? `\n ignoreDependencies: ${JSON.stringify(dependencies)},` : "";
|
|
7850
|
+
}
|
|
7851
|
+
function buildKnipConfigSingle(ignoreBinaries, ignoreDependencies) {
|
|
7813
7852
|
return `import type { KnipConfig } from "knip";
|
|
7814
7853
|
|
|
7815
7854
|
export default {
|
|
7816
7855
|
entry: ["src/index.ts"],
|
|
7817
|
-
project: ["src/**/*.ts"],${ignoreBinariesField(ignoreBinaries)}
|
|
7856
|
+
project: ["src/**/*.ts"],${ignoreBinariesField(ignoreBinaries)}${ignoreDependenciesField(ignoreDependencies)}
|
|
7818
7857
|
} satisfies KnipConfig;
|
|
7819
7858
|
`;
|
|
7820
7859
|
}
|
|
7821
|
-
function buildKnipConfigMonorepo(ignoreBinaries) {
|
|
7860
|
+
function buildKnipConfigMonorepo(ignoreBinaries, ignoreDependencies) {
|
|
7822
7861
|
return `import type { KnipConfig } from "knip";
|
|
7823
7862
|
|
|
7824
|
-
export default {${ignoreBinariesField(ignoreBinaries)}
|
|
7863
|
+
export default {${ignoreBinariesField(ignoreBinaries)}${ignoreDependenciesField(ignoreDependencies)}
|
|
7825
7864
|
workspaces: {
|
|
7826
7865
|
".": {
|
|
7827
7866
|
entry: [],
|
|
@@ -7882,16 +7921,17 @@ function hookIsInProjectScope(content, path) {
|
|
|
7882
7921
|
if (patterns === void 0) return true;
|
|
7883
7922
|
return patterns.some((pattern) => picomatch(pattern, { dot: true })(HOOK_FILE));
|
|
7884
7923
|
}
|
|
7885
|
-
function ensureIgnorePattern(content, path, ignoreBinaries) {
|
|
7924
|
+
function ensureIgnorePattern(content, path, ignoreBinaries, ignoreDependencies) {
|
|
7886
7925
|
const needsHooksIgnore = hookIsInProjectScope(content, path);
|
|
7887
|
-
if (isJsonConfig(path)) return ensureIgnoreInJson(content, ignoreBinaries, needsHooksIgnore);
|
|
7888
|
-
return ensureIgnoreInTs(content, ignoreBinaries, needsHooksIgnore);
|
|
7926
|
+
if (isJsonConfig(path)) return ensureIgnoreInJson(content, ignoreBinaries, ignoreDependencies, needsHooksIgnore);
|
|
7927
|
+
return ensureIgnoreInTs(content, ignoreBinaries, ignoreDependencies, needsHooksIgnore);
|
|
7889
7928
|
}
|
|
7890
7929
|
const KnipJsonSchema = z.object({
|
|
7891
7930
|
ignore: z.array(z.string()).optional(),
|
|
7892
|
-
ignoreBinaries: z.array(z.string()).optional()
|
|
7931
|
+
ignoreBinaries: z.array(z.string()).optional(),
|
|
7932
|
+
ignoreDependencies: z.array(z.string()).optional()
|
|
7893
7933
|
}).passthrough();
|
|
7894
|
-
function ensureIgnoreInJson(content, ignoreBinaries, needsHooksIgnore) {
|
|
7934
|
+
function ensureIgnoreInJson(content, ignoreBinaries, ignoreDependencies, needsHooksIgnore) {
|
|
7895
7935
|
let parsedJson;
|
|
7896
7936
|
try {
|
|
7897
7937
|
parsedJson = JSON.parse(content);
|
|
@@ -7912,6 +7952,12 @@ function ensureIgnoreInJson(content, ignoreBinaries, needsHooksIgnore) {
|
|
|
7912
7952
|
parsed.ignoreBinaries = [...parsed.ignoreBinaries ?? [], ...missingBinaries];
|
|
7913
7953
|
changed = true;
|
|
7914
7954
|
}
|
|
7955
|
+
const existingDependencies = new Set(parsed.ignoreDependencies ?? []);
|
|
7956
|
+
const missingDependencies = ignoreDependencies.filter((dependency) => !existingDependencies.has(dependency));
|
|
7957
|
+
if (missingDependencies.length > 0) {
|
|
7958
|
+
parsed.ignoreDependencies = [...parsed.ignoreDependencies ?? [], ...missingDependencies];
|
|
7959
|
+
changed = true;
|
|
7960
|
+
}
|
|
7915
7961
|
if (!changed) return void 0;
|
|
7916
7962
|
return JSON.stringify(parsed, null, 2) + "\n";
|
|
7917
7963
|
}
|
|
@@ -7921,7 +7967,30 @@ function missingIgnoreBinariesInTs(content, binaries) {
|
|
|
7921
7967
|
const arrayContent = match[1] ?? "";
|
|
7922
7968
|
return binaries.filter((binary) => !arrayContent.includes(`"${binary}"`));
|
|
7923
7969
|
}
|
|
7924
|
-
function
|
|
7970
|
+
function missingIgnoreDependenciesInTs(content, dependencies) {
|
|
7971
|
+
const match = /ignoreDependencies:\s*\[([^\]]*)\]/.exec(content);
|
|
7972
|
+
if (!match) return dependencies;
|
|
7973
|
+
const arrayContent = match[1] ?? "";
|
|
7974
|
+
return dependencies.filter((dependency) => !arrayContent.includes(`"${dependency}"`));
|
|
7975
|
+
}
|
|
7976
|
+
function insertIntoTsArray(content, field, entries) {
|
|
7977
|
+
const quoted = entries.map((entry) => `"${entry}"`).join(", ");
|
|
7978
|
+
const arrayPattern = new RegExp("(" + field + ":\\s*\\[)");
|
|
7979
|
+
if (arrayPattern.test(content)) return {
|
|
7980
|
+
content: content.replace(arrayPattern, `$1${quoted}, `),
|
|
7981
|
+
changed: true
|
|
7982
|
+
};
|
|
7983
|
+
const exportPattern = /(export default\s*\{)\n/;
|
|
7984
|
+
if (exportPattern.test(content)) return {
|
|
7985
|
+
content: content.replace(exportPattern, `$1\n ${field}: [${quoted}],\n`),
|
|
7986
|
+
changed: true
|
|
7987
|
+
};
|
|
7988
|
+
return {
|
|
7989
|
+
content,
|
|
7990
|
+
changed: false
|
|
7991
|
+
};
|
|
7992
|
+
}
|
|
7993
|
+
function ensureIgnoreInTs(content, ignoreBinaries, ignoreDependencies, needsHooksIgnore) {
|
|
7925
7994
|
let result = content;
|
|
7926
7995
|
let changed = false;
|
|
7927
7996
|
if (needsHooksIgnore && !result.includes(".claude/hooks")) {
|
|
@@ -7939,18 +8008,15 @@ function ensureIgnoreInTs(content, ignoreBinaries, needsHooksIgnore) {
|
|
|
7939
8008
|
}
|
|
7940
8009
|
const missingBinaries = missingIgnoreBinariesInTs(result, ignoreBinaries);
|
|
7941
8010
|
if (missingBinaries.length > 0) {
|
|
7942
|
-
const
|
|
7943
|
-
|
|
7944
|
-
|
|
7945
|
-
|
|
7946
|
-
|
|
7947
|
-
|
|
7948
|
-
|
|
7949
|
-
|
|
7950
|
-
|
|
7951
|
-
changed = true;
|
|
7952
|
-
}
|
|
7953
|
-
}
|
|
8011
|
+
const inserted = insertIntoTsArray(result, "ignoreBinaries", missingBinaries);
|
|
8012
|
+
result = inserted.content;
|
|
8013
|
+
changed = changed || inserted.changed;
|
|
8014
|
+
}
|
|
8015
|
+
const missingDependencies = missingIgnoreDependenciesInTs(result, ignoreDependencies);
|
|
8016
|
+
if (missingDependencies.length > 0) {
|
|
8017
|
+
const inserted = insertIntoTsArray(result, "ignoreDependencies", missingDependencies);
|
|
8018
|
+
result = inserted.content;
|
|
8019
|
+
changed = changed || inserted.changed;
|
|
7954
8020
|
}
|
|
7955
8021
|
return changed ? result : void 0;
|
|
7956
8022
|
}
|
|
@@ -7966,6 +8032,7 @@ async function generateKnip(ctx) {
|
|
|
7966
8032
|
};
|
|
7967
8033
|
const isMonorepo = ctx.config.structure === "monorepo";
|
|
7968
8034
|
const ignoreBinaries = foreignOwnedBinaries(ctx);
|
|
8035
|
+
const ignoreDependencies = ignorableDependencies(ctx);
|
|
7969
8036
|
const buildConfig = isMonorepo ? buildKnipConfigMonorepo : buildKnipConfigSingle;
|
|
7970
8037
|
const existingPath = KNIP_CONFIG_PATHS.find((p) => ctx.exists(p));
|
|
7971
8038
|
if (existingPath) {
|
|
@@ -7976,7 +8043,7 @@ async function generateKnip(ctx) {
|
|
|
7976
8043
|
description: "Could not read existing knip config"
|
|
7977
8044
|
};
|
|
7978
8045
|
if (content.trim() === "") {
|
|
7979
|
-
const blank = isJsonConfig(existingPath) ? ensureIgnorePattern("{}", existingPath, ignoreBinaries) ?? "{}\n" : formattedTemplate(ctx, existingPath, buildConfig(ignoreBinaries));
|
|
8046
|
+
const blank = isJsonConfig(existingPath) ? ensureIgnorePattern("{}", existingPath, ignoreBinaries, ignoreDependencies) ?? "{}\n" : formattedTemplate(ctx, existingPath, buildConfig(ignoreBinaries, ignoreDependencies));
|
|
7980
8047
|
ctx.write(existingPath, blank);
|
|
7981
8048
|
return {
|
|
7982
8049
|
filePath: existingPath,
|
|
@@ -7984,13 +8051,13 @@ async function generateKnip(ctx) {
|
|
|
7984
8051
|
description: createdDescription(existingPath)
|
|
7985
8052
|
};
|
|
7986
8053
|
}
|
|
7987
|
-
const updated = ensureIgnorePattern(content, existingPath, ignoreBinaries);
|
|
8054
|
+
const updated = ensureIgnorePattern(content, existingPath, ignoreBinaries, ignoreDependencies);
|
|
7988
8055
|
if (updated) {
|
|
7989
8056
|
ctx.write(existingPath, updated);
|
|
7990
8057
|
return {
|
|
7991
8058
|
filePath: existingPath,
|
|
7992
8059
|
action: "updated",
|
|
7993
|
-
description: "Added \".claude/hooks/**\" and/or
|
|
8060
|
+
description: "Added \".claude/hooks/**\", foreign-owned ignoreBinaries, and/or ignored dependencies"
|
|
7994
8061
|
};
|
|
7995
8062
|
}
|
|
7996
8063
|
return {
|
|
@@ -7999,7 +8066,7 @@ async function generateKnip(ctx) {
|
|
|
7999
8066
|
description: existingPath === filePath ? "Already configured" : `Existing config found at ${existingPath}`
|
|
8000
8067
|
};
|
|
8001
8068
|
}
|
|
8002
|
-
ctx.write(filePath, formattedTemplate(ctx, filePath, buildConfig(ignoreBinaries)));
|
|
8069
|
+
ctx.write(filePath, formattedTemplate(ctx, filePath, buildConfig(ignoreBinaries, ignoreDependencies)));
|
|
8003
8070
|
return {
|
|
8004
8071
|
filePath,
|
|
8005
8072
|
action: "created",
|
|
@@ -8197,7 +8264,7 @@ function writeEmbedded(ctx, file) {
|
|
|
8197
8264
|
}
|
|
8198
8265
|
const NOT_BUILT = "run `pnpm build` from the repo root";
|
|
8199
8266
|
async function generateClaudeHooks(ctx, embedded = {
|
|
8200
|
-
hook: "/**\n * bst-hook -- Claude Code PreToolUse hook\n * @bensandee/claude-hooks\n * https://github.com/bensandee/tooling\n *\n * Auto-generated by @bensandee/tooling repo:sync -- do not edit manually.\n */\nimport * as fs from \"node:fs\";\nimport { existsSync, readFileSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { execFileSync } from \"node:child_process\";\n\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/util.js\nfunction getEnumValues(entries) {\n const numericValues = Object.values(entries).filter((v) => typeof v === \"number\");\n return Object.entries(entries).filter(([k, _]) => numericValues.indexOf(+k) === -1).map(([_, v]) => v);\n}\nfunction joinValues(array, separator = \"|\") {\n return array.map((val) => stringifyPrimitive(val)).join(separator);\n}\nfunction jsonStringifyReplacer(_, value) {\n if (typeof value === \"bigint\") return value.toString();\n return value;\n}\nvar Cached = class {\n constructor(getter) {\n this._getter = getter;\n this._value = void 0;\n }\n get value() {\n const getter = this._getter;\n if (getter !== void 0) {\n this._value = getter();\n this._getter = void 0;\n }\n return this._value;\n }\n};\nfunction cached(getter) {\n return new Cached(getter);\n}\nfunction nullish(input) {\n return input === null || input === void 0;\n}\nfunction cleanRegex(source) {\n const start = source.startsWith(\"^\") ? 1 : 0;\n const end = source.endsWith(\"$\") ? source.length - 1 : source.length;\n return source.slice(start, end);\n}\nfunction assignProp(target, prop, value) {\n Object.defineProperty(target, prop, {\n value,\n writable: true,\n enumerable: true,\n configurable: true\n });\n}\nfunction rawShape(def) {\n const desc = Object.getOwnPropertyDescriptor(def, \"shape\");\n return desc?.get ? desc.get.raw : desc?.value;\n}\nfunction sourceShape(schema) {\n return rawShape(schema._zod.def) ?? schema._zod.def.shape;\n}\nfunction deferProp(target, key, getter) {\n Object.defineProperty(target, key, {\n get() {\n const value = getter();\n assignProp(this, key, value);\n return value;\n },\n enumerable: true,\n configurable: true\n });\n}\nfunction putProp(target, key, value) {\n if (key in target) assignProp(target, key, value);\n else target[key] = value;\n}\nfunction mirrorShape(target, source, keys, wrap) {\n const raw = sourceShape(source);\n for (const key of keys) {\n const desc = Object.getOwnPropertyDescriptor(raw, key);\n if (!desc.enumerable) continue;\n if (desc.get) deferProp(target, key, () => {\n const value = source._zod.def.shape[key];\n return wrap ? wrap(value, key) : value;\n });\n else putProp(target, key, wrap ? wrap(desc.value, key) : desc.value);\n }\n}\nfunction mirrorProps(target, source) {\n for (const key of Reflect.ownKeys(source)) {\n const desc = Object.getOwnPropertyDescriptor(source, key);\n if (!desc.enumerable) continue;\n if (desc.get) deferProp(target, key, () => source[key]);\n else putProp(target, key, desc.value);\n }\n}\nfunction mergeDefs(...defs) {\n const mergedDescriptors = {};\n for (const def of defs) {\n const descriptors = Object.getOwnPropertyDescriptors(def);\n Object.assign(mergedDescriptors, descriptors);\n }\n return Object.defineProperties({}, mergedDescriptors);\n}\nfunction esc(str) {\n return JSON.stringify(str);\n}\nfunction slugify(input) {\n return input.toLowerCase().trim().replace(/[^\\w\\s-]/g, \"\").replace(/[\\s_-]+/g, \"-\").replace(/^-+|-+$/g, \"\");\n}\nconst captureStackTrace = \"captureStackTrace\" in Error ? Error.captureStackTrace : (..._args) => {};\nfunction isObject(data) {\n return typeof data === \"object\" && data !== null && !Array.isArray(data);\n}\nconst allowsEval = /* @__PURE__*/ cached(() => {\n if (globalConfig.jitless) return false;\n if (typeof navigator !== \"undefined\" && navigator?.userAgent?.includes(\"Cloudflare\")) return false;\n try {\n new Function(\"\");\n return true;\n } catch (_) {\n return false;\n }\n});\nfunction isPlainObject(o) {\n if (isObject(o) === false) return false;\n const ctor = o.constructor;\n if (ctor === void 0) return true;\n if (typeof ctor !== \"function\") return true;\n const prot = ctor.prototype;\n if (isObject(prot) === false) return false;\n if (Object.prototype.hasOwnProperty.call(prot, \"isPrototypeOf\") === false) return false;\n return true;\n}\nfunction shallowClone(o) {\n if (isPlainObject(o)) return { ...o };\n if (Array.isArray(o)) return [...o];\n if (o instanceof Map) return new Map(o);\n if (o instanceof Set) return new Set(o);\n return o;\n}\nconst propertyKeyTypes = /* @__PURE__*/ new Set([\n \"string\",\n \"number\",\n \"symbol\"\n]);\nfunction escapeRegex(str) {\n return str.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n}\nfunction clone(inst, def, params) {\n const cl = new inst._zod.constr(def ?? inst._zod.def);\n if (!def || params?.parent) cl._zod.parent = inst;\n return cl;\n}\nfunction normalizeParams(_params) {\n const params = _params;\n if (!params) return {};\n if (typeof params === \"string\") return { error: () => params };\n if (params?.message !== void 0) {\n if (params?.error !== void 0) throw new Error(\"Cannot specify both `message` and `error` params\");\n params.error = params.message;\n }\n delete params.message;\n if (typeof params.error === \"string\") return {\n ...params,\n error: () => params.error\n };\n return params;\n}\nfunction stringifyPrimitive(value) {\n if (typeof value === \"bigint\") return value.toString() + \"n\";\n if (typeof value === \"string\") return `\"${value}\"`;\n return `${value}`;\n}\nfunction optionalKeys(shape) {\n return Object.keys(shape).filter((k) => {\n return shape[k]._zod.optin !== void 0 && shape[k]._zod.optout === \"optional\";\n });\n}\nconst NUMBER_FORMAT_RANGES = /*@__PURE__*/ (() => ({\n safeint: [Number.MIN_SAFE_INTEGER, Number.MAX_SAFE_INTEGER],\n int32: [-2147483648, 2147483647],\n uint32: [0, 4294967295],\n float32: [-34028234663852886e22, 34028234663852886e22],\n float64: [-Number.MAX_VALUE, Number.MAX_VALUE]\n}))();\nconst BIGINT_FORMAT_RANGES = {\n int64: [/* @__PURE__*/ BigInt(\"-9223372036854775808\"), /* @__PURE__*/ BigInt(\"9223372036854775807\")],\n uint64: [/* @__PURE__*/ BigInt(0), /* @__PURE__*/ BigInt(\"18446744073709551615\")]\n};\nfunction pick(schema, mask) {\n const currDef = schema._zod.def;\n const checks = currDef.checks;\n if (checks && checks.length > 0) throw new Error(\".pick() cannot be used on object schemas containing refinements\");\n const newShape = {};\n mirrorShape(newShape, schema, maskedKeys(schema, mask));\n return clone(schema, mergeDefs(currDef, {\n shape: newShape,\n checks: []\n }));\n}\nfunction maskedKeys(schema, mask) {\n const raw = sourceShape(schema);\n const keys = [];\n for (const key of Reflect.ownKeys(mask)) {\n if (!Object.getOwnPropertyDescriptor(raw, key)?.enumerable) throw new Error(`Unrecognized key: \"${String(key)}\"`);\n if (mask[key]) keys.push(key);\n }\n return keys;\n}\nfunction omit(schema, mask) {\n const currDef = schema._zod.def;\n const checks = currDef.checks;\n if (checks && checks.length > 0) throw new Error(\".omit() cannot be used on object schemas containing refinements\");\n const omitted = new Set(maskedKeys(schema, mask));\n const newShape = {};\n mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)).filter((key) => !omitted.has(key)));\n return clone(schema, mergeDefs(currDef, {\n shape: newShape,\n checks: []\n }));\n}\nfunction extend(schema, shape) {\n if (!isPlainObject(shape)) throw new Error(\"Invalid input to extend: expected a plain object\");\n const checks = schema._zod.def.checks;\n if (checks && checks.length > 0) {\n const existingShape = sourceShape(schema);\n for (const key of Reflect.ownKeys(shape)) if (Object.getOwnPropertyDescriptor(existingShape, key) !== void 0) throw new Error(\"Cannot overwrite keys on object schemas containing refinements. Use `.safeExtend()` instead.\");\n }\n return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));\n}\nfunction extended(schema, shape) {\n const newShape = {};\n mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)));\n mirrorProps(newShape, shape);\n return newShape;\n}\nfunction safeExtend(schema, shape) {\n if (!isPlainObject(shape)) throw new Error(\"Invalid input to safeExtend: expected a plain object\");\n return clone(schema, mergeDefs(schema._zod.def, { shape: extended(schema, shape) }));\n}\nfunction merge(a, b) {\n if (!b?._zod?.def) throw new Error(\"Invalid input to merge: expected an object schema. To merge a plain shape, use `.extend()`.\");\n if (a._zod.def.checks?.length) throw new Error(\".merge() cannot be used on object schemas containing refinements. Use .safeExtend() instead.\");\n const newShape = {};\n mirrorShape(newShape, a, Reflect.ownKeys(sourceShape(a)));\n mirrorShape(newShape, b, Reflect.ownKeys(sourceShape(b)));\n return clone(a, mergeDefs(a._zod.def, {\n shape: newShape,\n get catchall() {\n return b._zod.def.catchall;\n },\n checks: b._zod.def.checks ?? []\n }));\n}\nfunction partial(Class, schema, mask, name = \"partial\") {\n const checks = schema._zod.def.checks;\n if (checks && checks.length > 0) throw new Error(`.${name}() cannot be used on object schemas containing refinements`);\n const selected = mask ? new Set(maskedKeys(schema, mask)) : void 0;\n const newShape = {};\n mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), Class && ((value, key) => selected && !selected.has(key) ? value : new Class({\n type: \"optional\",\n innerType: value\n })));\n return clone(schema, mergeDefs(schema._zod.def, {\n shape: newShape,\n checks: []\n }));\n}\nfunction required(Class, schema, mask) {\n const selected = mask ? new Set(maskedKeys(schema, mask)) : void 0;\n const newShape = {};\n mirrorShape(newShape, schema, Reflect.ownKeys(sourceShape(schema)), (value, key) => selected && !selected.has(key) ? value : new Class({\n type: \"nonoptional\",\n innerType: value\n }));\n return clone(schema, mergeDefs(schema._zod.def, { shape: newShape }));\n}\nfunction aborted(x, startIndex = 0) {\n if (x.aborted === true) return true;\n for (let i = startIndex; i < x.issues.length; i++) if (x.issues[i]?.continue !== true) return true;\n return false;\n}\nfunction explicitlyAborted(x, startIndex = 0) {\n if (x.aborted === true) return true;\n for (let i = startIndex; i < x.issues.length; i++) if (x.issues[i]?.continue === false) return true;\n return false;\n}\nfunction prefixIssues(path, issues) {\n return issues.map((iss) => {\n var _a;\n (_a = iss).path ?? (_a.path = []);\n iss.path.unshift(path);\n return iss;\n });\n}\nfunction unwrapMessage(message) {\n return typeof message === \"string\" ? message : message?.message;\n}\nfunction attachSchema(issues, start, inst) {\n var _a;\n for (let i = start; i < issues.length; i++) (_a = issues[i]).schema ?? (_a.schema = inst);\n}\nfunction finalizeIssue(iss, ctx, config) {\n var _a;\n const traits = iss.inst?._zod?.traits;\n if (traits?.has(\"$ZodType\")) {\n if (traits.has(\"$ZodCheck\")) (_a = iss).schema ?? (_a.schema = iss.inst);\n else iss.schema = iss.inst;\n }\n const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;\n const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config.customError?.(iss)) ?? unwrapMessage(config.localeError?.(iss)) ?? \"Invalid input\";\n const full = {};\n for (const k of Object.keys(iss)) {\n if (k === \"inst\" || k === \"schema\" || k === \"continue\" || k === \"input\" || k === \"__proto__\") continue;\n full[k] = iss[k];\n }\n full.path ?? (full.path = []);\n full.message = message;\n if (ctx?.reportInput) full.input = iss.input;\n return full;\n}\nconst highSurrogate = /[\\uD800-\\uDBFF]/;\nfunction codePointLength(str) {\n const units = str.length;\n if (!highSurrogate.test(str)) return units;\n let count = units;\n for (let i = 0; i < units - 1; i++) if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {\n count--;\n i++;\n }\n return count;\n}\nfunction getLengthableOrigin(input) {\n if (Array.isArray(input)) return \"array\";\n if (typeof input === \"string\") return \"string\";\n return \"unknown\";\n}\nfunction parsedType(data) {\n const t = typeof data;\n switch (t) {\n case \"number\": return Number.isNaN(data) ? \"nan\" : \"number\";\n case \"object\": {\n if (data === null) return \"null\";\n if (Array.isArray(data)) return \"array\";\n const obj = data;\n if (obj && Object.getPrototypeOf(obj) !== Object.prototype && \"constructor\" in obj && obj.constructor) return obj.constructor.name;\n }\n }\n return t;\n}\nfunction issue(...args) {\n const [iss, input, inst] = args;\n if (typeof iss === \"string\") return {\n message: iss,\n code: \"custom\",\n input,\n inst\n };\n return { ...iss };\n}\nfunction members(proto, table) {\n for (const key in table) {\n const desc = Object.getOwnPropertyDescriptor(table, key);\n if (desc.get) Object.defineProperty(proto, key, {\n ...desc,\n enumerable: false\n });\n else defineBound(proto, key, desc.value);\n }\n}\nfunction own(inst, key, value, enumerable = true) {\n Object.defineProperty(inst, key, {\n configurable: true,\n writable: true,\n enumerable,\n value\n });\n return value;\n}\nfunction hide(inst, key, value) {\n return own(inst, key, value, false);\n}\nfunction derived(computes, table) {\n for (const key in computes) {\n const compute = computes[key];\n Object.defineProperty(table, key, {\n configurable: true,\n enumerable: true,\n get() {\n return own(this, key, compute(this));\n },\n set(value) {\n own(this, key, value);\n }\n });\n }\n return table;\n}\nfunction defineBound(proto, key, fn) {\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n return this == null ? fn : own(this, key, fn.bind(this));\n },\n set(value) {\n own(this, key, value);\n }\n });\n}\nfunction claim(inst, sentinel) {\n const proto = Object.getPrototypeOf(inst);\n return sentinel in proto ? void 0 : proto;\n}\nlet installing;\nlet broke = false;\nconst breaker = {\n configurable: true,\n get() {\n broke = true;\n }\n};\nfunction defineLazyInternal(inst, key, compute) {\n const proto = Object.getPrototypeOf(inst._zod);\n if (key in proto && installing !== inst._zod) {\n installing = void 0;\n return;\n }\n installing = inst._zod;\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n Object.defineProperty(this, key, breaker);\n const outer = broke;\n broke = false;\n try {\n const value = compute(this);\n if (broke) delete this[key];\n else Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n value\n });\n broke = broke || outer;\n return value;\n } catch (err) {\n delete this[key];\n broke = broke || outer;\n throw err;\n }\n },\n set(value) {\n Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n value\n });\n }\n });\n}\nfunction installLazyProp(inst, key, make, enumerable) {\n const proto = claim(inst, key);\n if (!proto) return;\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n const desc = {\n configurable: true,\n writable: true,\n enumerable,\n value: void 0\n };\n Object.defineProperty(this, key, desc);\n desc.value = make(this);\n Object.defineProperty(this, key, desc);\n return desc.value;\n },\n set(value) {\n Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n enumerable,\n value\n });\n }\n });\n}\nconst CONSTANT_CATCH = \"~constantCatch\";\nfunction constantCatch(value) {\n const fn = () => value;\n fn[CONSTANT_CATCH] = true;\n return fn;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/core.js\nvar _a$1;\nconst _zodDesc = {\n value: void 0,\n enumerable: false\n};\nlet _E = \"captureStackTrace\" in Error ? Error : null;\nfunction newError(Definition) {\n const E = _E;\n if (E) {\n const saved = E.stackTraceLimit;\n if (typeof saved === \"number\") {\n try {\n E.stackTraceLimit = 0;\n } catch {\n _E = null;\n return new Definition();\n }\n try {\n return new Definition();\n } finally {\n E.stackTraceLimit = saved;\n }\n }\n }\n return new Definition();\n}\nfunction $constructor(name, initializer, proto, params) {\n const zodProto = {};\n function Internals(def) {\n this.def = def;\n this.constr = _;\n this.traits = /* @__PURE__ */ new Set();\n }\n Internals.prototype = zodProto;\n const protoMembers = proto;\n const initialized = protoMembers && /* @__PURE__ */ new WeakSet();\n function init(inst, def) {\n if (!inst._zod) {\n _zodDesc.value = new Internals(def);\n try {\n Object.defineProperty(inst, \"_zod\", _zodDesc);\n } finally {\n _zodDesc.value = void 0;\n }\n } else if (inst._zod.traits.has(name)) return;\n inst._zod.traits.add(name);\n initializer(inst, def);\n if (initialized) {\n const own = Object.getPrototypeOf(inst);\n const ctorProto = inst._zod.constr.prototype;\n let up = own;\n while (up && up !== ctorProto) up = Object.getPrototypeOf(up);\n const target = up ?? own;\n if (!initialized.has(target)) {\n initialized.add(target);\n members(target, protoMembers);\n }\n }\n const proto = _.prototype;\n for (const k in proto) {\n if (!Object.prototype.hasOwnProperty.call(proto, k)) continue;\n if (!(k in inst)) inst[k] = proto[k].bind(inst);\n }\n }\n const Parent = params?.Parent ?? Object;\n class Definition extends Parent {}\n Object.defineProperty(Definition, \"name\", { value: name });\n function _(def) {\n const inst = params?.Parent ? newError(Definition) : this;\n init(inst, def);\n const deferred = inst._zod.deferred;\n if (deferred) {\n for (const fn of deferred) fn();\n inst._zod.deferred = void 0;\n }\n const pp = globalThis.__zod_globalConfig?.postProcessor;\n if (pp) pp(inst);\n return inst;\n }\n Object.defineProperty(_, \"init\", { value: init });\n Object.defineProperty(_, Symbol.hasInstance, { value: (inst) => {\n if (params?.Parent && inst instanceof params.Parent) return true;\n return inst?._zod?.traits?.has(name);\n } });\n Object.defineProperty(_, \"name\", { value: name });\n return _;\n}\nvar $ZodAsyncError = class extends Error {\n constructor() {\n super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);\n }\n};\nvar $ZodEncodeError = class extends Error {\n constructor(name) {\n super(`Encountered unidirectional transform during encode: ${name}`);\n this.name = \"ZodEncodeError\";\n }\n};\n(_a$1 = globalThis).__zod_globalConfig ?? (_a$1.__zod_globalConfig = {});\nconst globalConfig = globalThis.__zod_globalConfig;\nfunction config(newConfig) {\n if (newConfig) Object.assign(globalConfig, newConfig);\n return globalConfig;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/errors.js\nfunction _getMessage() {\n const internals = this._zod;\n internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2));\n return internals.message;\n}\nfunction _setMessage(value) {\n this._zod.message = value;\n}\nconst _messageDesc = {\n get: _getMessage,\n set: _setMessage,\n enumerable: true,\n configurable: true\n};\nconst _issuesDesc = {\n value: void 0,\n enumerable: false\n};\nconst _installedToString = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);\nconst initializer$1 = (inst, def) => {\n inst.name = \"$ZodError\";\n _issuesDesc.value = def;\n Object.defineProperty(inst, \"issues\", _issuesDesc);\n _issuesDesc.value = void 0;\n Object.defineProperty(inst, \"message\", _messageDesc);\n const proto = Object.getPrototypeOf(inst);\n if (!_installedToString.has(proto)) {\n _installedToString.add(proto);\n Object.defineProperty(proto, \"toString\", {\n configurable: true,\n enumerable: false,\n get() {\n const value = () => this.message;\n Object.defineProperty(this, \"toString\", {\n value,\n configurable: true,\n writable: true\n });\n return value;\n },\n set(value) {\n Object.defineProperty(this, \"toString\", {\n value,\n configurable: true,\n writable: true\n });\n }\n });\n }\n};\nconst $ZodError = $constructor(\"$ZodError\", initializer$1);\nconst $ZodRealError = $constructor(\"$ZodError\", initializer$1, void 0, { Parent: Error });\nfunction node(obj, key, make) {\n if (!Object.prototype.hasOwnProperty.call(obj, key)) {\n if (key === \"__proto__\") Object.defineProperty(obj, key, {\n value: make(),\n writable: true,\n enumerable: true,\n configurable: true\n });\n else obj[key] = make();\n }\n return obj[key];\n}\nfunction flattenError(error, mapper = (issue) => issue.message) {\n const fieldErrors = {};\n const formErrors = [];\n for (const sub of error.issues) if (sub.path.length > 0) node(fieldErrors, sub.path[0], () => []).push(mapper(sub));\n else formErrors.push(mapper(sub));\n return {\n formErrors,\n fieldErrors\n };\n}\nfunction formatError(error, mapper = (issue) => issue.message) {\n const fieldErrors = { _errors: [] };\n const processError = (error, path = []) => {\n for (const issue of error.issues) if (issue.code === \"invalid_union\" && issue.errors.length) issue.errors.map((issues) => processError({ issues }, [...path, ...issue.path]));\n else if (issue.code === \"invalid_key\") processError({ issues: issue.issues }, [...path, ...issue.path]);\n else if (issue.code === \"invalid_element\") processError({ issues: issue.issues }, [...path, ...issue.path]);\n else {\n const fullpath = [...path, ...issue.path];\n if (fullpath.length === 0) fieldErrors._errors.push(mapper(issue));\n else {\n let curr = fieldErrors;\n let i = 0;\n while (i < fullpath.length) {\n const el = fullpath[i];\n const terminal = i === fullpath.length - 1;\n if (el === \"_errors\") {\n if (terminal) curr._errors.push(mapper(issue));\n i++;\n continue;\n }\n if (!Object.prototype.hasOwnProperty.call(curr, el)) Object.defineProperty(curr, el, {\n value: { _errors: [] },\n enumerable: true,\n writable: true,\n configurable: true\n });\n const node = curr[el];\n if (terminal) node._errors.push(mapper(issue));\n curr = node;\n i++;\n }\n }\n }\n };\n processError(error);\n return fieldErrors;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/parse.js\nfunction finalizeParams(callee, params) {\n return {\n callee: params?.callee ?? callee,\n Err: params?.Err\n };\n}\nconst _parse = (_Err) => {\n const fn = (schema, value, _ctx, _params) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: false\n } : { async: false };\n const result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) throw new $ZodAsyncError();\n if (result.issues.length) {\n const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));\n captureStackTrace(e, _params?.callee ?? fn);\n throw e;\n }\n return result.value;\n };\n return fn;\n};\nconst _parseAsync = (_Err) => {\n const fn = async (schema, value, _ctx, params) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: true\n } : { async: true };\n let result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) result = await result;\n if (result.issues.length) {\n const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));\n captureStackTrace(e, params?.callee ?? fn);\n throw e;\n }\n return result.value;\n };\n return fn;\n};\nconst _safeParse = (_Err) => (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: false\n } : { async: false };\n const result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) throw new $ZodAsyncError();\n return result.issues.length ? failure(_Err, result.issues, ctx) : {\n success: true,\n data: result.value\n };\n};\nfunction failure(Err, issues, ctx) {\n let error;\n return {\n success: false,\n get error() {\n if (!error) {\n error = new Err(issues.map((iss) => finalizeIssue(iss, ctx, config())));\n issues = void 0;\n ctx = void 0;\n }\n return error;\n },\n set error(e) {\n error = e;\n issues = void 0;\n ctx = void 0;\n }\n };\n}\nconst _safeParseAsync = (_Err) => async (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: true\n } : { async: true };\n let result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) result = await result;\n return result.issues.length ? failure(_Err, result.issues, ctx) : {\n success: true,\n data: result.value\n };\n};\nconst COMPILE_INVALID = /* @__PURE__ */ Symbol.for(\"zod.compile.invalid\");\nconst COMPILE_FALLBACK = /* @__PURE__ */ Symbol.for(\"zod.compile.fallback\");\nconst validate = ((schema, value, _ctx) => {\n const validator = schema._zod.bag.validator;\n if (validator !== void 0) {\n if (validator(value) !== COMPILE_INVALID) return true;\n if (validator.definite === true && _ctx === void 0) return false;\n }\n return validateFallback(schema, value, _ctx);\n});\nfunction validateFallback(schema, value, _ctx) {\n const ctx = _ctx ? {\n ..._ctx,\n async: false,\n abortEarly: true\n } : {\n async: false,\n abortEarly: true\n };\n const fallbackRun = schema._zod.bag.fallbackRun;\n let result;\n if (fallbackRun) {\n ctx[COMPILE_FALLBACK] = true;\n result = fallbackRun({\n value,\n issues: []\n }, ctx);\n } else result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) throw new $ZodAsyncError();\n return result.issues.length === 0;\n}\nconst validateAsync$1 = async (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: true,\n abortEarly: true\n } : {\n async: true,\n abortEarly: true\n };\n let result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) result = await result;\n return result.issues.length === 0;\n};\nconst _encode = (_Err) => {\n const parse = _parse(_Err);\n const fn = (schema, value, _ctx, _params) => {\n const ctx = _ctx ? {\n ..._ctx,\n direction: \"backward\"\n } : { direction: \"backward\" };\n return parse(schema, value, ctx, finalizeParams(fn, _params));\n };\n return fn;\n};\nconst _decode = (_Err) => {\n const parse = _parse(_Err);\n const fn = (schema, value, _ctx, _params) => {\n return parse(schema, value, _ctx, finalizeParams(fn, _params));\n };\n return fn;\n};\nconst _encodeAsync = (_Err) => {\n const parseAsync = _parseAsync(_Err);\n const fn = async (schema, value, _ctx, _params) => {\n const ctx = _ctx ? {\n ..._ctx,\n direction: \"backward\"\n } : { direction: \"backward\" };\n return await parseAsync(schema, value, ctx, finalizeParams(fn, _params));\n };\n return fn;\n};\nconst _decodeAsync = (_Err) => {\n const parseAsync = _parseAsync(_Err);\n const fn = async (schema, value, _ctx, _params) => {\n return await parseAsync(schema, value, _ctx, finalizeParams(fn, _params));\n };\n return fn;\n};\nconst _safeEncode = (_Err) => (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n direction: \"backward\"\n } : { direction: \"backward\" };\n return _safeParse(_Err)(schema, value, ctx);\n};\nconst _safeDecode = (_Err) => (schema, value, _ctx) => {\n return _safeParse(_Err)(schema, value, _ctx);\n};\nconst _safeEncodeAsync = (_Err) => async (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n direction: \"backward\"\n } : { direction: \"backward\" };\n return _safeParseAsync(_Err)(schema, value, ctx);\n};\nconst _safeDecodeAsync = (_Err) => async (schema, value, _ctx) => {\n return _safeParseAsync(_Err)(schema, value, _ctx);\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/regexes.js\nconst cuid = /^[cC][0-9a-z]{6,}$/;\nconst cuid2 = /^[0-9a-z]+$/;\nconst ulid = /^[0-7][0-9A-HJKMNP-TV-Za-hjkmnp-tv-z]{25}$/;\nconst xid = /^[0-9a-vA-V]{20}$/;\nconst ksuid = /^[A-Za-z0-9]{27}$/;\nconst nanoid = /^[a-zA-Z0-9_-]{21}$/;\nfunction nanoidOfLength(length) {\n return new RegExp(`^[a-zA-Z0-9_-]{${length}}$`);\n}\nconst duration = /^P(?:(\\d+W)|(?!.*W)(?=\\d|T\\d)(\\d+Y)?(\\d+M)?(\\d+D)?(T(?=\\d)(\\d+H)?(\\d+M)?(\\d+([.,]\\d+)?S)?)?)$/;\nconst guid = /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12})$/;\nconst uuid = (version) => {\n if (!version) return /^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[1-8][0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12}|00000000-0000-0000-0000-000000000000|ffffffff-ffff-ffff-ffff-ffffffffffff)$/;\n return new RegExp(`^([0-9a-fA-F]{8}-[0-9a-fA-F]{4}-${version}[0-9a-fA-F]{3}-[89abAB][0-9a-fA-F]{3}-[0-9a-fA-F]{12})$`);\n};\nconst email = /^(?:[A-Za-z0-9_'+\\-]+\\.)*[A-Za-z0-9_'+\\-]*[A-Za-z0-9_+-]@(?:[A-Za-z0-9][A-Za-z0-9\\-]*\\.)+[A-Za-z]{2,}$/;\nconst _emoji$1 = `^(?=[\\\\s\\\\S]*[\\\\p{Extended_Pictographic}\\\\p{Regional_Indicator}\\\\u20E3])[\\\\p{Extended_Pictographic}\\\\p{Emoji_Component}]+$`;\nfunction emoji() {\n return new RegExp(_emoji$1, \"u\");\n}\nconst ipv4 = /^(?:(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(?:25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])$/;\nconst ipv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))$/;\nconst cidrv4 = /^((25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\.){3}(25[0-5]|2[0-4][0-9]|1[0-9][0-9]|[1-9][0-9]|[0-9])\\/([0-9]|[1-2][0-9]|3[0-2])$/;\nconst cidrv6 = /^(([0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,7}:|([0-9a-fA-F]{1,4}:){1,6}:[0-9a-fA-F]{1,4}|([0-9a-fA-F]{1,4}:){1,5}(:[0-9a-fA-F]{1,4}){1,2}|([0-9a-fA-F]{1,4}:){1,4}(:[0-9a-fA-F]{1,4}){1,3}|([0-9a-fA-F]{1,4}:){1,3}(:[0-9a-fA-F]{1,4}){1,4}|([0-9a-fA-F]{1,4}:){1,2}(:[0-9a-fA-F]{1,4}){1,5}|[0-9a-fA-F]{1,4}:((:[0-9a-fA-F]{1,4}){1,6})|:((:[0-9a-fA-F]{1,4}){1,7}|:))\\/(12[0-8]|1[01][0-9]|[1-9]?[0-9])$/;\nconst base64 = /^$|^(?:[0-9a-zA-Z+/]{4})*(?:(?:[0-9a-zA-Z+/]{2}==)|(?:[0-9a-zA-Z+/]{3}=))?$/;\nconst base64url = /^(?:[A-Za-z0-9_-]{4})*(?:[A-Za-z0-9_-]{2,3})?$/;\nconst httpProtocol = /^https?$/;\nconst e164 = /^\\+[1-9]\\d{6,14}$/;\nconst dateSource = `(?:(?:\\\\d\\\\d[2468][048]|\\\\d\\\\d[13579][26]|\\\\d\\\\d0[48]|[02468][048]00|[13579][26]00)-02-29|\\\\d{4}-(?:(?:0[13578]|1[02])-(?:0[1-9]|[12]\\\\d|3[01])|(?:0[469]|11)-(?:0[1-9]|[12]\\\\d|30)|(?:02)-(?:0[1-9]|1\\\\d|2[0-8])))`;\nfunction anchor(source) {\n return new RegExp(`^${source}$`);\n}\nconst date = /*@__PURE__*/ anchor(dateSource);\nfunction timeSource(args) {\n const hhmm = `(?:[01]\\\\d|2[0-3]):[0-5]\\\\d`;\n return typeof args.precision === \"number\" ? args.precision === -1 ? `${hhmm}` : args.precision === 0 ? `${hhmm}:[0-5]\\\\d` : `${hhmm}:[0-5]\\\\d\\\\.\\\\d{${args.precision}}` : args.seconds ? `${hhmm}:[0-5]\\\\d(?:\\\\.\\\\d+)?` : `${hhmm}(?::[0-5]\\\\d(?:\\\\.\\\\d+)?)?`;\n}\nfunction time(args) {\n return new RegExp(`^${timeSource(args)}$`);\n}\nfunction datetime(args) {\n const opts = [\"Z\"];\n if (args.offset) opts.push(`([+-](?:[01]\\\\d|2[0-3]):[0-5]\\\\d)`);\n const qualified = `${timeSource({\n precision: args.precision,\n seconds: true\n })}(?:${opts.join(\"|\")})`;\n const timeRegex = args.local ? `${qualified}|${timeSource({ precision: args.precision })}` : qualified;\n return new RegExp(`^${dateSource}T(?:${timeRegex})$`);\n}\nconst anyString = /^[\\s\\S]{0,}$/;\nconst integer = /^-?\\d+$/;\nconst number = /^-?\\d+(?:\\.\\d+)?$/;\nconst lowercase = /^[^A-Z]*$/;\nconst uppercase = /^[^a-z]*$/;\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/checks.js\nconst $ZodCheck = /*@__PURE__*/ $constructor(\"$ZodCheck\", (inst, def) => {\n var _a;\n inst._zod ?? (inst._zod = {});\n inst._zod.def = def;\n (_a = inst._zod).onattach ?? (_a.onattach = []);\n});\nconst _whenHasLength = (payload) => {\n const val = payload.value;\n return !nullish(val) && val.length !== void 0;\n};\nconst $ZodCheckMaxLength = /*@__PURE__*/ $constructor(\"$ZodCheckMaxLength\", (inst, def) => {\n var _a;\n $ZodCheck.init(inst, def);\n (_a = inst._zod.def).when ?? (_a.when = _whenHasLength);\n inst._zod.check = (payload) => {\n const input = payload.value;\n const units = input.length;\n if ((typeof input === \"string\" && units > def.maximum ? codePointLength(input) : units) <= def.maximum) return;\n const origin = getLengthableOrigin(input);\n payload.issues.push({\n origin,\n code: \"too_big\",\n maximum: def.maximum,\n inclusive: true,\n input,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckMinLength = /*@__PURE__*/ $constructor(\"$ZodCheckMinLength\", (inst, def) => {\n var _a;\n $ZodCheck.init(inst, def);\n (_a = inst._zod.def).when ?? (_a.when = _whenHasLength);\n inst._zod.check = (payload) => {\n const input = payload.value;\n const units = input.length;\n if ((typeof input === \"string\" && units >= def.minimum && units < def.minimum * 2 ? codePointLength(input) : units) >= def.minimum) return;\n const origin = getLengthableOrigin(input);\n payload.issues.push({\n origin,\n code: \"too_small\",\n minimum: def.minimum,\n inclusive: true,\n input,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckLengthEquals = /*@__PURE__*/ $constructor(\"$ZodCheckLengthEquals\", (inst, def) => {\n var _a;\n $ZodCheck.init(inst, def);\n (_a = inst._zod.def).when ?? (_a.when = _whenHasLength);\n inst._zod.check = (payload) => {\n const input = payload.value;\n const units = input.length;\n const length = typeof input === \"string\" && units >= def.length && units <= def.length * 2 ? codePointLength(input) : units;\n if (length === def.length) return;\n const origin = getLengthableOrigin(input);\n const tooBig = length > def.length;\n payload.issues.push({\n origin,\n ...tooBig ? {\n code: \"too_big\",\n maximum: def.length\n } : {\n code: \"too_small\",\n minimum: def.length\n },\n inclusive: true,\n exact: true,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckStringFormat = /*@__PURE__*/ $constructor(\"$ZodCheckStringFormat\", (inst, def) => {\n var _a, _b;\n $ZodCheck.init(inst, def);\n if (def.pattern) (_a = inst._zod).check ?? (_a.check = (payload) => {\n def.pattern.lastIndex = 0;\n if (def.pattern.test(payload.value)) return;\n payload.issues.push({\n origin: \"string\",\n code: \"invalid_format\",\n format: def.format,\n input: payload.value,\n ...def.pattern ? { pattern: def.pattern.toString() } : {},\n inst,\n continue: !def.abort\n });\n });\n else (_b = inst._zod).check ?? (_b.check = () => {});\n});\nconst $ZodCheckRegex = /*@__PURE__*/ $constructor(\"$ZodCheckRegex\", (inst, def) => {\n $ZodCheckStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n def.pattern.lastIndex = 0;\n if (def.pattern.test(payload.value)) return;\n payload.issues.push({\n origin: \"string\",\n code: \"invalid_format\",\n format: \"regex\",\n input: payload.value,\n pattern: def.pattern.toString(),\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckLowerCase = /*@__PURE__*/ $constructor(\"$ZodCheckLowerCase\", (inst, def) => {\n def.pattern ?? (def.pattern = lowercase);\n $ZodCheckStringFormat.init(inst, def);\n});\nconst $ZodCheckUpperCase = /*@__PURE__*/ $constructor(\"$ZodCheckUpperCase\", (inst, def) => {\n def.pattern ?? (def.pattern = uppercase);\n $ZodCheckStringFormat.init(inst, def);\n});\nconst $ZodCheckIncludes = /*@__PURE__*/ $constructor(\"$ZodCheckIncludes\", (inst, def) => {\n $ZodCheck.init(inst, def);\n const escapedRegex = escapeRegex(def.includes);\n def.pattern = new RegExp(typeof def.position === \"number\" ? `^.{${def.position},}${escapedRegex}` : escapedRegex);\n inst._zod.check = (payload) => {\n if (payload.value.includes(def.includes, def.position)) return;\n payload.issues.push({\n origin: \"string\",\n code: \"invalid_format\",\n format: \"includes\",\n includes: def.includes,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckStartsWith = /*@__PURE__*/ $constructor(\"$ZodCheckStartsWith\", (inst, def) => {\n $ZodCheck.init(inst, def);\n const pattern = new RegExp(`^${escapeRegex(def.prefix)}.*`);\n def.pattern ?? (def.pattern = pattern);\n inst._zod.check = (payload) => {\n if (payload.value.startsWith(def.prefix)) return;\n payload.issues.push({\n origin: \"string\",\n code: \"invalid_format\",\n format: \"starts_with\",\n prefix: def.prefix,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckEndsWith = /*@__PURE__*/ $constructor(\"$ZodCheckEndsWith\", (inst, def) => {\n $ZodCheck.init(inst, def);\n const pattern = new RegExp(`.*${escapeRegex(def.suffix)}$`);\n def.pattern ?? (def.pattern = pattern);\n inst._zod.check = (payload) => {\n if (payload.value.endsWith(def.suffix)) return;\n payload.issues.push({\n origin: \"string\",\n code: \"invalid_format\",\n format: \"ends_with\",\n suffix: def.suffix,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCheckOverwrite = /*@__PURE__*/ $constructor(\"$ZodCheckOverwrite\", (inst, def) => {\n $ZodCheck.init(inst, def);\n inst._zod.check = (payload) => {\n payload.value = def.tx(payload.value);\n };\n});\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/doc.js\nvar Doc = class {\n constructor(args = [], closed = {}) {\n this.content = [];\n this.indent = 0;\n this.args = args;\n this.closed = closed;\n }\n indented(fn) {\n this.indent += 1;\n try {\n fn(this);\n } finally {\n this.indent -= 1;\n }\n }\n write(arg) {\n if (typeof arg === \"function\") {\n arg(this, { execution: \"sync\" });\n arg(this, { execution: \"async\" });\n return;\n }\n const lines = arg.split(\"\\n\").filter((x) => x);\n const minIndent = Math.min(...lines.map((x) => x.length - x.trimStart().length));\n const dedented = lines.map((x) => x.slice(minIndent)).map((x) => \" \".repeat(this.indent * 2) + x);\n for (const line of dedented) this.content.push(line);\n }\n compile() {\n const F = Function;\n const content = this?.content ?? [``];\n return new F(...Object.keys(this.closed), `return function (${this.args.join(\", \")}) {\\n${content.join(\"\\n\")}\\n};`)(...Object.values(this.closed));\n }\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/versions.js\nconst version = {\n major: 4,\n minor: 6,\n patch: 5\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/schemas.js\nconst $ZodType = /*@__PURE__*/ $constructor(\"$ZodType\", (inst, def) => {\n var _a;\n inst ?? (inst = {});\n inst._zod.def = def;\n inst._zod.bag = inst._zod.bag || {};\n inst._zod.version = version;\n const defChecks = inst._zod.def.checks;\n const checks = inst._zod.traits.has(\"$ZodCheck\") ? [inst, ...defChecks ?? []] : defChecks?.length ? [...defChecks] : [];\n for (const ch of checks) for (const fn of ch._zod.onattach) fn(inst);\n if (checks.length === 0) {\n (_a = inst._zod).deferred ?? (_a.deferred = []);\n inst._zod.deferred?.push(() => {\n inst._zod.run = inst._zod.parse;\n });\n } else {\n const runChecks = (payload, checks, ctx) => {\n if (payload.memo) return payload;\n let isAborted = aborted(payload);\n let asyncResult;\n for (const ch of checks) {\n if (ch._zod.def.when) {\n if (explicitlyAborted(payload)) continue;\n if (!ch._zod.def.when(payload)) continue;\n } else if (isAborted) continue;\n const currLen = payload.issues.length;\n const _ = ch._zod.check(payload);\n if (_ instanceof Promise && ctx?.async === false) throw new $ZodAsyncError();\n if (asyncResult || _ instanceof Promise) asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {\n await _;\n if (payload.issues.length === currLen) return;\n attachSchema(payload.issues, currLen, inst);\n if (!isAborted) isAborted = aborted(payload, currLen);\n });\n else {\n if (payload.issues.length === currLen) continue;\n attachSchema(payload.issues, currLen, inst);\n if (!isAborted) isAborted = aborted(payload, currLen);\n }\n }\n if (asyncResult) return asyncResult.then(() => {\n return payload;\n });\n return payload;\n };\n const handleCanaryResult = (canary, payload, ctx) => {\n if (aborted(canary)) {\n canary.aborted = true;\n return canary;\n }\n const checkResult = runChecks(payload, checks, ctx);\n if (checkResult instanceof Promise) {\n if (ctx.async === false) throw new $ZodAsyncError();\n return checkResult.then((checkResult) => inst._zod.parse(checkResult, ctx));\n }\n return inst._zod.parse(checkResult, ctx);\n };\n inst._zod.run = (payload, ctx) => {\n if (ctx.skipChecks) return inst._zod.parse(payload, ctx);\n if (ctx.direction === \"backward\") {\n const canary = inst._zod.parse({\n value: payload.value,\n issues: []\n }, {\n ...ctx,\n skipChecks: true\n });\n if (canary instanceof Promise) return canary.then((canary) => {\n return handleCanaryResult(canary, payload, ctx);\n });\n return handleCanaryResult(canary, payload, ctx);\n }\n const result = inst._zod.parse(payload, ctx);\n if (result instanceof Promise) {\n if (ctx.async === false) throw new $ZodAsyncError();\n return result.then((result) => runChecks(result, checks, ctx));\n }\n return runChecks(result, checks, ctx);\n };\n }\n}, {\n get \"~standard\"() {\n return hide(this, \"~standard\", standardProps(this));\n },\n set \"~standard\"(value) {\n own(this, \"~standard\", value);\n }\n});\nconst toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value };\nasync function validateAsync(inst, value) {\n const ctx = { async: true };\n return toStandardResult(await inst._zod.run({\n value,\n issues: []\n }, ctx), ctx);\n}\nfunction standardProps(inst) {\n return {\n validate: (value) => {\n const ctx = { async: false };\n try {\n const r = inst._zod.run({\n value,\n issues: []\n }, ctx);\n if (!(r instanceof Promise)) return toStandardResult(r, ctx);\n } catch (_) {}\n return validateAsync(inst, value);\n },\n vendor: \"zod\",\n version: 1\n };\n}\nconst $ZodString = /*@__PURE__*/ $constructor(\"$ZodString\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.pattern = def.pattern ?? anyString;\n inst._zod.parse = (payload, _) => {\n if (def.coerce) try {\n payload.value = String(payload.value);\n } catch (_) {}\n if (typeof payload.value === \"string\") return payload;\n payload.issues.push({\n expected: \"string\",\n code: \"invalid_type\",\n input: payload.value,\n inst\n });\n return payload;\n };\n});\nconst $ZodStringFormat = /*@__PURE__*/ $constructor(\"$ZodStringFormat\", (inst, def) => {\n $ZodCheckStringFormat.init(inst, def);\n $ZodString.init(inst, def);\n});\nconst $ZodGUID = /*@__PURE__*/ $constructor(\"$ZodGUID\", (inst, def) => {\n def.pattern ?? (def.pattern = guid);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodUUID = /*@__PURE__*/ $constructor(\"$ZodUUID\", (inst, def) => {\n if (def.version) {\n const v = {\n v1: 1,\n v2: 2,\n v3: 3,\n v4: 4,\n v5: 5,\n v6: 6,\n v7: 7,\n v8: 8\n }[def.version];\n if (v === void 0) throw new Error(`Invalid UUID version: \"${def.version}\"`);\n def.pattern ?? (def.pattern = uuid(v));\n } else def.pattern ?? (def.pattern = uuid());\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodEmail = /*@__PURE__*/ $constructor(\"$ZodEmail\", (inst, def) => {\n def.pattern ?? (def.pattern = email);\n $ZodStringFormat.init(inst, def);\n});\nconst URL_BAD_FORMAT = 1;\nconst URL_UNPARSEABLE = 2;\nfunction canParseURL(input) {\n try {\n if (typeof URL !== \"undefined\" && typeof URL.canParse === \"function\") return URL.canParse(input);\n new URL(input);\n return true;\n } catch {\n return false;\n }\n}\nfunction validateURL(trimmed, def) {\n if (!(\"normalize\" in def) && !(\"hostname\" in def) && !(\"protocol\" in def)) return canParseURL(trimmed) || 2;\n return parseURLObject(trimmed, def);\n}\nfunction parseURLObject(trimmed, def) {\n if (!def.normalize && def.protocol?.source === httpProtocol.source && !/^https?:\\/\\//i.test(trimmed)) return 1;\n try {\n if (typeof URL !== \"undefined\") {\n const URLStatic = URL;\n if (typeof URLStatic.parse === \"function\") return URLStatic.parse(trimmed) ?? 2;\n }\n return new URL(trimmed);\n } catch {\n return 2;\n }\n}\nconst asciiTabOrNewline = /[\\t\\n\\r]/g;\nfunction stripTabAndNewline(value) {\n return value.replace(asciiTabOrNewline, \"\");\n}\nfunction urlHostnameOk(url, hostname) {\n hostname.lastIndex = 0;\n return hostname.test(url.hostname);\n}\nfunction urlProtocolOk(url, protocol) {\n protocol.lastIndex = 0;\n return protocol.test(url.protocol.endsWith(\":\") ? url.protocol.slice(0, -1) : url.protocol);\n}\nconst $ZodURL = /*@__PURE__*/ $constructor(\"$ZodURL\", (inst, def) => {\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n try {\n const trimmed = payload.value.trim();\n const url = validateURL(trimmed, def);\n if (url === 1) {\n payload.issues.push({\n code: \"invalid_format\",\n format: \"url\",\n note: \"Invalid URL format\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n return;\n }\n if (url === 2) {\n payload.issues.push({\n code: \"invalid_format\",\n format: \"url\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n return;\n }\n if (url === true) {\n payload.value = stripTabAndNewline(trimmed);\n return;\n }\n if (def.hostname && !urlHostnameOk(url, def.hostname)) payload.issues.push({\n code: \"invalid_format\",\n format: \"url\",\n note: \"Invalid hostname\",\n pattern: def.hostname.source,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n if (def.protocol && !urlProtocolOk(url, def.protocol)) payload.issues.push({\n code: \"invalid_format\",\n format: \"url\",\n note: \"Invalid protocol\",\n pattern: def.protocol.source,\n input: payload.value,\n inst,\n continue: !def.abort\n });\n payload.value = def.normalize ? url.href : stripTabAndNewline(trimmed);\n return;\n } catch (_) {\n payload.issues.push({\n code: \"invalid_format\",\n format: \"url\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n }\n };\n});\nconst $ZodEmoji = /*@__PURE__*/ $constructor(\"$ZodEmoji\", (inst, def) => {\n def.pattern ?? (def.pattern = emoji());\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodNanoID = /*@__PURE__*/ $constructor(\"$ZodNanoID\", (inst, def) => {\n if (def.length !== void 0 && (!Number.isInteger(def.length) || def.length < 1)) throw new Error(`Invalid nanoid length: ${def.length}`);\n def.pattern ?? (def.pattern = def.length === void 0 ? nanoid : nanoidOfLength(def.length));\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodCUID = /*@__PURE__*/ $constructor(\"$ZodCUID\", (inst, def) => {\n def.pattern ?? (def.pattern = cuid);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodCUID2 = /*@__PURE__*/ $constructor(\"$ZodCUID2\", (inst, def) => {\n def.pattern ?? (def.pattern = cuid2);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodULID = /*@__PURE__*/ $constructor(\"$ZodULID\", (inst, def) => {\n def.pattern ?? (def.pattern = ulid);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodXID = /*@__PURE__*/ $constructor(\"$ZodXID\", (inst, def) => {\n def.pattern ?? (def.pattern = xid);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodKSUID = /*@__PURE__*/ $constructor(\"$ZodKSUID\", (inst, def) => {\n def.pattern ?? (def.pattern = ksuid);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodISODateTime = /*@__PURE__*/ $constructor(\"$ZodISODateTime\", (inst, def) => {\n def.pattern ?? (def.pattern = datetime(def));\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodISODate = /*@__PURE__*/ $constructor(\"$ZodISODate\", (inst, def) => {\n def.pattern ?? (def.pattern = date);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodISOTime = /*@__PURE__*/ $constructor(\"$ZodISOTime\", (inst, def) => {\n def.pattern ?? (def.pattern = time(def));\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodISODuration = /*@__PURE__*/ $constructor(\"$ZodISODuration\", (inst, def) => {\n def.pattern ?? (def.pattern = duration);\n $ZodStringFormat.init(inst, def);\n});\nconst $ZodIPv4 = /*@__PURE__*/ $constructor(\"$ZodIPv4\", (inst, def) => {\n def.pattern ?? (def.pattern = ipv4);\n $ZodStringFormat.init(inst, def);\n});\nconst ipv6Alphabet = /^[0-9a-fA-F:.]+$/;\nfunction isValidIPv6(value) {\n if (!ipv6Alphabet.test(value)) return false;\n return canParseURL(`http://[${value}]`);\n}\nconst $ZodIPv6 = /*@__PURE__*/ $constructor(\"$ZodIPv6\", (inst, def) => {\n def.pattern ?? (def.pattern = ipv6);\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n if (!isValidIPv6(payload.value)) payload.issues.push({\n code: \"invalid_format\",\n format: \"ipv6\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodCIDRv4 = /*@__PURE__*/ $constructor(\"$ZodCIDRv4\", (inst, def) => {\n def.pattern ?? (def.pattern = cidrv4);\n $ZodStringFormat.init(inst, def);\n});\nfunction isValidCIDRv6(value) {\n const parts = value.split(\"/\");\n if (parts.length !== 2) return false;\n const [address, prefix] = parts;\n if (!prefix) return false;\n const prefixNum = Number(prefix);\n if (`${prefixNum}` !== prefix) return false;\n if (prefixNum < 0 || prefixNum > 128) return false;\n return isValidIPv6(address);\n}\nconst $ZodCIDRv6 = /*@__PURE__*/ $constructor(\"$ZodCIDRv6\", (inst, def) => {\n def.pattern ?? (def.pattern = cidrv6);\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n if (!isValidCIDRv6(payload.value)) payload.issues.push({\n code: \"invalid_format\",\n format: \"cidrv6\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nfunction isValidBase64(data) {\n if (data === \"\") return true;\n if (/\\s/.test(data)) return false;\n if (data.length % 4 !== 0) return false;\n try {\n atob(data);\n return true;\n } catch {\n return false;\n }\n}\nconst base64Charset = /^[0-9a-zA-Z+/]*={0,2}$/;\nconst $ZodBase64 = /*@__PURE__*/ $constructor(\"$ZodBase64\", (inst, def) => {\n def.pattern ?? (def.pattern = base64Charset);\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n if (isValidBase64(payload.value)) return;\n payload.issues.push({\n code: \"invalid_format\",\n format: \"base64\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst base64urlCharset = /^[A-Za-z0-9_-]*$/;\nfunction isValidBase64URL(data) {\n if (!base64urlCharset.test(data)) return false;\n const base64 = data.replace(/[-_]/g, (c) => c === \"-\" ? \"+\" : \"/\");\n return isValidBase64(base64.padEnd(Math.ceil(base64.length / 4) * 4, \"=\"));\n}\nconst $ZodBase64URL = /*@__PURE__*/ $constructor(\"$ZodBase64URL\", (inst, def) => {\n def.pattern ?? (def.pattern = base64urlCharset);\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n if (isValidBase64URL(payload.value)) return;\n payload.issues.push({\n code: \"invalid_format\",\n format: \"base64url\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodE164 = /*@__PURE__*/ $constructor(\"$ZodE164\", (inst, def) => {\n def.pattern ?? (def.pattern = e164);\n $ZodStringFormat.init(inst, def);\n});\nfunction isValidJWT(token, algorithm = null) {\n try {\n const tokensParts = token.split(\".\");\n if (tokensParts.length !== 3) return false;\n const [header] = tokensParts;\n if (!header) return false;\n const parsedHeader = JSON.parse(atob(header));\n if (\"typ\" in parsedHeader && parsedHeader?.typ !== \"JWT\") return false;\n if (!parsedHeader.alg) return false;\n if (algorithm && (!(\"alg\" in parsedHeader) || parsedHeader.alg !== algorithm)) return false;\n return true;\n } catch {\n return false;\n }\n}\nconst $ZodJWT = /*@__PURE__*/ $constructor(\"$ZodJWT\", (inst, def) => {\n $ZodStringFormat.init(inst, def);\n inst._zod.check = (payload) => {\n if (isValidJWT(payload.value, def.alg)) return;\n payload.issues.push({\n code: \"invalid_format\",\n format: \"jwt\",\n input: payload.value,\n inst,\n continue: !def.abort\n });\n };\n});\nconst $ZodUnknown = /*@__PURE__*/ $constructor(\"$ZodUnknown\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.parse = (payload) => payload;\n});\nconst $ZodNever = /*@__PURE__*/ $constructor(\"$ZodNever\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.parse = (payload, _ctx) => {\n payload.issues.push({\n expected: \"never\",\n code: \"invalid_type\",\n input: payload.value,\n inst\n });\n return payload;\n };\n});\nfunction handleArrayResult(result, final, index) {\n if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues));\n final.value[index] = result.value;\n}\nconst $ZodArray = /*@__PURE__*/ $constructor(\"$ZodArray\", (inst, def) => {\n $ZodType.init(inst, def);\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n const input = payload.value;\n if (!Array.isArray(input)) {\n payload.issues.push({\n expected: \"array\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n payload.value = memo ? memo.alloc(inst, payload, Array(input.length), ctx) : Array(input.length);\n const proms = [];\n const abortEarly = ctx?.abortEarly;\n for (let i = 0; i < input.length; i++) {\n const item = input[i];\n const result = def.element._zod.run({\n value: item,\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => handleArrayResult(result, payload, i)));\n else {\n handleArrayResult(result, payload, i);\n if (abortEarly && result.issues.length !== 0 && aborted(result)) break;\n }\n }\n if (proms.length) return Promise.all(proms).then(() => payload);\n return payload;\n };\n});\nfunction handlePropertyResult(result, final, key, input, optin, optout) {\n const isPresent = key in input;\n const isOptionalOut = optout === \"optional\";\n if (!isPresent && isOptionalOut && optin === \"optional\") return;\n if (result.issues.length) {\n if (optin !== void 0 && isOptionalOut && !isPresent) return;\n final.issues.push(...prefixIssues(key, result.issues));\n }\n if (!isPresent && optin === void 0) {\n if (!result.issues.length) final.issues.push({\n code: \"invalid_type\",\n expected: \"nonoptional\",\n input: void 0,\n path: [key]\n });\n return;\n }\n if (result.value === void 0) {\n if (isPresent || optin === \"defaulted\" && !isOptionalOut) final.value[key] = void 0;\n } else final.value[key] = result.value;\n}\nconst NO_SYMBOL_KEYS = [];\nfunction normalizeDef(def) {\n const keys = Object.keys(def.shape);\n const ownSymbols = Object.getOwnPropertySymbols(def.shape);\n const symbolKeys = ownSymbols.length ? ownSymbols : NO_SYMBOL_KEYS;\n const allKeys = symbolKeys.length ? [...keys, ...symbolKeys] : keys;\n for (const k of allKeys) if (!def.shape?.[k]?._zod?.traits?.has(\"$ZodType\")) throw new Error(`Invalid element at key \"${String(k)}\": expected a Zod schema`);\n const okeys = optionalKeys(def.shape);\n return {\n ...def,\n allKeys,\n symbolKeys,\n keySet: new Set(keys),\n numKeys: keys.length,\n optionalKeys: new Set(okeys)\n };\n}\nfunction handleCatchall(proms, input, payload, ctx, def, inst, abortEarly) {\n const unrecognized = [];\n const keySet = def.keySet;\n const _catchall = def.catchall._zod;\n const t = _catchall.def.type;\n const optin = _catchall.optin;\n const optout = _catchall.optout;\n let seen = 0;\n for (const key in input) {\n if (abortEarly && payload.issues.length !== seen) {\n if (aborted(payload, seen)) break;\n seen = payload.issues.length;\n }\n if (keySet.has(key)) continue;\n if (key === \"__proto__\") {\n if (t === \"never\") unrecognized.push(key);\n continue;\n }\n if (t === \"never\") {\n unrecognized.push(key);\n continue;\n }\n const r = _catchall.run({\n value: input[key],\n issues: []\n }, ctx);\n if (r instanceof Promise) proms.push(r.then((r) => handlePropertyResult(r, payload, key, input, optin, optout)));\n else handlePropertyResult(r, payload, key, input, optin, optout);\n }\n if (unrecognized.length) payload.issues.push({\n code: \"unrecognized_keys\",\n keys: unrecognized,\n input,\n inst,\n continue: true\n });\n if (!proms.length) return payload;\n return Promise.all(proms).then(() => {\n return payload;\n });\n}\nconst $ZodObject = /*@__PURE__*/ $constructor(\"$ZodObject\", (inst, def) => {\n $ZodType.init(inst, def);\n const desc = Object.getOwnPropertyDescriptor(def, \"shape\");\n const sh = desc?.get ? desc.get.raw : def.shape ?? {};\n if (sh) {\n const get = () => {\n const newSh = { ...sh };\n Object.defineProperty(def, \"shape\", { value: newSh });\n get.raw = newSh;\n return newSh;\n };\n get.raw = sh;\n Object.defineProperty(def, \"shape\", { get });\n }\n const _normalized = cached(() => normalizeDef(def));\n defineLazyInternal(inst, \"propValues\", (zod) => {\n const shape = zod.def.shape;\n const propValues = {};\n for (const key in shape) {\n const field = shape[key]._zod;\n if (field.values) {\n if (!Object.prototype.hasOwnProperty.call(propValues, key)) assignProp(propValues, key, /* @__PURE__ */ new Set());\n for (const v of field.values) propValues[key].add(v);\n if (field.optin !== void 0) propValues[key].add(void 0);\n }\n }\n return propValues;\n });\n const isObject$2 = isObject;\n const catchall = def.catchall;\n let value;\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n value ?? (value = _normalized.value);\n const input = payload.value;\n if (!isObject$2(input)) {\n payload.issues.push({\n expected: \"object\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n const proms = [];\n const shape = value.shape;\n const abortEarly = ctx?.abortEarly;\n let seen = payload.issues.length;\n for (const key of value.allKeys) {\n if (abortEarly && payload.issues.length !== seen) {\n if (aborted(payload, seen)) break;\n seen = payload.issues.length;\n }\n if (key === \"__proto__\") continue;\n const el = shape[key];\n const optin = el._zod.optin;\n const optout = el._zod.optout;\n const r = el._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (r instanceof Promise) proms.push(r.then((r) => handlePropertyResult(r, payload, key, input, optin, optout)));\n else handlePropertyResult(r, payload, key, input, optin, optout);\n }\n if (!catchall) return proms.length ? Promise.all(proms).then(() => payload) : payload;\n return handleCatchall(proms, input, payload, ctx, _normalized.value, inst, abortEarly === true);\n };\n});\nconst $ZodObjectJIT = /*@__PURE__*/ $constructor(\"$ZodObjectJIT\", (inst, def) => {\n $ZodObject.init(inst, def);\n const superParse = inst._zod.parse;\n const _normalized = cached(() => normalizeDef(def));\n const memo = globalConfig.memoizer;\n const generateFastpass = (shape) => {\n const normalized = _normalized.value;\n const syms = normalized.symbolKeys;\n const doc = new Doc([\"payload\", \"ctx\"], {\n shape,\n inst,\n memo,\n syms\n });\n const parseStr = (k) => `shape[${k}]._zod.run({ value: input[${k}], issues: [] }, ctx)`;\n const prefixStr = (id, k) => `\n let ${id}_ab = false;\n for (let i = 0; i < ${id}.issues.length; i++) {\n const iss = ${id}.issues[i];\n iss.path = iss.path ? [${k}, ...iss.path] : [${k}];\n payload.issues.push(iss);\n if (iss.continue !== true) ${id}_ab = true;\n }\n if (${id}_ab && ctx && ctx.abortEarly) {\n payload.value = newResult;\n return payload;\n }`;\n doc.write(`const input = payload.value;`);\n const ids = Object.create(null);\n let counter = 0;\n for (const key of normalized.allKeys) ids[key] = `key_${counter++}`;\n doc.write(memo ? `const newResult = memo.alloc(inst, payload, {}, ctx);` : `const newResult = {};`);\n for (const key of normalized.allKeys) {\n if (key === \"__proto__\") continue;\n const id = ids[key];\n const k = typeof key === \"symbol\" ? `syms[${syms.indexOf(key)}]` : esc(key);\n const isPresent = `${k} in input`;\n const schema = shape[key];\n const optin = schema?._zod?.optin;\n const isOptionalIn = optin !== void 0;\n const isOptionalOut = schema?._zod?.optout === \"optional\";\n doc.write(`const ${id} = ${parseStr(k)};`);\n if (isOptionalIn && isOptionalOut) {\n const assign = optin === \"optional\" ? `${id}_present` : `${id}.value !== undefined || ${id}_present`;\n doc.write(`\n const ${id}_present = ${isPresent};\n if (!${id}.issues.length || ${id}_present) {\n if (${id}.issues.length) {${prefixStr(id, k)}\n }\n\n if (${assign}) {\n newResult[${k}] = ${id}.value;\n }\n }\n\n `);\n } else if (!isOptionalIn) doc.write(`\n const ${id}_present = ${isPresent};\n if (${id}.issues.length) {${prefixStr(id, k)}\n }\n if (!${id}_present && !${id}.issues.length) {\n payload.issues.push({\n code: \"invalid_type\",\n expected: \"nonoptional\",\n input: undefined,\n path: [${k}]\n });\n if (ctx && ctx.abortEarly) {\n payload.value = newResult;\n return payload;\n }\n }\n\n if (${id}_present) {\n newResult[${k}] = ${id}.value;\n }\n\n `);\n else {\n doc.write(`\n if (${id}.issues.length) {${prefixStr(id, k)}\n }\n `);\n if (optin === \"defaulted\") doc.write(`newResult[${k}] = ${id}.value;`);\n else doc.write(`\n if (${id}.value !== undefined || ${isPresent}) {\n newResult[${k}] = ${id}.value;\n }\n `);\n }\n }\n doc.write(`payload.value = newResult;`);\n doc.write(`return payload;`);\n return doc.compile();\n };\n let fastpass;\n const isObject$1 = isObject;\n const jit = !globalConfig.jitless;\n const allowsEval$1 = allowsEval;\n const fastEnabled = jit && allowsEval$1.value;\n const catchall = def.catchall;\n let value;\n inst._zod.parse = (payload, ctx) => {\n value ?? (value = _normalized.value);\n const input = payload.value;\n if (!isObject$1(input)) {\n payload.issues.push({\n expected: \"object\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n if (jit && fastEnabled && ctx?.async === false && ctx.jitless !== true) {\n if (!fastpass) fastpass = generateFastpass(def.shape);\n payload = fastpass(payload, ctx);\n if (!catchall) return payload;\n return handleCatchall([], input, payload, ctx, value, inst, ctx?.abortEarly === true);\n }\n return superParse(payload, ctx);\n };\n});\nfunction handleUnionResults(results, final, inst, ctx) {\n for (const result of results) if (result.issues.length === 0) {\n final.value = result.value;\n return final;\n }\n const nonaborted = results.filter((r) => !aborted(r));\n if (nonaborted.length === 1) {\n final.value = nonaborted[0].value;\n return nonaborted[0];\n }\n final.issues.push({\n code: \"invalid_union\",\n input: final.value,\n inst,\n errors: results.map((result) => result.issues.map((iss) => finalizeIssue(iss, ctx, config())))\n });\n return final;\n}\nconst $ZodUnion = /*@__PURE__*/ $constructor(\"$ZodUnion\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.options.some((o) => o._zod.optin === \"defaulted\") ? \"defaulted\" : zod.def.options.some((o) => o._zod.optin !== void 0) ? \"optional\" : void 0);\n defineLazyInternal(inst, \"optout\", (zod) => zod.def.options.some((o) => o._zod.optout === \"optional\") ? \"optional\" : void 0);\n defineLazyInternal(inst, \"values\", (zod) => {\n if (zod.def.options.every((o) => o._zod.values)) return new Set(zod.def.options.flatMap((option) => Array.from(option._zod.values)));\n });\n defineLazyInternal(inst, \"pattern\", (zod) => {\n if (zod.def.options.every((o) => o._zod.pattern)) {\n const patterns = zod.def.options.map((o) => o._zod.pattern);\n return new RegExp(`^(${patterns.map((p) => cleanRegex(p.source)).join(\"|\")})$`);\n }\n });\n const first = def.options.length === 1 ? def.options[0]._zod.run : null;\n inst._zod.parse = (payload, ctx) => {\n if (first) return first(payload, ctx);\n let async = false;\n const results = [];\n for (const option of def.options) {\n const result = option._zod.run({\n value: payload.value,\n issues: []\n }, ctx);\n if (result instanceof Promise) {\n results.push(result);\n async = true;\n } else {\n if (result.issues.length === 0) return result;\n results.push(result);\n }\n }\n if (!async) return handleUnionResults(results, payload, inst, ctx);\n return Promise.all(results).then((results) => {\n return handleUnionResults(results, payload, inst, ctx);\n });\n };\n});\nconst $ZodIntersection = /*@__PURE__*/ $constructor(\"$ZodIntersection\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.parse = (payload, ctx) => {\n const input = payload.value;\n const left = def.left._zod.run({\n value: input,\n issues: []\n }, ctx);\n const right = def.right._zod.run({\n value: input,\n issues: []\n }, ctx);\n if (left instanceof Promise || right instanceof Promise) return Promise.all([left, right]).then(([left, right]) => {\n return handleIntersectionResults(payload, left, right);\n });\n return handleIntersectionResults(payload, left, right);\n };\n});\nfunction mergeValues(a, b) {\n if (a === b) return {\n valid: true,\n data: a\n };\n if (a instanceof Date && b instanceof Date && +a === +b) return {\n valid: true,\n data: a\n };\n if (isPlainObject(a) && isPlainObject(b)) {\n const bKeys = Object.keys(b);\n const sharedKeys = Object.keys(a).filter((key) => bKeys.indexOf(key) !== -1);\n const newObj = {\n ...a,\n ...b\n };\n if (Object.prototype.hasOwnProperty.call(newObj, \"__proto__\")) delete newObj.__proto__;\n for (const key of sharedKeys) {\n if (key === \"__proto__\") continue;\n const sharedValue = mergeValues(a[key], b[key]);\n if (!sharedValue.valid) return {\n valid: false,\n mergeErrorPath: [key, ...sharedValue.mergeErrorPath]\n };\n newObj[key] = sharedValue.data;\n }\n return {\n valid: true,\n data: newObj\n };\n }\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) return {\n valid: false,\n mergeErrorPath: []\n };\n const newArray = [];\n for (let index = 0; index < a.length; index++) {\n const itemA = a[index];\n const itemB = b[index];\n const sharedValue = mergeValues(itemA, itemB);\n if (!sharedValue.valid) return {\n valid: false,\n mergeErrorPath: [index, ...sharedValue.mergeErrorPath]\n };\n newArray.push(sharedValue.data);\n }\n return {\n valid: true,\n data: newArray\n };\n }\n return {\n valid: false,\n mergeErrorPath: []\n };\n}\nfunction handleIntersectionResults(result, left, right) {\n const unrecKeys = /* @__PURE__ */ new Map();\n let unrecIssue;\n const keyIssues = /* @__PURE__ */ new Map();\n const collect = (iss, side) => {\n let keys;\n if (iss.code === \"unrecognized_keys\" && !iss.path?.length) {\n unrecIssue ?? (unrecIssue = iss);\n keys = iss.keys;\n } else if (iss.code === \"invalid_key\" && iss.origin === \"record\" && iss.path?.length === 1) {\n const k = String(iss.path[0]);\n if (!keyIssues.has(k)) keyIssues.set(k, iss);\n keys = [k];\n } else return false;\n for (const k of keys) {\n if (!unrecKeys.has(k)) unrecKeys.set(k, {});\n unrecKeys.get(k)[side] = true;\n }\n return true;\n };\n for (const iss of left.issues) if (!collect(iss, \"l\")) result.issues.push(iss);\n for (const iss of right.issues) if (!collect(iss, \"r\")) result.issues.push(iss);\n const bothKeys = [...unrecKeys].filter(([, f]) => f.l && f.r).map(([k]) => k);\n if (bothKeys.length) {\n const aggregated = unrecIssue ? bothKeys.filter((k) => unrecIssue.keys.includes(k)) : [];\n if (aggregated.length) result.issues.push({\n ...unrecIssue,\n keys: aggregated\n });\n for (const k of bothKeys) if (!aggregated.includes(k) && keyIssues.has(k)) result.issues.push(keyIssues.get(k));\n }\n const merged = mergeValues(left.value, right.value);\n if (!merged.valid) {\n if (aborted(result)) return result;\n throw new Error(`Unmergable intersection. Error path: ${JSON.stringify(merged.mergeErrorPath)}`);\n }\n result.value = merged.data;\n return result;\n}\nconst $ZodRecord = /*@__PURE__*/ $constructor(\"$ZodRecord\", (inst, def) => {\n $ZodType.init(inst, def);\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n const input = payload.value;\n if (!isPlainObject(input)) {\n payload.issues.push({\n expected: \"record\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n const proms = [];\n const values = def.keyType._zod.values;\n if (values && !def.partial) {\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n const recordKeys = /* @__PURE__ */ new Set();\n for (const key of values) if (typeof key === \"string\" || typeof key === \"number\" || typeof key === \"symbol\") {\n recordKeys.add(typeof key === \"number\" ? key.toString() : key);\n if (key === \"__proto__\") continue;\n const keyResult = def.keyType._zod.run({\n value: key,\n issues: []\n }, ctx);\n if (keyResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (keyResult.issues.length) {\n payload.issues.push({\n code: \"invalid_key\",\n origin: \"record\",\n issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),\n input: key,\n path: [key],\n inst\n });\n continue;\n }\n const outKey = keyResult.value;\n if (outKey === \"__proto__\") continue;\n const result = def.valueType._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }));\n else {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }\n }\n let unrecognized;\n for (const key in input) if (!recordKeys.has(key)) {\n if (def.mode === \"loose\") {\n if (key === \"__proto__\") continue;\n payload.value[key] = input[key];\n } else {\n unrecognized = unrecognized ?? [];\n unrecognized.push(key);\n }\n }\n if (unrecognized && unrecognized.length > 0) payload.issues.push({\n code: \"unrecognized_keys\",\n input,\n inst,\n keys: unrecognized,\n continue: true\n });\n } else {\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n let unrecognized;\n for (const key of Reflect.ownKeys(input)) {\n if (key === \"__proto__\") continue;\n if (!Object.prototype.propertyIsEnumerable.call(input, key)) continue;\n let keyResult = def.keyType._zod.run({\n value: key,\n issues: []\n }, ctx);\n if (keyResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (typeof key === \"string\" && number.test(key) && keyResult.issues.length) {\n const retryResult = def.keyType._zod.run({\n value: Number(key),\n issues: []\n }, ctx);\n if (retryResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (retryResult.issues.length === 0) keyResult = retryResult;\n }\n if (keyResult.issues.length) {\n if (def.mode === \"loose\") payload.value[key] = input[key];\n else if (values) {\n unrecognized = unrecognized ?? [];\n unrecognized.push(key);\n } else payload.issues.push({\n code: \"invalid_key\",\n origin: \"record\",\n issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),\n input: key,\n path: [key],\n inst\n });\n continue;\n }\n const outKey = keyResult.value;\n if (outKey === \"__proto__\") continue;\n const result = def.valueType._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }));\n else {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }\n }\n if (unrecognized && unrecognized.length > 0) payload.issues.push({\n code: \"unrecognized_keys\",\n input,\n inst,\n keys: unrecognized,\n continue: true\n });\n }\n if (proms.length) return Promise.all(proms).then(() => payload);\n return payload;\n };\n});\nconst $ZodEnum = /*@__PURE__*/ $constructor(\"$ZodEnum\", (inst, def) => {\n $ZodType.init(inst, def);\n const values = getEnumValues(def.entries);\n const valuesSet = new Set(values);\n inst._zod.values = valuesSet;\n defineLazyInternal(inst, \"pattern\", (zod) => {\n const patternValues = getEnumValues(zod.def.entries).filter((k) => propertyKeyTypes.has(typeof k));\n return new RegExp(patternValues.length ? `^(${patternValues.map((o) => escapeRegex(o.toString())).join(\"|\")})$` : \"^[^\\\\s\\\\S]$\");\n });\n inst._zod.parse = (payload, _ctx) => {\n const input = payload.value;\n if (valuesSet.has(input)) return payload;\n payload.issues.push({\n code: \"invalid_value\",\n values,\n input,\n inst\n });\n return payload;\n };\n});\nconst $ZodTransform = /*@__PURE__*/ $constructor(\"$ZodTransform\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.optin = \"optional\";\n globalConfig.memoizer?.guard(inst);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") throw new $ZodEncodeError(inst.constructor.name);\n const _out = def.transform(payload.value, payload);\n if (ctx.async) return (_out instanceof Promise ? _out : Promise.resolve(_out)).then((output) => {\n payload.value = output;\n return payload;\n });\n if (_out instanceof Promise) throw new $ZodAsyncError();\n payload.value = _out;\n return payload;\n };\n});\nfunction handleOptionalResult(payload, result) {\n payload.value = result.issues.length ? void 0 : result.value;\n return payload;\n}\nconst $ZodOptional = /*@__PURE__*/ $constructor(\"$ZodOptional\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.innerType._zod.optin === \"defaulted\" ? \"defaulted\" : \"optional\");\n inst._zod.optout = \"optional\";\n defineLazyInternal(inst, \"values\", (zod) => {\n const values = zod.def.innerType._zod.values;\n return values ? /* @__PURE__ */ new Set([...values, void 0]) : void 0;\n });\n defineLazyInternal(inst, \"pattern\", (zod) => {\n const pattern = zod.def.innerType._zod.pattern;\n return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;\n });\n inst._zod.parse = (payload, ctx) => {\n if (payload.value === void 0) {\n if (def.innerType._zod.optin !== \"defaulted\") return payload;\n const result = def.innerType._zod.run({\n value: payload.value,\n issues: []\n }, ctx);\n if (result instanceof Promise) return result.then((result) => handleOptionalResult(payload, result));\n return handleOptionalResult(payload, result);\n }\n return def.innerType._zod.run(payload, ctx);\n };\n});\nconst $ZodExactOptional = /*@__PURE__*/ $constructor(\"$ZodExactOptional\", (inst, def) => {\n $ZodOptional.init(inst, def);\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n defineLazyInternal(inst, \"pattern\", (zod) => zod.def.innerType._zod.pattern);\n inst._zod.parse = (payload, ctx) => {\n return def.innerType._zod.run(payload, ctx);\n };\n});\nconst $ZodNullable = /*@__PURE__*/ $constructor(\"$ZodNullable\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.innerType._zod.optin);\n defineLazyInternal(inst, \"optout\", (zod) => zod.def.innerType._zod.optout);\n defineLazyInternal(inst, \"pattern\", (zod) => {\n const pattern = zod.def.innerType._zod.pattern;\n return pattern ? new RegExp(`^(${cleanRegex(pattern.source)}|null)$`) : void 0;\n });\n defineLazyInternal(inst, \"values\", (zod) => {\n return zod.def.innerType._zod.values ? /* @__PURE__ */ new Set([...zod.def.innerType._zod.values, null]) : void 0;\n });\n inst._zod.parse = (payload, ctx) => {\n if (payload.value === null) return payload;\n return def.innerType._zod.run(payload, ctx);\n };\n});\nconst $ZodDefault = /*@__PURE__*/ $constructor(\"$ZodDefault\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.optin = \"defaulted\";\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") return def.innerType._zod.run(payload, ctx);\n if (payload.value === void 0) {\n payload.value = def.defaultValue;\n return payload;\n }\n const result = def.innerType._zod.run(payload, ctx);\n if (result instanceof Promise) return result.then((result) => handleDefaultResult(result, def));\n return handleDefaultResult(result, def);\n };\n});\nfunction handleDefaultResult(payload, def) {\n if (payload.value === void 0) payload.value = def.defaultValue;\n return payload;\n}\nconst $ZodPrefault = /*@__PURE__*/ $constructor(\"$ZodPrefault\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.optin = \"defaulted\";\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") return def.innerType._zod.run(payload, ctx);\n if (payload.value === void 0) payload.value = def.defaultValue;\n return def.innerType._zod.run(payload, ctx);\n };\n});\nconst $ZodNonOptional = /*@__PURE__*/ $constructor(\"$ZodNonOptional\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"values\", (zod) => {\n const v = zod.def.innerType._zod.values;\n return v ? new Set([...v].filter((x) => x !== void 0)) : void 0;\n });\n inst._zod.parse = (payload, ctx) => {\n const result = def.innerType._zod.run(payload, ctx);\n if (result instanceof Promise) return result.then((result) => handleNonOptionalResult(result, inst));\n return handleNonOptionalResult(result, inst);\n };\n});\nfunction handleNonOptionalResult(payload, inst) {\n if (!payload.issues.length && payload.value === void 0) payload.issues.push({\n code: \"invalid_type\",\n expected: \"nonoptional\",\n input: payload.value,\n inst\n });\n return payload;\n}\nfunction handleCatchResult(payload, result, def, ctx) {\n if (!result.issues.length) {\n payload.value = result.value;\n if (result.memo) payload.memo = true;\n return payload;\n }\n payload.value = def.catchValue({\n ...result,\n value: payload.value,\n error: { issues: result.issues.map((iss) => finalizeIssue(iss, ctx, config())) },\n input: payload.value\n });\n return payload;\n}\nconst $ZodCatch = /*@__PURE__*/ $constructor(\"$ZodCatch\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.innerType._zod.optin === \"defaulted\" ? \"defaulted\" : \"optional\");\n defineLazyInternal(inst, \"optout\", (zod) => zod.def.innerType._zod.optout);\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") return def.innerType._zod.run(payload, ctx);\n const result = def.innerType._zod.run({\n value: payload.value,\n issues: []\n }, ctx);\n if (result instanceof Promise) return result.then((result) => handleCatchResult(payload, result, def, ctx));\n return handleCatchResult(payload, result, def, ctx);\n };\n});\nconst $ZodPipe = /*@__PURE__*/ $constructor(\"$ZodPipe\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"values\", (zod) => zod.def.in._zod.values);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.in._zod.optin);\n defineLazyInternal(inst, \"optout\", (zod) => zod.def.out._zod.optout);\n defineLazyInternal(inst, \"propValues\", (zod) => zod.def.in._zod.propValues);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") {\n const right = def.out._zod.run(payload, ctx);\n if (right instanceof Promise) return right.then((right) => handlePipeResult(right, def.in, ctx));\n return handlePipeResult(right, def.in, ctx);\n }\n const left = def.in._zod.run(payload, ctx);\n if (left instanceof Promise) return left.then((left) => handlePipeResult(left, def.out, ctx));\n return handlePipeResult(left, def.out, ctx);\n };\n});\nfunction handlePipeResult(left, next, ctx) {\n if (left.issues.some((iss) => iss.code !== \"unrecognized_keys\")) {\n left.aborted = true;\n return left;\n }\n return next._zod.run({\n value: left.value,\n issues: left.issues\n }, ctx);\n}\nconst $ZodReadonly = /*@__PURE__*/ $constructor(\"$ZodReadonly\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"propValues\", (zod) => zod.def.innerType._zod.propValues);\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.innerType?._zod?.optin);\n defineLazyInternal(inst, \"optout\", (zod) => zod.def.innerType?._zod?.optout);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") return def.innerType._zod.run(payload, ctx);\n const result = def.innerType._zod.run(payload, ctx);\n if (result instanceof Promise) return result.then(handleReadonlyResult);\n return handleReadonlyResult(result);\n };\n});\nfunction handleReadonlyResult(payload) {\n if (!payload.memo) payload.value = Object.freeze(payload.value);\n return payload;\n}\nconst $ZodCustom = /*@__PURE__*/ $constructor(\"$ZodCustom\", (inst, def) => {\n $ZodCheck.init(inst, def);\n $ZodType.init(inst, def);\n inst._zod.parse = (payload, _) => {\n return payload;\n };\n inst._zod.check = (payload) => {\n const input = payload.value;\n const r = def.fn(input);\n if (r instanceof Promise) return r.then((r) => handleRefineResult(r, payload, input, inst));\n handleRefineResult(r, payload, input, inst);\n };\n});\nfunction handleRefineResult(result, payload, input, inst) {\n if (!result) {\n const _iss = {\n code: \"custom\",\n input,\n inst,\n path: [...inst._zod.def.path ?? []],\n continue: !inst._zod.def.abort\n };\n if (inst._zod.def.params) _iss.params = inst._zod.def.params;\n payload.issues.push(issue(_iss));\n }\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/memoizer.js\nvar $ZodCyclicError = class extends Error {\n constructor() {\n super(`Cannot parse a reference cycle that closes through a transform`);\n this.name = \"ZodCyclicError\";\n }\n};\nconst STATE = \"~memo\";\nconst NO_ISSUES = [];\nfunction isRef(value) {\n return value !== null && typeof value === \"object\";\n}\nfunction cloneIssues(issues) {\n return issues.map((iss) => iss.path ? {\n ...iss,\n path: iss.path.slice()\n } : { ...iss });\n}\nconst recursive = /*@__PURE__*/ new WeakMap();\nconst NONE = 0;\nconst ASSUMED = 1;\nconst PROVEN = 2;\nfunction isRecursive(inst, stack, resolve) {\n const cached = recursive.get(inst);\n if (cached !== void 0) return cached ? PROVEN : NONE;\n if (stack.has(inst)) return PROVEN;\n stack.add(inst);\n let result = NONE;\n const check = (child) => {\n if (result !== PROVEN && child?._zod) {\n const answer = isRecursive(child, stack, resolve);\n if (answer > result) result = answer;\n }\n };\n const shape = (sh, spread) => {\n let answer = NONE;\n for (const key of Reflect.ownKeys(sh)) {\n const desc = Object.getOwnPropertyDescriptor(sh, key);\n if (spread && !desc.enumerable) continue;\n const child = desc.get ? ASSUMED : desc.value?._zod ? isRecursive(desc.value, stack, resolve) : NONE;\n if (child > answer) answer = child;\n }\n return answer;\n };\n const merge = (answer) => {\n if (answer > result) result = answer;\n };\n const def = inst._zod.def;\n switch (def.type) {\n case \"object\": {\n const raw = rawShape(def);\n merge(raw ? shape(raw, true) : ASSUMED);\n check(def.catchall);\n break;\n }\n case \"array\":\n check(def.element);\n break;\n case \"tuple\":\n for (const el of def.items) check(el);\n check(def.rest);\n break;\n case \"record\":\n case \"map\":\n check(def.keyType);\n check(def.valueType);\n break;\n case \"set\":\n check(def.valueType);\n break;\n case \"union\":\n for (const el of def.options) check(el);\n break;\n case \"intersection\":\n check(def.left);\n check(def.right);\n break;\n case \"optional\":\n case \"nullable\":\n case \"default\":\n case \"prefault\":\n case \"catch\":\n case \"readonly\":\n case \"nonoptional\":\n case \"promise\":\n case \"success\":\n check(def.innerType);\n break;\n case \"pipe\":\n check(def.in);\n check(def.out);\n break;\n case \"function\":\n check(def.input);\n check(def.output);\n break;\n case \"lazy\": {\n const inner = def._cachedInner ?? (resolve ? inst._zod.innerType : void 0);\n merge(inner ? isRecursive(inner, stack, false) : ASSUMED);\n break;\n }\n case \"template_literal\":\n case \"string\":\n case \"number\":\n case \"int\":\n case \"boolean\":\n case \"bigint\":\n case \"symbol\":\n case \"undefined\":\n case \"null\":\n case \"void\":\n case \"never\":\n case \"any\":\n case \"unknown\":\n case \"date\":\n case \"nan\":\n case \"enum\":\n case \"literal\":\n case \"file\":\n case \"transform\":\n case \"custom\": break;\n default: for (const key in def) {\n const desc = Object.getOwnPropertyDescriptor(def, key);\n if (!desc || desc.get) continue;\n const value = desc.value;\n if (!value || typeof value !== \"object\") continue;\n if (value._zod) check(value);\n else if (Array.isArray(value)) for (const el of value) check(el);\n }\n }\n stack.delete(inst);\n return settle(inst, result);\n}\nfunction settle(inst, answer) {\n if (answer !== ASSUMED) recursive.set(inst, answer === PROVEN);\n return answer;\n}\nfunction bucketFor(state, inst) {\n let bucket = state.buckets.get(inst);\n if (!bucket) {\n bucket = /* @__PURE__ */ new WeakMap();\n state.buckets.set(inst, bucket);\n }\n return bucket;\n}\nlet handoff;\nconst open = [];\nconst memo = {\n alloc(_inst, payload, empty) {\n const bucket = handoff;\n if (!bucket) return empty;\n handoff = void 0;\n const entry = {\n value: empty,\n issues: null\n };\n bucket.set(payload.value, entry);\n open.push(entry);\n return empty;\n },\n guard(inst) {\n var _a;\n (_a = inst._zod).deferred ?? (_a.deferred = []);\n inst._zod.deferred.push(() => {\n const base = inst._zod.parse;\n const wrapped = (payload, ctx) => {\n if (ctx.direction !== \"backward\" && isBackEdge(ctx, payload.value)) throw new $ZodCyclicError();\n return base(payload, ctx);\n };\n inst._zod.parse = wrapped;\n if (inst._zod.run === base) inst._zod.run = wrapped;\n });\n },\n attach(inst) {\n var _a;\n let isRecursiveInst;\n let rechecked = false;\n let lastCtx;\n let lastBucket;\n (_a = inst._zod).deferred ?? (_a.deferred = []);\n inst._zod.deferred.push(() => {\n const base = inst._zod.parse;\n const wrapped = (payload, ctx) => {\n if (isRecursiveInst === void 0) {\n const walked = isRecursive(inst, /* @__PURE__ */ new Set(), false);\n if (walked === NONE) {\n inst._zod.parse = base;\n if (inst._zod.run === wrapped) inst._zod.run = base;\n return base(payload, ctx);\n }\n if (walked === PROVEN || rechecked) isRecursiveInst = true;\n else rechecked = true;\n }\n const input = payload.value;\n if (!isRef(input)) return base(payload, ctx);\n let state = ctx[STATE];\n if (!state) {\n state = {\n buckets: /* @__PURE__ */ new WeakMap(),\n backEdges: void 0\n };\n ctx[STATE] = state;\n }\n let bucket;\n if (lastCtx === ctx) bucket = lastBucket;\n else {\n bucket = bucketFor(state, inst);\n lastCtx = ctx;\n lastBucket = bucket;\n }\n const hit = bucket.get(input);\n if (hit) {\n payload.value = hit.value;\n if (hit.issues) {\n if (hit.issues.length) payload.issues.push(...cloneIssues(hit.issues));\n } else {\n payload.memo = true;\n state.backEdges ?? (state.backEdges = /* @__PURE__ */ new WeakSet());\n state.backEdges.add(hit.value);\n }\n return payload;\n }\n handoff = bucket;\n const depth = open.length;\n const result = base(payload, ctx);\n handoff = void 0;\n const entry = open.length > depth ? open.pop() : void 0;\n if (result instanceof Promise) return result.then((r) => {\n if (entry) entry.issues = r.issues.length ? cloneIssues(r.issues) : NO_ISSUES;\n return r;\n });\n if (entry) entry.issues = result.issues.length ? cloneIssues(result.issues) : NO_ISSUES;\n return result;\n };\n inst._zod.parse = wrapped;\n if (inst._zod.run === base) inst._zod.run = wrapped;\n });\n }\n};\nfunction memoizer() {\n return memo;\n}\nfunction isBackEdge(ctx, value) {\n const backEdges = ctx[STATE]?.backEdges;\n return backEdges !== void 0 && isRef(value) && backEdges.has(value);\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/en.js\nconst error = () => {\n const Sizable = {\n string: {\n unit: \"characters\",\n verb: \"to have\"\n },\n file: {\n unit: \"bytes\",\n verb: \"to have\"\n },\n array: {\n unit: \"items\",\n verb: \"to have\"\n },\n set: {\n unit: \"items\",\n verb: \"to have\"\n },\n map: {\n unit: \"entries\",\n verb: \"to have\"\n }\n };\n function getSizing(origin) {\n return Sizable[origin] ?? null;\n }\n const FormatDictionary = {\n regex: \"input\",\n email: \"email address\",\n url: \"URL\",\n emoji: \"emoji\",\n uuid: \"UUID\",\n uuidv4: \"UUIDv4\",\n uuidv6: \"UUIDv6\",\n nanoid: \"nanoid\",\n guid: \"GUID\",\n cuid: \"cuid\",\n cuid2: \"cuid2\",\n ulid: \"ULID\",\n xid: \"XID\",\n ksuid: \"KSUID\",\n datetime: \"ISO datetime\",\n date: \"ISO date\",\n time: \"ISO time\",\n duration: \"ISO duration\",\n ipv4: \"IPv4 address\",\n ipv6: \"IPv6 address\",\n mac: \"MAC address\",\n cidrv4: \"IPv4 range\",\n cidrv6: \"IPv6 range\",\n base64: \"base64-encoded string\",\n base64url: \"base64url-encoded string\",\n json_string: \"JSON string\",\n e164: \"E.164 number\",\n currency_code: \"currency code\",\n credit_card: \"credit card number\",\n iban: \"IBAN\",\n jwt: \"JWT\",\n template_literal: \"input\"\n };\n const TypeDictionary = { nan: \"NaN\" };\n function getTypeName(type, input) {\n if (type === \"number\" && typeof input === \"number\" && !Number.isFinite(input)) return String(input);\n return TypeDictionary[type] ?? type;\n }\n return (issue) => {\n switch (issue.code) {\n case \"invalid_type\": return `Invalid input: expected ${getTypeName(issue.expected)}, received ${getTypeName(parsedType(issue.input), issue.input)}`;\n case \"invalid_value\":\n if (issue.values.length === 1) return `Invalid input: expected ${stringifyPrimitive(issue.values[0])}`;\n return `Invalid option: expected one of ${joinValues(issue.values, \"|\")}`;\n case \"too_big\": {\n const adj = issue.exact ? \"exactly \" : issue.inclusive ? \"<=\" : \"<\";\n const sizing = getSizing(issue.origin);\n if (sizing) return `Too big: expected ${issue.origin ?? \"value\"} to have ${adj}${issue.maximum.toString()} ${sizing.unit ?? \"elements\"}`;\n return `Too big: expected ${issue.origin ?? \"value\"} to be ${adj}${issue.maximum.toString()}`;\n }\n case \"too_small\": {\n const adj = issue.exact ? \"exactly \" : issue.inclusive ? \">=\" : \">\";\n const sizing = getSizing(issue.origin);\n if (sizing) return `Too small: expected ${issue.origin} to have ${adj}${issue.minimum.toString()} ${sizing.unit}`;\n return `Too small: expected ${issue.origin} to be ${adj}${issue.minimum.toString()}`;\n }\n case \"invalid_format\": {\n const _issue = issue;\n if (_issue.format === \"starts_with\") return `Invalid string: must start with \"${_issue.prefix}\"`;\n if (_issue.format === \"ends_with\") return `Invalid string: must end with \"${_issue.suffix}\"`;\n if (_issue.format === \"includes\") return `Invalid string: must include \"${_issue.includes}\"`;\n if (_issue.format === \"regex\") return `Invalid string: must match pattern ${_issue.pattern}`;\n return `Invalid ${FormatDictionary[_issue.format] ?? issue.format}`;\n }\n case \"not_multiple_of\": return `Invalid number: must be a multiple of ${issue.divisor}`;\n case \"unrecognized_keys\": return `Unrecognized key${issue.keys.length > 1 ? \"s\" : \"\"}: ${joinValues(issue.keys, \", \")}`;\n case \"invalid_key\": return `Invalid key in ${issue.origin}`;\n case \"invalid_union\":\n if (issue.options && Array.isArray(issue.options) && issue.options.length > 0) return `Invalid discriminator value. Expected ${issue.options.map((o) => `'${o}'`).join(\" | \")}`;\n if (issue.inclusive === false) return \"Invalid input: more than one option matched\";\n return \"Invalid input\";\n case \"invalid_element\": return `Invalid value in ${issue.origin}`;\n default: return `Invalid input`;\n }\n };\n};\nfunction en_default() {\n return { localeError: error() };\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/registries.js\nvar _a;\nvar $ZodRegistry = class {\n constructor() {\n this._map = /* @__PURE__ */ new WeakMap();\n this._idmap = /* @__PURE__ */ new Map();\n }\n add(schema, ..._meta) {\n const meta = _meta[0];\n this._map.set(schema, meta);\n if (meta && typeof meta === \"object\" && \"id\" in meta) this._idmap.set(meta.id, schema);\n return this;\n }\n clear() {\n this._map = /* @__PURE__ */ new WeakMap();\n this._idmap = /* @__PURE__ */ new Map();\n return this;\n }\n remove(schema) {\n const meta = this._map.get(schema);\n if (meta && typeof meta === \"object\" && \"id\" in meta) this._idmap.delete(meta.id);\n this._map.delete(schema);\n return this;\n }\n get(schema) {\n const p = schema._zod.parent;\n if (p) {\n const pm = { ...this.get(p) ?? {} };\n delete pm.id;\n const f = {\n ...pm,\n ...this._map.get(schema)\n };\n return Object.keys(f).length ? f : void 0;\n }\n return this._map.get(schema);\n }\n has(schema) {\n return this._map.has(schema);\n }\n};\nfunction registry() {\n return new $ZodRegistry();\n}\n(_a = globalThis).__zod_globalRegistry ?? (_a.__zod_globalRegistry = registry());\nconst globalRegistry = globalThis.__zod_globalRegistry;\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/api.js\nfunction snapshotChecks(def) {\n if (def.checks) def.checks = [...def.checks];\n return def;\n}\n// @__NO_SIDE_EFFECTS__\nfunction _string(Class, params) {\n return new Class(snapshotChecks({\n type: \"string\",\n ...normalizeParams(params)\n }));\n}\n// @__NO_SIDE_EFFECTS__\nfunction _email(Class, params) {\n return new Class({\n type: \"string\",\n format: \"email\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _guid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"guid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _uuid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"uuid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _uuidv4(Class, params) {\n return new Class({\n type: \"string\",\n format: \"uuid\",\n check: \"string_format\",\n abort: false,\n version: \"v4\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _uuidv6(Class, params) {\n return new Class({\n type: \"string\",\n format: \"uuid\",\n check: \"string_format\",\n abort: false,\n version: \"v6\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _uuidv7(Class, params) {\n return new Class({\n type: \"string\",\n format: \"uuid\",\n check: \"string_format\",\n abort: false,\n version: \"v7\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _url(Class, params) {\n return new Class({\n type: \"string\",\n format: \"url\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _emoji(Class, params) {\n return new Class({\n type: \"string\",\n format: \"emoji\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _nanoid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"nanoid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _cuid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"cuid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _cuid2(Class, params) {\n return new Class({\n type: \"string\",\n format: \"cuid2\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _ulid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"ulid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _xid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"xid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _ksuid(Class, params) {\n return new Class({\n type: \"string\",\n format: \"ksuid\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _ipv4(Class, params) {\n return new Class({\n type: \"string\",\n format: \"ipv4\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _ipv6(Class, params) {\n return new Class({\n type: \"string\",\n format: \"ipv6\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _cidrv4(Class, params) {\n return new Class({\n type: \"string\",\n format: \"cidrv4\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _cidrv6(Class, params) {\n return new Class({\n type: \"string\",\n format: \"cidrv6\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _base64(Class, params) {\n return new Class({\n type: \"string\",\n format: \"base64\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _base64url(Class, params) {\n return new Class({\n type: \"string\",\n format: \"base64url\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _e164(Class, params) {\n return new Class({\n type: \"string\",\n format: \"e164\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _jwt(Class, params) {\n return new Class({\n type: \"string\",\n format: \"jwt\",\n check: \"string_format\",\n abort: false,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _isoDateTime(Class, params) {\n return new Class({\n type: \"string\",\n format: \"datetime\",\n check: \"string_format\",\n offset: false,\n local: false,\n precision: null,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _isoDate(Class, params) {\n return new Class({\n type: \"string\",\n format: \"date\",\n check: \"string_format\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _isoTime(Class, params) {\n return new Class({\n type: \"string\",\n format: \"time\",\n check: \"string_format\",\n precision: null,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _isoDuration(Class, params) {\n return new Class({\n type: \"string\",\n format: \"duration\",\n check: \"string_format\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _unknown(Class) {\n return new Class({ type: \"unknown\" });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _never(Class, params) {\n return new Class({\n type: \"never\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _maxLength(maximum, params) {\n return new $ZodCheckMaxLength({\n check: \"max_length\",\n ...normalizeParams(params),\n maximum\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _minLength(minimum, params) {\n return new $ZodCheckMinLength({\n check: \"min_length\",\n ...normalizeParams(params),\n minimum\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _length(length, params) {\n return new $ZodCheckLengthEquals({\n check: \"length_equals\",\n ...normalizeParams(params),\n length\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _regex(pattern, params) {\n return new $ZodCheckRegex({\n check: \"string_format\",\n format: \"regex\",\n ...normalizeParams(params),\n pattern\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _lowercase(params) {\n return new $ZodCheckLowerCase({\n check: \"string_format\",\n format: \"lowercase\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _uppercase(params) {\n return new $ZodCheckUpperCase({\n check: \"string_format\",\n format: \"uppercase\",\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _includes(includes, params) {\n return new $ZodCheckIncludes({\n check: \"string_format\",\n format: \"includes\",\n ...normalizeParams(params),\n includes\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _startsWith(prefix, params) {\n return new $ZodCheckStartsWith({\n check: \"string_format\",\n format: \"starts_with\",\n ...normalizeParams(params),\n prefix\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _endsWith(suffix, params) {\n return new $ZodCheckEndsWith({\n check: \"string_format\",\n format: \"ends_with\",\n ...normalizeParams(params),\n suffix\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _overwrite(tx) {\n return new $ZodCheckOverwrite({\n check: \"overwrite\",\n tx\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _normalize(form) {\n return /* @__PURE__ */ _overwrite((input) => input.normalize(form));\n}\n// @__NO_SIDE_EFFECTS__\nfunction _trim() {\n return /* @__PURE__ */ _overwrite((input) => input.trim());\n}\n// @__NO_SIDE_EFFECTS__\nfunction _toLowerCase() {\n return /* @__PURE__ */ _overwrite((input) => input.toLowerCase());\n}\n// @__NO_SIDE_EFFECTS__\nfunction _toUpperCase() {\n return /* @__PURE__ */ _overwrite((input) => input.toUpperCase());\n}\n// @__NO_SIDE_EFFECTS__\nfunction _slugify() {\n return /* @__PURE__ */ _overwrite((input) => slugify(input));\n}\n// @__NO_SIDE_EFFECTS__\nfunction _array(Class, element, params) {\n return new Class({\n type: \"array\",\n element,\n ...normalizeParams(params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _refine(Class, fn, _params) {\n return new Class({\n type: \"custom\",\n check: \"custom\",\n fn,\n ...normalizeParams(_params)\n });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _superRefine(fn, params) {\n const ch = /* @__PURE__ */ _check((payload) => {\n payload.addIssue = (issue$2) => {\n if (typeof issue$2 === \"string\") payload.issues.push(issue(issue$2, payload.value, ch._zod.def));\n else {\n const _issue = issue$2;\n if (_issue.fatal) _issue.continue = false;\n _issue.code ?? (_issue.code = \"custom\");\n if (!(\"input\" in _issue)) _issue.input = payload.value;\n _issue.inst ?? (_issue.inst = ch);\n _issue.continue ?? (_issue.continue = !ch._zod.def.abort);\n payload.issues.push(issue(_issue));\n }\n };\n return fn(payload.value, payload);\n }, params);\n return ch;\n}\n// @__NO_SIDE_EFFECTS__\nfunction _check(fn, params) {\n const ch = new $ZodCheck({\n check: \"custom\",\n ...normalizeParams(params)\n });\n ch._zod.check = fn;\n return ch;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/to-json-schema.js\nfunction assignProps(target, ...sources) {\n for (const source of sources) for (const key of Reflect.ownKeys(source)) if (Object.prototype.propertyIsEnumerable.call(source, key)) assignProp(target, key, source[key]);\n return target;\n}\nfunction initializeContext(params) {\n let target = params?.target ?? \"draft-2020-12\";\n if (target === \"draft-4\") target = \"draft-04\";\n if (target === \"draft-7\") target = \"draft-07\";\n return {\n processors: params.processors ?? {},\n metadataRegistry: params?.metadata ?? globalRegistry,\n target,\n unrepresentable: params?.unrepresentable ?? \"throw\",\n override: params?.override ?? (() => {}),\n io: params?.io ?? \"output\",\n counter: 0,\n seen: /* @__PURE__ */ new Map(),\n sharedDefsExtractedFor: void 0,\n sharedEmitDoneFor: void 0,\n cycles: params?.cycles ?? \"ref\",\n reused: params?.reused ?? \"inline\",\n intersections: [],\n deferred: [],\n external: params?.external ?? void 0\n };\n}\nfunction handleUnrepresentable(schema, ctx, json, params, message) {\n const result = typeof ctx.unrepresentable === \"function\" ? ctx.unrepresentable({\n zodSchema: schema,\n path: params.path,\n message\n }) : ctx.unrepresentable;\n if (result === \"any\") return false;\n if (result === void 0 || result === \"throw\") throw new Error(message);\n Object.assign(json, result);\n return true;\n}\nfunction processSchema(schema, ctx, _params = {\n path: [],\n schemaPath: []\n}) {\n var _a;\n const def = schema._zod.def;\n const seen = ctx.seen.get(schema);\n if (seen) {\n seen.count++;\n if (_params.schemaPath.includes(schema)) seen.cycle = _params.path;\n return seen.schema;\n }\n const result = {\n schema: {},\n count: 1,\n cycle: void 0,\n path: _params.path\n };\n ctx.seen.set(schema, result);\n ctx.sharedDefsExtractedFor = void 0;\n ctx.sharedEmitDoneFor = void 0;\n const overrideSchema = schema._zod.toJSONSchema?.();\n if (overrideSchema) result.schema = overrideSchema;\n else {\n const params = {\n ..._params,\n schemaPath: [..._params.schemaPath, schema],\n path: _params.path\n };\n if (schema._zod.processJSONSchema) schema._zod.processJSONSchema(ctx, result.schema, params);\n else {\n const _json = result.schema;\n const processor = ctx.processors[def.type];\n if (!processor) throw new Error(`[toJSONSchema]: Non-representable type encountered: ${def.type}`);\n processor(schema, ctx, _json, params);\n }\n const parent = schema._zod.parent;\n if (parent) {\n if (!result.ref) result.ref = parent;\n processSchema(parent, ctx, params);\n ctx.seen.get(parent).isParent = true;\n }\n }\n const meta = ctx.metadataRegistry.get(schema);\n if (meta) assignProps(result.schema, meta);\n if (ctx.io === \"input\" && isTransforming(schema)) {\n delete result.schema.examples;\n delete result.schema.default;\n }\n if (ctx.io === \"input\" && \"_prefault\" in result.schema) (_a = result.schema).default ?? (_a.default = result.schema._prefault);\n delete result.schema._prefault;\n return ctx.seen.get(schema).schema;\n}\nfunction encodeJSONPointerSegment(segment) {\n return segment.replace(/~/g, \"~0\").replace(/\\//g, \"~1\");\n}\nfunction extractDefs(ctx, schema) {\n const root = ctx.seen.get(schema);\n if (!root) throw new Error(\"Unprocessed schema. This is a bug in Zod.\");\n if (ctx.external && ctx.sharedDefsExtractedFor === ctx.external) return;\n const idToSchema = /* @__PURE__ */ new Map();\n for (const entry of ctx.seen.entries()) {\n const id = ctx.metadataRegistry.get(entry[0])?.id;\n if (id) {\n const existing = idToSchema.get(id);\n if (existing && existing !== entry[0]) throw new Error(`Duplicate schema id \"${id}\" detected during JSON Schema conversion. Two different schemas cannot share the same id when converted together.`);\n idToSchema.set(id, entry[0]);\n }\n }\n const makeURI = (entry) => {\n const defsSegment = ctx.target === \"draft-2020-12\" ? \"$defs\" : \"definitions\";\n if (ctx.external) {\n const externalId = ctx.external.registry.get(entry[0])?.id;\n const uriGenerator = ctx.external.uri ?? ((id) => id);\n if (externalId) return { ref: uriGenerator(externalId) };\n const id = entry[1].defId ?? entry[1].schema.id ?? `schema${ctx.counter++}`;\n entry[1].defId = id;\n return {\n defId: id,\n ref: `${uriGenerator(\"__shared\")}#/${defsSegment}/${encodeJSONPointerSegment(id)}`\n };\n }\n const uriPrefix = `#`;\n const defUriPrefix = `${uriPrefix}/${defsSegment}/`;\n if (entry[1] === root && !entry[1].schema.id) return { ref: uriPrefix };\n const defId = entry[1].schema.id ?? `__schema${ctx.counter++}`;\n return {\n defId,\n ref: defUriPrefix + encodeJSONPointerSegment(defId)\n };\n };\n const extractToDef = (entry) => {\n if (entry[1].schema.$ref) return;\n const seen = entry[1];\n const { ref, defId } = makeURI(entry);\n seen.def = { ...seen.schema };\n if (defId) seen.defId = defId;\n const schema = seen.schema;\n for (const key in schema) delete schema[key];\n schema.$ref = ref;\n };\n if (ctx.cycles === \"throw\") for (const entry of ctx.seen.entries()) {\n const seen = entry[1];\n if (seen.cycle) throw new Error(`Cycle detected: #/${seen.cycle?.join(\"/\")}/<root>\n\nSet the \\`cycles\\` parameter to \\`\"ref\"\\` to resolve cyclical schemas with defs.`);\n }\n for (const entry of ctx.seen.entries()) {\n const seen = entry[1];\n if (schema === entry[0]) {\n extractToDef(entry);\n continue;\n }\n if (ctx.external) {\n const ext = ctx.external.registry.get(entry[0])?.id;\n if (schema !== entry[0] && ext) {\n extractToDef(entry);\n continue;\n }\n }\n if (ctx.metadataRegistry.get(entry[0])?.id) {\n extractToDef(entry);\n continue;\n }\n if (seen.cycle) {\n extractToDef(entry);\n continue;\n }\n if (seen.count > 1) {\n if (ctx.reused === \"ref\") extractToDef(entry);\n }\n }\n if (ctx.external) ctx.sharedDefsExtractedFor = ctx.external;\n}\nfunction compactTypeUnion(schema) {\n const options = schema.anyOf;\n if (!Array.isArray(options) || options.length === 0 || schema.type !== void 0) return;\n const types = [];\n for (const option of options) {\n if (!option || typeof option !== \"object\") return;\n compactTypeUnion(option);\n const keys = Object.keys(option);\n if (keys.length !== 1 || keys[0] !== \"type\") return;\n const type = option.type;\n for (const member of Array.isArray(type) ? type : [type]) {\n if (typeof member !== \"string\") return;\n if (!types.includes(member)) types.push(member);\n }\n }\n delete schema.anyOf;\n schema.type = types.length === 1 ? types[0] : types;\n}\nconst FOLDABLE_KEYS = /* @__PURE__ */ new Set([\n \"type\",\n \"properties\",\n \"required\",\n \"additionalProperties\"\n]);\nconst UNION_KEYS = [\"oneOf\", \"anyOf\"];\nfunction undeclaredConstraint(member) {\n const extra = member.additionalProperties;\n if (extra === void 0 || extra === false || typeof extra !== \"object\" || extra === null) return null;\n return Object.keys(extra).length ? extra : null;\n}\nfunction foldObjects(members) {\n const objects = [];\n for (const member of members) {\n if (typeof member !== \"object\" || member.type !== \"object\") return null;\n for (const key in member) if (!FOLDABLE_KEYS.has(key)) return null;\n objects.push(member);\n }\n const properties = {};\n const required = /* @__PURE__ */ new Set();\n for (const object of objects) {\n for (const key in object.properties) {\n if (Object.prototype.hasOwnProperty.call(properties, key)) continue;\n const parts = [];\n for (const other of objects) {\n const part = other.properties?.[key] ?? undeclaredConstraint(other);\n if (part === null || part === void 0) continue;\n if (!parts.some((seen) => JSON.stringify(seen) === JSON.stringify(part))) parts.push(part);\n }\n const merged = parts.length === 1 ? parts[0] : foldObjects(parts) ?? { allOf: parts };\n assignProp(properties, key, merged);\n }\n for (const key of object.required ?? []) required.add(key);\n }\n const folded = {\n type: \"object\",\n properties\n };\n if (required.size) folded.required = [...required];\n if (objects.every((object) => object.additionalProperties === false)) folded.additionalProperties = false;\n else {\n const constraints = [];\n for (const object of objects) {\n const constraint = undeclaredConstraint(object);\n if (constraint && !constraints.some((seen) => JSON.stringify(seen) === JSON.stringify(constraint))) constraints.push(constraint);\n }\n if (constraints.length === 1) folded.additionalProperties = constraints[0];\n else if (constraints.length > 1) folded.additionalProperties = { allOf: constraints };\n }\n return folded;\n}\nfunction foldIntersection(json) {\n const allOf = json.allOf;\n if (!Array.isArray(allOf) || allOf.length < 2) return;\n for (const key of FOLDABLE_KEYS) if (key in json) return;\n const unions = allOf.filter((m) => UNION_KEYS.some((k) => Array.isArray(m[k])));\n let folded = null;\n if (!unions.length) folded = foldObjects(allOf);\n else {\n const union = unions[0];\n const keyword = UNION_KEYS.find((k) => Array.isArray(union[k]));\n if (Object.keys(union).length !== 1) return;\n const rest = allOf.filter((m) => m !== union);\n const branches = union[keyword].map((branch) => foldObjects([...rest, branch]));\n if (branches.some((b) => !b)) return;\n folded = { [keyword]: branches };\n }\n if (!folded) return;\n delete json.allOf;\n assignProps(json, folded);\n}\nfunction finalize(ctx, schema) {\n const root = ctx.seen.get(schema);\n if (!root) throw new Error(\"Unprocessed schema. This is a bug in Zod.\");\n const flattenRef = (zodSchema) => {\n const seen = ctx.seen.get(zodSchema);\n if (seen.ref === null) return;\n const schema = seen.def ?? seen.schema;\n const _cached = { ...schema };\n const ref = seen.ref;\n seen.ref = null;\n if (ref) {\n flattenRef(ref);\n const refSeen = ctx.seen.get(ref);\n const refSchema = refSeen.schema;\n if (refSchema.$ref && (ctx.target === \"draft-07\" || ctx.target === \"draft-04\" || ctx.target === \"openapi-3.0\")) {\n schema.allOf = schema.allOf ?? [];\n schema.allOf.push(refSchema);\n } else assignProps(schema, refSchema);\n assignProps(schema, _cached);\n if (zodSchema._zod.parent === ref) for (const key in schema) {\n if (key === \"$ref\" || key === \"allOf\") continue;\n if (!(key in _cached)) delete schema[key];\n }\n if (refSchema.$ref && refSeen.def) for (const key in schema) {\n if (key === \"$ref\" || key === \"allOf\") continue;\n if (key in refSeen.def && JSON.stringify(schema[key]) === JSON.stringify(refSeen.def[key])) delete schema[key];\n }\n }\n const parent = zodSchema._zod.parent;\n if (parent && parent !== ref) {\n flattenRef(parent);\n const parentSeen = ctx.seen.get(parent);\n if (parentSeen?.schema.$ref) {\n schema.$ref = parentSeen.schema.$ref;\n if (parentSeen.def) for (const key in schema) {\n if (key === \"$ref\" || key === \"allOf\") continue;\n if (key in parentSeen.def && JSON.stringify(schema[key]) === JSON.stringify(parentSeen.def[key])) delete schema[key];\n }\n }\n }\n ctx.override({\n zodSchema,\n jsonSchema: schema,\n path: seen.path ?? []\n });\n };\n if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) {\n for (const entry of [...ctx.seen.entries()].reverse()) flattenRef(entry[0]);\n if (ctx.target !== \"openapi-3.0\") for (const entry of ctx.seen.entries()) compactTypeUnion(entry[1].def ?? entry[1].schema);\n for (const rewrite of ctx.deferred) rewrite();\n if (ctx.intersections.length) {\n const carriers = /* @__PURE__ */ new Map();\n for (const seen of ctx.seen.values()) for (const json of [seen.schema, seen.def]) {\n const allOf = json?.allOf;\n if (!Array.isArray(allOf)) continue;\n const existing = carriers.get(allOf);\n if (existing) existing.push(json);\n else carriers.set(allOf, [json]);\n }\n for (const allOf of ctx.intersections) for (const json of carriers.get(allOf) ?? []) foldIntersection(json);\n }\n }\n const result = {};\n if (ctx.target === \"draft-2020-12\") result.$schema = \"https://json-schema.org/draft/2020-12/schema\";\n else if (ctx.target === \"draft-07\") result.$schema = \"http://json-schema.org/draft-07/schema#\";\n else if (ctx.target === \"draft-04\") result.$schema = \"http://json-schema.org/draft-04/schema#\";\n else if (ctx.target === \"openapi-3.0\") {}\n if (ctx.external?.uri) {\n const id = ctx.external.registry.get(schema)?.id;\n if (!id) throw new Error(\"Schema is missing an `id` property\");\n result.$id = ctx.external.uri(id);\n }\n assignProps(result, root.defId ? root.schema : root.def ?? root.schema);\n const rootMetaId = ctx.metadataRegistry.get(schema)?.id;\n if (rootMetaId !== void 0 && result.id === rootMetaId) delete result.id;\n const defs = ctx.external?.defs ?? {};\n if (!ctx.external || ctx.sharedEmitDoneFor !== ctx.external) for (const entry of ctx.seen.entries()) {\n const seen = entry[1];\n if (seen.def && seen.defId) {\n if (seen.def.id === seen.defId) delete seen.def.id;\n assignProp(defs, seen.defId, seen.def);\n }\n }\n if (ctx.external) ctx.sharedEmitDoneFor = ctx.external;\n if (ctx.external) {} else if (Object.keys(defs).length > 0) {\n if (ctx.target === \"draft-2020-12\") result.$defs = defs;\n else result.definitions = defs;\n }\n try {\n const finalized = JSON.parse(JSON.stringify(result));\n Object.defineProperty(finalized, \"~standard\", {\n value: {\n ...schema[\"~standard\"],\n jsonSchema: {\n input: createStandardJSONSchemaMethod(schema, \"input\", ctx.processors),\n output: createStandardJSONSchemaMethod(schema, \"output\", ctx.processors)\n }\n },\n enumerable: false,\n writable: false\n });\n return finalized;\n } catch (_err) {\n throw new Error(\"Error converting schema to JSON.\");\n }\n}\nfunction isTransforming(_schema, _ctx) {\n const ctx = _ctx ?? { seen: /* @__PURE__ */ new Set() };\n if (ctx.seen.has(_schema)) return false;\n ctx.seen.add(_schema);\n const def = _schema._zod.def;\n if (def.type === \"transform\") return true;\n if (def.type === \"array\") return isTransforming(def.element, ctx);\n if (def.type === \"set\") return isTransforming(def.valueType, ctx);\n if (def.type === \"lazy\") return isTransforming(def.getter(), ctx);\n if (def.type === \"promise\" || def.type === \"optional\" || def.type === \"nonoptional\" || def.type === \"nullable\" || def.type === \"readonly\" || def.type === \"default\" || def.type === \"prefault\" || def.type === \"catch\") return isTransforming(def.innerType, ctx);\n if (def.type === \"intersection\") return isTransforming(def.left, ctx) || isTransforming(def.right, ctx);\n if (def.type === \"record\" || def.type === \"map\") return isTransforming(def.keyType, ctx) || isTransforming(def.valueType, ctx);\n if (def.type === \"pipe\") {\n if (_schema._zod.traits.has(\"$ZodCodec\")) return true;\n return isTransforming(def.in, ctx) || isTransforming(def.out, ctx);\n }\n if (def.type === \"object\") {\n for (const key in def.shape) if (isTransforming(def.shape[key], ctx)) return true;\n return false;\n }\n if (def.type === \"union\") {\n for (const option of def.options) if (isTransforming(option, ctx)) return true;\n return false;\n }\n if (def.type === \"tuple\") {\n for (const item of def.items) if (isTransforming(item, ctx)) return true;\n if (def.rest && isTransforming(def.rest, ctx)) return true;\n return false;\n }\n return false;\n}\nconst createToJSONSchemaMethod = (schema, processors = {}) => (params) => {\n const ctx = initializeContext({\n ...params,\n processors\n });\n processSchema(schema, ctx);\n extractDefs(ctx, schema);\n return finalize(ctx, schema);\n};\nconst createStandardJSONSchemaMethod = (schema, io, processors = {}) => (params) => {\n const { libraryOptions, target } = params ?? {};\n const ctx = initializeContext({\n ...libraryOptions ?? {},\n target,\n io,\n processors\n });\n processSchema(schema, ctx);\n extractDefs(ctx, schema);\n return finalize(ctx, schema);\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/json-schema-processors.js\nconst narrowMin = (agg, key, value) => {\n if (agg[key] === void 0 || value > agg[key]) agg[key] = value;\n};\nconst narrowMax = (agg, key, value) => {\n if (agg[key] === void 0 || value < agg[key]) agg[key] = value;\n};\nconst narrowBoth = (agg, value) => {\n narrowMin(agg, \"minimum\", value);\n narrowMax(agg, \"maximum\", value);\n};\nconst addDivisor = (agg, value) => {\n agg.multipleOf ?? (agg.multipleOf = []);\n if (!agg.multipleOf.includes(value)) agg.multipleOf.push(value);\n};\nconst addPattern = (agg, pattern) => {\n agg.patterns ?? (agg.patterns = /* @__PURE__ */ new Set());\n agg.patterns.add(pattern);\n};\nconst intersectMime = (agg, mime) => {\n agg.mime = agg.mime ? agg.mime.filter((m) => mime.includes(m)) : [...mime];\n};\nconst setFormat = (agg, format) => {\n agg.format = format;\n if (format.includes(\"int\")) agg.isInt = true;\n};\nconst minContributor = (agg, def) => narrowMin(agg, \"minimum\", def.minimum);\nconst maxContributor = (agg, def) => narrowMax(agg, \"maximum\", def.maximum);\nconst formatContributor = (ranges) => (agg, def) => {\n setFormat(agg, def.format);\n const [minimum, maximum] = ranges[def.format];\n narrowMin(agg, \"minimum\", minimum);\n narrowMax(agg, \"maximum\", maximum);\n};\nconst contributors = {\n greater_than: (agg, def) => narrowMin(agg, def.inclusive ? \"minimum\" : \"exclusiveMinimum\", def.value),\n less_than: (agg, def) => narrowMax(agg, def.inclusive ? \"maximum\" : \"exclusiveMaximum\", def.value),\n multiple_of: (agg, def) => addDivisor(agg, def.value),\n number_format: formatContributor(NUMBER_FORMAT_RANGES),\n bigint_format: formatContributor(BIGINT_FORMAT_RANGES),\n min_length: minContributor,\n max_length: maxContributor,\n length_equals: (agg, def) => narrowBoth(agg, def.length),\n min_size: minContributor,\n max_size: maxContributor,\n size_equals: (agg, def) => narrowBoth(agg, def.size),\n string_format: (agg, def) => {\n setFormat(agg, def.format);\n if (def.pattern) addPattern(agg, def.pattern);\n if (def.format === \"base64\" || def.format === \"base64url\") agg.contentEncoding = def.format;\n if (def.local || def.precision === -1) agg.laxFormat = true;\n },\n mime_type: (agg, def) => intersectMime(agg, def.mime)\n};\nfunction aggregateChecks(schema) {\n const agg = {};\n const def = schema._zod.def;\n const list = schema._zod.traits.has(\"$ZodCheck\") ? [schema, ...def.checks ?? []] : def.checks ?? [];\n for (const ch of list) contributors[ch._zod.def.check]?.(agg, ch._zod.def);\n const bag = schema._zod.bag;\n if (bag.minimum !== void 0) narrowMin(agg, \"minimum\", bag.minimum);\n if (bag.exclusiveMinimum !== void 0) narrowMin(agg, \"exclusiveMinimum\", bag.exclusiveMinimum);\n if (bag.maximum !== void 0) narrowMax(agg, \"maximum\", bag.maximum);\n if (bag.exclusiveMaximum !== void 0) narrowMax(agg, \"exclusiveMaximum\", bag.exclusiveMaximum);\n if (bag.multipleOf !== void 0) addDivisor(agg, bag.multipleOf);\n if (bag.format !== void 0) {\n agg.format ?? (agg.format = bag.format);\n if (bag.format.includes(\"int\")) agg.isInt = true;\n }\n if (bag.mime) intersectMime(agg, bag.mime);\n for (const pattern of bag.patterns ?? []) addPattern(agg, pattern);\n return agg;\n}\nconst formatMap = {\n guid: \"uuid\",\n url: \"uri\",\n datetime: \"date-time\",\n json_string: \"json-string\",\n regex: \"\"\n};\nconst exactPatterns = /* @__PURE__ */ new Map([[base64Charset, base64], [base64urlCharset, base64url]]);\nconst exactPattern = (p) => exactPatterns.get(p) ?? p;\nconst stringProcessor = (schema, ctx, _json, _params) => {\n const json = _json;\n json.type = \"string\";\n const { minimum, maximum, format, patterns, contentEncoding, laxFormat } = aggregateChecks(schema);\n if (typeof minimum === \"number\") json.minLength = minimum;\n if (typeof maximum === \"number\") json.maxLength = maximum;\n if (format) {\n json.format = formatMap[format] ?? format;\n if (json.format === \"\") delete json.format;\n if (format === \"time\" || laxFormat) delete json.format;\n }\n if (contentEncoding) json.contentEncoding = contentEncoding;\n if (patterns && patterns.size > 0) {\n const patternList = [...patterns].map(exactPattern);\n if (patternList.length === 1) json.pattern = patternList[0].source;\n else if (patternList.length > 1) json.allOf = [...patternList.map((regex) => ({\n ...ctx.target === \"draft-07\" || ctx.target === \"draft-04\" || ctx.target === \"openapi-3.0\" ? { type: \"string\" } : {},\n pattern: regex.source\n }))];\n }\n};\nconst neverProcessor = (_schema, _ctx, json, _params) => {\n json.not = {};\n};\nconst unknownProcessor = (_schema, _ctx, _json, _params) => {};\nconst enumProcessor = (schema, _ctx, json, _params) => {\n const def = schema._zod.def;\n const values = getEnumValues(def.entries);\n if (values.length === 0) {\n json.not = {};\n return;\n }\n if (values.every((v) => typeof v === \"number\")) json.type = \"number\";\n if (values.every((v) => typeof v === \"string\")) json.type = \"string\";\n json.enum = values;\n};\nconst customProcessor = (schema, ctx, json, params) => {\n handleUnrepresentable(schema, ctx, json, params, \"Custom types cannot be represented in JSON Schema\");\n};\nconst transformProcessor = (schema, ctx, json, params) => {\n handleUnrepresentable(schema, ctx, json, params, \"Transforms cannot be represented in JSON Schema\");\n};\nconst arrayProcessor = (schema, ctx, _json, params) => {\n const json = _json;\n const def = schema._zod.def;\n const { minimum, maximum } = aggregateChecks(schema);\n if (typeof minimum === \"number\") json.minItems = minimum;\n if (typeof maximum === \"number\") json.maxItems = maximum;\n json.type = \"array\";\n json.items = processSchema(def.element, ctx, {\n ...params,\n path: [...params.path, \"items\"]\n });\n};\nfunction inputOptin(schema) {\n const def = schema._zod.def;\n if (def.type === \"pipe\" && def.in._zod.traits.has(\"$ZodTransform\")) return inputOptin(def.out);\n if (def.type === \"catch\") return inputOptin(def.innerType);\n return schema._zod.optin;\n}\nconst objectProcessor = (schema, ctx, _json, params) => {\n const json = _json;\n const def = schema._zod.def;\n const shape = def.shape;\n if (Object.getOwnPropertySymbols(shape).length && handleUnrepresentable(schema, ctx, json, params, \"Symbol keys cannot be represented in JSON Schema\")) return;\n json.type = \"object\";\n json.properties = {};\n for (const key in shape) assignProp(json.properties, key, processSchema(shape[key], ctx, {\n ...params,\n path: [\n ...params.path,\n \"properties\",\n key\n ]\n }));\n const requiredKeys = [];\n for (const key of Object.keys(shape)) {\n const field = def.shape[key];\n if (ctx.io === \"input\" ? inputOptin(field) === void 0 : field._zod.optout === void 0) requiredKeys.push(key);\n }\n if (requiredKeys.length > 0) json.required = requiredKeys;\n if (def.catchall?._zod.def.type === \"never\") json.additionalProperties = false;\n else if (!def.catchall) {\n if (ctx.io === \"output\") json.additionalProperties = false;\n } else if (def.catchall) json.additionalProperties = processSchema(def.catchall, ctx, {\n ...params,\n path: [...params.path, \"additionalProperties\"]\n });\n};\nconst unionProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n const isExclusive = def.inclusive === false;\n const options = def.options.map((x, i) => processSchema(x, ctx, {\n ...params,\n path: [\n ...params.path,\n isExclusive ? \"oneOf\" : \"anyOf\",\n i\n ]\n }));\n if (isExclusive) json.oneOf = options;\n else json.anyOf = options;\n};\nconst intersectionProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n const a = processSchema(def.left, ctx, {\n ...params,\n path: [\n ...params.path,\n \"allOf\",\n 0\n ]\n });\n const b = processSchema(def.right, ctx, {\n ...params,\n path: [\n ...params.path,\n \"allOf\",\n 1\n ]\n });\n const isSimpleIntersection = (val) => \"allOf\" in val && Object.keys(val).length === 1;\n const allOf = [...isSimpleIntersection(a) ? a.allOf : [a], ...isSimpleIntersection(b) ? b.allOf : [b]];\n json.allOf = allOf;\n ctx.intersections.push(allOf);\n};\nfunction stringifyKeyNames(bySchema, json, visited) {\n if (json.$ref) {\n if (visited.has(json)) return json;\n visited.add(json);\n const def = bySchema.get(json)?.def;\n if (!def) return json;\n const inlined = stringifyKeyNames(bySchema, def, visited);\n return inlined === def ? json : inlined;\n }\n for (const keyword of [\"anyOf\", \"oneOf\"]) {\n const branches = json[keyword];\n if (!Array.isArray(branches)) continue;\n const mapped = branches.map((branch) => stringifyKeyNames(bySchema, branch, visited));\n if (mapped.some((branch, i) => branch !== branches[i])) json = {\n ...json,\n [keyword]: mapped\n };\n }\n const types = Array.isArray(json.type) ? json.type : [json.type];\n const numericType = !types.includes(\"string\") && types.some((t) => t === \"number\" || t === \"integer\");\n const values = json.enum ?? (json.const !== void 0 ? [json.const] : void 0);\n if (!numericType && !values?.some((v) => typeof v === \"number\")) return json;\n const { minimum, maximum, exclusiveMinimum, exclusiveMaximum, multipleOf, format, id, ...rest } = json;\n if (rest.enum) rest.enum = rest.enum.map((v) => typeof v === \"number\" ? String(v) : v);\n else if (typeof rest.const === \"number\") rest.const = String(rest.const);\n if (!numericType) return rest;\n rest.type = \"string\";\n if (!values) rest.pattern = (types.includes(\"number\") ? number : integer).source;\n return rest;\n}\nconst pendingRecords = /* @__PURE__ */ new WeakMap();\nfunction rewriteKeyNames(ctx) {\n const bySchema = /* @__PURE__ */ new Map();\n for (const entry of ctx.seen.values()) if (entry.def && !bySchema.has(entry.schema)) bySchema.set(entry.schema, entry);\n const rewrites = /* @__PURE__ */ new Map();\n for (const record of pendingRecords.get(ctx) ?? []) {\n const seen = ctx.seen.get(record);\n const names = (seen?.def ?? seen?.schema)?.propertyNames;\n if (!names || names === true || rewrites.has(names)) continue;\n const rewritten = stringifyKeyNames(bySchema, names, /* @__PURE__ */ new Set());\n if (rewritten !== names) rewrites.set(names, rewritten);\n }\n if (!rewrites.size) return;\n for (const entry of ctx.seen.values()) for (const carrier of [entry.schema, entry.def]) {\n const rewritten = carrier && rewrites.get(carrier.propertyNames);\n if (rewritten) carrier.propertyNames = rewritten;\n }\n}\nconst recordProcessor = (schema, ctx, _json, params) => {\n const json = _json;\n const def = schema._zod.def;\n json.type = \"object\";\n const keyType = def.keyType;\n const patterns = aggregateChecks(keyType).patterns;\n if (def.mode === \"loose\" && patterns && patterns.size > 0) {\n const valueSchema = processSchema(def.valueType, ctx, {\n ...params,\n path: [\n ...params.path,\n \"patternProperties\",\n \"*\"\n ]\n });\n json.patternProperties = {};\n for (const pattern of patterns) assignProp(json.patternProperties, exactPattern(pattern).source, valueSchema);\n } else {\n if (ctx.target === \"draft-07\" || ctx.target === \"draft-2020-12\") {\n json.propertyNames = processSchema(def.keyType, ctx, {\n ...params,\n path: [...params.path, \"propertyNames\"]\n });\n let pending = pendingRecords.get(ctx);\n if (!pending) {\n pending = [];\n pendingRecords.set(ctx, pending);\n ctx.deferred.push(() => rewriteKeyNames(ctx));\n }\n pending.push(schema);\n }\n json.additionalProperties = processSchema(def.valueType, ctx, {\n ...params,\n path: [...params.path, \"additionalProperties\"]\n });\n }\n const keyValues = keyType._zod.values;\n const omittableOnInput = ctx.io === \"input\" && inputOptin(def.valueType) !== void 0;\n if (keyValues && !def.partial && !omittableOnInput) {\n const validKeyValues = [...keyValues].filter((v) => typeof v === \"string\" || typeof v === \"number\");\n if (validKeyValues.length > 0) json.required = validKeyValues.map(String);\n }\n};\nconst nullableProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n const inner = processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n if (ctx.target === \"openapi-3.0\") {\n seen.ref = def.innerType;\n json.nullable = true;\n } else json.anyOf = [inner, { type: \"null\" }];\n};\nconst nonoptionalProcessor = (schema, ctx, _json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n};\nconst UNREPRESENTABLE_DEFAULT = Symbol();\nfunction serializeDefaultValue(value, schema, ctx, json, params) {\n let unrepresentable = false;\n const serialized = JSON.stringify(value, (_, val) => {\n if (typeof val !== \"bigint\") return val;\n unrepresentable = true;\n return null;\n });\n if (!unrepresentable) return JSON.parse(serialized);\n handleUnrepresentable(schema, ctx, json, params, \"BigInt defaults cannot be represented in JSON Schema\");\n return UNREPRESENTABLE_DEFAULT;\n}\nconst defaultProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);\n if (value !== UNREPRESENTABLE_DEFAULT) json.default = value;\n};\nconst prefaultProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n if (ctx.io !== \"input\") return;\n const value = serializeDefaultValue(def.defaultValue, schema, ctx, json, params);\n if (value !== UNREPRESENTABLE_DEFAULT) json._prefault = value;\n};\nconst catchProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n let catchValue;\n try {\n catchValue = def.catchValue(void 0);\n } catch {\n handleUnrepresentable(schema, ctx, json, params, \"Dynamic catch values are not supported in JSON Schema\");\n return;\n }\n json.default = catchValue;\n};\nconst pipeProcessor = (schema, ctx, _json, params) => {\n const def = schema._zod.def;\n const inIsTransform = def.in._zod.traits.has(\"$ZodTransform\");\n const innerType = ctx.io === \"input\" ? inIsTransform ? def.out : def.in : def.out;\n processSchema(innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = innerType;\n};\nconst readonlyProcessor = (schema, ctx, json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n json.readOnly = true;\n};\nconst optionalProcessor = (schema, ctx, _json, params) => {\n const def = schema._zod.def;\n processSchema(def.innerType, ctx, params);\n const seen = ctx.seen.get(schema);\n seen.ref = def.innerType;\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/errors.js\nconst _installedErrorProtos = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);\nfunction _lazyMethod(proto, key, make) {\n Object.defineProperty(proto, key, {\n configurable: true,\n enumerable: false,\n get() {\n const value = make(this);\n Object.defineProperty(this, key, {\n value,\n configurable: true,\n writable: true\n });\n return value;\n },\n set(value) {\n Object.defineProperty(this, key, {\n value,\n configurable: true,\n writable: true\n });\n }\n });\n}\nconst initializer = (inst, issues) => {\n $ZodError.init(inst, issues);\n inst.name = \"ZodError\";\n const proto = Object.getPrototypeOf(inst);\n if (_installedErrorProtos.has(proto)) return;\n _installedErrorProtos.add(proto);\n _lazyMethod(proto, \"format\", (self) => (mapper) => formatError(self, mapper));\n _lazyMethod(proto, \"flatten\", (self) => (mapper) => flattenError(self, mapper));\n _lazyMethod(proto, \"addIssue\", (self) => (issue) => {\n self.issues.push(issue);\n self.message = JSON.stringify(self.issues, jsonStringifyReplacer, 2);\n });\n _lazyMethod(proto, \"addIssues\", (self) => (issues) => {\n self.issues.push(...issues);\n self.message = JSON.stringify(self.issues, jsonStringifyReplacer, 2);\n });\n Object.defineProperty(proto, \"isEmpty\", {\n configurable: true,\n enumerable: false,\n get() {\n return this.issues.length === 0;\n }\n });\n};\nconst ZodRealError = /*@__PURE__*/ $constructor(\"ZodError\", initializer, void 0, { Parent: Error });\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/parse.js\nconst parse = /* @__PURE__ */ _parse(ZodRealError);\nconst parseAsync = /* @__PURE__ */ _parseAsync(ZodRealError);\nconst safeParse = /* @__PURE__ */ _safeParse(ZodRealError);\nconst safeParseAsync = /* @__PURE__ */ _safeParseAsync(ZodRealError);\nconst encode = /* @__PURE__ */ _encode(ZodRealError);\nconst decode = /* @__PURE__ */ _decode(ZodRealError);\nconst encodeAsync = /* @__PURE__ */ _encodeAsync(ZodRealError);\nconst decodeAsync = /* @__PURE__ */ _decodeAsync(ZodRealError);\nconst safeEncode = /* @__PURE__ */ _safeEncode(ZodRealError);\nconst safeDecode = /* @__PURE__ */ _safeDecode(ZodRealError);\nconst safeEncodeAsync = /* @__PURE__ */ _safeEncodeAsync(ZodRealError);\nconst safeDecodeAsync = /* @__PURE__ */ _safeDecodeAsync(ZodRealError);\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/classic/schemas.js\nfunction _ensureDefaultLocale() {\n if (!globalConfig.localeError) config(en_default());\n}\nfunction _ensureDefaultMemoizer() {\n if (!globalConfig.memoizer) config({ memoizer: memoizer() });\n}\nconst ZodType = /*@__PURE__*/ $constructor(\"ZodType\", (inst, def) => {\n _ensureDefaultLocale();\n $ZodType.init(inst, def);\n inst.def = def;\n inst.type = def.type;\n return inst;\n}, {\n check(...chks) {\n const def = this.def;\n return this.clone(mergeDefs(def, { checks: [...def.checks ?? [], ...chks.map((ch) => typeof ch === \"function\" ? { _zod: {\n check: ch,\n def: { check: \"custom\" },\n onattach: []\n } } : ch)] }), { parent: true });\n },\n with(...chks) {\n return this.check(...chks);\n },\n clone(def, params) {\n return clone(this, def, params);\n },\n brand() {\n return this;\n },\n register(reg, meta) {\n reg.add(this, meta);\n return this;\n },\n refine(check, params) {\n return this.check(refine(check, params));\n },\n superRefine(refinement, params) {\n return this.check(superRefine(refinement, params));\n },\n overwrite(fn) {\n return this.check(_overwrite(fn));\n },\n optional() {\n return optional(this);\n },\n exactOptional() {\n return exactOptional(this);\n },\n nullable() {\n return nullable(this);\n },\n nullish() {\n return optional(nullable(this));\n },\n nonoptional(params) {\n return nonoptional(this, params);\n },\n array() {\n return array(this);\n },\n or(arg) {\n return union([this, arg]);\n },\n and(arg) {\n return intersection(this, arg);\n },\n transform(tx) {\n return pipe(this, transform(tx));\n },\n default(d) {\n return _default(this, d);\n },\n prefault(d) {\n return prefault(this, d);\n },\n catch(params) {\n return _catch(this, params);\n },\n pipe(target) {\n return pipe(this, target);\n },\n readonly() {\n return readonly(this);\n },\n describe(description) {\n const cl = this.clone();\n globalRegistry.add(cl, { description });\n return cl;\n },\n meta(...args) {\n if (args.length === 0) return globalRegistry.get(this);\n const cl = this.clone();\n globalRegistry.add(cl, args[0]);\n return cl;\n },\n isOptional() {\n return this.safeParse(void 0).success;\n },\n isNullable() {\n return this.safeParse(null).success;\n },\n apply(fn, ...args) {\n return args.length === 0 ? fn(this) : fn(this, ...args);\n },\n get \"~standard\"() {\n return hide(this, \"~standard\", {\n ...standardProps(this),\n jsonSchema: {\n input: createStandardJSONSchemaMethod(this, \"input\"),\n output: createStandardJSONSchemaMethod(this, \"output\")\n }\n });\n },\n set \"~standard\"(value) {\n own(this, \"~standard\", value);\n },\n parse: function _parse(data, params) {\n return parse(this, data, params, { callee: _parse });\n },\n parseAsync: async function _parseAsync(data, params) {\n return await parseAsync(this, data, params, { callee: _parseAsync });\n },\n safeParse(data, params) {\n return safeParse(this, data, params);\n },\n async safeParseAsync(data, params) {\n return safeParseAsync(this, data, params);\n },\n get spa() {\n return this?.safeParseAsync;\n },\n set spa(value) {\n own(this, \"spa\", value);\n },\n validate(data, params) {\n return validate(this, data, params);\n },\n validateAsync(data, params) {\n return validateAsync$1(this, data, params);\n },\n encode: function _encode(data, params) {\n return encode(this, data, params, { callee: _encode });\n },\n decode: function _decode(data, params) {\n return decode(this, data, params, { callee: _decode });\n },\n encodeAsync: async function _encodeAsync(data, params) {\n return await encodeAsync(this, data, params, { callee: _encodeAsync });\n },\n decodeAsync: async function _decodeAsync(data, params) {\n return await decodeAsync(this, data, params, { callee: _decodeAsync });\n },\n safeEncode(data, params) {\n return safeEncode(this, data, params);\n },\n safeDecode(data, params) {\n return safeDecode(this, data, params);\n },\n async safeEncodeAsync(data, params) {\n return safeEncodeAsync(this, data, params);\n },\n async safeDecodeAsync(data, params) {\n return safeDecodeAsync(this, data, params);\n },\n toJSONSchema(params) {\n return createToJSONSchemaMethod(this, {})(params);\n },\n get description() {\n return globalRegistry.get(this)?.description;\n },\n get _def() {\n return this._zod.def;\n }\n});\nconst _ZodString = /*@__PURE__*/ $constructor(\"_ZodString\", (inst, def) => {\n $ZodString.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => stringProcessor(inst, ctx, json, params);\n}, /*@__PURE__*/ derived({\n format: (inst) => aggregateChecks(inst).format ?? null,\n minLength: (inst) => aggregateChecks(inst).minimum ?? null,\n maxLength: (inst) => aggregateChecks(inst).maximum ?? null\n}, {\n regex(...args) {\n return this.check(_regex(...args));\n },\n includes(...args) {\n return this.check(_includes(...args));\n },\n startsWith(...args) {\n return this.check(_startsWith(...args));\n },\n endsWith(...args) {\n return this.check(_endsWith(...args));\n },\n min(...args) {\n return this.check(_minLength(...args));\n },\n max(...args) {\n return this.check(_maxLength(...args));\n },\n length(...args) {\n return this.check(_length(...args));\n },\n nonempty(...args) {\n return this.check(_minLength(1, ...args));\n },\n lowercase(params) {\n return this.check(_lowercase(params));\n },\n uppercase(params) {\n return this.check(_uppercase(params));\n },\n trim() {\n return this.check(_trim());\n },\n normalize(...args) {\n return this.check(_normalize(...args));\n },\n toLowerCase() {\n return this.check(_toLowerCase());\n },\n toUpperCase() {\n return this.check(_toUpperCase());\n },\n slugify() {\n return this.check(_slugify());\n }\n}));\nconst ZodString = /*@__PURE__*/ $constructor(\"ZodString\", (inst, def) => {\n $ZodString.init(inst, def);\n _ZodString.init(inst, def);\n}, {\n email(params) {\n return this.check(_email(ZodEmail, params));\n },\n url(params) {\n return this.check(_url(ZodURL, params));\n },\n jwt(params) {\n return this.check(_jwt(ZodJWT, params));\n },\n emoji(params) {\n return this.check(_emoji(ZodEmoji, params));\n },\n guid(params) {\n return this.check(_guid(ZodGUID, params));\n },\n uuid(params) {\n return this.check(_uuid(ZodUUID, params));\n },\n uuidv4(params) {\n return this.check(_uuidv4(ZodUUID, params));\n },\n uuidv6(params) {\n return this.check(_uuidv6(ZodUUID, params));\n },\n uuidv7(params) {\n return this.check(_uuidv7(ZodUUID, params));\n },\n nanoid(params) {\n return this.check(_nanoid(ZodNanoID, params));\n },\n cuid(params) {\n return this.check(_cuid(ZodCUID, params));\n },\n cuid2(params) {\n return this.check(_cuid2(ZodCUID2, params));\n },\n ulid(params) {\n return this.check(_ulid(ZodULID, params));\n },\n base64(params) {\n return this.check(_base64(ZodBase64, params));\n },\n base64url(params) {\n return this.check(_base64url(ZodBase64URL, params));\n },\n xid(params) {\n return this.check(_xid(ZodXID, params));\n },\n ksuid(params) {\n return this.check(_ksuid(ZodKSUID, params));\n },\n ipv4(params) {\n return this.check(_ipv4(ZodIPv4, params));\n },\n ipv6(params) {\n return this.check(_ipv6(ZodIPv6, params));\n },\n cidrv4(params) {\n return this.check(_cidrv4(ZodCIDRv4, params));\n },\n cidrv6(params) {\n return this.check(_cidrv6(ZodCIDRv6, params));\n },\n e164(params) {\n return this.check(_e164(ZodE164, params));\n },\n datetime(params) {\n return this.check(_isoDateTime(ZodISODateTime, params));\n },\n date(params) {\n return this.check(_isoDate(ZodISODate, params));\n },\n time(params) {\n return this.check(_isoTime(ZodISOTime, params));\n },\n duration(params) {\n return this.check(_isoDuration(ZodISODuration, params));\n }\n});\nfunction string(params) {\n return _string(ZodString, params);\n}\nconst ZodStringFormat = /*@__PURE__*/ $constructor(\"ZodStringFormat\", (inst, def) => {\n $ZodStringFormat.init(inst, def);\n _ZodString.init(inst, def);\n});\nconst ZodISODateTime = /*@__PURE__*/ $constructor(\"ZodISODateTime\", (inst, def) => {\n $ZodISODateTime.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodISODate = /*@__PURE__*/ $constructor(\"ZodISODate\", (inst, def) => {\n $ZodISODate.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodISOTime = /*@__PURE__*/ $constructor(\"ZodISOTime\", (inst, def) => {\n $ZodISOTime.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodISODuration = /*@__PURE__*/ $constructor(\"ZodISODuration\", (inst, def) => {\n $ZodISODuration.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodEmail = /*@__PURE__*/ $constructor(\"ZodEmail\", (inst, def) => {\n $ZodEmail.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodGUID = /*@__PURE__*/ $constructor(\"ZodGUID\", (inst, def) => {\n $ZodGUID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodUUID = /*@__PURE__*/ $constructor(\"ZodUUID\", (inst, def) => {\n $ZodUUID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodURL = /*@__PURE__*/ $constructor(\"ZodURL\", (inst, def) => {\n $ZodURL.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodEmoji = /*@__PURE__*/ $constructor(\"ZodEmoji\", (inst, def) => {\n $ZodEmoji.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodNanoID = /*@__PURE__*/ $constructor(\"ZodNanoID\", (inst, def) => {\n $ZodNanoID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodCUID = /*@__PURE__*/ $constructor(\"ZodCUID\", (inst, def) => {\n $ZodCUID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodCUID2 = /*@__PURE__*/ $constructor(\"ZodCUID2\", (inst, def) => {\n $ZodCUID2.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodULID = /*@__PURE__*/ $constructor(\"ZodULID\", (inst, def) => {\n $ZodULID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodXID = /*@__PURE__*/ $constructor(\"ZodXID\", (inst, def) => {\n $ZodXID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodKSUID = /*@__PURE__*/ $constructor(\"ZodKSUID\", (inst, def) => {\n $ZodKSUID.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodIPv4 = /*@__PURE__*/ $constructor(\"ZodIPv4\", (inst, def) => {\n $ZodIPv4.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodIPv6 = /*@__PURE__*/ $constructor(\"ZodIPv6\", (inst, def) => {\n $ZodIPv6.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodCIDRv4 = /*@__PURE__*/ $constructor(\"ZodCIDRv4\", (inst, def) => {\n $ZodCIDRv4.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodCIDRv6 = /*@__PURE__*/ $constructor(\"ZodCIDRv6\", (inst, def) => {\n $ZodCIDRv6.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodBase64 = /*@__PURE__*/ $constructor(\"ZodBase64\", (inst, def) => {\n $ZodBase64.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodBase64URL = /*@__PURE__*/ $constructor(\"ZodBase64URL\", (inst, def) => {\n $ZodBase64URL.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodE164 = /*@__PURE__*/ $constructor(\"ZodE164\", (inst, def) => {\n $ZodE164.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodJWT = /*@__PURE__*/ $constructor(\"ZodJWT\", (inst, def) => {\n $ZodJWT.init(inst, def);\n ZodStringFormat.init(inst, def);\n});\nconst ZodUnknown = /*@__PURE__*/ $constructor(\"ZodUnknown\", (inst, def) => {\n $ZodUnknown.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => unknownProcessor(inst, ctx, json, params);\n});\nfunction unknown() {\n return _unknown(ZodUnknown);\n}\nconst ZodNever = /*@__PURE__*/ $constructor(\"ZodNever\", (inst, def) => {\n $ZodNever.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => neverProcessor(inst, ctx, json, params);\n});\nfunction never(params) {\n return _never(ZodNever, params);\n}\nconst ZodArray = /*@__PURE__*/ $constructor(\"ZodArray\", (inst, def) => {\n _ensureDefaultMemoizer();\n $ZodArray.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => arrayProcessor(inst, ctx, json, params);\n inst.element = def.element;\n}, {\n min(n, params) {\n return this.check(_minLength(n, params));\n },\n nonempty(params) {\n return this.check(_minLength(1, params));\n },\n max(n, params) {\n return this.check(_maxLength(n, params));\n },\n length(n, params) {\n return this.check(_length(n, params));\n },\n unwrap() {\n return this.element;\n }\n});\nfunction array(element, params) {\n return _array(ZodArray, element, params);\n}\nconst ZodObject = /*@__PURE__*/ $constructor(\"ZodObject\", (inst, def) => {\n _ensureDefaultMemoizer();\n $ZodObjectJIT.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => objectProcessor(inst, ctx, json, params);\n installLazyProp(inst, \"shape\", (self) => self._zod.def.shape, false);\n}, {\n keyof() {\n return _enum(Object.keys(this._zod.def.shape));\n },\n catchall(catchall) {\n return this.clone(mergeDefs(this._zod.def, { catchall }));\n },\n passthrough() {\n return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));\n },\n loose() {\n return this.clone(mergeDefs(this._zod.def, { catchall: unknown() }));\n },\n strict() {\n return this.clone(mergeDefs(this._zod.def, { catchall: never() }));\n },\n strip() {\n return this.clone(mergeDefs(this._zod.def, { catchall: void 0 }));\n },\n extend(incoming) {\n return extend(this, incoming);\n },\n safeExtend(incoming) {\n return safeExtend(this, incoming);\n },\n merge(other) {\n return merge(this, other);\n },\n pick(mask) {\n return pick(this, mask);\n },\n omit(mask) {\n return omit(this, mask);\n },\n partial(...args) {\n return partial(ZodOptional, this, args[0]);\n },\n exactPartial(...args) {\n return partial(ZodExactOptional, this, args[0], \"exactPartial\");\n },\n required(...args) {\n return required(ZodNonOptional, this, args[0]);\n }\n});\nfunction object(shape, params) {\n const def = {\n type: \"object\",\n shape: shape ?? {},\n ...normalizeParams(params)\n };\n return new ZodObject(def);\n}\nconst ZodUnion = /*@__PURE__*/ $constructor(\"ZodUnion\", (inst, def) => {\n $ZodUnion.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => unionProcessor(inst, ctx, json, params);\n inst.options = def.options;\n});\nfunction union(options, params) {\n return new ZodUnion({\n type: \"union\",\n options,\n ...normalizeParams(params)\n });\n}\nconst ZodIntersection = /*@__PURE__*/ $constructor(\"ZodIntersection\", (inst, def) => {\n $ZodIntersection.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => intersectionProcessor(inst, ctx, json, params);\n});\nfunction intersection(left, right) {\n return new ZodIntersection({\n type: \"intersection\",\n left,\n right\n });\n}\nconst ZodRecord = /*@__PURE__*/ $constructor(\"ZodRecord\", (inst, def) => {\n _ensureDefaultMemoizer();\n $ZodRecord.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => recordProcessor(inst, ctx, json, params);\n inst.keyType = def.keyType;\n inst.valueType = def.valueType;\n});\nfunction record(keyType, valueType, params) {\n if (!valueType || !valueType._zod) return new ZodRecord({\n type: \"record\",\n keyType: string(),\n valueType: keyType,\n ...normalizeParams(valueType)\n });\n return new ZodRecord({\n type: \"record\",\n keyType,\n valueType,\n ...normalizeParams(params)\n });\n}\nconst ZodEnum = /*@__PURE__*/ $constructor(\"ZodEnum\", (inst, def) => {\n $ZodEnum.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => enumProcessor(inst, ctx, json, params);\n inst.enum = def.entries;\n inst.options = [...inst._zod.values];\n const keys = new Set(Object.keys(def.entries));\n inst.extract = (values, params) => {\n const newEntries = {};\n for (const value of values) if (keys.has(value)) newEntries[value] = def.entries[value];\n else throw new Error(`Key ${value} not found in enum`);\n return new ZodEnum({\n ...def,\n checks: [],\n ...normalizeParams(params),\n entries: newEntries\n });\n };\n inst.exclude = (values, params) => {\n const newEntries = { ...def.entries };\n for (const value of values) if (keys.has(value)) delete newEntries[value];\n else throw new Error(`Key ${value} not found in enum`);\n return new ZodEnum({\n ...def,\n checks: [],\n ...normalizeParams(params),\n entries: newEntries\n });\n };\n});\nfunction _enum(values, params) {\n const entries = Array.isArray(values) ? Object.fromEntries(values.map((v) => [v, v])) : values;\n return new ZodEnum({\n type: \"enum\",\n entries,\n ...normalizeParams(params)\n });\n}\nconst ZodTransform = /*@__PURE__*/ $constructor(\"ZodTransform\", (inst, def) => {\n _ensureDefaultMemoizer();\n $ZodTransform.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => transformProcessor(inst, ctx, json, params);\n inst._zod.parse = (payload, _ctx) => {\n if (_ctx.direction === \"backward\") throw new $ZodEncodeError(inst.constructor.name);\n payload.addIssue = (issue$1) => {\n if (typeof issue$1 === \"string\") payload.issues.push(issue(issue$1, payload.value, def));\n else {\n const _issue = issue$1;\n if (_issue.fatal) _issue.continue = false;\n _issue.code ?? (_issue.code = \"custom\");\n if (!(\"input\" in _issue)) _issue.input = payload.value;\n _issue.inst ?? (_issue.inst = inst);\n payload.issues.push(issue(_issue));\n }\n };\n const output = def.transform(payload.value, payload);\n if (output instanceof Promise) return output.then((output) => {\n payload.value = output;\n return payload;\n });\n payload.value = output;\n return payload;\n };\n});\nfunction transform(fn) {\n return new ZodTransform({\n type: \"transform\",\n transform: fn\n });\n}\nconst ZodOptional = /*@__PURE__*/ $constructor(\"ZodOptional\", (inst, def) => {\n $ZodOptional.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => optionalProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction optional(innerType) {\n return new ZodOptional({\n type: \"optional\",\n innerType\n });\n}\nconst ZodExactOptional = /*@__PURE__*/ $constructor(\"ZodExactOptional\", (inst, def) => {\n $ZodExactOptional.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => optionalProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction exactOptional(innerType) {\n return new ZodExactOptional({\n type: \"optional\",\n innerType\n });\n}\nconst ZodNullable = /*@__PURE__*/ $constructor(\"ZodNullable\", (inst, def) => {\n $ZodNullable.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => nullableProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction nullable(innerType) {\n return new ZodNullable({\n type: \"nullable\",\n innerType\n });\n}\nconst ZodDefault = /*@__PURE__*/ $constructor(\"ZodDefault\", (inst, def) => {\n $ZodDefault.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => defaultProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n inst.removeDefault = inst.unwrap;\n});\nfunction _default(innerType, defaultValue) {\n return new ZodDefault({\n type: \"default\",\n innerType,\n get defaultValue() {\n return typeof defaultValue === \"function\" ? defaultValue() : shallowClone(defaultValue);\n }\n });\n}\nconst ZodPrefault = /*@__PURE__*/ $constructor(\"ZodPrefault\", (inst, def) => {\n $ZodPrefault.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => prefaultProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction prefault(innerType, defaultValue) {\n return new ZodPrefault({\n type: \"prefault\",\n innerType,\n get defaultValue() {\n return typeof defaultValue === \"function\" ? defaultValue() : shallowClone(defaultValue);\n }\n });\n}\nconst ZodNonOptional = /*@__PURE__*/ $constructor(\"ZodNonOptional\", (inst, def) => {\n $ZodNonOptional.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => nonoptionalProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction nonoptional(innerType, params) {\n return new ZodNonOptional({\n type: \"nonoptional\",\n innerType,\n ...normalizeParams(params)\n });\n}\nconst ZodCatch = /*@__PURE__*/ $constructor(\"ZodCatch\", (inst, def) => {\n $ZodCatch.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => catchProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n inst.removeCatch = inst.unwrap;\n});\nfunction _catch(innerType, catchValue) {\n return new ZodCatch({\n type: \"catch\",\n innerType,\n catchValue: typeof catchValue === \"function\" ? catchValue : constantCatch(catchValue)\n });\n}\nconst ZodPipe = /*@__PURE__*/ $constructor(\"ZodPipe\", (inst, def) => {\n $ZodPipe.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => pipeProcessor(inst, ctx, json, params);\n inst.in = def.in;\n inst.out = def.out;\n});\nfunction pipe(in_, out) {\n return new ZodPipe({\n type: \"pipe\",\n in: in_,\n out\n });\n}\nconst ZodReadonly = /*@__PURE__*/ $constructor(\"ZodReadonly\", (inst, def) => {\n $ZodReadonly.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => readonlyProcessor(inst, ctx, json, params);\n inst.unwrap = () => inst._zod.def.innerType;\n});\nfunction readonly(innerType) {\n return new ZodReadonly({\n type: \"readonly\",\n innerType\n });\n}\nconst ZodCustom = /*@__PURE__*/ $constructor(\"ZodCustom\", (inst, def) => {\n $ZodCustom.init(inst, def);\n ZodType.init(inst, def);\n inst._zod.processJSONSchema = (ctx, json, params) => customProcessor(inst, ctx, json, params);\n});\nfunction refine(fn, _params = {}) {\n return _refine(ZodCustom, fn, _params);\n}\nfunction superRefine(fn, params) {\n return _superRefine(fn, params);\n}\n\n//#endregion\n//#region src/lib/hook-io.ts\nconst HookInputSchema = object({\n session_id: string(),\n transcript_path: string(),\n cwd: string(),\n permission_mode: string(),\n hook_event_name: string(),\n tool_name: string(),\n tool_input: record(string(), unknown())\n});\nasync function readHookInput() {\n const chunks = [];\n for await (const chunk of process.stdin) chunks.push(typeof chunk === \"string\" ? chunk : String(chunk));\n let parsed;\n try {\n parsed = JSON.parse(chunks.join(\"\"));\n } catch (_error) {\n return {\n ok: false,\n raw: chunks.join(\"\").slice(0, 200),\n error: \"invalid JSON\"\n };\n }\n const result = HookInputSchema.safeParse(parsed);\n if (!result.success) return {\n ok: false,\n raw: parsed,\n error: result.error.message\n };\n return {\n ok: true,\n data: result.data\n };\n}\nconst BashInputSchema = object({\n command: string(),\n description: optional(string())\n});\nconst FilePathInputSchema = object({ file_path: string() });\nconst SearchInputSchema = object({\n pattern: string(),\n path: optional(string())\n});\nfunction parseBashInput(toolInput) {\n const result = BashInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction parseFilePathInput(toolInput) {\n const result = FilePathInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction parseSearchInput(toolInput) {\n const result = SearchInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction writeDeny(reason) {\n const decision = { hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n ...reason ? { permissionDecisionReason: reason } : {}\n } };\n process.stdout.write(JSON.stringify(decision));\n}\nfunction writeAdvice(advice) {\n const decision = { hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n additionalContext: advice\n } };\n process.stdout.write(JSON.stringify(decision));\n}\n\n//#endregion\n//#region src/lib/audit.ts\nconst MAX_LOG_SIZE = 1048576;\nfunction getLogPath() {\n const hookDir = path.dirname(fileURLToPath(import.meta.url));\n return path.join(hookDir, \"bst-hook.audit.local.jsonl\");\n}\nfunction rotateIfNeeded(logPath) {\n try {\n if (fs.statSync(logPath).size > MAX_LOG_SIZE) {\n const rotatedPath = `${logPath}.1`;\n fs.renameSync(logPath, rotatedPath);\n }\n } catch (_error) {}\n}\nlet rotationChecked = false;\nfunction audit(entry) {\n try {\n const logPath = getLogPath();\n if (!rotationChecked) {\n rotateIfNeeded(logPath);\n rotationChecked = true;\n }\n const record = {\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...entry\n };\n fs.appendFileSync(logPath, JSON.stringify(record) + \"\\n\");\n } catch (err) {\n process.stderr.write(`[bst-hook] audit write failed: ${err instanceof Error ? err.message : String(err)}\\n`);\n }\n}\n\n//#endregion\n//#region src/lib/shell-tokenizer.ts\nfunction scanDoubleQuoted(input, start) {\n let content = \"\";\n let i = start;\n while (i < input.length && input[i] !== \"\\\"\") {\n if (input[i] === \"\\\\\" && i + 1 < input.length) {\n const next = input[i + 1];\n if (next === \"\\\"\" || next === \"\\\\\" || next === \"$\" || next === \"`\") {\n content += next;\n i += 2;\n continue;\n }\n }\n content += input[i];\n i++;\n }\n if (i >= input.length) return null;\n return {\n content,\n next: i + 1\n };\n}\nfunction tokenize(input) {\n const tokens = [];\n let current = \"\";\n let i = 0;\n let inToken = false;\n while (i < input.length) {\n const ch = input[i];\n if (ch === \"'\") {\n inToken = true;\n i++;\n while (i < input.length && input[i] !== \"'\") {\n current += input[i];\n i++;\n }\n if (i >= input.length) return {\n ok: false,\n error: \"unterminated single quote\"\n };\n i++;\n } else if (ch === \"\\\"\") {\n inToken = true;\n const scanned = scanDoubleQuoted(input, i + 1);\n if (!scanned) return {\n ok: false,\n error: \"unterminated double quote\"\n };\n current += scanned.content;\n i = scanned.next;\n } else if (ch === \"\\\\\" && i + 1 < input.length) {\n inToken = true;\n current += input[i + 1];\n i += 2;\n } else if (ch === \" \" || ch === \" \") {\n if (inToken) {\n tokens.push(current);\n current = \"\";\n inToken = false;\n }\n i++;\n } else {\n inToken = true;\n current += ch;\n i++;\n }\n }\n if (inToken) tokens.push(current);\n return {\n ok: true,\n tokens\n };\n}\nconst SAFE_UNQUOTED_RE = /^[A-Za-z0-9_\\-./=:@%+,]+$/;\nfunction quoteToken(token) {\n if (token.length > 0 && SAFE_UNQUOTED_RE.test(token)) return token;\n return \"'\" + token.replace(/'/g, \"'\\\\''\") + \"'\";\n}\nfunction joinTokens(tokens) {\n return tokens.map(quoteToken).join(\" \");\n}\n\n//#endregion\n//#region src/lib/shell-splitter.ts\nfunction splitCommand(input) {\n if (!input || !input.trim()) return [];\n const segments = [];\n let current = \"\";\n let i = 0;\n let inSingleQuote = false;\n let inDoubleQuote = false;\n while (i < input.length) {\n const ch = input[i];\n if (ch === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n current += ch;\n i++;\n continue;\n }\n if (ch === \"\\\"\" && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n current += ch;\n i++;\n continue;\n }\n if (ch === \"\\\\\" && !inSingleQuote && i + 1 < input.length) {\n current += ch + input[i + 1];\n i += 2;\n continue;\n }\n if (!inSingleQuote && !inDoubleQuote) {\n if (ch === \"&\" && i + 1 < input.length && input[i + 1] === \"&\") {\n pushSegment(segments, current, \"&&\");\n current = \"\";\n i += 2;\n continue;\n }\n if (ch === \"&\" && !(i + 1 < input.length && input[i + 1] === \">\") && !(i > 0 && (input[i - 1] === \">\" || input[i - 1] === \"<\"))) {\n pushSegment(segments, current, \"&\");\n current = \"\";\n i++;\n continue;\n }\n if (ch === \"|\" && i + 1 < input.length && input[i + 1] === \"|\") {\n pushSegment(segments, current, \"||\");\n current = \"\";\n i += 2;\n continue;\n }\n if (ch === \"|\") {\n pushSegment(segments, current, \"|\");\n current = \"\";\n i++;\n continue;\n }\n if (ch === \";\") {\n pushSegment(segments, current, \";\");\n current = \"\";\n i++;\n continue;\n }\n }\n current += ch;\n i++;\n }\n const trimmed = current.trim();\n if (trimmed) segments.push({\n command: trimmed,\n operator: null\n });\n return segments;\n}\nfunction pushSegment(segments, text, operator) {\n const trimmed = text.trim();\n if (trimmed) segments.push({\n command: trimmed,\n operator\n });\n}\n\n//#endregion\n//#region src/lib/injection-guard.ts\nfunction hasBraceExpansion(token) {\n let depth = 0;\n for (let i = 0; i < token.length; i++) {\n const ch = token[i];\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n if (depth > 0) depth--;\n } else if (depth >= 1 && (ch === \",\" || ch === \".\" && token[i + 1] === \".\")) return true;\n }\n return false;\n}\nfunction checkInjection(tokens, rawSegment) {\n if (/[\\n\\r]/.test(rawSegment)) return {\n safe: false,\n reason: \"unquoted newline in command\"\n };\n for (const token of tokens) {\n if (token === \"`\") return {\n safe: false,\n reason: \"backtick command substitution\"\n };\n if (token.includes(\"`\")) return {\n safe: false,\n reason: \"backtick command substitution\"\n };\n if (token.includes(\"$\")) return {\n safe: false,\n reason: \"unresolved dollar-expansion\"\n };\n if (hasBraceExpansion(token)) return {\n safe: false,\n reason: \"brace expansion\"\n };\n if (token.includes(\"<(\")) return {\n safe: false,\n reason: \"process substitution\"\n };\n if (token.includes(\">(\")) return {\n safe: false,\n reason: \"process substitution\"\n };\n }\n return { safe: true };\n}\n\n//#endregion\n//#region src/lib/env-file.ts\nconst ENV_SAFE_SUFFIXES = [\n \".sample\",\n \".example\",\n \".template\"\n];\nconst ENV_TOOL_OWNED_SUFFIXES = [\".check.env\"];\nconst ENV_FILE_PATTERN = /(^|[/\\\\])(\\.env(\\..*)?|.*\\.env(\\..*)?|\\.env)$/;\nfunction isEnvSafeSuffix(filename) {\n return [...ENV_SAFE_SUFFIXES, ...ENV_TOOL_OWNED_SUFFIXES].some((suffix) => filename.endsWith(suffix));\n}\nfunction isEnvFile(filePath) {\n if (isEnvSafeSuffix(path.basename(filePath))) return false;\n return ENV_FILE_PATTERN.test(filePath);\n}\n\n//#endregion\n//#region src/lib/git-state.ts\nconst GIT_TIMEOUT_MS = 5e3;\nfunction getCurrentBranch(cwd) {\n try {\n const out = execFileSync(\"git\", [\n \"rev-parse\",\n \"--abbrev-ref\",\n \"HEAD\"\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!out || out === \"HEAD\") return null;\n return out;\n } catch {\n return null;\n }\n}\nfunction getRepoTopLevel(cwd) {\n try {\n const out = execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n return out === \"\" ? null : out;\n } catch {\n return null;\n }\n}\nfunction getRemoteDefaultBranch(cwd) {\n try {\n const out = execFileSync(\"git\", [\n \"symbolic-ref\",\n \"--short\",\n \"refs/remotes/origin/HEAD\"\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!out) return null;\n return out.startsWith(\"origin/\") ? out.slice(7) : out;\n } catch {\n return null;\n }\n}\nconst DefaultBranchSchema = object({ defaultBranch: string().min(1).optional() });\nfunction getConfiguredDefaultBranch(topLevel) {\n let parsed;\n try {\n parsed = JSON.parse(readFileSync(join(topLevel, \".tooling.json\"), \"utf-8\"));\n } catch {\n return null;\n }\n const result = DefaultBranchSchema.safeParse(parsed);\n return result.success ? result.data.defaultBranch ?? null : null;\n}\nconst ALWAYS_PROTECTED = [\"main\", \"master\"];\nfunction getProtectedBranches(cwd, extra) {\n const set = new Set(ALWAYS_PROTECTED);\n const remote = getRemoteDefaultBranch(cwd);\n if (remote) set.add(remote);\n for (const b of extra) set.add(b);\n return set;\n}\nfunction getUpstream(cwd, branch) {\n try {\n return execFileSync(\"git\", [\n \"rev-parse\",\n \"--abbrev-ref\",\n `${branch}@{upstream}`\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim() || null;\n } catch {\n return null;\n }\n}\nfunction resolveCommit(cwd, rev) {\n try {\n return execFileSync(\"git\", [\n \"rev-parse\",\n \"--verify\",\n \"--quiet\",\n `${rev}^{commit}`\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim() || null;\n } catch {\n return null;\n }\n}\nfunction branchCarriesOtherFiles(cwd, allowed) {\n const toplevel = getRepoTopLevel(cwd);\n if (toplevel === null) return null;\n try {\n const defaultBranch = getConfiguredDefaultBranch(toplevel) ?? getRemoteDefaultBranch(toplevel) ?? \"main\";\n const mergeBase = execFileSync(\"git\", [\n \"merge-base\",\n \"HEAD\",\n `origin/${defaultBranch}`\n ], {\n cwd: toplevel,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!mergeBase) return null;\n const names = (args) => execFileSync(\"git\", args, {\n cwd: toplevel,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().split(\"\\n\").filter((line) => line.length > 0);\n return [...names([\n \"diff\",\n \"--name-only\",\n mergeBase\n ]), ...names([\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\"\n ])].some((name) => !allowed.includes(name));\n } catch {\n return null;\n }\n}\nfunction isPrimaryWorktree(cwd) {\n try {\n const gitDir = execFileSync(\"git\", [\"rev-parse\", \"--absolute-git-dir\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n const commonRaw = execFileSync(\"git\", [\"rev-parse\", \"--git-common-dir\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!gitDir || !commonRaw) return false;\n const commonDir = resolve(cwd, commonRaw);\n return realpathSync(gitDir) === realpathSync(commonDir);\n } catch {\n return false;\n }\n}\n\n//#endregion\n//#region src/lib/git-short-options.ts\nconst VALUE_TAKING_LETTERS = {\n switch: /* @__PURE__ */ new Set([\"c\", \"C\"]),\n checkout: /* @__PURE__ */ new Set([\"b\", \"B\"]),\n branch: /* @__PURE__ */ new Set([\"u\"]),\n fetch: /* @__PURE__ */ new Set([\"o\", \"j\"])\n};\nfunction splitShortOptionCluster(token, sub) {\n if (!token.startsWith(\"-\") || token.startsWith(\"--\") || token.length <= 1) return;\n const valueLetters = VALUE_TAKING_LETTERS[sub];\n const letters = [];\n const chars = token.slice(1);\n for (let i = 0; i < chars.length; i++) {\n const ch = chars[i];\n letters.push(ch);\n if (valueLetters.has(ch)) return {\n letters,\n attachedValue: chars.slice(i + 1)\n };\n }\n return { letters };\n}\n\n//#endregion\n//#region src/lib/path-scope.ts\nfunction pathFlavorFor(base) {\n return /^[a-zA-Z]:[\\\\/]/.test(base) ? path.win32 : path.posix;\n}\nfunction resolveIn(base, target) {\n return pathFlavorFor(base).resolve(base, target);\n}\nfunction isWithin(dir, target) {\n const pp = pathFlavorFor(dir);\n const rel = pp.relative(dir, target);\n if (rel === \"\") return true;\n if (rel === \"..\" || rel.startsWith(\"..\" + pp.sep)) return false;\n return !pp.isAbsolute(rel);\n}\nfunction samePath(a, b) {\n return pathFlavorFor(a).relative(a, b) === \"\";\n}\nfunction targetsGitDir(filePath, cwd) {\n const pp = pathFlavorFor(cwd);\n const resolved = resolveIn(cwd, filePath);\n if (!isWithin(cwd, resolved)) return false;\n const rel = pp.relative(cwd, resolved);\n if (rel === \"\") return false;\n return rel.split(pp.sep).includes(\".git\");\n}\nfunction targetsNodeModules(filePath, cwd) {\n return resolveIn(cwd, filePath).split(/[/\\\\]/).includes(\"node_modules\");\n}\n\n//#endregion\n//#region src/rules.ts\nconst GIT_FLAGS_WITH_ARG = /* @__PURE__ */ new Set([\n \"-C\",\n \"-c\",\n \"--git-dir\",\n \"--work-tree\"\n]);\nfunction getGitSubcommand(tokens) {\n const args = tokens.slice(1);\n for (let i = 0; i < args.length; i++) {\n const t = args[i];\n if (GIT_FLAGS_WITH_ARG.has(t)) {\n i++;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n return t;\n }\n}\nconst WORKTREE_ADVICE = \"You're creating a feature branch in the primary worktree. An isolated worktree keeps this work independent of other windows, and with no commits on this branch yet, converting is cheap -- `git worktree add ../<dir> -b <branch>` (a sibling outside the repo, with its own dependency install). Claude Code keeps this session inside its own working tree, so the work continues in a new session opened in the sibling worktree. If you cannot open a session there, stay in the primary checkout on this branch and check `git branch --show-current` before each commit.\";\nfunction isGitBranchCreation(tokens) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"checkout\" && sub !== \"switch\") return false;\n const after = tokens.slice(tokens.indexOf(sub) + 1);\n const creationLetters = sub === \"checkout\" ? [\"b\", \"B\"] : [\"c\", \"C\"];\n return after.some((t) => {\n const cluster = splitShortOptionCluster(t, sub);\n return cluster !== void 0 && cluster.letters.some((l) => creationLetters.includes(l));\n });\n}\nfunction worktreeAdvice(tokens, ctx) {\n return isGitBranchCreation(tokens) && isPrimaryWorktree(ctx.cwd) ? WORKTREE_ADVICE : void 0;\n}\nconst GIT_FORCE_CREATE_LETTER = {\n switch: \"C\",\n checkout: \"B\"\n};\nconst GIT_FORCE_CREATE_LONG = {\n flag: \"--force-create\",\n shortest: \"--force-\"\n};\nfunction gitForceCreateTargets(after, letterSub) {\n const letter = GIT_FORCE_CREATE_LETTER[letterSub];\n const longFlag = GIT_FORCE_CREATE_LONG;\n const targets = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (letterSub === \"switch\") {\n const [flag, ...rest] = t.split(\"=\");\n if (flag !== void 0 && flag.length >= longFlag.shortest.length && longFlag.flag.startsWith(flag)) {\n const target = rest.length > 0 ? rest.join(\"=\") : after[i + 1];\n if (target !== void 0) targets.push(target);\n continue;\n }\n }\n const cluster = splitShortOptionCluster(t, letterSub);\n if (cluster === void 0 || !cluster.letters.includes(letter)) continue;\n if (cluster.attachedValue !== void 0 && cluster.attachedValue !== \"\") {\n targets.push(cluster.attachedValue);\n continue;\n }\n const next = after[i + 1];\n if (next !== void 0) targets.push(next);\n }\n return targets;\n}\nfunction gitCommandForceCreateTargets(tokens) {\n const sub = getGitSubcommand(tokens);\n if (sub === \"switch\" || sub === \"checkout\") return gitForceCreateTargets(tokens.slice(tokens.indexOf(sub) + 1), sub);\n if (sub === \"worktree\") {\n const worktreeIdx = tokens.indexOf(\"worktree\");\n if (tokens[worktreeIdx + 1] !== \"add\") return [];\n return gitForceCreateTargets(tokens.slice(worktreeIdx + 2), \"checkout\");\n }\n return [];\n}\nfunction isGitProtectedBranchForceCreate(tokens, ctx) {\n const targets = gitCommandForceCreateTargets(tokens);\n if (targets.length === 0) return false;\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n return targets.some((t) => protectedSet.has(t));\n}\nfunction isGitProtectedBranchRefWrite(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"branch\") return false;\n const { flags, positionals } = splitGitBranchArgs(tokens.slice(tokens.indexOf(sub) + 1));\n if (positionals.length === 0) return false;\n let deleteMode = false;\n let renameMode = false;\n let copyMode = false;\n let forceMode = false;\n for (const flag of flags) {\n if (flag.letters !== void 0) {\n if (flag.letters.includes(\"d\") || flag.letters.includes(\"D\")) deleteMode = true;\n if (flag.letters.includes(\"m\") || flag.letters.includes(\"M\")) renameMode = true;\n if (flag.letters.includes(\"c\") || flag.letters.includes(\"C\")) copyMode = true;\n if (flag.letters.includes(\"f\") || flag.letters.includes(\"M\") || flag.letters.includes(\"C\")) forceMode = true;\n continue;\n }\n if (flag.name === \"delete\") deleteMode = true;\n if (flag.name === \"move\") renameMode = true;\n if (flag.name === \"copy\") copyMode = true;\n if (flag.name === \"force\") forceMode = true;\n }\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n if (deleteMode && positionals.some((p) => protectedSet.has(p))) return true;\n if (renameMode && positionals.length >= 2 && protectedSet.has(positionals[0])) return true;\n if (forceMode) {\n const destination = renameMode || copyMode ? positionals[positionals.length - 1] : positionals[0];\n if (destination !== void 0 && protectedSet.has(destination)) return true;\n }\n return false;\n}\nfunction refspecDestination(refspec) {\n const spec = refspec.startsWith(\"+\") ? refspec.slice(1) : refspec;\n const colon = spec.lastIndexOf(\":\");\n return (colon === -1 ? spec : spec.slice(colon + 1)).replace(/^refs\\/heads\\//, \"\");\n}\nconst GIT_BRANCH_VALUE_FLAG_NAMES = /* @__PURE__ */ new Set([\n \"contains\",\n \"no-contains\",\n \"merged\",\n \"no-merged\",\n \"points-at\",\n \"sort\",\n \"format\",\n \"set-upstream-to\"\n]);\nfunction splitGitBranchArgs(after) {\n const flags = [];\n const positionals = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (t.startsWith(\"--\") && t !== \"--\") {\n const eq = t.indexOf(\"=\");\n const name = eq > 0 ? t.slice(2, eq) : t.slice(2);\n flags.push({\n raw: t,\n name\n });\n if (eq < 0 && GIT_BRANCH_VALUE_FLAG_NAMES.has(name)) i++;\n continue;\n }\n const cluster = splitShortOptionCluster(t, \"branch\");\n if (cluster === void 0) {\n flags.push({ raw: t });\n continue;\n }\n flags.push({\n raw: t,\n letters: cluster.letters\n });\n if (cluster.attachedValue === \"\") i++;\n }\n return {\n flags,\n positionals\n };\n}\nconst GIT_FETCH_VALUE_FLAG_NAMES = /* @__PURE__ */ new Set([\n \"depth\",\n \"deepen\",\n \"shallow-since\",\n \"shallow-exclude\",\n \"negotiation-tip\",\n \"filter\",\n \"jobs\",\n \"server-option\",\n \"upload-pack\",\n \"refmap\",\n \"submodule-prefix\",\n \"recurse-submodules-default\"\n]);\nfunction splitGitFetchArgs(after) {\n const flags = [];\n const positionals = [];\n const refmaps = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (t === \"--\") {\n flags.push({ raw: t });\n continue;\n }\n if (t.startsWith(\"--\")) {\n const eq = t.indexOf(\"=\");\n const name = eq > 0 ? t.slice(2, eq) : t.slice(2);\n flags.push({\n raw: t,\n name\n });\n if (name === \"refmap\") {\n if (eq > 0) refmaps.push(t.slice(eq + 1));\n else if (after[i + 1] !== void 0) refmaps.push(after[i + 1]);\n }\n if (eq < 0 && GIT_FETCH_VALUE_FLAG_NAMES.has(name)) i++;\n continue;\n }\n const cluster = splitShortOptionCluster(t, \"fetch\");\n if (cluster === void 0) {\n flags.push({ raw: t });\n continue;\n }\n flags.push({\n raw: t,\n letters: cluster.letters\n });\n if (cluster.attachedValue === \"\") i++;\n }\n return {\n flags,\n positionals,\n refmaps\n };\n}\nfunction fetchRefspecTarget(spec) {\n const body = spec.startsWith(\"+\") ? spec.slice(1) : spec;\n if (body.startsWith(\"^\")) return { kind: \"none\" };\n if (!body.includes(\":\")) return { kind: \"none\" };\n const destination = refspecDestination(body);\n if (destination === \"\") return { kind: \"none\" };\n if (destination.startsWith(\"refs/remotes/\")) return { kind: \"tracking\" };\n if (destination.startsWith(\"refs/\")) return { kind: \"other\" };\n return {\n kind: \"branch\",\n name: destination\n };\n}\nfunction globToAnchoredRegex(glob) {\n const escaped = glob.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`^${escaped.replace(/\\\\\\*/g, \".*\")}$`);\n}\nfunction isProtectedFetchBranch(name, protectedSet) {\n if (protectedSet.has(name)) return true;\n if (!name.includes(\"*\")) return false;\n const pattern = globToAnchoredRegex(name);\n for (const member of protectedSet) if (pattern.test(member)) return true;\n return false;\n}\nfunction isGitProtectedBranchFetchWrite(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"fetch\") return false;\n const { positionals, refmaps } = splitGitFetchArgs(tokens.slice(tokens.indexOf(sub) + 1));\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n return [...positionals, ...refmaps].some((spec) => {\n const target = fetchRefspecTarget(spec);\n if (target.kind !== \"branch\" || target.name === void 0) return false;\n return isProtectedFetchBranch(target.name, protectedSet);\n });\n}\nfunction isGitProtectedUpdateRef(tokens, ctx) {\n const after = tokens.slice(tokens.indexOf(\"update-ref\") + 1);\n let ref;\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === \"-m\") {\n i++;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n ref = t;\n break;\n }\n if (ref === void 0) return false;\n return getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []).has(ref.replace(/^refs\\/heads\\//, \"\"));\n}\nfunction gitEffectiveCwd(tokens, cwd) {\n let dir = cwd;\n const args = tokens.slice(1);\n for (let i = 0; i < args.length; i++) {\n const t = args[i];\n if (t === \"-C\") {\n const next = args[i + 1];\n if (next !== void 0) dir = path.resolve(dir, next);\n i++;\n continue;\n }\n if (GIT_FLAGS_WITH_ARG.has(t)) {\n i++;\n continue;\n }\n if (!t.startsWith(\"-\")) break;\n }\n return dir;\n}\nconst GIT_SWITCH_NEUTRAL_FLAGS = /* @__PURE__ */ new Set([\n \"-q\",\n \"--quiet\",\n \"-f\",\n \"--force\",\n \"--discard-changes\",\n \"-m\",\n \"--merge\",\n \"--no-track\",\n \"--progress\",\n \"--no-progress\",\n \"--guess\",\n \"--no-guess\",\n \"--ignore-other-worktrees\",\n \"--recurse-submodules\",\n \"--no-recurse-submodules\"\n]);\nconst GIT_SWITCH_CREATE_FLAGS = /* @__PURE__ */ new Set([\n \"--create\",\n \"--force-create\",\n \"--orphan\"\n]);\nconst GIT_CHECKOUT_PATH_FLAGS = /* @__PURE__ */ new Set([\n \"--ours\",\n \"--theirs\",\n \"-p\",\n \"--patch\",\n \"--conflict\",\n \"--pathspec-from-file\",\n \"--pathspec-file-nul\",\n \"--overlay\",\n \"--no-overlay\"\n]);\nconst GIT_SWITCH_NEUTRAL_LETTERS = /* @__PURE__ */ new Set([\n \"q\",\n \"f\",\n \"m\"\n]);\nfunction switchTarget(after, sub, isCheckoutBranch) {\n if (sub === \"checkout\" && after.includes(\"--\")) return void 0;\n const createLetters = sub === \"checkout\" ? [\"b\", \"B\"] : [\"c\", \"C\"];\n const known = (l) => GIT_SWITCH_NEUTRAL_LETTERS.has(l) || createLetters.includes(l);\n const positionals = [];\n let created;\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (GIT_SWITCH_NEUTRAL_FLAGS.has(t)) continue;\n const eq = t.indexOf(\"=\");\n if (sub === \"checkout\" && GIT_CHECKOUT_PATH_FLAGS.has(eq === -1 ? t : t.slice(0, eq))) return;\n if (GIT_SWITCH_CREATE_FLAGS.has(eq === -1 ? t : t.slice(0, eq))) {\n created = eq === -1 ? after[++i] : t.slice(eq + 1);\n continue;\n }\n const cluster = splitShortOptionCluster(t, sub);\n if (cluster === void 0 || !cluster.letters.every(known)) return null;\n if (cluster.letters.some((l) => createLetters.includes(l))) created = cluster.attachedValue ? cluster.attachedValue : after[++i];\n }\n if (created !== void 0) return created;\n if (positionals.length !== 1) return void 0;\n const target = positionals[0];\n if (target === \"HEAD\" || target === \"@\") return void 0;\n if (sub === \"checkout\" && !isCheckoutBranch(target)) return void 0;\n return target;\n}\nfunction branchSwitch(tokens, ctx, resolved) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"switch\" && sub !== \"checkout\") return void 0;\n const dir = gitEffectiveCwd(tokens, ctx.cwd);\n const isCheckoutBranch = (name) => !resolved || getProtectedBranches(dir, ctx.repoProtectedBranches ?? []).has(name) || resolveCommit(dir, name) !== null;\n const target = switchTarget(tokens.slice(tokens.indexOf(sub) + 1), sub, isCheckoutBranch);\n if (!resolved) return target === void 0 ? void 0 : {\n dir,\n branch: null\n };\n return target === void 0 ? void 0 : {\n dir,\n branch: target\n };\n}\nconst GIT_CHECKED_OUT_WRITES = /* @__PURE__ */ new Set([\n \"commit\",\n \"merge\",\n \"rebase\",\n \"cherry-pick\",\n \"revert\",\n \"am\",\n \"pull\"\n]);\nfunction subcommandArgs(tokens, sub, valueFlags = /* @__PURE__ */ new Set()) {\n const after = tokens.slice(tokens.indexOf(sub) + 1);\n const flags = [];\n const positionals = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n flags.push(t);\n if (valueFlags.has(t)) i++;\n }\n return {\n flags,\n positionals\n };\n}\nconst GIT_PUSH_VALUE_FLAGS = /* @__PURE__ */ new Set([\n \"-o\",\n \"--push-option\",\n \"--repo\",\n \"--receive-pack\",\n \"--exec\"\n]);\nfunction isMergeFastForwardFromUpstream(tokens, upstream) {\n const { flags, positionals } = subcommandArgs(tokens, \"merge\");\n if (!flags.includes(\"--ff-only\") || positionals.length !== 1) return false;\n const ref = positionals[0];\n return ref === \"@{u}\" || ref === \"@{upstream}\" || upstream !== null && ref === upstream;\n}\nconst GIT_PULL_NO_REBASE = /* @__PURE__ */ new Set([\n \"--rebase=false\",\n \"--rebase=no\",\n \"--rebase=off\",\n \"--rebase=0\"\n]);\nfunction isPullFromUpstream(tokens, upstream) {\n const { flags, positionals } = subcommandArgs(tokens, \"pull\");\n if (flags.some((t) => t.startsWith(\"--rebase\") && !GIT_PULL_NO_REBASE.has(t) || t === \"--no-ff\" || !t.startsWith(\"--\") && t.slice(1).includes(\"r\"))) return false;\n if (positionals.length === 0) return true;\n if (positionals.length !== 2 || upstream === null) return false;\n const [remote, branch] = positionals;\n return `${remote}/${branch.replace(/^refs\\/heads\\//, \"\")}` === upstream;\n}\nfunction isRefMovingReset(tokens, cwd, head) {\n if (tokens.slice(tokens.indexOf(\"reset\") + 1).includes(\"--\")) return false;\n const { positionals } = subcommandArgs(tokens, \"reset\");\n if (positionals.length !== 1) return false;\n if (head !== \"HEAD\" && /^(HEAD|@)/.test(positionals[0])) return false;\n const target = resolveCommit(cwd, positionals[0]);\n if (target === null) return false;\n return target !== resolveCommit(cwd, head);\n}\nfunction pushDestinations(tokens, current) {\n const { positionals } = subcommandArgs(tokens, \"push\", GIT_PUSH_VALUE_FLAGS);\n const refspecs = positionals.slice(1);\n if (refspecs.length === 0) return null;\n const names = [];\n for (const spec of refspecs) {\n const dst = refspecDestination(spec);\n if (dst === \"HEAD\" || dst === \"@\") {\n if (current !== null) names.push(current);\n continue;\n }\n names.push(dst);\n }\n return names;\n}\nconst GIT_PUSH_EVERY_BRANCH = /* @__PURE__ */ new Set([\n \"--all\",\n \"--branches\",\n \"--mirror\"\n]);\nfunction leavesRefInPlace(tokens, sub) {\n const { flags } = subcommandArgs(tokens, sub);\n if (flags.includes(\"--abort\") || flags.includes(\"--quit\")) return true;\n return sub === \"commit\" && flags.includes(\"--dry-run\");\n}\nfunction movesProtectedRef(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub === void 0) return false;\n if (sub === \"switch\" || sub === \"checkout\" || sub === \"worktree\") return isGitProtectedBranchForceCreate(tokens, ctx);\n if (sub === \"branch\") return isGitProtectedBranchRefWrite(tokens, ctx);\n if (sub === \"fetch\") return isGitProtectedBranchFetchWrite(tokens, ctx);\n if (sub === \"update-ref\") return isGitProtectedUpdateRef(tokens, ctx);\n if (sub !== \"push\" && sub !== \"reset\" && !GIT_CHECKED_OUT_WRITES.has(sub)) return false;\n const cwd = gitEffectiveCwd(tokens, ctx.cwd);\n const pending = ctx.pendingBranches?.[cwd];\n const current = pending ? pending.branch : getCurrentBranch(cwd);\n const protectedSet = getProtectedBranches(cwd, ctx.repoProtectedBranches ?? []);\n const onProtected = current !== null && protectedSet.has(current);\n if (sub === \"push\") {\n const { flags } = subcommandArgs(tokens, \"push\", GIT_PUSH_VALUE_FLAGS);\n if (flags.some((f) => GIT_PUSH_EVERY_BRANCH.has(f))) return true;\n const destinations = pushDestinations(tokens, current);\n if (destinations === null) {\n if (flags.includes(\"--tags\")) return false;\n return onProtected;\n }\n return destinations.some((d) => protectedSet.has(d));\n }\n if (!onProtected) return false;\n if (leavesRefInPlace(tokens, sub)) return false;\n if (sub === \"reset\") return isRefMovingReset(tokens, cwd, pending ? current : \"HEAD\");\n if (sub === \"merge\" || sub === \"pull\") {\n const upstream = getUpstream(cwd, current);\n if (sub === \"merge\" && isMergeFastForwardFromUpstream(tokens, upstream)) return false;\n if (sub === \"pull\" && isPullFromUpstream(tokens, upstream)) return false;\n }\n return true;\n}\nconst PNPM_BUILTINS = /* @__PURE__ */ new Set([\n \"install\",\n \"i\",\n \"add\",\n \"remove\",\n \"rm\",\n \"uninstall\",\n \"un\",\n \"update\",\n \"up\",\n \"upgrade\",\n \"list\",\n \"ls\",\n \"ll\",\n \"la\",\n \"why\",\n \"view\",\n \"info\",\n \"show\",\n \"outdated\",\n \"audit\",\n \"licenses\",\n \"init\",\n \"create\",\n \"link\",\n \"unlink\",\n \"pack\",\n \"publish\",\n \"config\",\n \"set\",\n \"get\",\n \"store\",\n \"cache\",\n \"rebuild\",\n \"rb\",\n \"prune\",\n \"dedupe\",\n \"dlx\",\n \"exec\",\n \"run\",\n \"patch\",\n \"patch-commit\",\n \"recursive\",\n \"-r\"\n]);\nconst NPM_READ_OPS = /* @__PURE__ */ new Set([\n \"view\",\n \"info\",\n \"show\"\n]);\nfunction isNpmReadOp(tokens) {\n const sub = tokens[1];\n return sub !== void 0 && NPM_READ_OPS.has(sub);\n}\nfunction getNpmRedirectReason(tokens) {\n const sub = tokens[1];\n const BASE = \"This project uses pnpm.\";\n if (!sub) return `${BASE} Use \\`pnpm\\` instead of npm.`;\n if (sub === \"install\" || sub === \"i\" || sub === \"ci\") {\n if (tokens.slice(2).some((t) => !t.startsWith(\"-\"))) return `${BASE} Use \\`pnpm add <pkg>\\` instead of \\`npm install <pkg>\\`.`;\n return `${BASE} Use \\`pnpm install\\` instead of npm.`;\n }\n if (sub === \"add\") return `${BASE} Use \\`pnpm add <pkg>\\` instead of npm.`;\n if (sub === \"uninstall\" || sub === \"remove\" || sub === \"rm\" || sub === \"un\" || sub === \"r\") return `${BASE} Use \\`pnpm remove <pkg>\\` instead of npm.`;\n if (sub === \"run\" || sub === \"run-script\") return `${BASE} Use \\`pnpm run <script>\\` or \\`pnpm <script>\\` instead of npm.`;\n if (sub === \"test\" || sub === \"t\" || sub === \"tst\") return `${BASE} Use \\`pnpm test\\` instead of npm.`;\n if (sub === \"start\") return `${BASE} Use \\`pnpm start\\` instead of npm.`;\n if (sub === \"stop\") return `${BASE} Use \\`pnpm stop\\` instead of npm.`;\n if (sub === \"restart\") return `${BASE} Use \\`pnpm restart\\` instead of npm.`;\n if (sub === \"exec\") return `${BASE} Use \\`pnpm exec <cmd>\\` instead of npm.`;\n if (sub === \"list\" || sub === \"ls\" || sub === \"ll\" || sub === \"la\") return `${BASE} Use \\`pnpm list\\` instead of npm.`;\n if (sub === \"why\") return `${BASE} Use \\`pnpm why\\` instead of npm.`;\n if (sub === \"outdated\") return `${BASE} Use \\`pnpm outdated\\` instead of npm.`;\n if (sub === \"audit\") return `${BASE} Use \\`pnpm audit\\` instead of npm.`;\n if (sub === \"update\" || sub === \"up\" || sub === \"upgrade\") return `${BASE} Use \\`pnpm update\\` instead of npm.`;\n if (sub === \"init\") return `${BASE} Use \\`pnpm init\\` instead of npm.`;\n if (sub === \"publish\") return `${BASE} Use \\`pnpm publish\\` instead of npm.`;\n if (sub === \"link\") return `${BASE} Use \\`pnpm link\\` instead of npm.`;\n if (sub === \"unlink\") return `${BASE} Use \\`pnpm unlink\\` instead of npm.`;\n if (sub === \"pack\") return `${BASE} Use \\`pnpm pack\\` instead of npm.`;\n if (sub === \"cache\") return `${BASE} Use \\`pnpm store\\` instead of \\`npm cache\\`.`;\n if (sub === \"config\" || sub === \"set\" || sub === \"get\") return `${BASE} Use \\`pnpm config\\` instead of npm.`;\n return `${BASE} Use the equivalent pnpm command instead of npm.`;\n}\nconst LAST_POSITIONAL_DEST = /* @__PURE__ */ new Set([\n \"cp\",\n \"mv\",\n \"rsync\",\n \"install\",\n \"ln\"\n]);\nconst ALL_POSITIONAL_DEST = /* @__PURE__ */ new Set([\"tee\", \"truncate\"]);\nfunction explicitTargetDirectory(rest) {\n for (const [i, t] of rest.entries()) {\n if (t === \"-t\" || t === \"--target-directory\") return rest[i + 1] ?? null;\n if (t.startsWith(\"--target-directory=\")) return t.slice(19);\n }\n return null;\n}\nconst OUTPUT_REDIRECT = /^(?:\\d*|&)>{1,2}$/;\nconst OUTPUT_REDIRECT_ATTACHED = /^(?:\\d*|&)>{1,2}(.+)$/;\nconst INPUT_REDIRECT = /^\\d*<$/;\nconst INPUT_REDIRECT_ATTACHED = /^\\d*<([^<].*)$/;\nfunction spacedRedirectDirection(token) {\n if (OUTPUT_REDIRECT.test(token)) return \"out\";\n if (INPUT_REDIRECT.test(token)) return \"in\";\n return null;\n}\nfunction splitRedirects(tokens) {\n const redirects = [];\n const rest = [];\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n const spaced = spacedRedirectDirection(t);\n if (spaced !== null) {\n const next = tokens[i + 1];\n if (next !== void 0) redirects.push({\n direction: spaced,\n target: next\n });\n i++;\n continue;\n }\n const out = OUTPUT_REDIRECT_ATTACHED.exec(t);\n if (out) {\n redirects.push({\n direction: \"out\",\n target: out[1]\n });\n continue;\n }\n const input = INPUT_REDIRECT_ATTACHED.exec(t);\n if (input) {\n redirects.push({\n direction: \"in\",\n target: input[1]\n });\n continue;\n }\n rest.push(t);\n }\n return {\n redirects,\n rest\n };\n}\nfunction redirectTargets(tokens, direction) {\n return splitRedirects(tokens).redirects.filter((r) => r.direction === direction).map((r) => r.target);\n}\nfunction writeDestinations(tokens) {\n const cmd = path.basename(tokens[0] ?? \"\");\n const rest = tokens.slice(1);\n const dests = redirectTargets(tokens, \"out\");\n if (cmd === \"dd\") dests.push(...rest.filter((t) => t.startsWith(\"of=\")).map((t) => t.slice(3)));\n else if (cmd === \"sed\") {\n if (rest.some((t) => t === \"--in-place\" || /^-[a-zA-Z]*i/.test(t))) dests.push(...rest.filter((t) => !t.startsWith(\"-\")));\n } else if (ALL_POSITIONAL_DEST.has(cmd)) dests.push(...rest.filter((t) => !t.startsWith(\"-\")));\n else if (LAST_POSITIONAL_DEST.has(cmd)) {\n if (cmd === \"cp\" && rest.includes(\"--remove-destination\")) return dests;\n const targetDir = explicitTargetDirectory(rest);\n if (targetDir !== null) dests.push(targetDir);\n else {\n const last = rest.findLast((t) => !t.startsWith(\"-\"));\n if (last !== void 0) dests.push(last);\n }\n }\n return dests;\n}\nfunction writesIntoNodeModules(tokens, ctx) {\n return writeDestinations(tokens).some((d) => targetsNodeModules(d, ctx.cwd));\n}\nconst NODE_MODULES_WRITE_REASON = \"Don't write into node_modules/. Its files are hardlinks into pnpm's global store, so overwriting one in place (plain `cp`, `>` redirect, `sed -i`, ...) writes through the link and corrupts that package for every project on this machine -- silently, since the directory you wrote into ends up fine. To test a local build as an installed dependency, run it directly (`node packages/<pkg>/dist/bin.mjs <cmd>`), or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`). If you must replace a file in place, `cp --remove-destination` is safe -- it unlinks the target first. Run `pnpm store status` to check whether the store is already damaged.\";\nfunction isChmod777(tokens) {\n return tokens.some((t) => t === \"777\" || t === \"0777\");\n}\nfunction isGitForcePush(tokens) {\n const pushIdx = tokens.indexOf(\"push\");\n if (pushIdx === -1) return false;\n return tokens.slice(pushIdx + 1).some((t) => t === \"--force\" || t === \"-f\");\n}\nconst ENV_READ_FILE_COMMANDS = /* @__PURE__ */ new Set([\n \"cat\",\n \"head\",\n \"tail\",\n \"less\",\n \"more\",\n \"source\",\n \".\"\n]);\nconst GREP_FAMILY_COMMANDS = /* @__PURE__ */ new Set([\n \"grep\",\n \"rg\",\n \"ag\"\n]);\nfunction grepFileOperands(rest) {\n const files = [];\n let patternAccountedFor = false;\n let optionsEnded = false;\n for (let i = 0; i < rest.length; i++) {\n const t = rest[i];\n if (!optionsEnded && t === \"--\") {\n optionsEnded = true;\n continue;\n }\n if (!optionsEnded) {\n if (t === \"-f\" || t === \"--file\") {\n const value = rest[i + 1];\n if (value !== void 0) {\n files.push(value);\n i++;\n }\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"--file=\")) {\n files.push(t.slice(7));\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"-f\") && t !== \"-f\" && !t.startsWith(\"--\")) {\n files.push(t.slice(2));\n patternAccountedFor = true;\n continue;\n }\n if (t === \"-e\" || t === \"--regexp\") {\n i++;\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"--regexp=\") || t.startsWith(\"-e\") && t !== \"-e\" && !t.startsWith(\"--\")) {\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n }\n if (!patternAccountedFor) {\n patternAccountedFor = true;\n continue;\n }\n files.push(t);\n }\n return files;\n}\nfunction envFileOperands(tokens) {\n const cmd = path.basename(tokens[0] ?? \"\");\n const { redirects, rest } = splitRedirects(tokens.slice(1));\n const operands = redirects.filter((r) => r.direction === \"in\").map((r) => r.target);\n if (GREP_FAMILY_COMMANDS.has(cmd)) operands.push(...grepFileOperands(rest));\n else if (ENV_READ_FILE_COMMANDS.has(cmd)) operands.push(...rest.filter((t) => !t.startsWith(\"-\")));\n return operands;\n}\nconst HEALTH_CEILING_FILES = [\"health-baseline.json\", \".tooling.json\"];\nconst HEALTH_BASELINE_FILE = \"health-baseline.json\";\nconst HEALTH_RAISE_REASON = \"A health ceiling raise travels alone: open a ceiling-only pull request -- only health-baseline.json and .tooling.json changed -- for a human to merge, or split the module. `bst health:check` refuses the raise beside code either way. To restore the default branch's copy run `git show origin/<default>:health-baseline.json > health-baseline.json`, and to adopt lower counts run `bst health:check --update-baseline`.\";\nfunction writesHealthBaseline(tokens, cwd) {\n const destinations = writeDestinations(tokens);\n if (!destinations.some((dest) => baseName(dest) === \"health-baseline.json\")) return false;\n const root = getRepoTopLevel(cwd) ?? cwd;\n return destinations.some((dest) => samePath(resolveIn(cwd, dest), path.join(root, HEALTH_BASELINE_FILE)));\n}\nfunction baseName(target) {\n const segments = target.split(/[/\\\\]/);\n return segments[segments.length - 1] ?? \"\";\n}\nfunction isBaselineRestore(tokens) {\n if (tokens[0] !== \"git\") return false;\n let i = 1;\n while (tokens[i]?.startsWith(\"-\") === true) i += GIT_FLAGS_WITH_ARG.has(tokens[i] ?? \"\") ? 2 : 1;\n if (tokens[i] !== \"show\") return false;\n return tokens.slice(i + 1).some((token) => token.includes(\":\") && baseName(token.slice(token.lastIndexOf(\":\") + 1)) === \"health-baseline.json\");\n}\nfunction isHealthBaselineReset(tokens) {\n return tokens.includes(\"health:check\") && tokens.includes(\"--update-baseline\") && tokens.includes(\"--reset\");\n}\nfunction raiseTravelsWithCode(cwd) {\n return branchCarriesOtherFiles(cwd, HEALTH_CEILING_FILES) === true;\n}\nconst denyRules = [\n {\n name: \"sudo\",\n match: /^sudo$/,\n action: \"deny\",\n reason: \"Don't use sudo. If you need elevated permissions, ask me to do it manually.\"\n },\n {\n name: \"git-force-push\",\n match: /^git$/,\n action: \"deny\",\n when: (tokens) => isGitForcePush(tokens),\n reason: \"Use `git push --force-with-lease` instead of `--force`.\"\n },\n {\n name: \"git-protected-branch-write\",\n match: /^git$/,\n action: \"deny\",\n when: (tokens, ctx) => movesProtectedRef(tokens, ctx),\n reason: \"This would move a protected branch (main, master, the remote's default branch, or one listed in .claude/hooks/bst-hook.settings.json#protectedBranches). Work on a feature branch in a worktree: `git worktree add ../<repo>-<topic> -b feat/<topic>`, then commit and push there. To bring `main` up to date, use `git pull --ff-only`.\"\n },\n {\n name: \"chmod-777\",\n match: /^chmod$/,\n action: \"deny\",\n when: (tokens) => isChmod777(tokens),\n reason: \"Don't use 777 permissions. Use more restrictive permissions.\"\n },\n {\n name: \"node-modules-write\",\n match: /./,\n action: \"deny\",\n when: (tokens, ctx) => writesIntoNodeModules(tokens, ctx),\n reason: NODE_MODULES_WRITE_REASON\n },\n {\n name: \"env-file-read\",\n match: /./,\n action: \"deny\",\n when: (tokens) => envFileOperands(tokens).some(isEnvFile),\n reason: \"Don't read .env files. These contain secrets that should not appear in the conversation.\"\n },\n {\n name: \"env-file-write\",\n match: /./,\n action: \"deny\",\n when: (tokens) => redirectTargets(tokens, \"out\").some(isEnvFile),\n reason: \"Don't write to .env files. These contain secrets.\"\n },\n {\n name: \"health-baseline-write\",\n match: /./,\n action: \"deny\",\n when: (tokens, ctx) => writesHealthBaseline(tokens, ctx.cwd) && !isBaselineRestore(tokens) && raiseTravelsWithCode(ctx.cwd),\n reason: HEALTH_RAISE_REASON\n },\n {\n name: \"health-baseline-reset\",\n match: /^bst$/,\n action: \"deny\",\n when: (tokens, ctx) => isHealthBaselineReset(tokens) && raiseTravelsWithCode(ctx.cwd),\n reason: HEALTH_RAISE_REASON\n },\n {\n name: \"npx-redirect\",\n match: /^npx$/,\n action: \"deny\",\n reason: \"This project uses pnpm. Use `pnpm dlx <pkg>` or `pnpm exec <cmd>` instead of npx.\"\n },\n {\n name: \"mise-self-update\",\n match: /^mise$/,\n action: \"deny\",\n when: (tokens) => tokens[1] === \"self-update\",\n reason: \"Don't self-update mise. The version is Renovate-managed; ask a human to bump the pin.\"\n }\n];\n\n//#endregion\n//#region src/lib/script-resolver.ts\nconst PackageJsonSchema = object({ scripts: record(string(), unknown()) });\nfunction resolveScript(scriptName, cwd) {\n const scripts = readScripts(cwd);\n if (!scripts) return null;\n const main = scripts[scriptName];\n if (typeof main !== \"string\") return null;\n const pre = scripts[`pre${scriptName}`];\n const post = scripts[`post${scriptName}`];\n return {\n pre: typeof pre === \"string\" ? pre : null,\n main,\n post: typeof post === \"string\" ? post : null\n };\n}\nfunction resolveFilteredScript(scriptName, filterPkg, cwd) {\n const pkgDir = findWorkspacePackageDir(filterPkg, cwd);\n if (!pkgDir) return null;\n const script = resolveScript(scriptName, pkgDir);\n if (!script) return null;\n return {\n ...script,\n pkgDir\n };\n}\nfunction resolveRecursiveScripts(scriptName, rootDir) {\n const pkgDirs = listWorkspacePackageDirs(rootDir);\n if (!pkgDirs) return null;\n const results = [];\n for (const pkgDir of pkgDirs) {\n const resolved = resolveScript(scriptName, pkgDir);\n if (resolved) results.push({\n ...resolved,\n pkgDir\n });\n }\n return results;\n}\nfunction listWorkspacePackageDirs(rootDir) {\n const patterns = readWorkspacePatterns(rootDir);\n if (!patterns) return null;\n const dirs = [];\n for (const pattern of patterns) {\n if (!pattern.endsWith(\"/*\")) continue;\n const baseDir = pattern.slice(0, -2);\n const parentDir = resolve(rootDir, baseDir);\n let entries;\n try {\n entries = readdirSync(parentDir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n const entryDir = join(parentDir, entry);\n try {\n if (!statSync(entryDir).isDirectory()) continue;\n } catch {\n continue;\n }\n dirs.push(entryDir);\n }\n }\n return dirs.length > 0 ? dirs : null;\n}\nfunction findWorkspacePackageDir(pkgName, rootDir) {\n const pkgDirs = listWorkspacePackageDirs(rootDir);\n if (!pkgDirs) return null;\n for (const entryDir of pkgDirs) {\n const name = readPackageName(entryDir);\n if (name === pkgName || name === `@${pkgName}`) return entryDir;\n if (entryDir.split(\"/\").pop() === pkgName) return entryDir;\n if (name) {\n if ((name.startsWith(\"@\") ? name.split(\"/\")[1] : name) === pkgName) return entryDir;\n }\n }\n return null;\n}\nfunction readWorkspacePatterns(rootDir) {\n try {\n const lines = readFileSync(join(rootDir, \"pnpm-workspace.yaml\"), \"utf-8\").split(\"\\n\");\n const packagesIdx = lines.findIndex((l) => /^packages\\s*:/.test(l));\n if (packagesIdx === -1) return null;\n const patterns = [];\n for (let i = packagesIdx + 1; i < lines.length; i++) {\n const line = lines[i];\n const match = /^\\s+-\\s+(.+)$/.exec(line);\n if (!match) break;\n patterns.push(match[1].trim().replace(/['\"`]/g, \"\"));\n }\n return patterns.length > 0 ? patterns : null;\n } catch {\n return null;\n }\n}\nconst PackageNameSchema = object({ name: string() });\nfunction readPackageName(dir) {\n try {\n const raw = readFileSync(join(dir, \"package.json\"), \"utf-8\");\n const result = PackageNameSchema.safeParse(JSON.parse(raw));\n if (!result.success) return null;\n return result.data.name;\n } catch {\n return null;\n }\n}\nfunction readScripts(cwd) {\n try {\n const raw = readFileSync(join(cwd, \"package.json\"), \"utf-8\");\n const result = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!result.success) return null;\n return result.data.scripts;\n } catch {\n return null;\n }\n}\n\n//#endregion\n//#region src/lib/workspace-root.ts\nfunction findWorkspaceRoot(cwd) {\n let dir = resolve(cwd);\n while (true) {\n if (existsSync(join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n//#endregion\n//#region src/evaluate.ts\nconst MAX_EVAL_DEPTH = 5;\nfunction subshellBody(command) {\n if (!command.startsWith(\"(\") || !command.endsWith(\")\")) return null;\n let depth = 0;\n let quote = null;\n for (let i = 0; i < command.length; i++) {\n const ch = command[i];\n if (quote !== null) {\n if (ch === quote) quote = null;\n else if (ch === \"\\\\\" && quote === \"\\\"\") i++;\n continue;\n }\n if (ch === \"\\\\\") i++;\n else if (ch === \"'\" || ch === \"\\\"\") quote = ch;\n else if (ch === \"(\") depth++;\n else if (ch === \")\") {\n depth--;\n if (depth === 0) return i === command.length - 1 ? command.slice(1, -1) : null;\n }\n }\n return null;\n}\nfunction extractCdDir(segment, ctx) {\n const tokenResult = tokenize(segment);\n if (!tokenResult.ok || tokenResult.tokens.length !== 2) return null;\n const tokens = tokenResult.tokens;\n if (tokens[0] !== \"cd\") return null;\n const dir = tokens[1];\n if (path.isAbsolute(dir)) return dir;\n return path.resolve(ctx.cwd, dir);\n}\nfunction extractBranchSwitch(segment, ctx) {\n const tokenResult = tokenize(segment);\n if (!tokenResult.ok) return void 0;\n let tokens = tokenResult.tokens;\n let envSkipped = 0;\n while (envSkipped < tokens.length && /^\\w+=/.test(tokens[envSkipped])) envSkipped++;\n tokens = tokens.slice(envSkipped);\n if (tokens.length === 0 || path.basename(tokens[0]) !== \"git\") return void 0;\n return branchSwitch(tokens, ctx, checkInjection(tokens, segment).safe);\n}\nfunction evaluateCommand(command, ctx) {\n if (ctx.depth >= MAX_EVAL_DEPTH) return {\n action: \"none\",\n rule: null,\n reason: \"max evaluation depth exceeded\"\n };\n const trimmed = command.trim();\n if (!trimmed) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n const body = subshellBody(trimmed);\n if (body !== null) return evaluateCommand(body, {\n ...ctx,\n depth: ctx.depth + 1\n });\n const segments = splitCommand(trimmed);\n if (segments.length === 0) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n let firstNone = null;\n const currentCtx = { ...ctx };\n let unknownAfterNext;\n for (const segment of segments) {\n if (segment.operator === \"&&\") {\n const cdDir = extractCdDir(segment.command, currentCtx);\n if (cdDir) currentCtx.cwd = cdDir;\n }\n const result = evaluateSegment(segment.command, currentCtx);\n if (result.action === \"deny\") return result;\n if (!firstNone) firstNone = result;\n if (unknownAfterNext) {\n currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [unknownAfterNext.dir]: unknownAfterNext\n };\n unknownAfterNext = void 0;\n }\n const switched = extractBranchSwitch(segment.command, currentCtx);\n if (switched) {\n const unknown = {\n dir: switched.dir,\n branch: null\n };\n if (segment.operator === \"&&\") currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [switched.dir]: switched\n };\n else if (segment.operator === \"||\") unknownAfterNext = unknown;\n else currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [switched.dir]: unknown\n };\n }\n }\n return firstNone ?? {\n action: \"none\",\n rule: null,\n reason: null\n };\n}\nfunction evaluateResolvedScript(resolved, ctx) {\n if (resolved.pre) {\n const preResult = evaluateCommand(resolved.pre, ctx);\n if (preResult.action === \"deny\") return preResult;\n }\n const mainResult = evaluateCommand(resolved.main, ctx);\n if (mainResult.action === \"deny\") return mainResult;\n if (resolved.post) {\n const postResult = evaluateCommand(resolved.post, ctx);\n if (postResult.action === \"deny\") return postResult;\n }\n return {\n action: \"none\",\n rule: null,\n reason: null\n };\n}\nfunction evaluateSegment(rawSegment, ctx) {\n const trimmed = rawSegment.trim();\n const body = subshellBody(trimmed);\n if (body !== null) return evaluateCommand(body, {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (trimmed.startsWith(\"(\") && trimmed.endsWith(\")\")) return {\n action: \"none\",\n rule: null,\n reason: \"subshell\"\n };\n const tokenResult = tokenize(rawSegment);\n if (!tokenResult.ok) return {\n action: \"none\",\n rule: null,\n reason: tokenResult.error\n };\n let tokens = tokenResult.tokens;\n if (tokens.length === 0) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n let envSkipped = 0;\n while (envSkipped < tokens.length && /^\\w+=/.test(tokens[envSkipped])) envSkipped++;\n if (envSkipped >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n tokens = tokens.slice(envSkipped);\n if (writesIntoNodeModules(tokens, ctx)) return {\n action: \"deny\",\n rule: \"node-modules-write\",\n reason: NODE_MODULES_WRITE_REASON\n };\n const injection = checkInjection(tokens, rawSegment);\n if (!injection.safe) return {\n action: \"none\",\n rule: null,\n reason: injection.reason\n };\n const SAFE_REDIRECT_TOKENS = /* @__PURE__ */ new Set([\n \"2>&1\",\n \"2>/dev/null\",\n \">/dev/null\",\n \"1>/dev/null\"\n ]);\n tokens = tokens.filter((t, i) => {\n if (SAFE_REDIRECT_TOKENS.has(t)) return false;\n if ((t === \">\" || t === \">>\") && tokens[i + 1] === \"/dev/null\") return false;\n if (t === \"/dev/null\" && i > 0 && (tokens[i - 1] === \">\" || tokens[i - 1] === \">>\")) return false;\n return true;\n });\n const cmdName = path.basename(tokens[0]);\n if (cmdName === \"command\" && tokens.length > 1) return evaluateCommand(joinTokens(tokens.slice(1)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (cmdName === \"env\") {\n let envIdx = 1;\n while (envIdx < tokens.length && /^\\w+=/.test(tokens[envIdx])) envIdx++;\n if (envIdx >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n return evaluateCommand(joinTokens(tokens.slice(envIdx)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n if (cmdName === \"pnpm\") return evaluatePnpm(tokens, ctx);\n if (cmdName === \"npm\") return evaluateNpm(tokens);\n if (cmdName === \"mise\" && tokens[1] === \"exec\") {\n const inner = miseExecInner(tokens);\n if (!inner) return {\n action: \"none\",\n rule: null,\n reason: \"bare mise exec\"\n };\n return evaluateCommand(joinTokens(inner), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n if (cmdName === \"bash\" || cmdName === \"sh\" || cmdName === \"zsh\") return evaluateShellC(tokens, ctx);\n if (cmdName === \"xargs\") return evaluateXargs(tokens, ctx);\n if (cmdName === \"node\" && (tokens.includes(\"-e\") || tokens.includes(\"-p\") || tokens.includes(\"--eval\") || tokens.includes(\"--print\"))) return {\n action: \"none\",\n rule: null,\n reason: \"node eval\"\n };\n for (const rule of denyRules) if (rule.match.test(cmdName)) {\n if (!rule.when || rule.when(tokens, ctx)) return {\n action: \"deny\",\n rule: rule.name,\n reason: rule.reason ?? null\n };\n }\n const advice = cmdName === \"git\" ? worktreeAdvice(tokens, ctx) : void 0;\n return {\n action: \"none\",\n rule: null,\n reason: `no rule matched: ${cmdName}`,\n ...advice ? { advice } : {}\n };\n}\nfunction miseExecInner(tokens) {\n const dashIdx = tokens.indexOf(\"--\");\n if (dashIdx === -1) return void 0;\n const inner = tokens.slice(dashIdx + 1);\n return inner.length > 0 ? inner : void 0;\n}\nfunction scanPnpmFlags(subTokens, from, state) {\n for (let i = from; i < subTokens.length; i++) {\n const t = subTokens[i];\n if (t === \"--filter\" || t.startsWith(\"--filter=\") || t === \"-F\" || t.startsWith(\"-F=\")) return {\n name: void 0,\n filterIdx: i\n };\n if (t === \"-r\" || t === \"--recursive\") {\n state.isRecursive = true;\n continue;\n }\n if (t === \"-w\" || t === \"--workspace-root\") {\n state.isWorkspaceRoot = true;\n continue;\n }\n if (t === \"-C\" || t === \"--dir\") {\n state.dirOverride = subTokens[++i];\n continue;\n }\n if (t.startsWith(\"-C=\") || t.startsWith(\"--dir=\")) {\n state.dirOverride = t.split(\"=\", 2)[1];\n continue;\n }\n if (t.startsWith(\"-\") && !PNPM_BUILTINS.has(t)) continue;\n return { name: t };\n }\n return { name: void 0 };\n}\nfunction evaluatePnpm(tokens, ctx) {\n const subTokens = tokens.slice(1);\n const state = {\n isRecursive: false,\n isWorkspaceRoot: false,\n dirOverride: void 0\n };\n const scan = scanPnpmFlags(subTokens, 0, state);\n if (scan.filterIdx !== void 0) return evaluatePnpmFilter(tokens, subTokens, scan.filterIdx, ctx);\n const subcommand = scan.name;\n const subcommandIdx = subcommand ? subTokens.indexOf(subcommand) : -1;\n if (!subcommand) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (subcommand === \"dlx\") return {\n action: \"none\",\n rule: null,\n reason: \"pnpm dlx\"\n };\n if (subcommand === \"add\") return {\n action: \"none\",\n rule: null,\n reason: \"pnpm add\"\n };\n if (subcommand === \"exec\") {\n const execArgs = subTokens.slice(subcommandIdx + 1);\n if (execArgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"bare pnpm exec\"\n };\n return evaluateCommand(joinTokens(execArgs), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n let scriptName;\n let { isRecursive, isWorkspaceRoot, dirOverride } = state;\n if (subcommand === \"run\") {\n const runScan = scanPnpmFlags(subTokens, subcommandIdx + 1, state);\n ({isRecursive, isWorkspaceRoot, dirOverride} = state);\n if (runScan.filterIdx !== void 0) return evaluatePnpmFilter(tokens, subTokens, runScan.filterIdx, ctx);\n if (!runScan.name) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm run without script name\"\n };\n scriptName = runScan.name;\n } else if (!PNPM_BUILTINS.has(subcommand)) scriptName = subcommand;\n else return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (isRecursive) return evaluatePnpmRecursive(scriptName, ctx);\n if (isWorkspaceRoot) {\n const root = findWorkspaceRoot(ctx.cwd);\n if (!root) return {\n action: \"none\",\n rule: null,\n reason: \"workspace root not found\"\n };\n return evaluatePnpmScript(scriptName, {\n ...ctx,\n cwd: root\n });\n }\n if (dirOverride) {\n const resolved = path.resolve(ctx.cwd, dirOverride);\n return evaluatePnpmScript(scriptName, {\n ...ctx,\n cwd: resolved\n });\n }\n return evaluatePnpmScript(scriptName, ctx);\n}\nfunction evaluatePnpmScript(scriptName, ctx) {\n const resolved = resolveScript(scriptName, ctx.cwd);\n if (!resolved) return {\n action: \"none\",\n rule: null,\n reason: \"script resolution failed\"\n };\n const res = evaluateResolvedScript(resolved, {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (res.action === \"deny\") return res;\n return {\n action: \"none\",\n rule: `pnpm-script:${scriptName}`,\n reason: null\n };\n}\nfunction evaluatePnpmRecursive(scriptName, ctx) {\n const resolved = resolveRecursiveScripts(scriptName, ctx.cwd);\n if (!resolved || resolved.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm recursive\"\n };\n for (const pkg of resolved) {\n const res = evaluateResolvedScript(pkg, {\n ...ctx,\n depth: ctx.depth + 1,\n cwd: pkg.pkgDir ?? ctx.cwd\n });\n if (res.action === \"deny\") return res;\n }\n return {\n action: \"none\",\n rule: `pnpm-recursive:${scriptName}`,\n reason: null\n };\n}\nfunction evaluateNpm(tokens) {\n if (isNpmReadOp(tokens)) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n return {\n action: \"deny\",\n rule: \"npm-redirect\",\n reason: getNpmRedirectReason(tokens)\n };\n}\nfunction evaluatePnpmFilter(_tokens, subTokens, filterIdx, ctx) {\n const filterPkgs = [];\n let cursor = filterIdx;\n while (cursor < subTokens.length) {\n const t = subTokens[cursor];\n if (t === \"--filter\" || t === \"-F\") {\n const pkg = subTokens[cursor + 1];\n if (!pkg || pkg.startsWith(\"-\")) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n filterPkgs.push(pkg);\n cursor += 2;\n } else if (t.startsWith(\"--filter=\") || t.startsWith(\"-F=\")) {\n const pkg = t.startsWith(\"-F=\") ? t.slice(3) : t.slice(9);\n if (!pkg) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n filterPkgs.push(pkg);\n cursor += 1;\n } else break;\n }\n if (filterPkgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n let filterSubcommand;\n let subcmdIdx = -1;\n for (let i = cursor; i < subTokens.length; i++) {\n const t = subTokens[i];\n if (t === \"--filter\" || t === \"-F\") {\n i += 1;\n continue;\n }\n if (t.startsWith(\"--filter=\") || t.startsWith(\"-F=\")) continue;\n if (t.startsWith(\"-\") && !PNPM_BUILTINS.has(t)) continue;\n filterSubcommand = t;\n subcmdIdx = i;\n break;\n }\n if (!filterSubcommand) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without subcommand\"\n };\n if (PNPM_BUILTINS.has(filterSubcommand) && filterSubcommand !== \"run\" && filterSubcommand !== \"exec\") return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (filterSubcommand === \"exec\") {\n const execArgs = subTokens.slice(subcmdIdx + 1);\n if (execArgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"bare pnpm exec\"\n };\n return evaluateCommand(joinTokens(execArgs), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n const scriptName = filterSubcommand === \"run\" ? subTokens[subcmdIdx + 1] : filterSubcommand;\n if (!scriptName || scriptName.startsWith(\"-\")) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter run without script name\"\n };\n if (PNPM_BUILTINS.has(scriptName) && scriptName !== \"run\") return {\n action: \"none\",\n rule: null,\n reason: null\n };\n for (const pkg of filterPkgs) {\n const resolved = resolveFilteredScript(scriptName, pkg, ctx.cwd);\n if (!resolved) return {\n action: \"none\",\n rule: null,\n reason: \"filtered script resolution failed\"\n };\n const res = evaluateResolvedScript(resolved, {\n ...ctx,\n depth: ctx.depth + 1,\n cwd: resolved.pkgDir ?? ctx.cwd\n });\n if (res.action === \"deny\") return res;\n }\n return {\n action: \"none\",\n rule: `pnpm-filter:${filterPkgs.join(\",\")}:${scriptName}`,\n reason: null\n };\n}\nconst SHELL_LOGIN_FLAGS = /* @__PURE__ */ new Set([\"-l\", \"--login\"]);\nfunction evaluateShellC(tokens, ctx) {\n let i = 1;\n while (i < tokens.length && SHELL_LOGIN_FLAGS.has(tokens[i])) i++;\n const flag = tokens[i];\n if (flag === void 0 || !/^-[lc]+$/.test(flag) || !flag.includes(\"c\")) return {\n action: \"none\",\n rule: null,\n reason: \"shell without a plain -c\"\n };\n const cmdArg = tokens[i + 1];\n if (!cmdArg) return {\n action: \"none\",\n rule: null,\n reason: \"shell -c without command\"\n };\n if (tokens.length > i + 2) return {\n action: \"none\",\n rule: null,\n reason: \"shell -c with positional args\"\n };\n return evaluateCommand(cmdArg, {\n ...ctx,\n depth: ctx.depth + 1\n });\n}\nconst XARGS_ARG_FLAGS = /* @__PURE__ */ new Set([\n \"-I\",\n \"-d\",\n \"-n\",\n \"-P\",\n \"-s\",\n \"-L\",\n \"-E\",\n \"-a\",\n \"--max-args\",\n \"--max-procs\",\n \"--delimiter\",\n \"--replace\",\n \"--max-lines\",\n \"--max-chars\",\n \"--arg-file\",\n \"--process-slot-var\"\n]);\nconst XARGS_BOOL_FLAGS = /* @__PURE__ */ new Set([\n \"-0\",\n \"--null\",\n \"-t\",\n \"--verbose\",\n \"-r\",\n \"--no-run-if-empty\",\n \"-p\",\n \"--interactive\",\n \"-x\",\n \"--exit\",\n \"--show-limits\"\n]);\nfunction evaluateXargs(tokens, ctx) {\n let i = 1;\n while (i < tokens.length) {\n const t = tokens[i];\n if (!t.startsWith(\"-\")) break;\n if (XARGS_ARG_FLAGS.has(t)) {\n i += 2;\n continue;\n }\n const eqIdx = t.indexOf(\"=\");\n if (eqIdx !== -1) {\n const flagName = t.slice(0, eqIdx);\n if (XARGS_ARG_FLAGS.has(flagName)) {\n i++;\n continue;\n }\n }\n if (t.length > 2 && XARGS_ARG_FLAGS.has(t.slice(0, 2))) {\n i++;\n continue;\n }\n if (XARGS_BOOL_FLAGS.has(t)) {\n i++;\n continue;\n }\n return {\n action: \"none\",\n rule: null,\n reason: \"xargs with unrecognised flags\"\n };\n }\n if (i >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: \"xargs without command\"\n };\n return evaluateCommand(joinTokens(tokens.slice(i)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n}\n\n//#endregion\n//#region src/file-rules.ts\nconst READ_TOOLS = /* @__PURE__ */ new Set([\n \"Read\",\n \"Glob\",\n \"Grep\"\n]);\nconst WRITE_TOOLS = /* @__PURE__ */ new Set([\"Write\", \"Edit\"]);\nconst fileDenyRules = [\n {\n name: \"env-file-read\",\n tools: READ_TOOLS,\n action: \"deny\",\n when: (filePath) => isEnvFile(filePath),\n reason: \"Don't read .env files. These contain secrets that should not appear in the conversation.\"\n },\n {\n name: \"env-file-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath) => isEnvFile(filePath),\n reason: \"Don't write to .env files. These contain secrets.\"\n },\n {\n name: \"hooks-folder-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n const hooksDir = path.join(ctx.cwd, \".claude\", \"hooks\");\n return isWithin(hooksDir, resolved);\n },\n reason: \"Don't write to .claude/hooks/. These files are managed by the project and should not be modified directly.\"\n },\n {\n name: \"git-dir-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => targetsGitDir(filePath, ctx.cwd),\n reason: \"Don't write into .git/ directly. Its internals (config, hooks, refs) are not plain project files -- a config edit can redirect remotes or push destinations that other rules trust, and a hooks/ script runs automatically on the next commit/push. Use git subcommands instead, or ask the user.\"\n },\n {\n name: \"node-modules-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => targetsNodeModules(filePath, ctx.cwd),\n reason: \"Don't write into node_modules/. Its files are hardlinks into pnpm's global store -- editing one in place corrupts that package for every project on this machine. Edit the source package and rebuild, or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`).\"\n },\n {\n name: \"claude-settings-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n return samePath(resolved, path.join(ctx.cwd, \".claude\", \"settings.json\"));\n },\n reason: \"Don't write to .claude/settings.json. This file is managed by the project and should not be modified directly.\"\n },\n {\n name: \"health-baseline-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx, toolInput) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n if (path.basename(resolved) !== \"health-baseline.json\") return false;\n const root = getRepoTopLevel(ctx.cwd) ?? ctx.cwd;\n if (!samePath(resolved, path.join(root, \"health-baseline.json\"))) return false;\n if (!writeRaisesBaseline(resolved, toolInput)) return false;\n return branchCarriesOtherFiles(ctx.cwd, HEALTH_CEILING_FILES) === true;\n },\n reason: HEALTH_RAISE_REASON\n }\n];\nfunction writeRaisesBaseline(file, toolInput) {\n let before;\n try {\n before = readFileSync(file, \"utf8\");\n } catch (_error) {\n return false;\n }\n const after = textAfterWrite(before, toolInput);\n if (after === void 0) return false;\n const beforeJson = parseJson(before);\n const afterJson = parseJson(after);\n if (beforeJson === void 0 || afterJson === void 0) return false;\n return numberRises(beforeJson, afterJson);\n}\nfunction textAfterWrite(before, toolInput) {\n const { content, old_string: oldText, new_string: newText, replace_all: all } = toolInput;\n if (typeof content === \"string\") return content;\n if (typeof oldText !== \"string\" || typeof newText !== \"string\" || oldText === \"\") return void 0;\n const at = before.indexOf(oldText);\n if (at === -1) return void 0;\n if (all === true) return before.split(oldText).join(newText);\n return before.slice(0, at) + newText + before.slice(at + oldText.length);\n}\nfunction parseJson(text) {\n try {\n const result = record(string(), unknown()).safeParse(JSON.parse(text));\n return result.success ? result.data : void 0;\n } catch (_error) {\n return;\n }\n}\nfunction numberRises(before, after) {\n if (typeof after === \"number\") return typeof before !== \"number\" || after > before;\n if (typeof after !== \"object\" || after === null) return false;\n const beforeObject = typeof before === \"object\" && before !== null ? before : {};\n return Object.entries(after).some(([key, value]) => numberRises(Object.entries(beforeObject).find(([k]) => k === key)?.[1], value));\n}\n\n//#endregion\n//#region src/evaluate-tool.ts\nconst FILE_PATH_TOOLS = /* @__PURE__ */ new Set([\n \"Read\",\n \"Write\",\n \"Edit\"\n]);\nconst SEARCH_TOOLS = /* @__PURE__ */ new Set([\"Glob\", \"Grep\"]);\nfunction extractPath(toolName, toolInput, cwd) {\n if (FILE_PATH_TOOLS.has(toolName)) return parseFilePathInput(toolInput)?.file_path ?? null;\n if (SEARCH_TOOLS.has(toolName)) return parseSearchInput(toolInput)?.path ?? cwd;\n return null;\n}\nfunction evaluateToolUse(toolName, toolInput, ctx) {\n const filePath = extractPath(toolName, toolInput, ctx.cwd);\n if (filePath === null) return {\n action: \"none\",\n rule: null,\n reason: \"unknown tool input shape\"\n };\n for (const rule of fileDenyRules) if (rule.tools.has(toolName) && rule.when(filePath, ctx, toolInput)) return {\n action: \"deny\",\n rule: rule.name,\n reason: rule.reason ?? null\n };\n return {\n action: \"none\",\n rule: null,\n reason: \"no file rule matched\"\n };\n}\n\n//#endregion\n//#region src/lib/settings.ts\nconst SETTINGS_PATH = \".claude/hooks/bst-hook.settings.json\";\nconst BstHookSettingsSchema = object({ protectedBranches: array(string().min(1)).default([]) });\nfunction isFileClean(cwd, relativePath) {\n try {\n execFileSync(\"git\", [\n \"ls-files\",\n \"--error-unmatch\",\n relativePath\n ], {\n cwd,\n stdio: \"ignore\"\n });\n execFileSync(\"git\", [\n \"diff\",\n \"--quiet\",\n \"HEAD\",\n \"--\",\n relativePath\n ], {\n cwd,\n stdio: \"ignore\"\n });\n return true;\n } catch {\n return false;\n }\n}\nfunction loadRepoSettings(cwd) {\n const root = findWorkspaceRoot(cwd) ?? cwd;\n const settingsFile = join(root, SETTINGS_PATH);\n const empty = { protectedBranches: [] };\n if (!existsSync(settingsFile)) return empty;\n if (!isFileClean(root, SETTINGS_PATH)) return empty;\n try {\n const raw = readFileSync(settingsFile, \"utf-8\");\n const parsed = JSON.parse(raw);\n const result = BstHookSettingsSchema.safeParse(parsed);\n if (!result.success) return empty;\n return { protectedBranches: result.data.protectedBranches };\n } catch {\n return empty;\n }\n}\n\n//#endregion\n//#region src/index.ts\nconst inputResult = await readHookInput();\nif (!inputResult.ok) {\n process.stderr.write(`[bst-hook] invalid hook input: ${inputResult.error}\\n`);\n audit({\n sessionId: \"unknown\",\n cwd: \"unknown\",\n command: `<invalid input: ${inputResult.error}>`,\n decision: \"none\",\n rule: null,\n reason: `validation failed: ${inputResult.error}`,\n permissionMode: void 0\n });\n process.exit(0);\n}\nconst input = inputResult.data;\nif (input.hook_event_name !== \"PreToolUse\") process.exit(0);\nif (!(/* @__PURE__ */ new Set([\n \"Bash\",\n \"Read\",\n \"Write\",\n \"Edit\",\n \"Glob\",\n \"Grep\"\n])).has(input.tool_name)) process.exit(0);\nconst repoSettings = loadRepoSettings(input.cwd);\nlet decision;\nlet auditCommand;\nif (input.tool_name === \"Bash\") {\n const bashInput = parseBashInput(input.tool_input);\n if (!bashInput) {\n audit({\n sessionId: input.session_id,\n cwd: input.cwd,\n toolName: input.tool_name,\n command: `<invalid Bash input: ${JSON.stringify(input.tool_input).slice(0, 200)}>`,\n decision: \"none\",\n rule: null,\n reason: \"Bash tool_input missing or invalid 'command' field\",\n permissionMode: input.permission_mode\n });\n process.exit(0);\n }\n decision = evaluateCommand(bashInput.command, {\n cwd: input.cwd,\n depth: 0,\n repoProtectedBranches: repoSettings.protectedBranches\n });\n auditCommand = bashInput.command;\n} else {\n const projectDir = findWorkspaceRoot(input.cwd) ?? process.env[\"CLAUDE_PROJECT_DIR\"] ?? input.cwd;\n decision = evaluateToolUse(input.tool_name, input.tool_input, {\n cwd: projectDir,\n sessionId: input.session_id\n });\n const filePath = String(input.tool_input[\"file_path\"] ?? input.tool_input[\"path\"] ?? \"\");\n auditCommand = `${input.tool_name} ${filePath}`;\n}\naudit({\n sessionId: input.session_id,\n cwd: input.cwd,\n toolName: input.tool_name,\n command: auditCommand,\n decision: decision.action,\n rule: decision.rule,\n reason: decision.reason,\n permissionMode: input.permission_mode\n});\nif (decision.action === \"deny\") writeDeny(decision.reason);\nelse if (decision.advice) writeAdvice(decision.advice);\n\n//#endregion\nexport { };",
|
|
8267
|
+
hook: "/**\n * bst-hook -- Claude Code PreToolUse hook\n * @bensandee/claude-hooks\n * https://github.com/bensandee/tooling\n *\n * Auto-generated by @bensandee/tooling repo:sync -- do not edit manually.\n */\nimport * as fs from \"node:fs\";\nimport { existsSync, readFileSync, readdirSync, realpathSync, statSync } from \"node:fs\";\nimport * as path from \"node:path\";\nimport { dirname, join, resolve } from \"node:path\";\nimport { fileURLToPath } from \"node:url\";\nimport { execFileSync } from \"node:child_process\";\n\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/util.js\nfunction joinValues(array, separator = \"|\") {\n return array.map((val) => stringifyPrimitive(val)).join(separator);\n}\nfunction jsonStringifyReplacer(_, value) {\n if (typeof value === \"bigint\") return value.toString();\n return value;\n}\nvar Cached = class {\n constructor(getter) {\n this._getter = getter;\n this._value = void 0;\n }\n get value() {\n const getter = this._getter;\n if (getter !== void 0) {\n this._value = getter();\n this._getter = void 0;\n }\n return this._value;\n }\n};\nfunction cached(getter) {\n return new Cached(getter);\n}\nfunction nullish(input) {\n return input === null || input === void 0;\n}\nfunction cleanRegex(source) {\n const start = source.startsWith(\"^\") ? 1 : 0;\n const end = source.endsWith(\"$\") ? source.length - 1 : source.length;\n return source.slice(start, end);\n}\nfunction assignProp(target, prop, value) {\n Object.defineProperty(target, prop, {\n value,\n writable: true,\n enumerable: true,\n configurable: true\n });\n}\nconst captureStackTrace = \"captureStackTrace\" in Error ? Error.captureStackTrace : (..._args) => {};\nfunction isObject(data) {\n return typeof data === \"object\" && data !== null && !Array.isArray(data);\n}\nfunction isPlainObject(o) {\n if (isObject(o) === false) return false;\n const ctor = o.constructor;\n if (ctor === void 0) return true;\n if (typeof ctor !== \"function\") return true;\n const prot = ctor.prototype;\n if (isObject(prot) === false) return false;\n if (Object.prototype.hasOwnProperty.call(prot, \"isPrototypeOf\") === false) return false;\n return true;\n}\nfunction shallowClone(o) {\n if (isPlainObject(o)) return { ...o };\n if (Array.isArray(o)) return [...o];\n if (o instanceof Map) return new Map(o);\n if (o instanceof Set) return new Set(o);\n return o;\n}\nfunction clone(inst, def, params) {\n const cl = new inst._zod.constr(def ?? inst._zod.def);\n if (!def || params?.parent) cl._zod.parent = inst;\n return cl;\n}\nfunction normalizeParams(_params) {\n const params = _params;\n if (!params) return {};\n if (typeof params === \"string\") return { error: () => params };\n if (params?.message !== void 0) {\n if (params?.error !== void 0) throw new Error(\"Cannot specify both `message` and `error` params\");\n params.error = params.message;\n }\n delete params.message;\n if (typeof params.error === \"string\") return {\n ...params,\n error: () => params.error\n };\n return params;\n}\nfunction stringifyPrimitive(value) {\n if (typeof value === \"bigint\") return value.toString() + \"n\";\n if (typeof value === \"string\") return `\"${value}\"`;\n return `${value}`;\n}\nfunction optionalKeys(shape) {\n return Object.keys(shape).filter((k) => {\n return shape[k]._zod.optin !== void 0 && shape[k]._zod.optout === \"optional\";\n });\n}\nfunction aborted(x, startIndex = 0) {\n if (x.aborted === true) return true;\n for (let i = startIndex; i < x.issues.length; i++) if (x.issues[i]?.continue !== true) return true;\n return false;\n}\nfunction explicitlyAborted(x, startIndex = 0) {\n if (x.aborted === true) return true;\n for (let i = startIndex; i < x.issues.length; i++) if (x.issues[i]?.continue === false) return true;\n return false;\n}\nfunction prefixIssues(path, issues) {\n return issues.map((iss) => {\n var _a;\n (_a = iss).path ?? (_a.path = []);\n iss.path.unshift(path);\n return iss;\n });\n}\nfunction unwrapMessage(message) {\n return typeof message === \"string\" ? message : message?.message;\n}\nfunction attachSchema(issues, start, inst) {\n var _a;\n for (let i = start; i < issues.length; i++) (_a = issues[i]).schema ?? (_a.schema = inst);\n}\nfunction finalizeIssue(iss, ctx, config) {\n var _a;\n const traits = iss.inst?._zod?.traits;\n if (traits?.has(\"$ZodType\")) {\n if (traits.has(\"$ZodCheck\")) (_a = iss).schema ?? (_a.schema = iss.inst);\n else iss.schema = iss.inst;\n }\n const schemaError = iss.schema !== iss.inst ? iss.schema?._zod.def?.error : void 0;\n const message = iss.message ? iss.message : unwrapMessage(iss.inst?._zod.def?.error?.(iss)) ?? unwrapMessage(schemaError?.(iss)) ?? unwrapMessage(ctx?.error?.(iss)) ?? unwrapMessage(config.customError?.(iss)) ?? unwrapMessage(config.localeError?.(iss)) ?? \"Invalid input\";\n const full = {};\n for (const k of Object.keys(iss)) {\n if (k === \"inst\" || k === \"schema\" || k === \"continue\" || k === \"input\" || k === \"__proto__\") continue;\n full[k] = iss[k];\n }\n full.path ?? (full.path = []);\n full.message = message;\n if (ctx?.reportInput) full.input = iss.input;\n return full;\n}\nconst highSurrogate = /[\\uD800-\\uDBFF]/;\nfunction codePointLength(str) {\n const units = str.length;\n if (!highSurrogate.test(str)) return units;\n let count = units;\n for (let i = 0; i < units - 1; i++) if ((str.charCodeAt(i) & 64512) === 55296 && (str.charCodeAt(i + 1) & 64512) === 56320) {\n count--;\n i++;\n }\n return count;\n}\nfunction getLengthableOrigin(input) {\n if (Array.isArray(input)) return \"array\";\n if (typeof input === \"string\") return \"string\";\n return \"unknown\";\n}\nfunction parsedType(data) {\n const t = typeof data;\n switch (t) {\n case \"number\": return Number.isNaN(data) ? \"nan\" : \"number\";\n case \"object\": {\n if (data === null) return \"null\";\n if (Array.isArray(data)) return \"array\";\n const obj = data;\n if (obj && Object.getPrototypeOf(obj) !== Object.prototype && \"constructor\" in obj && obj.constructor) return obj.constructor.name;\n }\n }\n return t;\n}\nfunction members(proto, table) {\n for (const key in table) {\n const desc = Object.getOwnPropertyDescriptor(table, key);\n if (desc.get) Object.defineProperty(proto, key, {\n ...desc,\n enumerable: false\n });\n else defineBound(proto, key, desc.value);\n }\n}\nfunction own(inst, key, value, enumerable = true) {\n Object.defineProperty(inst, key, {\n configurable: true,\n writable: true,\n enumerable,\n value\n });\n return value;\n}\nfunction hide(inst, key, value) {\n return own(inst, key, value, false);\n}\nfunction defineBound(proto, key, fn) {\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n return this == null ? fn : own(this, key, fn.bind(this));\n },\n set(value) {\n own(this, key, value);\n }\n });\n}\nfunction claim(inst, sentinel) {\n const proto = Object.getPrototypeOf(inst);\n return sentinel in proto ? void 0 : proto;\n}\nlet installing;\nlet broke = false;\nconst breaker = {\n configurable: true,\n get() {\n broke = true;\n }\n};\nfunction defineLazyInternal(inst, key, compute) {\n const proto = Object.getPrototypeOf(inst._zod);\n if (key in proto && installing !== inst._zod) {\n installing = void 0;\n return;\n }\n installing = inst._zod;\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n Object.defineProperty(this, key, breaker);\n const outer = broke;\n broke = false;\n try {\n const value = compute(this);\n if (broke) delete this[key];\n else Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n value\n });\n broke = broke || outer;\n return value;\n } catch (err) {\n delete this[key];\n broke = broke || outer;\n throw err;\n }\n },\n set(value) {\n Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n value\n });\n }\n });\n}\nfunction installLazyProp(inst, key, make, enumerable) {\n const proto = claim(inst, key);\n if (!proto) return;\n Object.defineProperty(proto, key, {\n configurable: true,\n get() {\n const desc = {\n configurable: true,\n writable: true,\n enumerable,\n value: void 0\n };\n Object.defineProperty(this, key, desc);\n desc.value = make(this);\n Object.defineProperty(this, key, desc);\n return desc.value;\n },\n set(value) {\n Object.defineProperty(this, key, {\n configurable: true,\n writable: true,\n enumerable,\n value\n });\n }\n });\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/core.js\nvar _a;\nconst _zodDesc = {\n value: void 0,\n enumerable: false\n};\nlet _E = \"captureStackTrace\" in Error ? Error : null;\nfunction newError(Definition) {\n const E = _E;\n if (E) {\n const saved = E.stackTraceLimit;\n if (typeof saved === \"number\") {\n try {\n E.stackTraceLimit = 0;\n } catch {\n _E = null;\n return new Definition();\n }\n try {\n return new Definition();\n } finally {\n E.stackTraceLimit = saved;\n }\n }\n }\n return new Definition();\n}\nfunction $constructor(name, initializer, proto, params) {\n const zodProto = {};\n function Internals(def) {\n this.def = def;\n this.constr = _;\n this.traits = /* @__PURE__ */ new Set();\n }\n Internals.prototype = zodProto;\n const protoMembers = proto;\n const initialized = protoMembers && /* @__PURE__ */ new WeakSet();\n function init(inst, def) {\n if (!inst._zod) {\n _zodDesc.value = new Internals(def);\n try {\n Object.defineProperty(inst, \"_zod\", _zodDesc);\n } finally {\n _zodDesc.value = void 0;\n }\n } else if (inst._zod.traits.has(name)) return;\n inst._zod.traits.add(name);\n initializer(inst, def);\n if (initialized) {\n const own = Object.getPrototypeOf(inst);\n const ctorProto = inst._zod.constr.prototype;\n let up = own;\n while (up && up !== ctorProto) up = Object.getPrototypeOf(up);\n const target = up ?? own;\n if (!initialized.has(target)) {\n initialized.add(target);\n members(target, protoMembers);\n }\n }\n const proto = _.prototype;\n for (const k in proto) {\n if (!Object.prototype.hasOwnProperty.call(proto, k)) continue;\n if (!(k in inst)) inst[k] = proto[k].bind(inst);\n }\n }\n const Parent = params?.Parent ?? Object;\n class Definition extends Parent {}\n Object.defineProperty(Definition, \"name\", { value: name });\n function _(def) {\n const inst = params?.Parent ? newError(Definition) : this;\n init(inst, def);\n const deferred = inst._zod.deferred;\n if (deferred) {\n for (const fn of deferred) fn();\n inst._zod.deferred = void 0;\n }\n const pp = globalThis.__zod_globalConfig?.postProcessor;\n if (pp) pp(inst);\n return inst;\n }\n Object.defineProperty(_, \"init\", { value: init });\n Object.defineProperty(_, Symbol.hasInstance, { value: (inst) => {\n if (params?.Parent && inst instanceof params.Parent) return true;\n return inst?._zod?.traits?.has(name);\n } });\n Object.defineProperty(_, \"name\", { value: name });\n return _;\n}\nvar $ZodAsyncError = class extends Error {\n constructor() {\n super(`Encountered Promise during synchronous parse. Use .parseAsync() instead.`);\n }\n};\n(_a = globalThis).__zod_globalConfig ?? (_a.__zod_globalConfig = {});\nconst globalConfig = globalThis.__zod_globalConfig;\nfunction config(newConfig) {\n if (newConfig) Object.assign(globalConfig, newConfig);\n return globalConfig;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/errors.js\nfunction _getMessage() {\n const internals = this._zod;\n internals.message ?? (internals.message = JSON.stringify(internals.def, jsonStringifyReplacer, 2));\n return internals.message;\n}\nfunction _setMessage(value) {\n this._zod.message = value;\n}\nconst _messageDesc = {\n get: _getMessage,\n set: _setMessage,\n enumerable: true,\n configurable: true\n};\nconst _issuesDesc = {\n value: void 0,\n enumerable: false\n};\nconst _installedToString = /* @__PURE__ */ new WeakSet([Object.prototype, Error.prototype]);\nconst initializer = (inst, def) => {\n inst.name = \"$ZodError\";\n _issuesDesc.value = def;\n Object.defineProperty(inst, \"issues\", _issuesDesc);\n _issuesDesc.value = void 0;\n Object.defineProperty(inst, \"message\", _messageDesc);\n const proto = Object.getPrototypeOf(inst);\n if (!_installedToString.has(proto)) {\n _installedToString.add(proto);\n Object.defineProperty(proto, \"toString\", {\n configurable: true,\n enumerable: false,\n get() {\n const value = () => this.message;\n Object.defineProperty(this, \"toString\", {\n value,\n configurable: true,\n writable: true\n });\n return value;\n },\n set(value) {\n Object.defineProperty(this, \"toString\", {\n value,\n configurable: true,\n writable: true\n });\n }\n });\n }\n};\nconst $ZodError = $constructor(\"$ZodError\", initializer);\nconst $ZodRealError = $constructor(\"$ZodError\", initializer, void 0, { Parent: Error });\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/parse.js\nconst _parse = (_Err) => {\n const fn = (schema, value, _ctx, _params) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: false\n } : { async: false };\n const result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) throw new $ZodAsyncError();\n if (result.issues.length) {\n const e = new ((_params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));\n captureStackTrace(e, _params?.callee ?? fn);\n throw e;\n }\n return result.value;\n };\n return fn;\n};\nconst parse = /* @__PURE__*/ _parse($ZodRealError);\nconst _parseAsync = (_Err) => {\n const fn = async (schema, value, _ctx, params) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: true\n } : { async: true };\n let result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) result = await result;\n if (result.issues.length) {\n const e = new ((params?.Err) ?? _Err)(result.issues.map((iss) => finalizeIssue(iss, ctx, config())));\n captureStackTrace(e, params?.callee ?? fn);\n throw e;\n }\n return result.value;\n };\n return fn;\n};\nconst parseAsync = /* @__PURE__*/ _parseAsync($ZodRealError);\nconst _safeParse = (_Err) => (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: false\n } : { async: false };\n const result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) throw new $ZodAsyncError();\n return result.issues.length ? failure(_Err, result.issues, ctx) : {\n success: true,\n data: result.value\n };\n};\nconst safeParse = /* @__PURE__*/ _safeParse($ZodRealError);\nfunction failure(Err, issues, ctx) {\n let error;\n return {\n success: false,\n get error() {\n if (!error) {\n error = new Err(issues.map((iss) => finalizeIssue(iss, ctx, config())));\n issues = void 0;\n ctx = void 0;\n }\n return error;\n },\n set error(e) {\n error = e;\n issues = void 0;\n ctx = void 0;\n }\n };\n}\nconst _safeParseAsync = (_Err) => async (schema, value, _ctx) => {\n const ctx = _ctx ? {\n ..._ctx,\n async: true\n } : { async: true };\n let result = schema._zod.run({\n value,\n issues: []\n }, ctx);\n if (result instanceof Promise) result = await result;\n return result.issues.length ? failure(_Err, result.issues, ctx) : {\n success: true,\n data: result.value\n };\n};\nconst safeParseAsync = /* @__PURE__*/ _safeParseAsync($ZodRealError);\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/regexes.js\nconst anyString = /^[\\s\\S]{0,}$/;\nconst number = /^-?\\d+(?:\\.\\d+)?$/;\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/checks.js\nconst $ZodCheck = /*@__PURE__*/ $constructor(\"$ZodCheck\", (inst, def) => {\n var _a;\n inst._zod ?? (inst._zod = {});\n inst._zod.def = def;\n (_a = inst._zod).onattach ?? (_a.onattach = []);\n});\nconst _whenHasLength = (payload) => {\n const val = payload.value;\n return !nullish(val) && val.length !== void 0;\n};\nconst $ZodCheckMinLength = /*@__PURE__*/ $constructor(\"$ZodCheckMinLength\", (inst, def) => {\n var _a;\n $ZodCheck.init(inst, def);\n (_a = inst._zod.def).when ?? (_a.when = _whenHasLength);\n inst._zod.check = (payload) => {\n const input = payload.value;\n const units = input.length;\n if ((typeof input === \"string\" && units >= def.minimum && units < def.minimum * 2 ? codePointLength(input) : units) >= def.minimum) return;\n const origin = getLengthableOrigin(input);\n payload.issues.push({\n origin,\n code: \"too_small\",\n minimum: def.minimum,\n inclusive: true,\n input,\n inst,\n continue: !def.abort\n });\n };\n});\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/versions.js\nconst version = {\n major: 4,\n minor: 6,\n patch: 5\n};\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/schemas.js\nconst $ZodType = /*@__PURE__*/ $constructor(\"$ZodType\", (inst, def) => {\n var _a;\n inst ?? (inst = {});\n inst._zod.def = def;\n inst._zod.bag = inst._zod.bag || {};\n inst._zod.version = version;\n const defChecks = inst._zod.def.checks;\n const checks = inst._zod.traits.has(\"$ZodCheck\") ? [inst, ...defChecks ?? []] : defChecks?.length ? [...defChecks] : [];\n for (const ch of checks) for (const fn of ch._zod.onattach) fn(inst);\n if (checks.length === 0) {\n (_a = inst._zod).deferred ?? (_a.deferred = []);\n inst._zod.deferred?.push(() => {\n inst._zod.run = inst._zod.parse;\n });\n } else {\n const runChecks = (payload, checks, ctx) => {\n if (payload.memo) return payload;\n let isAborted = aborted(payload);\n let asyncResult;\n for (const ch of checks) {\n if (ch._zod.def.when) {\n if (explicitlyAborted(payload)) continue;\n if (!ch._zod.def.when(payload)) continue;\n } else if (isAborted) continue;\n const currLen = payload.issues.length;\n const _ = ch._zod.check(payload);\n if (_ instanceof Promise && ctx?.async === false) throw new $ZodAsyncError();\n if (asyncResult || _ instanceof Promise) asyncResult = (asyncResult ?? Promise.resolve()).then(async () => {\n await _;\n if (payload.issues.length === currLen) return;\n attachSchema(payload.issues, currLen, inst);\n if (!isAborted) isAborted = aborted(payload, currLen);\n });\n else {\n if (payload.issues.length === currLen) continue;\n attachSchema(payload.issues, currLen, inst);\n if (!isAborted) isAborted = aborted(payload, currLen);\n }\n }\n if (asyncResult) return asyncResult.then(() => {\n return payload;\n });\n return payload;\n };\n const handleCanaryResult = (canary, payload, ctx) => {\n if (aborted(canary)) {\n canary.aborted = true;\n return canary;\n }\n const checkResult = runChecks(payload, checks, ctx);\n if (checkResult instanceof Promise) {\n if (ctx.async === false) throw new $ZodAsyncError();\n return checkResult.then((checkResult) => inst._zod.parse(checkResult, ctx));\n }\n return inst._zod.parse(checkResult, ctx);\n };\n inst._zod.run = (payload, ctx) => {\n if (ctx.skipChecks) return inst._zod.parse(payload, ctx);\n if (ctx.direction === \"backward\") {\n const canary = inst._zod.parse({\n value: payload.value,\n issues: []\n }, {\n ...ctx,\n skipChecks: true\n });\n if (canary instanceof Promise) return canary.then((canary) => {\n return handleCanaryResult(canary, payload, ctx);\n });\n return handleCanaryResult(canary, payload, ctx);\n }\n const result = inst._zod.parse(payload, ctx);\n if (result instanceof Promise) {\n if (ctx.async === false) throw new $ZodAsyncError();\n return result.then((result) => runChecks(result, checks, ctx));\n }\n return runChecks(result, checks, ctx);\n };\n }\n}, {\n get \"~standard\"() {\n return hide(this, \"~standard\", standardProps(this));\n },\n set \"~standard\"(value) {\n own(this, \"~standard\", value);\n }\n});\nconst toStandardResult = (r, ctx) => r.issues.length ? { issues: r.issues.map((iss) => finalizeIssue(iss, ctx, config())) } : { value: r.value };\nasync function validateAsync(inst, value) {\n const ctx = { async: true };\n return toStandardResult(await inst._zod.run({\n value,\n issues: []\n }, ctx), ctx);\n}\nfunction standardProps(inst) {\n return {\n validate: (value) => {\n const ctx = { async: false };\n try {\n const r = inst._zod.run({\n value,\n issues: []\n }, ctx);\n if (!(r instanceof Promise)) return toStandardResult(r, ctx);\n } catch (_) {}\n return validateAsync(inst, value);\n },\n vendor: \"zod\",\n version: 1\n };\n}\nconst $ZodString = /*@__PURE__*/ $constructor(\"$ZodString\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.pattern = def.pattern ?? anyString;\n inst._zod.parse = (payload, _) => {\n if (def.coerce) try {\n payload.value = String(payload.value);\n } catch (_) {}\n if (typeof payload.value === \"string\") return payload;\n payload.issues.push({\n expected: \"string\",\n code: \"invalid_type\",\n input: payload.value,\n inst\n });\n return payload;\n };\n});\nconst $ZodUnknown = /*@__PURE__*/ $constructor(\"$ZodUnknown\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.parse = (payload) => payload;\n});\nfunction handleArrayResult(result, final, index) {\n if (result.issues.length) final.issues.push(...prefixIssues(index, result.issues));\n final.value[index] = result.value;\n}\nconst $ZodArray = /*@__PURE__*/ $constructor(\"$ZodArray\", (inst, def) => {\n $ZodType.init(inst, def);\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n const input = payload.value;\n if (!Array.isArray(input)) {\n payload.issues.push({\n expected: \"array\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n payload.value = memo ? memo.alloc(inst, payload, Array(input.length), ctx) : Array(input.length);\n const proms = [];\n const abortEarly = ctx?.abortEarly;\n for (let i = 0; i < input.length; i++) {\n const item = input[i];\n const result = def.element._zod.run({\n value: item,\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => handleArrayResult(result, payload, i)));\n else {\n handleArrayResult(result, payload, i);\n if (abortEarly && result.issues.length !== 0 && aborted(result)) break;\n }\n }\n if (proms.length) return Promise.all(proms).then(() => payload);\n return payload;\n };\n});\nfunction handlePropertyResult(result, final, key, input, optin, optout) {\n const isPresent = key in input;\n const isOptionalOut = optout === \"optional\";\n if (!isPresent && isOptionalOut && optin === \"optional\") return;\n if (result.issues.length) {\n if (optin !== void 0 && isOptionalOut && !isPresent) return;\n final.issues.push(...prefixIssues(key, result.issues));\n }\n if (!isPresent && optin === void 0) {\n if (!result.issues.length) final.issues.push({\n code: \"invalid_type\",\n expected: \"nonoptional\",\n input: void 0,\n path: [key]\n });\n return;\n }\n if (result.value === void 0) {\n if (isPresent || optin === \"defaulted\" && !isOptionalOut) final.value[key] = void 0;\n } else final.value[key] = result.value;\n}\nconst NO_SYMBOL_KEYS = [];\nfunction normalizeDef(def) {\n const keys = Object.keys(def.shape);\n const ownSymbols = Object.getOwnPropertySymbols(def.shape);\n const symbolKeys = ownSymbols.length ? ownSymbols : NO_SYMBOL_KEYS;\n const allKeys = symbolKeys.length ? [...keys, ...symbolKeys] : keys;\n for (const k of allKeys) if (!def.shape?.[k]?._zod?.traits?.has(\"$ZodType\")) throw new Error(`Invalid element at key \"${String(k)}\": expected a Zod schema`);\n const okeys = optionalKeys(def.shape);\n return {\n ...def,\n allKeys,\n symbolKeys,\n keySet: new Set(keys),\n numKeys: keys.length,\n optionalKeys: new Set(okeys)\n };\n}\nfunction handleCatchall(proms, input, payload, ctx, def, inst, abortEarly) {\n const unrecognized = [];\n const keySet = def.keySet;\n const _catchall = def.catchall._zod;\n const t = _catchall.def.type;\n const optin = _catchall.optin;\n const optout = _catchall.optout;\n let seen = 0;\n for (const key in input) {\n if (abortEarly && payload.issues.length !== seen) {\n if (aborted(payload, seen)) break;\n seen = payload.issues.length;\n }\n if (keySet.has(key)) continue;\n if (key === \"__proto__\") {\n if (t === \"never\") unrecognized.push(key);\n continue;\n }\n if (t === \"never\") {\n unrecognized.push(key);\n continue;\n }\n const r = _catchall.run({\n value: input[key],\n issues: []\n }, ctx);\n if (r instanceof Promise) proms.push(r.then((r) => handlePropertyResult(r, payload, key, input, optin, optout)));\n else handlePropertyResult(r, payload, key, input, optin, optout);\n }\n if (unrecognized.length) payload.issues.push({\n code: \"unrecognized_keys\",\n keys: unrecognized,\n input,\n inst,\n continue: true\n });\n if (!proms.length) return payload;\n return Promise.all(proms).then(() => {\n return payload;\n });\n}\nconst $ZodObject = /*@__PURE__*/ $constructor(\"$ZodObject\", (inst, def) => {\n $ZodType.init(inst, def);\n const desc = Object.getOwnPropertyDescriptor(def, \"shape\");\n const sh = desc?.get ? desc.get.raw : def.shape ?? {};\n if (sh) {\n const get = () => {\n const newSh = { ...sh };\n Object.defineProperty(def, \"shape\", { value: newSh });\n get.raw = newSh;\n return newSh;\n };\n get.raw = sh;\n Object.defineProperty(def, \"shape\", { get });\n }\n const _normalized = cached(() => normalizeDef(def));\n defineLazyInternal(inst, \"propValues\", (zod) => {\n const shape = zod.def.shape;\n const propValues = {};\n for (const key in shape) {\n const field = shape[key]._zod;\n if (field.values) {\n if (!Object.prototype.hasOwnProperty.call(propValues, key)) assignProp(propValues, key, /* @__PURE__ */ new Set());\n for (const v of field.values) propValues[key].add(v);\n if (field.optin !== void 0) propValues[key].add(void 0);\n }\n }\n return propValues;\n });\n const isObject$2 = isObject;\n const catchall = def.catchall;\n let value;\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n value ?? (value = _normalized.value);\n const input = payload.value;\n if (!isObject$2(input)) {\n payload.issues.push({\n expected: \"object\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n const proms = [];\n const shape = value.shape;\n const abortEarly = ctx?.abortEarly;\n let seen = payload.issues.length;\n for (const key of value.allKeys) {\n if (abortEarly && payload.issues.length !== seen) {\n if (aborted(payload, seen)) break;\n seen = payload.issues.length;\n }\n if (key === \"__proto__\") continue;\n const el = shape[key];\n const optin = el._zod.optin;\n const optout = el._zod.optout;\n const r = el._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (r instanceof Promise) proms.push(r.then((r) => handlePropertyResult(r, payload, key, input, optin, optout)));\n else handlePropertyResult(r, payload, key, input, optin, optout);\n }\n if (!catchall) return proms.length ? Promise.all(proms).then(() => payload) : payload;\n return handleCatchall(proms, input, payload, ctx, _normalized.value, inst, abortEarly === true);\n };\n});\nconst $ZodRecord = /*@__PURE__*/ $constructor(\"$ZodRecord\", (inst, def) => {\n $ZodType.init(inst, def);\n const memo = globalConfig.memoizer;\n memo?.attach(inst);\n inst._zod.parse = (payload, ctx) => {\n const input = payload.value;\n if (!isPlainObject(input)) {\n payload.issues.push({\n expected: \"record\",\n code: \"invalid_type\",\n input,\n inst\n });\n return payload;\n }\n const proms = [];\n const values = def.keyType._zod.values;\n if (values && !def.partial) {\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n const recordKeys = /* @__PURE__ */ new Set();\n for (const key of values) if (typeof key === \"string\" || typeof key === \"number\" || typeof key === \"symbol\") {\n recordKeys.add(typeof key === \"number\" ? key.toString() : key);\n if (key === \"__proto__\") continue;\n const keyResult = def.keyType._zod.run({\n value: key,\n issues: []\n }, ctx);\n if (keyResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (keyResult.issues.length) {\n payload.issues.push({\n code: \"invalid_key\",\n origin: \"record\",\n issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),\n input: key,\n path: [key],\n inst\n });\n continue;\n }\n const outKey = keyResult.value;\n if (outKey === \"__proto__\") continue;\n const result = def.valueType._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }));\n else {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }\n }\n let unrecognized;\n for (const key in input) if (!recordKeys.has(key)) {\n if (def.mode === \"loose\") {\n if (key === \"__proto__\") continue;\n payload.value[key] = input[key];\n } else {\n unrecognized = unrecognized ?? [];\n unrecognized.push(key);\n }\n }\n if (unrecognized && unrecognized.length > 0) payload.issues.push({\n code: \"unrecognized_keys\",\n input,\n inst,\n keys: unrecognized,\n continue: true\n });\n } else {\n payload.value = memo ? memo.alloc(inst, payload, {}, ctx) : {};\n let unrecognized;\n for (const key of Reflect.ownKeys(input)) {\n if (key === \"__proto__\") continue;\n if (!Object.prototype.propertyIsEnumerable.call(input, key)) continue;\n let keyResult = def.keyType._zod.run({\n value: key,\n issues: []\n }, ctx);\n if (keyResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (typeof key === \"string\" && number.test(key) && keyResult.issues.length) {\n const retryResult = def.keyType._zod.run({\n value: Number(key),\n issues: []\n }, ctx);\n if (retryResult instanceof Promise) throw new Error(\"Async schemas not supported in object keys currently\");\n if (retryResult.issues.length === 0) keyResult = retryResult;\n }\n if (keyResult.issues.length) {\n if (def.mode === \"loose\") payload.value[key] = input[key];\n else if (values) {\n unrecognized = unrecognized ?? [];\n unrecognized.push(key);\n } else payload.issues.push({\n code: \"invalid_key\",\n origin: \"record\",\n issues: keyResult.issues.map((iss) => finalizeIssue(iss, ctx, config())),\n input: key,\n path: [key],\n inst\n });\n continue;\n }\n const outKey = keyResult.value;\n if (outKey === \"__proto__\") continue;\n const result = def.valueType._zod.run({\n value: input[key],\n issues: []\n }, ctx);\n if (result instanceof Promise) proms.push(result.then((result) => {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }));\n else {\n if (result.issues.length) payload.issues.push(...prefixIssues(key, result.issues));\n payload.value[outKey] = result.value;\n }\n }\n if (unrecognized && unrecognized.length > 0) payload.issues.push({\n code: \"unrecognized_keys\",\n input,\n inst,\n keys: unrecognized,\n continue: true\n });\n }\n if (proms.length) return Promise.all(proms).then(() => payload);\n return payload;\n };\n});\nfunction handleOptionalResult(payload, result) {\n payload.value = result.issues.length ? void 0 : result.value;\n return payload;\n}\nconst $ZodOptional = /*@__PURE__*/ $constructor(\"$ZodOptional\", (inst, def) => {\n $ZodType.init(inst, def);\n defineLazyInternal(inst, \"optin\", (zod) => zod.def.innerType._zod.optin === \"defaulted\" ? \"defaulted\" : \"optional\");\n inst._zod.optout = \"optional\";\n defineLazyInternal(inst, \"values\", (zod) => {\n const values = zod.def.innerType._zod.values;\n return values ? /* @__PURE__ */ new Set([...values, void 0]) : void 0;\n });\n defineLazyInternal(inst, \"pattern\", (zod) => {\n const pattern = zod.def.innerType._zod.pattern;\n return pattern ? new RegExp(`^(${cleanRegex(pattern.source)})?$`) : void 0;\n });\n inst._zod.parse = (payload, ctx) => {\n if (payload.value === void 0) {\n if (def.innerType._zod.optin !== \"defaulted\") return payload;\n const result = def.innerType._zod.run({\n value: payload.value,\n issues: []\n }, ctx);\n if (result instanceof Promise) return result.then((result) => handleOptionalResult(payload, result));\n return handleOptionalResult(payload, result);\n }\n return def.innerType._zod.run(payload, ctx);\n };\n});\nconst $ZodDefault = /*@__PURE__*/ $constructor(\"$ZodDefault\", (inst, def) => {\n $ZodType.init(inst, def);\n inst._zod.optin = \"defaulted\";\n defineLazyInternal(inst, \"values\", (zod) => zod.def.innerType._zod.values);\n inst._zod.parse = (payload, ctx) => {\n if (ctx.direction === \"backward\") return def.innerType._zod.run(payload, ctx);\n if (payload.value === void 0) {\n payload.value = def.defaultValue;\n return payload;\n }\n const result = def.innerType._zod.run(payload, ctx);\n if (result instanceof Promise) return result.then((result) => handleDefaultResult(result, def));\n return handleDefaultResult(result, def);\n };\n});\nfunction handleDefaultResult(payload, def) {\n if (payload.value === void 0) payload.value = def.defaultValue;\n return payload;\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/locales/en.js\nconst error = () => {\n const Sizable = {\n string: {\n unit: \"characters\",\n verb: \"to have\"\n },\n file: {\n unit: \"bytes\",\n verb: \"to have\"\n },\n array: {\n unit: \"items\",\n verb: \"to have\"\n },\n set: {\n unit: \"items\",\n verb: \"to have\"\n },\n map: {\n unit: \"entries\",\n verb: \"to have\"\n }\n };\n function getSizing(origin) {\n return Sizable[origin] ?? null;\n }\n const FormatDictionary = {\n regex: \"input\",\n email: \"email address\",\n url: \"URL\",\n emoji: \"emoji\",\n uuid: \"UUID\",\n uuidv4: \"UUIDv4\",\n uuidv6: \"UUIDv6\",\n nanoid: \"nanoid\",\n guid: \"GUID\",\n cuid: \"cuid\",\n cuid2: \"cuid2\",\n ulid: \"ULID\",\n xid: \"XID\",\n ksuid: \"KSUID\",\n datetime: \"ISO datetime\",\n date: \"ISO date\",\n time: \"ISO time\",\n duration: \"ISO duration\",\n ipv4: \"IPv4 address\",\n ipv6: \"IPv6 address\",\n mac: \"MAC address\",\n cidrv4: \"IPv4 range\",\n cidrv6: \"IPv6 range\",\n base64: \"base64-encoded string\",\n base64url: \"base64url-encoded string\",\n json_string: \"JSON string\",\n e164: \"E.164 number\",\n currency_code: \"currency code\",\n credit_card: \"credit card number\",\n iban: \"IBAN\",\n jwt: \"JWT\",\n template_literal: \"input\"\n };\n const TypeDictionary = { nan: \"NaN\" };\n function getTypeName(type, input) {\n if (type === \"number\" && typeof input === \"number\" && !Number.isFinite(input)) return String(input);\n return TypeDictionary[type] ?? type;\n }\n return (issue) => {\n switch (issue.code) {\n case \"invalid_type\": return `Invalid input: expected ${getTypeName(issue.expected)}, received ${getTypeName(parsedType(issue.input), issue.input)}`;\n case \"invalid_value\":\n if (issue.values.length === 1) return `Invalid input: expected ${stringifyPrimitive(issue.values[0])}`;\n return `Invalid option: expected one of ${joinValues(issue.values, \"|\")}`;\n case \"too_big\": {\n const adj = issue.exact ? \"exactly \" : issue.inclusive ? \"<=\" : \"<\";\n const sizing = getSizing(issue.origin);\n if (sizing) return `Too big: expected ${issue.origin ?? \"value\"} to have ${adj}${issue.maximum.toString()} ${sizing.unit ?? \"elements\"}`;\n return `Too big: expected ${issue.origin ?? \"value\"} to be ${adj}${issue.maximum.toString()}`;\n }\n case \"too_small\": {\n const adj = issue.exact ? \"exactly \" : issue.inclusive ? \">=\" : \">\";\n const sizing = getSizing(issue.origin);\n if (sizing) return `Too small: expected ${issue.origin} to have ${adj}${issue.minimum.toString()} ${sizing.unit}`;\n return `Too small: expected ${issue.origin} to be ${adj}${issue.minimum.toString()}`;\n }\n case \"invalid_format\": {\n const _issue = issue;\n if (_issue.format === \"starts_with\") return `Invalid string: must start with \"${_issue.prefix}\"`;\n if (_issue.format === \"ends_with\") return `Invalid string: must end with \"${_issue.suffix}\"`;\n if (_issue.format === \"includes\") return `Invalid string: must include \"${_issue.includes}\"`;\n if (_issue.format === \"regex\") return `Invalid string: must match pattern ${_issue.pattern}`;\n return `Invalid ${FormatDictionary[_issue.format] ?? issue.format}`;\n }\n case \"not_multiple_of\": return `Invalid number: must be a multiple of ${issue.divisor}`;\n case \"unrecognized_keys\": return `Unrecognized key${issue.keys.length > 1 ? \"s\" : \"\"}: ${joinValues(issue.keys, \", \")}`;\n case \"invalid_key\": return `Invalid key in ${issue.origin}`;\n case \"invalid_union\":\n if (issue.options && Array.isArray(issue.options) && issue.options.length > 0) return `Invalid discriminator value. Expected ${issue.options.map((o) => `'${o}'`).join(\" | \")}`;\n if (issue.inclusive === false) return \"Invalid input: more than one option matched\";\n return \"Invalid input\";\n case \"invalid_element\": return `Invalid value in ${issue.origin}`;\n default: return `Invalid input`;\n }\n };\n};\nfunction en_default() {\n return { localeError: error() };\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/core/api.js\nfunction snapshotChecks(def) {\n if (def.checks) def.checks = [...def.checks];\n return def;\n}\n// @__NO_SIDE_EFFECTS__\nfunction _string(Class, params) {\n return new Class(snapshotChecks({\n type: \"string\",\n ...normalizeParams(params)\n }));\n}\n// @__NO_SIDE_EFFECTS__\nfunction _unknown(Class) {\n return new Class({ type: \"unknown\" });\n}\n// @__NO_SIDE_EFFECTS__\nfunction _minLength(minimum, params) {\n return new $ZodCheckMinLength({\n check: \"min_length\",\n ...normalizeParams(params),\n minimum\n });\n}\n\n//#endregion\n//#region ../../node_modules/.pnpm/zod@4.6.5/node_modules/zod/v4/mini/schemas.js\nconst ZodMiniType = /*@__PURE__*/ $constructor(\"ZodMiniType\", (inst, def) => {\n if (!inst._zod) throw new Error(\"Uninitialized schema in ZodMiniType.\");\n $ZodType.init(inst, def);\n inst.def = def;\n inst.type = def.type;\n}, {\n get with() {\n return this.check;\n },\n set with(value) {\n own(this, \"with\", value);\n },\n parse(data, params) {\n return parse(this, data, params, { callee: this.parse });\n },\n parseAsync(data, params) {\n return parseAsync(this, data, params, { callee: this.parseAsync });\n },\n safeParse(data, params) {\n return safeParse(this, data, params);\n },\n safeParseAsync(data, params) {\n return safeParseAsync(this, data, params);\n },\n check(...checks) {\n const def = this.def;\n return this.clone({\n ...def,\n checks: [...def.checks ?? [], ...checks.map((ch) => typeof ch === \"function\" ? { _zod: {\n check: ch,\n def: { check: \"custom\" },\n onattach: []\n } } : ch)]\n }, { parent: true });\n },\n clone(_def, params) {\n return clone(this, _def, params);\n },\n brand() {\n return this;\n },\n register(reg, meta) {\n reg.add(this, meta);\n return this;\n },\n apply(fn, ...args) {\n return args.length === 0 ? fn(this) : fn(this, ...args);\n }\n});\nconst ZodMiniString = /*@__PURE__*/ $constructor(\"ZodMiniString\", (inst, def) => {\n $ZodString.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction string(params) {\n return _string(ZodMiniString, params);\n}\nconst ZodMiniUnknown = /*@__PURE__*/ $constructor(\"ZodMiniUnknown\", (inst, def) => {\n $ZodUnknown.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction unknown() {\n return _unknown(ZodMiniUnknown);\n}\nconst ZodMiniArray = /*@__PURE__*/ $constructor(\"ZodMiniArray\", (inst, def) => {\n $ZodArray.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction array(element, params) {\n return new ZodMiniArray({\n type: \"array\",\n element,\n ...normalizeParams(params)\n });\n}\nconst ZodMiniObject = /*@__PURE__*/ $constructor(\"ZodMiniObject\", (inst, def) => {\n $ZodObject.init(inst, def);\n ZodMiniType.init(inst, def);\n installLazyProp(inst, \"shape\", (self) => self._zod.def.shape, false);\n});\n// @__NO_SIDE_EFFECTS__\nfunction object(shape, params) {\n const def = {\n type: \"object\",\n shape: shape ?? {},\n ...normalizeParams(params)\n };\n return new ZodMiniObject(def);\n}\nconst ZodMiniRecord = /*@__PURE__*/ $constructor(\"ZodMiniRecord\", (inst, def) => {\n $ZodRecord.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction record(keyType, valueType, params) {\n if (!valueType || !valueType._zod) return new ZodMiniRecord({\n type: \"record\",\n keyType: /* @__PURE__ */ string(),\n valueType: keyType,\n ...normalizeParams(valueType)\n });\n return new ZodMiniRecord({\n type: \"record\",\n keyType,\n valueType,\n ...normalizeParams(params)\n });\n}\nconst ZodMiniOptional = /*@__PURE__*/ $constructor(\"ZodMiniOptional\", (inst, def) => {\n $ZodOptional.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction optional(innerType) {\n return new ZodMiniOptional({\n type: \"optional\",\n innerType\n });\n}\nconst ZodMiniDefault = /*@__PURE__*/ $constructor(\"ZodMiniDefault\", (inst, def) => {\n $ZodDefault.init(inst, def);\n ZodMiniType.init(inst, def);\n});\n// @__NO_SIDE_EFFECTS__\nfunction _default(innerType, defaultValue) {\n return new ZodMiniDefault({\n type: \"default\",\n innerType,\n get defaultValue() {\n return typeof defaultValue === \"function\" ? defaultValue() : shallowClone(defaultValue);\n }\n });\n}\n\n//#endregion\n//#region src/lib/hook-io.ts\nconfig(en_default());\nconst HookInputSchema = object({\n session_id: string(),\n transcript_path: string(),\n cwd: string(),\n permission_mode: string(),\n hook_event_name: string(),\n tool_name: string(),\n tool_input: record(string(), unknown())\n});\nasync function readHookInput() {\n const chunks = [];\n for await (const chunk of process.stdin) chunks.push(typeof chunk === \"string\" ? chunk : String(chunk));\n let parsed;\n try {\n parsed = JSON.parse(chunks.join(\"\"));\n } catch (_error) {\n return {\n ok: false,\n raw: chunks.join(\"\").slice(0, 200),\n error: \"invalid JSON\"\n };\n }\n const result = HookInputSchema.safeParse(parsed);\n if (!result.success) return {\n ok: false,\n raw: parsed,\n error: result.error.message\n };\n return {\n ok: true,\n data: result.data\n };\n}\nconst BashInputSchema = object({\n command: string(),\n description: optional(string())\n});\nconst FilePathInputSchema = object({ file_path: string() });\nconst SearchInputSchema = object({\n pattern: string(),\n path: optional(string())\n});\nfunction parseBashInput(toolInput) {\n const result = BashInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction parseFilePathInput(toolInput) {\n const result = FilePathInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction parseSearchInput(toolInput) {\n const result = SearchInputSchema.safeParse(toolInput);\n return result.success ? result.data : null;\n}\nfunction writeDeny(reason) {\n const decision = { hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n permissionDecision: \"deny\",\n ...reason ? { permissionDecisionReason: reason } : {}\n } };\n process.stdout.write(JSON.stringify(decision));\n}\nfunction writeAdvice(advice) {\n const decision = { hookSpecificOutput: {\n hookEventName: \"PreToolUse\",\n additionalContext: advice\n } };\n process.stdout.write(JSON.stringify(decision));\n}\n\n//#endregion\n//#region src/lib/audit.ts\nconst MAX_LOG_SIZE = 1048576;\nfunction getLogPath() {\n const hookDir = path.dirname(fileURLToPath(import.meta.url));\n return path.join(hookDir, \"bst-hook.audit.local.jsonl\");\n}\nfunction rotateIfNeeded(logPath) {\n try {\n if (fs.statSync(logPath).size > MAX_LOG_SIZE) {\n const rotatedPath = `${logPath}.1`;\n fs.renameSync(logPath, rotatedPath);\n }\n } catch (_error) {}\n}\nlet rotationChecked = false;\nfunction audit(entry) {\n try {\n const logPath = getLogPath();\n if (!rotationChecked) {\n rotateIfNeeded(logPath);\n rotationChecked = true;\n }\n const record = {\n timestamp: (/* @__PURE__ */ new Date()).toISOString(),\n ...entry\n };\n fs.appendFileSync(logPath, JSON.stringify(record) + \"\\n\");\n } catch (err) {\n process.stderr.write(`[bst-hook] audit write failed: ${err instanceof Error ? err.message : String(err)}\\n`);\n }\n}\n\n//#endregion\n//#region src/lib/shell-tokenizer.ts\nfunction scanDoubleQuoted(input, start) {\n let content = \"\";\n let i = start;\n while (i < input.length && input[i] !== \"\\\"\") {\n if (input[i] === \"\\\\\" && i + 1 < input.length) {\n const next = input[i + 1];\n if (next === \"\\\"\" || next === \"\\\\\" || next === \"$\" || next === \"`\") {\n content += next;\n i += 2;\n continue;\n }\n }\n content += input[i];\n i++;\n }\n if (i >= input.length) return null;\n return {\n content,\n next: i + 1\n };\n}\nfunction tokenize(input) {\n const tokens = [];\n let current = \"\";\n let i = 0;\n let inToken = false;\n while (i < input.length) {\n const ch = input[i];\n if (ch === \"'\") {\n inToken = true;\n i++;\n while (i < input.length && input[i] !== \"'\") {\n current += input[i];\n i++;\n }\n if (i >= input.length) return {\n ok: false,\n error: \"unterminated single quote\"\n };\n i++;\n } else if (ch === \"\\\"\") {\n inToken = true;\n const scanned = scanDoubleQuoted(input, i + 1);\n if (!scanned) return {\n ok: false,\n error: \"unterminated double quote\"\n };\n current += scanned.content;\n i = scanned.next;\n } else if (ch === \"\\\\\" && i + 1 < input.length) {\n inToken = true;\n current += input[i + 1];\n i += 2;\n } else if (ch === \" \" || ch === \" \") {\n if (inToken) {\n tokens.push(current);\n current = \"\";\n inToken = false;\n }\n i++;\n } else {\n inToken = true;\n current += ch;\n i++;\n }\n }\n if (inToken) tokens.push(current);\n return {\n ok: true,\n tokens\n };\n}\nconst SAFE_UNQUOTED_RE = /^[A-Za-z0-9_\\-./=:@%+,]+$/;\nfunction quoteToken(token) {\n if (token.length > 0 && SAFE_UNQUOTED_RE.test(token)) return token;\n return \"'\" + token.replace(/'/g, \"'\\\\''\") + \"'\";\n}\nfunction joinTokens(tokens) {\n return tokens.map(quoteToken).join(\" \");\n}\n\n//#endregion\n//#region src/lib/shell-splitter.ts\nfunction splitCommand(input) {\n if (!input || !input.trim()) return [];\n const segments = [];\n let current = \"\";\n let i = 0;\n let inSingleQuote = false;\n let inDoubleQuote = false;\n while (i < input.length) {\n const ch = input[i];\n if (ch === \"'\" && !inDoubleQuote) {\n inSingleQuote = !inSingleQuote;\n current += ch;\n i++;\n continue;\n }\n if (ch === \"\\\"\" && !inSingleQuote) {\n inDoubleQuote = !inDoubleQuote;\n current += ch;\n i++;\n continue;\n }\n if (ch === \"\\\\\" && !inSingleQuote && i + 1 < input.length) {\n current += ch + input[i + 1];\n i += 2;\n continue;\n }\n if (!inSingleQuote && !inDoubleQuote) {\n if (ch === \"&\" && i + 1 < input.length && input[i + 1] === \"&\") {\n pushSegment(segments, current, \"&&\");\n current = \"\";\n i += 2;\n continue;\n }\n if (ch === \"&\" && !(i + 1 < input.length && input[i + 1] === \">\") && !(i > 0 && (input[i - 1] === \">\" || input[i - 1] === \"<\"))) {\n pushSegment(segments, current, \"&\");\n current = \"\";\n i++;\n continue;\n }\n if (ch === \"|\" && i + 1 < input.length && input[i + 1] === \"|\") {\n pushSegment(segments, current, \"||\");\n current = \"\";\n i += 2;\n continue;\n }\n if (ch === \"|\") {\n pushSegment(segments, current, \"|\");\n current = \"\";\n i++;\n continue;\n }\n if (ch === \";\") {\n pushSegment(segments, current, \";\");\n current = \"\";\n i++;\n continue;\n }\n }\n current += ch;\n i++;\n }\n const trimmed = current.trim();\n if (trimmed) segments.push({\n command: trimmed,\n operator: null\n });\n return segments;\n}\nfunction pushSegment(segments, text, operator) {\n const trimmed = text.trim();\n if (trimmed) segments.push({\n command: trimmed,\n operator\n });\n}\n\n//#endregion\n//#region src/lib/injection-guard.ts\nfunction hasBraceExpansion(token) {\n let depth = 0;\n for (let i = 0; i < token.length; i++) {\n const ch = token[i];\n if (ch === \"{\") depth++;\n else if (ch === \"}\") {\n if (depth > 0) depth--;\n } else if (depth >= 1 && (ch === \",\" || ch === \".\" && token[i + 1] === \".\")) return true;\n }\n return false;\n}\nfunction checkInjection(tokens, rawSegment) {\n if (/[\\n\\r]/.test(rawSegment)) return {\n safe: false,\n reason: \"unquoted newline in command\"\n };\n for (const token of tokens) {\n if (token === \"`\") return {\n safe: false,\n reason: \"backtick command substitution\"\n };\n if (token.includes(\"`\")) return {\n safe: false,\n reason: \"backtick command substitution\"\n };\n if (token.includes(\"$\")) return {\n safe: false,\n reason: \"unresolved dollar-expansion\"\n };\n if (hasBraceExpansion(token)) return {\n safe: false,\n reason: \"brace expansion\"\n };\n if (token.includes(\"<(\")) return {\n safe: false,\n reason: \"process substitution\"\n };\n if (token.includes(\">(\")) return {\n safe: false,\n reason: \"process substitution\"\n };\n }\n return { safe: true };\n}\n\n//#endregion\n//#region src/lib/env-file.ts\nconst ENV_SAFE_SUFFIXES = [\n \".sample\",\n \".example\",\n \".template\"\n];\nconst ENV_TOOL_OWNED_SUFFIXES = [\".check.env\"];\nconst ENV_FILE_PATTERN = /(^|[/\\\\])(\\.env(\\..*)?|.*\\.env(\\..*)?|\\.env)$/;\nfunction isEnvSafeSuffix(filename) {\n return [...ENV_SAFE_SUFFIXES, ...ENV_TOOL_OWNED_SUFFIXES].some((suffix) => filename.endsWith(suffix));\n}\nfunction isEnvFile(filePath) {\n if (isEnvSafeSuffix(path.basename(filePath))) return false;\n return ENV_FILE_PATTERN.test(filePath);\n}\n\n//#endregion\n//#region src/lib/git-state.ts\nconst GIT_TIMEOUT_MS = 5e3;\nfunction getCurrentBranch(cwd) {\n try {\n const out = execFileSync(\"git\", [\n \"rev-parse\",\n \"--abbrev-ref\",\n \"HEAD\"\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!out || out === \"HEAD\") return null;\n return out;\n } catch {\n return null;\n }\n}\nfunction getRepoTopLevel(cwd) {\n try {\n const out = execFileSync(\"git\", [\"rev-parse\", \"--show-toplevel\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n return out === \"\" ? null : out;\n } catch {\n return null;\n }\n}\nfunction getRemoteDefaultBranch(cwd) {\n try {\n const out = execFileSync(\"git\", [\n \"symbolic-ref\",\n \"--short\",\n \"refs/remotes/origin/HEAD\"\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!out) return null;\n return out.startsWith(\"origin/\") ? out.slice(7) : out;\n } catch {\n return null;\n }\n}\nconst DefaultBranchSchema = object({ defaultBranch: optional(string().check(_minLength(1))) });\nfunction getConfiguredDefaultBranch(topLevel) {\n let parsed;\n try {\n parsed = JSON.parse(readFileSync(join(topLevel, \".tooling.json\"), \"utf-8\"));\n } catch {\n return null;\n }\n const result = DefaultBranchSchema.safeParse(parsed);\n return result.success ? result.data.defaultBranch ?? null : null;\n}\nconst ALWAYS_PROTECTED = [\"main\", \"master\"];\nfunction getProtectedBranches(cwd, extra) {\n const set = new Set(ALWAYS_PROTECTED);\n const remote = getRemoteDefaultBranch(cwd);\n if (remote) set.add(remote);\n for (const b of extra) set.add(b);\n return set;\n}\nfunction getUpstream(cwd, branch) {\n try {\n return execFileSync(\"git\", [\n \"rev-parse\",\n \"--abbrev-ref\",\n `${branch}@{upstream}`\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim() || null;\n } catch {\n return null;\n }\n}\nfunction resolveCommit(cwd, rev) {\n try {\n return execFileSync(\"git\", [\n \"rev-parse\",\n \"--verify\",\n \"--quiet\",\n `${rev}^{commit}`\n ], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim() || null;\n } catch {\n return null;\n }\n}\nfunction branchCarriesOtherFiles(cwd, allowed) {\n const toplevel = getRepoTopLevel(cwd);\n if (toplevel === null) return null;\n try {\n const defaultBranch = getConfiguredDefaultBranch(toplevel) ?? getRemoteDefaultBranch(toplevel) ?? \"main\";\n const mergeBase = execFileSync(\"git\", [\n \"merge-base\",\n \"HEAD\",\n `origin/${defaultBranch}`\n ], {\n cwd: toplevel,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!mergeBase) return null;\n const names = (args) => execFileSync(\"git\", args, {\n cwd: toplevel,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().split(\"\\n\").filter((line) => line.length > 0);\n return [...names([\n \"diff\",\n \"--name-only\",\n mergeBase\n ]), ...names([\n \"ls-files\",\n \"--others\",\n \"--exclude-standard\"\n ])].some((name) => !allowed.includes(name));\n } catch {\n return null;\n }\n}\nfunction isPrimaryWorktree(cwd) {\n try {\n const gitDir = execFileSync(\"git\", [\"rev-parse\", \"--absolute-git-dir\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n const commonRaw = execFileSync(\"git\", [\"rev-parse\", \"--git-common-dir\"], {\n cwd,\n stdio: [\n \"ignore\",\n \"pipe\",\n \"ignore\"\n ],\n timeout: GIT_TIMEOUT_MS\n }).toString().trim();\n if (!gitDir || !commonRaw) return false;\n const commonDir = resolve(cwd, commonRaw);\n return realpathSync(gitDir) === realpathSync(commonDir);\n } catch {\n return false;\n }\n}\n\n//#endregion\n//#region src/lib/git-short-options.ts\nconst VALUE_TAKING_LETTERS = {\n switch: /* @__PURE__ */ new Set([\"c\", \"C\"]),\n checkout: /* @__PURE__ */ new Set([\"b\", \"B\"]),\n branch: /* @__PURE__ */ new Set([\"u\"]),\n fetch: /* @__PURE__ */ new Set([\"o\", \"j\"])\n};\nfunction splitShortOptionCluster(token, sub) {\n if (!token.startsWith(\"-\") || token.startsWith(\"--\") || token.length <= 1) return;\n const valueLetters = VALUE_TAKING_LETTERS[sub];\n const letters = [];\n const chars = token.slice(1);\n for (let i = 0; i < chars.length; i++) {\n const ch = chars[i];\n letters.push(ch);\n if (valueLetters.has(ch)) return {\n letters,\n attachedValue: chars.slice(i + 1)\n };\n }\n return { letters };\n}\n\n//#endregion\n//#region src/lib/path-scope.ts\nfunction pathFlavorFor(base) {\n return /^[a-zA-Z]:[\\\\/]/.test(base) ? path.win32 : path.posix;\n}\nfunction resolveIn(base, target) {\n return pathFlavorFor(base).resolve(base, target);\n}\nfunction isWithin(dir, target) {\n const pp = pathFlavorFor(dir);\n const rel = pp.relative(dir, target);\n if (rel === \"\") return true;\n if (rel === \"..\" || rel.startsWith(\"..\" + pp.sep)) return false;\n return !pp.isAbsolute(rel);\n}\nfunction samePath(a, b) {\n return pathFlavorFor(a).relative(a, b) === \"\";\n}\nfunction targetsGitDir(filePath, cwd) {\n const pp = pathFlavorFor(cwd);\n const resolved = resolveIn(cwd, filePath);\n if (!isWithin(cwd, resolved)) return false;\n const rel = pp.relative(cwd, resolved);\n if (rel === \"\") return false;\n return rel.split(pp.sep).includes(\".git\");\n}\nfunction targetsNodeModules(filePath, cwd) {\n return resolveIn(cwd, filePath).split(/[/\\\\]/).includes(\"node_modules\");\n}\n\n//#endregion\n//#region src/rules.ts\nconst GIT_FLAGS_WITH_ARG = /* @__PURE__ */ new Set([\n \"-C\",\n \"-c\",\n \"--git-dir\",\n \"--work-tree\"\n]);\nfunction getGitSubcommand(tokens) {\n const args = tokens.slice(1);\n for (let i = 0; i < args.length; i++) {\n const t = args[i];\n if (GIT_FLAGS_WITH_ARG.has(t)) {\n i++;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n return t;\n }\n}\nconst WORKTREE_ADVICE = \"You're creating a feature branch in the primary worktree. An isolated worktree keeps this work independent of other windows, and with no commits on this branch yet, converting is cheap -- `git worktree add ../<dir> -b <branch>` (a sibling outside the repo, with its own dependency install). Claude Code keeps this session inside its own working tree, so the work continues in a new session opened in the sibling worktree. If you cannot open a session there, stay in the primary checkout on this branch and check `git branch --show-current` before each commit.\";\nfunction isGitBranchCreation(tokens) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"checkout\" && sub !== \"switch\") return false;\n const after = tokens.slice(tokens.indexOf(sub) + 1);\n const creationLetters = sub === \"checkout\" ? [\"b\", \"B\"] : [\"c\", \"C\"];\n return after.some((t) => {\n const cluster = splitShortOptionCluster(t, sub);\n return cluster !== void 0 && cluster.letters.some((l) => creationLetters.includes(l));\n });\n}\nfunction worktreeAdvice(tokens, ctx) {\n return isGitBranchCreation(tokens) && isPrimaryWorktree(ctx.cwd) ? WORKTREE_ADVICE : void 0;\n}\nconst GIT_FORCE_CREATE_LETTER = {\n switch: \"C\",\n checkout: \"B\"\n};\nconst GIT_FORCE_CREATE_LONG = {\n flag: \"--force-create\",\n shortest: \"--force-\"\n};\nfunction gitForceCreateTargets(after, letterSub) {\n const letter = GIT_FORCE_CREATE_LETTER[letterSub];\n const longFlag = GIT_FORCE_CREATE_LONG;\n const targets = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (letterSub === \"switch\") {\n const [flag, ...rest] = t.split(\"=\");\n if (flag !== void 0 && flag.length >= longFlag.shortest.length && longFlag.flag.startsWith(flag)) {\n const target = rest.length > 0 ? rest.join(\"=\") : after[i + 1];\n if (target !== void 0) targets.push(target);\n continue;\n }\n }\n const cluster = splitShortOptionCluster(t, letterSub);\n if (cluster === void 0 || !cluster.letters.includes(letter)) continue;\n if (cluster.attachedValue !== void 0 && cluster.attachedValue !== \"\") {\n targets.push(cluster.attachedValue);\n continue;\n }\n const next = after[i + 1];\n if (next !== void 0) targets.push(next);\n }\n return targets;\n}\nfunction gitCommandForceCreateTargets(tokens) {\n const sub = getGitSubcommand(tokens);\n if (sub === \"switch\" || sub === \"checkout\") return gitForceCreateTargets(tokens.slice(tokens.indexOf(sub) + 1), sub);\n if (sub === \"worktree\") {\n const worktreeIdx = tokens.indexOf(\"worktree\");\n if (tokens[worktreeIdx + 1] !== \"add\") return [];\n return gitForceCreateTargets(tokens.slice(worktreeIdx + 2), \"checkout\");\n }\n return [];\n}\nfunction isGitProtectedBranchForceCreate(tokens, ctx) {\n const targets = gitCommandForceCreateTargets(tokens);\n if (targets.length === 0) return false;\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n return targets.some((t) => protectedSet.has(t));\n}\nfunction isGitProtectedBranchRefWrite(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"branch\") return false;\n const { flags, positionals } = splitGitBranchArgs(tokens.slice(tokens.indexOf(sub) + 1));\n if (positionals.length === 0) return false;\n let deleteMode = false;\n let renameMode = false;\n let copyMode = false;\n let forceMode = false;\n for (const flag of flags) {\n if (flag.letters !== void 0) {\n if (flag.letters.includes(\"d\") || flag.letters.includes(\"D\")) deleteMode = true;\n if (flag.letters.includes(\"m\") || flag.letters.includes(\"M\")) renameMode = true;\n if (flag.letters.includes(\"c\") || flag.letters.includes(\"C\")) copyMode = true;\n if (flag.letters.includes(\"f\") || flag.letters.includes(\"M\") || flag.letters.includes(\"C\")) forceMode = true;\n continue;\n }\n if (flag.name === \"delete\") deleteMode = true;\n if (flag.name === \"move\") renameMode = true;\n if (flag.name === \"copy\") copyMode = true;\n if (flag.name === \"force\") forceMode = true;\n }\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n if (deleteMode && positionals.some((p) => protectedSet.has(p))) return true;\n if (renameMode && positionals.length >= 2 && protectedSet.has(positionals[0])) return true;\n if (forceMode) {\n const destination = renameMode || copyMode ? positionals[positionals.length - 1] : positionals[0];\n if (destination !== void 0 && protectedSet.has(destination)) return true;\n }\n return false;\n}\nfunction refspecDestination(refspec) {\n const spec = refspec.startsWith(\"+\") ? refspec.slice(1) : refspec;\n const colon = spec.lastIndexOf(\":\");\n return (colon === -1 ? spec : spec.slice(colon + 1)).replace(/^refs\\/heads\\//, \"\");\n}\nconst GIT_BRANCH_VALUE_FLAG_NAMES = /* @__PURE__ */ new Set([\n \"contains\",\n \"no-contains\",\n \"merged\",\n \"no-merged\",\n \"points-at\",\n \"sort\",\n \"format\",\n \"set-upstream-to\"\n]);\nfunction splitGitBranchArgs(after) {\n const flags = [];\n const positionals = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (t.startsWith(\"--\") && t !== \"--\") {\n const eq = t.indexOf(\"=\");\n const name = eq > 0 ? t.slice(2, eq) : t.slice(2);\n flags.push({\n raw: t,\n name\n });\n if (eq < 0 && GIT_BRANCH_VALUE_FLAG_NAMES.has(name)) i++;\n continue;\n }\n const cluster = splitShortOptionCluster(t, \"branch\");\n if (cluster === void 0) {\n flags.push({ raw: t });\n continue;\n }\n flags.push({\n raw: t,\n letters: cluster.letters\n });\n if (cluster.attachedValue === \"\") i++;\n }\n return {\n flags,\n positionals\n };\n}\nconst GIT_FETCH_VALUE_FLAG_NAMES = /* @__PURE__ */ new Set([\n \"depth\",\n \"deepen\",\n \"shallow-since\",\n \"shallow-exclude\",\n \"negotiation-tip\",\n \"filter\",\n \"jobs\",\n \"server-option\",\n \"upload-pack\",\n \"refmap\",\n \"submodule-prefix\",\n \"recurse-submodules-default\"\n]);\nfunction splitGitFetchArgs(after) {\n const flags = [];\n const positionals = [];\n const refmaps = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === void 0) continue;\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (t === \"--\") {\n flags.push({ raw: t });\n continue;\n }\n if (t.startsWith(\"--\")) {\n const eq = t.indexOf(\"=\");\n const name = eq > 0 ? t.slice(2, eq) : t.slice(2);\n flags.push({\n raw: t,\n name\n });\n if (name === \"refmap\") {\n if (eq > 0) refmaps.push(t.slice(eq + 1));\n else if (after[i + 1] !== void 0) refmaps.push(after[i + 1]);\n }\n if (eq < 0 && GIT_FETCH_VALUE_FLAG_NAMES.has(name)) i++;\n continue;\n }\n const cluster = splitShortOptionCluster(t, \"fetch\");\n if (cluster === void 0) {\n flags.push({ raw: t });\n continue;\n }\n flags.push({\n raw: t,\n letters: cluster.letters\n });\n if (cluster.attachedValue === \"\") i++;\n }\n return {\n flags,\n positionals,\n refmaps\n };\n}\nfunction fetchRefspecTarget(spec) {\n const body = spec.startsWith(\"+\") ? spec.slice(1) : spec;\n if (body.startsWith(\"^\")) return { kind: \"none\" };\n if (!body.includes(\":\")) return { kind: \"none\" };\n const destination = refspecDestination(body);\n if (destination === \"\") return { kind: \"none\" };\n if (destination.startsWith(\"refs/remotes/\")) return { kind: \"tracking\" };\n if (destination.startsWith(\"refs/\")) return { kind: \"other\" };\n return {\n kind: \"branch\",\n name: destination\n };\n}\nfunction globToAnchoredRegex(glob) {\n const escaped = glob.replace(/[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&\");\n return new RegExp(`^${escaped.replace(/\\\\\\*/g, \".*\")}$`);\n}\nfunction isProtectedFetchBranch(name, protectedSet) {\n if (protectedSet.has(name)) return true;\n if (!name.includes(\"*\")) return false;\n const pattern = globToAnchoredRegex(name);\n for (const member of protectedSet) if (pattern.test(member)) return true;\n return false;\n}\nfunction isGitProtectedBranchFetchWrite(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"fetch\") return false;\n const { positionals, refmaps } = splitGitFetchArgs(tokens.slice(tokens.indexOf(sub) + 1));\n const protectedSet = getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []);\n return [...positionals, ...refmaps].some((spec) => {\n const target = fetchRefspecTarget(spec);\n if (target.kind !== \"branch\" || target.name === void 0) return false;\n return isProtectedFetchBranch(target.name, protectedSet);\n });\n}\nfunction isGitProtectedUpdateRef(tokens, ctx) {\n const after = tokens.slice(tokens.indexOf(\"update-ref\") + 1);\n let ref;\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (t === \"-m\") {\n i++;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n ref = t;\n break;\n }\n if (ref === void 0) return false;\n return getProtectedBranches(ctx.cwd, ctx.repoProtectedBranches ?? []).has(ref.replace(/^refs\\/heads\\//, \"\"));\n}\nfunction gitEffectiveCwd(tokens, cwd) {\n let dir = cwd;\n const args = tokens.slice(1);\n for (let i = 0; i < args.length; i++) {\n const t = args[i];\n if (t === \"-C\") {\n const next = args[i + 1];\n if (next !== void 0) dir = path.resolve(dir, next);\n i++;\n continue;\n }\n if (GIT_FLAGS_WITH_ARG.has(t)) {\n i++;\n continue;\n }\n if (!t.startsWith(\"-\")) break;\n }\n return dir;\n}\nconst GIT_SWITCH_NEUTRAL_FLAGS = /* @__PURE__ */ new Set([\n \"-q\",\n \"--quiet\",\n \"-f\",\n \"--force\",\n \"--discard-changes\",\n \"-m\",\n \"--merge\",\n \"--no-track\",\n \"--progress\",\n \"--no-progress\",\n \"--guess\",\n \"--no-guess\",\n \"--ignore-other-worktrees\",\n \"--recurse-submodules\",\n \"--no-recurse-submodules\"\n]);\nconst GIT_SWITCH_CREATE_FLAGS = /* @__PURE__ */ new Set([\n \"--create\",\n \"--force-create\",\n \"--orphan\"\n]);\nconst GIT_CHECKOUT_PATH_FLAGS = /* @__PURE__ */ new Set([\n \"--ours\",\n \"--theirs\",\n \"-p\",\n \"--patch\",\n \"--conflict\",\n \"--pathspec-from-file\",\n \"--pathspec-file-nul\",\n \"--overlay\",\n \"--no-overlay\"\n]);\nconst GIT_SWITCH_NEUTRAL_LETTERS = /* @__PURE__ */ new Set([\n \"q\",\n \"f\",\n \"m\"\n]);\nfunction switchTarget(after, sub, isCheckoutBranch) {\n if (sub === \"checkout\" && after.includes(\"--\")) return void 0;\n const createLetters = sub === \"checkout\" ? [\"b\", \"B\"] : [\"c\", \"C\"];\n const known = (l) => GIT_SWITCH_NEUTRAL_LETTERS.has(l) || createLetters.includes(l);\n const positionals = [];\n let created;\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n if (GIT_SWITCH_NEUTRAL_FLAGS.has(t)) continue;\n const eq = t.indexOf(\"=\");\n if (sub === \"checkout\" && GIT_CHECKOUT_PATH_FLAGS.has(eq === -1 ? t : t.slice(0, eq))) return;\n if (GIT_SWITCH_CREATE_FLAGS.has(eq === -1 ? t : t.slice(0, eq))) {\n created = eq === -1 ? after[++i] : t.slice(eq + 1);\n continue;\n }\n const cluster = splitShortOptionCluster(t, sub);\n if (cluster === void 0 || !cluster.letters.every(known)) return null;\n if (cluster.letters.some((l) => createLetters.includes(l))) created = cluster.attachedValue ? cluster.attachedValue : after[++i];\n }\n if (created !== void 0) return created;\n if (positionals.length !== 1) return void 0;\n const target = positionals[0];\n if (target === \"HEAD\" || target === \"@\") return void 0;\n if (sub === \"checkout\" && !isCheckoutBranch(target)) return void 0;\n return target;\n}\nfunction branchSwitch(tokens, ctx, resolved) {\n const sub = getGitSubcommand(tokens);\n if (sub !== \"switch\" && sub !== \"checkout\") return void 0;\n const dir = gitEffectiveCwd(tokens, ctx.cwd);\n const isCheckoutBranch = (name) => !resolved || getProtectedBranches(dir, ctx.repoProtectedBranches ?? []).has(name) || resolveCommit(dir, name) !== null;\n const target = switchTarget(tokens.slice(tokens.indexOf(sub) + 1), sub, isCheckoutBranch);\n if (!resolved) return target === void 0 ? void 0 : {\n dir,\n branch: null\n };\n return target === void 0 ? void 0 : {\n dir,\n branch: target\n };\n}\nconst GIT_CHECKED_OUT_WRITES = /* @__PURE__ */ new Set([\n \"commit\",\n \"merge\",\n \"rebase\",\n \"cherry-pick\",\n \"revert\",\n \"am\",\n \"pull\"\n]);\nfunction subcommandArgs(tokens, sub, valueFlags = /* @__PURE__ */ new Set()) {\n const after = tokens.slice(tokens.indexOf(sub) + 1);\n const flags = [];\n const positionals = [];\n for (let i = 0; i < after.length; i++) {\n const t = after[i];\n if (!t.startsWith(\"-\")) {\n positionals.push(t);\n continue;\n }\n flags.push(t);\n if (valueFlags.has(t)) i++;\n }\n return {\n flags,\n positionals\n };\n}\nconst GIT_PUSH_VALUE_FLAGS = /* @__PURE__ */ new Set([\n \"-o\",\n \"--push-option\",\n \"--repo\",\n \"--receive-pack\",\n \"--exec\"\n]);\nfunction isMergeFastForwardFromUpstream(tokens, upstream) {\n const { flags, positionals } = subcommandArgs(tokens, \"merge\");\n if (!flags.includes(\"--ff-only\") || positionals.length !== 1) return false;\n const ref = positionals[0];\n return ref === \"@{u}\" || ref === \"@{upstream}\" || upstream !== null && ref === upstream;\n}\nconst GIT_PULL_NO_REBASE = /* @__PURE__ */ new Set([\n \"--rebase=false\",\n \"--rebase=no\",\n \"--rebase=off\",\n \"--rebase=0\"\n]);\nfunction isPullFromUpstream(tokens, upstream) {\n const { flags, positionals } = subcommandArgs(tokens, \"pull\");\n if (flags.some((t) => t.startsWith(\"--rebase\") && !GIT_PULL_NO_REBASE.has(t) || t === \"--no-ff\" || !t.startsWith(\"--\") && t.slice(1).includes(\"r\"))) return false;\n if (positionals.length === 0) return true;\n if (positionals.length !== 2 || upstream === null) return false;\n const [remote, branch] = positionals;\n return `${remote}/${branch.replace(/^refs\\/heads\\//, \"\")}` === upstream;\n}\nfunction isRefMovingReset(tokens, cwd, head) {\n if (tokens.slice(tokens.indexOf(\"reset\") + 1).includes(\"--\")) return false;\n const { positionals } = subcommandArgs(tokens, \"reset\");\n if (positionals.length !== 1) return false;\n if (head !== \"HEAD\" && /^(HEAD|@)/.test(positionals[0])) return false;\n const target = resolveCommit(cwd, positionals[0]);\n if (target === null) return false;\n return target !== resolveCommit(cwd, head);\n}\nfunction pushDestinations(tokens, current) {\n const { positionals } = subcommandArgs(tokens, \"push\", GIT_PUSH_VALUE_FLAGS);\n const refspecs = positionals.slice(1);\n if (refspecs.length === 0) return null;\n const names = [];\n for (const spec of refspecs) {\n const dst = refspecDestination(spec);\n if (dst === \"HEAD\" || dst === \"@\") {\n if (current !== null) names.push(current);\n continue;\n }\n names.push(dst);\n }\n return names;\n}\nconst GIT_PUSH_EVERY_BRANCH = /* @__PURE__ */ new Set([\n \"--all\",\n \"--branches\",\n \"--mirror\"\n]);\nfunction leavesRefInPlace(tokens, sub) {\n const { flags } = subcommandArgs(tokens, sub);\n if (flags.includes(\"--abort\") || flags.includes(\"--quit\")) return true;\n return sub === \"commit\" && flags.includes(\"--dry-run\");\n}\nfunction movesProtectedRef(tokens, ctx) {\n const sub = getGitSubcommand(tokens);\n if (sub === void 0) return false;\n if (sub === \"switch\" || sub === \"checkout\" || sub === \"worktree\") return isGitProtectedBranchForceCreate(tokens, ctx);\n if (sub === \"branch\") return isGitProtectedBranchRefWrite(tokens, ctx);\n if (sub === \"fetch\") return isGitProtectedBranchFetchWrite(tokens, ctx);\n if (sub === \"update-ref\") return isGitProtectedUpdateRef(tokens, ctx);\n if (sub !== \"push\" && sub !== \"reset\" && !GIT_CHECKED_OUT_WRITES.has(sub)) return false;\n const cwd = gitEffectiveCwd(tokens, ctx.cwd);\n const pending = ctx.pendingBranches?.[cwd];\n const current = pending ? pending.branch : getCurrentBranch(cwd);\n const protectedSet = getProtectedBranches(cwd, ctx.repoProtectedBranches ?? []);\n const onProtected = current !== null && protectedSet.has(current);\n if (sub === \"push\") {\n const { flags } = subcommandArgs(tokens, \"push\", GIT_PUSH_VALUE_FLAGS);\n if (flags.some((f) => GIT_PUSH_EVERY_BRANCH.has(f))) return true;\n const destinations = pushDestinations(tokens, current);\n if (destinations === null) {\n if (flags.includes(\"--tags\")) return false;\n return onProtected;\n }\n return destinations.some((d) => protectedSet.has(d));\n }\n if (!onProtected) return false;\n if (leavesRefInPlace(tokens, sub)) return false;\n if (sub === \"reset\") return isRefMovingReset(tokens, cwd, pending ? current : \"HEAD\");\n if (sub === \"merge\" || sub === \"pull\") {\n const upstream = getUpstream(cwd, current);\n if (sub === \"merge\" && isMergeFastForwardFromUpstream(tokens, upstream)) return false;\n if (sub === \"pull\" && isPullFromUpstream(tokens, upstream)) return false;\n }\n return true;\n}\nconst PNPM_BUILTINS = /* @__PURE__ */ new Set([\n \"install\",\n \"i\",\n \"add\",\n \"remove\",\n \"rm\",\n \"uninstall\",\n \"un\",\n \"update\",\n \"up\",\n \"upgrade\",\n \"list\",\n \"ls\",\n \"ll\",\n \"la\",\n \"why\",\n \"view\",\n \"info\",\n \"show\",\n \"outdated\",\n \"audit\",\n \"licenses\",\n \"init\",\n \"create\",\n \"link\",\n \"unlink\",\n \"pack\",\n \"publish\",\n \"config\",\n \"set\",\n \"get\",\n \"store\",\n \"cache\",\n \"rebuild\",\n \"rb\",\n \"prune\",\n \"dedupe\",\n \"dlx\",\n \"exec\",\n \"run\",\n \"patch\",\n \"patch-commit\",\n \"recursive\",\n \"-r\"\n]);\nconst NPM_READ_OPS = /* @__PURE__ */ new Set([\n \"view\",\n \"info\",\n \"show\"\n]);\nfunction isNpmReadOp(tokens) {\n const sub = tokens[1];\n return sub !== void 0 && NPM_READ_OPS.has(sub);\n}\nfunction getNpmRedirectReason(tokens) {\n const sub = tokens[1];\n const BASE = \"This project uses pnpm.\";\n if (!sub) return `${BASE} Use \\`pnpm\\` instead of npm.`;\n if (sub === \"install\" || sub === \"i\" || sub === \"ci\") {\n if (tokens.slice(2).some((t) => !t.startsWith(\"-\"))) return `${BASE} Use \\`pnpm add <pkg>\\` instead of \\`npm install <pkg>\\`.`;\n return `${BASE} Use \\`pnpm install\\` instead of npm.`;\n }\n if (sub === \"add\") return `${BASE} Use \\`pnpm add <pkg>\\` instead of npm.`;\n if (sub === \"uninstall\" || sub === \"remove\" || sub === \"rm\" || sub === \"un\" || sub === \"r\") return `${BASE} Use \\`pnpm remove <pkg>\\` instead of npm.`;\n if (sub === \"run\" || sub === \"run-script\") return `${BASE} Use \\`pnpm run <script>\\` or \\`pnpm <script>\\` instead of npm.`;\n if (sub === \"test\" || sub === \"t\" || sub === \"tst\") return `${BASE} Use \\`pnpm test\\` instead of npm.`;\n if (sub === \"start\") return `${BASE} Use \\`pnpm start\\` instead of npm.`;\n if (sub === \"stop\") return `${BASE} Use \\`pnpm stop\\` instead of npm.`;\n if (sub === \"restart\") return `${BASE} Use \\`pnpm restart\\` instead of npm.`;\n if (sub === \"exec\") return `${BASE} Use \\`pnpm exec <cmd>\\` instead of npm.`;\n if (sub === \"list\" || sub === \"ls\" || sub === \"ll\" || sub === \"la\") return `${BASE} Use \\`pnpm list\\` instead of npm.`;\n if (sub === \"why\") return `${BASE} Use \\`pnpm why\\` instead of npm.`;\n if (sub === \"outdated\") return `${BASE} Use \\`pnpm outdated\\` instead of npm.`;\n if (sub === \"audit\") return `${BASE} Use \\`pnpm audit\\` instead of npm.`;\n if (sub === \"update\" || sub === \"up\" || sub === \"upgrade\") return `${BASE} Use \\`pnpm update\\` instead of npm.`;\n if (sub === \"init\") return `${BASE} Use \\`pnpm init\\` instead of npm.`;\n if (sub === \"publish\") return `${BASE} Use \\`pnpm publish\\` instead of npm.`;\n if (sub === \"link\") return `${BASE} Use \\`pnpm link\\` instead of npm.`;\n if (sub === \"unlink\") return `${BASE} Use \\`pnpm unlink\\` instead of npm.`;\n if (sub === \"pack\") return `${BASE} Use \\`pnpm pack\\` instead of npm.`;\n if (sub === \"cache\") return `${BASE} Use \\`pnpm store\\` instead of \\`npm cache\\`.`;\n if (sub === \"config\" || sub === \"set\" || sub === \"get\") return `${BASE} Use \\`pnpm config\\` instead of npm.`;\n return `${BASE} Use the equivalent pnpm command instead of npm.`;\n}\nconst LAST_POSITIONAL_DEST = /* @__PURE__ */ new Set([\n \"cp\",\n \"mv\",\n \"rsync\",\n \"install\",\n \"ln\"\n]);\nconst ALL_POSITIONAL_DEST = /* @__PURE__ */ new Set([\"tee\", \"truncate\"]);\nfunction explicitTargetDirectory(rest) {\n for (const [i, t] of rest.entries()) {\n if (t === \"-t\" || t === \"--target-directory\") return rest[i + 1] ?? null;\n if (t.startsWith(\"--target-directory=\")) return t.slice(19);\n }\n return null;\n}\nconst OUTPUT_REDIRECT = /^(?:\\d*|&)>{1,2}$/;\nconst OUTPUT_REDIRECT_ATTACHED = /^(?:\\d*|&)>{1,2}(.+)$/;\nconst INPUT_REDIRECT = /^\\d*<$/;\nconst INPUT_REDIRECT_ATTACHED = /^\\d*<([^<].*)$/;\nfunction spacedRedirectDirection(token) {\n if (OUTPUT_REDIRECT.test(token)) return \"out\";\n if (INPUT_REDIRECT.test(token)) return \"in\";\n return null;\n}\nfunction splitRedirects(tokens) {\n const redirects = [];\n const rest = [];\n for (let i = 0; i < tokens.length; i++) {\n const t = tokens[i];\n const spaced = spacedRedirectDirection(t);\n if (spaced !== null) {\n const next = tokens[i + 1];\n if (next !== void 0) redirects.push({\n direction: spaced,\n target: next\n });\n i++;\n continue;\n }\n const out = OUTPUT_REDIRECT_ATTACHED.exec(t);\n if (out) {\n redirects.push({\n direction: \"out\",\n target: out[1]\n });\n continue;\n }\n const input = INPUT_REDIRECT_ATTACHED.exec(t);\n if (input) {\n redirects.push({\n direction: \"in\",\n target: input[1]\n });\n continue;\n }\n rest.push(t);\n }\n return {\n redirects,\n rest\n };\n}\nfunction redirectTargets(tokens, direction) {\n return splitRedirects(tokens).redirects.filter((r) => r.direction === direction).map((r) => r.target);\n}\nfunction writeDestinations(tokens) {\n const cmd = path.basename(tokens[0] ?? \"\");\n const rest = tokens.slice(1);\n const dests = redirectTargets(tokens, \"out\");\n if (cmd === \"dd\") dests.push(...rest.filter((t) => t.startsWith(\"of=\")).map((t) => t.slice(3)));\n else if (cmd === \"sed\") {\n if (rest.some((t) => t === \"--in-place\" || /^-[a-zA-Z]*i/.test(t))) dests.push(...rest.filter((t) => !t.startsWith(\"-\")));\n } else if (ALL_POSITIONAL_DEST.has(cmd)) dests.push(...rest.filter((t) => !t.startsWith(\"-\")));\n else if (LAST_POSITIONAL_DEST.has(cmd)) {\n if (cmd === \"cp\" && rest.includes(\"--remove-destination\")) return dests;\n const targetDir = explicitTargetDirectory(rest);\n if (targetDir !== null) dests.push(targetDir);\n else {\n const last = rest.findLast((t) => !t.startsWith(\"-\"));\n if (last !== void 0) dests.push(last);\n }\n }\n return dests;\n}\nfunction writesIntoNodeModules(tokens, ctx) {\n return writeDestinations(tokens).some((d) => targetsNodeModules(d, ctx.cwd));\n}\nconst NODE_MODULES_WRITE_REASON = \"Don't write into node_modules/. Its files are hardlinks into pnpm's global store, so overwriting one in place (plain `cp`, `>` redirect, `sed -i`, ...) writes through the link and corrupts that package for every project on this machine -- silently, since the directory you wrote into ends up fine. To test a local build as an installed dependency, run it directly (`node packages/<pkg>/dist/bin.mjs <cmd>`), or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`). If you must replace a file in place, `cp --remove-destination` is safe -- it unlinks the target first. Run `pnpm store status` to check whether the store is already damaged.\";\nfunction isChmod777(tokens) {\n return tokens.some((t) => t === \"777\" || t === \"0777\");\n}\nfunction isGitForcePush(tokens) {\n const pushIdx = tokens.indexOf(\"push\");\n if (pushIdx === -1) return false;\n return tokens.slice(pushIdx + 1).some((t) => t === \"--force\" || t === \"-f\");\n}\nconst ENV_READ_FILE_COMMANDS = /* @__PURE__ */ new Set([\n \"cat\",\n \"head\",\n \"tail\",\n \"less\",\n \"more\",\n \"source\",\n \".\"\n]);\nconst GREP_FAMILY_COMMANDS = /* @__PURE__ */ new Set([\n \"grep\",\n \"rg\",\n \"ag\"\n]);\nfunction grepFileOperands(rest) {\n const files = [];\n let patternAccountedFor = false;\n let optionsEnded = false;\n for (let i = 0; i < rest.length; i++) {\n const t = rest[i];\n if (!optionsEnded && t === \"--\") {\n optionsEnded = true;\n continue;\n }\n if (!optionsEnded) {\n if (t === \"-f\" || t === \"--file\") {\n const value = rest[i + 1];\n if (value !== void 0) {\n files.push(value);\n i++;\n }\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"--file=\")) {\n files.push(t.slice(7));\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"-f\") && t !== \"-f\" && !t.startsWith(\"--\")) {\n files.push(t.slice(2));\n patternAccountedFor = true;\n continue;\n }\n if (t === \"-e\" || t === \"--regexp\") {\n i++;\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"--regexp=\") || t.startsWith(\"-e\") && t !== \"-e\" && !t.startsWith(\"--\")) {\n patternAccountedFor = true;\n continue;\n }\n if (t.startsWith(\"-\")) continue;\n }\n if (!patternAccountedFor) {\n patternAccountedFor = true;\n continue;\n }\n files.push(t);\n }\n return files;\n}\nfunction envFileOperands(tokens) {\n const cmd = path.basename(tokens[0] ?? \"\");\n const { redirects, rest } = splitRedirects(tokens.slice(1));\n const operands = redirects.filter((r) => r.direction === \"in\").map((r) => r.target);\n if (GREP_FAMILY_COMMANDS.has(cmd)) operands.push(...grepFileOperands(rest));\n else if (ENV_READ_FILE_COMMANDS.has(cmd)) operands.push(...rest.filter((t) => !t.startsWith(\"-\")));\n return operands;\n}\nconst HEALTH_CEILING_FILES = [\"health-baseline.json\", \".tooling.json\"];\nconst HEALTH_BASELINE_FILE = \"health-baseline.json\";\nconst HEALTH_RAISE_REASON = \"A health ceiling raise travels alone: open a ceiling-only pull request -- only health-baseline.json and .tooling.json changed -- for a human to merge, or split the module. `bst health:check` refuses the raise beside code either way. To restore the default branch's copy run `git show origin/<default>:health-baseline.json > health-baseline.json`, and to adopt lower counts run `bst health:check --update-baseline`.\";\nfunction writesHealthBaseline(tokens, cwd) {\n const destinations = writeDestinations(tokens);\n if (!destinations.some((dest) => baseName(dest) === \"health-baseline.json\")) return false;\n const root = getRepoTopLevel(cwd) ?? cwd;\n return destinations.some((dest) => samePath(resolveIn(cwd, dest), path.join(root, HEALTH_BASELINE_FILE)));\n}\nfunction baseName(target) {\n const segments = target.split(/[/\\\\]/);\n return segments[segments.length - 1] ?? \"\";\n}\nfunction isBaselineRestore(tokens) {\n if (tokens[0] !== \"git\") return false;\n let i = 1;\n while (tokens[i]?.startsWith(\"-\") === true) i += GIT_FLAGS_WITH_ARG.has(tokens[i] ?? \"\") ? 2 : 1;\n if (tokens[i] !== \"show\") return false;\n return tokens.slice(i + 1).some((token) => token.includes(\":\") && baseName(token.slice(token.lastIndexOf(\":\") + 1)) === \"health-baseline.json\");\n}\nfunction isHealthBaselineReset(tokens) {\n return tokens.includes(\"health:check\") && tokens.includes(\"--update-baseline\") && tokens.includes(\"--reset\");\n}\nfunction raiseTravelsWithCode(cwd) {\n return branchCarriesOtherFiles(cwd, HEALTH_CEILING_FILES) === true;\n}\nconst denyRules = [\n {\n name: \"sudo\",\n match: /^sudo$/,\n action: \"deny\",\n reason: \"Don't use sudo. If you need elevated permissions, ask me to do it manually.\"\n },\n {\n name: \"git-force-push\",\n match: /^git$/,\n action: \"deny\",\n when: (tokens) => isGitForcePush(tokens),\n reason: \"Use `git push --force-with-lease` instead of `--force`.\"\n },\n {\n name: \"git-protected-branch-write\",\n match: /^git$/,\n action: \"deny\",\n when: (tokens, ctx) => movesProtectedRef(tokens, ctx),\n reason: \"This would move a protected branch (main, master, the remote's default branch, or one listed in .claude/hooks/bst-hook.settings.json#protectedBranches). Work on a feature branch in a worktree: `git worktree add ../<repo>-<topic> -b feat/<topic>`, then commit and push there. To bring `main` up to date, use `git pull --ff-only`.\"\n },\n {\n name: \"chmod-777\",\n match: /^chmod$/,\n action: \"deny\",\n when: (tokens) => isChmod777(tokens),\n reason: \"Don't use 777 permissions. Use more restrictive permissions.\"\n },\n {\n name: \"node-modules-write\",\n match: /./,\n action: \"deny\",\n when: (tokens, ctx) => writesIntoNodeModules(tokens, ctx),\n reason: NODE_MODULES_WRITE_REASON\n },\n {\n name: \"env-file-read\",\n match: /./,\n action: \"deny\",\n when: (tokens) => envFileOperands(tokens).some(isEnvFile),\n reason: \"Don't read .env files. These contain secrets that should not appear in the conversation.\"\n },\n {\n name: \"env-file-write\",\n match: /./,\n action: \"deny\",\n when: (tokens) => redirectTargets(tokens, \"out\").some(isEnvFile),\n reason: \"Don't write to .env files. These contain secrets.\"\n },\n {\n name: \"health-baseline-write\",\n match: /./,\n action: \"deny\",\n when: (tokens, ctx) => writesHealthBaseline(tokens, ctx.cwd) && !isBaselineRestore(tokens) && raiseTravelsWithCode(ctx.cwd),\n reason: HEALTH_RAISE_REASON\n },\n {\n name: \"health-baseline-reset\",\n match: /^bst$/,\n action: \"deny\",\n when: (tokens, ctx) => isHealthBaselineReset(tokens) && raiseTravelsWithCode(ctx.cwd),\n reason: HEALTH_RAISE_REASON\n },\n {\n name: \"npx-redirect\",\n match: /^npx$/,\n action: \"deny\",\n reason: \"This project uses pnpm. Use `pnpm dlx <pkg>` or `pnpm exec <cmd>` instead of npx.\"\n },\n {\n name: \"mise-self-update\",\n match: /^mise$/,\n action: \"deny\",\n when: (tokens) => tokens[1] === \"self-update\",\n reason: \"Don't self-update mise. The version is Renovate-managed; ask a human to bump the pin.\"\n }\n];\n\n//#endregion\n//#region src/lib/script-resolver.ts\nconst PackageJsonSchema = object({ scripts: record(string(), unknown()) });\nfunction resolveScript(scriptName, cwd) {\n const scripts = readScripts(cwd);\n if (!scripts) return null;\n const main = scripts[scriptName];\n if (typeof main !== \"string\") return null;\n const pre = scripts[`pre${scriptName}`];\n const post = scripts[`post${scriptName}`];\n return {\n pre: typeof pre === \"string\" ? pre : null,\n main,\n post: typeof post === \"string\" ? post : null\n };\n}\nfunction resolveFilteredScript(scriptName, filterPkg, cwd) {\n const pkgDir = findWorkspacePackageDir(filterPkg, cwd);\n if (!pkgDir) return null;\n const script = resolveScript(scriptName, pkgDir);\n if (!script) return null;\n return {\n ...script,\n pkgDir\n };\n}\nfunction resolveRecursiveScripts(scriptName, rootDir) {\n const pkgDirs = listWorkspacePackageDirs(rootDir);\n if (!pkgDirs) return null;\n const results = [];\n for (const pkgDir of pkgDirs) {\n const resolved = resolveScript(scriptName, pkgDir);\n if (resolved) results.push({\n ...resolved,\n pkgDir\n });\n }\n return results;\n}\nfunction listWorkspacePackageDirs(rootDir) {\n const patterns = readWorkspacePatterns(rootDir);\n if (!patterns) return null;\n const dirs = [];\n for (const pattern of patterns) {\n if (!pattern.endsWith(\"/*\")) continue;\n const baseDir = pattern.slice(0, -2);\n const parentDir = resolve(rootDir, baseDir);\n let entries;\n try {\n entries = readdirSync(parentDir);\n } catch {\n continue;\n }\n for (const entry of entries) {\n const entryDir = join(parentDir, entry);\n try {\n if (!statSync(entryDir).isDirectory()) continue;\n } catch {\n continue;\n }\n dirs.push(entryDir);\n }\n }\n return dirs.length > 0 ? dirs : null;\n}\nfunction findWorkspacePackageDir(pkgName, rootDir) {\n const pkgDirs = listWorkspacePackageDirs(rootDir);\n if (!pkgDirs) return null;\n for (const entryDir of pkgDirs) {\n const name = readPackageName(entryDir);\n if (name === pkgName || name === `@${pkgName}`) return entryDir;\n if (entryDir.split(\"/\").pop() === pkgName) return entryDir;\n if (name) {\n if ((name.startsWith(\"@\") ? name.split(\"/\")[1] : name) === pkgName) return entryDir;\n }\n }\n return null;\n}\nfunction readWorkspacePatterns(rootDir) {\n try {\n const lines = readFileSync(join(rootDir, \"pnpm-workspace.yaml\"), \"utf-8\").split(\"\\n\");\n const packagesIdx = lines.findIndex((l) => /^packages\\s*:/.test(l));\n if (packagesIdx === -1) return null;\n const patterns = [];\n for (let i = packagesIdx + 1; i < lines.length; i++) {\n const line = lines[i];\n const match = /^\\s+-\\s+(.+)$/.exec(line);\n if (!match) break;\n patterns.push(match[1].trim().replace(/['\"`]/g, \"\"));\n }\n return patterns.length > 0 ? patterns : null;\n } catch {\n return null;\n }\n}\nconst PackageNameSchema = object({ name: string() });\nfunction readPackageName(dir) {\n try {\n const raw = readFileSync(join(dir, \"package.json\"), \"utf-8\");\n const result = PackageNameSchema.safeParse(JSON.parse(raw));\n if (!result.success) return null;\n return result.data.name;\n } catch {\n return null;\n }\n}\nfunction readScripts(cwd) {\n try {\n const raw = readFileSync(join(cwd, \"package.json\"), \"utf-8\");\n const result = PackageJsonSchema.safeParse(JSON.parse(raw));\n if (!result.success) return null;\n return result.data.scripts;\n } catch {\n return null;\n }\n}\n\n//#endregion\n//#region src/lib/workspace-root.ts\nfunction findWorkspaceRoot(cwd) {\n let dir = resolve(cwd);\n while (true) {\n if (existsSync(join(dir, \"pnpm-workspace.yaml\"))) return dir;\n const parent = dirname(dir);\n if (parent === dir) return null;\n dir = parent;\n }\n}\n\n//#endregion\n//#region src/evaluate.ts\nconst MAX_EVAL_DEPTH = 5;\nfunction subshellBody(command) {\n if (!command.startsWith(\"(\") || !command.endsWith(\")\")) return null;\n let depth = 0;\n let quote = null;\n for (let i = 0; i < command.length; i++) {\n const ch = command[i];\n if (quote !== null) {\n if (ch === quote) quote = null;\n else if (ch === \"\\\\\" && quote === \"\\\"\") i++;\n continue;\n }\n if (ch === \"\\\\\") i++;\n else if (ch === \"'\" || ch === \"\\\"\") quote = ch;\n else if (ch === \"(\") depth++;\n else if (ch === \")\") {\n depth--;\n if (depth === 0) return i === command.length - 1 ? command.slice(1, -1) : null;\n }\n }\n return null;\n}\nfunction extractCdDir(segment, ctx) {\n const tokenResult = tokenize(segment);\n if (!tokenResult.ok || tokenResult.tokens.length !== 2) return null;\n const tokens = tokenResult.tokens;\n if (tokens[0] !== \"cd\") return null;\n const dir = tokens[1];\n if (path.isAbsolute(dir)) return dir;\n return path.resolve(ctx.cwd, dir);\n}\nfunction extractBranchSwitch(segment, ctx) {\n const tokenResult = tokenize(segment);\n if (!tokenResult.ok) return void 0;\n let tokens = tokenResult.tokens;\n let envSkipped = 0;\n while (envSkipped < tokens.length && /^\\w+=/.test(tokens[envSkipped])) envSkipped++;\n tokens = tokens.slice(envSkipped);\n if (tokens.length === 0 || path.basename(tokens[0]) !== \"git\") return void 0;\n return branchSwitch(tokens, ctx, checkInjection(tokens, segment).safe);\n}\nfunction evaluateCommand(command, ctx) {\n if (ctx.depth >= MAX_EVAL_DEPTH) return {\n action: \"none\",\n rule: null,\n reason: \"max evaluation depth exceeded\"\n };\n const trimmed = command.trim();\n if (!trimmed) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n const body = subshellBody(trimmed);\n if (body !== null) return evaluateCommand(body, {\n ...ctx,\n depth: ctx.depth + 1\n });\n const segments = splitCommand(trimmed);\n if (segments.length === 0) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n let firstNone = null;\n const currentCtx = { ...ctx };\n let unknownAfterNext;\n for (const segment of segments) {\n if (segment.operator === \"&&\") {\n const cdDir = extractCdDir(segment.command, currentCtx);\n if (cdDir) currentCtx.cwd = cdDir;\n }\n const result = evaluateSegment(segment.command, currentCtx);\n if (result.action === \"deny\") return result;\n if (!firstNone) firstNone = result;\n if (unknownAfterNext) {\n currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [unknownAfterNext.dir]: unknownAfterNext\n };\n unknownAfterNext = void 0;\n }\n const switched = extractBranchSwitch(segment.command, currentCtx);\n if (switched) {\n const unknown = {\n dir: switched.dir,\n branch: null\n };\n if (segment.operator === \"&&\") currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [switched.dir]: switched\n };\n else if (segment.operator === \"||\") unknownAfterNext = unknown;\n else currentCtx.pendingBranches = {\n ...currentCtx.pendingBranches,\n [switched.dir]: unknown\n };\n }\n }\n return firstNone ?? {\n action: \"none\",\n rule: null,\n reason: null\n };\n}\nfunction evaluateResolvedScript(resolved, ctx) {\n if (resolved.pre) {\n const preResult = evaluateCommand(resolved.pre, ctx);\n if (preResult.action === \"deny\") return preResult;\n }\n const mainResult = evaluateCommand(resolved.main, ctx);\n if (mainResult.action === \"deny\") return mainResult;\n if (resolved.post) {\n const postResult = evaluateCommand(resolved.post, ctx);\n if (postResult.action === \"deny\") return postResult;\n }\n return {\n action: \"none\",\n rule: null,\n reason: null\n };\n}\nfunction evaluateSegment(rawSegment, ctx) {\n const trimmed = rawSegment.trim();\n const body = subshellBody(trimmed);\n if (body !== null) return evaluateCommand(body, {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (trimmed.startsWith(\"(\") && trimmed.endsWith(\")\")) return {\n action: \"none\",\n rule: null,\n reason: \"subshell\"\n };\n const tokenResult = tokenize(rawSegment);\n if (!tokenResult.ok) return {\n action: \"none\",\n rule: null,\n reason: tokenResult.error\n };\n let tokens = tokenResult.tokens;\n if (tokens.length === 0) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n let envSkipped = 0;\n while (envSkipped < tokens.length && /^\\w+=/.test(tokens[envSkipped])) envSkipped++;\n if (envSkipped >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n tokens = tokens.slice(envSkipped);\n if (writesIntoNodeModules(tokens, ctx)) return {\n action: \"deny\",\n rule: \"node-modules-write\",\n reason: NODE_MODULES_WRITE_REASON\n };\n const injection = checkInjection(tokens, rawSegment);\n if (!injection.safe) return {\n action: \"none\",\n rule: null,\n reason: injection.reason\n };\n const SAFE_REDIRECT_TOKENS = /* @__PURE__ */ new Set([\n \"2>&1\",\n \"2>/dev/null\",\n \">/dev/null\",\n \"1>/dev/null\"\n ]);\n tokens = tokens.filter((t, i) => {\n if (SAFE_REDIRECT_TOKENS.has(t)) return false;\n if ((t === \">\" || t === \">>\") && tokens[i + 1] === \"/dev/null\") return false;\n if (t === \"/dev/null\" && i > 0 && (tokens[i - 1] === \">\" || tokens[i - 1] === \">>\")) return false;\n return true;\n });\n const cmdName = path.basename(tokens[0]);\n if (cmdName === \"command\" && tokens.length > 1) return evaluateCommand(joinTokens(tokens.slice(1)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (cmdName === \"env\") {\n let envIdx = 1;\n while (envIdx < tokens.length && /^\\w+=/.test(tokens[envIdx])) envIdx++;\n if (envIdx >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n return evaluateCommand(joinTokens(tokens.slice(envIdx)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n if (cmdName === \"pnpm\") return evaluatePnpm(tokens, ctx);\n if (cmdName === \"npm\") return evaluateNpm(tokens);\n if (cmdName === \"mise\" && tokens[1] === \"exec\") {\n const inner = miseExecInner(tokens);\n if (!inner) return {\n action: \"none\",\n rule: null,\n reason: \"bare mise exec\"\n };\n return evaluateCommand(joinTokens(inner), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n if (cmdName === \"bash\" || cmdName === \"sh\" || cmdName === \"zsh\") return evaluateShellC(tokens, ctx);\n if (cmdName === \"xargs\") return evaluateXargs(tokens, ctx);\n if (cmdName === \"node\" && (tokens.includes(\"-e\") || tokens.includes(\"-p\") || tokens.includes(\"--eval\") || tokens.includes(\"--print\"))) return {\n action: \"none\",\n rule: null,\n reason: \"node eval\"\n };\n for (const rule of denyRules) if (rule.match.test(cmdName)) {\n if (!rule.when || rule.when(tokens, ctx)) return {\n action: \"deny\",\n rule: rule.name,\n reason: rule.reason ?? null\n };\n }\n const advice = cmdName === \"git\" ? worktreeAdvice(tokens, ctx) : void 0;\n return {\n action: \"none\",\n rule: null,\n reason: `no rule matched: ${cmdName}`,\n ...advice ? { advice } : {}\n };\n}\nfunction miseExecInner(tokens) {\n const dashIdx = tokens.indexOf(\"--\");\n if (dashIdx === -1) return void 0;\n const inner = tokens.slice(dashIdx + 1);\n return inner.length > 0 ? inner : void 0;\n}\nfunction scanPnpmFlags(subTokens, from, state) {\n for (let i = from; i < subTokens.length; i++) {\n const t = subTokens[i];\n if (t === \"--filter\" || t.startsWith(\"--filter=\") || t === \"-F\" || t.startsWith(\"-F=\")) return {\n name: void 0,\n filterIdx: i\n };\n if (t === \"-r\" || t === \"--recursive\") {\n state.isRecursive = true;\n continue;\n }\n if (t === \"-w\" || t === \"--workspace-root\") {\n state.isWorkspaceRoot = true;\n continue;\n }\n if (t === \"-C\" || t === \"--dir\") {\n state.dirOverride = subTokens[++i];\n continue;\n }\n if (t.startsWith(\"-C=\") || t.startsWith(\"--dir=\")) {\n state.dirOverride = t.split(\"=\", 2)[1];\n continue;\n }\n if (t.startsWith(\"-\") && !PNPM_BUILTINS.has(t)) continue;\n return { name: t };\n }\n return { name: void 0 };\n}\nfunction evaluatePnpm(tokens, ctx) {\n const subTokens = tokens.slice(1);\n const state = {\n isRecursive: false,\n isWorkspaceRoot: false,\n dirOverride: void 0\n };\n const scan = scanPnpmFlags(subTokens, 0, state);\n if (scan.filterIdx !== void 0) return evaluatePnpmFilter(tokens, subTokens, scan.filterIdx, ctx);\n const subcommand = scan.name;\n const subcommandIdx = subcommand ? subTokens.indexOf(subcommand) : -1;\n if (!subcommand) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (subcommand === \"dlx\") return {\n action: \"none\",\n rule: null,\n reason: \"pnpm dlx\"\n };\n if (subcommand === \"add\") return {\n action: \"none\",\n rule: null,\n reason: \"pnpm add\"\n };\n if (subcommand === \"exec\") {\n const execArgs = subTokens.slice(subcommandIdx + 1);\n if (execArgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"bare pnpm exec\"\n };\n return evaluateCommand(joinTokens(execArgs), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n let scriptName;\n let { isRecursive, isWorkspaceRoot, dirOverride } = state;\n if (subcommand === \"run\") {\n const runScan = scanPnpmFlags(subTokens, subcommandIdx + 1, state);\n ({isRecursive, isWorkspaceRoot, dirOverride} = state);\n if (runScan.filterIdx !== void 0) return evaluatePnpmFilter(tokens, subTokens, runScan.filterIdx, ctx);\n if (!runScan.name) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm run without script name\"\n };\n scriptName = runScan.name;\n } else if (!PNPM_BUILTINS.has(subcommand)) scriptName = subcommand;\n else return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (isRecursive) return evaluatePnpmRecursive(scriptName, ctx);\n if (isWorkspaceRoot) {\n const root = findWorkspaceRoot(ctx.cwd);\n if (!root) return {\n action: \"none\",\n rule: null,\n reason: \"workspace root not found\"\n };\n return evaluatePnpmScript(scriptName, {\n ...ctx,\n cwd: root\n });\n }\n if (dirOverride) {\n const resolved = path.resolve(ctx.cwd, dirOverride);\n return evaluatePnpmScript(scriptName, {\n ...ctx,\n cwd: resolved\n });\n }\n return evaluatePnpmScript(scriptName, ctx);\n}\nfunction evaluatePnpmScript(scriptName, ctx) {\n const resolved = resolveScript(scriptName, ctx.cwd);\n if (!resolved) return {\n action: \"none\",\n rule: null,\n reason: \"script resolution failed\"\n };\n const res = evaluateResolvedScript(resolved, {\n ...ctx,\n depth: ctx.depth + 1\n });\n if (res.action === \"deny\") return res;\n return {\n action: \"none\",\n rule: `pnpm-script:${scriptName}`,\n reason: null\n };\n}\nfunction evaluatePnpmRecursive(scriptName, ctx) {\n const resolved = resolveRecursiveScripts(scriptName, ctx.cwd);\n if (!resolved || resolved.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm recursive\"\n };\n for (const pkg of resolved) {\n const res = evaluateResolvedScript(pkg, {\n ...ctx,\n depth: ctx.depth + 1,\n cwd: pkg.pkgDir ?? ctx.cwd\n });\n if (res.action === \"deny\") return res;\n }\n return {\n action: \"none\",\n rule: `pnpm-recursive:${scriptName}`,\n reason: null\n };\n}\nfunction evaluateNpm(tokens) {\n if (isNpmReadOp(tokens)) return {\n action: \"none\",\n rule: null,\n reason: null\n };\n return {\n action: \"deny\",\n rule: \"npm-redirect\",\n reason: getNpmRedirectReason(tokens)\n };\n}\nfunction evaluatePnpmFilter(_tokens, subTokens, filterIdx, ctx) {\n const filterPkgs = [];\n let cursor = filterIdx;\n while (cursor < subTokens.length) {\n const t = subTokens[cursor];\n if (t === \"--filter\" || t === \"-F\") {\n const pkg = subTokens[cursor + 1];\n if (!pkg || pkg.startsWith(\"-\")) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n filterPkgs.push(pkg);\n cursor += 2;\n } else if (t.startsWith(\"--filter=\") || t.startsWith(\"-F=\")) {\n const pkg = t.startsWith(\"-F=\") ? t.slice(3) : t.slice(9);\n if (!pkg) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n filterPkgs.push(pkg);\n cursor += 1;\n } else break;\n }\n if (filterPkgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without package\"\n };\n let filterSubcommand;\n let subcmdIdx = -1;\n for (let i = cursor; i < subTokens.length; i++) {\n const t = subTokens[i];\n if (t === \"--filter\" || t === \"-F\") {\n i += 1;\n continue;\n }\n if (t.startsWith(\"--filter=\") || t.startsWith(\"-F=\")) continue;\n if (t.startsWith(\"-\") && !PNPM_BUILTINS.has(t)) continue;\n filterSubcommand = t;\n subcmdIdx = i;\n break;\n }\n if (!filterSubcommand) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter without subcommand\"\n };\n if (PNPM_BUILTINS.has(filterSubcommand) && filterSubcommand !== \"run\" && filterSubcommand !== \"exec\") return {\n action: \"none\",\n rule: null,\n reason: null\n };\n if (filterSubcommand === \"exec\") {\n const execArgs = subTokens.slice(subcmdIdx + 1);\n if (execArgs.length === 0) return {\n action: \"none\",\n rule: null,\n reason: \"bare pnpm exec\"\n };\n return evaluateCommand(joinTokens(execArgs), {\n ...ctx,\n depth: ctx.depth + 1\n });\n }\n const scriptName = filterSubcommand === \"run\" ? subTokens[subcmdIdx + 1] : filterSubcommand;\n if (!scriptName || scriptName.startsWith(\"-\")) return {\n action: \"none\",\n rule: null,\n reason: \"pnpm --filter run without script name\"\n };\n if (PNPM_BUILTINS.has(scriptName) && scriptName !== \"run\") return {\n action: \"none\",\n rule: null,\n reason: null\n };\n for (const pkg of filterPkgs) {\n const resolved = resolveFilteredScript(scriptName, pkg, ctx.cwd);\n if (!resolved) return {\n action: \"none\",\n rule: null,\n reason: \"filtered script resolution failed\"\n };\n const res = evaluateResolvedScript(resolved, {\n ...ctx,\n depth: ctx.depth + 1,\n cwd: resolved.pkgDir ?? ctx.cwd\n });\n if (res.action === \"deny\") return res;\n }\n return {\n action: \"none\",\n rule: `pnpm-filter:${filterPkgs.join(\",\")}:${scriptName}`,\n reason: null\n };\n}\nconst SHELL_LOGIN_FLAGS = /* @__PURE__ */ new Set([\"-l\", \"--login\"]);\nfunction evaluateShellC(tokens, ctx) {\n let i = 1;\n while (i < tokens.length && SHELL_LOGIN_FLAGS.has(tokens[i])) i++;\n const flag = tokens[i];\n if (flag === void 0 || !/^-[lc]+$/.test(flag) || !flag.includes(\"c\")) return {\n action: \"none\",\n rule: null,\n reason: \"shell without a plain -c\"\n };\n const cmdArg = tokens[i + 1];\n if (!cmdArg) return {\n action: \"none\",\n rule: null,\n reason: \"shell -c without command\"\n };\n if (tokens.length > i + 2) return {\n action: \"none\",\n rule: null,\n reason: \"shell -c with positional args\"\n };\n return evaluateCommand(cmdArg, {\n ...ctx,\n depth: ctx.depth + 1\n });\n}\nconst XARGS_ARG_FLAGS = /* @__PURE__ */ new Set([\n \"-I\",\n \"-d\",\n \"-n\",\n \"-P\",\n \"-s\",\n \"-L\",\n \"-E\",\n \"-a\",\n \"--max-args\",\n \"--max-procs\",\n \"--delimiter\",\n \"--replace\",\n \"--max-lines\",\n \"--max-chars\",\n \"--arg-file\",\n \"--process-slot-var\"\n]);\nconst XARGS_BOOL_FLAGS = /* @__PURE__ */ new Set([\n \"-0\",\n \"--null\",\n \"-t\",\n \"--verbose\",\n \"-r\",\n \"--no-run-if-empty\",\n \"-p\",\n \"--interactive\",\n \"-x\",\n \"--exit\",\n \"--show-limits\"\n]);\nfunction evaluateXargs(tokens, ctx) {\n let i = 1;\n while (i < tokens.length) {\n const t = tokens[i];\n if (!t.startsWith(\"-\")) break;\n if (XARGS_ARG_FLAGS.has(t)) {\n i += 2;\n continue;\n }\n const eqIdx = t.indexOf(\"=\");\n if (eqIdx !== -1) {\n const flagName = t.slice(0, eqIdx);\n if (XARGS_ARG_FLAGS.has(flagName)) {\n i++;\n continue;\n }\n }\n if (t.length > 2 && XARGS_ARG_FLAGS.has(t.slice(0, 2))) {\n i++;\n continue;\n }\n if (XARGS_BOOL_FLAGS.has(t)) {\n i++;\n continue;\n }\n return {\n action: \"none\",\n rule: null,\n reason: \"xargs with unrecognised flags\"\n };\n }\n if (i >= tokens.length) return {\n action: \"none\",\n rule: null,\n reason: \"xargs without command\"\n };\n return evaluateCommand(joinTokens(tokens.slice(i)), {\n ...ctx,\n depth: ctx.depth + 1\n });\n}\n\n//#endregion\n//#region src/file-rules.ts\nconst READ_TOOLS = /* @__PURE__ */ new Set([\n \"Read\",\n \"Glob\",\n \"Grep\"\n]);\nconst WRITE_TOOLS = /* @__PURE__ */ new Set([\"Write\", \"Edit\"]);\nconst fileDenyRules = [\n {\n name: \"env-file-read\",\n tools: READ_TOOLS,\n action: \"deny\",\n when: (filePath) => isEnvFile(filePath),\n reason: \"Don't read .env files. These contain secrets that should not appear in the conversation.\"\n },\n {\n name: \"env-file-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath) => isEnvFile(filePath),\n reason: \"Don't write to .env files. These contain secrets.\"\n },\n {\n name: \"hooks-folder-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n const hooksDir = path.join(ctx.cwd, \".claude\", \"hooks\");\n return isWithin(hooksDir, resolved);\n },\n reason: \"Don't write to .claude/hooks/. These files are managed by the project and should not be modified directly.\"\n },\n {\n name: \"git-dir-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => targetsGitDir(filePath, ctx.cwd),\n reason: \"Don't write into .git/ directly. Its internals (config, hooks, refs) are not plain project files -- a config edit can redirect remotes or push destinations that other rules trust, and a hooks/ script runs automatically on the next commit/push. Use git subcommands instead, or ask the user.\"\n },\n {\n name: \"node-modules-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => targetsNodeModules(filePath, ctx.cwd),\n reason: \"Don't write into node_modules/. Its files are hardlinks into pnpm's global store -- editing one in place corrupts that package for every project on this machine. Edit the source package and rebuild, or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`).\"\n },\n {\n name: \"claude-settings-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n return samePath(resolved, path.join(ctx.cwd, \".claude\", \"settings.json\"));\n },\n reason: \"Don't write to .claude/settings.json. This file is managed by the project and should not be modified directly.\"\n },\n {\n name: \"health-baseline-write\",\n tools: WRITE_TOOLS,\n action: \"deny\",\n when: (filePath, ctx, toolInput) => {\n const resolved = resolveIn(ctx.cwd, filePath);\n if (path.basename(resolved) !== \"health-baseline.json\") return false;\n const root = getRepoTopLevel(ctx.cwd) ?? ctx.cwd;\n if (!samePath(resolved, path.join(root, \"health-baseline.json\"))) return false;\n if (!writeRaisesBaseline(resolved, toolInput)) return false;\n return branchCarriesOtherFiles(ctx.cwd, HEALTH_CEILING_FILES) === true;\n },\n reason: HEALTH_RAISE_REASON\n }\n];\nfunction writeRaisesBaseline(file, toolInput) {\n let before;\n try {\n before = readFileSync(file, \"utf8\");\n } catch (_error) {\n return false;\n }\n const after = textAfterWrite(before, toolInput);\n if (after === void 0) return false;\n const beforeJson = parseJson(before);\n const afterJson = parseJson(after);\n if (beforeJson === void 0 || afterJson === void 0) return false;\n return numberRises(beforeJson, afterJson);\n}\nfunction textAfterWrite(before, toolInput) {\n const { content, old_string: oldText, new_string: newText, replace_all: all } = toolInput;\n if (typeof content === \"string\") return content;\n if (typeof oldText !== \"string\" || typeof newText !== \"string\" || oldText === \"\") return void 0;\n const at = before.indexOf(oldText);\n if (at === -1) return void 0;\n if (all === true) return before.split(oldText).join(newText);\n return before.slice(0, at) + newText + before.slice(at + oldText.length);\n}\nfunction parseJson(text) {\n try {\n const result = record(string(), unknown()).safeParse(JSON.parse(text));\n return result.success ? result.data : void 0;\n } catch (_error) {\n return;\n }\n}\nfunction numberRises(before, after) {\n if (typeof after === \"number\") return typeof before !== \"number\" || after > before;\n if (typeof after !== \"object\" || after === null) return false;\n const beforeObject = typeof before === \"object\" && before !== null ? before : {};\n return Object.entries(after).some(([key, value]) => numberRises(Object.entries(beforeObject).find(([k]) => k === key)?.[1], value));\n}\n\n//#endregion\n//#region src/evaluate-tool.ts\nconst FILE_PATH_TOOLS = /* @__PURE__ */ new Set([\n \"Read\",\n \"Write\",\n \"Edit\"\n]);\nconst SEARCH_TOOLS = /* @__PURE__ */ new Set([\"Glob\", \"Grep\"]);\nfunction extractPath(toolName, toolInput, cwd) {\n if (FILE_PATH_TOOLS.has(toolName)) return parseFilePathInput(toolInput)?.file_path ?? null;\n if (SEARCH_TOOLS.has(toolName)) return parseSearchInput(toolInput)?.path ?? cwd;\n return null;\n}\nfunction evaluateToolUse(toolName, toolInput, ctx) {\n const filePath = extractPath(toolName, toolInput, ctx.cwd);\n if (filePath === null) return {\n action: \"none\",\n rule: null,\n reason: \"unknown tool input shape\"\n };\n for (const rule of fileDenyRules) if (rule.tools.has(toolName) && rule.when(filePath, ctx, toolInput)) return {\n action: \"deny\",\n rule: rule.name,\n reason: rule.reason ?? null\n };\n return {\n action: \"none\",\n rule: null,\n reason: \"no file rule matched\"\n };\n}\n\n//#endregion\n//#region src/lib/settings.ts\nconst SETTINGS_PATH = \".claude/hooks/bst-hook.settings.json\";\nconst BstHookSettingsSchema = object({ protectedBranches: _default(array(string().check(_minLength(1))), []) });\nfunction isFileClean(cwd, relativePath) {\n try {\n execFileSync(\"git\", [\n \"ls-files\",\n \"--error-unmatch\",\n relativePath\n ], {\n cwd,\n stdio: \"ignore\"\n });\n execFileSync(\"git\", [\n \"diff\",\n \"--quiet\",\n \"HEAD\",\n \"--\",\n relativePath\n ], {\n cwd,\n stdio: \"ignore\"\n });\n return true;\n } catch {\n return false;\n }\n}\nfunction loadRepoSettings(cwd) {\n const root = findWorkspaceRoot(cwd) ?? cwd;\n const settingsFile = join(root, SETTINGS_PATH);\n const empty = { protectedBranches: [] };\n if (!existsSync(settingsFile)) return empty;\n if (!isFileClean(root, SETTINGS_PATH)) return empty;\n try {\n const raw = readFileSync(settingsFile, \"utf-8\");\n const parsed = JSON.parse(raw);\n const result = BstHookSettingsSchema.safeParse(parsed);\n if (!result.success) return empty;\n return { protectedBranches: result.data.protectedBranches };\n } catch {\n return empty;\n }\n}\n\n//#endregion\n//#region src/index.ts\nconst inputResult = await readHookInput();\nif (!inputResult.ok) {\n process.stderr.write(`[bst-hook] invalid hook input: ${inputResult.error}\\n`);\n audit({\n sessionId: \"unknown\",\n cwd: \"unknown\",\n command: `<invalid input: ${inputResult.error}>`,\n decision: \"none\",\n rule: null,\n reason: `validation failed: ${inputResult.error}`,\n permissionMode: void 0\n });\n process.exit(0);\n}\nconst input = inputResult.data;\nif (input.hook_event_name !== \"PreToolUse\") process.exit(0);\nif (!(/* @__PURE__ */ new Set([\n \"Bash\",\n \"Read\",\n \"Write\",\n \"Edit\",\n \"Glob\",\n \"Grep\"\n])).has(input.tool_name)) process.exit(0);\nconst repoSettings = loadRepoSettings(input.cwd);\nlet decision;\nlet auditCommand;\nif (input.tool_name === \"Bash\") {\n const bashInput = parseBashInput(input.tool_input);\n if (!bashInput) {\n audit({\n sessionId: input.session_id,\n cwd: input.cwd,\n toolName: input.tool_name,\n command: `<invalid Bash input: ${JSON.stringify(input.tool_input).slice(0, 200)}>`,\n decision: \"none\",\n rule: null,\n reason: \"Bash tool_input missing or invalid 'command' field\",\n permissionMode: input.permission_mode\n });\n process.exit(0);\n }\n decision = evaluateCommand(bashInput.command, {\n cwd: input.cwd,\n depth: 0,\n repoProtectedBranches: repoSettings.protectedBranches\n });\n auditCommand = bashInput.command;\n} else {\n const projectDir = findWorkspaceRoot(input.cwd) ?? process.env[\"CLAUDE_PROJECT_DIR\"] ?? input.cwd;\n decision = evaluateToolUse(input.tool_name, input.tool_input, {\n cwd: projectDir,\n sessionId: input.session_id\n });\n const filePath = String(input.tool_input[\"file_path\"] ?? input.tool_input[\"path\"] ?? \"\");\n auditCommand = `${input.tool_name} ${filePath}`;\n}\naudit({\n sessionId: input.session_id,\n cwd: input.cwd,\n toolName: input.tool_name,\n command: auditCommand,\n decision: decision.action,\n rule: decision.rule,\n reason: decision.reason,\n permissionMode: input.permission_mode\n});\nif (decision.action === \"deny\") writeDeny(decision.reason);\nelse if (decision.advice) writeAdvice(decision.advice);\n\n//#endregion\nexport { };",
|
|
8201
8268
|
guide: "# bst-hook Permission Guide\n\nThis project uses a PreToolUse hook (`bst-hook`) that checks each Bash command\nand file tool call before it runs. The hook only ever blocks a command; it does\nnot approve anything on its own. A command that matches a rule below is denied,\nwith a message that says what to do instead.\n\n## Denied commands\n\nThese are blocked. The hook tells you what to do instead.\n\n### Bash\n\n- **sudo**: Don't use sudo. If you need elevated permissions, ask me to do it manually.\n- **git-force-push**: Use `git push --force-with-lease` instead of `--force`.\n- **git-protected-branch-write**: This would move a protected branch (main, master, the remote's default branch, or one listed in .claude/hooks/bst-hook.settings.json#protectedBranches). Work on a feature branch in a worktree: `git worktree add ../<repo>-<topic> -b feat/<topic>`, then commit and push there. To bring `main` up to date, use `git pull --ff-only`.\n- **chmod-777**: Don't use 777 permissions. Use more restrictive permissions.\n- **node-modules-write**: Don't write into node_modules/. Its files are hardlinks into pnpm's global store, so overwriting one in place (plain `cp`, `>` redirect, `sed -i`, ...) writes through the link and corrupts that package for every project on this machine -- silently, since the directory you wrote into ends up fine. To test a local build as an installed dependency, run it directly (`node packages/<pkg>/dist/bin.mjs <cmd>`), or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`). If you must replace a file in place, `cp --remove-destination` is safe -- it unlinks the target first. Run `pnpm store status` to check whether the store is already damaged.\n- **env-file-read**: Don't read .env files. These contain secrets that should not appear in the conversation.\n- **env-file-write**: Don't write to .env files. These contain secrets.\n- **health-baseline-write**: A health ceiling raise travels alone: open a ceiling-only pull request -- only health-baseline.json and .tooling.json changed -- for a human to merge, or split the module. `bst health:check` refuses the raise beside code either way. To restore the default branch's copy run `git show origin/<default>:health-baseline.json > health-baseline.json`, and to adopt lower counts run `bst health:check --update-baseline`.\n- **health-baseline-reset**: A health ceiling raise travels alone: open a ceiling-only pull request -- only health-baseline.json and .tooling.json changed -- for a human to merge, or split the module. `bst health:check` refuses the raise beside code either way. To restore the default branch's copy run `git show origin/<default>:health-baseline.json > health-baseline.json`, and to adopt lower counts run `bst health:check --update-baseline`.\n- **npx-redirect**: This project uses pnpm. Use `pnpm dlx <pkg>` or `pnpm exec <cmd>` instead of npx.\n- **mise-self-update**: Don't self-update mise. The version is Renovate-managed; ask a human to bump the pin.\n\n### File tools (Read, Write, Edit, Glob, Grep)\n\n- **env-file-read**: Don't read .env files. These contain secrets that should not appear in the conversation.\n- **env-file-write**: Don't write to .env files. These contain secrets.\n- **hooks-folder-write**: Don't write to .claude/hooks/. These files are managed by the project and should not be modified directly.\n- **git-dir-write**: Don't write into .git/ directly. Its internals (config, hooks, refs) are not plain project files -- a config edit can redirect remotes or push destinations that other rules trust, and a hooks/ script runs automatically on the next commit/push. Use git subcommands instead, or ask the user.\n- **node-modules-write**: Don't write into node_modules/. Its files are hardlinks into pnpm's global store -- editing one in place corrupts that package for every project on this machine. Edit the source package and rebuild, or install into a scratch tree with an isolated store (`pnpm add --store-dir <scratch> <pkg>`).\n- **claude-settings-write**: Don't write to .claude/settings.json. This file is managed by the project and should not be modified directly.\n- **health-baseline-write**: A health ceiling raise travels alone: open a ceiling-only pull request -- only health-baseline.json and .tooling.json changed -- for a human to merge, or split the module. `bst health:check` refuses the raise beside code either way. To restore the default branch's copy run `git show origin/<default>:health-baseline.json > health-baseline.json`, and to adopt lower counts run `bst health:check --update-baseline`.\n\n## How commands are evaluated\n\n- **Pipelines and chains**: every segment is checked; a deny on any segment blocks the whole command.\n- **pnpm scripts**: `pnpm <script>` resolves against `package.json` (including pre/post hooks and `--filter` workspaces) and evaluates the resolved command recursively.\n- **cd propagation**: `cd dir && cmd` evaluates `cmd` relative to the new directory.\n- **Branch switch propagation**: `git switch <branch> && cmd` (or `git checkout <branch>`) evaluates a git write in `cmd` against the branch it switched to, not the one checked out before. This holds only across `&&` and only in the same directory.\n- **Audit log**: all decisions are logged to `.claude/hooks/bst-hook.audit.local.jsonl`.\n\n## Everything else\n\nA command that matches none of the rules above is judged by Claude Code's own\nauto mode, not by this hook.\n"
|
|
8202
8269
|
}) {
|
|
8203
8270
|
const results = [{
|
|
@@ -9117,7 +9184,7 @@ const COMMENTS_GUIDE_BODY = [
|
|
|
9117
9184
|
"",
|
|
9118
9185
|
"- Default to none. A comment earns its place by carrying what the code cannot -- a rejected alternative, the bug that forced this shape, an invariant enforced elsewhere -- and earns it one decision at a time, in a sentence or two each: what was rejected, and what it cost. Five decisions is five sentences, not five paragraphs. Recoverable from the code? Leave it unwritten.",
|
|
9119
9186
|
"- Present tense, about what is. No `now`, `previously`, `changed to`: diff narration is stale on the next edit, and the commit message carries it. No running ledgers or changelogs: when adjusting a threshold, constant, or baseline, state the active invariant and prune past deltas.",
|
|
9120
|
-
"- Never cite a lifecycle-managed doc, PR, or issue from code: no PR or issue numbers (`PR #123`, `closes #456`), no path under `docs/superpowers/` or `docs/design/`, none carrying a `retired/` or `completed/` segment, no `docs/plan-*.md`, and no bare decision or task ID (`D3`, `T2`). They move, retire, and renumber, nothing checks the reference, and the reader has no way to tell a dead one from a live one. State the constraint itself, or cite a maintained reference doc instead. A `docs/` path that is a glob or an elided example rather than a reference (`docs/*.md`) is vocabulary, not a citation, and is fine.",
|
|
9187
|
+
"- Never cite a lifecycle-managed doc, PR, or issue from code: no PR or issue numbers (`PR #123`, `closes #456`), no path under `docs/specs/`, `docs/plans/`, `docs/superpowers/` or `docs/design/`, none carrying a `retired/` or `completed/` segment, no `docs/plan-*.md`, and no bare decision or task ID (`D3`, `T2`). They move, retire, and renumber, nothing checks the reference, and the reader has no way to tell a dead one from a live one. State the constraint itself, or cite a maintained reference doc instead. A `docs/` path that is a glob or an elided example rather than a reference (`docs/*.md`) is vocabulary, not a citation, and is fine.",
|
|
9121
9188
|
"- Code that exists only to accept an older shape -- a file, field, flag, environment variable, label or comment format -- carries `// @compat <id> until <expiry>: <reason>` on the line above it. The expiry is a date (`YYYY-MM-DD`) when the old shape lives with consumers who upgrade on their own schedule; a version of the code's own package (`v1.4.0`) when its consumer upgrades with each release; or `forge-clean` for old data on the forge, which has neither. Remove the code and every test that carries the same id together.",
|
|
9122
9189
|
"- **The code is the fact.** When a comment disagrees with it, fix it in one line or delete it -- never grow one to argue the code is right."
|
|
9123
9190
|
].join("\n");
|
|
@@ -9179,7 +9246,7 @@ const PLAN_LIFECYCLE_GUIDE_BODY = [
|
|
|
9179
9246
|
"",
|
|
9180
9247
|
"A plan's **directory** is the source of truth for whether it shipped -- not its `Status:` line, not its checkboxes. Read the source it names.",
|
|
9181
9248
|
"",
|
|
9182
|
-
"`.superpowers/` (no `docs/` prefix) is scratch state, not a plan's home -- a plan doc
|
|
9249
|
+
"`.superpowers/` (no `docs/` prefix) is scratch state, not a plan's home -- a plan doc lives under `docs/plans/` (older ones under `docs/superpowers/plans/`), even one drafted while running a plan through subagents.",
|
|
9183
9250
|
"",
|
|
9184
9251
|
"Retiring the plan is the last task of the plan, done in the PR that delivers the work: \"in the tree\" means committed on this branch, not merged to a default branch. Run `bst docs:retire <plan.md> --status <verb> --shipped \"<text>\"` -- it moves the doc, relinks what the move breaks, de-links paths pointing outside `docs/`, and writes the dated terminal `Status:` line, the historical banner, and the \"Shipped:\" paragraph. You supply the judgement: the honest verb -- `completed` / `superseded` / `abandoned` / `rejected` -- and a truthful `--shipped` naming the delivering PR; never fabricate it for uncommitted code or claim a merge that has not happened. A plan that lands one phase of a larger spec retires the plan and leaves the spec open.",
|
|
9185
9252
|
"",
|
|
@@ -9196,11 +9263,11 @@ const PLANNING_GUIDE_BODY = [
|
|
|
9196
9263
|
"",
|
|
9197
9264
|
"## The spec",
|
|
9198
9265
|
"",
|
|
9199
|
-
"Say why and what, not how: the problem, who it is for, the constraints, what done looks like, and the alternatives you rejected, each with its reason. Work with several independent parts gets one spec per part. Save it as `docs/
|
|
9266
|
+
"Say why and what, not how: the problem, who it is for, the constraints, what done looks like, and the alternatives you rejected, each with its reason. Work with several independent parts gets one spec per part. Save it as `docs/specs/<YYYY-MM-DD>-<topic>-design.md`.",
|
|
9200
9267
|
"",
|
|
9201
9268
|
"## The plan",
|
|
9202
9269
|
"",
|
|
9203
|
-
"Write for an executor who has not seen this repo or the spec. They write idiomatic code once they know the exact interface and the exact test, and make a reasonable choice wherever the plan leaves one open; what they cannot know is what you decided. A plan records those decisions -- it is not a transcript of the code. Save it under `docs/
|
|
9270
|
+
"Write for an executor who has not seen this repo or the spec. They write idiomatic code once they know the exact interface and the exact test, and make a reasonable choice wherever the plan leaves one open; what they cannot know is what you decided. A plan records those decisions -- it is not a transcript of the code. Save it under `docs/plans/`.",
|
|
9204
9271
|
"",
|
|
9205
9272
|
"- Check the plan's premises against the tree before building on them. \"Today X is broken\" is a claim: read the code that handles X, not just the line that throws.",
|
|
9206
9273
|
"- Label each task `Task <n>:` at the start of its heading or checkbox, numbered from 1, so `bst plan:brief` can find it. A checkbox's first sentence is the task's name on the control panel: end it with a period inside one short line, and put the files, commands, and checks in the sentences after it.",
|
|
@@ -9269,18 +9336,18 @@ function webUiGuideBody() {
|
|
|
9269
9336
|
"@types/node": "24.19.1",
|
|
9270
9337
|
"@vitest/coverage-v8": "5.0.3",
|
|
9271
9338
|
"commit-and-tag-version": "13.2.1",
|
|
9272
|
-
"knip": "6.
|
|
9273
|
-
"lefthook": "2.1
|
|
9274
|
-
"modern-web-guidance": "0.0.
|
|
9275
|
-
"oxfmt": "0.
|
|
9276
|
-
"oxlint": "1.
|
|
9339
|
+
"knip": "6.41.0",
|
|
9340
|
+
"lefthook": "2.2.1",
|
|
9341
|
+
"modern-web-guidance": "0.0.193",
|
|
9342
|
+
"oxfmt": "0.72.0",
|
|
9343
|
+
"oxlint": "1.87.0",
|
|
9277
9344
|
"oxlint-tsgolint": "7.0.2003",
|
|
9278
9345
|
"prettier": "3.9.9",
|
|
9279
|
-
"release-it": "21.1.
|
|
9346
|
+
"release-it": "21.1.1",
|
|
9280
9347
|
"tsdown": "0.23.0",
|
|
9281
9348
|
"typescript": "6.0.3",
|
|
9282
9349
|
"vitest": "5.0.3",
|
|
9283
|
-
"pnpm": "11.28.
|
|
9350
|
+
"pnpm": "11.28.5"
|
|
9284
9351
|
}["modern-web-guidance"]}`;
|
|
9285
9352
|
return [
|
|
9286
9353
|
"# Web UI",
|
|
@@ -9840,7 +9907,7 @@ function reportFailures(failed, command) {
|
|
|
9840
9907
|
function generateMigratePrompt(results, config, detected) {
|
|
9841
9908
|
const sections = [];
|
|
9842
9909
|
const timestamp = (/* @__PURE__ */ new Date()).toISOString();
|
|
9843
|
-
sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.
|
|
9910
|
+
sections.push(`# Migration Prompt\n\n_Generated by \`@bensandee/tooling@0.90.0 repo:sync\` on ${timestamp}_\n`);
|
|
9844
9911
|
const changed = results.filter((r) => r.action === "created" || r.action === "updated" || r.action === "archived");
|
|
9845
9912
|
if (changed.length > 0) {
|
|
9846
9913
|
const items = changed.map((r) => {
|
|
@@ -10693,129 +10760,6 @@ function groupSkippedSteps(steps, defined, flagSkip, configSkip) {
|
|
|
10693
10760
|
}));
|
|
10694
10761
|
}
|
|
10695
10762
|
//#endregion
|
|
10696
|
-
//#region ../forgejo/src/git.ts
|
|
10697
|
-
const GIT_LOCAL_TIMEOUT_MS = 6e4;
|
|
10698
|
-
const GIT_WRITE_TIMEOUT_MS = 3e5;
|
|
10699
|
-
function pickDefaultBranch(override, originHead) {
|
|
10700
|
-
if (override !== void 0 && override !== "") return override;
|
|
10701
|
-
if (originHead !== void 0) {
|
|
10702
|
-
const name = originHead.startsWith("origin/") ? originHead.slice(7) : originHead;
|
|
10703
|
-
if (name !== "") return name;
|
|
10704
|
-
}
|
|
10705
|
-
return "main";
|
|
10706
|
-
}
|
|
10707
|
-
async function resolveOriginHead(git, cwd, signal = null) {
|
|
10708
|
-
const result = await git.run([
|
|
10709
|
-
"symbolic-ref",
|
|
10710
|
-
"--short",
|
|
10711
|
-
"refs/remotes/origin/HEAD"
|
|
10712
|
-
], {
|
|
10713
|
-
cwd,
|
|
10714
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10715
|
-
signal
|
|
10716
|
-
});
|
|
10717
|
-
if (result.exitCode !== 0) return void 0;
|
|
10718
|
-
const out = result.stdout.trim();
|
|
10719
|
-
return out === "" ? void 0 : out;
|
|
10720
|
-
}
|
|
10721
|
-
async function currentBranch(git, cwd, signal = null) {
|
|
10722
|
-
const result = await git.run([
|
|
10723
|
-
"rev-parse",
|
|
10724
|
-
"--abbrev-ref",
|
|
10725
|
-
"HEAD"
|
|
10726
|
-
], {
|
|
10727
|
-
cwd,
|
|
10728
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10729
|
-
signal
|
|
10730
|
-
});
|
|
10731
|
-
const branch = result.stdout.trim();
|
|
10732
|
-
if (result.exitCode !== 0 || branch === "") throw new FatalError("Could not determine the current branch -- is this a git repository?");
|
|
10733
|
-
if (branch === "HEAD") throw new FatalError("HEAD is detached. Check out a feature branch first.");
|
|
10734
|
-
return branch;
|
|
10735
|
-
}
|
|
10736
|
-
async function baseRef(git, cwd, base, signal = null) {
|
|
10737
|
-
const remote = `origin/${base}`;
|
|
10738
|
-
const result = await git.run([
|
|
10739
|
-
"rev-parse",
|
|
10740
|
-
"--verify",
|
|
10741
|
-
"--quiet",
|
|
10742
|
-
remote
|
|
10743
|
-
], {
|
|
10744
|
-
cwd,
|
|
10745
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10746
|
-
signal
|
|
10747
|
-
});
|
|
10748
|
-
return result.exitCode === 0 && result.stdout.trim() !== "" ? remote : base;
|
|
10749
|
-
}
|
|
10750
|
-
async function commitSubjects(git, cwd, ref, signal = null) {
|
|
10751
|
-
return (await git.run([
|
|
10752
|
-
"log",
|
|
10753
|
-
"--format=%s",
|
|
10754
|
-
`${ref}..HEAD`
|
|
10755
|
-
], {
|
|
10756
|
-
cwd,
|
|
10757
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10758
|
-
signal
|
|
10759
|
-
})).stdout.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
10760
|
-
}
|
|
10761
|
-
async function commitMessages(git, cwd, ref, signal = null) {
|
|
10762
|
-
const result = await git.run([
|
|
10763
|
-
"log",
|
|
10764
|
-
"-z",
|
|
10765
|
-
"--format=%B",
|
|
10766
|
-
`${ref}..HEAD`
|
|
10767
|
-
], {
|
|
10768
|
-
cwd,
|
|
10769
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10770
|
-
signal
|
|
10771
|
-
});
|
|
10772
|
-
if (result.exitCode !== 0) throw new FatalError(`Failed to read commit messages: ${result.stderr || result.stdout}`);
|
|
10773
|
-
return result.stdout.split("\0").map((message) => message.trim()).filter((message) => message !== "");
|
|
10774
|
-
}
|
|
10775
|
-
async function hasUncommittedChanges(git, cwd, signal = null) {
|
|
10776
|
-
return (await git.run(["status", "--porcelain"], {
|
|
10777
|
-
cwd,
|
|
10778
|
-
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
10779
|
-
signal
|
|
10780
|
-
})).stdout.trim() !== "";
|
|
10781
|
-
}
|
|
10782
|
-
async function pushBranch(git, cwd, branch, env, forceWithLease = false) {
|
|
10783
|
-
const pushArgs = forceWithLease ? [
|
|
10784
|
-
"push",
|
|
10785
|
-
"--force-with-lease",
|
|
10786
|
-
"-u",
|
|
10787
|
-
"origin",
|
|
10788
|
-
branch
|
|
10789
|
-
] : [
|
|
10790
|
-
"push",
|
|
10791
|
-
"-u",
|
|
10792
|
-
"origin",
|
|
10793
|
-
branch
|
|
10794
|
-
];
|
|
10795
|
-
const result = await git.run(pushArgs, env === void 0 ? {
|
|
10796
|
-
cwd,
|
|
10797
|
-
timeoutMs: GIT_WRITE_TIMEOUT_MS,
|
|
10798
|
-
signal: null
|
|
10799
|
-
} : {
|
|
10800
|
-
cwd,
|
|
10801
|
-
env,
|
|
10802
|
-
timeoutMs: GIT_WRITE_TIMEOUT_MS,
|
|
10803
|
-
signal: null
|
|
10804
|
-
});
|
|
10805
|
-
if (result.exitCode !== 0) throw new FatalError(`Failed to push ${branch}: ${result.stderr || result.stdout}`);
|
|
10806
|
-
}
|
|
10807
|
-
//#endregion
|
|
10808
|
-
//#region src/utils/branch.ts
|
|
10809
|
-
function resolveDefaultBranch(options) {
|
|
10810
|
-
const override = options.configOverride;
|
|
10811
|
-
if (override !== void 0 && override !== "") return pickDefaultBranch(override, void 0);
|
|
10812
|
-
return pickDefaultBranch(void 0, (options.git ?? defaultGitRunner)([
|
|
10813
|
-
"symbolic-ref",
|
|
10814
|
-
"--short",
|
|
10815
|
-
"refs/remotes/origin/HEAD"
|
|
10816
|
-
], options.cwd));
|
|
10817
|
-
}
|
|
10818
|
-
//#endregion
|
|
10819
10763
|
//#region src/codebase-health/executor.ts
|
|
10820
10764
|
function createRealHealthExecutor(rootDir) {
|
|
10821
10765
|
return {
|
|
@@ -10910,6 +10854,34 @@ function repoPrefix(executor, cwd) {
|
|
|
10910
10854
|
function ceilingFileNamesAt(prefix) {
|
|
10911
10855
|
return HEALTH_CEILING_FILES.map((name) => `${prefix}${name}`);
|
|
10912
10856
|
}
|
|
10857
|
+
function processCiEventSource() {
|
|
10858
|
+
return {
|
|
10859
|
+
env: process.env,
|
|
10860
|
+
readFile: (absolutePath) => {
|
|
10861
|
+
try {
|
|
10862
|
+
return readFileSync(absolutePath, "utf-8");
|
|
10863
|
+
} catch (_error) {
|
|
10864
|
+
return;
|
|
10865
|
+
}
|
|
10866
|
+
}
|
|
10867
|
+
};
|
|
10868
|
+
}
|
|
10869
|
+
const CiEventSchema = z.object({ repository: z.object({ default_branch: z.string().min(1) }) });
|
|
10870
|
+
function ciDefaultBranch(source) {
|
|
10871
|
+
if (source === void 0 || source.env["GITHUB_ACTIONS"] !== "true") return void 0;
|
|
10872
|
+
const eventPath = source.env["GITHUB_EVENT_PATH"];
|
|
10873
|
+
if (eventPath === void 0 || eventPath === "") return void 0;
|
|
10874
|
+
const raw = source.readFile(eventPath);
|
|
10875
|
+
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
10876
|
+
let json;
|
|
10877
|
+
try {
|
|
10878
|
+
json = JSON.parse(raw);
|
|
10879
|
+
} catch (_error) {
|
|
10880
|
+
return;
|
|
10881
|
+
}
|
|
10882
|
+
const result = CiEventSchema.safeParse(json);
|
|
10883
|
+
return result.success ? result.data.repository.default_branch : void 0;
|
|
10884
|
+
}
|
|
10913
10885
|
const DefaultBranchSchema = z.object({ defaultBranch: z.string().optional() });
|
|
10914
10886
|
function parseDefaultBranchOverride(raw) {
|
|
10915
10887
|
if (raw === void 0 || raw.trim() === "") return void 0;
|
|
@@ -10922,28 +10894,41 @@ function parseDefaultBranchOverride(raw) {
|
|
|
10922
10894
|
const result = DefaultBranchSchema.safeParse(json);
|
|
10923
10895
|
return result.success ? result.data.defaultBranch : void 0;
|
|
10924
10896
|
}
|
|
10925
|
-
function resolveReferenceBranch(executor, cwd, prefix) {
|
|
10897
|
+
function resolveReferenceBranch(executor, cwd, prefix, ciEvent) {
|
|
10926
10898
|
const git = gitRunner(executor);
|
|
10927
|
-
const
|
|
10928
|
-
|
|
10929
|
-
|
|
10930
|
-
});
|
|
10931
|
-
const ref = `refs/remotes/origin/${trusted}`;
|
|
10899
|
+
const anchor = ciDefaultBranch(ciEvent) ?? originHeadBranch(git, cwd);
|
|
10900
|
+
const chosen = anchor ?? "main";
|
|
10901
|
+
const ref = `refs/remotes/origin/${chosen}`;
|
|
10932
10902
|
if (git([
|
|
10933
10903
|
"rev-parse",
|
|
10934
10904
|
"--verify",
|
|
10935
10905
|
"--quiet",
|
|
10936
10906
|
ref
|
|
10937
|
-
], cwd) !== void 0)
|
|
10938
|
-
cwd,
|
|
10939
|
-
|
|
10940
|
-
|
|
10941
|
-
|
|
10942
|
-
|
|
10943
|
-
|
|
10944
|
-
|
|
10945
|
-
|
|
10946
|
-
}
|
|
10907
|
+
], cwd) !== void 0) {
|
|
10908
|
+
const branch = parseDefaultBranchOverride(showAt(executor, cwd, ref, `${prefix}${TOOLING_FILE}`)) ?? chosen;
|
|
10909
|
+
if (anchor !== void 0) return { branch };
|
|
10910
|
+
const namedElsewhere = parseDefaultBranchOverride(executor.readFile(TOOLING_FILE));
|
|
10911
|
+
if (namedElsewhere === void 0 || namedElsewhere === branch) return { branch };
|
|
10912
|
+
return {
|
|
10913
|
+
branch,
|
|
10914
|
+
warning: unconfirmedDefaultWarning(branch, namedElsewhere)
|
|
10915
|
+
};
|
|
10916
|
+
}
|
|
10917
|
+
if (anchor !== void 0) return { branch: chosen };
|
|
10918
|
+
return { branch: parseDefaultBranchOverride(executor.readFile(TOOLING_FILE)) ?? "main" };
|
|
10919
|
+
}
|
|
10920
|
+
function originHeadBranch(git, cwd) {
|
|
10921
|
+
const head = git([
|
|
10922
|
+
"symbolic-ref",
|
|
10923
|
+
"--short",
|
|
10924
|
+
"refs/remotes/origin/HEAD"
|
|
10925
|
+
], cwd);
|
|
10926
|
+
if (head === void 0) return void 0;
|
|
10927
|
+
const name = head.startsWith("origin/") ? head.slice(7) : head;
|
|
10928
|
+
return name === "" ? void 0 : name;
|
|
10929
|
+
}
|
|
10930
|
+
function unconfirmedDefaultWarning(branch, namedByTree) {
|
|
10931
|
+
return `health: could not confirm the default branch, so the reference was read against origin/${branch}, while .tooling.json#defaultBranch names ${namedByTree}. If ${namedByTree} is the repository's default branch, record it in this clone with \`git remote set-head origin --auto\`, or run in GitHub or Forgejo Actions, where the event payload names it.`;
|
|
10947
10932
|
}
|
|
10948
10933
|
function gitRunner(executor) {
|
|
10949
10934
|
return (args, cwd) => {
|
|
@@ -10960,7 +10945,7 @@ function showAt(executor, cwd, sha, file) {
|
|
|
10960
10945
|
}
|
|
10961
10946
|
function readReference(executor, opts) {
|
|
10962
10947
|
const prefix = repoPrefix(executor, opts.cwd);
|
|
10963
|
-
const branch = resolveReferenceBranch(executor, opts.cwd, prefix);
|
|
10948
|
+
const { branch, warning } = resolveReferenceBranch(executor, opts.cwd, prefix, opts.ciEvent);
|
|
10964
10949
|
const mergeBase = executor.exec("git", [
|
|
10965
10950
|
"merge-base",
|
|
10966
10951
|
"HEAD",
|
|
@@ -10978,14 +10963,20 @@ function readReference(executor, opts) {
|
|
|
10978
10963
|
read: (rel) => rel === TOOLING_FILE ? toolingText : void 0,
|
|
10979
10964
|
config: { stack: opts.stack }
|
|
10980
10965
|
}, { isMonorepo: opts.isMonorepo });
|
|
10966
|
+
const reference = {
|
|
10967
|
+
mergeBase: sha,
|
|
10968
|
+
prefix,
|
|
10969
|
+
baseline: baselineText === void 0 ? void 0 : parseHealthBaseline(baselineText),
|
|
10970
|
+
health
|
|
10971
|
+
};
|
|
10972
|
+
if (warning === void 0) return {
|
|
10973
|
+
kind: "read",
|
|
10974
|
+
reference
|
|
10975
|
+
};
|
|
10981
10976
|
return {
|
|
10982
10977
|
kind: "read",
|
|
10983
|
-
reference
|
|
10984
|
-
|
|
10985
|
-
prefix,
|
|
10986
|
-
baseline: baselineText === void 0 ? void 0 : parseHealthBaseline(baselineText),
|
|
10987
|
-
health
|
|
10988
|
-
}
|
|
10978
|
+
reference,
|
|
10979
|
+
warning
|
|
10989
10980
|
};
|
|
10990
10981
|
}
|
|
10991
10982
|
function referenceEnablesHealth(cwd) {
|
|
@@ -10993,7 +10984,8 @@ function referenceEnablesHealth(cwd) {
|
|
|
10993
10984
|
const read = readReference(createRealHealthExecutor(cwd), {
|
|
10994
10985
|
cwd,
|
|
10995
10986
|
stack: "none",
|
|
10996
|
-
isMonorepo: false
|
|
10987
|
+
isMonorepo: false,
|
|
10988
|
+
ciEvent: processCiEventSource()
|
|
10997
10989
|
});
|
|
10998
10990
|
return read.kind === "read" && read.reference.health.enabled && read.reference.baseline !== void 0;
|
|
10999
10991
|
} catch (_error) {
|
|
@@ -11123,6 +11115,129 @@ function isCeilingOnly(names, prefix = "") {
|
|
|
11123
11115
|
return names.every((name) => files.includes(name));
|
|
11124
11116
|
}
|
|
11125
11117
|
//#endregion
|
|
11118
|
+
//#region ../forgejo/src/git.ts
|
|
11119
|
+
const GIT_LOCAL_TIMEOUT_MS = 6e4;
|
|
11120
|
+
const GIT_WRITE_TIMEOUT_MS = 3e5;
|
|
11121
|
+
function pickDefaultBranch(override, originHead) {
|
|
11122
|
+
if (override !== void 0 && override !== "") return override;
|
|
11123
|
+
if (originHead !== void 0) {
|
|
11124
|
+
const name = originHead.startsWith("origin/") ? originHead.slice(7) : originHead;
|
|
11125
|
+
if (name !== "") return name;
|
|
11126
|
+
}
|
|
11127
|
+
return "main";
|
|
11128
|
+
}
|
|
11129
|
+
async function resolveOriginHead(git, cwd, signal = null) {
|
|
11130
|
+
const result = await git.run([
|
|
11131
|
+
"symbolic-ref",
|
|
11132
|
+
"--short",
|
|
11133
|
+
"refs/remotes/origin/HEAD"
|
|
11134
|
+
], {
|
|
11135
|
+
cwd,
|
|
11136
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11137
|
+
signal
|
|
11138
|
+
});
|
|
11139
|
+
if (result.exitCode !== 0) return void 0;
|
|
11140
|
+
const out = result.stdout.trim();
|
|
11141
|
+
return out === "" ? void 0 : out;
|
|
11142
|
+
}
|
|
11143
|
+
async function currentBranch(git, cwd, signal = null) {
|
|
11144
|
+
const result = await git.run([
|
|
11145
|
+
"rev-parse",
|
|
11146
|
+
"--abbrev-ref",
|
|
11147
|
+
"HEAD"
|
|
11148
|
+
], {
|
|
11149
|
+
cwd,
|
|
11150
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11151
|
+
signal
|
|
11152
|
+
});
|
|
11153
|
+
const branch = result.stdout.trim();
|
|
11154
|
+
if (result.exitCode !== 0 || branch === "") throw new FatalError("Could not determine the current branch -- is this a git repository?");
|
|
11155
|
+
if (branch === "HEAD") throw new FatalError("HEAD is detached. Check out a feature branch first.");
|
|
11156
|
+
return branch;
|
|
11157
|
+
}
|
|
11158
|
+
async function baseRef(git, cwd, base, signal = null) {
|
|
11159
|
+
const remote = `origin/${base}`;
|
|
11160
|
+
const result = await git.run([
|
|
11161
|
+
"rev-parse",
|
|
11162
|
+
"--verify",
|
|
11163
|
+
"--quiet",
|
|
11164
|
+
remote
|
|
11165
|
+
], {
|
|
11166
|
+
cwd,
|
|
11167
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11168
|
+
signal
|
|
11169
|
+
});
|
|
11170
|
+
return result.exitCode === 0 && result.stdout.trim() !== "" ? remote : base;
|
|
11171
|
+
}
|
|
11172
|
+
async function commitSubjects(git, cwd, ref, signal = null) {
|
|
11173
|
+
return (await git.run([
|
|
11174
|
+
"log",
|
|
11175
|
+
"--format=%s",
|
|
11176
|
+
`${ref}..HEAD`
|
|
11177
|
+
], {
|
|
11178
|
+
cwd,
|
|
11179
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11180
|
+
signal
|
|
11181
|
+
})).stdout.split("\n").map((line) => line.trim()).filter((line) => line !== "");
|
|
11182
|
+
}
|
|
11183
|
+
async function commitMessages(git, cwd, ref, signal = null) {
|
|
11184
|
+
const result = await git.run([
|
|
11185
|
+
"log",
|
|
11186
|
+
"-z",
|
|
11187
|
+
"--format=%B",
|
|
11188
|
+
`${ref}..HEAD`
|
|
11189
|
+
], {
|
|
11190
|
+
cwd,
|
|
11191
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11192
|
+
signal
|
|
11193
|
+
});
|
|
11194
|
+
if (result.exitCode !== 0) throw new FatalError(`Failed to read commit messages: ${result.stderr || result.stdout}`);
|
|
11195
|
+
return result.stdout.split("\0").map((message) => message.trim()).filter((message) => message !== "");
|
|
11196
|
+
}
|
|
11197
|
+
async function hasUncommittedChanges(git, cwd, signal = null) {
|
|
11198
|
+
return (await git.run(["status", "--porcelain"], {
|
|
11199
|
+
cwd,
|
|
11200
|
+
timeoutMs: GIT_LOCAL_TIMEOUT_MS,
|
|
11201
|
+
signal
|
|
11202
|
+
})).stdout.trim() !== "";
|
|
11203
|
+
}
|
|
11204
|
+
async function pushBranch(git, cwd, branch, env, forceWithLease = false) {
|
|
11205
|
+
const pushArgs = forceWithLease ? [
|
|
11206
|
+
"push",
|
|
11207
|
+
"--force-with-lease",
|
|
11208
|
+
"-u",
|
|
11209
|
+
"origin",
|
|
11210
|
+
branch
|
|
11211
|
+
] : [
|
|
11212
|
+
"push",
|
|
11213
|
+
"-u",
|
|
11214
|
+
"origin",
|
|
11215
|
+
branch
|
|
11216
|
+
];
|
|
11217
|
+
const result = await git.run(pushArgs, env === void 0 ? {
|
|
11218
|
+
cwd,
|
|
11219
|
+
timeoutMs: GIT_WRITE_TIMEOUT_MS,
|
|
11220
|
+
signal: null
|
|
11221
|
+
} : {
|
|
11222
|
+
cwd,
|
|
11223
|
+
env,
|
|
11224
|
+
timeoutMs: GIT_WRITE_TIMEOUT_MS,
|
|
11225
|
+
signal: null
|
|
11226
|
+
});
|
|
11227
|
+
if (result.exitCode !== 0) throw new FatalError(`Failed to push ${branch}: ${result.stderr || result.stdout}`);
|
|
11228
|
+
}
|
|
11229
|
+
//#endregion
|
|
11230
|
+
//#region src/utils/branch.ts
|
|
11231
|
+
function resolveDefaultBranch(options) {
|
|
11232
|
+
const override = options.configOverride;
|
|
11233
|
+
if (override !== void 0 && override !== "") return pickDefaultBranch(override, void 0);
|
|
11234
|
+
return pickDefaultBranch(void 0, (options.git ?? defaultGitRunner)([
|
|
11235
|
+
"symbolic-ref",
|
|
11236
|
+
"--short",
|
|
11237
|
+
"refs/remotes/origin/HEAD"
|
|
11238
|
+
], options.cwd));
|
|
11239
|
+
}
|
|
11240
|
+
//#endregion
|
|
11126
11241
|
//#region ../cli-kit/src/flags.ts
|
|
11127
11242
|
const UNIVERSAL_FLAGS = [
|
|
11128
11243
|
"--help",
|
|
@@ -11895,10 +12010,10 @@ function runComposeLintGate(targetDir, config, memo) {
|
|
|
11895
12010
|
for (const warning of findDockerRebuildRisks(targetDir, config, memo)) log$1.warn(warning);
|
|
11896
12011
|
return issues.length;
|
|
11897
12012
|
}
|
|
11898
|
-
function runCheckOnlyImageGate(config, targetDir, memo) {
|
|
12013
|
+
function runCheckOnlyImageGate(config, targetDir, memo, phase) {
|
|
11899
12014
|
if (!config.publishDocker) return [];
|
|
11900
12015
|
const images = [];
|
|
11901
|
-
for (const risk of findCheckOnlyPublishRisks(targetDir,
|
|
12016
|
+
for (const risk of findCheckOnlyPublishRisks(targetDir, phase, memo)) {
|
|
11902
12017
|
log$1.warn(`Image "${risk.imageName}" is declared only in ${risk.declaredIn}, the check overlay, so a later tooling release stops publishing it with docker:publish by default. Keep it: set publish to true for "${risk.imageName}" under .tooling.json#docker. Settle it: set publish to false there, or move the service into a base compose file.`);
|
|
11903
12018
|
images.push(risk.imageName);
|
|
11904
12019
|
}
|
|
@@ -11912,6 +12027,18 @@ function runWorkflowAptGate(targetDir) {
|
|
|
11912
12027
|
}
|
|
11913
12028
|
return steps;
|
|
11914
12029
|
}
|
|
12030
|
+
function findInertAgentKeys(saved) {
|
|
12031
|
+
const agent = saved?.agent;
|
|
12032
|
+
if (!agent) return [];
|
|
12033
|
+
if (agent.enabled === true) return [];
|
|
12034
|
+
return Object.keys(agent).filter((key) => key !== "enabled").toSorted();
|
|
12035
|
+
}
|
|
12036
|
+
function runInertAgentSettingsGate(saved) {
|
|
12037
|
+
const keys = findInertAgentKeys(saved);
|
|
12038
|
+
if (keys.length === 0) return [];
|
|
12039
|
+
log$1.warn(`.tooling.json sets ${keys.map((key) => `agent.${key}`).join(", ")}, but agent.enabled is not true, so the agent ignores them. Set "agent.enabled": true, or remove those keys.`);
|
|
12040
|
+
return keys;
|
|
12041
|
+
}
|
|
11915
12042
|
function runPublishConfigGate(config, targetDir) {
|
|
11916
12043
|
if (!config.publishNpm) return 0;
|
|
11917
12044
|
const issues = lintPublishConfig(targetDir, config.structure);
|
|
@@ -12137,7 +12264,7 @@ const syncCommand = defineCommand({
|
|
|
12137
12264
|
},
|
|
12138
12265
|
json: {
|
|
12139
12266
|
type: "boolean",
|
|
12140
|
-
description: "Emit one JSON document: status (up-to-date | drift | workflow-drift | failed), actionable, failed, toolchain, checkOnlyImages, aptSteps, warnCount, exitCode. --check only: the write mode prompts and inherits child streams."
|
|
12267
|
+
description: "Emit one JSON document: status (up-to-date | drift | workflow-drift | failed), actionable, failed, toolchain, checkOnlyImages, aptSteps, inertAgentKeys, warnCount, exitCode. --check only: the write mode prompts and inherits child streams."
|
|
12141
12268
|
}
|
|
12142
12269
|
},
|
|
12143
12270
|
async run({ args }) {
|
|
@@ -12185,6 +12312,7 @@ async function runUpdate(targetDir, flags = {}) {
|
|
|
12185
12312
|
}
|
|
12186
12313
|
warnStaleChecksAdd(saved);
|
|
12187
12314
|
warnCoveredChecksAdd(saved, targetDir);
|
|
12315
|
+
runInertAgentSettingsGate(saved);
|
|
12188
12316
|
if (runComposeLintGate(targetDir, saved, dockerDiscovery) > 0) {
|
|
12189
12317
|
process.exitCode = 1;
|
|
12190
12318
|
return [];
|
|
@@ -12210,12 +12338,17 @@ function gateFailure(toolchainWarned = false) {
|
|
|
12210
12338
|
toolchain: { warned: toolchainWarned },
|
|
12211
12339
|
checkOnlyImages: [],
|
|
12212
12340
|
aptSteps: [],
|
|
12341
|
+
inertAgentKeys: [],
|
|
12213
12342
|
warnCount: 0,
|
|
12214
12343
|
exitCode: 1
|
|
12215
12344
|
};
|
|
12216
12345
|
}
|
|
12217
|
-
function
|
|
12218
|
-
|
|
12346
|
+
function advisoryWarnCount(advisories) {
|
|
12347
|
+
return (advisories.toolchainWarned ? 1 : 0) + advisories.checkOnlyImages.length + advisories.aptSteps.length + (advisories.inertAgentKeys.length > 0 ? 1 : 0);
|
|
12348
|
+
}
|
|
12349
|
+
function upToDateReport(advisories) {
|
|
12350
|
+
const toolchain = { warned: advisories.toolchainWarned };
|
|
12351
|
+
const warnCount = advisoryWarnCount(advisories);
|
|
12219
12352
|
if (warnCount > 0) {
|
|
12220
12353
|
if (!isJsonMode()) rawLog$1(formatWarnMarker(warnCount));
|
|
12221
12354
|
} else log$1.success("Repository is up to date.");
|
|
@@ -12224,8 +12357,9 @@ function upToDateReport(toolchain, checkOnlyImages, aptSteps) {
|
|
|
12224
12357
|
actionable: [],
|
|
12225
12358
|
failed: [],
|
|
12226
12359
|
toolchain,
|
|
12227
|
-
checkOnlyImages,
|
|
12228
|
-
aptSteps,
|
|
12360
|
+
checkOnlyImages: advisories.checkOnlyImages,
|
|
12361
|
+
aptSteps: advisories.aptSteps,
|
|
12362
|
+
inertAgentKeys: advisories.inertAgentKeys,
|
|
12229
12363
|
warnCount,
|
|
12230
12364
|
exitCode: 0
|
|
12231
12365
|
};
|
|
@@ -12248,17 +12382,21 @@ async function runCheckReport(targetDir) {
|
|
|
12248
12382
|
...gateFailure(),
|
|
12249
12383
|
toolchain: { warned: toolchain.warned }
|
|
12250
12384
|
};
|
|
12251
|
-
const
|
|
12252
|
-
|
|
12385
|
+
const advisories = {
|
|
12386
|
+
toolchainWarned: toolchain.warned,
|
|
12387
|
+
checkOnlyImages: runCheckOnlyImageGate(config, targetDir, dockerDiscovery),
|
|
12388
|
+
aptSteps: runWorkflowAptGate(targetDir),
|
|
12389
|
+
inertAgentKeys: runInertAgentSettingsGate(saved)
|
|
12390
|
+
};
|
|
12253
12391
|
const { ctx, pendingWrites } = createDryRunContext(config, dockerDiscovery);
|
|
12254
12392
|
logDetectionSummary(ctx);
|
|
12255
12393
|
const results = await runGenerators(ctx);
|
|
12256
12394
|
const failed = failedResults(results);
|
|
12257
12395
|
reportFailures(failed, "repo:sync");
|
|
12258
12396
|
const actionable = actionableResults(results, pendingWrites, targetDir);
|
|
12259
|
-
const
|
|
12260
|
-
const toolchainState = { warned:
|
|
12261
|
-
if (actionable.length === 0 && failed.length === 0) return upToDateReport(
|
|
12397
|
+
const advisoryCount = advisoryWarnCount(advisories);
|
|
12398
|
+
const toolchainState = { warned: advisories.toolchainWarned };
|
|
12399
|
+
if (actionable.length === 0 && failed.length === 0) return upToDateReport(advisories);
|
|
12262
12400
|
if (actionable.length === 0) return {
|
|
12263
12401
|
status: "failed",
|
|
12264
12402
|
actionable: [],
|
|
@@ -12266,21 +12404,23 @@ async function runCheckReport(targetDir) {
|
|
|
12266
12404
|
toolchain: toolchainState,
|
|
12267
12405
|
checkOnlyImages: [],
|
|
12268
12406
|
aptSteps: [],
|
|
12407
|
+
inertAgentKeys: [],
|
|
12269
12408
|
warnCount: 0,
|
|
12270
12409
|
exitCode: 1
|
|
12271
12410
|
};
|
|
12272
12411
|
log$1.warn(`${actionable.length} file(s) would be changed by repo:sync`);
|
|
12273
12412
|
for (const r of actionable) logActionableChange(r, targetDir, pendingWrites);
|
|
12274
12413
|
if (failed.length === 0 && actionable.every((r) => isWorkflowDirPath(r.filePath))) {
|
|
12275
|
-
const warnCount = actionable.length +
|
|
12414
|
+
const warnCount = actionable.length + advisoryCount;
|
|
12276
12415
|
if (!isJsonMode()) rawLog$1(formatWarnMarker(warnCount));
|
|
12277
12416
|
return {
|
|
12278
12417
|
status: "workflow-drift",
|
|
12279
12418
|
actionable,
|
|
12280
12419
|
failed: [],
|
|
12281
12420
|
toolchain: toolchainState,
|
|
12282
|
-
checkOnlyImages,
|
|
12283
|
-
aptSteps,
|
|
12421
|
+
checkOnlyImages: advisories.checkOnlyImages,
|
|
12422
|
+
aptSteps: advisories.aptSteps,
|
|
12423
|
+
inertAgentKeys: advisories.inertAgentKeys,
|
|
12284
12424
|
warnCount,
|
|
12285
12425
|
exitCode: 0
|
|
12286
12426
|
};
|
|
@@ -12292,6 +12432,7 @@ async function runCheckReport(targetDir) {
|
|
|
12292
12432
|
toolchain: toolchainState,
|
|
12293
12433
|
checkOnlyImages: [],
|
|
12294
12434
|
aptSteps: [],
|
|
12435
|
+
inertAgentKeys: [],
|
|
12295
12436
|
warnCount: 0,
|
|
12296
12437
|
exitCode: 1
|
|
12297
12438
|
};
|
|
@@ -14890,16 +15031,17 @@ async function githubLabelDescriptions(executor, cwd, repository) {
|
|
|
14890
15031
|
const stdout = await runGh(executor, cwd, [
|
|
14891
15032
|
"api",
|
|
14892
15033
|
"--paginate",
|
|
15034
|
+
"--slurp",
|
|
14893
15035
|
`repos/${repository}/labels`
|
|
14894
15036
|
], "gh api");
|
|
14895
15037
|
let parsed;
|
|
14896
15038
|
try {
|
|
14897
|
-
parsed = GitHubLabelListSchema.safeParse(JSON.parse(stdout));
|
|
15039
|
+
parsed = z.array(GitHubLabelListSchema).safeParse(JSON.parse(stdout));
|
|
14898
15040
|
} catch {
|
|
14899
15041
|
throw new UnexpectedError("Unexpected 'gh api' labels response: not JSON");
|
|
14900
15042
|
}
|
|
14901
15043
|
if (!parsed.success) throw new UnexpectedError(`Unexpected 'gh api' labels response: ${parsed.error.message}`);
|
|
14902
|
-
return descriptionsOf(parsed.data.map((label) => ({
|
|
15044
|
+
return descriptionsOf(parsed.data.flat().map((label) => ({
|
|
14903
15045
|
name: label.name,
|
|
14904
15046
|
description: label.description ?? void 0
|
|
14905
15047
|
})));
|
|
@@ -15081,6 +15223,15 @@ async function createWorkGit(executor, cwd) {
|
|
|
15081
15223
|
"--format=%cI",
|
|
15082
15224
|
rev
|
|
15083
15225
|
], `log -1 --format=%cI ${rev}`)).trim();
|
|
15226
|
+
},
|
|
15227
|
+
async originRepository() {
|
|
15228
|
+
const remote = await ask([
|
|
15229
|
+
"remote",
|
|
15230
|
+
"get-url",
|
|
15231
|
+
"origin"
|
|
15232
|
+
]);
|
|
15233
|
+
if (remote.exitCode !== 0) return null;
|
|
15234
|
+
return repositoryFromRemoteUrl(remote.stdout);
|
|
15084
15235
|
}
|
|
15085
15236
|
};
|
|
15086
15237
|
}
|
|
@@ -15174,7 +15325,7 @@ function retireDestination(src, verb) {
|
|
|
15174
15325
|
if (dir === DOCS_ROOT && LEGACY_ACTIVE_PATTERN.test(base)) return `${DOCS_ROOT}/${RETIRED_DIR}/${verb}-${base.slice(5)}`;
|
|
15175
15326
|
return `${dir}/${RETIRED_DIR}/${base}`;
|
|
15176
15327
|
}
|
|
15177
|
-
function
|
|
15328
|
+
function candidatePairs(exec, config) {
|
|
15178
15329
|
const candidates = [];
|
|
15179
15330
|
for (const active of [...conventionalActiveDirs(exec), ...config.extraDirs]) candidates.push({
|
|
15180
15331
|
active,
|
|
@@ -15189,8 +15340,16 @@ function discoverPairs(exec, config) {
|
|
|
15189
15340
|
activePattern: LEGACY_ACTIVE_PATTERN,
|
|
15190
15341
|
enforced: isEnforced(DOCS_ROOT, config.enforced)
|
|
15191
15342
|
});
|
|
15343
|
+
return candidates;
|
|
15344
|
+
}
|
|
15345
|
+
function matchableActiveDirs(exec, config) {
|
|
15192
15346
|
const seen = /* @__PURE__ */ new Set();
|
|
15193
|
-
|
|
15347
|
+
for (const pair of candidatePairs(exec, config)) if (exec.readDir(pair.active) !== void 0) seen.add(pair.active);
|
|
15348
|
+
return [...seen].toSorted();
|
|
15349
|
+
}
|
|
15350
|
+
function discoverPairs(exec, config) {
|
|
15351
|
+
const seen = /* @__PURE__ */ new Set();
|
|
15352
|
+
return candidatePairs(exec, config).filter((pair) => {
|
|
15194
15353
|
if (seen.has(pair.active)) return false;
|
|
15195
15354
|
if (!(listDocs(exec, pair.active, pair.activePattern).length > 0 || pair.retiredDirs.some((dir) => listDocs(exec, dir).length > 0))) return false;
|
|
15196
15355
|
seen.add(pair.active);
|
|
@@ -17837,6 +17996,12 @@ function tryResolveWorkForge(executor, topLevel, target) {
|
|
|
17837
17996
|
return error instanceof Error ? error : new UnexpectedError(String(error));
|
|
17838
17997
|
}
|
|
17839
17998
|
}
|
|
17999
|
+
function sameRepository(one, other) {
|
|
18000
|
+
return one.toLowerCase() === other.toLowerCase();
|
|
18001
|
+
}
|
|
18002
|
+
function refNamesAnotherRepository(checkoutRepository, refRepository) {
|
|
18003
|
+
return new FatalError(`Usage: bst work:status reads this checkout's repository (${checkoutRepository}); the ref names ${refRepository}`);
|
|
18004
|
+
}
|
|
17840
18005
|
const workStatusCommand = defineCommand({
|
|
17841
18006
|
meta: {
|
|
17842
18007
|
name: "work:status",
|
|
@@ -17862,10 +18027,14 @@ const workStatusCommand = defineCommand({
|
|
|
17862
18027
|
const ref = refText === "" ? null : parseIssueRef(refText);
|
|
17863
18028
|
const executor = createRealExecutor$1();
|
|
17864
18029
|
const git = await createWorkGit(executor, process.cwd());
|
|
17865
|
-
let forge = tryResolveWorkForge(executor, git.topLevel);
|
|
17866
18030
|
const target = ref?.target;
|
|
18031
|
+
if (target !== void 0) {
|
|
18032
|
+
const checkout = await git.originRepository();
|
|
18033
|
+
if (checkout !== null && !sameRepository(target.repository, checkout)) throw refNamesAnotherRepository(checkout, target.repository);
|
|
18034
|
+
}
|
|
18035
|
+
let forge = tryResolveWorkForge(executor, git.topLevel);
|
|
17867
18036
|
if (target !== void 0 && !(forge instanceof Error)) {
|
|
17868
|
-
if (target.repository
|
|
18037
|
+
if (!sameRepository(target.repository, forge.repository)) throw refNamesAnotherRepository(forge.repository, target.repository);
|
|
17869
18038
|
forge = tryResolveWorkForge(executor, git.topLevel, target);
|
|
17870
18039
|
}
|
|
17871
18040
|
const docs = resolveDocsConfig(git.topLevel);
|
|
@@ -20028,7 +20197,7 @@ function composePs(executor, config) {
|
|
|
20028
20197
|
//#region src/docker-check/health.ts
|
|
20029
20198
|
const DOCKER_RUN_START_FAILURE_EXIT_CODE = 125;
|
|
20030
20199
|
const PROBE_TIMEOUT_SECONDS = "5";
|
|
20031
|
-
const PROBE_IMAGE = "curlimages/curl:8.
|
|
20200
|
+
const PROBE_IMAGE = "curlimages/curl:8.22.0@sha256:58adaa4e8dca9c988bae2aba4ab3434a0bb2da16bbe3f92dec39ec7785166777";
|
|
20032
20201
|
function getContainerHealth(containers, serviceName) {
|
|
20033
20202
|
return containers.find((c) => c.Service === serviceName)?.Health ?? "unknown";
|
|
20034
20203
|
}
|
|
@@ -22677,7 +22846,7 @@ function findStaleEntries(baseline, details, exempt) {
|
|
|
22677
22846
|
//#region src/commands/health-check.ts
|
|
22678
22847
|
const BASELINE_FILE = "health-baseline.json";
|
|
22679
22848
|
function assessRaises(executor, targetDir, current, out) {
|
|
22680
|
-
const read = readTargetReference(executor, targetDir);
|
|
22849
|
+
const read = readTargetReference(executor, targetDir, out);
|
|
22681
22850
|
if (read.kind === "unavailable") throw new FatalError(read.reason);
|
|
22682
22851
|
const reference = read.reference;
|
|
22683
22852
|
if (reference.baseline === void 0) {
|
|
@@ -22693,13 +22862,16 @@ function assessRaises(executor, targetDir, current, out) {
|
|
|
22693
22862
|
}
|
|
22694
22863
|
return refuseBesideCode(executor, targetDir, reference, findRaises(reference, current), out);
|
|
22695
22864
|
}
|
|
22696
|
-
function readTargetReference(executor, targetDir) {
|
|
22865
|
+
function readTargetReference(executor, targetDir, out) {
|
|
22697
22866
|
const context = detectHealthContext(targetDir);
|
|
22698
|
-
|
|
22867
|
+
const read = readReference(executor, {
|
|
22699
22868
|
cwd: targetDir,
|
|
22700
22869
|
stack: context.stack,
|
|
22701
|
-
isMonorepo: context.isMonorepo
|
|
22870
|
+
isMonorepo: context.isMonorepo,
|
|
22871
|
+
ciEvent: processCiEventSource()
|
|
22702
22872
|
});
|
|
22873
|
+
if (read.kind === "read" && read.warning !== void 0) out.notice(read.warning);
|
|
22874
|
+
return read;
|
|
22703
22875
|
}
|
|
22704
22876
|
function refuseBesideCode(executor, targetDir, reference, raises, out) {
|
|
22705
22877
|
if (raises.length === 0) return {
|
|
@@ -22728,14 +22900,18 @@ function refuseBesideCode(executor, targetDir, reference, raises, out) {
|
|
|
22728
22900
|
};
|
|
22729
22901
|
}
|
|
22730
22902
|
function assessSwitchOff(executor, targetDir, config, out) {
|
|
22731
|
-
const read = readTargetReference(executor, targetDir);
|
|
22903
|
+
const read = readTargetReference(executor, targetDir, out);
|
|
22732
22904
|
if (read.kind === "unavailable") return void 0;
|
|
22733
22905
|
const reference = read.reference;
|
|
22734
22906
|
if (!reference.health.enabled || reference.baseline === void 0) return void 0;
|
|
22735
22907
|
const baselinePath = path.join(targetDir, BASELINE_FILE);
|
|
22908
|
+
const treeBaseline = existsSync(baselinePath) ? parseHealthBaseline(readFileSync(baselinePath, "utf-8")) : void 0;
|
|
22909
|
+
const named = healthOverridesAt(targetDir);
|
|
22910
|
+
const limitsOver = { ...config };
|
|
22911
|
+
for (const name of RAISABLE_LIMITS) if (named?.[name] === void 0) limitsOver[name] = reference.health[name];
|
|
22736
22912
|
return refuseBesideCode(executor, targetDir, reference, findRaises(reference, {
|
|
22737
|
-
baseline:
|
|
22738
|
-
health:
|
|
22913
|
+
baseline: treeBaseline,
|
|
22914
|
+
health: limitsOver
|
|
22739
22915
|
}), out);
|
|
22740
22916
|
}
|
|
22741
22917
|
function refuseUnresolvedImports(details) {
|
|
@@ -23999,7 +24175,7 @@ function collectViolations(exec, config, opts) {
|
|
|
23999
24175
|
retiredCount += result.retired;
|
|
24000
24176
|
}
|
|
24001
24177
|
violations.push(...collectSpecRetirementViolations(exec, pairs, config, opts));
|
|
24002
|
-
const activeDirs =
|
|
24178
|
+
const activeDirs = matchableActiveDirs(exec, config);
|
|
24003
24179
|
const unmatchedEnforced = Array.isArray(config.enforced) ? config.enforced.filter((entry) => !activeDirs.includes(entry)) : [];
|
|
24004
24180
|
return {
|
|
24005
24181
|
violations,
|
|
@@ -24142,7 +24318,7 @@ const docsCheckCommand = defineCommand({
|
|
|
24142
24318
|
},
|
|
24143
24319
|
json: {
|
|
24144
24320
|
type: "boolean",
|
|
24145
|
-
description: "Emit one JSON document: violations ([{file, rule, message, fix, severity (fatal | advisory)}]), activeCount, retiredCount, pairCount, pass, activeDirs, unmatchedEnforced. When docs are disabled in .tooling.json the document is only enabled (false)."
|
|
24321
|
+
description: "Emit one JSON document: violations ([{file, rule, message, fix, severity (fatal | advisory)}]), activeCount, retiredCount, pairCount, pass, activeDirs, unmatchedEnforced. activeDirs lists every existing doc directory an enforced entry can match, holding docs or not; unmatchedEnforced the .tooling.json#docs.enforced entries that match none of them. When docs are disabled in .tooling.json the document is only enabled (false)."
|
|
24146
24322
|
},
|
|
24147
24323
|
verbose: {
|
|
24148
24324
|
type: "boolean",
|
|
@@ -25777,6 +25953,9 @@ var EmptyCommentError = class extends FatalError {
|
|
|
25777
25953
|
super("The comment resolved to empty text.");
|
|
25778
25954
|
}
|
|
25779
25955
|
};
|
|
25956
|
+
function rejectEmptyComment(comment) {
|
|
25957
|
+
if (comment !== void 0 && comment.trim() === "") throw new EmptyCommentError();
|
|
25958
|
+
}
|
|
25780
25959
|
var PullRequestStateError = class extends FatalError {
|
|
25781
25960
|
number;
|
|
25782
25961
|
action;
|
|
@@ -25786,20 +25965,35 @@ var PullRequestStateError = class extends FatalError {
|
|
|
25786
25965
|
this.action = action;
|
|
25787
25966
|
}
|
|
25788
25967
|
};
|
|
25968
|
+
var NotAPullRequestError = class extends FatalError {
|
|
25969
|
+
number;
|
|
25970
|
+
constructor(number) {
|
|
25971
|
+
super(`#${String(number)} is an issue, not a pull request.`);
|
|
25972
|
+
this.number = number;
|
|
25973
|
+
}
|
|
25974
|
+
};
|
|
25975
|
+
var StateNotTakenError = class extends FatalError {
|
|
25976
|
+
number;
|
|
25977
|
+
expected;
|
|
25978
|
+
actual;
|
|
25979
|
+
constructor(number, expected, actual) {
|
|
25980
|
+
super(`The forge did not change #${String(number)}: it is still ${actual}, not ${expected}.`);
|
|
25981
|
+
this.number = number;
|
|
25982
|
+
this.expected = expected;
|
|
25983
|
+
this.actual = actual;
|
|
25984
|
+
}
|
|
25985
|
+
};
|
|
25789
25986
|
const TARGET_STATE = {
|
|
25790
25987
|
close: "closed",
|
|
25791
25988
|
reopen: "open"
|
|
25792
25989
|
};
|
|
25793
|
-
async function
|
|
25794
|
-
const ref = parseIssueRef(request.ref);
|
|
25795
|
-
const number = requireIssueNumber(ref);
|
|
25796
|
-
if (request.comment !== void 0 && request.comment.trim() === "") throw new EmptyCommentError();
|
|
25797
|
-
const commentGiven = request.comment !== void 0;
|
|
25798
|
-
const { api } = resolve(resolveIssueTarget(ref.target, request.repo));
|
|
25990
|
+
async function changeState(api, number, request, subject) {
|
|
25799
25991
|
const before = await api.get(number);
|
|
25800
|
-
if (before.isPullRequest) throw new PullRequestStateError(number, request.action);
|
|
25992
|
+
if (subject === "issue" && before.isPullRequest) throw new PullRequestStateError(number, request.action);
|
|
25993
|
+
if (subject === "pull-request" && !before.isPullRequest) throw new NotAPullRequestError(number);
|
|
25994
|
+
const commentGiven = request.comment !== void 0;
|
|
25801
25995
|
const targetState = TARGET_STATE[request.action];
|
|
25802
|
-
const buildResult = (url, current, changed, posted) => ({
|
|
25996
|
+
const buildResult = (url, current, changed, posted, merged) => ({
|
|
25803
25997
|
number,
|
|
25804
25998
|
url,
|
|
25805
25999
|
action: request.action,
|
|
@@ -25808,20 +26002,32 @@ async function setIssueState(resolve, request) {
|
|
|
25808
26002
|
current
|
|
25809
26003
|
},
|
|
25810
26004
|
changed,
|
|
25811
|
-
...commentGiven ? { comment: { posted } } : {}
|
|
26005
|
+
...commentGiven ? { comment: { posted } } : {},
|
|
26006
|
+
...merged === void 0 ? {} : { merged }
|
|
25812
26007
|
});
|
|
25813
|
-
if (before.state === targetState)
|
|
26008
|
+
if (before.state === targetState) {
|
|
26009
|
+
const merged = subject === "pull-request" ? (await api.pullRequest(number)).merged : void 0;
|
|
26010
|
+
return buildResult(before.url, before.state, false, false, merged);
|
|
26011
|
+
}
|
|
25814
26012
|
if (request.dryRun) return buildResult(before.url, targetState, true, true);
|
|
25815
26013
|
if (commentGiven) await api.addComment(number, request.comment ?? "");
|
|
25816
26014
|
let after;
|
|
25817
26015
|
try {
|
|
25818
26016
|
after = await api.setState(number, targetState);
|
|
26017
|
+
if (after.state !== targetState) throw new StateNotTakenError(number, targetState, after.state);
|
|
25819
26018
|
} catch (error) {
|
|
25820
26019
|
if (commentGiven && error instanceof Error) error.message = `The comment on #${String(number)} was already posted; a retry will duplicate it. ` + error.message;
|
|
25821
26020
|
throw error;
|
|
25822
26021
|
}
|
|
25823
26022
|
return buildResult(after.url, after.state, true, true);
|
|
25824
26023
|
}
|
|
26024
|
+
async function setIssueState(resolve, request) {
|
|
26025
|
+
const ref = parseIssueRef(request.ref);
|
|
26026
|
+
const number = requireIssueNumber(ref);
|
|
26027
|
+
rejectEmptyComment(request.comment);
|
|
26028
|
+
const { api } = resolve(resolveIssueTarget(ref.target, request.repo));
|
|
26029
|
+
return changeState(api, number, request, "issue");
|
|
26030
|
+
}
|
|
25825
26031
|
const PAST_TENSE = {
|
|
25826
26032
|
close: "Closed",
|
|
25827
26033
|
reopen: "Reopened"
|
|
@@ -26714,7 +26920,7 @@ async function runCli(config) {
|
|
|
26714
26920
|
//#region src/cli-main.ts
|
|
26715
26921
|
setLogLevel(resolveLogLevel({}));
|
|
26716
26922
|
setForgejoLogger(log$1);
|
|
26717
|
-
const displayVersion = "0.
|
|
26923
|
+
const displayVersion = "0.90.0";
|
|
26718
26924
|
const bstSubCommands = {
|
|
26719
26925
|
"repo:sync": syncCommand,
|
|
26720
26926
|
"checks:run": runChecksCommand,
|